From fb643aba56ec3bf1876a21fdb1a07166e56544d7 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Thu, 31 Mar 2005 21:41:07 +0200 Subject: [PATCH 01/34] Fixes for bugs reported by Stefano Di Paola (stefano.dipaola@wisec.it) Originally contained in 2005/03/03 19:51:29+01:00 serg@serg.mylan; contained in MySQL 4.1.10a; re-committed for archival purposes. --- include/my_global.h | 3 ++ isam/create.c | 5 +- merge/mrg_create.c | 2 +- myisam/mi_create.c | 14 ++--- myisammrg/myrg_create.c | 2 +- mysys/mf_tempfile.c | 8 +-- sql/ha_myisam.cc | 18 ++++--- sql/mysql_priv.h | 2 +- sql/mysqld.cc | 10 +++- sql/share/english/errmsg.txt | 2 +- sql/sql_udf.cc | 99 ++++++++++++++++++++++++------------ sql/table.cc | 6 ++- 12 files changed, 112 insertions(+), 59 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 7ca3d5e1e58..23cf0d54824 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -523,6 +523,9 @@ typedef SOCKET_SIZE_TYPE size_socket; #ifndef O_SHORT_LIVED #define O_SHORT_LIVED 0 #endif +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 +#endif /* #define USE_RECORD_LOCK */ diff --git a/isam/create.c b/isam/create.c index 4c23f3edd11..204d3157d00 100644 --- a/isam/create.c +++ b/isam/create.c @@ -58,13 +58,14 @@ int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo, base_pos=512; /* Enough for N_STATE_INFO */ bzero((byte*) &share,sizeof(share)); if ((file = my_create(fn_format(buff,name,"",N_NAME_IEXT,4),0, - O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) + O_RDWR | O_EXCL | O_NOFOLLOW,MYF(MY_WME))) < 0) goto err; errpos=1; VOID(fn_format(buff,name,"",N_NAME_DEXT,2+4)); if (!(flags & HA_DONT_TOUCH_DATA)) { - if ((dfile = my_create(buff,0,O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) + if ((dfile = my_create(buff,0,O_RDWR | O_EXCL | O_NOFOLLOW, + MYF(MY_WME))) < 0) goto err; errpos=2; } diff --git a/merge/mrg_create.c b/merge/mrg_create.c index d55a1421647..3508b7967f4 100644 --- a/merge/mrg_create.c +++ b/merge/mrg_create.c @@ -33,7 +33,7 @@ int mrg_create(const char *name, const char**table_names) errpos=0; if ((file = my_create(fn_format(buff,name,"",MRG_NAME_EXT,4),0, - O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) + O_RDWR | O_EXCL | O_NOFOLLOW,MYF(MY_WME))) < 0) goto err; errpos=1; if (table_names) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index f99a2c655d2..2cadc86f452 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -39,7 +39,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, { register uint i,j; File dfile,file; - int errpos,save_errno; + int errpos,save_errno, create_mode= O_RDWR | O_TRUNC; myf create_flag; uint fields,length,max_key_length,packed,pointer,real_length_diff, key_length,info_length,key_segs,options,min_key_length_skip, @@ -176,7 +176,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, min_pack_length+=varchar_length+2*varchar_count; } if (flags & HA_CREATE_TMP_TABLE) + { options|= HA_OPTION_TMP_TABLE; + create_mode|= O_EXCL | O_NOFOLLOW; + } if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM)) { options|= HA_OPTION_CHECKSUM; @@ -533,9 +536,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, create_flag=MY_DELETE_OLD; } - if ((file= my_create_with_symlink(linkname_ptr, - filename, - 0, O_RDWR | O_TRUNC, + if ((file= my_create_with_symlink(linkname_ptr, filename, 0, create_mode, MYF(MY_WME | create_flag))) < 0) goto err; errpos=1; @@ -546,7 +547,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, if (share.base.raid_type) { (void) fn_format(filename,name,"",MI_NAME_DEXT,2+4); - if ((dfile=my_raid_create(filename,0,O_RDWR | O_TRUNC, + if ((dfile=my_raid_create(filename, 0, create_mode share.base.raid_type, share.base.raid_chunks, share.base.raid_chunksize, @@ -570,8 +571,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, create_flag=MY_DELETE_OLD; } if ((dfile= - my_create_with_symlink(linkname_ptr, filename, - 0,O_RDWR | O_TRUNC, + my_create_with_symlink(linkname_ptr, filename, 0, create_mode, MYF(MY_WME | create_flag))) < 0) goto err; } diff --git a/myisammrg/myrg_create.c b/myisammrg/myrg_create.c index 5fc3c60ff32..7ddb7ecb3b9 100644 --- a/myisammrg/myrg_create.c +++ b/myisammrg/myrg_create.c @@ -34,7 +34,7 @@ int myrg_create(const char *name, const char **table_names, errpos=0; if ((file = my_create(fn_format(buff,name,"",MYRG_NAME_EXT,4),0, - O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) + O_RDWR | O_EXCL | O_NOFOLLOW,MYF(MY_WME))) < 0) goto err; errpos=1; if (table_names) diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c index af9ff0d6711..a15bda4da6d 100644 --- a/mysys/mf_tempfile.c +++ b/mysys/mf_tempfile.c @@ -70,7 +70,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, { strmake(to,res,FN_REFLEN-1); (*free)(res); - file=my_create(to,0, mode, MyFlags); + file=my_create(to,0, mode | O_EXCL | O_NOFOLLOW, MyFlags); } environ=old_env; } @@ -81,7 +81,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, { strmake(to,res,FN_REFLEN-1); (*free)(res); - file=my_create(to, 0, mode, MyFlags); + file=my_create(to, 0, mode | O_EXCL | O_NOFOLLOW, MyFlags); } #elif defined(HAVE_MKSTEMP) && !defined(__NETWARE__) { @@ -143,7 +143,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, strmake(to,res,FN_REFLEN-1); (*free)(res); file=my_create(to,0, - (int) (O_RDWR | O_BINARY | O_TRUNC | + (int) (O_RDWR | O_BINARY | O_TRUNC | O_EXCL | O_NOFOLLOW | O_TEMPORARY | O_SHORT_LIVED), MYF(MY_WME)); @@ -186,7 +186,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, } (void) strmov(end_pos,TMP_EXT); file=my_create(to,0, - (int) (O_RDWR | O_BINARY | O_TRUNC | + (int) (O_RDWR | O_BINARY | O_TRUNC | O_EXCL | O_NOFOLLOW | O_TEMPORARY | O_SHORT_LIVED), MYF(MY_WME)); } diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index a7beae664b9..58fd67ddfa3 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1334,7 +1334,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, HA_CREATE_INFO *info) { int error; - uint i,j,recpos,minpos,fieldpos,temp_length,length; + uint i,j,recpos,minpos,fieldpos,temp_length,length, create_flags; bool found_real_auto_increment=0; enum ha_base_keytype type; char buff[FN_REFLEN]; @@ -1510,17 +1510,21 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, create_info.data_file_name= info->data_file_name; create_info.index_file_name=info->index_file_name; + if (info->options & HA_LEX_CREATE_TMP_TABLE) + create_flags|= HA_CREATE_TMP_TABLE; + if (options & HA_OPTION_PACK_RECORD) + create_flags|= HA_PACK_RECORD; + if (options & HA_OPTION_CHECKSUM) + create_flags|= HA_CREATE_CHECKSUM; + if (options & HA_OPTION_DELAY_KEY_WRITE) + create_flags|= HA_CREATE_DELAY_KEY_WRITE; + /* TODO: Check that the following fn_format is really needed */ error=mi_create(fn_format(buff,name,"","",2+4), table_arg->keys,keydef, (uint) (recinfo_pos-recinfo), recinfo, 0, (MI_UNIQUEDEF*) 0, - &create_info, - (((options & HA_OPTION_PACK_RECORD) ? HA_PACK_RECORD : 0) | - ((options & HA_OPTION_CHECKSUM) ? HA_CREATE_CHECKSUM : 0) | - ((options & HA_OPTION_DELAY_KEY_WRITE) ? - HA_CREATE_DELAY_KEY_WRITE : 0))); - + &create_info, create_flags); my_free((gptr) recinfo,MYF(0)); DBUG_RETURN(error); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6218bc49f53..36eca63ab0e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -911,7 +911,7 @@ extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types; extern my_bool opt_safe_show_db, opt_local_infile; extern my_bool opt_slave_compressed_protocol, use_temp_pool; extern my_bool opt_readonly, lower_case_file_system; -extern my_bool opt_enable_named_pipe, opt_sync_frm; +extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs; extern my_bool opt_secure_auth; extern uint opt_crash_binlog_innodb; extern char *shared_memory_base_name, *mysqld_unix_port; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 53dca59bc92..6eaaed2800b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -289,6 +289,7 @@ my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam, opt_ndbcluster; const char *opt_ndbcluster_connectstring= 0; my_bool opt_ndb_shm, opt_ndb_optimized_node_selection; #endif +my_bool opt_allow_suspicious_udfs; my_bool opt_readonly, use_temp_pool, relay_log_purge; my_bool opt_sync_bdb_logs, opt_sync_frm; my_bool opt_secure_auth= 0; @@ -4101,7 +4102,7 @@ enum options_mysqld OPT_BDB_MAX_LOCK, OPT_ERROR_LOG_FILE, OPT_DEFAULT_WEEK_FORMAT, - OPT_RANGE_ALLOC_BLOCK_SIZE, + OPT_RANGE_ALLOC_BLOCK_SIZE, OPT_ALLOW_SUSPICIOUS_UDFS, OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE, OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE, OPT_SYNC_FRM, OPT_SYNC_BINLOG, @@ -4141,6 +4142,13 @@ struct my_option my_long_options[] = #endif /* HAVE_REPLICATION */ {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"allow-suspicious-udfs", OPT_ALLOW_SUSPICIOUS_UDFS, + "Allows to use UDF's consisting of only one symbol xxx() " + "without corresponing xxx_init() or xxx_deinit(). That also means " + "that one can load any function from any library, for example exit() " + "from libc.so", + (gptr*) &opt_allow_suspicious_udfs, (gptr*) &opt_allow_suspicious_udfs, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"basedir", 'b', "Path to installation directory. All paths are usually resolved relative to this.", (gptr*) &mysql_home_ptr, (gptr*) &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG, diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 8ede3f61a0b..104a055417c 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -143,7 +143,7 @@ character-set=latin1 "No paths allowed for shared library", "Function '%-.64s' already exists", "Can't open shared library '%-.64s' (errno: %d %-.64s)", -"Can't find function '%-.64s' in library'", +"Can't find function '%-.64s' in library", "Function '%-.64s' is not defined", "Host '%-.64s' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'", "Host '%-.64s' is not allowed to connect to this MySQL server", diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 0bb8ac8a28b..ae89c1eaa35 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -74,32 +74,49 @@ static HASH udf_hash; static rw_lock_t THR_LOCK_udf; -static udf_func *add_udf(LEX_STRING *name, Item_result ret, char *dl, - Item_udftype typ); +static udf_func *add_udf(char *name, Item_result ret, + char *dl, Item_udftype typ); static void del_udf(udf_func *udf); static void *find_udf_dl(const char *dl); - -static void init_syms(udf_func *tmp) +static char *init_syms(udf_func *tmp, char *nm) { - char nm[MAX_FIELD_NAME+16],*end; + char *end; + + if (!((tmp->func= dlsym(tmp->dlhandle, tmp->name)))) + return tmp->name; - tmp->func = dlsym(tmp->dlhandle, tmp->name.str); end=strmov(nm,tmp->name.str); - (void) strmov(end,"_init"); - tmp->func_init = dlsym(tmp->dlhandle, nm); - (void) strmov(end,"_deinit"); - tmp->func_deinit = dlsym(tmp->dlhandle, nm); + if (tmp->type == UDFTYPE_AGGREGATE) { - (void)strmov( end, "_clear" ); - tmp->func_clear = dlsym( tmp->dlhandle, nm ); - (void)strmov( end, "_add" ); - tmp->func_add = dlsym( tmp->dlhandle, nm ); - /* Give error if _clear and _add doesn't exists */ - if (!tmp->func_clear || ! tmp->func_add) - tmp->func= 0; + (void)strmov(end, "_reset"); + if (!((tmp->func_reset= dlsym(tmp->dlhandle, nm)))) + return nm; + (void)strmov(end, "_add"); + if (!((tmp->func_add= dlsym(tmp->dlhandle, nm)))) + return nm; } + + (void) strmov(end,"_deinit"); + tmp->func_deinit= dlsym(tmp->dlhandle, nm); + + (void) strmov(end,"_init"); + tmp->func_init= dlsym(tmp->dlhandle, nm); + + /* + to prefent loading "udf" from, e.g. libc.so + let's ensure that at least one auxiliary symbol is defined + */ + if (!tmp->func_init && !tmp->func_deinit && tmp->type != UDFTYPE_AGGREGATE) + { + if (opt_allow_suspicious_udfs) + sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), nm); + else + return nm; + } + + return 0; } extern "C" byte* get_hash_key(const byte *buff,uint *length, @@ -111,7 +128,7 @@ extern "C" byte* get_hash_key(const byte *buff,uint *length, } /* -** Read all predeclared functions from func@mysql and accept all that +** Read all predeclared functions from mysql.func and accept all that ** can be used. */ @@ -153,7 +170,7 @@ void udf_init() if (simple_open_n_lock_tables(new_thd, &tables)) { DBUG_PRINT("error",("Can't open udf table")); - sql_print_error("Can't open the mysql/func table. Please run the mysql_install_db script to create it."); + sql_print_error("Can't open the mysql.func table. Please run the mysql_install_db script to create it."); goto end; } @@ -171,10 +188,22 @@ void udf_init() if (table->fields >= 4) // New func table udftype=(Item_udftype) table->field[3]->val_int(); + /* + Ensure that the .dll doesn't have a path + This is done to ensure that only approved dll from the system + directories are used (to make this even remotely secure). + */ + if (strchr(dl_name, '/') || strlen(name) > NAME_LEN) + { + sql_print_error("Invalid row in mysql.func table for function '%.64s'", + name); + continue; + } + if (!(tmp = add_udf(&name,(Item_result) table->field[1]->val_int(), dl_name, udftype))) { - sql_print_error("Can't alloc memory for udf function: name"); + sql_print_error("Can't alloc memory for udf function: '%.64s'", name); continue; } @@ -191,13 +220,15 @@ void udf_init() new_dl=1; } tmp->dlhandle = dl; - init_syms(tmp); - if (!tmp->func) { - sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name); - del_udf(tmp); - if (new_dl) - dlclose(dl); + char buf[MAX_FIELD_NAME+16], *missing; + if ((missing= init_syms(tmp, buf))) + { + sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), missing); + del_udf(tmp); + if (new_dl) + dlclose(dl); + } } } if (error > 0) @@ -406,13 +437,15 @@ int mysql_create_function(THD *thd,udf_func *udf) new_dl=1; } udf->dlhandle=dl; - init_syms(udf); - - if (udf->func == NULL) { - net_printf(thd, ER_CANT_FIND_DL_ENTRY, udf->name); - goto err; + char buf[MAX_FIELD_NAME+16], *missing; + if ((missing= init_syms(udf, buf))) + { + net_printf(thd, ER_CANT_FIND_DL_ENTRY, missing); + goto err; + } } + udf->name.str=strdup_root(&mem,udf->name.str); udf->dl=strdup_root(&mem,udf->dl); if (!(u_d=add_udf(&udf->name,udf->returns,udf->dl,udf->type))) @@ -427,7 +460,7 @@ int mysql_create_function(THD *thd,udf_func *udf) u_d->func_clear=udf->func_clear; u_d->func_add=udf->func_add; - /* create entry in mysql/func table */ + /* create entry in mysql.func table */ bzero((char*) &tables,sizeof(tables)); tables.db= (char*) "mysql"; @@ -447,7 +480,7 @@ int mysql_create_function(THD *thd,udf_func *udf) close_thread_tables(thd); if (error) { - net_printf(thd, ER_ERROR_ON_WRITE, "func@mysql",error); + net_printf(thd, ER_ERROR_ON_WRITE, "mysql.func",error); del_udf(u_d); goto err; } diff --git a/sql/table.cc b/sql/table.cc index 064d7f1afc1..cdcd5148787 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1229,6 +1229,10 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo, uint key_length; ulong length; char fill[IO_SIZE]; + int create_flags= O_RDWR | O_TRUNC; + + if (create_info->options & HA_LEX_CREATE_TMP_TABLE) + create_flags|= O_EXCL | O_NOFOLLOW; #if SIZEOF_OFF_T > 4 /* Fix this when we have new .frm files; Current limit is 4G rows (QQ) */ @@ -1243,7 +1247,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo, */ set_if_smaller(create_info->raid_chunks, 255); - if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) + if ((file= my_create(name, CREATE_MODE, create_flags, MYF(MY_WME))) >= 0) { bzero((char*) fileinfo,64); fileinfo[0]=(uchar) 254; fileinfo[1]= 1; fileinfo[2]= FRM_VER+3; // Header From e286515667d3cd3028092ef5c1277dff75d2ee21 Mon Sep 17 00:00:00 2001 From: "jimw@mysql.com" <> Date: Thu, 31 Mar 2005 11:43:39 -0800 Subject: [PATCH 02/34] Fix segmentation fault in mysqlcheck when the last table checked with --auto-repair mode returned an error (such as being a merge table). (Bug #9492) --- client/mysqlcheck.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 8764611adf4..b5a80782948 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -537,6 +537,7 @@ static void print_result() my_bool found_error=0; res = mysql_use_result(sock); + prev[0] = '\0'; for (i = 0; (row = mysql_fetch_row(res)); i++) { @@ -565,7 +566,7 @@ static void print_result() putchar('\n'); } if (found_error && opt_auto_repair && what_to_do != DO_REPAIR && - (!opt_fast || strcmp(row[3],"OK"))) + !opt_fast) insert_dynamic(&tables4repair, prev); mysql_free_result(res); } From 62c83214d91b0698a6da7123a9166cff27381ede Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Thu, 31 Mar 2005 21:44:48 +0200 Subject: [PATCH 03/34] uninit variable fixed Originally contained in 2005/03/03 21:13:33+01:00 serg@serg.mylan; contained in MySQL 4.1.10a; re-committed for archival purposes. --- sql/ha_myisam.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 58fd67ddfa3..7ddb7ca25ed 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1334,7 +1334,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, HA_CREATE_INFO *info) { int error; - uint i,j,recpos,minpos,fieldpos,temp_length,length, create_flags; + uint i,j,recpos,minpos,fieldpos,temp_length,length, create_flags= 0; bool found_real_auto_increment=0; enum ha_base_keytype type; char buff[FN_REFLEN]; From 9db41fb08ee38bd3412a8ce2776d074b5b7c40e5 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Thu, 31 Mar 2005 21:47:18 +0200 Subject: [PATCH 04/34] typos fixed Originally contained in 2005/03/03 23:10:23+01:00 serg@serg.mylan; contained in MySQL 4.1.10a; re-committed for archival purposes. --- sql/mysqld.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6eaaed2800b..988482d00d2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4143,8 +4143,8 @@ struct my_option my_long_options[] = {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"allow-suspicious-udfs", OPT_ALLOW_SUSPICIOUS_UDFS, - "Allows to use UDF's consisting of only one symbol xxx() " - "without corresponing xxx_init() or xxx_deinit(). That also means " + "Allows use of UDFs consisting of only one symbol xxx() " + "without corresponding xxx_init() or xxx_deinit(). That also means " "that one can load any function from any library, for example exit() " "from libc.so", (gptr*) &opt_allow_suspicious_udfs, (gptr*) &opt_allow_suspicious_udfs, From ccd6fe786a5fc8875ffde66200921c2bc30865ee Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Thu, 31 Mar 2005 21:57:46 +0200 Subject: [PATCH 05/34] after merge fixes Originally contained in 2005/03/03 23:57:48+01:00 serg@serg.mylan; contained in MySQL 4.1.10a; re-committed for archival purposes. --- sql/sql_udf.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index ae89c1eaa35..d20fca86323 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -83,8 +83,8 @@ static char *init_syms(udf_func *tmp, char *nm) { char *end; - if (!((tmp->func= dlsym(tmp->dlhandle, tmp->name)))) - return tmp->name; + if (!((tmp->func= dlsym(tmp->dlhandle, tmp->name.str)))) + return tmp->name.str; end=strmov(nm,tmp->name.str); @@ -193,17 +193,17 @@ void udf_init() This is done to ensure that only approved dll from the system directories are used (to make this even remotely secure). */ - if (strchr(dl_name, '/') || strlen(name) > NAME_LEN) + if (strchr(dl_name, '/') || name.length > NAME_LEN) { sql_print_error("Invalid row in mysql.func table for function '%.64s'", - name); + name.str); continue; } if (!(tmp = add_udf(&name,(Item_result) table->field[1]->val_int(), dl_name, udftype))) { - sql_print_error("Can't alloc memory for udf function: '%.64s'", name); + sql_print_error("Can't alloc memory for udf function: '%.64s'", name.str); continue; } @@ -270,7 +270,7 @@ void udf_free() { initialized= 0; rwlock_destroy(&THR_LOCK_udf); - } + } DBUG_VOID_RETURN; } From e2a3d0da36b7f5d110ac2cbf3a6cd994c5c8f6a5 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Thu, 31 Mar 2005 22:02:05 +0200 Subject: [PATCH 06/34] Fix for a build bug. Added a missing comma. Originally contained in 2005/03/04 09:30:22+01:00 ingo@mysql.com; contained in MySQL 4.1.10a; re-committed for archival purposes. --- myisam/mi_create.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 2cadc86f452..a513f840965 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -547,7 +547,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, if (share.base.raid_type) { (void) fn_format(filename,name,"",MI_NAME_DEXT,2+4); - if ((dfile=my_raid_create(filename, 0, create_mode + if ((dfile=my_raid_create(filename, 0, create_mode, share.base.raid_type, share.base.raid_chunks, share.base.raid_chunksize, From 7f52a616f453219f7abfc3e13bbde748863068d7 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Fri, 1 Apr 2005 18:38:19 +0200 Subject: [PATCH 07/34] Last minor things to finish MySQL 4.1.10a: - some wordings, - RPM packaging improvements. --- configure.in | 2 +- scripts/mysql_create_system_tables.sh | 4 +--- sql/mysqld.cc | 4 ++-- sql/sql_udf.cc | 12 ++++++------ support-files/mysql.spec.sh | 10 ++++++++-- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/configure.in b/configure.in index 665029accb3..314283f6012 100644 --- a/configure.in +++ b/configure.in @@ -5,7 +5,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 4.1.10) +AM_INIT_AUTOMAKE(mysql, 4.1.10a) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index f524b322388..83fdc0639ce 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -163,9 +163,7 @@ then INSERT INTO user (host,user) values ('localhost','');" else i_u="$i_u - INSERT INTO user VALUES ('%','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - INSERT INTO user VALUES ('%','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0);" + INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);" fi fi fi diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 988482d00d2..1164506a0a7 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -284,12 +284,12 @@ my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol; my_bool opt_safe_user_create = 0, opt_no_mix_types = 0; my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0; my_bool opt_log_slave_updates= 0; +my_bool opt_allow_suspicious_udfs; my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam, opt_ndbcluster; #ifdef HAVE_NDBCLUSTER_DB const char *opt_ndbcluster_connectstring= 0; my_bool opt_ndb_shm, opt_ndb_optimized_node_selection; #endif -my_bool opt_allow_suspicious_udfs; my_bool opt_readonly, use_temp_pool, relay_log_purge; my_bool opt_sync_bdb_logs, opt_sync_frm; my_bool opt_secure_auth= 0; @@ -4143,7 +4143,7 @@ struct my_option my_long_options[] = {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"allow-suspicious-udfs", OPT_ALLOW_SUSPICIOUS_UDFS, - "Allows use of UDFs consisting of only one symbol xxx() " + "Allows to use UDFs consisting of only one symbol xxx() " "without corresponding xxx_init() or xxx_deinit(). That also means " "that one can load any function from any library, for example exit() " "from libc.so", diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index d20fca86323..05df069d69a 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -74,7 +74,7 @@ static HASH udf_hash; static rw_lock_t THR_LOCK_udf; -static udf_func *add_udf(char *name, Item_result ret, +static udf_func *add_udf(LEX_STRING *name, Item_result ret, char *dl, Item_udftype typ); static void del_udf(udf_func *udf); static void *find_udf_dl(const char *dl); @@ -90,8 +90,8 @@ static char *init_syms(udf_func *tmp, char *nm) if (tmp->type == UDFTYPE_AGGREGATE) { - (void)strmov(end, "_reset"); - if (!((tmp->func_reset= dlsym(tmp->dlhandle, nm)))) + (void)strmov(end, "_clear"); + if (!((tmp->func_clear= dlsym(tmp->dlhandle, nm)))) return nm; (void)strmov(end, "_add"); if (!((tmp->func_add= dlsym(tmp->dlhandle, nm)))) @@ -200,8 +200,9 @@ void udf_init() continue; } - if (!(tmp = add_udf(&name,(Item_result) table->field[1]->val_int(), - dl_name, udftype))) + + if (!(tmp= add_udf(&name,(Item_result) table->field[1]->val_int(), + dl_name, udftype))) { sql_print_error("Can't alloc memory for udf function: '%.64s'", name.str); continue; @@ -445,7 +446,6 @@ int mysql_create_function(THD *thd,udf_func *udf) goto err; } } - udf->name.str=strdup_root(&mem,udf->name.str); udf->dl=strdup_root(&mem,udf->dl); if (!(u_d=add_udf(&udf->name,udf->returns,udf->dl,udf->type))) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index b06ba462b26..07c8e6a46fb 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -276,7 +276,6 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \ --includedir=%{_includedir} \ --mandir=%{_mandir} \ --enable-thread-safe-client \ - --with-comment=\"Official MySQL RPM\" \ --with-readline ; # Add this for more debugging support # --with-debug @@ -333,6 +332,7 @@ BuildMySQL "--enable-shared \ --with-csv-storage-engine \ --with-example-storage-engine \ --with-embedded-server \ + --with-comment=\"MySQL Community Edition - Max (GPL)\" \ --with-server-suffix='-Max'" # Save everything for debug @@ -379,6 +379,7 @@ BuildMySQL "--disable-shared \ --with-client-ldflags='-all-static' \ $USE_OTHER_LIBC_DIR \ %endif + --with-comment=\"MySQL Community Edition - Standard (GPL)\" \ --with-server-suffix='%{server_suffix}' \ --without-embedded-server \ --without-berkeley-db \ @@ -694,7 +695,12 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog -* Monday Feb 7 2005 Tomas Ulin +* Mon Feb 14 2005 Lenz Grimmer + +* Fixed the compilation comments and moved them into the separate build sections + for Max and Standard + +* Mon Feb 7 2005 Tomas Ulin - enabled the "Ndbcluster" storage engine for the max binary - added extra make install in ndb subdir after Max build to get ndb binaries From d0c9b36224d1a81b83e1141f8af8ce8f464c3b8e Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Tue, 5 Apr 2005 02:42:23 +0400 Subject: [PATCH 08/34] Fix for BUG#8877: Implementation of "Early NULL-values filtering for ref access" (attempt2+post-review fixes) 1. update_ref_and_keys() accumulates info about null-rejecting predicates in in KEY_FIELD::null_rejecting, add_key_part saves these to KEYUSE. 2. create_ref_for_key copies them to TABLE_REF. 3. add_not_null_conds adds "x IS NOT NULL" to join_tab->select_cond of appropiate JOIN_TAB members. Includes code cleanups: * add_key_field() params: s/COND/Item_func/ (as only Item_funcs are passed to it) * add_key_fields() params: JOIN_TAB *stat removed (wasn't used) --- sql/sql_select.cc | 164 ++++++++++++++++++++++++++++++++++++++++++---- sql/sql_select.h | 10 +++ 2 files changed, 162 insertions(+), 12 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 57b09fa40b4..42c13b4c0f4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1995,6 +1995,11 @@ typedef struct key_field_t { // Used when finding key fields uint level; uint optimize; bool eq_func; + /* + If true, the condition this struct represents will not be satisfied + when val IS NULL. + */ + bool null_rejecting; } KEY_FIELD; /* Values in optimize */ @@ -2011,6 +2016,12 @@ typedef struct key_field_t { // Used when finding key fields that are internally transformed to something like: SELECT * FROM t1 WHERE t1.key=outer_ref_field or t1.key IS NULL + + KEY_FIELD::null_rejecting is processed as follows: + result has null_rejecting=true if it is set for both ORed references. + for example: + (t2.key = t1.field OR t2.key = t1.field) -> null_rejecting=true + (t2.key = t1.field OR t2.key <=> t1.field) -> null_rejecting=false */ static KEY_FIELD * @@ -2044,6 +2055,8 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, KEY_OPTIMIZE_EXISTS) | ((old->optimize | new_fields->optimize) & KEY_OPTIMIZE_REF_OR_NULL)); + old->null_rejecting= old->null_rejecting && + new_fields->null_rejecting; } } else if (old->eq_func && new_fields->eq_func && @@ -2055,6 +2068,8 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, KEY_OPTIMIZE_EXISTS) | ((old->optimize | new_fields->optimize) & KEY_OPTIMIZE_REF_OR_NULL)); + old->null_rejecting= old->null_rejecting && + new_fields->null_rejecting; } else if (old->eq_func && new_fields->eq_func && (old->val->is_null() || new_fields->val->is_null())) @@ -2065,6 +2080,8 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, /* Remember the NOT NULL value */ if (old->val->is_null()) old->val= new_fields->val; + /* The referred expression can be NULL: */ + old->null_rejecting= false; } else { @@ -2119,7 +2136,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, */ static void -add_key_field(KEY_FIELD **key_fields,uint and_level, COND *cond, +add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond, Field *field,bool eq_func,Item **value, uint num_values, table_map usable_tables) { @@ -2221,12 +2238,29 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, COND *cond, (*key_fields)->val= *value; (*key_fields)->level= and_level; (*key_fields)->optimize= exists_optimize; + /* + If the condition has form "tbl.keypart = othertbl.field" and + othertbl.field can be NULL, there will be no matches if othertbl.field + has NULL value. + */ + (*key_fields)->null_rejecting= (cond->functype() == Item_func::EQ_FUNC) && + ((*value)->type() == Item::FIELD_ITEM) && + ((Item_field*)*value)->field->maybe_null(); (*key_fields)++; } - +/* + SYNOPSIS + add_key_fields() + key_fields Add KEY_FIELD entries to this array (and move the + pointer) + and_level AND-level (a value that is different for every n-way + AND operation) + cond Condition to analyze + usable_tables Value to pass to add_key_field +*/ static void -add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, +add_key_fields(KEY_FIELD **key_fields,uint *and_level, COND *cond, table_map usable_tables) { if (cond->type() == Item_func::COND_ITEM) @@ -2238,20 +2272,20 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, { Item *item; while ((item=li++)) - add_key_fields(stat,key_fields,and_level,item,usable_tables); + add_key_fields(key_fields,and_level,item,usable_tables); for (; org_key_fields != *key_fields ; org_key_fields++) org_key_fields->level= *and_level; } else { (*and_level)++; - add_key_fields(stat,key_fields,and_level,li++,usable_tables); + add_key_fields(key_fields,and_level,li++,usable_tables); Item *item; while ((item=li++)) { KEY_FIELD *start_key_fields= *key_fields; (*and_level)++; - add_key_fields(stat,key_fields,and_level,item,usable_tables); + add_key_fields(key_fields,and_level,item,usable_tables); *key_fields=merge_key_fields(org_key_fields,start_key_fields, *key_fields,++(*and_level)); } @@ -2363,6 +2397,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field) keyuse.keypart_map= (key_part_map) 1 << part; keyuse.used_tables=key_field->val->used_tables(); keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL; + keyuse.null_rejecting= key_field->null_rejecting; VOID(insert_dynamic(keyuse_array,(gptr) &keyuse)); } } @@ -2456,8 +2491,22 @@ sort_keyuse(KEYUSE *a,KEYUSE *b) /* Update keyuse array with all possible keys we can use to fetch rows - join_tab is a array in tablenr_order - stat is a reference array in 'prefered' order. + + SYNOPSIS + update_ref_and_keys() + thd + keyuse OUT Put here ordered array of KEYUSE structures + join_tab Array in tablenr_order + tables Number of tables in join + cond WHERE condition (note that the function analyzes + join_tab[i]->on_expr too) + normal_tables tables not inner w.r.t some outer join (ones for which + we can make ref access based the WHERE clause) + select_lex current SELECT + + RETURN + 0 - OK + 1 - Out of memory. */ static bool @@ -2478,7 +2527,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, return TRUE; if (cond) { - add_key_fields(join_tab,&end,&and_level,cond,normal_tables); + add_key_fields(&end,&and_level,cond,normal_tables); for (; field != end ; field++) { add_key_part(keyuse,field); @@ -2492,7 +2541,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, { if (join_tab[i].on_expr) { - add_key_fields(join_tab,&end,&and_level,join_tab[i].on_expr, + add_key_fields(&end,&and_level,join_tab[i].on_expr, join_tab[i].table->map); } } @@ -3232,6 +3281,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, } j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length); j->ref.key_err=1; + j->ref.null_rejecting= 0; keyuse=org_keyuse; store_key **ref_key= j->ref.key_copy; @@ -3256,6 +3306,8 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, uint maybe_null= test(keyinfo->key_part[i].null_bit); j->ref.items[i]=keyuse->val; // Save for cond removal + if (keyuse->null_rejecting) + j->ref.null_rejecting |= 1 << i; keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables; if (!keyuse->used_tables && !(join->select_options & SELECT_DESCRIBE)) @@ -3410,12 +3462,99 @@ make_simple_join(JOIN *join,TABLE *tmp_table) } +inline void add_cond_and_fix(Item **e1, Item *e2) +{ + if (*e1) + { + Item *res; + if ((res= new Item_cond_and(*e1, e2))) + { + *e1= res; + res->quick_fix_field(); + } + } + else + *e1= e2; +} + + +/* + Add to join_tab->select_cond[i] "table.field IS NOT NULL" conditions we've + inferred from ref/eq_ref access performed. + + SYNOPSIS + add_not_null_conds() + join Join to process + + NOTES + This function is a part of "Early NULL-values filtering for ref access" + optimization. + + Example of this optimization: + For query SELECT * FROM t1,t2 WHERE t2.key=t1.field + and plan " any-access(t1), ref(t2.key=t1.field) " + add "t1.field IS NOT NULL" to t1's table condition. + Description of the optimization: + + We look through equalities choosen to perform ref/eq_ref access, + pick equalities that have form "tbl.part_of_key = othertbl.field" + (where othertbl is a non-const table and othertbl.field may be NULL) + and add them to conditions on correspoding tables (othertbl in this + example). + + This optimization doesn't affect the choices that ref, range, or join + optimizer make. This was intentional because this was added after 4.1 + was GA. + + Implementation overview + 1. update_ref_and_keys() accumulates info about null-rejecting + predicates in in KEY_FIELD::null_rejecting + 1.1 add_key_part saves these to KEYUSE. + 2. create_ref_for_key copies them to TABLE_REF. + 3. add_not_null_conds adds "x IS NOT NULL" to join_tab->select_cond of + appropiate JOIN_TAB members. +*/ + +static void add_not_null_conds(JOIN *join) +{ + DBUG_ENTER("add_not_null_conds"); + for (uint i=join->const_tables ; i < join->tables ; i++) + { + JOIN_TAB *tab=join->join_tab+i; + if ((tab->type == JT_REF || tab->type == JT_REF_OR_NULL) && + !tab->table->maybe_null) + { + for (uint keypart= 0; keypart < tab->ref.key_parts; keypart++) + { + if (tab->ref.null_rejecting & (1 << keypart)) + { + Item *item= tab->ref.items[keypart]; + DBUG_ASSERT(item->type() == Item::FIELD_ITEM); + Item_field *not_null_item= (Item_field*)item; + JOIN_TAB *referred_tab= not_null_item->field->table->reginfo.join_tab; + Item_func_isnotnull *null_rej; + if (!(null_rej= new Item_func_isnotnull(not_null_item))) + DBUG_VOID_RETURN; + + null_rej->quick_fix_field(); + //psergey-todo: Flatten AND's + DBUG_EXECUTE("where",print_where(null_rej, + referred_tab->table->table_name);); + add_cond_and_fix(&referred_tab->select_cond, null_rej); + } + } + } + } + DBUG_VOID_RETURN; +} + static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) { DBUG_ENTER("make_join_select"); if (select) { + add_not_null_conds(join); table_map used_tables; if (join->tables > 1) cond->update_used_tables(); // Tablenr may have changed @@ -3472,13 +3611,14 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) } if (tmp) { - DBUG_EXECUTE("where",print_where(tmp,tab->table->table_name);); SQL_SELECT *sel=tab->select=(SQL_SELECT*) join->thd->memdup((gptr) select, sizeof(SQL_SELECT)); if (!sel) DBUG_RETURN(1); // End of memory - tab->select_cond=sel->cond=tmp; + add_cond_and_fix(&tab->select_cond, tmp); + sel->cond= tab->select_cond; sel->head=tab->table; + DBUG_EXECUTE("where",print_where(tmp,tab->table->table_name);); if (tab->quick) { /* Use quick key read if it's a constant and it's not used diff --git a/sql/sql_select.h b/sql/sql_select.h index 4ea7e1b23e7..ab3b442ef74 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -31,6 +31,11 @@ typedef struct keyuse_t { uint key, keypart, optimize; key_part_map keypart_map; ha_rows ref_table_rows; + /* + If true, the comparison this value was created from will not be + satisfied if val has NULL 'value'. + */ + bool null_rejecting; } KEYUSE; class store_key; @@ -45,6 +50,11 @@ typedef struct st_table_ref byte *key_buff2; // key_buff+key_length store_key **key_copy; // Item **items; // val()'s for each keypart + /* + (null_rejecting & (1<table->table_name);); add_cond_and_fix(&referred_tab->select_cond, null_rej); From 9db39659242d089f948d934356f4428f84b65977 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Tue, 5 Apr 2005 11:35:03 +0300 Subject: [PATCH 10/34] dict0dict.c: Add a note that ENUM in new tables cannot reference ENUM in old tables, in FOREIGN KEY constraints --- innobase/dict/dict0dict.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 2bceb432aa6..cb48c86c541 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -3285,6 +3285,9 @@ try_find_index: "Cannot find an index in the referenced table where the\n" "referenced columns appear as the first columns, or column types\n" "in the table and the referenced table do not match for constraint.\n" +"Note that the internal storage type of ENUM and SET changed in\n" +"tables created with >= InnoDB-4.1.12, and such columns in old tables\n" +"cannot be referenced by such columns in new tables.\n" "See http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n" "for correct foreign key definition.\n", start_of_latest_foreign); From 6ed11e3bb3fe3f720433965b4ebf02eddaf18258 Mon Sep 17 00:00:00 2001 From: "jani@ua141d10.elisa.omakaista.fi" <> Date: Tue, 5 Apr 2005 13:15:04 +0300 Subject: [PATCH 11/34] A fix for Netware. --- mysys/my_rename.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/my_rename.c b/mysys/my_rename.c index d4f99e83247..b5d813ad787 100644 --- a/mysys/my_rename.c +++ b/mysys/my_rename.c @@ -45,7 +45,7 @@ int my_rename(const char *from, const char *to, myf MyFlags) } #endif #if defined(HAVE_RENAME) -#ifdef __WIN__ +#if defined(__WIN__) || defined(__NETWARE__) /* On windows we can't rename over an existing file: Remove any conflicting files: From 114b421c8bd552bc92296073b27a21691c0ce6da Mon Sep 17 00:00:00 2001 From: "pekka@mysql.com" <> Date: Tue, 5 Apr 2005 13:14:03 +0200 Subject: [PATCH 12/34] ndb - csc#4847 release scan op early to save memory --- ndb/include/ndbapi/NdbConnection.hpp | 1 + ndb/include/ndbapi/NdbScanOperation.hpp | 2 +- ndb/src/ndbapi/NdbConnection.cpp | 31 +++++++++++++++++++++++++ ndb/src/ndbapi/NdbResultSet.cpp | 2 +- ndb/src/ndbapi/NdbScanOperation.cpp | 21 +++++++++++------ ndb/tools/desc.cpp | 2 +- 6 files changed, 49 insertions(+), 10 deletions(-) diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp index 3a9f18665e9..2ab6f7d6f64 100644 --- a/ndb/include/ndbapi/NdbConnection.hpp +++ b/ndb/include/ndbapi/NdbConnection.hpp @@ -542,6 +542,7 @@ private: // Release all cursor operations in connection void releaseOps(NdbOperation*); void releaseScanOperations(NdbIndexScanOperation*); + void releaseExecutedScanOperation(NdbIndexScanOperation*); // Set the transaction identity of the transaction void setTransactionId(Uint64 aTransactionId); diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp index f25f9405033..f6e68dd4abe 100644 --- a/ndb/include/ndbapi/NdbScanOperation.hpp +++ b/ndb/include/ndbapi/NdbScanOperation.hpp @@ -93,7 +93,7 @@ protected: int nextResult(bool fetchAllowed = true, bool forceSend = false); virtual void release(); - void closeScan(bool forceSend = false); + void closeScan(bool forceSend = false, bool releaseOp = false); int close_impl(class TransporterFacade*, bool forceSend = false); // Overloaded methods from NdbCursorOperation diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp index 0a1c7303771..e1f70160fb7 100644 --- a/ndb/src/ndbapi/NdbConnection.cpp +++ b/ndb/src/ndbapi/NdbConnection.cpp @@ -963,6 +963,37 @@ NdbConnection::releaseScanOperations(NdbIndexScanOperation* cursorOp) } }//NdbConnection::releaseScanOperations() +/***************************************************************************** +void releaseExecutedScanOperation(); + +Remark: Release scan op when hupp'ed trans closed (save memory) +******************************************************************************/ +void +NdbConnection::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp) +{ + DBUG_ENTER("NdbConnection::releaseExecutedScanOperation"); + DBUG_PRINT("enter", ("this=0x%x op=0x%x", (UintPtr)this, (UintPtr)cursorOp)) + + // here is one reason to make op lists doubly linked + if (m_firstExecutedScanOp == cursorOp) { + m_firstExecutedScanOp = (NdbIndexScanOperation*)cursorOp->theNext; + cursorOp->release(); + theNdb->releaseScanOperation(cursorOp); + } else if (m_firstExecutedScanOp != NULL) { + NdbIndexScanOperation* tOp = m_firstExecutedScanOp; + while (tOp->theNext != NULL) { + if (tOp->theNext == cursorOp) { + tOp->theNext = cursorOp->theNext; + cursorOp->release(); + theNdb->releaseScanOperation(cursorOp); + break; + } + tOp = (NdbIndexScanOperation*)tOp->theNext; + } + } + DBUG_VOID_RETURN; +}//NdbConnection::releaseExecutedScanOperation() + /***************************************************************************** NdbOperation* getNdbOperation(const char* aTableName); diff --git a/ndb/src/ndbapi/NdbResultSet.cpp b/ndb/src/ndbapi/NdbResultSet.cpp index d9d71464026..87b304126ba 100644 --- a/ndb/src/ndbapi/NdbResultSet.cpp +++ b/ndb/src/ndbapi/NdbResultSet.cpp @@ -69,7 +69,7 @@ int NdbResultSet::nextResult(bool fetchAllowed, bool forceSend) void NdbResultSet::close(bool forceSend) { - m_operation->closeScan(forceSend); + m_operation->closeScan(forceSend, true); } NdbOperation* diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index 670a18f72a0..fc5a22cce17 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -674,7 +674,7 @@ NdbScanOperation::doSend(int ProcessorId) return 0; } -void NdbScanOperation::closeScan(bool forceSend) +void NdbScanOperation::closeScan(bool forceSend, bool releaseOp) { if(m_transConnection){ if(DEBUG_NEXT_RESULT) @@ -691,13 +691,20 @@ void NdbScanOperation::closeScan(bool forceSend) Guard guard(tp->theMutexPtr); close_impl(tp, forceSend); - } while(0); - - theNdbCon->theScanningOp = 0; - theNdb->closeTransaction(theNdbCon); - - theNdbCon = 0; + } + + NdbConnection* tCon = theNdbCon; + NdbConnection* tTransCon = m_transConnection; + theNdbCon = NULL; m_transConnection = NULL; + + if (releaseOp && tTransCon) { + NdbIndexScanOperation* tOp = (NdbIndexScanOperation*)this; + tTransCon->releaseExecutedScanOperation(tOp); + } + + tCon->theScanningOp = 0; + theNdb->closeTransaction(tCon); } void diff --git a/ndb/tools/desc.cpp b/ndb/tools/desc.cpp index 4287a771694..aac47c9042c 100644 --- a/ndb/tools/desc.cpp +++ b/ndb/tools/desc.cpp @@ -89,7 +89,7 @@ int main(int argc, char** argv){ unsigned j; for (j= 0; (int)j < pTab->getNoOfPrimaryKeys(); j++) { - const NdbDictionary::Column * col = pTab->getColumn(j); + const NdbDictionary::Column * col = pTab->getColumn(pTab->getPrimaryKey(j)); ndbout << col->getName(); if ((int)j < pTab->getNoOfPrimaryKeys()-1) ndbout << ", "; From 3c3defaa0a50ef6a21c803bd9145473890a92967 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Tue, 5 Apr 2005 15:16:15 +0200 Subject: [PATCH 13/34] add changeset key to the bk commit mail --- BitKeeper/triggers/post-commit | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index d2a4f9153b2..4c28b408658 100755 --- a/BitKeeper/triggers/post-commit +++ b/BitKeeper/triggers/post-commit @@ -27,6 +27,7 @@ then fi CHANGESET=`bk -R prs -r+ -h -d':P:::I:' ChangeSet` +CSETKEY=`bk -R prs -r+ -h -d':KEY:' ChangeSet` BUG=`bk -R prs -r+ -h -d':C:' ChangeSet | sed -ne 's/^.*[Bb][Uu][Gg] *# *\([0-9][0-9]*\).*$/\1/p'` if [ "$BUG" = "" ] @@ -51,6 +52,7 @@ List-ID: From: $FROM To: $TO Subject: bk commit - $VERSION tree ($CHANGESET)$BS +X-CSetKey: <$CSETKEY> $BH EOF bk changes -v -r+ @@ -67,6 +69,7 @@ List-ID: From: $FROM To: $INTERNALS Subject: bk commit into $VERSION tree ($CHANGESET)$BS +X-CSetKey: <$CSETKEY> $BH Below is the list of changes that have just been committed into a local $VERSION repository of $USER. When $USER does a push these changes will From 42277bdd2fa842f281abdc9a6292d8be92d490d8 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Tue, 5 Apr 2005 18:42:34 +0200 Subject: [PATCH 14/34] Per Heikki's request make trans_register_ha tolerant to multiple registrations --- sql/handler.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 3eead37482b..96fe3937198 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -505,10 +505,16 @@ void ha_close_connection(THD* thd) "beginning of transaction" and "beginning of statement"). Only storage engines registered for the transaction/statement will know when to commit/rollback it. + + NOTE + trans_register_ha is idempotent - storage engine may register many + times per transaction. + */ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg) { THD_TRANS *trans; + handlerton **ht; DBUG_ENTER("trans_register_ha"); DBUG_PRINT("enter",("%s", all ? "all" : "stmt")); @@ -520,15 +526,12 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg) else trans= &thd->transaction.stmt; -#ifndef DBUG_OFF - handlerton **ht=trans->ht; - while (*ht) - { - DBUG_ASSERT(*ht != ht_arg); - ht++; - } -#endif + for (ht=trans->ht; *ht; ht++) + if (*ht == ht_arg) + DBUG_VOID_RETURN; + trans->ht[trans->nht++]=ht_arg; + DBUG_ASSERT(*ht == ht_arg); trans->no_2pc|=(ht_arg->prepare==0); if (thd->transaction.xid.is_null()) thd->transaction.xid.set(thd->query_id); From 0134a2b286e8402932207e9f2c402c28448568bc Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Wed, 6 Apr 2005 11:53:15 +0500 Subject: [PATCH 15/34] Adding a new parameter for well_formed_length to return error. We'll use it for better warnign reporting. --- include/m_ctype.h | 9 ++++++--- ndb/src/ndbapi/NdbIndexOperation.cpp | 4 +++- ndb/src/ndbapi/NdbOperationDefine.cpp | 4 +++- ndb/src/ndbapi/NdbOperationSearch.cpp | 4 +++- sql/field.cc | 15 ++++++++------- sql/sql_yacc.yy | 3 ++- strings/ctype-big5.c | 6 +++++- strings/ctype-mb.c | 9 ++++++--- strings/ctype-simple.c | 6 +++--- strings/ctype-sjis.c | 5 ++++- strings/ctype-ucs2.c | 6 +++--- strings/ctype-ujis.c | 13 +++++++++++-- 12 files changed, 57 insertions(+), 27 deletions(-) diff --git a/include/m_ctype.h b/include/m_ctype.h index 26e285b9683..aab39156de1 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -147,7 +147,8 @@ typedef struct my_charset_handler_st uint (*numchars)(struct charset_info_st *, const char *b, const char *e); uint (*charpos)(struct charset_info_st *, const char *b, const char *e, uint pos); uint (*well_formed_len)(struct charset_info_st *, - const char *b,const char *e, uint nchars); + const char *b,const char *e, + uint nchars, int *error); uint (*lengthsp)(struct charset_info_st *, const char *ptr, uint length); uint (*numcells)(struct charset_info_st *, const char *b, const char *e); @@ -341,7 +342,8 @@ int my_wildcmp_8bit(CHARSET_INFO *, uint my_numchars_8bit(CHARSET_INFO *, const char *b, const char *e); uint my_numcells_8bit(CHARSET_INFO *, const char *b, const char *e); uint my_charpos_8bit(CHARSET_INFO *, const char *b, const char *e, uint pos); -uint my_well_formed_len_8bit(CHARSET_INFO *, const char *b, const char *e, uint pos); +uint my_well_formed_len_8bit(CHARSET_INFO *, const char *b, const char *e, + uint pos, int *error); int my_mbcharlen_8bit(CHARSET_INFO *, uint c); @@ -359,7 +361,8 @@ int my_wildcmp_mb(CHARSET_INFO *, uint my_numchars_mb(CHARSET_INFO *, const char *b, const char *e); uint my_numcells_mb(CHARSET_INFO *, const char *b, const char *e); uint my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, uint pos); -uint my_well_formed_len_mb(CHARSET_INFO *, const char *b, const char *e, uint pos); +uint my_well_formed_len_mb(CHARSET_INFO *, const char *b, const char *e, + uint pos, int *error); uint my_instr_mb(struct charset_info_st *, const char *b, uint b_length, const char *s, uint s_length, diff --git a/ndb/src/ndbapi/NdbIndexOperation.cpp b/ndb/src/ndbapi/NdbIndexOperation.cpp index 23af646c4c7..39da9c5f5d0 100644 --- a/ndb/src/ndbapi/NdbIndexOperation.cpp +++ b/ndb/src/ndbapi/NdbIndexOperation.cpp @@ -354,12 +354,14 @@ int NdbIndexOperation::equal_impl(const NdbColumnImpl* tAttrInfo, *************************************************************************/ if ((tOpType == WriteRequest)) { if (!tAttrInfo->m_indexOnly){ + int dummy_error; // invalid data can crash kernel if (cs != NULL && (*cs->cset->well_formed_len)(cs, aValueToWrite, aValueToWrite + sizeInBytes, - sizeInBytes) != sizeInBytes) + sizeInBytes, + &dummy_error) != sizeInBytes) goto equal_error4; Uint32 ahValue; Uint32 sz = totalSizeInWords; diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp index c4aaffb3119..dfc54133e6c 100644 --- a/ndb/src/ndbapi/NdbOperationDefine.cpp +++ b/ndb/src/ndbapi/NdbOperationDefine.cpp @@ -526,6 +526,7 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo, const Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize; CHARSET_INFO* cs = tAttrInfo->m_cs; + int dummy_error; // invalid data can crash kernel if (cs != NULL && // fast fix bug#7340 @@ -533,7 +534,8 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo, (*cs->cset->well_formed_len)(cs, aValue, aValue + sizeInBytes, - sizeInBytes) != sizeInBytes) { + sizeInBytes, + &dummy_error) != sizeInBytes) { setErrorCodeAbort(744); return -1; } diff --git a/ndb/src/ndbapi/NdbOperationSearch.cpp b/ndb/src/ndbapi/NdbOperationSearch.cpp index 28a70abcb9b..97b2393e5ed 100644 --- a/ndb/src/ndbapi/NdbOperationSearch.cpp +++ b/ndb/src/ndbapi/NdbOperationSearch.cpp @@ -226,12 +226,14 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo, if ((tOpType == InsertRequest) || (tOpType == WriteRequest)) { if (!tAttrInfo->m_indexOnly){ + int dummy_error; // invalid data can crash kernel if (cs != NULL && (*cs->cset->well_formed_len)(cs, aValueToWrite, aValueToWrite + sizeInBytes, - sizeInBytes) != sizeInBytes) + sizeInBytes, + &dummy_error) != sizeInBytes) goto equal_error4; Uint32 ahValue; const Uint32 sz = totalSizeInWords; diff --git a/sql/field.cc b/sql/field.cc index bf581e62f34..740c027350d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4939,9 +4939,10 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) as well as don't copy a malformed data. */ copy_length= field_charset->cset->well_formed_len(field_charset, - from,from+length, - field_length/ - field_charset->mbmaxlen); + from,from+length, + field_length/ + field_charset->mbmaxlen, + &error); memcpy(ptr,from,copy_length); if (copy_length < field_length) // Append spaces if shorter field_charset->cset->fill(field_charset,ptr+copy_length, @@ -4958,7 +4959,6 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) } if (error) set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); - return error; } @@ -5577,9 +5577,10 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) the 'min()' call below. */ copy_length= field_charset->cset->well_formed_len(field_charset, - from,from + - min(length, copy_length), - copy_length); + from,from + + min(length, copy_length), + copy_length, + &error); if (copy_length < length) error= 1; Field_blob::store_length(copy_length); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9f25e17b6fd..dcda19a7080 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5032,9 +5032,10 @@ IDENT_sys: if (thd->charset_is_system_charset) { CHARSET_INFO *cs= system_charset_info; + int dummy_error; uint wlen= cs->cset->well_formed_len(cs, $1.str, $1.str+$1.length, - $1.length); + $1.length, &dummy_error); if (wlen < $1.length) { net_printf(YYTHD, ER_INVALID_CHARACTER_STRING, cs->csname, diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index e083d1371ec..07b30205f89 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6278,10 +6278,13 @@ my_mb_wc_big5(CHARSET_INFO *cs __attribute__((unused)), */ static uint my_well_formed_len_big5(CHARSET_INFO *cs __attribute__((unused)), - const char *b, const char *e, uint pos) + const char *b, const char *e, + uint pos, int *error) { const char *b0= b; const char *emb= e - 1; /* Last possible end of an MB character */ + + *error= 0; while (pos && b < e) { if ((uchar) b[0] < 128) @@ -6297,6 +6300,7 @@ uint my_well_formed_len_big5(CHARSET_INFO *cs __attribute__((unused)), else { /* Wrong byte sequence */ + *error= 1; break; } } diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 6cf48291c91..dbe3a24324e 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -264,18 +264,21 @@ uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)), } -uint my_well_formed_len_mb(CHARSET_INFO *cs, - const char *b, const char *e, uint pos) +uint my_well_formed_len_mb(CHARSET_INFO *cs, const char *b, const char *e, + uint pos, int *error) { const char *b_start= b; - + *error= 0; while (pos) { my_wc_t wc; int mblen; if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) b, (uchar*) e)) <= 0) + { + *error= 1; break; + } b+= mblen; pos--; } diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 080e0b780b7..bd5131b7448 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -1093,11 +1093,11 @@ uint my_charpos_8bit(CHARSET_INFO *cs __attribute__((unused)), uint my_well_formed_len_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *start, - const char *end, - uint nchars) + const char *start, const char *end, + uint nchars, int *error) { uint nbytes= (uint) (end-start); + *error= 0; return min(nbytes, nchars); } diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 20f0081888f..35182db3345 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4571,9 +4571,11 @@ uint my_numcells_sjis(CHARSET_INFO *cs __attribute__((unused)), */ static uint my_well_formed_len_sjis(CHARSET_INFO *cs __attribute__((unused)), - const char *b, const char *e, uint pos) + const char *b, const char *e, + uint pos, int *error) { const char *b0= b; + *error= 0; while (pos && b < e) { if ((uchar) b[0] < 128) @@ -4594,6 +4596,7 @@ uint my_well_formed_len_sjis(CHARSET_INFO *cs __attribute__((unused)), else { /* Wrong byte sequence */ + *error= 1; break; } } diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 9c67d1b7846..f5d0721fa9b 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1267,11 +1267,11 @@ uint my_charpos_ucs2(CHARSET_INFO *cs __attribute__((unused)), static uint my_well_formed_len_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *b, - const char *e, - uint nchars) + const char *b, const char *e, + uint nchars, int *error) { uint nbytes= (e-b) & ~ (uint)1; + *error= 0; nchars*= 2; return min(nbytes, nchars); } diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index fc1496df280..612dda2b3eb 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8253,11 +8253,12 @@ my_jisx0212_uni_onechar(int code){ static uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)), - const char *beg, const char *end, uint pos) + const char *beg, const char *end, + uint pos, int *error) { const uchar *b= (uchar *) beg; - for ( ; pos && b < (uchar*) end; pos--, b++) + for ( *error= 0 ; pos && b < (uchar*) end; pos--, b++) { char *chbeg; uint ch= *b; @@ -8267,12 +8268,16 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)), chbeg= (char *) b++; if (b >= (uchar *) end) /* need more bytes */ + { + *error= 1; return chbeg - beg; /* unexpected EOL */ + } if (ch == 0x8E) /* [x8E][xA0-xDF] */ { if (*b >= 0xA0 && *b <= 0xDF) continue; + *error= 1; return chbeg - beg; /* invalid sequence */ } @@ -8280,12 +8285,16 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)), { ch= *b++; if (b >= (uchar*) end) + { + *error= 1; return chbeg - beg; /* unexpected EOL */ + } } if (ch >= 0xA1 && ch <= 0xFE && *b >= 0xA1 && *b <= 0xFE) /* [xA1-xFE][xA1-xFE] */ continue; + *error= 1; return chbeg - beg; /* invalid sequence */ } return b - (uchar *) beg; From 0c2caeb4d82f49dd109a0495ead6242953e8b053 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Wed, 6 Apr 2005 10:27:40 +0300 Subject: [PATCH 16/34] row0sel.c, btr0pcur.c, btr0pcur.ic, btr0pcur.h: Add diagnostic code to track assertion failure in ut_a(cursor->old_stored == BTR_PCUR_OLD_STORED); the failure happened in OPTIMIZE TABLE, and in 4.0.24 in some other context --- innobase/btr/btr0pcur.c | 10 +++++++++- innobase/include/btr0pcur.h | 4 ++++ innobase/include/btr0pcur.ic | 10 ++++++++++ innobase/row/row0sel.c | 4 ++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c index cf8a612ef28..0dcf6c2f3fc 100644 --- a/innobase/btr/btr0pcur.c +++ b/innobase/btr/btr0pcur.c @@ -14,6 +14,7 @@ Created 2/23/1996 Heikki Tuuri #include "ut0byte.h" #include "rem0cmp.h" +#include "trx0trx.h" /****************************************************************** Allocates memory for a persistent cursor object and initializes the cursor. */ @@ -203,7 +204,14 @@ btr_pcur_restore_position( ut_a(cursor->pos_state == BTR_PCUR_WAS_POSITIONED || cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_a(cursor->old_stored == BTR_PCUR_OLD_STORED); + if (cursor->old_stored != BTR_PCUR_OLD_STORED) { + ut_print_buf(stderr, (const byte*)cursor, sizeof(btr_pcur_t)); + if (cursor->trx_if_known) { + trx_print(stderr, cursor->trx_if_known); + } + + ut_a(0); + } if (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) { diff --git a/innobase/include/btr0pcur.h b/innobase/include/btr0pcur.h index 81f19af4d40..9339eb5d0ee 100644 --- a/innobase/include/btr0pcur.h +++ b/innobase/include/btr0pcur.h @@ -477,6 +477,10 @@ struct btr_pcur_struct{ BTR_PCUR_WAS_POSITIONED, BTR_PCUR_NOT_POSITIONED */ ulint search_mode; /* PAGE_CUR_G, ... */ + trx_t* trx_if_known; /* the transaction, if we know it; + otherwise this field is not defined; + can ONLY BE USED in error prints in + fatal assertion failures! */ /*-----------------------------*/ /* NOTE that the following fields may possess dynamically allocated memory which should be freed if not needed anymore! */ diff --git a/innobase/include/btr0pcur.ic b/innobase/include/btr0pcur.ic index b553a569bda..9a7d7867025 100644 --- a/innobase/include/btr0pcur.ic +++ b/innobase/include/btr0pcur.ic @@ -493,6 +493,8 @@ btr_pcur_open( btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode, btr_cursor, 0, mtr); cursor->pos_state = BTR_PCUR_IS_POSITIONED; + + cursor->trx_if_known = NULL; } /****************************************************************** @@ -535,6 +537,8 @@ btr_pcur_open_with_no_init( cursor->pos_state = BTR_PCUR_IS_POSITIONED; cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; + + cursor->trx_if_known = NULL; } /********************************************************************* @@ -568,6 +572,8 @@ btr_pcur_open_at_index_side( pcur->pos_state = BTR_PCUR_IS_POSITIONED; pcur->old_stored = BTR_PCUR_OLD_NOT_STORED; + + pcur->trx_if_known = NULL; } /************************************************************************** @@ -592,6 +598,8 @@ btr_pcur_open_at_rnd_pos( btr_pcur_get_btr_cur(cursor), mtr); cursor->pos_state = BTR_PCUR_IS_POSITIONED; cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; + + cursor->trx_if_known = NULL; } /****************************************************************** @@ -617,4 +625,6 @@ btr_pcur_close( cursor->latch_mode = BTR_NO_LATCHES; cursor->pos_state = BTR_PCUR_NOT_POSITIONED; + + cursor->trx_if_known = NULL; } diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 07140e74e54..eb88ac31ba9 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2507,6 +2507,8 @@ row_sel_get_clust_rec_for_mysql( clust_rec = btr_pcur_get_rec(prebuilt->clust_pcur); + prebuilt->clust_pcur->trx_if_known = trx; + /* Note: only if the search ends up on a non-infimum record is the low_match value the real match to the search tuple */ @@ -3222,6 +3224,8 @@ shortcut_fails_too_big_rec: btr_pcur_open_with_no_init(index, search_tuple, mode, BTR_SEARCH_LEAF, pcur, 0, &mtr); + + pcur->trx_if_known = trx; } else { if (mode == PAGE_CUR_G) { btr_pcur_open_at_index_side(TRUE, index, From 6f18d7d26f0a8348dd6599f2994dd20ddf19679c Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Wed, 6 Apr 2005 14:13:06 +0500 Subject: [PATCH 17/34] Fix for bug #9286: SESSION/GLOBAL should be disallowed for user variables --- BitKeeper/etc/logging_ok | 1 + mysql-test/r/user_var.result | 4 +++ mysql-test/t/user_var.test | 8 +++++ sql/sql_yacc.yy | 66 +++++++++++++++++++++--------------- 4 files changed, 52 insertions(+), 27 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 90e6c3c100d..9237eea21c4 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -51,6 +51,7 @@ georg@lmy002.wdf.sap.corp gerberb@ou800.zenez.com gluh@gluh.(none) gluh@gluh.mysql.r18.ru +gluh@mysql.com gordon@zero.local.lan greg@gcw.ath.cx greg@mysql.com diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 9edeea404ec..e42849abdf1 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -175,3 +175,7 @@ set @v1=null, @v2=1, @v3=1.1, @v4=now(); select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4); coercibility(@v1) coercibility(@v2) coercibility(@v3) coercibility(@v4) 2 2 2 2 +set session @honk=99; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@honk=99' at line 1 +set one_shot @honk=99; +ERROR HY000: The SET ONE_SHOT syntax is reserved for purposes internal to the MySQL server diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index b907f21056c..a288b7ef708 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -111,3 +111,11 @@ select FIELD( @var,'1it','Hit') as my_column; select @v, coercibility(@v); set @v1=null, @v2=1, @v3=1.1, @v4=now(); select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4); + +# +# Bug #9286 SESSION/GLOBAL should be disallowed for user variables +# +--error 1064 +set session @honk=99; +--error 1105 +set one_shot @honk=99; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9f25e17b6fd..4a23a393fa9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5360,17 +5360,26 @@ opt_option: | OPTION {}; option_value_list: - option_type option_value - | option_value_list ',' option_type option_value; + option_value_ext + | option_value_list ',' option_value_ext; -option_type: - /* empty */ {} +option_value_ext: + option_type_ext sys_option_value {} + | option_type option_value {} + ; + +option_type_ext: + option_type {} | GLOBAL_SYM { Lex->option_type= OPT_GLOBAL; } | LOCAL_SYM { Lex->option_type= OPT_SESSION; } | SESSION_SYM { Lex->option_type= OPT_SESSION; } - | ONE_SHOT_SYM { Lex->option_type= OPT_SESSION; Lex->one_shot_set= 1; } ; +option_type: + /* empty */ {} + | ONE_SHOT_SYM { Lex->option_type= OPT_SESSION; Lex->one_shot_set= 1; } + ; + opt_var_type: /* empty */ { $$=OPT_SESSION; } | GLOBAL_SYM { $$=OPT_GLOBAL; } @@ -5385,34 +5394,37 @@ opt_var_ident_type: | SESSION_SYM '.' { $$=OPT_SESSION; } ; +sys_option_value: + internal_variable_name equal set_expr_or_default + { + LEX *lex=Lex; + lex->var_list.push_back(new set_var(lex->option_type, $1.var, + &$1.base_name, $3)); + } + | TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types + { + LEX *lex=Lex; + LEX_STRING tmp; + tmp.str=0; + tmp.length=0; + lex->var_list.push_back(new set_var(lex->option_type, + find_sys_var("tx_isolation"), + &tmp, + new Item_int((int32) $4))); + } + ; + option_value: '@' ident_or_text equal expr { Lex->var_list.push_back(new set_var_user(new Item_func_set_user_var($2,$4))); } - | internal_variable_name equal set_expr_or_default - { - LEX *lex=Lex; - lex->var_list.push_back(new set_var(lex->option_type, $1.var, - &$1.base_name, $3)); - } | '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default - { - LEX *lex=Lex; - lex->var_list.push_back(new set_var((enum_var_type) $3, $4.var, - &$4.base_name, $6)); - } - | TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types - { - LEX *lex=Lex; - LEX_STRING tmp; - tmp.str=0; - tmp.length=0; - lex->var_list.push_back(new set_var(lex->option_type, - find_sys_var("tx_isolation"), - &tmp, - new Item_int((int32) $4))); - } + { + LEX *lex=Lex; + lex->var_list.push_back(new set_var((enum_var_type) $3, $4.var, + &$4.base_name, $6)); + } | charset old_or_new_charset_name_or_default { THD *thd= YYTHD; From 1c46a020695b3720cf8ce2fd86b566447fdedccc Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Wed, 6 Apr 2005 15:12:44 +0500 Subject: [PATCH 18/34] Minor clean-ups for the previous commit. --- sql/field.cc | 8 ++++---- strings/ctype-mb.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index 740c027350d..d73257a673f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4914,7 +4914,7 @@ void Field_datetime::sql_type(String &res) const int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) { - int error= 0; + int error= 0, well_formed_error; uint32 not_used; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); @@ -4942,7 +4942,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) from,from+length, field_length/ field_charset->mbmaxlen, - &error); + &well_formed_error); memcpy(ptr,from,copy_length); if (copy_length < field_length) // Append spaces if shorter field_charset->cset->fill(field_charset,ptr+copy_length, @@ -5545,7 +5545,7 @@ void Field_blob::put_length(char *pos, uint32 length) int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) { - int error= 0; + int error= 0, well_formed_error; if (!length) { bzero(ptr,Field_blob::pack_length()); @@ -5580,7 +5580,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) from,from + min(length, copy_length), copy_length, - &error); + &well_formed_error); if (copy_length < length) error= 1; Field_blob::store_length(copy_length); diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index dbe3a24324e..cbbd035c631 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -276,7 +276,7 @@ uint my_well_formed_len_mb(CHARSET_INFO *cs, const char *b, const char *e, if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) b, (uchar*) e)) <= 0) { - *error= 1; + *error= b < e ? 1 : 0; break; } b+= mblen; From 57d89142878202551462bdae7259d77e629b37ba Mon Sep 17 00:00:00 2001 From: "kent@mysql.com" <> Date: Wed, 6 Apr 2005 12:20:55 +0200 Subject: [PATCH 19/34] Makefile.am: Include the Perl version of mysql-test-run rpl_rewrite_db.test, rpl_rewrite_db.result: Added missing database cleanup mysql-test-run.pl: Embedded result files no longer needed --- mysql-test/Makefile.am | 15 ++++++++++----- mysql-test/mysql-test-run.pl | 1 - mysql-test/r/rpl_rewrite_db.result | 1 + mysql-test/t/rpl_rewrite_db.test | 3 +++ 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index b2e86d8c00e..57598f5f3e3 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -32,21 +32,21 @@ endif benchdir_root= $(prefix) testdir = $(benchdir_root)/mysql-test -EXTRA_SCRIPTS = mysql-test-run.sh install_test_db.sh +EXTRA_SCRIPTS = mysql-test-run.sh mysql-test-run.pl install_test_db.sh EXTRA_DIST = $(EXTRA_SCRIPTS) test_SCRIPTS = mysql-test-run install_test_db test_DATA = std_data/client-key.pem std_data/client-cert.pem std_data/cacert.pem CLEANFILES = $(test_SCRIPTS) $(test_DATA) -INCLUDES = -I$(srcdir)/../include -I../include -I.. -EXTRA_PROGRAMS = mysql_test_run_new +INCLUDES = -I$(srcdir)/../include -I../include -I.. +EXTRA_PROGRAMS = mysql_test_run_new noinst_HEADERS = my_manage.h mysql_test_run_new_SOURCES= mysql_test_run_new.c my_manage.c my_create_tables.c dist-hook: mkdir -p $(distdir)/t $(distdir)/r $(distdir)/include \ - $(distdir)/std_data + $(distdir)/std_data $(distdir)/lib $(INSTALL_DATA) $(srcdir)/t/*.test $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t $(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include $(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.result.es $(srcdir)/r/*.require $(distdir)/r @@ -54,6 +54,8 @@ dist-hook: $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.pem $(distdir)/std_data + $(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(distdir)/lib + $(INSTALL_DATA) $(srcdir)/lib/*.pl $(distdir)/lib install-data-local: @@ -61,7 +63,8 @@ install-data-local: $(DESTDIR)$(testdir)/t \ $(DESTDIR)$(testdir)/r \ $(DESTDIR)$(testdir)/include \ - $(DESTDIR)$(testdir)/std_data + $(DESTDIR)$(testdir)/std_data \ + $(DESTDIR)$(testdir)/lib $(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(testdir) $(INSTALL_DATA) $(srcdir)/t/*.test $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.opt $(DESTDIR)$(testdir)/t @@ -75,6 +78,8 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.pem $(DESTDIR)$(testdir)/std_data + $(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(DESTDIR)$(testdir)/lib + $(INSTALL_DATA) $(srcdir)/lib/*.pl $(DESTDIR)$(testdir)/lib std_data/%.pem: @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index ae5caa8044a..e4f14447e30 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -635,7 +635,6 @@ sub command_line_setup () { { mtr_error("Can't use --extern with --embedded-server"); } - $opt_result_ext= ".es"; } # FIXME don't understand what this is diff --git a/mysql-test/r/rpl_rewrite_db.result b/mysql-test/r/rpl_rewrite_db.result index a2c8706e3e1..da3ec0243fe 100644 --- a/mysql-test/r/rpl_rewrite_db.result +++ b/mysql-test/r/rpl_rewrite_db.result @@ -89,4 +89,5 @@ a b 2 row 2 3 row 3 0 +drop database rewrite; drop table t1; diff --git a/mysql-test/t/rpl_rewrite_db.test b/mysql-test/t/rpl_rewrite_db.test index b6118854037..b77d57294fa 100644 --- a/mysql-test/t/rpl_rewrite_db.test +++ b/mysql-test/t/rpl_rewrite_db.test @@ -73,5 +73,8 @@ connection slave; # The empty line last comes from the end line field in the file select * from rewrite.t1; +drop database rewrite; + connection master; drop table t1; + From 1e030d5d9349100d91019b056a91c51ba8745768 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Wed, 6 Apr 2005 12:27:43 +0200 Subject: [PATCH 20/34] BUG#9626 Several serious errors reported by Valgrind in latest 5.0 bk tree - Fixing obvious ones --- sql/ha_ndbcluster.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index e3f6235c62c..0668c3db7a8 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -5803,6 +5803,7 @@ extern "C" pthread_handler_decl(ndb_util_thread_func, { thd->cleanup(); delete thd; + delete ndb; DBUG_RETURN(NULL); } @@ -5921,6 +5922,7 @@ extern "C" pthread_handler_decl(ndb_util_thread_func, thd->cleanup(); delete thd; + delete ndb; DBUG_PRINT("exit", ("ndb_util_thread")); my_thread_end(); pthread_exit(0); From f32fe9c154adbd169407c0bf3c11647dc7f0f7b8 Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Wed, 6 Apr 2005 15:09:15 +0300 Subject: [PATCH 21/34] InnoDB: Avoid test suite failures caused by a locking conflict between two server instances at server shutdown/startup. This conflict on advisory locks appears to be the result of a bug in the operating system; these locks should be released when the files are closed, but somehow that does not always happen immediately in Linux. (Bug #9381) --- innobase/include/os0file.h | 2 ++ innobase/os/os0file.c | 27 +++++++++++++++++++++++---- innobase/srv/srv0start.c | 5 +++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index d1439faf29f..ebc014df9fd 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -65,6 +65,8 @@ log. */ #define OS_FILE_OVERWRITE 53 #define OS_FILE_OPEN_RAW 54 #define OS_FILE_CREATE_PATH 55 +#define OS_FILE_OPEN_RETRY 56 /* for os_file_create() on + the first ibdata file */ #define OS_FILE_READ_ONLY 333 #define OS_FILE_READ_WRITE 444 diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 8d1ad895aa9..15f5bf40e51 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -402,8 +402,6 @@ os_file_lock( "InnoDB: using the same InnoDB data or log files.\n"); } - close(fd); - return(-1); } @@ -978,6 +976,7 @@ try_again: } else if (access_type == OS_FILE_READ_WRITE && os_file_lock(file, name)) { *success = FALSE; + close(file); file = -1; #endif } else { @@ -1090,6 +1089,7 @@ os_file_create_simple_no_error_handling( } else if (access_type == OS_FILE_READ_WRITE && os_file_lock(file, name)) { *success = FALSE; + close(file); file = -1; #endif } else { @@ -1141,7 +1141,8 @@ try_again: if (create_mode == OS_FILE_OPEN_RAW) { create_flag = OPEN_EXISTING; share_mode = FILE_SHARE_WRITE; - } else if (create_mode == OS_FILE_OPEN) { + } else if (create_mode == OS_FILE_OPEN + || create_mode == OS_FILE_OPEN_RETRY) { create_flag = OPEN_EXISTING; } else if (create_mode == OS_FILE_CREATE) { create_flag = CREATE_NEW; @@ -1232,7 +1233,8 @@ try_again: try_again: ut_a(name); - if (create_mode == OS_FILE_OPEN || create_mode == OS_FILE_OPEN_RAW) { + if (create_mode == OS_FILE_OPEN || create_mode == OS_FILE_OPEN_RAW + || create_mode == OS_FILE_OPEN_RETRY) { mode_str = "OPEN"; create_flag = O_RDWR; } else if (create_mode == OS_FILE_CREATE) { @@ -1305,6 +1307,23 @@ try_again: } else if (create_mode != OS_FILE_OPEN_RAW && os_file_lock(file, name)) { *success = FALSE; + if (create_mode == OS_FILE_OPEN_RETRY) { + int i; + ut_print_timestamp(stderr); + fputs(" InnoDB: Retrying to lock the first data file\n", + stderr); + for (i = 0; i < 100; i++) { + os_thread_sleep(1000000); + if (!os_file_lock(file, name)) { + *success = TRUE; + return(file); + } + } + ut_print_timestamp(stderr); + fputs(" InnoDB: Unable to open the first data file\n", + stderr); + } + close(file); file = -1; #endif } else { diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 44cf645f170..62df7301cc9 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -789,6 +789,11 @@ open_or_create_data_files( files[i] = os_file_create( name, OS_FILE_OPEN_RAW, OS_FILE_NORMAL, OS_DATA_FILE, &ret); + } else if (i == 0) { + files[i] = os_file_create( + name, OS_FILE_OPEN_RETRY, + OS_FILE_NORMAL, + OS_DATA_FILE, &ret); } else { files[i] = os_file_create( name, OS_FILE_OPEN, OS_FILE_NORMAL, From 49e721677f9eec2ae8e869dacc8acb522f72ef05 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Wed, 6 Apr 2005 17:22:21 +0300 Subject: [PATCH 22/34] Fixed errors descovered by valgrind 2.4 Added suppression file for some valgrind warnings that are not real errors --- mysql-test/mysql-test-run.sh | 2 +- mysql-test/r/heap.result | 21 ++----- mysql-test/t/heap.test | 27 +++------ mysql-test/valgrind.supp | 94 +++++++++++++++++++++++++++++ mysys/default.c | 4 +- scripts/make_binary_distribution.sh | 1 + sql/ha_federated.cc | 6 +- sql/ha_heap.cc | 1 + sql/mysqld.cc | 3 +- sql/sql_parse.cc | 3 +- strings/decimal.c | 2 +- 11 files changed, 121 insertions(+), 43 deletions(-) create mode 100644 mysql-test/valgrind.supp diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index ac1755cab9c..d294ef50421 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -418,7 +418,7 @@ while test $# -gt 0; do fi # >=2.1.2 requires the --tool option, some versions write to stdout, some to stderr valgrind --help 2>&1 | grep "\-\-tool" > /dev/null && VALGRIND="$VALGRIND --tool=memcheck" - VALGRIND="$VALGRIND --alignment=8 --leak-check=yes --num-callers=16" + VALGRIND="$VALGRIND --alignment=8 --leak-check=yes --num-callers=16 --suppressions=$CWD/valgrind.supp" EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc --skip-bdb" EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc --skip-bdb" SLEEP_TIME_AFTER_RESTART=10 diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result index db20b242962..631bd8c713c 100644 --- a/mysql-test/r/heap.result +++ b/mysql-test/r/heap.result @@ -667,14 +667,7 @@ drop table t1; set storage_engine=MyISAM; create table t1 (a bigint unsigned auto_increment primary key, b int, key (b, a)) engine=heap; -insert t1 (b) values (1); -insert t1 (b) values (1); -insert t1 (b) values (1); -insert t1 (b) values (1); -insert t1 (b) values (1); -insert t1 (b) values (1); -insert t1 (b) values (1); -insert t1 (b) values (1); +insert t1 (b) values (1),(1),(1),(1),(1),(1),(1),(1); select * from t1; a b 1 1 @@ -688,14 +681,7 @@ a b drop table t1; create table t1 (a int not null, b int not null auto_increment, primary key(a, b), key(b)) engine=heap; -insert t1 (a) values (1); -insert t1 (a) values (1); -insert t1 (a) values (1); -insert t1 (a) values (1); -insert t1 (a) values (1); -insert t1 (a) values (1); -insert t1 (a) values (1); -insert t1 (a) values (1); +insert t1 (a) values (1),(1),(1),(1),(1),(1),(1),(1); select * from t1; a b 1 1 @@ -707,3 +693,6 @@ a b 1 7 1 8 drop table t1; +create table t1 (a int not null, b int not null auto_increment, +primary key(a, b)) engine=heap; +ERROR 42000: Incorrect table definition; there can be only one auto column and it must be defined as a key diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test index b69649585ff..c36474bda30 100644 --- a/mysql-test/t/heap.test +++ b/mysql-test/t/heap.test @@ -413,25 +413,16 @@ eval set storage_engine=$default; create table t1 (a bigint unsigned auto_increment primary key, b int, key (b, a)) engine=heap; -insert t1 (b) values (1); -insert t1 (b) values (1); -insert t1 (b) values (1); -insert t1 (b) values (1); -insert t1 (b) values (1); -insert t1 (b) values (1); -insert t1 (b) values (1); -insert t1 (b) values (1); -select * from t1; +insert t1 (b) values (1),(1),(1),(1),(1),(1),(1),(1); +select * from t1; drop table t1; + create table t1 (a int not null, b int not null auto_increment, primary key(a, b), key(b)) engine=heap; -insert t1 (a) values (1); -insert t1 (a) values (1); -insert t1 (a) values (1); -insert t1 (a) values (1); -insert t1 (a) values (1); -insert t1 (a) values (1); -insert t1 (a) values (1); -insert t1 (a) values (1); -select * from t1; +insert t1 (a) values (1),(1),(1),(1),(1),(1),(1),(1); +select * from t1; drop table t1; + +--error 1075 +create table t1 (a int not null, b int not null auto_increment, + primary key(a, b)) engine=heap; diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp new file mode 100644 index 00000000000..d8a13ca9dfd --- /dev/null +++ b/mysql-test/valgrind.supp @@ -0,0 +1,94 @@ +# +# Suppress some common (not fatal) errors in system libraries found by valgrind +# + +# +# Pthread doesn't free all thread specific memory before program exists +# +{ + pthread allocate_tls memory loss + Memcheck:Leak + fun:calloc + fun:_dl_allocate_tls + fun:allocate_stack + fun:pthread_create@@GLIBC_2.1 +} + +{ + pthread allocate_dtv memory loss + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls_storage + fun:__GI__dl_allocate_tls + fun:pthread_create +} + +{ + pthread memalign memory loss + Memcheck:Leak + fun:memalign + fun:_dl_allocate_tls_storage + fun:__GI__dl_allocate_tls + fun:pthread_create +} + +{ + pthread errno + Memcheck:Leak + fun:calloc + fun:_dlerror_run + fun:dlsym + fun:__errno_location +} + + +# +# Warnings in libz becasue it works with aligned memory(?) +# + +{ + libz tr_flush_block + Memcheck:Cond + fun:_tr_flush_block + fun:deflate_slow + fun:deflate + fun:do_flush + fun:gzclose +} + +{ + libz tr_flush_block2 + Memcheck:Cond + fun:_tr_flush_block + fun:deflate_slow + fun:deflate + fun:compress2 +} + +{ + libz longest_match + Memcheck:Cond + fun:longest_match + fun:deflate_slow + fun:deflate + fun:do_flush +} + +{ + libz longest_match2 + Memcheck:Cond + fun:longest_match + fun:deflate_slow + fun:deflate + fun:compress2 +} + +{ + libz deflate + Memcheck:Cond + obj:/usr/lib/libz.so.* + obj:/usr/lib/libz.so.* + fun:deflate + fun:compress2 +} diff --git a/mysys/default.c b/mysys/default.c index ddff4e26be5..6352cc18d56 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -477,13 +477,13 @@ static int search_default_file_with_ext(Process_option_func opt_handler, if ((stat_info.st_mode & S_IWOTH) && (stat_info.st_mode & S_IFMT) == S_IFREG) { - fprintf(stderr, "warning: World-writable config file %s is ignored\n", + fprintf(stderr, "Warning: World-writable config file '%s' is ignored\n", name); return 0; } } #endif - if (!(fp= my_fopen(fn_format(name, name, "", "", 4), O_RDONLY, MYF(0)))) + if (!(fp= my_fopen(name, O_RDONLY, MYF(0)))) return 0; /* Ignore wrong files */ while (fgets(buff, sizeof(buff) - 1, fp)) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index ddce55c063d..22bf13d8bef 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -207,6 +207,7 @@ rm -f $MYSQL_SHARE/Makefile* $MYSQL_SHARE/*/*.OLD for i in mysql-test/mysql-test-run mysql-test/install_test_db \ mysql-test/mysql-test-run.pl mysql-test/README \ + mysql-test/valgrind.supp \ netware/mysql_test_run.nlm netware/install_test_db.ncf do if [ -f $i ] diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 8000aae180d..33acc9cad0b 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -548,12 +548,12 @@ error: static int parse_url(FEDERATED_SHARE *share, TABLE *table, uint table_create_flag) { + uint error_num= (table_create_flag ? ER_CANT_CREATE_TABLE : + ER_CONNECT_TO_MASTER); DBUG_ENTER("ha_federated::parse_url"); share->port= 0; - uint error_num= (table_create_flag ? ER_CANT_CREATE_TABLE : - ER_CONNECT_TO_MASTER); - + share->socket= 0; share->scheme= my_strdup(table->s->comment, MYF(0)); if ((share->username= strstr(share->scheme, "://"))) diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index de51fad4365..0d700f6c9a5 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -548,6 +548,7 @@ int ha_heap::create(const char *name, TABLE *table_arg, hp_create_info.auto_increment= (create_info->auto_increment_value ? create_info->auto_increment_value - 1 : 0); hp_create_info.max_table_size=current_thd->variables.max_heap_table_size; + hp_create_info.with_auto_increment= found_real_auto_increment; max_rows = (ha_rows) (hp_create_info.max_table_size / mem_per_row); error= heap_create(fn_format(buff,name,"","",4+2), keys, keydef, share->reclength, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e1303585114..7611270fc42 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1519,6 +1519,7 @@ void end_thread(THD *thd, bool put_in_cache) thd=thread_cache.get(); thd->real_id=pthread_self(); (void) thd->store_globals(); + thd->thr_create_time= time(NULL); threads.append(thd); pthread_mutex_unlock(&LOCK_thread_count); DBUG_VOID_RETURN; @@ -5180,7 +5181,7 @@ log and this option does nothing anymore.", (gptr*) &dflt_key_cache_var.param_buff_size, (gptr*) 0, 0, (GET_ULL | GET_ASK_ADDR), - REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, UINT_MAX32, MALLOC_OVERHEAD, + REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, ~(ulong) 0, MALLOC_OVERHEAD, IO_SIZE, 0}, {"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD, "This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in key cache", diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1d7eba4ce43..9e7cf81de3c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1103,7 +1103,8 @@ pthread_handler_decl(handle_one_connection,arg) thd->proc_info=0; thd->set_time(); thd->init_for_queries(); - while (!net->error && net->vio != 0 && !(thd->killed == THD::KILL_CONNECTION)) + while (!net->error && net->vio != 0 && + !(thd->killed == THD::KILL_CONNECTION)) { net->no_send_error= 0; if (do_command(thd)) diff --git a/strings/decimal.c b/strings/decimal.c index 56dba61d887..9af95511f6d 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -806,7 +806,7 @@ internal_str2dec(const char *from, decimal_t *to, char **end, my_bool fixed) if (s < end_of_string && *s=='.') { endp= s+1; - while (s < end_of_string && my_isdigit(&my_charset_latin1, *endp)) + while (endp < end_of_string && my_isdigit(&my_charset_latin1, *endp)) endp++; frac= endp - s - 1; } From a7c6348192b857e12d8219bed24e44fee15ae181 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Wed, 6 Apr 2005 19:43:35 +0300 Subject: [PATCH 23/34] Fixed errors found during review --- mysql-test/r/drop.result | 4 ++-- mysql-test/r/kill.result | 2 +- mysql-test/t/kill.test | 2 +- mysys/my_sync.c | 2 +- sql/records.cc | 2 +- sql/share/errmsg.txt | 48 ++++++++++++++++++++-------------------- sql/sql_class.cc | 5 +++-- sql/sql_show.cc | 2 +- 8 files changed, 34 insertions(+), 33 deletions(-) diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result index b91cc89cfea..979e5d48871 100644 --- a/mysql-test/r/drop.result +++ b/mysql-test/r/drop.result @@ -30,13 +30,13 @@ table7, table8, table9, table10, table11, table12, table13, table14, table15, table16, table17, table18, table19, table20, table21, table22, table23, table24, table25, table26, table27, table28; -ERROR 42S02: Unknown table 'table1,table2,table3,table4,table5,table6,table7,table8,table9,table10,table11,table12,table13,table14,table15,table16,table17,table18,table19,table20,table21,table22,table23,table' +ERROR 42S02: Unknown table 'table1,table2,table3,table4,table5,table6,table7,table8,table9,table10,table11,table12,table13,table' drop table table1, table2, table3, table4, table5, table6, table7, table8, table9, table10, table11, table12, table13, table14, table15, table16, table17, table18, table19, table20, table21, table22, table23, table24, table25, table26, table27, table28, table29, table30; -ERROR 42S02: Unknown table 'table1,table2,table3,table4,table5,table6,table7,table8,table9,table10,table11,table12,table13,table14,table15,table16,table17,table18,table19,table20,table21,table22,table23,table' +ERROR 42S02: Unknown table 'table1,table2,table3,table4,table5,table6,table7,table8,table9,table10,table11,table12,table13,table' use test; drop database mysqltest; flush tables with read lock; diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result index 049281ad5d4..754568093ff 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -6,7 +6,7 @@ select ((@id := kill_id) - kill_id) from t1; 0 kill @id; select 1; -ERROR HY000: MySQL server has gone away +Got one of the listed errors select ((@id := kill_id) - kill_id) from t1; ((@id := kill_id) - kill_id) 0 diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index 6744a212828..37e11e14df5 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -27,7 +27,7 @@ connection con1; --disable_reconnect # this statement should fail ---error 2006 +--error 2006,2013 select 1; --enable_reconnect # this should work, and we should have a new connection_id() diff --git a/mysys/my_sync.c b/mysys/my_sync.c index bfaf09ce402..c557324b52c 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -65,7 +65,7 @@ int my_sync(File fd, myf my_flags) int er= errno; if (!(my_errno= er)) my_errno= -1; /* Unknown error */ - if (my_flags & MY_IGNORE_BADFD && + if ((my_flags & MY_IGNORE_BADFD) && (er == EBADF || er == EINVAL || er == EROFS)) res= 0; else if (my_flags & MY_WME) diff --git a/sql/records.cc b/sql/records.cc index cfb7cb3d065..b71bcf70865 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -131,7 +131,7 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, /* Condition pushdown to storage engine */ if (thd->variables.engine_condition_pushdown && select && select->cond && - select->cond->used_tables() & table->map && + (select->cond->used_tables() & table->map) && !table->file->pushed_cond) table->file->cond_push(select->cond); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 9a92f1f4f76..46c8fcc7863 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -1214,30 +1214,30 @@ ER_TABLE_EXISTS_ERROR 42S01 swe "Tabellen '%-.64s' finns redan" ukr "ôÁÂÌÉÃÑ '%-.64s' ×ÖÅ ¦ÓÎÕ¤" ER_BAD_TABLE_ERROR 42S02 - cze "Nezn-Bámá tabulka '%-.180s'" - dan "Ukendt tabel '%-.180s'" - nla "Onbekende tabel '%-.180s'" - eng "Unknown table '%-.180s'" - jps "table '%-.180s' ‚Í‚ ‚è‚Ü‚¹‚ñ.", - est "Tundmatu tabel '%-.180s'" - fre "Table '%-.180s' inconnue" - ger "Unbekannte Tabelle '%-.180s'" - greek "Áãíùóôïò ðßíáêáò '%-.180s'" - hun "Ervenytelen tabla: '%-.180s'" - ita "Tabella '%-.180s' sconosciuta" - jpn "table '%-.180s' ¤Ï¤¢¤ê¤Þ¤»¤ó." - kor "Å×À̺í '%-.180s'´Â ¾Ë¼ö ¾øÀ½" - nor "Ukjent tabell '%-.180s'" - norwegian-ny "Ukjent tabell '%-.180s'" - pol "Nieznana tabela '%-.180s'" - por "Tabela '%-.180s' desconhecida" - rum "Tabela '%-.180s' este invalida" - rus "îÅÉÚ×ÅÓÔÎÁÑ ÔÁÂÌÉÃÁ '%-.180s'" - serbian "Nepoznata tabela '%-.180s'" - slo "Neznáma tabuµka '%-.180s'" - spa "Tabla '%-.180s' desconocida" - swe "Okänd tabell '%-.180s'" - ukr "îÅצÄÏÍÁ ÔÁÂÌÉÃÑ '%-.180s'" + cze "Nezn-Bámá tabulka '%-.100s'" + dan "Ukendt tabel '%-.100s'" + nla "Onbekende tabel '%-.100s'" + eng "Unknown table '%-.100s'" + jps "table '%-.100s' ‚Í‚ ‚è‚Ü‚¹‚ñ.", + est "Tundmatu tabel '%-.100s'" + fre "Table '%-.100s' inconnue" + ger "Unbekannte Tabelle '%-.100s'" + greek "Áãíùóôïò ðßíáêáò '%-.100s'" + hun "Ervenytelen tabla: '%-.100s'" + ita "Tabella '%-.100s' sconosciuta" + jpn "table '%-.100s' ¤Ï¤¢¤ê¤Þ¤»¤ó." + kor "Å×À̺í '%-.100s'´Â ¾Ë¼ö ¾øÀ½" + nor "Ukjent tabell '%-.100s'" + norwegian-ny "Ukjent tabell '%-.100s'" + pol "Nieznana tabela '%-.100s'" + por "Tabela '%-.100s' desconhecida" + rum "Tabela '%-.100s' este invalida" + rus "îÅÉÚ×ÅÓÔÎÁÑ ÔÁÂÌÉÃÁ '%-.100s'" + serbian "Nepoznata tabela '%-.100s'" + slo "Neznáma tabuµka '%-.100s'" + spa "Tabla '%-.100s' desconocida" + swe "Okänd tabell '%-.100s'" + ukr "îÅצÄÏÍÁ ÔÁÂÌÉÃÑ '%-.100s'" ER_NON_UNIQ_ERROR 23000 cze "Sloupec '%-.64s' v %s nen-Bí zcela jasný" dan "Felt: '%-.64s' i tabel %s er ikke entydigt" diff --git a/sql/sql_class.cc b/sql/sql_class.cc index cdda013d23a..c68dc826147 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -343,8 +343,9 @@ void THD::change_user(void) void THD::cleanup(void) { DBUG_ENTER("THD::cleanup"); - /* TODO uncomment the line below when binlog will be able to prepare */ - // if (transaction.xa_state != XA_PREPARED) +#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE + if (transaction.xa_state != XA_PREPARED) +#endif ha_rollback(this); if (locked_tables) { diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d2cab6bf49f..8b906f133ba 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2312,7 +2312,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, } } #else - end=strmov(end,""); + *end= 0; #endif table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs); From 70aecbb8a450fedc3390e71daf7bd432db376b04 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Wed, 6 Apr 2005 21:48:16 +0400 Subject: [PATCH 24/34] Refactor parts of do_select() (JOIN execution). --- sql/sql_select.cc | 93 +++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 410b3090b5c..cbde0752cd1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -111,6 +111,7 @@ static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item); static bool open_tmp_table(TABLE *table); static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, ulong options); +static Next_select_func setup_end_select_func(JOIN *join); static int do_select(JOIN *join,List *fields,TABLE *tmp_table, Procedure *proc); static int sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records); @@ -1638,6 +1639,8 @@ JOIN::exec() { thd->proc_info="Sending data"; DBUG_PRINT("info", ("%s", thd->proc_info)); + result->send_fields(*curr_fields_list, + Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); error= do_select(curr_join, curr_fields_list, NULL, procedure); thd->limit_found_rows= curr_join->send_records; thd->examined_row_count= curr_join->examined_rows; @@ -1776,12 +1779,7 @@ Cursor::open(JOIN *join_arg) thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; /* Prepare JOIN for reading rows. */ - - Next_select_func end_select= join->sort_and_group || join->procedure && - join->procedure->flags & PROC_GROUP ? - end_send_group : end_send; - - join->join_tab[join->tables-1].next_select= end_select; + join->join_tab[join->tables-1].next_select= setup_end_select_func(join); join->send_records= 0; join->fetch_limit= join->unit->offset_limit_cnt; @@ -1802,6 +1800,11 @@ Cursor::open(JOIN *join_arg) */ DBUG_ASSERT(join_tab->table->null_row == 0); + /* + There is always at least one record in the table, as otherwise we + wouldn't have opened the cursor. Therefore a failure is the only + reason read_first_record can return not 0. + */ DBUG_RETURN(join_tab->read_first_record(join_tab)); } @@ -8733,36 +8736,24 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, } -/**************************************************************************** - Make a join of all tables and write it on socket or to table - Return: 0 if ok - 1 if error is sent - -1 if error should be sent -****************************************************************************/ +/* + SYNOPSIS + setup_end_select_func() + join join to setup the function for. -static int -do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) + DESCRIPTION + Rows produced by a join sweep may end up in a temporary table or be sent + to a client. Setup the function of the nested loop join algorithm which + handles final fully constructed and matched records. + + RETURN + end_select function to use. This function can't fail. +*/ + +static Next_select_func setup_end_select_func(JOIN *join) { - int error= 0; - JOIN_TAB *join_tab; + TABLE *table= join->tmp_table; Next_select_func end_select; - DBUG_ENTER("do_select"); - - join->procedure=procedure; - /* - Tell the client how many fields there are in a row - */ - if (!table) - join->result->send_fields(*fields, - Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); - else - { - VOID(table->file->extra(HA_EXTRA_WRITE_CACHE)); - empty_record(table); - } - join->tmp_table= table; /* Save for easy recursion */ - join->fields= fields; - /* Set up select_end */ if (table) { @@ -8772,8 +8763,6 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) { DBUG_PRINT("info",("Using end_update")); end_select=end_update; - if (!table->file->inited) - table->file->ha_index_init(0); } else { @@ -8807,7 +8796,38 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) else end_select= end_send; } - join->join_tab[join->tables-1].next_select=end_select; + return end_select; +} + + +/**************************************************************************** + Make a join of all tables and write it on socket or to table + Return: 0 if ok + 1 if error is sent + -1 if error should be sent +****************************************************************************/ + +static int +do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) +{ + int error= 0; + JOIN_TAB *join_tab; + DBUG_ENTER("do_select"); + + join->procedure=procedure; + join->tmp_table= table; /* Save for easy recursion */ + join->fields= fields; + + if (table) + { + VOID(table->file->extra(HA_EXTRA_WRITE_CACHE)); + empty_record(table); + if (table->group && join->tmp_table_param.sum_func_count && + table->s->keys && !table->file->inited) + table->file->ha_index_init(0); + } + /* Set up select_end */ + join->join_tab[join->tables-1].next_select= setup_end_select_func(join); join_tab=join->join_tab+join->const_tables; join->send_records=0; @@ -8819,6 +8839,7 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) */ if (!join->conds || join->conds->val_int()) { + Next_select_func end_select= join->join_tab[join->tables-1].next_select; if (!(error=(*end_select)(join,join_tab,0)) || error == -3) error=(*end_select)(join,join_tab,1); } From 5f8d71710b6e8a8a147e00feff86bff140ec7696 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Wed, 6 Apr 2005 22:09:43 +0400 Subject: [PATCH 25/34] Minor fix in cursors execution. --- sql/sql_select.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cbde0752cd1..baf2ef09d2b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1779,6 +1779,7 @@ Cursor::open(JOIN *join_arg) thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; /* Prepare JOIN for reading rows. */ + join->tmp_table= 0; join->join_tab[join->tables-1].next_select= setup_end_select_func(join); join->send_records= 0; join->fetch_limit= join->unit->offset_limit_cnt; From 288eff45cba7e173d3f3a70a92ad13ef19ce6160 Mon Sep 17 00:00:00 2001 From: "jani@a193-229-222-105.elisa-laajakaista.fi" <> Date: Wed, 6 Apr 2005 21:55:34 +0300 Subject: [PATCH 26/34] Added missing file to Makefile.am --- mysql-test/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index f3efa24b628..34b1dd1a1fe 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -59,6 +59,7 @@ dist-hook: $(INSTALL_DATA) $(srcdir)/std_data/*.frm $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(distdir)/lib $(INSTALL_DATA) $(srcdir)/lib/*.pl $(distdir)/lib + $(INSTALL_DATA) $(srcdir)/*.supp $(distdir)/ install-data-local: $(mkinstalldirs) \ From 5cd866610df606253827d5495343365af0cc9134 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Wed, 6 Apr 2005 23:12:10 +0200 Subject: [PATCH 27/34] after merge fix --- mysql-test/r/user_var.result | 3 +-- mysql-test/t/user_var.test | 3 +-- ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp | 3 ++- strings/ctype-cp932.c | 4 +++- strings/ctype-eucjpms.c | 11 +++++++---- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index d36dca86e39..68eae111111 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -180,6 +180,5 @@ select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4); coercibility(@v1) coercibility(@v2) coercibility(@v3) coercibility(@v4) 2 2 2 2 set session @honk=99; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@honk=99' at line 1 set one_shot @honk=99; -ERROR HY000: The SET ONE_SHOT syntax is reserved for purposes internal to the MySQL server +ERROR HY000: The 'SET ONE_SHOT' syntax is reserved for purposes internal to the MySQL server diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index 49941bc81f3..ef360f2231d 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -116,7 +116,6 @@ select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4); # # Bug #9286 SESSION/GLOBAL should be disallowed for user variables # ---error 1064 set session @honk=99; ---error 1105 +--error 1382 set one_shot @honk=99; diff --git a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp index c3f85cdebd5..3170d23499a 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp @@ -813,6 +813,7 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer, ndbrequire(i < regTabPtr->noOfCharsets); // not const in MySQL CHARSET_INFO* cs = regTabPtr->charsetArray[i]; + int not_used; const char* ssrc = (const char*)&inBuffer[tInBufIndex + 1]; Uint32 lb, len; if (! NdbSqlUtil::get_var_length(typeId, ssrc, bytes, lb, len)) { @@ -822,7 +823,7 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer, } // fast fix bug#7340 if (typeId != NDB_TYPE_TEXT && - (*cs->cset->well_formed_len)(cs, ssrc + lb, ssrc + lb + len, ZNIL) != len) { + (*cs->cset->well_formed_len)(cs, ssrc + lb, ssrc + lb + len, ZNIL, ¬_used) != len) { ljam(); terrorCode = ZINVALID_CHAR_FORMAT; return false; diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index c47f2c2d8ce..47bf1167c8c 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -5413,9 +5413,10 @@ uint my_numcells_cp932(CHARSET_INFO *cs __attribute__((unused)), */ static uint my_well_formed_len_cp932(CHARSET_INFO *cs __attribute__((unused)), - const char *b, const char *e, uint pos) + const char *b, const char *e, uint pos, int *error) { const char *b0= b; + *error= 0; while (pos && b < e) { /* @@ -5441,6 +5442,7 @@ uint my_well_formed_len_cp932(CHARSET_INFO *cs __attribute__((unused)), else { /* Wrong byte sequence */ + *error= 1; break; } } diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c index 8c8d237cf48..346b5ecdf6b 100644 --- a/strings/ctype-eucjpms.c +++ b/strings/ctype-eucjpms.c @@ -8380,17 +8380,18 @@ my_jisx0212_uni_onechar(int code){ /* EUC-JP encoding subcomponents: - [x00-x7F] # ASCII/JIS-Roman (one-byte/character) - [x8E][xA0-xDF] # half-width katakana (two bytes/char) - [x8F][xA1-xFE][xA1-xFE] # JIS X 0212-1990 (three bytes/char) + [x00-x7F] # ASCII/JIS-Roman (one-byte/character) + [x8E][xA0-xDF] # half-width katakana (two bytes/char) + [x8F][xA1-xFE][xA1-xFE] # JIS X 0212-1990 (three bytes/char) [xA1-xFE][xA1-xFE] # JIS X 0208:1997 (two bytes/char) */ static uint my_well_formed_len_eucjpms(CHARSET_INFO *cs __attribute__((unused)), - const char *beg, const char *end, uint pos) + const char *beg, const char *end, uint pos, int *error) { const uchar *b= (uchar *) beg; + *error=0; for ( ; pos && b < (uchar*) end; pos--, b++) { @@ -8408,6 +8409,7 @@ uint my_well_formed_len_eucjpms(CHARSET_INFO *cs __attribute__((unused)), { if (*b >= 0xA0 && *b <= 0xDF) continue; + *error=1; return chbeg - beg; /* invalid sequence */ } @@ -8421,6 +8423,7 @@ uint my_well_formed_len_eucjpms(CHARSET_INFO *cs __attribute__((unused)), if (ch >= 0xA1 && ch <= 0xFE && *b >= 0xA1 && *b <= 0xFE) /* [xA1-xFE][xA1-xFE] */ continue; + *error=1; return chbeg - beg; /* invalid sequence */ } return b - (uchar *) beg; From d85bed11215aff82e4d63b9c9e6e7fca29562a86 Mon Sep 17 00:00:00 2001 From: "dlenev@brandersnatch.localdomain" <> Date: Thu, 7 Apr 2005 01:40:29 +0400 Subject: [PATCH 28/34] Fix for bug #9566 "explicit LOCK TABLE and store procedures result in illegal state". We should not assume that mysql.proc table does not exist if we are unable to open it under LOCK TABLES or in prelocked mode (and remember this fact by setting mysql_proc_table_exists to zero). --- mysql-test/r/sp.result | 10 ++++++++++ mysql-test/t/sp.test | 23 +++++++++++++++++++++++ sql/sp.cc | 13 +++++++++---- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index daad032b854..cb0ae310ceb 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -2779,4 +2779,14 @@ a 3.2000 drop procedure bug8937| delete from t1| +drop procedure if exists bug9566| +create procedure bug9566() +begin +select * from t1; +end| +lock table t1 read| +call bug9566()| +ERROR HY000: Table 'proc' was not locked with LOCK TABLES +unlock tables| +drop procedure bug9566| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index a741a4af7d8..799e88a6615 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -3397,6 +3397,29 @@ call bug8937()| drop procedure bug8937| delete from t1| +# +# BUG#9566: explicit LOCK TABLE and store procedures result in illegal state +# +# We should not think that mysql.proc table does not exist if we are unable +# to open it under LOCK TABLE or in prelocked mode. Probably this test +# should be removed when Monty will allow access to mysql.proc without +# locking it. +# +--disable_warnings +drop procedure if exists bug9566| +--enable_warnings +create procedure bug9566() +begin + select * from t1; +end| +lock table t1 read| +# This should fail because we forgot to lock mysql.proc table explicitly +--error 1100 +call bug9566()| +unlock tables| +# This should succeed +drop procedure bug9566| + # # BUG#NNNN: New bug synopsis diff --git a/sql/sp.cc b/sql/sp.cc index 23d389cd299..1956f32f2c6 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -70,9 +70,8 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, type, name->m_name.length, name->m_name.str)); /* - Speed up things if mysql.proc doesn't exists - mysql_proc_table_exists is set when on creates a stored procedure - or on flush privileges + Speed up things if mysql.proc doesn't exists. mysql_proc_table_exists + is set when we create or read stored procedure or on flush privileges. */ if (!mysql_proc_table_exists && ltype == TL_READ) DBUG_RETURN(SP_OPEN_TABLE_FAILED); @@ -98,7 +97,13 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, if (! (table= open_ltable(thd, &tables, ltype))) { *tablep= NULL; - mysql_proc_table_exists= 0; + /* + Under explicit LOCK TABLES or in prelocked mode we should not + say that mysql.proc table does not exist if we are unable to + open it since this condition may be transient. + */ + if (!(thd->locked_tables || thd->prelocked_mode)) + mysql_proc_table_exists= 0; DBUG_RETURN(SP_OPEN_TABLE_FAILED); } *opened= TRUE; From 8d05aa0f02bc0083261d1717bb875b5c11d24309 Mon Sep 17 00:00:00 2001 From: "dlenev@brandersnatch.localdomain" <> Date: Thu, 7 Apr 2005 11:57:47 +0400 Subject: [PATCH 29/34] Moved test for bug #9566 "explicit LOCK TABLE and store procedures result in illegal state" to sp-error.test. According to Per-Erik all SP related tests which should result in error should go into sp-error.test and not in sp.test, because we want to be able to run sp.test using normal client. --- mysql-test/r/sp-error.result | 10 ++++++++++ mysql-test/r/sp.result | 10 ---------- mysql-test/t/sp-error.test | 23 +++++++++++++++++++++++ mysql-test/t/sp.test | 23 ----------------------- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index c979ee34df0..ff7d71b3384 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -503,4 +503,14 @@ ERROR 0A000: LOCK is not allowed in stored procedures create procedure bug6600() unlock table t1| ERROR 0A000: UNLOCK is not allowed in stored procedures +drop procedure if exists bug9566| +create procedure bug9566() +begin +select * from t1; +end| +lock table t1 read| +call bug9566()| +ERROR HY000: Table 'proc' was not locked with LOCK TABLES +unlock tables| +drop procedure bug9566| drop table t1| diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index cb0ae310ceb..daad032b854 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -2779,14 +2779,4 @@ a 3.2000 drop procedure bug8937| delete from t1| -drop procedure if exists bug9566| -create procedure bug9566() -begin -select * from t1; -end| -lock table t1 read| -call bug9566()| -ERROR HY000: Table 'proc' was not locked with LOCK TABLES -unlock tables| -drop procedure bug9566| drop table t1,t2; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 621700b732a..51776453730 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -696,6 +696,29 @@ create procedure bug6600() create procedure bug6600() unlock table t1| +# +# BUG#9566: explicit LOCK TABLE and store procedures result in illegal state +# +# We should not think that mysql.proc table does not exist if we are unable +# to open it under LOCK TABLE or in prelocked mode. Probably this test +# should be removed when Monty will allow access to mysql.proc without +# locking it. +# +--disable_warnings +drop procedure if exists bug9566| +--enable_warnings +create procedure bug9566() +begin + select * from t1; +end| +lock table t1 read| +# This should fail because we forgot to lock mysql.proc table explicitly +--error 1100 +call bug9566()| +unlock tables| +# This should succeed +drop procedure bug9566| + # # BUG#NNNN: New bug synopsis diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 799e88a6615..a741a4af7d8 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -3397,29 +3397,6 @@ call bug8937()| drop procedure bug8937| delete from t1| -# -# BUG#9566: explicit LOCK TABLE and store procedures result in illegal state -# -# We should not think that mysql.proc table does not exist if we are unable -# to open it under LOCK TABLE or in prelocked mode. Probably this test -# should be removed when Monty will allow access to mysql.proc without -# locking it. -# ---disable_warnings -drop procedure if exists bug9566| ---enable_warnings -create procedure bug9566() -begin - select * from t1; -end| -lock table t1 read| -# This should fail because we forgot to lock mysql.proc table explicitly ---error 1100 -call bug9566()| -unlock tables| -# This should succeed -drop procedure bug9566| - # # BUG#NNNN: New bug synopsis From 18354f457005c98112e51d02fa18f16feff50724 Mon Sep 17 00:00:00 2001 From: "jani@ua141d10.elisa.omakaista.fi" <> Date: Thu, 7 Apr 2005 13:20:15 +0300 Subject: [PATCH 30/34] A small fix to Makefile.am --- mysql-test/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 34b1dd1a1fe..9963074daf5 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -32,7 +32,7 @@ endif benchdir_root= $(prefix) testdir = $(benchdir_root)/mysql-test -EXTRA_SCRIPTS = mysql-test-run.sh mysql-test-run.pl install_test_db.sh +EXTRA_SCRIPTS = mysql-test-run.sh mysql-test-run.pl install_test_db.sh valgrind.supp EXTRA_DIST = $(EXTRA_SCRIPTS) test_SCRIPTS = mysql-test-run install_test_db test_DATA = std_data/client-key.pem std_data/client-cert.pem std_data/cacert.pem @@ -59,7 +59,6 @@ dist-hook: $(INSTALL_DATA) $(srcdir)/std_data/*.frm $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(distdir)/lib $(INSTALL_DATA) $(srcdir)/lib/*.pl $(distdir)/lib - $(INSTALL_DATA) $(srcdir)/*.supp $(distdir)/ install-data-local: $(mkinstalldirs) \ From b950bc210c64440c9bc12c9d8d77c9cf4a0b5ac4 Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Thu, 7 Apr 2005 16:14:45 +0500 Subject: [PATCH 31/34] ctype-eucjpms.c: After merge fix. --- strings/ctype-eucjpms.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c index 346b5ecdf6b..ab12446754a 100644 --- a/strings/ctype-eucjpms.c +++ b/strings/ctype-eucjpms.c @@ -8417,7 +8417,10 @@ uint my_well_formed_len_eucjpms(CHARSET_INFO *cs __attribute__((unused)), { ch= *b++; if (b >= (uchar*) end) + { + *error= 1; return chbeg - beg; /* unexpected EOL */ + } } if (ch >= 0xA1 && ch <= 0xFE && From 9911194a1373181aaf6bbd736d487f75ea7aca5a Mon Sep 17 00:00:00 2001 From: "magnus@msdesk.mysql.com" <> Date: Thu, 7 Apr 2005 14:39:30 +0200 Subject: [PATCH 32/34] Fix linking problem on bsd53 - See article http://archive.netbsd.se/?ml=freebsd-current&a=2004-07&m=257561 or http://www.geocrawler.com/archives/3/254/2003/3/450/10409564/ --- configure.in | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/configure.in b/configure.in index c7e93c9676a..01f669a0d1b 100644 --- a/configure.in +++ b/configure.in @@ -351,6 +351,15 @@ then if echo $CXX | grep gcc > /dev/null 2>&1 then GCC_VERSION=`gcc -v 2>&1 | grep version | sed -e 's/[[^0-9. ]]//g; s/^ *//g; s/ .*//g'` + case $SYSTEM_TYPE in + *freebsd*) + # The libsupc++ library on freebsd with gcc 3.4.2 is dependent on + # libstdc++, disable it since other solution works fine + GCC_VERSION="NOSUPCPP_$GCC_VERSION" + ;; + *) + ;; + esac echo "Using gcc version '$GCC_VERSION'" case "$GCC_VERSION" in 3.4.*|3.5.*) From b591d3434a16f079d012cb0cdb4853906e8f1470 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Thu, 7 Apr 2005 17:42:32 +0400 Subject: [PATCH 33/34] BUG#8877: Post-merge fixes. --- sql/sql_select.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 21e8316bb9e..09fb0b3c5ae 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2231,6 +2231,8 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if (s->dependent & table->map) s->dependent |= table->reginfo.join_tab->dependent; } + if (s->dependent) + s->table->maybe_null= 1; } /* Catch illegal cross references for outer joins */ for (i= 0, s= stat ; i < table_count ; i++, s++) @@ -2623,6 +2625,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, static void add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond, + Field *field, bool eq_func, Item **value, uint num_values, table_map usable_tables) { uint exists_optimize= 0; @@ -2758,7 +2761,7 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond, static void add_key_equal_fields(KEY_FIELD **key_fields, uint and_level, - COND *cond, Item_field *field_item, + Item_func *cond, Item_field *field_item, bool eq_func, Item **val, uint num_values, table_map usable_tables) { @@ -2899,7 +2902,7 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level, */ while ((item= it++)) { - add_key_field(key_fields, *and_level, cond, item->field, + add_key_field(key_fields, *and_level, cond_func, item->field, TRUE, &const_item, 1, usable_tables); } } @@ -2919,7 +2922,7 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level, { if (!field->eq(item->field)) { - add_key_field(key_fields, *and_level, cond, field, + add_key_field(key_fields, *and_level, cond_func, field, TRUE, (Item **) &item, 1, usable_tables); } } @@ -3139,7 +3142,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, { NESTED_JOIN *nested_join= embedding->nested_join; if (nested_join->join_list.head() == tab) - add_key_fields(join_tab, &end, &and_level, embedding->on_expr, + add_key_fields(&end, &and_level, embedding->on_expr, nested_join->used_tables); } } @@ -5174,7 +5177,7 @@ static void add_not_null_conds(JOIN *join) null_rej->quick_fix_field(); DBUG_EXECUTE("where",print_where(null_rej, - referred_tab->table->table_name);); + referred_tab->table->alias);); add_cond_and_fix(&referred_tab->select_cond, null_rej); } } @@ -5454,7 +5457,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) tab->select_cond= sel->cond= NULL; sel->head=tab->table; - DBUG_EXECUTE("where",print_where(tmp,tab->table->table_name);); + DBUG_EXECUTE("where",print_where(tmp,tab->table->alias);); if (tab->quick) { /* Use quick key read if it's a constant and it's not used From 0cd5877b025f77bf8a33b9ac6dd8eaea9cc6edcb Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Thu, 7 Apr 2005 17:44:48 +0400 Subject: [PATCH 34/34] Post-review fixes: local variable renamed --- sql/sql_select.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 248ed06b6b3..8a668b64edf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3532,14 +3532,14 @@ static void add_not_null_conds(JOIN *join) DBUG_ASSERT(item->type() == Item::FIELD_ITEM); Item_field *not_null_item= (Item_field*)item; JOIN_TAB *referred_tab= not_null_item->field->table->reginfo.join_tab; - Item_func_isnotnull *null_rej; - if (!(null_rej= new Item_func_isnotnull(not_null_item))) + Item_func_isnotnull *notnull; + if (!(notnull= new Item_func_isnotnull(not_null_item))) DBUG_VOID_RETURN; - null_rej->quick_fix_field(); - DBUG_EXECUTE("where",print_where(null_rej, + notnull->quick_fix_field(); + DBUG_EXECUTE("where",print_where(notnull, referred_tab->table->table_name);); - add_cond_and_fix(&referred_tab->select_cond, null_rej); + add_cond_and_fix(&referred_tab->select_cond, notnull); } } }