summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <serg@sergbook.mysql.com>2004-12-31 15:26:24 +0100
committerunknown <serg@sergbook.mysql.com>2004-12-31 15:26:24 +0100
commitb99bea6704299399c84bd8374ef7f248ff9570c5 (patch)
tree928b06c231edee4cb95ace87ed30e879e3dcb0fb /sql
parentbd23099be0b22845e8c97e2fb36ee3c6eb0e2491 (diff)
parent5eaf65ab4be77911eb03cceefac9ecea48c25f71 (diff)
downloadmariadb-git-b99bea6704299399c84bd8374ef7f248ff9570c5.tar.gz
manually merged
configure.in: Auto merged client/mysqldump.c: Auto merged innobase/buf/buf0rea.c: Auto merged innobase/dict/dict0load.c: Auto merged innobase/fil/fil0fil.c: Auto merged innobase/include/fil0fil.h: Auto merged innobase/include/row0mysql.h: Auto merged innobase/include/trx0trx.h: Auto merged innobase/os/os0file.c: Auto merged innobase/row/row0ins.c: Auto merged innobase/row/row0mysql.c: Auto merged innobase/row/row0sel.c: Auto merged innobase/srv/srv0start.c: Auto merged innobase/trx/trx0trx.c: Auto merged libmysqld/lib_sql.cc: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/r/alter_table.result: Auto merged mysql-test/r/ctype_ucs.result: Auto merged mysql-test/r/func_str.result: Auto merged mysql-test/r/grant.result: Auto merged mysql-test/r/grant_cache.result: Auto merged mysql-test/r/merge.result: Auto merged mysql-test/r/ndb_blob.result: Auto merged mysql-test/r/ps_1general.result: Auto merged mysql-test/r/subselect.result: Auto merged mysql-test/r/timezone2.result: Auto merged mysql-test/t/ctype_ucs.test: Auto merged mysql-test/t/grant.test: Auto merged mysql-test/t/merge.test: Auto merged mysql-test/t/multi_update.test: Auto merged mysql-test/t/mysqldump.test: Auto merged mysql-test/t/subselect.test: Auto merged ndb/src/ndbapi/NdbBlob.cpp: Auto merged ndb/src/ndbapi/NdbConnection.cpp: Auto merged ndb/src/ndbapi/NdbDictionaryImpl.cpp: Auto merged ndb/src/ndbapi/NdbOperationDefine.cpp: Auto merged sql/ha_innodb.cc: Auto merged sql/ha_myisammrg.cc: Auto merged sql/ha_myisammrg.h: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_func.cc: Auto merged sql/item_strfunc.cc: Auto merged sql/log.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/set_var.cc: Auto merged sql-common/client.c: Auto merged sql/sql_table.cc: Auto merged sql/strfunc.cc: Auto merged sql/unireg.cc: Auto merged vio/vio.c: Auto merged vio/viosocket.c: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_innodb.cc44
-rw-r--r--sql/item_cmpfunc.cc5
-rw-r--r--sql/item_func.cc3
-rw-r--r--sql/item_strfunc.cc21
-rw-r--r--sql/item_subselect.cc11
-rw-r--r--sql/item_timefunc.cc60
-rw-r--r--sql/log.cc4
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/mysqld.cc67
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/sql_acl.cc160
-rw-r--r--sql/sql_insert.cc4
-rw-r--r--sql/sql_prepare.cc28
-rw-r--r--sql/sql_table.cc6
-rw-r--r--sql/strfunc.cc37
-rw-r--r--sql/table.cc62
-rw-r--r--sql/unireg.cc11
17 files changed, 300 insertions, 228 deletions
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 6577590f14a..91517770d04 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -380,15 +380,15 @@ convert_error_code_to_mysql(
} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
- /* Since we rolled back the whole transaction, we must
- tell it also to MySQL so that MySQL knows to empty the
- cached binlog for this transaction */
+ /* Since we rolled back the whole transaction, we must
+ tell it also to MySQL so that MySQL knows to empty the
+ cached binlog for this transaction */
- if (thd) {
- ha_rollback(thd);
- }
+ if (thd) {
+ ha_rollback(thd);
+ }
- return(HA_ERR_LOCK_WAIT_TIMEOUT);
+ return(HA_ERR_LOCK_WAIT_TIMEOUT);
} else if (error == (int) DB_NO_REFERENCED_ROW) {
@@ -4075,11 +4075,9 @@ ha_innobase::discard_or_import_tablespace(
err = row_import_tablespace_for_mysql(dict_table->name, trx);
}
- if (err == DB_SUCCESS) {
- DBUG_RETURN(0);
- }
+ err = convert_error_code_to_mysql(err, NULL);
- DBUG_RETURN(-1);
+ DBUG_RETURN(err);
}
/*********************************************************************
@@ -5215,19 +5213,6 @@ ha_innobase::external_lock(
update_thd(thd);
- if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB error:\n"
-"MySQL is trying to use a table handle but the .ibd file for\n"
-"table %s does not exist.\n"
-"Have you deleted the .ibd file from the database directory under\n"
-"the MySQL datadir, or have you used DISCARD TABLESPACE?\n"
-"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
-"how you can resolve the problem.\n",
- prebuilt->table->name);
- DBUG_RETURN(HA_ERR_CRASHED);
- }
-
trx = prebuilt->trx;
prebuilt->sql_stat_start = TRUE;
@@ -5276,9 +5261,18 @@ ha_innobase::external_lock(
prebuilt->select_lock_type = LOCK_S;
}
+ /* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
+ TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
+ an InnoDB table lock if it is released immediately at the end
+ of LOCK TABLES, and InnoDB's table locks in that case cause
+ VERY easily deadlocks. */
+
if (prebuilt->select_lock_type != LOCK_NONE) {
+
if (thd->in_lock_tables &&
- thd->variables.innodb_table_locks) {
+ thd->variables.innodb_table_locks &&
+ (thd->options & OPTION_NOT_AUTOCOMMIT)) {
+
ulint error;
error = row_lock_table_for_mysql(prebuilt,
NULL, LOCK_TABLE_EXP);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 40513c2c25a..aa98f1860b6 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -661,12 +661,13 @@ longlong Item_in_optimizer::val_int()
{
DBUG_ASSERT(fixed == 1);
cache->store(args[0]);
+ longlong tmp= args[1]->val_int_result();
if (cache->null_value)
{
- null_value= 1;
+ if (tmp)
+ null_value= 1;
return 0;
}
- longlong tmp= args[1]->val_int_result();
null_value= args[1]->null_value;
return tmp;
}
diff --git a/sql/item_func.cc b/sql/item_func.cc
index f2d78fdb9e8..69ddd21f913 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1187,7 +1187,8 @@ double Item_func_round::val_real()
bool Item_func_rand::fix_fields(THD *thd, struct st_table_list *tables,
Item **ref)
{
- Item_real_func::fix_fields(thd, tables, ref);
+ if (Item_real_func::fix_fields(thd, tables, ref))
+ return TRUE;
used_tables_cache|= RAND_TABLE_BIT;
if (arg_count)
{ // Only use argument once in query
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index c271ff43fa3..88f32067c6c 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1302,9 +1302,18 @@ String *Item_func_trim::val_str(String *str)
return 0; /* purecov: inspected */
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),res->charset());
- String *remove_str= (arg_count==2) ? args[1]->val_str(&tmp) : &remove;
uint remove_length;
LINT_INIT(remove_length);
+ String *remove_str; /* The string to remove from res. */
+
+ if (arg_count == 2)
+ {
+ remove_str= args[1]->val_str(&tmp);
+ if ((null_value= args[1]->null_value))
+ return 0;
+ }
+ else
+ remove_str= &remove; /* Default value. */
if (!remove_str || (remove_length=remove_str->length()) == 0 ||
remove_length > res->length())
@@ -2608,16 +2617,16 @@ String *Item_func_quote::val_str(String *str)
/*
We have to use realloc() instead of alloc() as we want to keep the
- old result in str
+ old result in arg
*/
- if (str->realloc(new_length))
+ if (arg->realloc(new_length))
goto null;
/*
As 'arg' and 'str' may be the same string, we must replace characters
from the end to the beginning
*/
- to= (char*) str->ptr() + new_length - 1;
+ to= (char*) arg->ptr() + new_length - 1;
*to--= '\'';
for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--)
{
@@ -2645,10 +2654,10 @@ String *Item_func_quote::val_str(String *str)
}
}
*to= '\'';
- str->length(new_length);
+ arg->length(new_length);
str->set_charset(collation.collation);
null_value= 0;
- return str;
+ return arg;
null:
null_value= 1;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 064744158d1..dbf30d7d793 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -830,6 +830,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
ref_pointer_array,
(char *)"<ref>",
this->full_name()));
+ if (!abort_on_null && left_expr->maybe_null)
+ item= new Item_cond_or(new Item_func_isnull(left_expr), item);
/*
AND and comparison functions can't be changed during fix_fields()
we can assign select_lex->having here, and pass 0 as last
@@ -874,6 +876,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
goto err;
item= new Item_cond_or(item,
new Item_func_isnull(orig_item));
+ if (left_expr->maybe_null)
+ item= new Item_cond_or(new Item_func_isnull(left_expr), item);
}
item->name= (char *)in_additional_cond;
/*
@@ -895,12 +899,13 @@ Item_in_subselect::single_value_transformer(JOIN *join,
we can assign select_lex->having here, and pass 0 as last
argument (reference) to fix_fields()
*/
- select_lex->having=
- join->having=
- func->create(expr,
+ item= func->create(expr,
new Item_null_helper(this, item,
(char *)"<no matter>",
(char *)"<result>"));
+ if (!abort_on_null && left_expr->maybe_null)
+ item= new Item_cond_or(new Item_func_isnull(left_expr), item);
+ select_lex->having= join->having= item;
select_lex->having_fix_field= 1;
tmp= join->having->fix_fields(thd, join->tables_list, 0);
select_lex->having_fix_field= 0;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 215218a8277..27c000138d8 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -149,6 +149,9 @@ static DATE_TIME_FORMAT time_24hrs_format= {{0}, '\0', 0,
conversion specifiers that can be used in such sub-patterns is limited.
Also most of checks are skipped in this case.
+ If one adds new format specifiers to this function he should also
+ consider adding them to get_date_time_result_type() function.
+
RETURN
0 ok
1 error
@@ -2821,25 +2824,31 @@ void Item_func_get_format::print(String *str)
/*
- check_result_type(s, l) returns DATE/TIME type
- according to format string
-
- s: DATE/TIME format string
- l: length of s
- Result: date_time_format_types value:
- DATE_TIME_MICROSECOND, DATE_TIME,
- TIME_MICROSECOND, TIME_ONLY
-
- We don't process day format's characters('D', 'd', 'e')
- because day may be a member of all date/time types.
- If only day format's character and no time part present
- the result type is MYSQL_TYPE_DATE
+ Get type of datetime value (DATE/TIME/...) which will be produced
+ according to format string.
+
+ SYNOPSIS
+ get_date_time_result_type()
+ format - format string
+ length - length of format string
+
+ NOTE
+ We don't process day format's characters('D', 'd', 'e') because day
+ may be a member of all date/time types.
+
+ Format specifiers supported by this function should be in sync with
+ specifiers supported by extract_date_time() function.
+
+ RETURN VALUE
+ One of date_time_format_types values:
+ DATE_TIME_MICROSECOND, DATE_TIME, DATE_ONLY, TIME_MICROSECOND, TIME_ONLY
*/
-date_time_format_types check_result_type(const char *format, uint length)
+static date_time_format_types
+get_date_time_result_type(const char *format, uint length)
{
const char *time_part_frms= "HISThiklrs";
- const char *date_part_frms= "MUYWabcjmuyw";
+ const char *date_part_frms= "MVUXYWabcjmvuxyw";
bool date_part_used= 0, time_part_used= 0, frac_second_used= 0;
const char *val= format;
@@ -2850,22 +2859,30 @@ date_time_format_types check_result_type(const char *format, uint length)
if (*val == '%' && val+1 != end)
{
val++;
- if ((frac_second_used= (*val == 'f')) ||
- (!time_part_used && strchr(time_part_frms, *val)))
+ if (*val == 'f')
+ frac_second_used= time_part_used= 1;
+ else if (!time_part_used && strchr(time_part_frms, *val))
time_part_used= 1;
else if (!date_part_used && strchr(date_part_frms, *val))
date_part_used= 1;
- if (time_part_used && date_part_used && frac_second_used)
+ if (date_part_used && frac_second_used)
+ {
+ /*
+ frac_second_used implies time_part_used, and thus we already
+ have all types of date-time components and can end our search.
+ */
return DATE_TIME_MICROSECOND;
}
}
+ }
+ /* We don't have all three types of date-time components */
+ if (frac_second_used)
+ return TIME_MICROSECOND;
if (time_part_used)
{
if (date_part_used)
return DATE_TIME;
- if (frac_second_used)
- return TIME_MICROSECOND;
return TIME_ONLY;
}
return DATE_ONLY;
@@ -2896,7 +2913,8 @@ void Item_func_str_to_date::fix_length_and_dec()
if ((const_item= args[1]->const_item()))
{
format= args[1]->val_str(&format_str);
- cached_format_type= check_result_type(format->ptr(), format->length());
+ cached_format_type= get_date_time_result_type(format->ptr(),
+ format->length());
switch (cached_format_type) {
case DATE_ONLY:
cached_timestamp_type= MYSQL_TIMESTAMP_DATE;
diff --git a/sql/log.cc b/sql/log.cc
index 5d56fefa26a..00c39acec09 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -2046,6 +2046,7 @@ bool flush_error_log()
char err_renamed[FN_REFLEN], *end;
end= strmake(err_renamed,log_error_file,FN_REFLEN-4);
strmov(end, "-old");
+ VOID(pthread_mutex_lock(&LOCK_error_log));
#ifdef __WIN__
char err_temp[FN_REFLEN+4];
/*
@@ -2066,7 +2067,7 @@ bool flush_error_log()
if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0)
{
while ((bytes = (int) my_read(fd, (byte*) buf, IO_SIZE, MYF(0))) > 0)
- my_fwrite(stderr, (byte*) buf, (uint) strlen(buf),MYF(0));
+ my_fwrite(stderr, (byte*) buf, bytes, MYF(0));
my_close(fd, MYF(0));
}
(void) my_delete(err_temp, MYF(0));
@@ -2080,6 +2081,7 @@ bool flush_error_log()
else
result= 1;
#endif
+ VOID(pthread_mutex_unlock(&LOCK_error_log));
}
return result;
}
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 4cba19181d4..88260bb7b1b 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -939,6 +939,7 @@ ulonglong find_set(TYPELIB *lib, const char *x, uint length, CHARSET_INFO *cs,
char **err_pos, uint *err_len, bool *set_warning);
uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match);
uint find_type2(TYPELIB *lib, const char *find, uint length, CHARSET_INFO *cs);
+void unhex_type2(TYPELIB *lib);
uint check_word(TYPELIB *lib, const char *val, const char *end,
const char **end_of_word);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index de1ac6d8727..e9d4a088d16 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -54,7 +54,7 @@
#endif
#ifdef HAVE_NDBCLUSTER_DB
#define OPT_NDBCLUSTER_DEFAULT 0
-#ifdef NDB_SHM_TRANSPORTER
+#if defined(NDB_SHM_TRANSPORTER) && MYSQL_VERSION_ID >= 50000
#define OPT_NDB_SHM_DEFAULT 1
#else
#define OPT_NDB_SHM_DEFAULT 0
@@ -141,15 +141,6 @@ extern "C" { // Because of SCO 3.2V4.2
int allow_severity = LOG_INFO;
int deny_severity = LOG_WARNING;
-#ifdef __STDC__
-#define my_fromhost(A) fromhost(A)
-#define my_hosts_access(A) hosts_access(A)
-#define my_eval_client(A) eval_client(A)
-#else
-#define my_fromhost(A) fromhost()
-#define my_hosts_access(A) hosts_access()
-#define my_eval_client(A) eval_client()
-#endif /* __STDC__ */
#endif /* HAVE_LIBWRAP */
#ifdef HAVE_SYS_MMAN_H
@@ -3689,8 +3680,8 @@ extern "C" pthread_handler_decl(handle_connections_sockets,
struct request_info req;
signal(SIGCHLD, SIG_DFL);
request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL);
- my_fromhost(&req);
- if (!my_hosts_access(&req))
+ fromhost(&req);
+ if (!hosts_access(&req))
{
/*
This may be stupid but refuse() includes an exit(0)
@@ -3698,7 +3689,7 @@ extern "C" pthread_handler_decl(handle_connections_sockets,
clean_exit() - same stupid thing ...
*/
syslog(deny_severity, "refused connect from %s",
- my_eval_client(&req));
+ eval_client(&req));
/*
C++ sucks (the gibberish in front just translates the supplied
@@ -3939,6 +3930,7 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
HANDLE event_client_read= 0; // for transfer data server <-> client
HANDLE event_server_wrote= 0;
HANDLE event_server_read= 0;
+ HANDLE event_conn_closed= 0;
THD *thd= 0;
p= int10_to_str(connect_number, connect_number_char, 10);
@@ -3969,29 +3961,35 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
goto errorconn;
}
strmov(suffix_pos, "CLIENT_WROTE");
- if ((event_client_wrote= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
+ if ((event_client_wrote= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
{
errmsg= "Could not create client write event";
goto errorconn;
}
strmov(suffix_pos, "CLIENT_READ");
- if ((event_client_read= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
+ if ((event_client_read= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
{
errmsg= "Could not create client read event";
goto errorconn;
}
strmov(suffix_pos, "SERVER_READ");
- if ((event_server_read= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
+ if ((event_server_read= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
{
errmsg= "Could not create server read event";
goto errorconn;
}
strmov(suffix_pos, "SERVER_WROTE");
- if ((event_server_wrote= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
+ if ((event_server_wrote= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
{
errmsg= "Could not create server write event";
goto errorconn;
}
+ strmov(suffix_pos, "CONNECTION_CLOSED");
+ if ((event_conn_closed= CreateEvent(0, TRUE , FALSE, tmp)) == 0)
+ {
+ errmsg= "Could not create closed connection event";
+ goto errorconn;
+ }
if (abort_loop)
goto errorconn;
if (!(thd= new THD))
@@ -4010,13 +4008,14 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
goto errorconn;
}
if (!(thd->net.vio= vio_new_win32shared_memory(&thd->net,
- handle_client_file_map,
- handle_client_map,
- event_client_wrote,
- event_client_read,
- event_server_wrote,
- event_server_read)) ||
- my_net_init(&thd->net, thd->net.vio))
+ handle_client_file_map,
+ handle_client_map,
+ event_client_wrote,
+ event_client_read,
+ event_server_wrote,
+ event_server_read,
+ event_conn_closed)) ||
+ my_net_init(&thd->net, thd->net.vio))
{
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
errmsg= 0;
@@ -4036,12 +4035,20 @@ errorconn:
NullS);
sql_perror(buff);
}
- if (handle_client_file_map) CloseHandle(handle_client_file_map);
- if (handle_client_map) UnmapViewOfFile(handle_client_map);
- if (event_server_wrote) CloseHandle(event_server_wrote);
- if (event_server_read) CloseHandle(event_server_read);
- if (event_client_wrote) CloseHandle(event_client_wrote);
- if (event_client_read) CloseHandle(event_client_read);
+ if (handle_client_file_map)
+ CloseHandle(handle_client_file_map);
+ if (handle_client_map)
+ UnmapViewOfFile(handle_client_map);
+ if (event_server_wrote)
+ CloseHandle(event_server_wrote);
+ if (event_server_read)
+ CloseHandle(event_server_read);
+ if (event_client_wrote)
+ CloseHandle(event_client_wrote);
+ if (event_client_read)
+ CloseHandle(event_client_read);
+ if (event_conn_closed)
+ CloseHandle(event_conn_closed);
delete thd;
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 3fb39d0fc27..fbbe209eea4 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -3051,9 +3051,11 @@ bool sys_var_thd_storage_engine::check(THD *thd, set_var *var)
if (var->value->result_type() == STRING_RESULT)
{
+ enum db_type db_type;
if (!(res=var->value->val_str(&str)) ||
!(var->save_result.ulong_value=
- (ulong) ha_resolve_by_name(res->ptr(), res->length())))
+ (ulong) db_type= ha_resolve_by_name(res->ptr(), res->length())) ||
+ ha_checktype(db_type) != db_type)
{
value= res ? res->c_ptr() : "NULL";
goto err;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 16503c58739..85f8d5d5e6f 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1644,6 +1644,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
Field **tmp_field;
ulong priv;
+ uint next_field;
for (tmp_field= table->field+3, priv = SELECT_ACL;
*tmp_field && (*tmp_field)->real_type() == FIELD_TYPE_ENUM &&
((Field_enum*) (*tmp_field))->typelib->count == 2 ;
@@ -1652,59 +1653,60 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
if (priv & rights) // set requested privileges
(*tmp_field)->store(&what, 1, &my_charset_latin1);
}
- rights=get_access(table,3);
+ rights= get_access(table, 3, &next_field);
DBUG_PRINT("info",("table->fields: %d",table->fields));
if (table->fields >= 31) /* From 4.0.0 we have more fields */
{
/* We write down SSL related ACL stuff */
switch (lex->ssl_type) {
case SSL_TYPE_ANY:
- table->field[24]->store("ANY",3, &my_charset_latin1);
- table->field[25]->store("", 0, &my_charset_latin1);
- table->field[26]->store("", 0, &my_charset_latin1);
- table->field[27]->store("", 0, &my_charset_latin1);
+ table->field[next_field]->store("ANY", 3, &my_charset_latin1);
+ table->field[next_field+1]->store("", 0, &my_charset_latin1);
+ table->field[next_field+2]->store("", 0, &my_charset_latin1);
+ table->field[next_field+3]->store("", 0, &my_charset_latin1);
break;
case SSL_TYPE_X509:
- table->field[24]->store("X509",4, &my_charset_latin1);
- table->field[25]->store("", 0, &my_charset_latin1);
- table->field[26]->store("", 0, &my_charset_latin1);
- table->field[27]->store("", 0, &my_charset_latin1);
+ table->field[next_field]->store("X509", 4, &my_charset_latin1);
+ table->field[next_field+1]->store("", 0, &my_charset_latin1);
+ table->field[next_field+2]->store("", 0, &my_charset_latin1);
+ table->field[next_field+3]->store("", 0, &my_charset_latin1);
break;
case SSL_TYPE_SPECIFIED:
- table->field[24]->store("SPECIFIED",9, &my_charset_latin1);
- table->field[25]->store("", 0, &my_charset_latin1);
- table->field[26]->store("", 0, &my_charset_latin1);
- table->field[27]->store("", 0, &my_charset_latin1);
+ table->field[next_field]->store("SPECIFIED", 9, &my_charset_latin1);
+ table->field[next_field+1]->store("", 0, &my_charset_latin1);
+ table->field[next_field+2]->store("", 0, &my_charset_latin1);
+ table->field[next_field+3]->store("", 0, &my_charset_latin1);
if (lex->ssl_cipher)
- table->field[25]->store(lex->ssl_cipher,
- strlen(lex->ssl_cipher), system_charset_info);
+ table->field[next_field+1]->store(lex->ssl_cipher,
+ strlen(lex->ssl_cipher), system_charset_info);
if (lex->x509_issuer)
- table->field[26]->store(lex->x509_issuer,
- strlen(lex->x509_issuer), system_charset_info);
+ table->field[next_field+2]->store(lex->x509_issuer,
+ strlen(lex->x509_issuer), system_charset_info);
if (lex->x509_subject)
- table->field[27]->store(lex->x509_subject,
- strlen(lex->x509_subject), system_charset_info);
+ table->field[next_field+3]->store(lex->x509_subject,
+ strlen(lex->x509_subject), system_charset_info);
break;
case SSL_TYPE_NOT_SPECIFIED:
break;
case SSL_TYPE_NONE:
- table->field[24]->store("", 0, &my_charset_latin1);
- table->field[25]->store("", 0, &my_charset_latin1);
- table->field[26]->store("", 0, &my_charset_latin1);
- table->field[27]->store("", 0, &my_charset_latin1);
+ table->field[next_field]->store("", 0, &my_charset_latin1);
+ table->field[next_field+1]->store("", 0, &my_charset_latin1);
+ table->field[next_field+2]->store("", 0, &my_charset_latin1);
+ table->field[next_field+3]->store("", 0, &my_charset_latin1);
break;
}
+ next_field+=4;
USER_RESOURCES mqh= lex->mqh;
if (mqh.specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
- table->field[28]->store((longlong) mqh.questions);
+ table->field[next_field]->store((longlong) mqh.questions);
if (mqh.specified_limits & USER_RESOURCES::UPDATES_PER_HOUR)
- table->field[29]->store((longlong) mqh.updates);
+ table->field[next_field+1]->store((longlong) mqh.updates);
if (mqh.specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR)
- table->field[30]->store((longlong) mqh.conn_per_hour);
+ table->field[next_field+2]->store((longlong) mqh.conn_per_hour);
if (table->fields >= 36 &&
(mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS))
- table->field[33]->store((longlong) mqh.user_conn);
+ table->field[next_field+3]->store((longlong) mqh.user_conn);
mqh_used= mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour;
}
if (old_row_exists)
@@ -2587,41 +2589,59 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(TRUE);
}
- if (columns.elements && !revoke_grant)
+ if (!revoke_grant)
{
- class LEX_COLUMN *column;
- List_iterator <LEX_COLUMN> column_iter(columns);
- int res;
-
- if (open_and_lock_tables(thd, table_list))
- DBUG_RETURN(TRUE);
-
- while ((column = column_iter++))
+ if (columns.elements)
{
- uint unused_field_idx= NO_CACHED_FIELD_INDEX;
- if (!find_field_in_table(thd, table_list, column->column.ptr(),
- column->column.ptr(),
- column->column.length(), 0, 0, 0, 0,
- &unused_field_idx, FALSE))
+ class LEX_COLUMN *column;
+ List_iterator <LEX_COLUMN> column_iter(columns);
+ int res;
+
+ if (open_and_lock_tables(thd, table_list))
+ DBUG_RETURN(TRUE);
+
+ while ((column = column_iter++))
{
- my_error(ER_BAD_FIELD_ERROR, MYF(0),
- column->column.c_ptr(), table_list->alias);
- DBUG_RETURN(TRUE);
+ uint unused_field_idx= NO_CACHED_FIELD_INDEX;
+ Field *f=find_field_in_table(thd, table_list, column->column.ptr(),
+ column->column.ptr(),
+ column->column.length(), 0, 0, 0, 0,
+ &unused_field_idx, FALSE);
+ if (f == (Field*)0)
+ {
+ my_error(ER_BAD_FIELD_ERROR, MYF(0),
+ column->column.c_ptr(), table_list->alias);
+ DBUG_RETURN(TRUE);
+ }
+ if (f == (Field *)-1)
+ DBUG_RETURN(TRUE);
+ column_priv|= column->rights;
}
- column_priv|= column->rights;
+ close_thread_tables(thd);
}
- close_thread_tables(thd);
- }
- else if (!(rights & CREATE_ACL) && !revoke_grant)
- {
- char buf[FN_REFLEN];
- sprintf(buf,"%s/%s/%s.frm",mysql_data_home, table_list->db,
- table_list->real_name);
- fn_format(buf,buf,"","",4+16+32);
- if (access(buf,F_OK))
+ else
{
- my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias);
- DBUG_RETURN(TRUE);
+ if (!(rights & CREATE_ACL))
+ {
+ char buf[FN_REFLEN];
+ sprintf(buf,"%s/%s/%s.frm",mysql_data_home, table_list->db,
+ table_list->real_name);
+ fn_format(buf,buf,"","",4+16+32);
+ if (access(buf,F_OK))
+ {
+ my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias);
+ DBUG_RETURN(TRUE);
+ }
+ }
+ if (table_list->grant.want_privilege)
+ {
+ char command[128];
+ get_privilege_desc(command, sizeof(command),
+ table_list->grant.want_privilege);
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
+ command, thd->priv_user, thd->host_or_ip, table_list->alias);
+ DBUG_RETURN(-1);
+ }
}
}
@@ -3337,25 +3357,8 @@ err:
rw_unlock(&LOCK_grant);
if (!no_errors) // Not a silent skip of table
{
- const char *command="";
- if (want_access & SELECT_ACL)
- command= "select";
- else if (want_access & INSERT_ACL)
- command= "insert";
- else if (want_access & UPDATE_ACL)
- command= "update";
- else if (want_access & DELETE_ACL)
- command= "delete";
- else if (want_access & DROP_ACL)
- command= "drop";
- else if (want_access & CREATE_ACL)
- command= "create";
- else if (want_access & ALTER_ACL)
- command= "alter";
- else if (want_access & INDEX_ACL)
- command= "index";
- else if (want_access & GRANT_ACL)
- command= "grant";
+ char command[128];
+ get_privilege_desc(command, sizeof(command), want_access);
else if (want_access & CREATE_VIEW_ACL)
command= "create view";
else if (want_access & SHOW_VIEW_ACL)
@@ -3473,11 +3476,8 @@ bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
err:
rw_unlock(&LOCK_grant);
err2:
- const char *command= "";
- if (want_access & SELECT_ACL)
- command= "select";
- else if (want_access & INSERT_ACL)
- command= "insert";
+ char command[128];
+ get_privilege_desc(command, sizeof(command), want_access);
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
command,
thd->priv_user,
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index c681fe25548..7a271daa862 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -702,9 +702,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
if (!table)
table= table_list->table;
- if ((thd->lex->sql_command == SQLCOM_INSERT ||
- thd->lex->sql_command == SQLCOM_REPLACE) &&
- unique_table(table_list, table_list->next_global))
+ if (!select_insert && unique_table(table_list, table_list->next_global))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
DBUG_RETURN(TRUE);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index c860e3a79ac..180e2c67f8d 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -907,15 +907,16 @@ static bool mysql_test_insert(Prepared_statement *stmt,
ulong counter= 0;
Item *unused_conds= 0;
+ table_list->table->insert_values=(byte *)1; // don't allocate insert_values
if ((res= mysql_prepare_insert(thd, table_list, table_list->table,
fields, values, update_fields,
update_values, duplic,
&unused_conds, FALSE)))
goto error;
-
+
value_count= values->elements;
its.rewind();
-
+
while ((values= its++))
{
counter++;
@@ -932,6 +933,7 @@ static bool mysql_test_insert(Prepared_statement *stmt,
res= 0;
error:
lex->unit.cleanup();
+ table_list->table->insert_values=0;
DBUG_RETURN(res);
}
@@ -1587,28 +1589,6 @@ static bool init_param_array(Prepared_statement *stmt)
return FALSE;
}
-
-/* Init statement before execution */
-
-static void cleanup_stmt_for_execute(Prepared_statement *stmt)
-{
- THD *thd= stmt->thd;
- LEX *lex= stmt->lex;
- SELECT_LEX *sl= lex->all_selects_list;
-
- for (; sl; sl= sl->next_select_in_list())
- {
- for (TABLE_LIST *tables= (TABLE_LIST*) sl->table_list.first;
- tables;
- tables= tables->next_global)
- {
- if (tables->table)
- tables->table->insert_values= 0;
- }
- }
-}
-
-
/*
Given a query string with parameter markers, create a Prepared Statement
from it and send PS info back to the client.
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 3cc421b1312..e8655a2a304 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2585,7 +2585,11 @@ err:
send_ok(thd);
DBUG_RETURN(0);
}
- DBUG_RETURN(error);
+
+ if (error == HA_ERR_ROW_IS_REFERENCED)
+ my_error(ER_ROW_IS_REFERENCED, MYF(0));
+
+ DBUG_RETURN(-1);
}
diff --git a/sql/strfunc.cc b/sql/strfunc.cc
index 777b3851294..824aa15097e 100644
--- a/sql/strfunc.cc
+++ b/sql/strfunc.cc
@@ -170,6 +170,43 @@ uint find_type2(TYPELIB *typelib, const char *x, uint length, CHARSET_INFO *cs)
/*
+ Un-hex all elements in a typelib
+
+ SYNOPSIS
+ unhex_type2()
+ interval TYPELIB (struct of pointer to values + lengths + count)
+
+ NOTES
+
+ RETURN
+ N/A
+*/
+
+void unhex_type2(TYPELIB *interval)
+{
+ for (uint pos= 0; pos < interval->count; pos++)
+ {
+ char *from, *to;
+ for (from= to= (char*) interval->type_names[pos]; *from; )
+ {
+ /*
+ Note, hexchar_to_int(*from++) doesn't work
+ one some compilers, e.g. IRIX. Looks like a compiler
+ bug in inline functions in combination with arguments
+ that have a side effect. So, let's use from[0] and from[1]
+ and increment 'from' by two later.
+ */
+
+ *to++= (char) (hexchar_to_int(from[0]) << 4) +
+ hexchar_to_int(from[1]);
+ from+= 2;
+ }
+ interval->type_lengths[pos] /= 2;
+ }
+}
+
+
+/*
Check if the first word in a string is one of the ones in TYPELIB
SYNOPSIS
diff --git a/sql/table.cc b/sql/table.cc
index efc27a964c7..ee204347b88 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -24,7 +24,8 @@
/* Functions defined in this file */
-static void frm_error(int error,TABLE *form,const char *name,int errortype);
+static void frm_error(int error,TABLE *form,const char *name,
+ int errortype, int errarg);
static void fix_type_pointers(const char ***array, TYPELIB *point_to_type,
uint types, char **names);
static uint find_field(TABLE *form,uint start,uint length);
@@ -57,7 +58,7 @@ static byte* get_field_name(Field **buff,uint *length,
2 Error (see frm_error)
3 Wrong data in .frm file
4 Error (see frm_error)
- 5 It is new format of .frm file
+ 5 Error (see frm_error: charset unavailable)
*/
int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
@@ -65,7 +66,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
{
reg1 uint i;
reg2 uchar *strpos;
- int j,error;
+ int j,error, errarg= 0;
uint rec_buff_length,n_length,int_length,records,key_parts,keys,
interval_count,interval_parts,read_length,db_create_options;
uint key_info_length, com_length;
@@ -454,10 +455,14 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
}
else
{
- if (!strpos[14])
- charset= &my_charset_bin;
- else if (!(charset=get_charset((uint) strpos[14], MYF(0))))
- charset= outparam->table_charset;
+ if (!strpos[14])
+ charset= &my_charset_bin;
+ else if (!(charset=get_charset((uint) strpos[14], MYF(0))))
+ {
+ error= 5; // Unknown or unavailable charset
+ errarg= (int) strpos[14];
+ goto err_not_open;
+ }
}
if (!comment_length)
{
@@ -509,25 +514,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
{
/* Unescape UCS2 intervals from HEX notation */
TYPELIB *interval= outparam->intervals + interval_nr - 1;
- for (uint pos= 0; pos < interval->count; pos++)
- {
- char *from, *to;
- for (from= to= (char*) interval->type_names[pos]; *from; )
- {
- /*
- Note, hexchar_to_int(*from++) doesn't work
- one some compilers, e.g. IRIX. Looks like a compiler
- bug in inline functions in combination with arguments
- that have a side effect. So, let's use from[0] and from[1]
- and increment 'from' by two later.
- */
-
- *to++= (char) (hexchar_to_int(from[0]) << 4) +
- hexchar_to_int(from[1]);
- from+= 2;
- }
- interval->type_lengths[pos] /= 2;
- }
+ unhex_type2(interval);
}
*field_ptr=reg_field=
@@ -847,7 +834,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
delete crypted;
*root_ptr= old_root;
if (! error_reported)
- frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG);
+ frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG, errarg);
delete outparam->file;
outparam->file=0; // For easier errorchecking
outparam->db_stat=0;
@@ -1032,7 +1019,8 @@ ulong make_new_entry(File file, uchar *fileinfo, TYPELIB *formnames,
/* error message when opening a form file */
-static void frm_error(int error, TABLE *form, const char *name, myf errortype)
+static void frm_error(int error, TABLE *form, const char *name,
+ myf errortype, int errarg)
{
int err_no;
char buff[FN_REFLEN];
@@ -1059,8 +1047,22 @@ static void frm_error(int error, TABLE *form, const char *name, myf errortype)
datext= datext==NullS ? "" : datext;
err_no= (my_errno == ENOENT) ? ER_FILE_NOT_FOUND : (my_errno == EAGAIN) ?
ER_FILE_USED : ER_CANT_OPEN_FILE;
- my_error(err_no, errortype,
- fn_format(buff, form->real_name, form_dev, datext, 2), my_errno);
+ my_error(err_no,errortype,
+ fn_format(buff,form->real_name,form_dev,datext,2),my_errno);
+ break;
+ }
+ case 5:
+ {
+ const char *csname= get_charset_name((uint) errarg);
+ char tmp[10];
+ if (!csname || csname[0] =='?')
+ {
+ my_snprintf(tmp, sizeof(tmp), "#%d", errarg);
+ csname= tmp;
+ }
+ my_printf_error(ER_UNKNOWN_COLLATION,
+ "Unknown collation '%s' in table '%-.64s' definition",
+ MYF(0), csname, form->real_name);
break;
}
default: /* Better wrong error than none */
diff --git a/sql/unireg.cc b/sql/unireg.cc
index a16439530fc..ee036ed113d 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -174,6 +174,17 @@ bool mysql_create_frm(THD *thd, my_string file_name,
goto err2;
if (my_close(file,MYF(MY_WME)))
goto err3;
+
+ {
+ /* Unescape all UCS2 intervals: were escaped in pack_headers */
+ List_iterator<create_field> it(create_fields);
+ create_field *field;
+ while ((field=it++))
+ {
+ if (field->interval && field->charset->mbminlen > 1)
+ unhex_type2(field->interval);
+ }
+ }
DBUG_RETURN(0);
err: