From 36d1659a80ce09f480e2af9efa9c6eb32157ec02 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Nov 2007 18:02:12 +0200 Subject: Bug #31928: Search fails on '1000-00-00' date after sql_mode change When constructing a key image stricter date checking (from sql_mode) should not be enabled, because it will reject invalid dates that the server would otherwise accept for searching when there's no index. Fixed by disabling strict date checking when constructing a key image. mysql-test/r/type_date.result: Bug #31928: test case mysql-test/t/type_date.test: Bug #31928: test case sql/sql_select.h: Bug #31928: Disable strict date checking when consructing a key image --- sql/sql_select.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/sql_select.h b/sql/sql_select.h index 4fc32e7fdb3..42be8d3ec68 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -548,14 +548,17 @@ public: enum store_key_result copy() { enum store_key_result result; - enum_check_fields saved_count_cuted_fields= - to_field->table->in_use->count_cuted_fields; + THD *thd= to_field->table->in_use; + enum_check_fields saved_count_cuted_fields= thd->count_cuted_fields; + ulong sql_mode= thd->variables.sql_mode; + thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); - to_field->table->in_use->count_cuted_fields= CHECK_FIELD_IGNORE; + thd->count_cuted_fields= CHECK_FIELD_IGNORE; result= copy_inner(); - to_field->table->in_use->count_cuted_fields= saved_count_cuted_fields; + thd->count_cuted_fields= saved_count_cuted_fields; + thd->variables.sql_mode= sql_mode; return result; } -- cgit v1.2.1 From 06323c2b742a16ed54069251321b4b57085930ca Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 10 Nov 2007 16:54:25 +0400 Subject: Bug #32063 "create table like" works case-significant only in "embedded" server (libmysqld) in mysql_creata_like_table() we 'downcase' the complete path to the .frm file. It works fine in standalone case as there usually we only have './' as a path to the datahome, but doesn't work in the embedded server where we add the real path there, so if a directory has uppercase letters in it's name, it won't be found. Fixed by 'downcasing' only database/table pair. sql/sql_table.cc: Bug #32063 "create table like" works case-significant only in "embedded" server (libmysqld) do not lowercase the database directory --- sql/sql_table.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0316d6a3c10..a1df7e21b73 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2429,12 +2429,12 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, strxmov(src_path, (*tmp_table)->path, reg_ext, NullS); else { - strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table, - reg_ext, NullS); + char *tablename_pos= strxmov(src_path, mysql_data_home, "/", NullS); + strxmov(tablename_pos, src_db, "/", src_table, reg_ext, NullS); + if (lower_case_table_names) + my_casedn_str(files_charset_info, tablename_pos); /* Resolve symlinks (for windows) */ fn_format(src_path, src_path, "", "", MYF(MY_UNPACK_FILENAME)); - if (lower_case_table_names) - my_casedn_str(files_charset_info, src_path); if (access(src_path, F_OK)) { my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table); -- cgit v1.2.1 From eb347921b736c06651189623b1dcd92a6d6d1039 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Nov 2007 10:51:47 +0400 Subject: Bug #31158 Spatial, Union, LONGBLOB vs BLOB bug (crops data) max_length parameter for BLOB-returning functions must be big enough for any possible content. Otherwise the field created for a table will be too small. mysql-test/r/gis.result: Bug #31158 Spatial, Union, LONGBLOB vs BLOB bug (crops data) test result mysql-test/t/gis.test: Bug #31158 Spatial, Union, LONGBLOB vs BLOB bug (crops data) test case sql/field.cc: Bug #31158 Spatial, Union, LONGBLOB vs BLOB bug (crops data) max_field_size used instead of numeric value sql/field.h: Bug #31158 Spatial, Union, LONGBLOB vs BLOB bug (crops data) max_field_size constant defined sql/item_geofunc.cc: Bug #31158 Spatial, Union, LONGBLOB vs BLOB bug (crops data) max_length parameter fixed --- sql/field.cc | 2 +- sql/field.h | 1 + sql/item_geofunc.cc | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 5b43b9b1955..ed6523e9299 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6975,7 +6975,7 @@ uint32 Field_blob::max_length() case 3: return 16777215 * field_charset->mbmaxlen; case 4: - return (uint32) 4294967295U; + return max_field_size; default: DBUG_ASSERT(0); // we should never go here return 0; diff --git a/sql/field.h b/sql/field.h index 20f1209a439..29be9ef38d4 100644 --- a/sql/field.h +++ b/sql/field.h @@ -26,6 +26,7 @@ #define NOT_FIXED_DEC 31 #define DATETIME_DEC 6 +const uint32 max_field_size= (uint32) 4294967295U; class Send_field; class Protocol; diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 6cb8c790319..7900396e5d8 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -29,7 +29,7 @@ void Item_geometry_func::fix_length_and_dec() { collation.set(&my_charset_bin); decimals=0; - max_length=MAX_BLOB_WIDTH; + max_length= max_field_size; maybe_null= 1; } -- cgit v1.2.1 From ee21ace74dcea0638835b46af44311e286d000f4 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Nov 2007 12:10:22 +0400 Subject: Bug #31960 All embedded test crash Crash happens as a result of NO_EMBEDDED_ACCESS_CHECKS option (which is default for embedded server). check_table_access failed on using unintialized structure. Better solutions here is to disable that code completely in this case. Though the crash happens only in 6.0 i belive it's good to do it in 5.1 sql/mysql_priv.h: Bug #31960 All embedded test crash. Access check functions from sql_parse.cc defined as FALSE if NO_EMBEDDED_ACCESS_CHECKS sql/sql_parse.cc: Bug #31960 All embedded test crash. Implementation of access checkings functions #ifdefed out for NO_EMBEDDED_ACCESS_CHECKS --- sql/mysql_priv.h | 36 ++++++++++++++++++++++++++++++++++++ sql/sql_parse.cc | 20 ++------------------ 2 files changed, 38 insertions(+), 18 deletions(-) (limited to 'sql') diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3b88fe0fca8..32e8574b979 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -680,6 +680,8 @@ void free_items(Item *item); void cleanup_items(Item *item); class THD; void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0); + +#ifndef NO_EMBEDDED_ACCESS_CHECKS bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables); bool check_single_table_access(THD *thd, ulong privilege, TABLE_LIST *tables, bool no_errors); @@ -688,6 +690,24 @@ bool check_routine_access(THD *thd,ulong want_access,char *db,char *name, bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table); bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list); bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc); +#else +inline bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables) +{ return false; } +inline bool check_single_table_access(THD *thd, ulong privilege, + TABLE_LIST *tables, bool no_errors) +{ return false; } +inline bool check_routine_access(THD *thd,ulong want_access,char *db, + char *name, bool is_proc, bool no_errors) +{ return false; } +inline bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table) +{ return false; } +inline bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list) +{ return false; } +inline bool check_some_routine_access(THD *thd, const char *db, + const char *name, bool is_proc) +{ return false; } +#endif /*NO_EMBEDDED_ACCESS_CHECKS*/ + bool multi_update_precheck(THD *thd, TABLE_LIST *tables); bool multi_delete_precheck(THD *thd, TABLE_LIST *tables); bool mysql_multi_update_prepare(THD *thd); @@ -992,11 +1012,27 @@ void kill_mysql(void); void close_connection(THD *thd, uint errcode, bool lock); bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, bool *write_to_binlog); +#ifndef NO_EMBEDDED_ACCESS_CHECKS bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv, bool no_grant, bool no_errors, bool schema_db); bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables, bool no_errors); bool check_global_access(THD *thd, ulong want_access); +#else +inline bool check_access(THD *thd, ulong access, const char *db, + ulong *save_priv, bool no_grant, bool no_errors, + bool schema_db) +{ + if (save_priv) + *save_priv= GLOBAL_ACLS; + return false; +} +inline bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables, + bool no_errors) +{ return false; } +inline bool check_global_access(THD *thd, ulong want_access) +{ return false; } +#endif /*NO_EMBEDDED_ACCESS_CHECKS*/ /* Support routine for SQL parser on partitioning syntax diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e6d953bcbe1..7334f989905 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3893,14 +3893,12 @@ create_sp_error: thd->server_status|= SERVER_MORE_RESULTS_EXISTS; } -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_routine_access(thd, EXECUTE_ACL, sp->m_db.str, sp->m_name.str, TRUE, FALSE)) { thd->net.no_send_ok= save_no_send_ok; goto error; } -#endif select_limit= thd->variables.select_limit; thd->variables.select_limit= HA_POS_ERROR; @@ -4580,6 +4578,7 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) } +#ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check grants for commands which work only with one table. @@ -4697,7 +4696,6 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, bool dont_check_global_grants, bool no_errors, bool schema_db) { Security_context *sctx= thd->security_ctx; -#ifndef NO_EMBEDDED_ACCESS_CHECKS ulong db_access; /* GRANT command: @@ -4710,7 +4708,6 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, */ bool db_is_pattern= (test(want_access & GRANT_ACL) && dont_check_global_grants); -#endif ulong dummy; DBUG_ENTER("check_access"); DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu", @@ -4749,9 +4746,6 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, } } -#ifdef NO_EMBEDDED_ACCESS_CHECKS - DBUG_RETURN(0); -#else if ((sctx->master_access & want_access) == want_access) { /* @@ -4809,7 +4803,6 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, thd->db : "unknown"))); /* purecov: tested */ DBUG_RETURN(TRUE); /* purecov: tested */ -#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } @@ -4834,16 +4827,12 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, bool check_global_access(THD *thd, ulong want_access) { -#ifdef NO_EMBEDDED_ACCESS_CHECKS - return 0; -#else char command[128]; if ((thd->security_ctx->master_access & want_access)) return 0; get_privilege_desc(command, sizeof(command), want_access); my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command); return 1; -#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } @@ -4933,9 +4922,7 @@ bool check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, bool no_errors) { -#ifndef NO_EMBEDDED_ACCESS_CHECKS TABLE_LIST *org_tables= tables; -#endif TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table(); Security_context *sctx= thd->security_ctx, *backup_ctx= thd->security_ctx; /* @@ -5022,11 +5009,7 @@ check_routine_access(THD *thd, ulong want_access,char *db, char *name, 0, no_errors, 0)) return TRUE; -#ifndef NO_EMBEDDED_ACCESS_CHECKS return check_grant_routine(thd, want_access, tables, is_proc, no_errors); -#else - return FALSE; -#endif } @@ -5116,6 +5099,7 @@ bool check_merge_table_access(THD *thd, char *db, return error; } +#endif /*NO_EMBEDDED_ACCESS_CHECKS*/ /**************************************************************************** Check stack size; Send error if there isn't enough stack to continue -- cgit v1.2.1 From b88cfbad684ed57b058a3e6b63d458516b41db85 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Nov 2007 13:09:59 +0400 Subject: Bug #31868 mysql_server_init crash when language path is not correctly set. When mysql_server_init() interrupts on some error (wrong errmsg file for example) in the middle of it's execution, it doesn't call execute_ddl_log_recovery() so LOCK_gdl mutex isn't init-ed. In this case we shouldn't execute release_ddl_log during cleanup as it uses that mutex inside. BitKeeper/etc/ignore: Added libmysqld/scheduler.cc libmysqld/sql_connect.cc libmysqld/sql_tablespace.cc libmysql_r/client_settings.h to the ignore list libmysqld/lib_sql.cc: Bug #31868 mysql_server_init crash when language path is not correctly set. line moved to clean_up() sql/mysqld.cc: Bug #31868 mysql_server_init crash when language path is not correctly set. release_ddl_log() now can be called from common 'clean_up()' sql/sql_table.cc: Bug #31868 mysql_server_init crash when language path is not correctly set. do_release flag added to the global_ddl_log and the construcntor to set it's initial value. Also now release_ddl_log() checks for that flag. --- sql/mysqld.cc | 3 ++- sql/sql_table.cc | 13 ++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a355c560996..09fe7fc1f2e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1164,6 +1164,8 @@ void clean_up(bool print_message) if (cleanup_done++) return; /* purecov: inspected */ + release_ddl_log(); + /* make sure that handlers finish up what they have that is dependent on the binlog @@ -3995,7 +3997,6 @@ we force server id to 2, but this MySQL server will not act as a slave."); pthread_cond_wait(&COND_thread_count,&LOCK_thread_count); (void) pthread_mutex_unlock(&LOCK_thread_count); - release_ddl_log(); #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY) if (Service.IsNT() && start_mode) Service.Stop(); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 86d1fe79a00..a8efdac57dc 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -279,7 +279,7 @@ uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen) */ -typedef struct st_global_ddl_log +struct st_global_ddl_log { /* We need to adjust buffer size to be able to handle downgrades/upgrades @@ -297,10 +297,12 @@ typedef struct st_global_ddl_log uint name_len; uint io_size; bool inited; + bool do_release; bool recovery_phase; -} GLOBAL_DDL_LOG; + st_global_ddl_log() : inited(false), do_release(false) {} +}; -GLOBAL_DDL_LOG global_ddl_log; +st_global_ddl_log global_ddl_log; pthread_mutex_t LOCK_gdl; @@ -460,6 +462,7 @@ static uint read_ddl_log_header() global_ddl_log.first_used= NULL; global_ddl_log.num_entries= 0; VOID(pthread_mutex_init(&LOCK_gdl, MY_MUTEX_INIT_FAST)); + global_ddl_log.do_release= true; DBUG_RETURN(entry_no); } @@ -1150,6 +1153,9 @@ void release_ddl_log() DDL_LOG_MEMORY_ENTRY *used_list= global_ddl_log.first_used; DBUG_ENTER("release_ddl_log"); + if (!global_ddl_log.do_release) + DBUG_VOID_RETURN; + pthread_mutex_lock(&LOCK_gdl); while (used_list) { @@ -1167,6 +1173,7 @@ void release_ddl_log() global_ddl_log.inited= 0; pthread_mutex_unlock(&LOCK_gdl); VOID(pthread_mutex_destroy(&LOCK_gdl)); + global_ddl_log.do_release= false; DBUG_VOID_RETURN; } -- cgit v1.2.1 From 0cfa3267fb222a8ce15ab80865400ea4293295a5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 Nov 2007 14:46:36 +0400 Subject: Bug#30294 blackhole engine causes 100% with 2 alter table statements running Implement neccessary shared lock structure for table locks. This is the backport of bug26241 fix. sql/ha_blackhole.cc: Implement neccessary shared lock structure for table locks. sql/ha_blackhole.h: Declare shared structure for table locks sql/handler.cc: added BLACKHOLE_DB case --- sql/ha_blackhole.cc | 122 +++++++++++++++++++++++++++++++++++++++++++++++----- sql/ha_blackhole.h | 18 +++++++- sql/handler.cc | 4 ++ 3 files changed, 132 insertions(+), 12 deletions(-) (limited to 'sql') diff --git a/sql/ha_blackhole.cc b/sql/ha_blackhole.cc index 3f4285ec595..93d085bbc88 100644 --- a/sql/ha_blackhole.cc +++ b/sql/ha_blackhole.cc @@ -22,6 +22,14 @@ #ifdef HAVE_BLACKHOLE_DB #include "ha_blackhole.h" +/* Static declarations for shared structures */ + +static pthread_mutex_t blackhole_mutex; +static HASH blackhole_open_tables; +static int blackhole_init= FALSE; + +static st_blackhole_share *get_share(const char *table_name); +static void free_share(st_blackhole_share *share); /* Blackhole storage engine handlerton */ @@ -30,7 +38,7 @@ handlerton blackhole_hton= { SHOW_OPTION_YES, "/dev/null storage engine (anything you write to it disappears)", DB_TYPE_BLACKHOLE_DB, - NULL, + blackhole_db_init, 0, /* slot */ 0, /* savepoint size. */ NULL, /* close_connection */ @@ -70,15 +78,18 @@ const char **ha_blackhole::bas_ext() const int ha_blackhole::open(const char *name, int mode, uint test_if_locked) { DBUG_ENTER("ha_blackhole::open"); - thr_lock_init(&thr_lock); - thr_lock_data_init(&thr_lock,&lock,NULL); + + if (!(share= get_share(name))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + + thr_lock_data_init(&share->lock, &lock, NULL); DBUG_RETURN(0); } int ha_blackhole::close(void) { DBUG_ENTER("ha_blackhole::close"); - thr_lock_delete(&thr_lock); + free_share(share); DBUG_RETURN(0); } @@ -161,17 +172,23 @@ int ha_blackhole::external_lock(THD *thd, int lock_type) } -uint ha_blackhole::lock_count(void) const -{ - DBUG_ENTER("ha_blackhole::lock_count"); - DBUG_RETURN(0); -} - THR_LOCK_DATA **ha_blackhole::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type) { DBUG_ENTER("ha_blackhole::store_lock"); + if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) + { + if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && + lock_type <= TL_WRITE) && !thd->in_lock_tables) + lock_type = TL_WRITE_ALLOW_WRITE; + + if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) + lock_type = TL_READ; + + lock.type= lock_type; + } + *to++= &lock; DBUG_RETURN(to); } @@ -226,4 +243,89 @@ int ha_blackhole::index_last(byte * buf) DBUG_RETURN(HA_ERR_END_OF_FILE); } + +static st_blackhole_share *get_share(const char *table_name) +{ + st_blackhole_share *share; + uint length; + + length= (uint) strlen(table_name); + pthread_mutex_lock(&blackhole_mutex); + + if (!(share= (st_blackhole_share*) hash_search(&blackhole_open_tables, + (byte*) table_name, length))) + { + if (!(share= (st_blackhole_share*) my_malloc(sizeof(st_blackhole_share) + + length, + MYF(MY_WME | MY_ZEROFILL)))) + goto error; + + share->table_name_length= length; + strmov(share->table_name, table_name); + + if (my_hash_insert(&blackhole_open_tables, (byte*) share)) + { + my_free((gptr) share, MYF(0)); + share= NULL; + goto error; + } + + thr_lock_init(&share->lock); + } + share->use_count++; + +error: + pthread_mutex_unlock(&blackhole_mutex); + return share; +} + +static void free_share(st_blackhole_share *share) +{ + pthread_mutex_lock(&blackhole_mutex); + if (!--share->use_count) + hash_delete(&blackhole_open_tables, (byte*) share); + pthread_mutex_unlock(&blackhole_mutex); +} + + +static byte* blackhole_get_key(st_blackhole_share *share, uint *length, + my_bool not_used __attribute__((unused))) +{ + *length= share->table_name_length; + return (byte*) share->table_name; +} + + +bool blackhole_db_init() +{ + DBUG_ENTER("blackhole_db_init"); + if (pthread_mutex_init(&blackhole_mutex, MY_MUTEX_INIT_FAST)) + goto error; + if (hash_init(&blackhole_open_tables, &my_charset_bin, 32, 0, 0, + (hash_get_key) blackhole_get_key, 0, 0)) + { + VOID(pthread_mutex_destroy(&blackhole_mutex)); + } + else + { + blackhole_init= TRUE; + DBUG_RETURN(FALSE); + } +error: + have_blackhole_db= SHOW_OPTION_DISABLED; // If we couldn't use handler + DBUG_RETURN(TRUE); +} + + +bool blackhole_db_end() +{ + if (blackhole_init) + { + hash_free(&blackhole_open_tables); + VOID(pthread_mutex_destroy(&blackhole_mutex)); + } + blackhole_init= 0; + return FALSE; +} + #endif /* HAVE_BLACKHOLE_DB */ diff --git a/sql/ha_blackhole.h b/sql/ha_blackhole.h index 4dcb37c637d..45ed0351457 100644 --- a/sql/ha_blackhole.h +++ b/sql/ha_blackhole.h @@ -17,6 +17,18 @@ #pragma interface /* gcc class implementation */ #endif + +/* + Shared structure for correct LOCK operation +*/ +struct st_blackhole_share { + THR_LOCK lock; + uint use_count; + uint table_name_length; + char table_name[1]; +}; + + /* Class definition for the blackhole storage engine "Dumbest named feature ever" @@ -24,7 +36,7 @@ class ha_blackhole: public handler { THR_LOCK_DATA lock; /* MySQL lock */ - THR_LOCK thr_lock; + st_blackhole_share *share; public: ha_blackhole(TABLE *table_arg); @@ -76,10 +88,12 @@ public: void position(const byte *record); int info(uint flag); int external_lock(THD *thd, int lock_type); - uint lock_count(void) const; int create(const char *name, TABLE *table_arg, HA_CREATE_INFO *create_info); THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type); }; + +bool blackhole_db_init(void); +bool blackhole_db_end(void); diff --git a/sql/handler.cc b/sql/handler.cc index bfb7e8c369f..27204ae725b 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -515,6 +515,10 @@ int ha_panic(enum ha_panic_function flag) if (have_berkeley_db == SHOW_OPTION_YES) error|=berkeley_end(); #endif +#ifdef HAVE_BLACKHOLE_DB + if (have_blackhole_db == SHOW_OPTION_YES) + error|= blackhole_db_end(); +#endif #ifdef HAVE_INNOBASE_DB if (have_innodb == SHOW_OPTION_YES) error|=innobase_end(); -- cgit v1.2.1 From 1c1dd1f25c42081c7bf72042ccfcb83896298aab Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 Nov 2007 13:58:09 +0300 Subject: Fix for bug #32241: memory corruption due to large index map in 'Range checked for each record' The problem was in incorrectly calculated length of the buffer used to store a hexadecimal representation of an index map in select_describe(). This could result in buffer overrun and stack corruption under some circumstances. Fixed by correcting the calculation. mysql-test/r/explain.result: Added a test case for bug #32241. mysql-test/t/explain.test: Added a test case for bug #32241. sql/sql_select.cc: Corrected the buffer length calculation. Count one hex digit as 4 bits, not 8. --- sql/sql_select.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 24d1639edf1..4ff80185a85 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15282,7 +15282,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, { if (tab->use_quick == 2) { - char buf[MAX_KEY/8+1]; + /* 4 bits per 1 hex digit + terminating '\0' */ + char buf[MAX_KEY / 4 + 1]; extra.append(STRING_WITH_LEN("; Range checked for each " "record (index map: 0x")); extra.append(tab->keys.print(buf)); -- cgit v1.2.1 From 99054db64c8a41acbe570756e286a8d78811197c Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 18 Nov 2007 00:02:55 +0400 Subject: Fixed bug #32335. Comparison of a BIGINT NOT NULL column with a constant arithmetic expression that evaluates to NULL caused error 1048: "Column '...' cannot be null". Made convert_constant_item() check if the constant expression is NULL before attempting to store it in a field. Attempts to store NULL in a NOT NULL field caused query errors. sql/item_cmpfunc.cc: Fixed bug #32335. 1. Made convert_constant_item() check if the constant expression is NULL before attempting to store it in a field. Attempts to store NULL in a NOT NULL field caused query errors. 2. Also minor bug has been fixed: the thd->count_cuted_fields value was not restored in case of successful conversion. mysql-test/t/select.test: Added test case for bug #32335. mysql-test/r/select.result: Added test case for bug #32335. --- sql/item_cmpfunc.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 85ec8fa40d6..f9744baf19e 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -350,11 +350,12 @@ static bool convert_constant_item(THD *thd, Field *field, Item **item) thd->variables.sql_mode= (orig_sql_mode & ~MODE_NO_ZERO_DATE) | MODE_INVALID_DATES; thd->count_cuted_fields= CHECK_FIELD_IGNORE; - if (!(*item)->save_in_field(field, 1) && !((*item)->null_value)) + if (!(*item)->is_null() && !(*item)->save_in_field(field, 1)) { Item *tmp=new Item_int_with_ref(field->val_int(), *item, test(field->flags & UNSIGNED_FLAG)); thd->variables.sql_mode= orig_sql_mode; + thd->count_cuted_fields= orig_count_cuted_fields; if (tmp) thd->change_item_tree(item, tmp); return 1; // Item was replaced -- cgit v1.2.1 From b15802298b53f0627ab10739c1e54cfc22434e1a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Nov 2007 12:42:25 +0400 Subject: Bug#32158 Crash in open_table_from_share, on mysql_unpack_partition errors added check for the result of mysql_unpack_partition() sql/table.cc: added check for the result of mysql_unpack_partition() --- sql/table.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/table.cc b/sql/table.cc index c3ddb809b9e..c30407920f4 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1787,13 +1787,18 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, outparam, is_create_table, share->default_part_db_type, &work_part_info_used); - if (!tmp) - outparam->part_info->is_auto_partitioned= share->auto_partitioned; + if (tmp) + { + thd->stmt_arena= backup_stmt_arena_ptr; + thd->restore_active_arena(&part_func_arena, &backup_arena); + goto partititon_err; + } + outparam->part_info->is_auto_partitioned= share->auto_partitioned; DBUG_PRINT("info", ("autopartitioned: %u", share->auto_partitioned)); /* we should perform the fix_partition_func in either local or caller's arena depending on work_part_info_used value */ - if (!tmp && !work_part_info_used) + if (!work_part_info_used) tmp= fix_partition_func(thd, outparam, is_create_table); thd->stmt_arena= backup_stmt_arena_ptr; thd->restore_active_arena(&part_func_arena, &backup_arena); @@ -1803,6 +1808,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, tmp= fix_partition_func(thd, outparam, is_create_table); outparam->part_info->item_free_list= part_func_arena.free_list; } +partititon_err: if (tmp) { if (is_create_table) -- cgit v1.2.1 From ea739898281a86c074275f2f0a084840d7ed3e44 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Nov 2007 21:34:21 +0400 Subject: Fixed bug #32282: TEXT silently truncates when value is exactly 65536 bytes length. The server has been modified to report warnings on truncation to 65536 bytes as usual. sql/sql_string.cc: Fixed bug #32282. The well_formed_copy_nchars function returned an incorrect value of copied bytes of the truncated input string: extra length of the first truncated character added to the *from_end_pos pointer. That has been fixed. mysql-test/r/type_blob.result: Added test case for bug #32282. mysql-test/t/type_blob.test: Added test case for bug #32282. --- sql/sql_string.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 9d7df73cd7a..606a9ddb26d 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -858,7 +858,7 @@ outp: with optional left padding (for binary -> UCS2 conversion) SYNOPSIS - well_formed_copy_nhars() + well_formed_copy_nchars() to Store result here to_length Maxinum length of "to" string to_cs Character set of "to" string @@ -997,7 +997,10 @@ outp: goto outp; } else + { + from= from_prev; break; + } } *from_end_pos= from; res= to - to_start; -- cgit v1.2.1 From 13105534fa6107c5afb139a4459c659329525b2e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Nov 2007 20:00:25 +0000 Subject: Bug#31048: Many nested subqueries may cause server crash. This bug is actually two. The first one manifests itself on an EXPLAIN SELECT query with nested subqueries that employs the filesort algorithm. The whole SELECT under explain is marked as UNCACHEABLE_EXPLAIN to preserve some temporary structures for explain. As a side-effect of this values of nested subqueries weren't cached and subqueries were re-evaluated many times. Each time buffer for filesort was allocated but wasn't freed because freeing occurs at the end of topmost SELECT. Thus all available memory was eaten up step by step and OOM event occur. The second bug manifests itself on SELECT queries with conditions where a subquery result is compared with a key field and the subquery itself also has such condition. When a long chain of such nested subqueries is present the stack overrun occur. This happens because at some point the range optimizer temporary puts the PARAM structure on the stack. Its size if about 8K and the stack is exhausted very fast. Now the subselect_single_select_engine::exec function allows subquery result caching when the UNCACHEABLE_EXPLAIN flag is set. Now the SQL_SELECT::test_quick_select function calls the check_stack_overrun function for stack checking purposes to prevent server crash. mysql-test/t/subselect.test: Added a test case for the bug#31048: Many nested subqueries may cause server crash. mysql-test/r/subselect.result: Added a test case for the bug#31048: Many nested subqueries may cause server crash. sql/opt_range.cc: Bug#31048: Many nested subqueries may cause server crash. Now the SQL_SELECT::test_quick_select function calls the check_stack_overrun function for stack checking purposes to preven server crash. sql/item_subselect.cc: Bug31048: Many nested subqueries may cause server crash. Now the subselect_single_select_engine::exec function allows subquery result caching when the UNCACHEABLE_EXPLAIN flag is set. --- sql/item_subselect.cc | 4 +++- sql/opt_range.cc | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 0020dd35c61..19eb7708539 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1800,7 +1800,9 @@ int subselect_single_select_engine::exec() DBUG_RETURN(1); } } - if (select_lex->uncacheable && executed) + if (select_lex->uncacheable && + select_lex->uncacheable != UNCACHEABLE_EXPLAIN + && executed) { if (join->reinit()) { diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 969777d4792..dbdb2b919dc 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1978,12 +1978,18 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, keys_to_use.intersect(head->keys_in_use_for_query); if (!keys_to_use.is_clear_all()) { +#ifndef EMBEDDED_LIBRARY // Avoid compiler warning + char buff[STACK_BUFF_ALLOC]; +#endif MEM_ROOT alloc; SEL_TREE *tree= NULL; KEY_PART *key_parts; KEY *key_info; PARAM param; + if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) + DBUG_RETURN(0); // Fatal error flag is set + /* set up parameter that is passed to all functions */ param.thd= thd; param.baseflag=head->file->table_flags(); -- cgit v1.2.1 From 4addb6b71777706f4050163c66f3c1d9dc896cfe Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Nov 2007 21:05:17 +0000 Subject: Bug#30384: Having SQL_BUFFER_RESULT option in the CREATE .. KEY(..) .. SELECT led to creating corrupted index. Corrected fix. The new method called prepare2 is added to the select_create class. As all preparations are done by the select_create::prepare function it doesn't do anything. Slightly changed algorithm of calling the start_bulk_insert function. Now it's called from the select_insert::prepare2 function when the SQL_BUFFER_RESULT flags is set. The is_bulk_insert_mode flag is removed as it is not needed anymore. sql/sql_class.h: Bug#30384: Having SQL_BUFFER_RESULT option in the CREATE .. KEY(..) .. SELECT led to creating corrupted index. Corrected fix. The new method called prepare2 is added to the select_create class. As all preparetions are done by the select_create::prepare function it doesn't do anything. The is_bulk_insert_mode flag is removed as it is not needed anymore. sql/sql_insert.cc: Bug#30384: Having SQL_BUFFER_RESULT option in the CREATE .. KEY(..) .. SELECT led to creating corrupted index. Slightly changed algorithm of calling the start_bulk_insert function. Now it's called from the select_insert::prepare2 function when the SQL_BUFFER_RESULT flags is set. Corrected fix. The is_bulk_insert_mode flag is removed as it is not needed anymore. --- sql/sql_class.h | 4 ++-- sql/sql_insert.cc | 18 +++++------------- 2 files changed, 7 insertions(+), 15 deletions(-) (limited to 'sql') diff --git a/sql/sql_class.h b/sql/sql_class.h index e6d65f3133a..936798c9344 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2029,14 +2029,13 @@ class select_insert :public select_result_interceptor { ulonglong last_insert_id; COPY_INFO info; bool insert_into_view; - bool is_bulk_insert_mode; select_insert(TABLE_LIST *table_list_par, TABLE *table_par, List *fields_par, List *update_fields, List *update_values, enum_duplicates duplic, bool ignore); ~select_insert(); int prepare(List &list, SELECT_LEX_UNIT *u); - int prepare2(void); + virtual int prepare2(void); bool send_data(List &items); virtual void store_values(List &values); void send_error(uint errcode,const char *err); @@ -2071,6 +2070,7 @@ public: void send_error(uint errcode,const char *err); bool send_eof(); void abort(); + int prepare2(void) { return 0; } }; #include diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 770bbd1349d..48c1ee8e51f 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2645,8 +2645,7 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par, bool ignore_check_option_errors) :table_list(table_list_par), table(table_par), fields(fields_par), last_insert_id(0), - insert_into_view(table_list_par && table_list_par->view != 0), - is_bulk_insert_mode(FALSE) + insert_into_view(table_list_par && table_list_par->view != 0) { bzero((char*) &info,sizeof(info)); info.handle_duplicates= duplic; @@ -2755,14 +2754,14 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) Is table which we are changing used somewhere in other parts of query */ - if (!(lex->current_select->options & OPTION_BUFFER_RESULT) && - unique_table(thd, table_list, table_list->next_global, 0)) + if (unique_table(thd, table_list, table_list->next_global, 0)) { /* Using same table for INSERT and SELECT */ lex->current_select->options|= OPTION_BUFFER_RESULT; lex->current_select->join->select_options|= OPTION_BUFFER_RESULT; } - else if (!thd->prelocked_mode) + else if (!(lex->current_select->options & OPTION_BUFFER_RESULT) && + !thd->prelocked_mode) { /* We must not yet prepare the result table if it is the same as one of the @@ -2831,11 +2830,8 @@ int select_insert::prepare2(void) { DBUG_ENTER("select_insert::prepare2"); if (thd->lex->current_select->options & OPTION_BUFFER_RESULT && - !thd->prelocked_mode && !is_bulk_insert_mode) - { + !thd->prelocked_mode) table->file->start_bulk_insert((ha_rows) 0); - is_bulk_insert_mode= TRUE; - } DBUG_RETURN(0); } @@ -2941,7 +2937,6 @@ bool select_insert::send_eof() DBUG_ENTER("select_insert::send_eof"); error= (!thd->prelocked_mode) ? table->file->end_bulk_insert():0; - is_bulk_insert_mode= FALSE; table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); @@ -3277,10 +3272,7 @@ select_create::prepare(List &values, SELECT_LEX_UNIT *u) if (info.handle_duplicates == DUP_UPDATE) table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE); if (!thd->prelocked_mode) - { table->file->start_bulk_insert((ha_rows) 0); - is_bulk_insert_mode= TRUE; - } thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | -- cgit v1.2.1 From 0b22925cc0553c11fc7d131f27b1846253a8ee87 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Nov 2007 05:02:49 +0300 Subject: BUG#30573: Ordered range scan over partitioned tables returns some rows twice The problem: ha_partition::read_range_first() could return a record that is outside of the scanned range. If that record happened to be in the next subsequent range, it would satisfy the WHERE and appear in the output twice. (we would get it the second time when scanning the next subsequent range) Fix: Made ha_partition::read_range_first() check if the returned recod is within the scanned range, like other read_range_first() implementations do. mysql-test/r/partition_range.result: BUG#30573: Ordered range scan over partitioned tables returns some rows twice - Testcase mysql-test/t/partition_range.test: BUG#30573: Ordered range scan over partitioned tables returns some rows twice - Testcase sql/ha_partition.cc: BUG#30573: Ordered range scan over partitioned tables returns some rows twice - Make ha_partition::read_range_first() check if the returned record is within the range. --- sql/ha_partition.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 1400d9da753..423415ce4ae 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3838,7 +3838,7 @@ int ha_partition::read_range_first(const key_range *start_key, start_key->key, start_key->keypart_map, start_key->flag); } - DBUG_RETURN(error); + DBUG_RETURN (error? error: compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE); } -- cgit v1.2.1 From 2eaa6352e93b3b011be4c643d534b39a9fc8bf76 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Nov 2007 15:46:33 +0400 Subject: merging --- sql/mysql_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b5f0fa3a678..d58e3ae58ed 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -679,7 +679,7 @@ extern my_decimal decimal_zero; void free_items(Item *item); void cleanup_items(Item *item); class THD; -void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0); +void close_thread_tables(THD *thd); #ifndef NO_EMBEDDED_ACCESS_CHECKS bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables); -- cgit v1.2.1 From 429abc58452ce57256d6aacaece77d1672bccadf Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Nov 2007 16:07:24 +0200 Subject: Bug #32268: Indexed queries give bogus MIN and MAX results Loose index scan does the grouping so the temp table does not need to do it, even when sorting. Fixed by checking if the grouping is already done before doing sorting and grouping in a temp table and do only sorting. mysql-test/r/group_min_max.result: Bug #32268: test case mysql-test/t/group_min_max.test: Bug #32268: test case sql/sql_select.cc: Bug #32268: don't group in the temp table if already done --- sql/sql_select.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3d3b8668a79..757bfb3a29e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10256,7 +10256,8 @@ Next_select_func setup_end_select_func(JOIN *join) /* Set up select_end */ if (table) { - if (table->group && tmp_tbl->sum_func_count) + if (table->group && tmp_tbl->sum_func_count && + !tmp_tbl->precomputed_group_by) { if (table->s->keys) { -- cgit v1.2.1 From 0a91f285ad4a8d017a508e32a1c5d4deb7e0203a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Nov 2007 20:15:20 +0400 Subject: Fixed bug #32533. 8bit escape characters, termination and enclosed characters were silently ignored by SELECT INTO query, but LOAD DATA INFILE algorithm is 8bit-clean, so data was corrupted during encoding. sql/sql_class.cc: Fixed bug #32533. SELECT INTO OUTFILE encoding was not 8bit clear, it has been fixed for a symmetry with the LOAD DATA INFILE decoding algorithm. mysql-test/t/outfile_loaddata.test: Added test case for bug #32533. mysql-test/r/outfile_loaddata.result: Added test case for bug #32533. --- sql/sql_class.cc | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'sql') diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ef199b6f883..93f5a34d5c6 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1219,16 +1219,18 @@ select_export::prepare(List &list, SELECT_LEX_UNIT *u) } } field_term_length=exchange->field_term->length(); - field_term_char= field_term_length ? (*exchange->field_term)[0] : INT_MAX; + field_term_char= field_term_length ? + (int) (uchar) (*exchange->field_term)[0] : INT_MAX; if (!exchange->line_term->length()) exchange->line_term=exchange->field_term; // Use this if it exists - field_sep_char= (exchange->enclosed->length() ? (*exchange->enclosed)[0] : - field_term_char); - escape_char= (exchange->escaped->length() ? (*exchange->escaped)[0] : -1); + field_sep_char= (exchange->enclosed->length() ? + (int) (uchar) (*exchange->enclosed)[0] : field_term_char); + escape_char= (exchange->escaped->length() ? + (int) (uchar) (*exchange->escaped)[0] : -1); is_ambiguous_field_sep= test(strchr(ESCAPE_CHARS, field_sep_char)); is_unsafe_field_sep= test(strchr(NUMERIC_CHARS, field_sep_char)); line_sep_char= (exchange->line_term->length() ? - (*exchange->line_term)[0] : INT_MAX); + (int) (uchar) (*exchange->line_term)[0] : INT_MAX); if (!field_term_length) exchange->opt_enclosed=0; if (!exchange->enclosed->length()) @@ -1385,10 +1387,11 @@ bool select_export::send_data(List &items) Don't escape field_term_char by doubling - doubling is only valid for ENCLOSED BY characters: */ - (enclosed || !is_ambiguous_field_term || *pos != field_term_char)) + (enclosed || !is_ambiguous_field_term || + (int) (uchar) *pos != field_term_char)) { char tmp_buff[2]; - tmp_buff[0]= ((int) *pos == field_sep_char && + tmp_buff[0]= ((int) (uchar) *pos == field_sep_char && is_ambiguous_field_sep) ? field_sep_char : escape_char; tmp_buff[1]= *pos ? *pos : '0'; -- cgit v1.2.1 From 870d46819e517ec9dcd7b0e077147c69dbafa929 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Nov 2007 19:18:21 +0200 Subject: Bug #32400: Complex SELECT query returns correct result only on some occasions Referencing an element from the SELECT list in a WHERE clause is not permitted. The namespace of the WHERE clause is the table columns only. This was not enforced correctly when resolving outer references in sub-queries. Fixed by not allowing references to aliases in a sub-query in WHERE. mysql-test/include/ps_query.inc: Bug #32400: fixed old test queries mysql-test/r/ps_2myisam.result: Bug #32400: fixed old test queries mysql-test/r/ps_3innodb.result: Bug #32400: fixed old test queries mysql-test/r/ps_4heap.result: Bug #32400: fixed old test queries mysql-test/r/ps_5merge.result: Bug #32400: fixed old test queries mysql-test/r/ps_6bdb.result: Bug #32400: fixed old test queries mysql-test/r/ps_7ndb.result: Bug #32400: fixed old test queries mysql-test/r/subselect.result: Bug #32400: test case mysql-test/t/subselect.test: Bug #32400: test case sql/item.cc: Bug #32400: don't allow references to aliases in WHERE tests/mysql_client_test.c: Bug #32400: fixed old test queries --- sql/item.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index 431d82af331..3555df40060 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3641,7 +3641,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) } /* Search in SELECT and GROUP lists of the outer select. */ - if (outer_context->resolve_in_select_list) + if (place != IN_WHERE && place != IN_ON) { if (!(ref= resolve_ref_in_select_and_group(thd, this, select))) return -1; /* Some error occurred (e.g. ambiguous names). */ -- cgit v1.2.1 From 3a0d1f300bd3982f8332659270c531ecd8d1f288 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Nov 2007 02:48:01 +0300 Subject: sql_select.cc: Additional stack check for the bug#31048. sql/sql_select.cc: Additional stack check for the bug#31048. --- sql/sql_select.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sql') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3d3b8668a79..e25d0d78c87 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2332,6 +2332,11 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, { int error; DBUG_ENTER("get_quick_record_count"); +#ifndef EMBEDDED_LIBRARY // Avoid compiler warning + char buff[STACK_BUFF_ALLOC]; +#endif + if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) + DBUG_RETURN(0); // Fatal error flag is set if (select) { select->head=table; -- cgit v1.2.1 From e9832ceeac70a62b53d72a6c48e672165d658d8f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Nov 2007 11:40:05 +0200 Subject: Bug #30788: Inconsistent retrieval of char/varchar Index lookup does not always guarantee that we can simply remove the relevant conditions from the WHERE clause. Reasons can be e.g. conversion errors, partial indexes etc. The optimizer was removing these parts of the WHERE condition without any further checking. This leads to "false positives" when using indexes. Fixed by checking the index reference conditions (using WHERE) when using indexes with sub-queries. mysql-test/r/subselect.result: Bug #30788: - using where - test case mysql-test/r/subselect3.result: Bug #30788: using where mysql-test/t/subselect.test: Bug #30788: test case sql/item.h: Bug #30788: - Declare eq() method of Item_cache descendants : this is used in test_if_ref() - preserve the field that is being cached for type comparisions sql/sql_select.cc: Bug #30788: Don't remove the WHERE when using index lookup with subqueries. --- sql/item.h | 22 +++++++++++++++++++++- sql/sql_select.cc | 26 +++++++++++++++----------- 2 files changed, 36 insertions(+), 12 deletions(-) (limited to 'sql') diff --git a/sql/item.h b/sql/item.h index b611c59b8f1..ba65014d5e6 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2452,8 +2452,18 @@ class Item_cache: public Item protected: Item *example; table_map used_table_map; + /* + Field that this object will get value from. This is set/used by + index-based subquery engines to detect and remove the equality injected + by IN->EXISTS transformation. + For all other uses of Item_cache, cached_field doesn't matter. + */ + Field *cached_field; public: - Item_cache(): example(0), used_table_map(0) {fixed= 1; null_value= 1;} + Item_cache(): example(0), used_table_map(0), cached_field(0) + { + fixed= 1; null_value= 1; + } void set_used_tables(table_map map) { used_table_map= map; } @@ -2465,6 +2475,8 @@ public: decimals= item->decimals; collation.set(item->collation); unsigned_flag= item->unsigned_flag; + if (item->type() == FIELD_ITEM) + cached_field= ((Item_field *)item)->field; return 0; }; virtual void store(Item *)= 0; @@ -2475,6 +2487,14 @@ public: // to prevent drop fixed flag (no need parent cleanup call) void cleanup() {} void print(String *str); + bool eq_def(Field *field) + { + return cached_field ? cached_field->eq_def (field) : FALSE; + } + bool eq(const Item *item, bool binary_cmp) const + { + return this == item; + } }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7af39071561..211ac416c6d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -217,6 +217,7 @@ static void select_describe(JOIN *join, bool need_tmp_table,bool need_order, bool distinct, const char *message=NullS); static Item *remove_additional_cond(Item* conds); static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab); +static bool test_if_ref(Item_field *left_item,Item *right_item); /* @@ -673,9 +674,6 @@ err: without "checking NULL", remove the predicates that were pushed down into the subquery. - We can remove the equalities that will be guaranteed to be true by the - fact that subquery engine will be using index lookup. - If the subquery compares scalar values, we can remove the condition that was wrapped into trig_cond (it will be checked when needed by the subquery engine) @@ -685,6 +683,12 @@ err: and non-NULL values, we'll do a full table scan and will rely on the equalities corresponding to non-NULL parts of left tuple to filter out non-matching records. + + TODO: We can remove the equalities that will be guaranteed to be true by the + fact that subquery engine will be using index lookup. This must be done only + for cases where there are no conversion errors of significance, e.g. 257 + that is searched in a byte. But this requires homogenization of the return + codes of all Field*::store() methods. */ void JOIN::remove_subq_pushed_predicates(Item **where) @@ -692,17 +696,13 @@ void JOIN::remove_subq_pushed_predicates(Item **where) if (conds->type() == Item::FUNC_ITEM && ((Item_func *)this->conds)->functype() == Item_func::EQ_FUNC && ((Item_func *)conds)->arguments()[0]->type() == Item::REF_ITEM && - ((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM) + ((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM && + test_if_ref ((Item_field *)((Item_func *)conds)->arguments()[1], + ((Item_func *)conds)->arguments()[0])) { *where= 0; return; } - if (conds->type() == Item::COND_ITEM && - ((class Item_func *)this->conds)->functype() == - Item_func::COND_AND_FUNC) - { - *where= remove_additional_cond(conds); - } } @@ -1219,7 +1219,7 @@ JOIN::optimize() { if (!having) { - Item *where= 0; + Item *where= conds; if (join_tab[0].type == JT_EQ_REF && join_tab[0].ref.items[0]->name == in_left_expr_name) { @@ -11862,8 +11862,12 @@ static bool test_if_ref(Item_field *left_item,Item *right_item) Item *ref_item=part_of_refkey(field->table,field); if (ref_item && ref_item->eq(right_item,1)) { + right_item= right_item->real_item(); if (right_item->type() == Item::FIELD_ITEM) return (field->eq_def(((Item_field *) right_item)->field)); + /* remove equalities injected by IN->EXISTS transformation */ + else if (right_item->type() == Item::CACHE_ITEM) + return ((Item_cache *)right_item)->eq_def (field); if (right_item->const_item() && !(right_item->is_null())) { /* -- cgit v1.2.1 From a7c04594b8aced94b04329605f7789bb644baf91 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Nov 2007 22:56:42 +0400 Subject: Fixed bug #32556: assert in "using index for group-by" : is_last_prefix <= 0, file .\opt_range.cc. SELECT ... GROUP BY bit field failed with an assertion if the bit length of that field was not divisible by 8. sql/key.cc: Fixed bug #32556. Copying of "uneven" bits of a bit field was duplicated in the key_copy() and in the Field_bit::get_key_image(). So, instead of copying of the rest of a bit field, Field_bit::get_key_image() copied "uneven" bits to key image again, and the lowest field byte was not copied to key at all. Duplicated code has been removed from the key_copy function. mysql-test/t/type_bit.test: Added test case for bug #32556. mysql-test/r/type_bit.result: Added test case for bug #32556. --- sql/key.cc | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'sql') diff --git a/sql/key.cc b/sql/key.cc index 2bdde46b6b3..1c044f3dc7d 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -106,19 +106,6 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length) key_part->null_bit); key_length--; } - if (key_part->type == HA_KEYTYPE_BIT) - { - Field_bit *field= (Field_bit *) (key_part->field); - if (field->bit_len) - { - uchar bits= get_rec_bits((uchar*) from_record + - key_part->null_offset + - (key_part->null_bit == 128), - field->bit_ofs, field->bit_len); - *to_key++= bits; - key_length--; - } - } if (key_part->key_part_flag & HA_BLOB_PART || key_part->key_part_flag & HA_VAR_LENGTH_PART) { -- cgit v1.2.1 From 67522fcb9f92f8286060eeac3b5f054576b16735 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Nov 2007 19:22:54 +0300 Subject: Fix for bug #29976: Excessive Slave I/O errors in replication tests Problem: The "Slave I/O thread couldn't register on master" error sporadically occurred in replication tests because the slave I/O thread got killed by STOP SLAVE before or while registering on master. Fixed by checking the state of the I/O thread, and issueing the error only if it was not explicitely killed by a user. sql/slave.cc: When the slave I/O thread fails to register on master, issue an error message only if it is not explicitely killed by a user with STOP SLAVE. --- sql/slave.cc | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'sql') diff --git a/sql/slave.cc b/sql/slave.cc index fcbd4eb841b..9d8b0dc95eb 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -137,6 +137,7 @@ static int terminate_slave_thread(THD *thd, pthread_cond_t* term_cond, volatile uint *slave_running, bool skip_lock); +static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info); /* Find out which replications threads are running @@ -821,7 +822,7 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi) mi->clock_diff_with_master= (long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10)); } - else + else if (!check_io_slave_killed(mi->io_thd, mi, NULL)) { mi->clock_diff_with_master= 0; /* The "most sensible" value */ sql_print_warning("\"SELECT UNIX_TIMESTAMP()\" failed on master, " @@ -1223,7 +1224,7 @@ int register_slave_on_master(MYSQL* mysql, Master_info *mi, { *suppress_warnings= TRUE; // Suppress reconnect warning } - else + else if (!check_io_slave_killed(mi->io_thd, mi, NULL)) { char buf[256]; my_snprintf(buf, sizeof(buf), "%s (Errno: %d)", mysql_error(mysql), @@ -1985,7 +1986,7 @@ static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info) { if (io_slave_killed(thd, mi)) { - if (global_system_variables.log_warnings) + if (info && global_system_variables.log_warnings) sql_print_information(info); return TRUE; } @@ -2170,11 +2171,15 @@ connected: thd->proc_info = "Registering slave on master"; if (register_slave_on_master(mysql, mi, &suppress_warnings)) { - sql_print_error("Slave I/O thread couldn't register on master"); - if (check_io_slave_killed(thd, mi, "Slave I/O thread killed while \ -registering slave on master") || - try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings, - reconnect_messages[SLAVE_RECON_ACT_REG])) + if (!check_io_slave_killed(thd, mi, "Slave I/O thread killed " + "while registering slave on master")) + { + sql_print_error("Slave I/O thread couldn't register on master"); + if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings, + reconnect_messages[SLAVE_RECON_ACT_REG])) + goto err; + } + else goto err; goto connected; } -- cgit v1.2.1 From a197c4e95ddd69cf9ebe3a6b2796a68f420c009a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Nov 2007 00:16:17 +0300 Subject: opt_range.cc: Fix for the bug#31048 for 64bit platforms. subselect.test, subselect.result: Corrected text case for the bug#31048. mysql-test/t/subselect.test: Corrected text case for the bug#31048. mysql-test/r/subselect.result: Corrected text case for the bug#31048. sql/opt_range.cc: Fix for the bug#31048 for 64bit platforms. --- sql/opt_range.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index dbdb2b919dc..1a3c2bec621 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1987,7 +1987,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, KEY *key_info; PARAM param; - if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) + if (check_stack_overrun(thd, 2*STACK_MIN_SIZE, buff)) DBUG_RETURN(0); // Fatal error flag is set /* set up parameter that is passed to all functions */ -- cgit v1.2.1 From 339e8f5d6354d350ea6a5eb13ff8faead65dca49 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Nov 2007 13:40:53 +0200 Subject: merge 5.0-opt -> 5.1-opt --- sql/opt_range.cc | 2 +- sql/sql_select.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 10280168f07..a56fd9aad64 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2162,7 +2162,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, if (!keys_to_use.is_clear_all()) { #ifndef EMBEDDED_LIBRARY // Avoid compiler warning - char buff[STACK_BUFF_ALLOC]; + uchar buff[STACK_BUFF_ALLOC]; #endif MEM_ROOT alloc; SEL_TREE *tree= NULL; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index bec8d987276..f379542f8d7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2367,7 +2367,7 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, int error; DBUG_ENTER("get_quick_record_count"); #ifndef EMBEDDED_LIBRARY // Avoid compiler warning - char buff[STACK_BUFF_ALLOC]; + uchar buff[STACK_BUFF_ALLOC]; #endif if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) DBUG_RETURN(0); // Fatal error flag is set -- cgit v1.2.1 From 6b3fed49ea438ebb4e685510aa8f13f584ac0945 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Nov 2007 16:27:05 +0400 Subject: Bug#32178 server crash when select from i_s and concurrent partition management The crash happens because we change share->partition_info where 'share' is global struct (it affects other threads which use the same 'share'). It causes discrepancy between 'share' and handler data. The fix: Move share->partition_info update into WFRM_INSTALL_SHADOW part which is protected by OPEN_lock. sql/sql_partition.cc: fast_end_partition: added close_thread_tables() for the case when error occures fast_alter_partition_table: added close_thread_tables() for the case when error occures sql/sql_table.cc: The crash happens because we change share->partition_info where 'share' is global struct. It causes discrepancy between 'share' and handler data. The fix: Move share->partition_info update into WFRM_INSTALL_SHADOW part which is protected by OPEN_lock. --- sql/sql_partition.cc | 14 +++++++++----- sql/sql_table.cc | 52 ++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 47 insertions(+), 19 deletions(-) (limited to 'sql') diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index a06ad0a4612..1f365ac991b 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -3984,6 +3984,7 @@ static int fast_end_partition(THD *thd, ulonglong copied, DBUG_RETURN(FALSE); } table->file->print_error(error, MYF(0)); + close_thread_tables(thd); DBUG_RETURN(TRUE); } @@ -6106,7 +6107,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, (error= table->file->repair_partitions(thd)))) { table->file->print_error(error, MYF(0)); - DBUG_RETURN(TRUE); + goto err; } } else if (fast_alter_partition & HA_PARTITION_ONE_PHASE) @@ -6153,7 +6154,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, if (mysql_write_frm(lpt, WFRM_WRITE_SHADOW | WFRM_PACK_FRM) || mysql_change_partitions(lpt)) { - DBUG_RETURN(TRUE); + goto err; } } else if (alter_info->flags == ALTER_DROP_PARTITION) @@ -6246,7 +6247,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, (release_name_lock(lpt), FALSE)) { handle_alter_part_error(lpt, not_completed, TRUE, frm_install); - DBUG_RETURN(TRUE); + goto err; } } else if ((alter_info->flags & ALTER_ADD_PARTITION) && @@ -6315,7 +6316,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, (release_name_lock(lpt), FALSE)) { handle_alter_part_error(lpt, not_completed, FALSE, frm_install); - DBUG_RETURN(TRUE); + goto err; } } else @@ -6408,7 +6409,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, (release_name_lock(lpt), FALSE)) { handle_alter_part_error(lpt, not_completed, FALSE, frm_install); - DBUG_RETURN(TRUE); + goto err; } } /* @@ -6418,6 +6419,9 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, DBUG_RETURN(fast_end_partition(thd, lpt->copied, lpt->deleted, table, table_list, FALSE, NULL, written_bin_log)); +err: + close_thread_tables(thd); + DBUG_RETURN(TRUE); } #endif diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6f0864cb1cf..bf15968f09b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1248,6 +1248,10 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) char shadow_path[FN_REFLEN+1]; char shadow_frm_name[FN_REFLEN+1]; char frm_name[FN_REFLEN+1]; +#ifdef WITH_PARTITION_STORAGE_ENGINE + char *part_syntax_buf; + uint syntax_len; +#endif DBUG_ENTER("mysql_write_frm"); /* @@ -1271,12 +1275,8 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) #ifdef WITH_PARTITION_STORAGE_ENGINE { partition_info *part_info= lpt->table->part_info; - char *part_syntax_buf; - uint syntax_len; - if (part_info) { - TABLE_SHARE *share= lpt->table->s; if (!(part_syntax_buf= generate_partition_syntax(part_info, &syntax_len, TRUE, TRUE))) @@ -1284,16 +1284,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) DBUG_RETURN(TRUE); } part_info->part_info_string= part_syntax_buf; - share->partition_info_len= part_info->part_info_len= syntax_len; - if (share->partition_info_buffer_size < syntax_len + 1) - { - share->partition_info_buffer_size= syntax_len+1; - if (!(share->partition_info= - (char*) alloc_root(&share->mem_root, syntax_len+1))) - DBUG_RETURN(TRUE); - - } - memcpy((char*) share->partition_info, part_syntax_buf, syntax_len + 1); + part_info->part_info_len= syntax_len; } } #endif @@ -1371,7 +1362,40 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) #endif { error= 1; + goto err; + } +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (part_info) + { + TABLE_SHARE *share= lpt->table->s; + char *tmp_part_syntax_str; + if (!(part_syntax_buf= generate_partition_syntax(part_info, + &syntax_len, + TRUE, TRUE))) + { + error= 1; + goto err; + } + if (share->partition_info_buffer_size < syntax_len + 1) + { + share->partition_info_buffer_size= syntax_len+1; + if (!(tmp_part_syntax_str= (char*) strmake_root(&share->mem_root, + part_syntax_buf, + syntax_len))) + { + error= 1; + goto err; + } + share->partition_info= tmp_part_syntax_str; + } + else + memcpy((char*) share->partition_info, part_syntax_buf, syntax_len + 1); + share->partition_info_len= part_info->part_info_len= syntax_len; + part_info->part_info_string= part_syntax_buf; } +#endif + +err: VOID(pthread_mutex_unlock(&LOCK_open)); #ifdef WITH_PARTITION_STORAGE_ENGINE deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos); -- cgit v1.2.1 From 9a34c80e117872b6e564879e0d6cb6dafaa6568a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Nov 2007 18:21:24 +0400 Subject: Bug#30152 MySQLD crash duing alter table causes DROP DATABASE to FAIL due to temp file disable decoding of table name if the table is internal temporary table mysql-test/r/drop.result: test result mysql-test/t/drop.test: test case sql/sql_db.cc: check is the name is internal tmp table name sql/sql_table.cc: disable decoding of table name if the table is internal temporary table sql/table.h: added flag which is true when table name is the name of internal temporary table --- sql/sql_db.cc | 1 + sql/sql_table.cc | 5 +++-- sql/table.h | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/sql_db.cc b/sql/sql_db.cc index abbf2131957..88902e65a42 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1111,6 +1111,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, VOID(filename_to_tablename(file->name, table_list->table_name, strlen(file->name) + 1)); table_list->alias= table_list->table_name; // If lower_case_table_names=2 + table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix); /* Link into list */ (*tot_list_next)= table_list; tot_list_next= &table_list->next_local; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index bf15968f09b..75c97d8edd4 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1663,8 +1663,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, } alias= (lower_case_table_names == 2) ? table->alias : table->table_name; /* remove .frm file and engine files */ - path_length= build_table_filename(path, sizeof(path), - db, alias, reg_ext, 0); + path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext, + table->internal_tmp_table ? + FN_IS_TMP : 0); } if (drop_temporary || (table_type == NULL && diff --git a/sql/table.h b/sql/table.h index 2bbd71b70c6..440f3a3d5cf 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1081,6 +1081,7 @@ struct TABLE_LIST ... SELECT implementation). */ bool create; + bool internal_tmp_table; /* View creation context. */ -- cgit v1.2.1 From f3f9855d133060c5279349edac49546748ceae57 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Nov 2007 13:36:24 +0200 Subject: Bug #32036: EXISTS within a WHERE clause with a UNION crashes MySQL 5.122 There was a difference in how UNIONs are handled on top level and when in sub-query. Because the rules for sub-queries were syntactically allowing cases that are not currently supported by the server we had crashes (this bug) or wrong results (bug 32051). Fixed by making the syntax rules for UNIONs match the ones at top level. These rules however do not support nesting UNIONs, e.g. (SELECT a FROM t1 UNION ALL SELECT b FROM t2) UNION (SELECT c FROM t3 UNION ALL SELECT d FROM t4) Supports for statements with nested UNIONs will be added in a future version. mysql-test/r/subselect.result: Bug #32036: test case mysql-test/t/subselect.test: Bug #32036: test case sql/sql_yacc.yy: Bug #32036: Make the syntax rules for UNIONs in subqueries the same as for top level UNIONs. --- sql/sql_yacc.yy | 41 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) (limited to 'sql') diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3401bf739b3..2e2a9b180d0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1137,7 +1137,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type internal_variable_name -%type subselect subselect_init +%type subselect take_first_select get_select_lex %type comp_op @@ -9422,35 +9422,22 @@ union_option: | ALL { $$=0; } ; +take_first_select: /* empty */ + { + $$= Lex->current_select->master_unit()->first_select(); + }; + subselect: - SELECT_SYM subselect_start subselect_init subselect_end + SELECT_SYM subselect_start select_init2 take_first_select + subselect_end { - $$= $3; + $$= $4; } - | '(' subselect_start subselect ')' - { - THD *thd= YYTHD; - /* - note that a local variable can't be used for - $3 as it's used in local variable construction - and some compilers can't guarnatee the order - in which the local variables are initialized. - */ - List_iterator it($3->item_list); - Item *item; - /* - we must fill the items list for the "derived table". - */ - while ((item= it++)) - add_item_to_list(thd, item); - } - union_clause subselect_end { $$= $3; }; - -subselect_init: - select_init2 - { - $$= Lex->current_select->master_unit()->first_select(); - }; + | '(' subselect_start select_paren take_first_select + subselect_end ')' + { + $$= $4; + }; subselect_start: { -- cgit v1.2.1 From 1836b736000595b3b63c03b1a6db01003b01e395 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Nov 2007 18:36:05 +0300 Subject: 5.0 version of the fix for bug #9481: mysql_insert_id() returns 0 after insert ... select. The 5.0 manual page for mysql_insert_id() does not mention anything about INSERT ... SELECT, though its current behavior is incosistent with what the manual says about the plain INSERT. Fixed by changing the AUTO_INCREMENT and mysql_insert_id() handling logic in INSERT ... SELECT to be consistent with the INSERT behavior, the manual, and the changes in 5.1 introduced by WL3146: - mysql_insert_id() now returns the first automatically generated AUTO_INCREMENT value that was successfully inserted by INSERT ... SELECT - if an INSERT ... SELECT statement is executed, and no automatically generated value is successfully inserted, mysql_insert_id() now returns the ID of the last inserted row. sql/sql_class.h: Replaced last_insert_id with autoinc_value_of_last_inserted_row to be consistent with 5.1 code. sql/sql_insert.cc: Revised the AUTO_INCREMENT and mysql_insert_id() handling logic in INSERT ... SELECT to be consistent with INSERT behavior, the manual, and changes in 5.1 introduced by WL3146: - mysql_insert_id() now returns the first automatically generated AUTO_INCREMENT value that was successfully inserted; - if an INSERT ... SELECT statement is executed, and no automatically generated value is successfully inserted, mysql_insert_id() now returns the ID of the last inserted row. tests/mysql_client_test.c: Backported the test cases related to INSERT ... SELECT and mysql_insert_id() from WL3146 patch to 5.0. --- sql/sql_class.h | 3 ++- sql/sql_insert.cc | 48 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 9 deletions(-) (limited to 'sql') diff --git a/sql/sql_class.h b/sql/sql_class.h index 93a9d4d6da2..5a5607469d9 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2048,7 +2048,8 @@ class select_insert :public select_result_interceptor { TABLE_LIST *table_list; TABLE *table; List *fields; - ulonglong last_insert_id; + ulonglong autoinc_value_of_last_inserted_row; // not autogenerated + ulonglong autoinc_value_of_first_inserted_row; // autogenerated COPY_INFO info; bool insert_into_view; bool is_bulk_insert_mode; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 770bbd1349d..70f73f90be4 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2644,7 +2644,8 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par, enum_duplicates duplic, bool ignore_check_option_errors) :table_list(table_list_par), table(table_par), fields(fields_par), - last_insert_id(0), + autoinc_value_of_last_inserted_row(0), + autoinc_value_of_first_inserted_row(0), insert_into_view(table_list_par && table_list_par->view != 0), is_bulk_insert_mode(FALSE) { @@ -2901,15 +2902,25 @@ bool select_insert::send_data(List &values) } if (table->next_number_field) { + /* + If no value has been autogenerated so far, we need to remember the + value we just saw, we may need to send it to client in the end. + */ + if (!thd->insert_id_used) + autoinc_value_of_last_inserted_row= table->next_number_field->val_int(); /* Clear auto-increment field for the next record, if triggers are used we will clear it twice, but this should be cheap. */ table->next_number_field->reset(); - if (!last_insert_id && thd->insert_id_used) - last_insert_id= thd->last_insert_id; + if (!autoinc_value_of_last_inserted_row && thd->insert_id_used) + autoinc_value_of_last_inserted_row= thd->last_insert_id; } } + + if (thd->insert_id_used && !autoinc_value_of_first_inserted_row) + autoinc_value_of_first_inserted_row= thd->last_insert_id; + DBUG_RETURN(error); } @@ -2938,6 +2949,7 @@ bool select_insert::send_eof() { int error, error2; bool changed, transactional_table= table->file->has_transactions(); + ulonglong id; DBUG_ENTER("select_insert::send_eof"); error= (!thd->prelocked_mode) ? table->file->end_bulk_insert():0; @@ -2959,8 +2971,17 @@ bool select_insert::send_eof() DBUG_ASSERT(transactional_table || !changed || thd->transaction.stmt.modified_non_trans_table); - if (last_insert_id) - thd->insert_id(info.copied ? last_insert_id : 0); // For binary log + // For binary log + if (autoinc_value_of_last_inserted_row) + { + if (info.copied) + thd->insert_id(autoinc_value_of_last_inserted_row); + else + { + autoinc_value_of_first_inserted_row= 0; + thd->insert_id(0); + } + } /* Write to binlog before commiting transaction */ if (mysql_bin_log.is_open()) { @@ -2987,7 +3008,9 @@ bool select_insert::send_eof() thd->row_count_func= info.copied + info.deleted + ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? info.touched : info.updated); - ::send_ok(thd, (ulong) thd->row_count_func, last_insert_id, buff); + id= autoinc_value_of_first_inserted_row > 0 ? + autoinc_value_of_first_inserted_row : thd->last_insert_id; + ::send_ok(thd, (ulong) thd->row_count_func, id, buff); DBUG_RETURN(0); } @@ -3016,8 +3039,17 @@ void select_insert::abort() if ((changed= info.copied || info.deleted || info.updated) && !transactional_table) { - if (last_insert_id) - thd->insert_id(last_insert_id); // For binary log + // For binary log + if (autoinc_value_of_last_inserted_row) + { + if (info.copied) + thd->insert_id(autoinc_value_of_last_inserted_row); + else + { + autoinc_value_of_first_inserted_row= 0; + thd->insert_id(0); + } + } if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, -- cgit v1.2.1 From 67bf39f241bb1742dfa221218ff3d50842f58490 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Nov 2007 18:58:54 +0300 Subject: Fix for bug #28837: MyISAM storage engine error (134) doing delete with self-join When doing DELETE with self-join on a MyISAM or MERGE table, it could happen that a record being retrieved in join_read_next_same() has already been deleted by previous iterations. That caused the engine's index_next_same() method to fail with HA_ERR_RECORD_DELETED error and the whole DELETE query to be aborted with an error. Fixed by suppressing the HA_ERR_RECORD_DELETED error in hy_myisam::index_next_same() and ha_myisammrg::index_next_same(). Since HA_ERR_RECORD_DELETED can only be returned by MyISAM, there is no point in filtering this error in the SQL layer. mysql-test/r/merge.result: Added a test case for bug #28837. mysql-test/r/myisam.result: Added a test case for bug #28837. mysql-test/t/merge.test: Added a test case for bug #28837. mysql-test/t/myisam.test: Added a test case for bug #28837. sql/ha_myisam.cc: Skip HA_ERR_RECORD_DELETED silently when calling mi_rnext_same(). sql/ha_myisammrg.cc: Skip HA_ERR_RECORD_DELETED silently when calling mi_rnext_same(). --- sql/ha_myisam.cc | 8 ++++++-- sql/ha_myisammrg.cc | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 92fa9e405e1..86f04672676 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1602,10 +1602,14 @@ int ha_myisam::index_next_same(byte * buf, const byte *key __attribute__((unused)), uint length __attribute__((unused))) { + int error; DBUG_ASSERT(inited==INDEX); statistic_increment(table->in_use->status_var.ha_read_next_count, - &LOCK_status); - int error=mi_rnext_same(file,buf); + &LOCK_status); + do + { + error= mi_rnext_same(file,buf); + } while (error == HA_ERR_RECORD_DELETED); table->status=error ? STATUS_NOT_FOUND: 0; return error; } diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 60aa4bd6adc..78492d2843d 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -294,9 +294,13 @@ int ha_myisammrg::index_next_same(byte * buf, const byte *key __attribute__((unused)), uint length __attribute__((unused))) { + int error; statistic_increment(table->in_use->status_var.ha_read_next_count, - &LOCK_status); - int error=myrg_rnext_same(file,buf); + &LOCK_status); + do + { + error= myrg_rnext_same(file,buf); + } while (error == HA_ERR_RECORD_DELETED); table->status=error ? STATUS_NOT_FOUND: 0; return error; } -- cgit v1.2.1 From d068dd1aabf29d7080a040469cf6ca58996f6fea Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 Nov 2007 19:14:48 +0400 Subject: Fixed bug #32403: query causes a crash due to stack and memory corruptions. The right pointer field of the SEL_ARG structure was not initialized in the constructor and sometimes that led to server crashes. There is no testcase because the bug occurs only when uninitialized memory has particular values, which can't be re-created in the test suite. sql/opt_range.cc: Fixed bug #32403. The eq_tree function requires that SEL_ARG::left and SEL_ARG::right are equal to null pointer if SEL_ARG type is MAYBE_KEY, but SEL_ARG::right was not initialized and contained garbage. --- sql/opt_range.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 969777d4792..58ce6c8da7a 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -250,6 +250,9 @@ public: Field *field; char *min_value,*max_value; // Pointer to range + /* + eq_tree() requires that left == right == 0 if the type is MAYBE_KEY. + */ SEL_ARG *left,*right; /* R-B tree children */ SEL_ARG *next,*prev; /* Links for bi-directional interval list */ SEL_ARG *parent; /* R-B tree parent */ @@ -265,7 +268,7 @@ public: SEL_ARG(Field *field, uint8 part, char *min_value, char *max_value, uint8 min_flag, uint8 max_flag, uint8 maybe_flag); SEL_ARG(enum Type type_arg) - :min_flag(0),elements(1),use_count(1),left(0),next_key_part(0), + :min_flag(0),elements(1),use_count(1),left(0),right(0),next_key_part(0), color(BLACK), type(type_arg) {} inline bool is_same(SEL_ARG *arg) -- cgit v1.2.1 From 63b65169534c97f0c225859d2d6d49f3cee2bc10 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 Nov 2007 17:16:52 +0200 Subject: Bug #30355: Incorrect ordering of UDF results There's currently no way of knowing the determinicity of an UDF. And the optimizer and the sequence() UDFs were making wrong assumptions about what the is_const member means. Plus there was no implementation of update_system_tables() causing the optimizer to overwrite the information returned by the _init function. Fixed by equating the assumptions about the semantics of is_const and providing a implementation of update_used_tables(). Added a TODO item for the UDF API change needed to make a better implementation. include/mysql_com.h: Bug #30355: comment added mysql-test/r/udf.result: Bug #30355: test case mysql-test/t/udf.test: Bug #30355: test case sql/item_func.cc: Bug #30355: keep const_item_cache and used_tables_cache in sync sql/item_func.h: Bug #30355: - a better implementation of update_used_tables() - keep const_item_cache and used_tables_cache in sync sql/udf_example.c: Bug #30355: Wrong value for const_item fixed. --- sql/item_func.cc | 6 ++++++ sql/item_func.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ sql/udf_example.c | 10 ++++------ 3 files changed, 60 insertions(+), 6 deletions(-) (limited to 'sql') diff --git a/sql/item_func.cc b/sql/item_func.cc index 264d9265bca..0309c1a17cb 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2968,6 +2968,12 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, func->max_length=min(initid.max_length,MAX_BLOB_WIDTH); func->maybe_null=initid.maybe_null; const_item_cache=initid.const_item; + /* + Keep used_tables_cache in sync with const_item_cache. + See the comment in Item_udf_func::update_used tables. + */ + if (!const_item_cache && !used_tables_cache) + used_tables_cache= RAND_TABLE_BIT; func->decimals=min(initid.decimals,NOT_FIXED_DEC); } initialized=1; diff --git a/sql/item_func.h b/sql/item_func.h index a31294c0395..734b215ddc0 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1016,6 +1016,56 @@ public: fixed= 1; return res; } + void update_used_tables() + { + /* + TODO: Make a member in UDF_INIT and return if a UDF is deterministic or + not. + Currently UDF_INIT has a member (const_item) that is an in/out + parameter to the init() call. + The code in udf_handler::fix_fields also duplicates the arguments + handling code in Item_func::fix_fields(). + + The lack of information if a UDF is deterministic makes writing + a correct update_used_tables() for UDFs impossible. + One solution to this would be : + - Add a is_deterministic member of UDF_INIT + - (optionally) deprecate the const_item member of UDF_INIT + - Take away the duplicate code from udf_handler::fix_fields() and + make Item_udf_func call Item_func::fix_fields() to process its + arguments as for any other function. + - Store the deterministic flag returned by _init into the + udf_handler. + - Don't implement Item_udf_func::fix_fields, implement + Item_udf_func::fix_length_and_dec() instead (similar to non-UDF + functions). + - Override Item_func::update_used_tables to call + Item_func::update_used_tables() and add a RAND_TABLE_BIT to the + result of Item_func::update_used_tables() if the UDF is + non-deterministic. + - (optionally) rename RAND_TABLE_BIT to NONDETERMINISTIC_BIT to + better describe its usage. + + The above would require a change of the UDF API. + Until that change is done here's how the current code works: + We call Item_func::update_used_tables() only when we know that + the function depends on real non-const tables and is deterministic. + This can be done only because we know that the optimizer will + call update_used_tables() only when there's possibly a new const + table. So update_used_tables() can only make a Item_func more + constant than it is currently. + That's why we don't need to do anything if a function is guaranteed + to return non-constant (it's non-deterministic) or is already a + const. + */ + if ((used_tables_cache & ~PSEUDO_TABLE_BITS) && + !(used_tables_cache & RAND_TABLE_BIT)) + { + Item_func::update_used_tables(); + if (!const_item_cache && !used_tables_cache) + used_tables_cache= RAND_TABLE_BIT; + } + } void cleanup(); Item_result result_type () const { return udf.result_type(); } table_map not_null_tables() const { return 0; } diff --git a/sql/udf_example.c b/sql/udf_example.c index df3a69755ad..4ca6133da03 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -648,13 +648,11 @@ my_bool sequence_init(UDF_INIT *initid, UDF_ARGS *args, char *message) return 1; } bzero(initid->ptr,sizeof(longlong)); - /* - Fool MySQL to think that this function is a constant - This will ensure that MySQL only evalutes the function - when the rows are sent to the client and not before any ORDER BY - clauses + /* + sequence() is a non-deterministic function : it has different value + even if called with the same arguments. */ - initid->const_item=1; + initid->const_item=0; return 0; } -- cgit v1.2.1 From 7c0db983ad8eb8e1d37cf8468bbfd32de87a14ad Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 Nov 2007 18:24:24 +0100 Subject: Bug#32707: misdimensioned buffer in protocol layer Miscalculation in protocol-layer: size buffer correctly so even really long error messages cannot overflow our buffer. sql/protocol.cc: size buffer correctly so really long error messages cannot overflow it. --- sql/protocol.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/protocol.cc b/sql/protocol.cc index 7c7dfaf7bef..f7a34fde94a 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -56,7 +56,10 @@ void send_error(THD *thd, uint sql_errno, const char *err) { #ifndef EMBEDDED_LIBRARY uint length; - char buff[MYSQL_ERRMSG_SIZE+2], *pos; + /* + buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + MYSQL_ERRMSG_SIZE:512 + */ + char buff[2+1+SQLSTATE_LENGTH+MYSQL_ERRMSG_SIZE], *pos; #endif const char *orig_err= err; NET *net= &thd->net; -- cgit v1.2.1 From b5c0cf454dd20f3512d74984c7fc1b77c2e7b737 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 Nov 2007 03:02:05 +0300 Subject: BUG#32772: partition crash 1: enum column The bug was that for ordered index scans, ha_partition::index_init() did not put index columns into table->read_set if the underlying storage engine did not have HA_PARTIAL_COLUMN_READ flag. This was causing assertion failure when handle_ordered_index_scan() tried to sort the records according to index order. Fixed by making ha_partition::index_init() put index columns into table->read_set for all ordered scans. mysql-test/r/partition.result: BUG#32772: partition crash 1: enum column - Testcase mysql-test/t/partition.test: BUG#32772: partition crash 1: enum column - Testcase sql/ha_partition.cc: BUG#32772: partition crash 1: enum column - Make ha_partition::index_init() include index columns in the read_set whenever an ordered scan is initialized, no matter if HA_PARTIAL_COLUMN_READ is set or not. --- sql/ha_partition.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'sql') diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 423415ce4ae..7234222b79f 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3413,14 +3413,17 @@ int ha_partition::index_init(uint inx, bool sorted) */ if (m_lock_type == F_WRLCK) bitmap_union(table->read_set, &m_part_info->full_part_field_set); - else if (sorted && m_table_flags & HA_PARTIAL_COLUMN_READ) + else if (sorted) { /* - An ordered scan is requested and necessary fields aren't in read_set. - This may happen e.g. with SELECT COUNT(*) FROM t1. We must ensure - that all fields of current key are included into read_set, as - partitioning requires them for sorting - (see ha_partition::handle_ordered_index_scan). + An ordered scan is requested. We must make sure all fields of the + used index are in the read set, as partitioning requires them for + sorting (see ha_partition::handle_ordered_index_scan). + + The SQL layer may request an ordered index scan without having index + fields in the read set when + - it needs to do an ordered scan over an index prefix. + - it evaluates ORDER BY with SELECT COUNT(*) FROM t1. TODO: handle COUNT(*) queries via unordered scan. */ -- cgit v1.2.1 From b9d8e34925d1be4b6c1c8950217d41456a02c542 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 Nov 2007 15:37:00 +0400 Subject: Bug#25629 CREATE TABLE LIKE does not work with INFORMATION_SCHEMA added new func mysql_create_like_schema_frm() which creates frm file based on I_S table mysql-test/r/create.result: test result mysql-test/t/create.test: test case sql/sql_table.cc: added new func mysql_create_like_schema_frm() which creates frm file based on I_S table --- sql/sql_table.cc | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 75c97d8edd4..f179d8bea1e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4565,6 +4565,55 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables) } + +/** + @brief Create frm file based on I_S table + + @param[in] thd thread handler + @param[in] schema_table I_S table + @param[in] dst_path path where frm should be created + @param[in] create_info Create info + + @return Operation status + @retval 0 success + @retval 1 error +*/ + + +bool mysql_create_like_schema_frm(THD* thd, TABLE_LIST* schema_table, + char *dst_path, HA_CREATE_INFO *create_info) +{ + HA_CREATE_INFO local_create_info; + Alter_info alter_info; + bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE); + uint keys= schema_table->table->s->keys; + uint db_options= 0; + DBUG_ENTER("mysql_create_like_schema_frm"); + + bzero((char*) &local_create_info, sizeof(local_create_info)); + local_create_info.db_type= schema_table->table->s->db_type(); + local_create_info.row_type= schema_table->table->s->row_type; + local_create_info.default_table_charset=default_charset_info; + alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE); + schema_table->table->use_all_columns(); + if (mysql_prepare_alter_table(thd, schema_table->table, + &local_create_info, &alter_info)) + DBUG_RETURN(1); + if (mysql_prepare_create_table(thd, &local_create_info, &alter_info, + tmp_table, &db_options, + schema_table->table->file, + &schema_table->table->s->key_info, &keys, 0)) + DBUG_RETURN(1); + local_create_info.max_rows= 0; + if (mysql_create_frm(thd, dst_path, NullS, NullS, + &local_create_info, alter_info.create_list, + keys, schema_table->table->s->key_info, + schema_table->table->file)) + DBUG_RETURN(1); + DBUG_RETURN(0); +} + + /* Create a table identical to the specified table @@ -4668,7 +4717,15 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, during the call to ha_create_table(). See bug #28614 for more info. */ VOID(pthread_mutex_lock(&LOCK_open)); - if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE))) + if (src_table->schema_table) + { + if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info)) + { + VOID(pthread_mutex_unlock(&LOCK_open)); + goto err; + } + } + else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE))) { if (my_errno == ENOENT) my_error(ER_BAD_DB_ERROR,MYF(0),db); -- cgit v1.2.1 From 1d062682f5098ea5c30b9b3fef844195790a095e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 29 Nov 2007 10:37:07 +0400 Subject: Bug #32624 Error with multi queries in MySQL embedded server 5.1.22. server status wasn't properly sent to the client after the error by the embedded server. Wasn't noticed before as one usually stopped retrieving results after he gets an error. libmysqld/lib_sql.cc: Bug #32624 Error with multi queries in MySQL embedded server 5.1.22. server status transferred to the client after errors sql/protocol.cc: Bug #32624 Error with multi queries in MySQL embedded server 5.1.22. set server status before net_send_error_packet() call as this function sends it to the client in the embedded server tests/mysql_client_test.c: Bug #32624 Error with multi queries in MySQL embedded server 5.1.22. testcase added --- sql/protocol.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/protocol.cc b/sql/protocol.cc index 2bdbe83eea1..ac562a9f5ab 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -110,13 +110,14 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, sql_errno, err); } + /* Abort multi-result sets */ + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; + net_send_error_packet(thd, sql_errno, err); thd->is_fatal_error=0; // Error message is given thd->net.report_error= 0; - /* Abort multi-result sets */ - thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; DBUG_VOID_RETURN; } -- cgit v1.2.1 From 23e402bf4595c6310bef2d7e6a3bcfefb4cb8173 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 29 Nov 2007 14:52:36 +0400 Subject: Bug #29085 A small double precision number becomes zero. Denormalized DOUBLE-s can't be properly handled by old MIPS processors. So we need to enable specific mode for them so IRIX will do use software round to handle such numbers. sql/mysqld.cc: Bug #29085 A small double precision number becomes zero. reset_floating_point_exeption() renamed as set_proper_floating_point_mode() #ifdef __sgi code added to enable denormalized DOUBLE-s on IRIX --- sql/mysqld.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 51332053df6..62105e0093a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -193,7 +193,7 @@ typedef fp_except fp_except_t; this on freebsd */ -inline void reset_floating_point_exceptions() +inline void set_proper_floating_point_mode() { /* Don't fall for overflow, underflow,divide-by-zero or loss of precision */ #if defined(__i386__) @@ -204,8 +204,22 @@ inline void reset_floating_point_exceptions() FP_X_IMP)); #endif } +#elif defined(__sgi) +/* for IRIX to use set_fpc_csr() */ +#include + +inline void set_proper_floating_point_mode() +{ + /* Enable denormalized DOUBLE values support for IRIX */ + { + union fpc_csr n; + n.fc_word = get_fpc_csr(); + n.fc_struct.flush = 0; + set_fpc_csr(n.fc_word); + } +} #else -#define reset_floating_point_exceptions() +#define set_proper_floating_point_mode() #endif /* __FreeBSD__ && HAVE_IEEEFP_H */ } /* cplusplus */ @@ -2876,7 +2890,7 @@ static int init_server_components() query_cache_init(); query_cache_resize(query_cache_size); randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2); - reset_floating_point_exceptions(); + set_proper_floating_point_mode(); init_thr_lock(); #ifdef HAVE_REPLICATION init_slave_list(); -- cgit v1.2.1 From 89a208850a714d5653207cffa2d654e86063a7e7 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 Nov 2007 06:32:04 +0100 Subject: Bug#31177: Server variables can't be set to their current values Default values of variables were not subject to upper/lower bounds and step, while setting variables was. Bounds and step are also applied to defaults now; defaults are corrected quietly, values given by the user are corrected, and a correction-warning is thrown as needed. Lastly, very large values could wrap around, starting from 0 again. They are bounded at the maximum value for the respective data-type now if no lower maximum is specified in the variable's definition. client/mysql.cc: correct maxima in options array client/mysqltest.c: adjust minimum for "sleep" option so default value is no longer out of bounds. include/m_string.h: ullstr() - the unsigned brother of llstr() include/my_getopt.h: Flag if we bounded the value (that is, correct anything aside from making value a multiple of block-size) mysql-test/r/delayed.result: We throw a warning now when we adjust out of range parameters. mysql-test/r/index_merge.result: We throw a warning now when we adjust out of range parameters. mysql-test/r/innodb.result: We throw a warning now when we adjust out of range parameters. mysql-test/r/innodb_mysql.result: We throw a warning now when we adjust out of range parameters. mysql-test/r/key_cache.result: We throw a warning now when we adjust out of range parameters. mysql-test/r/packet.result: We throw a warning now when we adjust out of range parameters. mysql-test/r/ps.result: We throw a warning now when we adjust out of range parameters. mysql-test/r/subselect.result: We throw a warning now when we adjust out of range parameters. mysql-test/r/type_bit.result: We throw a warning now when we adjust out of range parameters. mysql-test/r/type_bit_innodb.result: We throw a warning now when we adjust out of range parameters. mysql-test/r/variables.result: correct results: bounds and step apply to variables' default values, too mysql-test/t/variables.test: correct results: bounds and step apply to variables' default values, too mysys/my_getopt.c: - apply bounds/step to default values of variables (based on work by serg) - print complaints about incorrect values for variables (truncation etc., by requestion of consulting) - if no lower maximum is specified in variable definition, bound unsigned values at their maximum to prevent wrap-around - some calls to error_reporter had a \n, some didn't. remove \n from calls, let reporter-function handle it, so the default reporter behaves like that in mysqld sql/mysql_priv.h: correct RANGE_ALLOC_BLOCK_SIZE (cleared with monty) sql/mysqld.cc: correct maxima to correct data-type. correct minima where higher than default. correct range-alloc-block-size. correct inno variables so GET_* corresponds to actual variable's type. sql/set_var.cc: When the new value for a variable is out of bounds, we'll send the client a warning (but not if the value was simply not a multiple of 'blocksize'). sys_var_thd_ulong had this, sys_var_long_ptr_global didn't; broken out and streamlined to avoid duplication of code. strings/llstr.c: ullstr() - the unsigned brother of llstr() --- sql/mysql_priv.h | 2 +- sql/mysqld.cc | 80 +++++++++++++++++++++++++++++--------------------------- sql/set_var.cc | 70 +++++++++++++++++++++++++++++++++---------------- 3 files changed, 90 insertions(+), 62 deletions(-) (limited to 'sql') diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 47396748da6..4334dedfe4e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -186,7 +186,7 @@ MY_LOCALE *my_locale_by_number(uint number); #define QUERY_ALLOC_PREALLOC_SIZE 8192 #define TRANS_ALLOC_BLOCK_SIZE 4096 #define TRANS_ALLOC_PREALLOC_SIZE 4096 -#define RANGE_ALLOC_BLOCK_SIZE 2048 +#define RANGE_ALLOC_BLOCK_SIZE 4096 #define ACL_ALLOC_BLOCK_SIZE 1024 #define UDF_ALLOC_BLOCK_SIZE 1024 #define TABLE_ALLOC_BLOCK_SIZE 1024 diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4c459d34a55..3900f74da7e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4958,7 +4958,7 @@ Disable with --skip-bdb (will save memory).", {"concurrent-insert", OPT_CONCURRENT_INSERT, "Use concurrent insert with MyISAM. Disable with --concurrent-insert=0", (gptr*) &myisam_concurrent_insert, (gptr*) &myisam_concurrent_insert, - 0, GET_LONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, + 0, GET_ULONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, {"console", OPT_CONSOLE, "Write error output on screen; Don't remove the console window on windows.", (gptr*) &opt_console, (gptr*) &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -5127,7 +5127,7 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite, {"innodb_max_purge_lag", OPT_INNODB_MAX_PURGE_LAG, "Desired maximum length of the purge queue (0 = no limit)", (gptr*) &srv_max_purge_lag, - (gptr*) &srv_max_purge_lag, 0, GET_LONG, REQUIRED_ARG, 0, 0, ~0L, + (gptr*) &srv_max_purge_lag, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1L, 0}, {"innodb_rollback_on_timeout", OPT_INNODB_ROLLBACK_ON_TIMEOUT, "Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)", @@ -5237,7 +5237,8 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite, #ifdef HAVE_MMAP {"log-tc-size", OPT_LOG_TC_SIZE, "Size of transaction coordinator log.", (gptr*) &opt_tc_log_size, (gptr*) &opt_tc_log_size, 0, GET_ULONG, - REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ~0L, 0, TC_LOG_PAGE_SIZE, 0}, + REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ULONG_MAX, 0, + TC_LOG_PAGE_SIZE, 0}, #endif {"log-update", OPT_UPDATE_LOG, "The update log is deprecated since version 5.0, is replaced by the binary \ @@ -5660,8 +5661,8 @@ log and this option does nothing anymore.", NO_ARG, 0, 0, 0, 0, 0, 0}, {"warnings", 'W', "Deprecated; use --log-warnings instead.", (gptr*) &global_system_variables.log_warnings, - (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, ~0L, - 0, 0, 0}, + (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, + 1, 0, ULONG_MAX, 0, 0, 0}, { "back_log", OPT_BACK_LOG, "The number of outstanding connection requests MySQL can have. This comes into play when the main MySQL thread gets very many connection requests in a very short time.", (gptr*) &back_log, (gptr*) &back_log, 0, GET_ULONG, @@ -5670,29 +5671,29 @@ log and this option does nothing anymore.", { "bdb_cache_size", OPT_BDB_CACHE_SIZE, "The buffer that is allocated to cache index and rows for BDB tables.", (gptr*) &berkeley_cache_size, (gptr*) &berkeley_cache_size, 0, GET_ULONG, - REQUIRED_ARG, KEY_CACHE_SIZE, 20*1024, (long) ~0, 0, IO_SIZE, 0}, + REQUIRED_ARG, KEY_CACHE_SIZE, 20*1024, ULONG_MAX, 0, IO_SIZE, 0}, /* QQ: The following should be removed soon! (bdb_max_lock preferred) */ {"bdb_lock_max", OPT_BDB_MAX_LOCK, "Synonym for bdb_max_lock.", (gptr*) &berkeley_max_lock, (gptr*) &berkeley_max_lock, 0, GET_ULONG, - REQUIRED_ARG, 10000, 0, (long) ~0, 0, 1, 0}, + REQUIRED_ARG, 10000, 0, ULONG_MAX, 0, 1, 0}, {"bdb_log_buffer_size", OPT_BDB_LOG_BUFFER_SIZE, "The buffer that is allocated to cache index and rows for BDB tables.", (gptr*) &berkeley_log_buffer_size, (gptr*) &berkeley_log_buffer_size, 0, - GET_ULONG, REQUIRED_ARG, 0, 256*1024L, ~0L, 0, 1024, 0}, + GET_ULONG, REQUIRED_ARG, 0, 256*1024L, ULONG_MAX, 0, 1024, 0}, {"bdb_max_lock", OPT_BDB_MAX_LOCK, "The maximum number of locks you can have active on a BDB table.", (gptr*) &berkeley_max_lock, (gptr*) &berkeley_max_lock, 0, GET_ULONG, - REQUIRED_ARG, 10000, 0, (long) ~0, 0, 1, 0}, + REQUIRED_ARG, 10000, 0, ULONG_MAX, 0, 1, 0}, #endif /* HAVE_BERKELEY_DB */ {"binlog_cache_size", OPT_BINLOG_CACHE_SIZE, "The size of the cache to hold the SQL statements for the binary log during a transaction. If you often use big, multi-statement transactions you can increase this to get more performance.", (gptr*) &binlog_cache_size, (gptr*) &binlog_cache_size, 0, GET_ULONG, - REQUIRED_ARG, 32*1024L, IO_SIZE, ~0L, 0, IO_SIZE, 0}, + REQUIRED_ARG, 32*1024L, IO_SIZE, ULONG_MAX, 0, IO_SIZE, 0}, {"bulk_insert_buffer_size", OPT_BULK_INSERT_BUFFER_SIZE, "Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread!", (gptr*) &global_system_variables.bulk_insert_buff_size, (gptr*) &max_system_variables.bulk_insert_buff_size, - 0, GET_ULONG, REQUIRED_ARG, 8192*1024, 0, ~0L, 0, 1, 0}, + 0, GET_ULONG, REQUIRED_ARG, 8192*1024, 0, ULONG_MAX, 0, 1, 0}, {"connect_timeout", OPT_CONNECT_TIMEOUT, "The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake'.", (gptr*) &connect_timeout, (gptr*) &connect_timeout, @@ -5715,7 +5716,7 @@ log and this option does nothing anymore.", {"delayed_insert_limit", OPT_DELAYED_INSERT_LIMIT, "After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing.", (gptr*) &delayed_insert_limit, (gptr*) &delayed_insert_limit, 0, GET_ULONG, - REQUIRED_ARG, DELAYED_LIMIT, 1, ~0L, 0, 1, 0}, + REQUIRED_ARG, DELAYED_LIMIT, 1, ULONG_MAX, 0, 1, 0}, {"delayed_insert_timeout", OPT_DELAYED_INSERT_TIMEOUT, "How long a INSERT DELAYED thread should wait for INSERT statements before terminating.", (gptr*) &delayed_insert_timeout, (gptr*) &delayed_insert_timeout, 0, @@ -5723,7 +5724,7 @@ log and this option does nothing anymore.", { "delayed_queue_size", OPT_DELAYED_QUEUE_SIZE, "What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again.", (gptr*) &delayed_queue_size, (gptr*) &delayed_queue_size, 0, GET_ULONG, - REQUIRED_ARG, DELAYED_QUEUE_SIZE, 1, ~0L, 0, 1, 0}, + REQUIRED_ARG, DELAYED_QUEUE_SIZE, 1, ULONG_MAX, 0, 1, 0}, {"div_precision_increment", OPT_DIV_PRECINCREMENT, "Precision of the result of '/' operator will be increased on that value.", (gptr*) &global_system_variables.div_precincrement, @@ -5760,16 +5761,16 @@ log and this option does nothing anymore.", (gptr*) &ft_stopword_file, (gptr*) &ft_stopword_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { "group_concat_max_len", OPT_GROUP_CONCAT_MAX_LEN, - "The maximum length of the result of function group_concat.", + "The maximum length of the result of function group_concat.", (gptr*) &global_system_variables.group_concat_max_len, (gptr*) &max_system_variables.group_concat_max_len, 0, GET_ULONG, - REQUIRED_ARG, 1024, 4, (long) ~0, 0, 1, 0}, + REQUIRED_ARG, 1024, 4, ULONG_MAX, 0, 1, 0}, #ifdef HAVE_INNOBASE_DB {"innodb_additional_mem_pool_size", OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE, "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.", (gptr*) &innobase_additional_mem_pool_size, (gptr*) &innobase_additional_mem_pool_size, 0, GET_LONG, REQUIRED_ARG, - 1*1024*1024L, 512*1024L, ~0L, 0, 1024, 0}, + 1*1024*1024L, 512*1024L, LONG_MAX, 0, 1024, 0}, {"innodb_autoextend_increment", OPT_INNODB_AUTOEXTEND_INCREMENT, "Data file autoextend increment in megabytes", (gptr*) &srv_auto_extend_increment, @@ -5793,7 +5794,7 @@ log and this option does nothing anymore.", SQL query after it has once got the ticket", (gptr*) &srv_n_free_tickets_to_enter, (gptr*) &srv_n_free_tickets_to_enter, - 0, GET_LONG, REQUIRED_ARG, 500L, 1L, ~0L, 0, 1L, 0}, + 0, GET_ULONG, REQUIRED_ARG, 500L, 1L, ULONG_MAX, 0, 1L, 0}, {"innodb_file_io_threads", OPT_INNODB_FILE_IO_THREADS, "Number of file I/O threads in InnoDB.", (gptr*) &innobase_file_io_threads, (gptr*) &innobase_file_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 4, 64, 0, @@ -5809,7 +5810,7 @@ log and this option does nothing anymore.", {"innodb_log_buffer_size", OPT_INNODB_LOG_BUFFER_SIZE, "The size of the buffer which InnoDB uses to write log to the log files on disk.", (gptr*) &innobase_log_buffer_size, (gptr*) &innobase_log_buffer_size, 0, - GET_LONG, REQUIRED_ARG, 1024*1024L, 256*1024L, ~0L, 0, 1024, 0}, + GET_LONG, REQUIRED_ARG, 1024*1024L, 256*1024L, LONG_MAX, 0, 1024, 0}, {"innodb_log_file_size", OPT_INNODB_LOG_FILE_SIZE, "Size of each log file in a log group.", (gptr*) &innobase_log_file_size, (gptr*) &innobase_log_file_size, 0, @@ -5827,24 +5828,24 @@ log and this option does nothing anymore.", {"innodb_open_files", OPT_INNODB_OPEN_FILES, "How many files at the maximum InnoDB keeps open at the same time.", (gptr*) &innobase_open_files, (gptr*) &innobase_open_files, 0, - GET_LONG, REQUIRED_ARG, 300L, 10L, ~0L, 0, 1L, 0}, + GET_LONG, REQUIRED_ARG, 300L, 10L, LONG_MAX, 0, 1L, 0}, {"innodb_sync_spin_loops", OPT_INNODB_SYNC_SPIN_LOOPS, "Count of spin-loop rounds in InnoDB mutexes", (gptr*) &srv_n_spin_wait_rounds, (gptr*) &srv_n_spin_wait_rounds, - 0, GET_LONG, REQUIRED_ARG, 20L, 0L, ~0L, 0, 1L, 0}, + 0, GET_ULONG, REQUIRED_ARG, 20L, 0L, ULONG_MAX, 0, 1L, 0}, {"innodb_thread_concurrency", OPT_INNODB_THREAD_CONCURRENCY, "Helps in performance tuning in heavily concurrent environments. " "Sets the maximum number of threads allowed inside InnoDB. Value 0" " will disable the thread throttling.", (gptr*) &srv_thread_concurrency, (gptr*) &srv_thread_concurrency, - 0, GET_LONG, REQUIRED_ARG, 8, 0, 1000, 0, 1, 0}, + 0, GET_ULONG, REQUIRED_ARG, 8, 0, 1000, 0, 1, 0}, {"innodb_thread_sleep_delay", OPT_INNODB_THREAD_SLEEP_DELAY, "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0" " disable a sleep", (gptr*) &srv_thread_sleep_delay, (gptr*) &srv_thread_sleep_delay, - 0, GET_LONG, REQUIRED_ARG, 10000L, 0L, ~0L, 0, 1L, 0}, + 0, GET_ULONG, REQUIRED_ARG, 10000L, 0L, ULONG_MAX, 0, 1L, 0}, #endif /* HAVE_INNOBASE_DB */ {"interactive_timeout", OPT_INTERACTIVE_TIMEOUT, "The number of seconds the server waits for activity on an interactive connection before closing it.", @@ -5874,7 +5875,7 @@ log and this option does nothing anymore.", (gptr*) &dflt_key_cache_var.param_age_threshold, (gptr*) 0, 0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, - 300, 100, ~0L, 0, 100, 0}, + 300, 100, ULONG_MAX, 0, 100, 0}, {"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, "The default size of key cache blocks", (gptr*) &dflt_key_cache_var.param_block_size, @@ -5910,7 +5911,7 @@ log and this option does nothing anymore.", {"max_binlog_cache_size", OPT_MAX_BINLOG_CACHE_SIZE, "Can be used to restrict the total size used to cache a multi-transaction query.", (gptr*) &max_binlog_cache_size, (gptr*) &max_binlog_cache_size, 0, - GET_ULONG, REQUIRED_ARG, ~0L, IO_SIZE, ~0L, 0, IO_SIZE, 0}, + GET_ULONG, REQUIRED_ARG, ULONG_MAX, IO_SIZE, ULONG_MAX, 0, IO_SIZE, 0}, {"max_binlog_size", OPT_MAX_BINLOG_SIZE, "Binary log will be rotated automatically when the size exceeds this \ value. Will also apply to relay logs if max_relay_log_size is 0. \ @@ -5920,7 +5921,7 @@ The minimum value for this variable is 4096.", {"max_connect_errors", OPT_MAX_CONNECT_ERRORS, "If there is more than this number of interrupted connections from a host this host will be blocked from further connections.", (gptr*) &max_connect_errors, (gptr*) &max_connect_errors, 0, GET_ULONG, - REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ~0L, 0, 1, 0}, + REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ULONG_MAX, 0, 1, 0}, {"max_connections", OPT_MAX_CONNECTIONS, "The number of simultaneous clients allowed.", (gptr*) &max_connections, (gptr*) &max_connections, 0, GET_ULONG, REQUIRED_ARG, 100, 1, 16384, 0, 1, @@ -5963,7 +5964,7 @@ The minimum value for this variable is 4096.", "Limit assumed max number of seeks when looking up rows based on a key", (gptr*) &global_system_variables.max_seeks_for_key, (gptr*) &max_system_variables.max_seeks_for_key, 0, GET_ULONG, - REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0 }, + REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0 }, {"max_sort_length", OPT_MAX_SORT_LENGTH, "The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored).", (gptr*) &global_system_variables.max_sort_length, @@ -5978,20 +5979,20 @@ The minimum value for this variable is 4096.", "Maximum number of temporary tables a client can keep open at a time.", (gptr*) &global_system_variables.max_tmp_tables, (gptr*) &max_system_variables.max_tmp_tables, 0, GET_ULONG, - REQUIRED_ARG, 32, 1, ~0L, 0, 1, 0}, + REQUIRED_ARG, 32, 1, ULONG_MAX, 0, 1, 0}, {"max_user_connections", OPT_MAX_USER_CONNECTIONS, "The maximum number of active connections for a single user (0 = no limit).", (gptr*) &max_user_connections, (gptr*) &max_user_connections, 0, GET_UINT, - REQUIRED_ARG, 0, 1, ~0, 0, 1, 0}, + REQUIRED_ARG, 0, 0, (uint) ~0, 0, 1, 0}, {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT, "After this many write locks, allow some read locks to run in between.", (gptr*) &max_write_lock_count, (gptr*) &max_write_lock_count, 0, GET_ULONG, - REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0}, + REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0}, {"multi_range_count", OPT_MULTI_RANGE_COUNT, "Number of key ranges to request at once.", (gptr*) &global_system_variables.multi_range_count, (gptr*) &max_system_variables.multi_range_count, 0, - GET_ULONG, REQUIRED_ARG, 256, 1, ~0L, 0, 1, 0}, + GET_ULONG, REQUIRED_ARG, 256, 1, ULONG_MAX, 0, 1, 0}, {"myisam_block_size", OPT_MYISAM_BLOCK_SIZE, "Block size to be used for MyISAM index pages.", (gptr*) &opt_myisam_block_size, @@ -6019,7 +6020,7 @@ The minimum value for this variable is 4096.", "Number of threads to use when repairing MyISAM tables. The value of 1 disables parallel repair.", (gptr*) &global_system_variables.myisam_repair_threads, (gptr*) &max_system_variables.myisam_repair_threads, 0, - GET_ULONG, REQUIRED_ARG, 1, 1, ~0L, 0, 1, 0}, + GET_ULONG, REQUIRED_ARG, 1, 1, ULONG_MAX, 0, 1, 0}, {"myisam_sort_buffer_size", OPT_MYISAM_SORT_BUFFER_SIZE, "The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.", (gptr*) &global_system_variables.myisam_sort_buff_size, @@ -6045,7 +6046,7 @@ The minimum value for this variable is 4096.", "If a read on a communication port is interrupted, retry this many times before giving up.", (gptr*) &global_system_variables.net_retry_count, (gptr*) &max_system_variables.net_retry_count,0, - GET_ULONG, REQUIRED_ARG, MYSQLD_NET_RETRY_COUNT, 1, ~0L, 0, 1, 0}, + GET_ULONG, REQUIRED_ARG, MYSQLD_NET_RETRY_COUNT, 1, ULONG_MAX, 0, 1, 0}, {"net_write_timeout", OPT_NET_WRITE_TIMEOUT, "Number of seconds to wait for a block to be written to a connection before aborting the write.", (gptr*) &global_system_variables.net_write_timeout, @@ -6074,7 +6075,7 @@ The minimum value for this variable is 4096.", "Allocation block size for query parsing and execution", (gptr*) &global_system_variables.query_alloc_block_size, (gptr*) &max_system_variables.query_alloc_block_size, 0, GET_ULONG, - REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0}, + REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0}, #ifdef HAVE_QUERY_CACHE {"query_cache_limit", OPT_QUERY_CACHE_LIMIT, "Don't cache results that are bigger than this.", @@ -6107,12 +6108,13 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.query_prealloc_size, (gptr*) &max_system_variables.query_prealloc_size, 0, GET_ULONG, REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, QUERY_ALLOC_PREALLOC_SIZE, - ~0L, 0, 1024, 0}, + ULONG_MAX, 0, 1024, 0}, {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE, "Allocation block size for storing ranges during optimization", (gptr*) &global_system_variables.range_alloc_block_size, (gptr*) &max_system_variables.range_alloc_block_size, 0, GET_ULONG, - REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 4096, ~0L, 0, 1024, 0}, + REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, RANGE_ALLOC_BLOCK_SIZE, ULONG_MAX, + 0, 1024, 0}, {"read_buffer_size", OPT_RECORD_BUFFER, "Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.", (gptr*) &global_system_variables.read_buff_size, @@ -6182,7 +6184,7 @@ The minimum value for this variable is 4096.", "Synchronously flush binary log to disk after every #th event. " "Use 0 (default) to disable synchronous flushing.", (gptr*) &sync_binlog_period, (gptr*) &sync_binlog_period, 0, GET_ULONG, - REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0}, + REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1, 0}, {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default.", (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, @@ -6206,7 +6208,7 @@ The minimum value for this variable is 4096.", {"thread_stack", OPT_THREAD_STACK, "The stack size for each thread.", (gptr*) &thread_stack, (gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, - 1024L*128L, ~0L, 0, 1024, 0}, + 1024L*128L, ULONG_MAX, 0, 1024, 0}, { "time_format", OPT_TIME_FORMAT, "The TIME format (for future).", (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME], @@ -6222,12 +6224,12 @@ The minimum value for this variable is 4096.", "Allocation block size for various transaction-related structures", (gptr*) &global_system_variables.trans_alloc_block_size, (gptr*) &max_system_variables.trans_alloc_block_size, 0, GET_ULONG, - REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0}, + REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0}, {"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE, "Persistent buffer for various transaction-related structures", (gptr*) &global_system_variables.trans_prealloc_size, (gptr*) &max_system_variables.trans_prealloc_size, 0, GET_ULONG, - REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0}, + REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ULONG_MAX, 0, 1024, 0}, {"updatable_views_with_limit", OPT_UPDATABLE_VIEWS_WITH_LIMIT, "1 = YES = Don't issue an error message (warning only) if a VIEW without presence of a key of the underlying table is used in queries with a LIMIT clause for updating. 0 = NO = Prohibit update of a VIEW, which does not contain a key of the underlying table and the query uses a LIMIT clause (usually get from GUI tools).", (gptr*) &global_system_variables.updatable_views_with_limit, diff --git a/sql/set_var.cc b/sql/set_var.cc index 066b879fa6b..84b3f92c1ca 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -113,6 +113,9 @@ static int check_max_delayed_threads(THD *thd, set_var *var); static void fix_thd_mem_root(THD *thd, enum_var_type type); static void fix_trans_mem_root(THD *thd, enum_var_type type); static void fix_server_id(THD *thd, enum_var_type type); +static ulonglong fix_unsigned(THD *thd, ulonglong num, + const struct my_option *option_limits); +static void throw_bounds_warning(THD *thd, const char *name, ulonglong num); static KEY_CACHE *create_key_cache(const char *name, uint length); void fix_sql_mode_var(THD *thd, enum_var_type type); static byte *get_error_count(THD *thd); @@ -1448,6 +1451,27 @@ static void fix_server_id(THD *thd, enum_var_type type) } +static void throw_bounds_warning(THD *thd, const char *name, ulonglong num) +{ + char buf[22]; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), name, + ullstr(num, buf)); +} + +static ulonglong fix_unsigned(THD *thd, ulonglong num, + const struct my_option *option_limits) +{ + bool fixed= FALSE; + ulonglong out= getopt_ull_limit_value(num, option_limits, &fixed); + + if (fixed) + throw_bounds_warning(thd, option_limits->name, num); + return out; +} + + sys_var_long_ptr:: sys_var_long_ptr(const char *name_arg, ulong *value_ptr_arg, sys_after_update_func after_update_arg) @@ -1468,9 +1492,20 @@ bool sys_var_long_ptr_global::update(THD *thd, set_var *var) ulonglong tmp= var->save_result.ulonglong_value; pthread_mutex_lock(guard); if (option_limits) - *value= (ulong) getopt_ull_limit_value(tmp, option_limits); + *value= (ulong) fix_unsigned(thd, tmp, option_limits); else + { +#if SIZEOF_LONG < SIZEOF_LONG_LONG + /* Avoid overflows on 32 bit systems */ + if (tmp > (ulonglong) ~(ulong) 0) + { + tmp= ((ulonglong) ~(ulong) 0); + throw_bounds_warning(thd, name, var->save_result.ulonglong_value); + } +#endif *value= (ulong) tmp; + } + pthread_mutex_unlock(guard); return 0; } @@ -1489,7 +1524,7 @@ bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var) ulonglong tmp= var->save_result.ulonglong_value; pthread_mutex_lock(&LOCK_global_system_variables); if (option_limits) - *value= (ulonglong) getopt_ull_limit_value(tmp, option_limits); + *value= (ulonglong) fix_unsigned(thd, tmp, option_limits); else *value= (ulonglong) tmp; pthread_mutex_unlock(&LOCK_global_system_variables); @@ -1539,38 +1574,29 @@ bool sys_var_thd_ulong::check(THD *thd, set_var *var) bool sys_var_thd_ulong::update(THD *thd, set_var *var) { ulonglong tmp= var->save_result.ulonglong_value; - char buf[22]; - bool truncated= false; /* Don't use bigger value than given with --maximum-variable-name=.. */ if ((ulong) tmp > max_system_variables.*offset) { - truncated= true; - llstr(tmp, buf); + throw_bounds_warning(thd, name, tmp); tmp= max_system_variables.*offset; } -#if SIZEOF_LONG == 4 - /* Avoid overflows on 32 bit systems */ - if (tmp > (ulonglong) ~(ulong) 0) + if (option_limits) + tmp= (ulong) fix_unsigned(thd, tmp, option_limits); +#if SIZEOF_LONG < SIZEOF_LONG_LONG + else if (tmp > (ulonglong) ~(ulong) 0) { - truncated= true; - llstr(tmp, buf); tmp= ((ulonglong) ~(ulong) 0); + throw_bounds_warning(thd, name, var->save_result.ulonglong_value); } #endif - if (truncated) - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_TRUNCATED_WRONG_VALUE, - ER(ER_TRUNCATED_WRONG_VALUE), name, - buf); - if (option_limits) - tmp= (ulong) getopt_ull_limit_value(tmp, option_limits); if (var->type == OPT_GLOBAL) global_system_variables.*offset= (ulong) tmp; else thd->variables.*offset= (ulong) tmp; + return 0; } @@ -1605,7 +1631,7 @@ bool sys_var_thd_ha_rows::update(THD *thd, set_var *var) tmp= max_system_variables.*offset; if (option_limits) - tmp= (ha_rows) getopt_ull_limit_value(tmp, option_limits); + tmp= (ha_rows) fix_unsigned(thd, tmp, option_limits); if (var->type == OPT_GLOBAL) { /* Lock is needed to make things safe on 32 bit systems */ @@ -1649,7 +1675,7 @@ bool sys_var_thd_ulonglong::update(THD *thd, set_var *var) tmp= max_system_variables.*offset; if (option_limits) - tmp= getopt_ull_limit_value(tmp, option_limits); + tmp= fix_unsigned(thd, tmp, option_limits); if (var->type == OPT_GLOBAL) { /* Lock is needed to make things safe on 32 bit systems */ @@ -2493,7 +2519,7 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) } key_cache->param_buff_size= - (ulonglong) getopt_ull_limit_value(tmp, option_limits); + (ulonglong) fix_unsigned(thd, tmp, option_limits); /* If key cache didn't existed initialize it, else resize it */ key_cache->in_init= 1; @@ -2541,7 +2567,7 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var) goto end; *((ulong*) (((char*) key_cache) + offset))= - (ulong) getopt_ull_limit_value(tmp, option_limits); + (ulong) fix_unsigned(thd, tmp, option_limits); /* Don't create a new key cache if it didn't exist -- cgit v1.2.1 From cef31e05e58b43ec4f7c02569432df70c60969f5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 Nov 2007 17:08:00 +0400 Subject: Bug #32374 crash with filesort when selecting from federated table and view. filesort() uses file->estimate_rows_upper_bound() call to allocate internal buffers. If this function returns a value smaller than a number of row that will be returned later in find_all_keys(), that can cause server crash. Fixed by implementing ha_federated::estimate_rows_upper_bound() to return maximum possible number of rows. Present estimation for FEDERATED always returns 0 if the linked to the VIEW. mysql-test/r/federated.result: Bug #32374 crash with filesort when selecting from federated table and view. test result mysql-test/t/federated.test: Bug #32374 crash with filesort when selecting from federated table and view. test case sql/ha_federated.cc: Bug #32374 crash with filesort when selecting from federated table and view. ha_federated::estimate_rows_upper_bound() implemented sql/ha_federated.h: Bug #32374 crash with filesort when selecting from federated table and view. ha_federated::estimate_rows_upper_bound() interface --- sql/ha_federated.cc | 18 ++++++++++++++++++ sql/ha_federated.h | 1 + 2 files changed, 19 insertions(+) (limited to 'sql') diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index d7f2309657b..ac1e0962ffb 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -2166,6 +2166,24 @@ error: } +/* + This method is used exlusevely by filesort() to check if we + can create sorting buffers of necessary size. + If the handler returns more records that it declares + here server can just crash on filesort(). + We cannot guarantee that's not going to happen with + the FEDERATED engine, as we have records==0 always if the + client is a VIEW, and for the table the number of + records can inpredictably change during execution. + So we return maximum possible value here. +*/ + +ha_rows ha_federated::estimate_rows_upper_bound() +{ + return HA_POS_ERROR; +} + + /* Initialized at each key walk (called multiple times unlike rnd_init()) */ int ha_federated::index_init(uint keynr) diff --git a/sql/ha_federated.h b/sql/ha_federated.h index dc4f976c578..349c596ae5a 100644 --- a/sql/ha_federated.h +++ b/sql/ha_federated.h @@ -277,6 +277,7 @@ public: int update_row(const byte *old_data, byte *new_data); int delete_row(const byte *buf); int index_init(uint keynr); + ha_rows estimate_rows_upper_bound(); int index_read(byte *buf, const byte *key, uint key_len, enum ha_rkey_function find_flag); int index_read_idx(byte *buf, uint idx, const byte *key, -- cgit v1.2.1 From ff7e7fcb6794d243b8324c3a76359a9c5ac68710 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 Nov 2007 18:48:22 +0400 Subject: Bug#32775 problems with SHOW EVENTS and Information_Schema removed unnecessary privilege checks for I_S schema mysql-test/r/information_schema.result: test result mysql-test/t/information_schema.test: test case sql/events.cc: There is no events in I_S so we don't need to execute check_access here. sql/sql_parse.cc: removed unnecessary check --- sql/events.cc | 4 ++-- sql/sql_parse.cc | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'sql') diff --git a/sql/events.cc b/sql/events.cc index 262c62bdbc8..4579fb4d086 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -825,8 +825,8 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS) { DBUG_ASSERT(thd->lex->select_lex.db); - if (check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, - is_schema_db(thd->lex->select_lex.db))) + if (!is_schema_db(thd->lex->select_lex.db) && // There is no events in I_S + check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, 0)) DBUG_RETURN(1); db= thd->lex->select_lex.db; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9f510f9b33c..7a777ba2bbd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1855,10 +1855,6 @@ mysql_execute_command(THD *thd) switch (lex->sql_command) { case SQLCOM_SHOW_EVENTS: - if ((res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, - is_schema_db(thd->lex->select_lex.db)))) - break; - /* fall through */ case SQLCOM_SHOW_STATUS_PROC: case SQLCOM_SHOW_STATUS_FUNC: res= execute_sqlcom_select(thd, all_tables); -- cgit v1.2.1 From 58f10e554aa2ce340e853be1006e1f411f89f09d Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 1 Dec 2007 19:55:06 +0100 Subject: Bug#31177: Server variables can't be set to their current values 5.1+ specific fixes (plugins etc.) include/my_getopt.h: make both ull and ll global mysql-test/r/index_merge_myisam.result: we throw warnings to the client, yea, verily mysql-test/r/innodb.result: we throw warnings to the client, yea, verily mysql-test/r/variables.result: we throw warnings to the client, yea, verily mysql-test/t/variables.test: correct result, is multiple of variable's block_size now mysys/my_getopt.c: export getopt_ll_limit_value(), check for integer wrap-around in it, same as in ull variant. Only print warnings to reporter when caller didn't ask for diagnostics, otherwise assume caller will handle any warnings (id est, throw them client-wards) sql/mysqld.cc: correct signedness of "concurrent-insert" sql/sql_plugin.cc: Throw sys-var out-of-range warnings client-wards for plugins, too. --- sql/mysqld.cc | 2 +- sql/sql_plugin.cc | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 5 deletions(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9d753f905dc..b81ccfc5db9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5216,7 +5216,7 @@ struct my_option my_long_options[] = {"concurrent-insert", OPT_CONCURRENT_INSERT, "Use concurrent insert with MyISAM. Disable with --concurrent-insert=0", (uchar**) &myisam_concurrent_insert, (uchar**) &myisam_concurrent_insert, - 0, GET_LONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, + 0, GET_ULONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, {"console", OPT_CONSOLE, "Write error output on screen; Don't remove the console window on windows.", (uchar**) &opt_console, (uchar**) &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 2af528f6699..07bf313067a 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1874,11 +1874,20 @@ err: static int check_func_int(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { + bool fixed; long long tmp; struct my_option options; value->val_int(value, &tmp); plugin_opt_set_limits(&options, var); - *(int *)save= (int) getopt_ull_limit_value(tmp, &options); + *(int *)save= (int) getopt_ull_limit_value(tmp, &options, &fixed); + if (fixed) + { + char buf[22]; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), var->name, + ullstr(tmp, buf)); + } return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) && (*(int *)save != (int) tmp); } @@ -1887,24 +1896,42 @@ static int check_func_int(THD *thd, struct st_mysql_sys_var *var, static int check_func_long(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { + bool fixed; long long tmp; struct my_option options; value->val_int(value, &tmp); plugin_opt_set_limits(&options, var); - *(long *)save= (long) getopt_ull_limit_value(tmp, &options); + *(long *)save= (long) getopt_ull_limit_value(tmp, &options, &fixed); + if (fixed) + { + char buf[22]; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), var->name, + ullstr(tmp, buf)); + } return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) && (*(long *)save != (long) tmp); } static int check_func_longlong(THD *thd, struct st_mysql_sys_var *var, - void *save, st_mysql_value *value) + void *save, st_mysql_value *value) { + bool fixed; long long tmp; struct my_option options; value->val_int(value, &tmp); plugin_opt_set_limits(&options, var); - *(ulonglong *)save= getopt_ull_limit_value(tmp, &options); + *(ulonglong *)save= getopt_ull_limit_value(tmp, &options, &fixed); + if (fixed) + { + char buf[22]; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), var->name, + ullstr(tmp, buf)); + } return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) && (*(long long *)save != tmp); } -- cgit v1.2.1 From b4a146a6ebe0ad14d40f241c0a37c9a43c7fd7f3 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 3 Dec 2007 10:08:58 +0100 Subject: Bug#30234: Unexpected behavior using DELETE with AS and USING Anti-patch. This patch undoes the previously pushed patch. It is null-merged in versions 5.1 and above since there the original patch is still desired. mysql-test/r/delete.result: Bug#30234: Anti-patch mysql-test/t/delete.test: Bug#30234: Anti-patch sql/sql_yacc.yy: Bug#30234: Anti-patch --- sql/sql_yacc.yy | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'sql') diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 82100b3d3dd..c4bc4616841 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1162,8 +1162,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); field_opt_list opt_binary table_lock_list table_lock ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use opt_delete_options opt_delete_option varchar nchar nvarchar - opt_outer table_list table_name table_alias_ref_list table_alias_ref - opt_option opt_place + opt_outer table_list table_name opt_option opt_place opt_attribute opt_attribute_list attribute column_list column_list_id opt_column_list grant_privileges grant_ident grant_list grant_option object_privilege object_privilege_list user_list rename_list @@ -6554,20 +6553,6 @@ table_name: } ; -table_alias_ref_list: - table_alias_ref - | table_alias_ref_list ',' table_alias_ref; - -table_alias_ref: - table_ident - { - if (!Select->add_table_to_list(YYTHD, $1, NULL, - TL_OPTION_UPDATING | TL_OPTION_ALIAS, - Lex->lock_option )) - MYSQL_YYABORT; - } - ; - if_exists: /* empty */ { $$= 0; } | IF EXISTS { $$= 1; } @@ -6838,7 +6823,7 @@ single_multi: if (multi_delete_set_locks_and_link_aux_tables(Lex)) MYSQL_YYABORT; } - | FROM table_alias_ref_list + | FROM table_wild_list { mysql_init_multi_delete(Lex); } USING join_table_list where_clause { -- cgit v1.2.1 From 09bf5b91693110bc91fa949bb2d85a0ac587d07e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 4 Dec 2007 01:17:52 +0100 Subject: Bug#31177: Server variables can't be set to their current values additional fixes for 64-bit --- Merge mysql.com:/misc/mysql/31177/50-31177 into mysql.com:/misc/mysql/31177/51-31177 --- Bug#31177: Server variables can't be set to their current values additional 5.1 fixes (for plugins) mysql-test/t/variables.test: replace 32-bit and 64-bit values --- manual merge mysys/my_getopt.c: 'mod' no longer used. on 64-bit, limit to (signed) (LONG)LONG_MAX to prevent badness in classes using longlong. sql/sql_plugin.cc: handle signedness in plugin-vars so we won't hit an assert() in getopt_*_limit_value() --- sql/sql_plugin.cc | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 08b33c4502c..002fb5be31e 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1880,7 +1880,13 @@ static int check_func_int(THD *thd, struct st_mysql_sys_var *var, struct my_option options; value->val_int(value, &tmp); plugin_opt_set_limits(&options, var); - *(int *)save= (int) getopt_ull_limit_value(tmp, &options, &fixed); + + if (var->flags & PLUGIN_VAR_UNSIGNED) + *(uint *)save= (uint) getopt_ull_limit_value((ulonglong) tmp, &options, + &fixed); + else + *(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed); + if (fixed) { char buf[22]; @@ -1902,7 +1908,13 @@ static int check_func_long(THD *thd, struct st_mysql_sys_var *var, struct my_option options; value->val_int(value, &tmp); plugin_opt_set_limits(&options, var); - *(long *)save= (long) getopt_ull_limit_value(tmp, &options, &fixed); + + if (var->flags & PLUGIN_VAR_UNSIGNED) + *(ulong *)save= (ulong) getopt_ull_limit_value((ulonglong) tmp, &options, + &fixed); + else + *(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed); + if (fixed) { char buf[22]; @@ -1925,6 +1937,13 @@ static int check_func_longlong(THD *thd, struct st_mysql_sys_var *var, value->val_int(value, &tmp); plugin_opt_set_limits(&options, var); *(ulonglong *)save= getopt_ull_limit_value(tmp, &options, &fixed); + + if (var->flags & PLUGIN_VAR_UNSIGNED) + *(ulonglong *)save= getopt_ull_limit_value((ulonglong) tmp, &options, + &fixed); + else + *(longlong *)save= getopt_ll_limit_value(tmp, &options, &fixed); + if (fixed) { char buf[22]; -- cgit v1.2.1 From 4618d68d6d85141cd2422c892ed5053c72aa097a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Dec 2007 01:28:01 +0100 Subject: Bug#31177: Server variables can't be set to their current values additional fixes for BDB and correct assignment of both signed and unsigned 64-bit data to unsigned system variables mysql-test/r/ps_2myisam.result: account for UNSIGNED_FLAG mysql-test/r/ps_3innodb.result: account for UNSIGNED_FLAG mysql-test/r/ps_4heap.result: account for UNSIGNED_FLAG mysql-test/r/ps_5merge.result: account for UNSIGNED_FLAG mysql-test/r/ps_6bdb.result: account for UNSIGNED_FLAG mysql-test/r/ps_7ndb.result: account for UNSIGNED_FLAG mysys/my_getopt.c: We have correct signed/unsigned information now, so we no longer need to err on the side of caution. sql/item_func.cc: Copy unsigned info over from entry so the item's data correctly describe it. sql/mysqld.cc: BDB log buffer size: default can't be less than minimum sql/set_var.cc: Handle signedness of in-values correctly when assigning to unsigned types, all the way up to 64-bit. Use handler from all three unsigned sysvar types. sql/set_var.h: thd_ulonglong: Override default check with one for unsigned types --- sql/item_func.cc | 2 ++ sql/mysqld.cc | 2 +- sql/set_var.cc | 32 ++++++++++++++++++++++++-------- sql/set_var.h | 1 + 4 files changed, 28 insertions(+), 9 deletions(-) (limited to 'sql') diff --git a/sql/item_func.cc b/sql/item_func.cc index 2ee9973c785..019df9176c9 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4597,6 +4597,8 @@ void Item_func_get_user_var::fix_length_and_dec() if (var_entry) { + unsigned_flag= var_entry->unsigned_flag; + collation.set(var_entry->collation); switch (var_entry->type) { case REAL_RESULT: diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3900f74da7e..23a05485796 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5679,7 +5679,7 @@ log and this option does nothing anymore.", {"bdb_log_buffer_size", OPT_BDB_LOG_BUFFER_SIZE, "The buffer that is allocated to cache index and rows for BDB tables.", (gptr*) &berkeley_log_buffer_size, (gptr*) &berkeley_log_buffer_size, 0, - GET_ULONG, REQUIRED_ARG, 0, 256*1024L, ULONG_MAX, 0, 1024, 0}, + GET_ULONG, REQUIRED_ARG, 256*1024L, 256*1024L, ULONG_MAX, 0, 1024, 0}, {"bdb_max_lock", OPT_BDB_MAX_LOCK, "The maximum number of locks you can have active on a BDB table.", (gptr*) &berkeley_max_lock, (gptr*) &berkeley_max_lock, 0, GET_ULONG, diff --git a/sql/set_var.cc b/sql/set_var.cc index 84b3f92c1ca..58b9b93b17f 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -115,6 +115,7 @@ static void fix_trans_mem_root(THD *thd, enum_var_type type); static void fix_server_id(THD *thd, enum_var_type type); static ulonglong fix_unsigned(THD *thd, ulonglong num, const struct my_option *option_limits); +static bool get_unsigned(THD *thd, set_var *var); static void throw_bounds_warning(THD *thd, const char *name, ulonglong num); static KEY_CACHE *create_key_cache(const char *name, uint length); void fix_sql_mode_var(THD *thd, enum_var_type type); @@ -1471,6 +1472,18 @@ static ulonglong fix_unsigned(THD *thd, ulonglong num, return out; } +static bool get_unsigned(THD *thd, set_var *var) +{ + if (var->value->unsigned_flag) + var->save_result.ulonglong_value= (ulonglong) var->value->val_int(); + else + { + longlong v= var->value->val_int(); + var->save_result.ulonglong_value= (ulonglong) ((v < 0) ? 0 : v); + } + return 0; +} + sys_var_long_ptr:: sys_var_long_ptr(const char *name_arg, ulong *value_ptr_arg, @@ -1482,9 +1495,7 @@ sys_var_long_ptr(const char *name_arg, ulong *value_ptr_arg, bool sys_var_long_ptr_global::check(THD *thd, set_var *var) { - longlong v= var->value->val_int(); - var->save_result.ulonglong_value= v < 0 ? 0 : v; - return 0; + return get_unsigned(thd, var); } bool sys_var_long_ptr_global::update(THD *thd, set_var *var) @@ -1497,9 +1508,9 @@ bool sys_var_long_ptr_global::update(THD *thd, set_var *var) { #if SIZEOF_LONG < SIZEOF_LONG_LONG /* Avoid overflows on 32 bit systems */ - if (tmp > (ulonglong) ~(ulong) 0) + if (tmp > ULONG_MAX) { - tmp= ((ulonglong) ~(ulong) 0); + tmp= ULONG_MAX; throw_bounds_warning(thd, name, var->save_result.ulonglong_value); } #endif @@ -1567,7 +1578,7 @@ byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) bool sys_var_thd_ulong::check(THD *thd, set_var *var) { - return (sys_var_thd::check(thd, var) || + return (get_unsigned(thd, var) || (check_func && (*check_func)(thd, var))); } @@ -1585,9 +1596,9 @@ bool sys_var_thd_ulong::update(THD *thd, set_var *var) if (option_limits) tmp= (ulong) fix_unsigned(thd, tmp, option_limits); #if SIZEOF_LONG < SIZEOF_LONG_LONG - else if (tmp > (ulonglong) ~(ulong) 0) + else if (tmp > ULONG_MAX) { - tmp= ((ulonglong) ~(ulong) 0); + tmp= ULONG_MAX; throw_bounds_warning(thd, name, var->save_result.ulonglong_value); } #endif @@ -1667,6 +1678,11 @@ byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type, return (byte*) &(thd->variables.*offset); } +bool sys_var_thd_ulonglong::check(THD *thd, set_var *var) +{ + return get_unsigned(thd, var); +} + bool sys_var_thd_ulonglong::update(THD *thd, set_var *var) { ulonglong tmp= var->save_result.ulonglong_value; diff --git a/sql/set_var.h b/sql/set_var.h index 7b3f864f44c..93402e21258 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -365,6 +365,7 @@ public: void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_LONGLONG; } byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + bool check(THD *thd, set_var *var); bool check_default(enum_var_type type) { return type == OPT_GLOBAL && !option_limits; -- cgit v1.2.1 From b6c0c1754c5d378de3d37ca02b21df7dfaa3b229 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Dec 2007 16:39:42 +0400 Subject: Bug #32247 Test reports wrong value of "AUTO_INCREMENT" (on a partitioned InnoDB table). ha_partition::update_create_info() just calls update_create_info of a first partition, so only get the autoincrement maximum of the first partition, so SHOW CREATE TABLE can show small AUTO_INCREMENT parameters. Fixed by implementing ha_partition::update_create_info() in a way other handlers work. HA_ARCHIVE:stats.auto_increment handling made consistent with other engines mysql-test/r/archive.result: Bug #32247 Test reports wrong value of "AUTO_INCREMENT" (on a partitioned InnoDB table). test result fixed mysql-test/r/partition.result: Bug #32247 Test reports wrong value of "AUTO_INCREMENT" (on a partitioned InnoDB table). test result mysql-test/suite/rpl/r/rpl_innodb_bug28430.result: Bug #32247 Test reports wrong value of "AUTO_INCREMENT" (on a partitioned InnoDB table). test result fixed mysql-test/t/partition.test: Bug #32247 Test reports wrong value of "AUTO_INCREMENT" (on a partitioned InnoDB table). test added as rpl_innodb_bug28430 is INNOBASE specific while the bug is not sql/ha_partition.cc: Bug #32247 Test reports wrong value of "AUTO_INCREMENT" (on a partitioned InnoDB table). ha_partition::update_create_info() implemented storage/archive/ha_archive.cc: Bug #32247 Test reports wrong value of "AUTO_INCREMENT" (on a partitioned InnoDB table). ha_archive.stats.auto_increment now contains next (not last used) value of auto_increment to be consistent with other engines --- sql/ha_partition.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 8afaab71160..15dcc4f3b4a 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1598,7 +1598,11 @@ error: void ha_partition::update_create_info(HA_CREATE_INFO *create_info) { - m_file[0]->update_create_info(create_info); + info(HA_STATUS_AUTO); + + if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) + create_info->auto_increment_value= stats.auto_increment_value; + return; } -- cgit v1.2.1 From 85eed9de26a1957f3911aaa5559d9dcdd493aa33 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Dec 2007 18:03:30 +0100 Subject: Bug#31177: Server variables can't be set to their current values initialise limits properly for getopt_ll_limit() (fixes falcon_opt test) sql/sql_plugin.cc: initialise limits properly for getopt_ll_limit() --- sql/sql_plugin.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sql') diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 002fb5be31e..d306ded7f4f 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -2725,6 +2725,8 @@ bool sys_var_pluginvar::update(THD *thd, set_var *var) static void plugin_opt_set_limits(struct my_option *options, const struct st_mysql_sys_var *opt) { + options->sub_size= 0; + switch (opt->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) { /* global system variables */ -- cgit v1.2.1 From 0ad7fc58c7e149fe7885d6a3558637f87513047a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Dec 2007 22:54:47 +0300 Subject: Bug#32482: Crash for a query with ORDER BY a user variable. The Item_func_set_user_var::register_field_in_read_map() did not check that the result_field was null.This caused server crashes for queries that required order by such a field and were executed without using a temporary table. The Item_func_set_user_var::register_field_in_read_map() now checks the result_field to be not null. mysql-test/t/user_var.test: Added a test case for the bug#32482: Crash for a query with ORDER BY a user variable. mysql-test/r/user_var.result: Added a test case for the bug#32482: Crash for a query with ORDER BY a user variable. sql/item_func.cc: Bug#32482: Crash for a query with ORDER BY a user variable. The Item_func_set_user_var::register_field_in_read_map() now checks the result_field to be not null. --- sql/item_func.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/item_func.cc b/sql/item_func.cc index e2551979202..41de960a37e 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3848,9 +3848,12 @@ Item_func_set_user_var::fix_length_and_dec() bool Item_func_set_user_var::register_field_in_read_map(uchar *arg) { - TABLE *table= (TABLE *) arg; - if (result_field->table == table || !table) - bitmap_set_bit(result_field->table->read_set, result_field->field_index); + if (result_field) + { + TABLE *table= (TABLE *) arg; + if (result_field->table == table || !table) + bitmap_set_bit(result_field->table->read_set, result_field->field_index); + } return 0; } -- cgit v1.2.1 From d776054e00b917e1d6fbf0195b924a052466320a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Dec 2007 17:14:59 -0800 Subject: Fixed bug #32815. The index (key_part_1, key_part-2) was erroneously considered as compatible with the required ordering in the function test_test_if_order_by_key when a query with an ORDER BY clause contained a condition of the form key_part_1=const OR key_part_1 IS NULL and the order list contained only key_part_2. This happened because the value of the const_key_parts field in the KEYUSE structure was not formed correctly for the keys that could be used for ref_or_null access. This was fixed in the code of the update_ref_and_keys function. The problem could not manifest itself for MyISAM databases because the implementation of the keys_to_use_for_scanning() handler function always returns an empty bitmap for the MyISAM engine. mysql-test/r/innodb_mysql.result: Added a test case for bug #32815. mysql-test/t/innodb_mysql.test: Added a test case for bug #32815. sql/sql_select.cc: Fixed bug #32815. The index (key_part_1, key_part-2) was erroneously considered as compatible with the required ordering in the function test_test_if_order_by_key when a query with an ORDER BY clause contained a condition of the form key_part_1=const OR key_part_1 IS NULL and the order list contained only key_part_2. This happened because the value of the const_key_parts field in the KEYUSE structure was not formed correctly for the keys that could be used for ref_or_null access. This was fixed in the code of the update_ref_and_keys function. --- sql/sql_select.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index bcf538cdde2..d1bd018878a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3691,7 +3691,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, found_eq_constant=0; for (i=0 ; i < keyuse->elements-1 ; i++,use++) { - if (!use->used_tables) + if (!use->used_tables && use->optimize != KEY_OPTIMIZE_REF_OR_NULL) use->table->const_key_parts[use->key]|= use->keypart_map; if (use->keypart != FT_KEYPART) { -- cgit v1.2.1 From b1b2e0d053029ef2111b37f6aa624af364186bde Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Dec 2007 23:36:58 -0800 Subject: Fixed bug #27545. Both arguments of the function NAME_CONST must be constant expressions. This constraint is checked in the Item_name_const::fix_fields method. Yet if the argument of the function was not a constant expression no error message was reported. As a result the client hanged waiting for a response. Now the function Item_name_const::fix_fields reports an error message when any of the additional context conditions imposed on the function NAME_CONST is not satisfied. mysql-test/r/func_misc.result: Added a test case for bug #26545. mysql-test/t/func_misc.test: Added a test case for bug #26545. --- sql/item.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index 3555df40060..4eeb2b2aa84 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1221,14 +1221,14 @@ bool Item_name_const::fix_fields(THD *thd, Item **ref) s.length(0); if (value_item->fix_fields(thd, &value_item) || - name_item->fix_fields(thd, &name_item)) - return TRUE; - if (!(value_item->const_item() && name_item->const_item())) + name_item->fix_fields(thd, &name_item) || + !value_item->const_item() || + !name_item->const_item() || + !(item_name= name_item->val_str(&s))) // Can't have a NULL name + { + my_error(ER_RESERVED_SYNTAX, MYF(0), "NAME_CONST"); return TRUE; - - if (!(item_name= name_item->val_str(&s))) - return TRUE; /* Can't have a NULL name */ - + } set_name(item_name->ptr(), (uint) item_name->length(), system_charset_info); max_length= value_item->max_length; decimals= value_item->decimals; -- cgit v1.2.1 From b3d8ff4ebd16c418dbce2731a5553c3ae6a47a7f Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 8 Dec 2007 23:05:00 +0200 Subject: Fix for BUG#32694 "NOT NULL table field in a subquery produces invalid results" The problem was that when convert_constant_item is called for subqueries, this happens when we already started executing the top-level query, and the field argument of convert_constant_item pointed to a valid table row. In turn convert_constant_item used the field buffer to compute the value of its item argument. This copied the item's value into the field, and made equalities with outer references always true. The fix saves/restores the original field's value when it belongs to an outer table. mysql-test/r/type_datetime.result: Test for BUG#32694. mysql-test/t/type_datetime.test: Test for BUG#32694. sql/item_cmpfunc.cc: - Changed convert_constant_item() so that it doesn't destroy the contents of its field argument when the field originates from table in an outer query. --- sql/item_cmpfunc.cc | 67 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 26 deletions(-) (limited to 'sql') diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f9744baf19e..1881d2f7f1f 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -24,7 +24,8 @@ #include #include "sql_select.h" -static bool convert_constant_item(THD *thd, Field *field, Item **item); +static bool convert_constant_item(THD *thd, Item_field *field_item, + Item **item); static Item_result item_store_type(Item_result a, Item *item, my_bool unsigned_flag) @@ -317,7 +318,7 @@ longlong Item_func_nop_all::val_int() SYNOPSIS convert_constant_item() thd thread handle - field item will be converted using the type of this field + field_item item will be converted using the type of this field item [in/out] reference to the item to convert DESCRIPTION @@ -340,30 +341,46 @@ longlong Item_func_nop_all::val_int() 1 Item was replaced with an integer version of the item */ -static bool convert_constant_item(THD *thd, Field *field, Item **item) +static bool convert_constant_item(THD *thd, Item_field *field_item, + Item **item) { + Field *field= field_item->field; + int result= 0; + if (!(*item)->with_subselect && (*item)->const_item()) { /* For comparison purposes allow invalid dates like 2000-01-32 */ ulong orig_sql_mode= thd->variables.sql_mode; enum_check_fields orig_count_cuted_fields= thd->count_cuted_fields; + ulonglong orig_field_val; /* original field value if valid */ thd->variables.sql_mode= (orig_sql_mode & ~MODE_NO_ZERO_DATE) | MODE_INVALID_DATES; thd->count_cuted_fields= CHECK_FIELD_IGNORE; + /* + Store the value of the field if it references an outer field because + the call to save_in_field below overrides that value. + */ + if (field_item->depended_from) + orig_field_val= field->val_int(); if (!(*item)->is_null() && !(*item)->save_in_field(field, 1)) { Item *tmp=new Item_int_with_ref(field->val_int(), *item, test(field->flags & UNSIGNED_FLAG)); - thd->variables.sql_mode= orig_sql_mode; - thd->count_cuted_fields= orig_count_cuted_fields; if (tmp) thd->change_item_tree(item, tmp); - return 1; // Item was replaced + result= 1; // Item was replaced + } + /* Restore the original field value. */ + if (field_item->depended_from) + { + result= field->store(orig_field_val, TRUE); + /* orig_field_val must be a valid value that can be restored back. */ + DBUG_ASSERT(!result); } thd->variables.sql_mode= orig_sql_mode; thd->count_cuted_fields= orig_count_cuted_fields; } - return 0; + return result; } @@ -411,15 +428,14 @@ void Item_bool_func2::fix_length_and_dec() thd= current_thd; if (!thd->is_context_analysis_only()) { - Item *arg_real_item= args[0]->real_item(); - if (arg_real_item->type() == FIELD_ITEM) + if (args[0]->real_item()->type() == FIELD_ITEM) { - Field *field=((Item_field*) arg_real_item)->field; - if (field->can_be_compared_as_longlong() && - !(arg_real_item->is_datetime() && + Item_field *field_item= (Item_field*) (args[0]->real_item()); + if (field_item->field->can_be_compared_as_longlong() && + !(field_item->is_datetime() && args[1]->result_type() == STRING_RESULT)) { - if (convert_constant_item(thd, field,&args[1])) + if (convert_constant_item(thd, field_item, &args[1])) { cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, INT_RESULT); // Works for all types. @@ -428,15 +444,14 @@ void Item_bool_func2::fix_length_and_dec() } } } - arg_real_item= args[1]->real_item(); - if (arg_real_item->type() == FIELD_ITEM) + if (args[1]->real_item()->type() == FIELD_ITEM) { - Field *field=((Item_field*) arg_real_item)->field; - if (field->can_be_compared_as_longlong() && - !(arg_real_item->is_datetime() && + Item_field *field_item= (Item_field*) (args[1]->real_item()); + if (field_item->field->can_be_compared_as_longlong() && + !(field_item->is_datetime() && args[0]->result_type() == STRING_RESULT)) { - if (convert_constant_item(thd, field,&args[0])) + if (convert_constant_item(thd, field_item, &args[0])) { cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, INT_RESULT); // Works for all types. @@ -1889,16 +1904,16 @@ void Item_func_between::fix_length_and_dec() thd->lex->sql_command != SQLCOM_CREATE_VIEW && thd->lex->sql_command != SQLCOM_SHOW_CREATE) { - Field *field=((Item_field*) (args[0]->real_item()))->field; - if (field->can_be_compared_as_longlong()) + Item_field *field_item= (Item_field*) (args[0]->real_item()); + if (field_item->field->can_be_compared_as_longlong()) { /* The following can't be recoded with || as convert_constant_item changes the argument */ - if (convert_constant_item(thd, field,&args[1])) + if (convert_constant_item(thd, field_item, &args[1])) cmp_type=INT_RESULT; // Works for all types. - if (convert_constant_item(thd, field,&args[2])) + if (convert_constant_item(thd, field_item, &args[2])) cmp_type=INT_RESULT; // Works for all types. } } @@ -3491,13 +3506,13 @@ void Item_func_in::fix_length_and_dec() thd->lex->sql_command != SQLCOM_SHOW_CREATE && cmp_type != INT_RESULT) { - Field *field= ((Item_field*) (args[0]->real_item()))->field; - if (field->can_be_compared_as_longlong()) + Item_field *field_item= (Item_field*) (args[0]->real_item()); + if (field_item->field->can_be_compared_as_longlong()) { bool all_converted= TRUE; for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++) { - if (!convert_constant_item (thd, field, &arg[0])) + if (!convert_constant_item (thd, field_item, &arg[0])) all_converted= FALSE; } if (all_converted) -- cgit v1.2.1 From 1cdd95f7d1a27723c1ae1d3a6f457a0042b44795 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 9 Dec 2007 11:53:07 -0800 Subject: Forced compilers to remove the warning appeared after the patch with a fix for bug 32694. --- sql/item_cmpfunc.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'sql') diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1881d2f7f1f..4b584f5cb0b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -353,6 +353,7 @@ static bool convert_constant_item(THD *thd, Item_field *field_item, ulong orig_sql_mode= thd->variables.sql_mode; enum_check_fields orig_count_cuted_fields= thd->count_cuted_fields; ulonglong orig_field_val; /* original field value if valid */ + LINT_INIT(orig_field_val); thd->variables.sql_mode= (orig_sql_mode & ~MODE_NO_ZERO_DATE) | MODE_INVALID_DATES; thd->count_cuted_fields= CHECK_FIELD_IGNORE; -- cgit v1.2.1 From 1ebb563422e5650f80addc3adf08f88044b4b340 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 10 Dec 2007 08:12:41 +0100 Subject: Bug #31177: Server variables can't be set to their current values fixes for SLES10 mysql-test/r/change_user.result: It's unsigned. mysys/my_getopt.c: Failsafe no longer needed, we handle signedness correctly now. sql/set_var.cc: ha_rows can be derived from all kinds of types, but they're all unsigned. Display it as such. tests/mysql_client_test.c: cannot easily check this here due to types. check with Alik whether we need this on top of change_user.test. --- sql/set_var.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/set_var.cc b/sql/set_var.cc index d78a691768e..8a6f0ac6285 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1551,7 +1551,7 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) pthread_mutex_lock(&LOCK_global_system_variables); value= *(ha_rows*) value_ptr(thd, var_type, base); pthread_mutex_unlock(&LOCK_global_system_variables); - return new Item_int((longlong) value); + return new Item_int((ulonglong) value); } case SHOW_MY_BOOL: { -- cgit v1.2.1 From c6675cd1876a90468ca2e2cb10471af93728aa6c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 13 Dec 2007 13:38:22 +0300 Subject: BUG#32198: Comparison of DATE with DATETIME still not using indexes correctly - Make conditions like "date_col $CMP$ 'datetime-const'" range-sargable mysql-test/r/range.result: BUG#32198: Comparison of DATE with DATETIME still not using indexes correctly - Testcase mysql-test/t/range.test: BUG#32198: Comparison of DATE with DATETIME still not using indexes correctly - Testcase sql/field.cc: BUG#32198: Comparison of DATE with DATETIME still not using indexes correctly - Added comments --- sql/field.cc | 3 +++ sql/opt_range.cc | 27 ++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 86853389c64..955694933a0 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5259,6 +5259,9 @@ void Field_date::sql_type(String &res) const 1 Value was cut during conversion 2 Wrong date string 3 Datetime value that was cut (warning level NOTE) + This is used by opt_range.cc:get_mm_leaf(). Note that there is a + nearly-identical class Field_date doesn't ever return 3 from its + store function. */ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 7a51dbbe76c..5d8bba69422 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -4414,6 +4414,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, { tree= new (alloc) SEL_ARG(field, 0, 0); tree->type= SEL_ARG::IMPOSSIBLE; + goto end; } else { @@ -4422,8 +4423,32 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, for the cases like int_field > 999999999999999999999999 as well. */ tree= 0; + if (err == 3 && field->type() == FIELD_TYPE_DATE && + (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC || + type == Item_func::LT_FUNC || type == Item_func::LE_FUNC) ) + { + /* + We were saving DATETIME into a DATE column, the conversion went ok + but a non-zero time part was cut off. + + In MySQL's SQL dialect, DATE and DATETIME are compared as datetime + values. Index over a DATE column uses DATE comparison. Changing + from one comparison to the other is possible: + + datetime(date_col)< '2007-12-10 12:34:55' -> date_col<='2007-12-10' + datetime(date_col)<='2007-12-10 12:34:55' -> date_col<='2007-12-10' + + datetime(date_col)> '2007-12-10 12:34:55' -> date_col>='2007-12-10' + datetime(date_col)>='2007-12-10 12:34:55' -> date_col>='2007-12-10' + + but we'll need to convert '>' to '>=' and '<' to '<='. This will + be done together with other types at the end of this function + (grep for field_is_equal_to_item) + */ + } + else + goto end; } - goto end; } if (err < 0) { -- cgit v1.2.1 From 0cc269da52f939ffc6a6272370d113aac9ab5369 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 13 Dec 2007 18:26:27 +0400 Subject: after merge fix --- sql/sql_parse.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2435c16819f..7c00ac6d1c9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -487,7 +487,7 @@ end: (CREATE TABLE, ALTER TABLE ... UNION=(...)). Set TL_WRITE for every child. Set 'db' for every child if not present. */ - +#ifndef NO_EMBEDDED_ACCESS_CHECKS static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list) { @@ -508,7 +508,7 @@ static bool check_merge_table_access(THD *thd, char *db, } return error; } - +#endif /* This works because items are allocated with sql_alloc() */ -- cgit v1.2.1 From f61f5f72f55b44d33ff77de00432649134eab25c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 13 Dec 2007 21:34:05 +0400 Subject: additional after merge fix mysql-test/r/partition_range.result: removed fix for bug#30573 mysql-test/suite/parts/r/rpl_partition.result: updated result file mysql-test/t/partition_range.test: removed test case for bug#30573 sql/ha_partition.cc: removed fix for bug#30573 --- sql/ha_partition.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index a792d5c4161..d251e056c3e 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3853,7 +3853,7 @@ int ha_partition::read_range_first(const key_range *start_key, start_key->key, start_key->keypart_map, start_key->flag); } - DBUG_RETURN (error? error: compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE); + DBUG_RETURN(error); } -- cgit v1.2.1