diff options
author | unknown <serg@sergbook.mysql.com> | 2004-12-31 15:26:24 +0100 |
---|---|---|
committer | unknown <serg@sergbook.mysql.com> | 2004-12-31 15:26:24 +0100 |
commit | b99bea6704299399c84bd8374ef7f248ff9570c5 (patch) | |
tree | 928b06c231edee4cb95ace87ed30e879e3dcb0fb /sql | |
parent | bd23099be0b22845e8c97e2fb36ee3c6eb0e2491 (diff) | |
parent | 5eaf65ab4be77911eb03cceefac9ecea48c25f71 (diff) | |
download | mariadb-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.cc | 44 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 5 | ||||
-rw-r--r-- | sql/item_func.cc | 3 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 21 | ||||
-rw-r--r-- | sql/item_subselect.cc | 11 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 60 | ||||
-rw-r--r-- | sql/log.cc | 4 | ||||
-rw-r--r-- | sql/mysql_priv.h | 1 | ||||
-rw-r--r-- | sql/mysqld.cc | 67 | ||||
-rw-r--r-- | sql/set_var.cc | 4 | ||||
-rw-r--r-- | sql/sql_acl.cc | 160 | ||||
-rw-r--r-- | sql/sql_insert.cc | 4 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 28 | ||||
-rw-r--r-- | sql/sql_table.cc | 6 | ||||
-rw-r--r-- | sql/strfunc.cc | 37 | ||||
-rw-r--r-- | sql/table.cc | 62 | ||||
-rw-r--r-- | sql/unireg.cc | 11 |
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: |