From d178780289651e59baf16a36a8e451509eb8bb42 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Sun, 7 Nov 2010 12:14:45 +0200 Subject: [PATCH 1/5] Updated state and version number --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index fedad95edab..72cde9def8c 100644 --- a/configure.in +++ b/configure.in @@ -12,7 +12,7 @@ dnl dnl When changing the major version number please also check the switch dnl statement in mysqlbinlog::check_master_version(). You may also need dnl to update version.c in ndb. -AC_INIT([MariaDB Server], [5.2.2-MariaDB-gamma], [], [mysql]) +AC_INIT([MariaDB Server], [5.2.3-MariaDB], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM From 7b047a31a09a7999353232cb6407b4e6338d5b70 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Mon, 8 Nov 2010 13:43:54 +0200 Subject: [PATCH 2/5] Make SQLString reallocation addaptive Avoid doing reallocs Prealloc some strings / provide extension allocation size to some strings This gave a 25 % speedup in some mysql-test-run tests. mysys/safemalloc.c: More DBUG_PRINT sql/net_serv.cc: Make all mallocs() look the similar. (just-for-safety fix) sql/protocol.cc: Ensure that communication packet buffer is allocated. (It's freed by stored precedures and some DLL statements) sql/sp.cc: Fixed valgrind warning sql/sql_select.cc: Set extent allocation for buffer that has a lot of append() calls. sql/sql_show.cc: Fixed wrong usage of string buffer. Old code worked in test suite 'just-by-chance' sql/sql_string.cc: Call realloc_with_extra_if_needed() in append() functions. sql/sql_string.h: Added 'extra_alloc' member, to specify chunck size for realloc(). extra_alloc is addaptive to catch cases where preallocation of buffers is not done properly. Simplified free() to allow compiler to optimize things better (and to keep things consistent). Fixed shrink() to take into account the extra memory added to the Alloced_length in realloc(). This saves us a realloc() per query. sql/sql_test.cc: Set extent allocation for buffer that has a lot of append() calls. sql/table.cc: Set extent allocation for buffer that has a lot of append() calls. --- mysys/safemalloc.c | 4 ++++ sql/net_serv.cc | 4 ++-- sql/protocol.cc | 3 +++ sql/sp.cc | 2 +- sql/sql_select.cc | 1 + sql/sql_show.cc | 2 +- sql/sql_string.cc | 18 ++++++++--------- sql/sql_string.h | 48 +++++++++++++++++++++++++++++----------------- sql/sql_test.cc | 3 ++- sql/table.cc | 4 +++- 10 files changed, 56 insertions(+), 33 deletions(-) diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index 0d0ae2dabe5..0e489263c69 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -224,6 +224,8 @@ void *_myrealloc(register void *ptr, register size_t size, struct st_irem *irem; char *data; DBUG_ENTER("_myrealloc"); + DBUG_PRINT("my",("ptr: 0x%lx size: %lu my_flags: %d", (long) ptr, + (ulong) size, MyFlags)); if (!ptr && (MyFlags & MY_ALLOW_ZERO_PTR)) DBUG_RETURN(_mymalloc(size, filename, lineno, MyFlags)); @@ -245,6 +247,8 @@ void *_myrealloc(register void *ptr, register size_t size, (void) fflush(stderr); DBUG_RETURN((uchar*) NULL); } + DBUG_PRINT("my", ("old_size: %lu -> new_size: %lu", + (ulong) irem->datasize, (ulong) size)); if ((data= _mymalloc(size,filename,lineno,MyFlags))) /* Allocate new area */ { diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 4796a5601bf..6a4079b1fef 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -116,7 +116,7 @@ my_bool my_net_init(NET *net, Vio* vio) net->vio = vio; my_net_local_init(net); /* Set some limits */ if (!(net->buff=(uchar*) my_malloc((size_t) net->max_packet+ - NET_HEADER_SIZE + COMP_HEADER_SIZE, + NET_HEADER_SIZE + COMP_HEADER_SIZE +1, MYF(MY_WME)))) DBUG_RETURN(1); net->buff_end=net->buff+net->max_packet; @@ -580,7 +580,7 @@ net_real_write(NET *net,const uchar *packet, size_t len) uchar *b; uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE; if (!(b= (uchar*) my_malloc(len + NET_HEADER_SIZE + - COMP_HEADER_SIZE, MYF(MY_WME)))) + COMP_HEADER_SIZE + 1, MYF(MY_WME)))) { net->error= 2; net->last_errno= ER_OUT_OF_RESOURCES; diff --git a/sql/protocol.cc b/sql/protocol.cc index 8a9d712077d..70b171fa652 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -632,6 +632,9 @@ bool Protocol::send_fields(List *list, uint flags) uint count= 0; #endif + /* We have to reallocate it here as a stored procedure may have reset it */ + (void) local_packet->alloc(thd->variables.net_buffer_length); + while ((item=it++)) { char *pos; diff --git a/sql/sp.cc b/sql/sp.cc index ebf2b3c360d..68e2f19fd47 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -785,7 +785,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, { Parser_state parser_state; - if (parser_state.init(thd, defstr.c_ptr(), defstr.length())) + if (parser_state.init(thd, defstr.c_ptr_safe(), defstr.length())) { ret= SP_INTERNAL_ERROR; goto end; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e185996126d..e6be979becb 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15997,6 +15997,7 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, char buff[256]; String str(buff,sizeof(buff),&my_charset_bin); str.length(0); + str.extra_allocation(1024); item->print(&str, QT_ORDINARY); item_field->name= sql_strmake(str.ptr(),str.length()); } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8f1f938d36e..265c86f55e7 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4329,7 +4329,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, base_type [(dimension)] [unsigned] [zerofill]. For DATA_TYPE column we extract only base type. */ - tmp_buff= strchr(type.ptr(), '('); + tmp_buff= strchr(type.c_ptr_safe(), '('); if (!tmp_buff) /* if there is no dimention part then check the presence of diff --git a/sql/sql_string.cc b/sql/sql_string.cc index eafd8502706..b359b2a7168 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -411,7 +411,7 @@ bool String::append(const String &s) { if (s.length()) { - if (realloc(str_length+s.length())) + if (realloc_with_extra_if_needed(str_length+s.length())) return TRUE; memcpy(Ptr+str_length,s.ptr(),s.length()); str_length+=s.length(); @@ -436,7 +436,7 @@ bool String::append(const char *s,uint32 arg_length) { uint32 add_length=arg_length * str_charset->mbmaxlen; uint dummy_errors; - if (realloc(str_length+ add_length)) + if (realloc_with_extra_if_needed(str_length+ add_length)) return TRUE; str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset, s, arg_length, &my_charset_latin1, @@ -447,7 +447,7 @@ bool String::append(const char *s,uint32 arg_length) /* For an ASCII compatinble string we can just append. */ - if (realloc(str_length+arg_length)) + if (realloc_with_extra_if_needed(str_length+arg_length)) return TRUE; memcpy(Ptr+str_length,s,arg_length); str_length+=arg_length; @@ -478,14 +478,14 @@ bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs) { uint32 add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen; uint dummy_errors; - if (realloc(str_length + add_length)) + if (realloc_with_extra_if_needed(str_length + add_length)) return TRUE; str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset, s, arg_length, cs, &dummy_errors); } else { - if (realloc(str_length + arg_length)) + if (realloc_with_extra_if_needed(str_length + arg_length)) return TRUE; memcpy(Ptr + str_length, s, arg_length); str_length+= arg_length; @@ -497,7 +497,7 @@ bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs) #ifdef TO_BE_REMOVED bool String::append(FILE* file, uint32 arg_length, myf my_flags) { - if (realloc(str_length+arg_length)) + if (realloc_with_extra_if_needed(str_length+arg_length)) return TRUE; if (my_fread(file, (uchar*) Ptr + str_length, arg_length, my_flags)) { @@ -511,7 +511,7 @@ bool String::append(FILE* file, uint32 arg_length, myf my_flags) bool String::append(IO_CACHE* file, uint32 arg_length) { - if (realloc(str_length+arg_length)) + if (realloc_with_extra_if_needed(str_length+arg_length)) return TRUE; if (my_b_read(file, (uchar*) Ptr + str_length, arg_length)) { @@ -527,7 +527,7 @@ bool String::append_with_prefill(const char *s,uint32 arg_length, { int t_length= arg_length > full_length ? arg_length : full_length; - if (realloc(str_length + t_length)) + if (realloc_with_extra_if_needed(str_length + t_length)) return TRUE; t_length= full_length - arg_length; if (t_length > 0) @@ -636,7 +636,7 @@ bool String::replace(uint32 offset,uint32 arg_length, { if (diff) { - if (realloc(str_length+(uint32) diff)) + if (realloc_with_extra_if_needed(str_length+(uint32) diff)) return TRUE; bmove_upp((uchar*) Ptr+str_length+diff, (uchar*) Ptr+str_length, str_length-offset-arg_length); diff --git a/sql/sql_string.h b/sql/sql_string.h index e595de47f99..dc9122a4fcb 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -53,23 +53,24 @@ uint convert_to_printable(char *to, size_t to_len, class String { char *Ptr; - uint32 str_length,Alloced_length; + uint32 str_length,Alloced_length, extra_alloc; bool alloced; CHARSET_INFO *str_charset; public: String() { - Ptr=0; str_length=Alloced_length=0; alloced=0; + Ptr=0; str_length=Alloced_length=extra_alloc=0; alloced=0; str_charset= &my_charset_bin; } String(uint32 length_arg) { - alloced=0; Alloced_length=0; (void) real_alloc(length_arg); + alloced=0; Alloced_length= extra_alloc= 0; (void) real_alloc(length_arg); str_charset= &my_charset_bin; } String(const char *str, CHARSET_INFO *cs) { - Ptr=(char*) str; str_length=(uint) strlen(str); Alloced_length=0; alloced=0; + Ptr=(char*) str; str_length= (uint32) strlen(str); + Alloced_length= extra_alloc= 0; alloced=0; str_charset=cs; } /* @@ -79,18 +80,18 @@ public: */ String(const char *str,uint32 len, CHARSET_INFO *cs) { - Ptr=(char*) str; str_length=len; Alloced_length=0; alloced=0; + Ptr=(char*) str; str_length=len; Alloced_length= extra_alloc=0; alloced=0; str_charset=cs; } String(char *str,uint32 len, CHARSET_INFO *cs) { - Ptr=(char*) str; Alloced_length=str_length=len; alloced=0; + Ptr=(char*) str; Alloced_length=str_length=len; extra_alloc= 0; alloced=0; str_charset=cs; } String(const String &str) { Ptr=str.Ptr ; str_length=str.str_length ; - Alloced_length=str.Alloced_length; alloced=0; + Alloced_length=str.Alloced_length; extra_alloc= 0; alloced=0; str_charset=str.str_charset; } static void *operator new(size_t size, MEM_ROOT *mem_root) throw () @@ -106,8 +107,10 @@ public: inline CHARSET_INFO *charset() const { return str_charset; } inline uint32 length() const { return str_length;} inline uint32 alloced_length() const { return Alloced_length;} + inline uint32 extra_allocation() const { return extra_alloc;} inline char& operator [] (uint32 i) const { return Ptr[i]; } inline void length(uint32 len) { str_length=len ; } + inline void extra_allocation(uint32 len) { extra_alloc= len; } inline bool is_empty() const { return (str_length == 0); } inline void mark_as_const() { Alloced_length= 0;} inline const char *ptr() const { return Ptr; } @@ -136,23 +139,21 @@ public: { DBUG_ASSERT(&str != this); free(); - Ptr=(char*) str.ptr()+offset; str_length=arg_length; alloced=0; + Ptr=(char*) str.ptr()+offset; str_length=arg_length; if (str.Alloced_length) Alloced_length=str.Alloced_length-offset; - else - Alloced_length=0; str_charset=str.str_charset; } inline void set(char *str,uint32 arg_length, CHARSET_INFO *cs) { free(); - Ptr=(char*) str; str_length=Alloced_length=arg_length ; alloced=0; + Ptr=(char*) str; str_length=Alloced_length=arg_length; str_charset=cs; } inline void set(const char *str,uint32 arg_length, CHARSET_INFO *cs) { free(); - Ptr=(char*) str; str_length=arg_length; Alloced_length=0 ; alloced=0; + Ptr=(char*) str; str_length=arg_length; str_charset=cs; } bool set_ascii(const char *str, uint32 arg_length); @@ -203,11 +204,11 @@ public: if (alloced) { alloced=0; - Alloced_length=0; my_free(Ptr,MYF(0)); - Ptr=0; - str_length=0; /* Safety */ } + Alloced_length= extra_alloc= 0; + Ptr=0; + str_length=0; /* Safety */ } inline bool alloc(uint32 arg_length) { @@ -217,9 +218,21 @@ public: } bool real_alloc(uint32 arg_length); // Empties old string bool realloc(uint32 arg_length); - inline void shrink(uint32 arg_length) // Shrink buffer + bool realloc_with_extra(uint32 arg_length) + { + if (extra_alloc < 4096) + extra_alloc= extra_alloc*2+128; + return realloc(arg_length + extra_alloc); + } + bool realloc_with_extra_if_needed(uint32 arg_length) { if (arg_length < Alloced_length) + return 0; + return realloc_with_extra(arg_length); + } + inline void shrink(uint32 arg_length) // Shrink buffer + { + if (ALIGN_SIZE(arg_length+1) < Alloced_length) { char *new_ptr; if (!(new_ptr=(char*) my_realloc(Ptr,arg_length,MYF(0)))) @@ -246,7 +259,6 @@ public: DBUG_ASSERT(!s.uses_buffer_owned_by(this)); free(); Ptr=s.Ptr ; str_length=s.str_length ; Alloced_length=s.Alloced_length; - alloced=0; } return *this; } @@ -281,7 +293,7 @@ public: } else { - if (realloc(str_length+1)) + if (realloc_with_extra(str_length + 1)) return 1; Ptr[str_length++]=chr; } diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 541fcc155af..185c0a02799 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -57,9 +57,10 @@ print_where(COND *cond,const char *info, enum_query_type query_type) { if (cond) { - char buff[256]; + char buff[1024]; String str(buff,(uint32) sizeof(buff), system_charset_info); str.length(0); + str.extra_allocation(1024); cond->print(&str, query_type); str.append('\0'); DBUG_LOCK_FILE; diff --git a/sql/table.cc b/sql/table.cc index 7a2581d5ab8..45c1f5ab378 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3328,11 +3328,13 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) is backward compatible. */ } - char buffer[STRING_BUFFER_USUAL_SIZE]; + char buffer[1024]; for (i=0 ; i < table_def->count; i++, field_def++) { String sql_type(buffer, sizeof(buffer), system_charset_info); sql_type.length(0); + /* Allocate min 256 characters at once */ + sql_type.extra_allocation(256); if (i < table->s->fields) { Field *field= table->field[i]; From 9e008bd7261028cdac77ef995c68cba749e473e3 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Tue, 9 Nov 2010 10:17:36 +0200 Subject: [PATCH 3/5] Removed version number from test case mysql-test/suite/maria/t/compat_aliases.test: Removed column with version number sql/sql_show.cc: Fixed compiler warning --- mysql-test/suite/maria/r/compat_aliases.result | 4 ++-- mysql-test/suite/maria/t/compat_aliases.test | 1 + sql/sql_show.cc | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/maria/r/compat_aliases.result b/mysql-test/suite/maria/r/compat_aliases.result index db33737ebbc..bcc9ece0986 100644 --- a/mysql-test/suite/maria/r/compat_aliases.result +++ b/mysql-test/suite/maria/r/compat_aliases.result @@ -1,7 +1,7 @@ select * from information_schema.plugins where plugin_name like '%aria'; PLUGIN_NAME PLUGIN_VERSION PLUGIN_STATUS PLUGIN_TYPE PLUGIN_TYPE_VERSION PLUGIN_LIBRARY PLUGIN_LIBRARY_VERSION PLUGIN_AUTHOR PLUGIN_DESCRIPTION PLUGIN_LICENSE PLUGIN_MATURITY PLUGIN_AUTH_VERSION -Maria 1.5 ACTIVE DAEMON 50202.0 NULL NULL Monty Program Ab Compatibility aliases for the Aria engine GPL Gamma 1.5 -Aria 1.5 ACTIVE STORAGE ENGINE 50202.0 NULL NULL Monty Program Ab Crash-safe tables with MyISAM heritage GPL Gamma 1.5 +Maria 1.5 ACTIVE DAEMON # NULL NULL Monty Program Ab Compatibility aliases for the Aria engine GPL Gamma 1.5 +Aria 1.5 ACTIVE STORAGE ENGINE # NULL NULL Monty Program Ab Crash-safe tables with MyISAM heritage GPL Gamma 1.5 select maria_vars.variable_name, aria_vars.variable_name from information_schema.session_variables as maria_vars left join information_schema.session_variables as aria_vars diff --git a/mysql-test/suite/maria/t/compat_aliases.test b/mysql-test/suite/maria/t/compat_aliases.test index d48128a3041..7b94d24e643 100644 --- a/mysql-test/suite/maria/t/compat_aliases.test +++ b/mysql-test/suite/maria/t/compat_aliases.test @@ -3,6 +3,7 @@ # command-line options). They should match aria* variables. # +--replace_column 5 # select * from information_schema.plugins where plugin_name like '%aria'; select maria_vars.variable_name, aria_vars.variable_name from diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8f1f938d36e..e721175cbe5 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4064,7 +4064,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, } else { - char option_buff[350],*ptr; + char option_buff[350]; String str(option_buff,sizeof(option_buff), system_charset_info); TABLE *show_table= tables->table; TABLE_SHARE *share= show_table->s; From 52090a443493f5a8410094b43bfa5cdde8c32f5d Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 24 Nov 2010 00:08:48 +0200 Subject: [PATCH 4/5] Code cleanup to get fewer reallocs() during execution. - Changed TABLE->alias to String to get fewer reallocs when alias are used. - Preallocate some buffers Changed some String->c_ptr() -> String->ptr() when \0 is not needed. Fixed wrong usage of String->ptr() when we need a \0 terminated string. Use my_strtod() instead of my_atof() to avoid having to add \0 to string. c_ptr() -> c_ptr_safe() to avoid warnings from valgrind. zr sql/event_db_repository.cc: Update usage of TABLE->alias sql/event_scheduler.cc: c_ptr() -> c_ptr_safe() sql/events.cc: c_ptr() -> ptr() as \0 was not needed sql/field.cc: Update usage of TABLE->alias sql/field.h: Update usage of TABLE->alias sql/ha_partition.cc: Update usage of TABLE->alias sql/handler.cc: Update usage of TABLE->alias Fixed wrong usage of str.ptr() sql/item.cc: Fixed error where code wrongly assumed string was \0 terminated. sql/item_func.cc: c_ptr() -> c_ptr_safe() Update usage of TABLE->alias sql/item_sum.h: Use my_strtod() instead of my_atof() to avoid having to add \0 to string sql/lock.cc: Update usage of TABLE->alias sql/log.cc: c_ptr() -> ptr() as \0 was not needed sql/log_event.cc: c_ptr_quick() -> ptr() as \0 was not needed sql/opt_range.cc: ptr() -> c_ptr() as \0 is needed sql/opt_subselect.cc: Update usage of TABLE->alias sql/opt_table_elimination.cc: Update usage of TABLE->alias sql/set_var.cc: ptr() -> c_ptr() as \0 is needed c_ptr() -> c_ptr_safe() sql/sp.cc: c_ptr() -> ptr() as \0 was not needed sql/sp_rcontext.cc: Update usage of TABLE->alias sql/sql_base.cc: Preallocate buffers Update usage of TABLE->alias sql/sql_class.cc: Fix arguments to sprintf() to work even if string is not \0 terminated sql/sql_insert.cc: Update usage of TABLE->alias c_ptr() -> ptr() as \0 was not needed sql/sql_load.cc: Preallocate buffers Trivial optimizations sql/sql_parse.cc: Trivial optimization sql/sql_plugin.cc: c_ptr() -> ptr() as \0 was not needed sql/sql_select.cc: Update usage of TABLE->alias sql/sql_show.cc: Update usage of TABLE->alias sql/sql_string.h: Added move() function to move allocated memory from one object to another. sql/sql_table.cc: Update usage of TABLE->alias c_ptr() -> c_ptr_safe() sql/sql_test.cc: ptr() -> c_ptr_safe() sql/sql_trigger.cc: Update usage of TABLE->alias c_ptr() -> c_ptr_safe() sql/sql_update.cc: Update usage of TABLE->alias sql/sql_view.cc: ptr() -> c_ptr_safe() sql/sql_yacc.yy: ptr() -> c_ptr() sql/table.cc: Update usage of TABLE->alias sql/table.h: Changed TABLE->alias to String to get fewer reallocs when alias are used. storage/federatedx/ha_federatedx.cc: Use c_ptr_safe() to ensure strings are \0 terminated. storage/maria/ha_maria.cc: Update usage of TABLE->alias storage/myisam/ha_myisam.cc: Update usage of TABLE->alias storage/xtradb/row/row0sel.c: Ensure that null bits in record are properly reset. (Old code didn't work as row_search_for_mysql() can be called twice while reading fields from one row. --- sql/event_db_repository.cc | 2 +- sql/event_scheduler.cc | 2 +- sql/events.cc | 4 +- sql/field.cc | 4 +- sql/field.h | 9 ++++- sql/ha_partition.cc | 6 ++- sql/handler.cc | 8 ++-- sql/item.cc | 27 ++++++++----- sql/item_func.cc | 4 +- sql/item_sum.h | 9 ++++- sql/lock.cc | 2 +- sql/log.cc | 4 +- sql/log_event.cc | 2 +- sql/opt_range.cc | 5 ++- sql/opt_subselect.cc | 7 ++-- sql/opt_table_elimination.cc | 9 +++-- sql/set_var.cc | 20 +++++---- sql/sp.cc | 4 +- sql/sp_rcontext.cc | 2 +- sql/sql_base.cc | 63 +++++++++++++++-------------- sql/sql_class.cc | 6 +-- sql/sql_insert.cc | 14 ++++--- sql/sql_load.cc | 15 ++++--- sql/sql_parse.cc | 3 +- sql/sql_plugin.cc | 2 +- sql/sql_select.cc | 17 +++++--- sql/sql_show.cc | 6 +-- sql/sql_string.h | 9 +++++ sql/sql_table.cc | 6 +-- sql/sql_test.cc | 8 ++-- sql/sql_trigger.cc | 7 +--- sql/sql_update.cc | 3 +- sql/sql_view.cc | 4 +- sql/sql_yacc.yy | 2 +- sql/table.cc | 28 +++++++------ sql/table.h | 2 +- storage/federatedx/ha_federatedx.cc | 9 +++-- storage/maria/ha_maria.cc | 6 +-- storage/myisam/ha_myisam.cc | 6 +-- storage/xtradb/row/row0sel.c | 16 +++----- 40 files changed, 206 insertions(+), 156 deletions(-) diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index d1fa971847b..c1a64446c12 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -212,7 +212,7 @@ mysql_event_fill_row(THD *thd, Safety: this can only happen if someone started the server and then altered mysql.event. */ - my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED, MYF(0), table->alias, + my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED, MYF(0), table->alias.c_ptr(), (int) ET_FIELD_COUNT, table->s->fields); DBUG_RETURN(TRUE); } diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 8446fe75c8f..4d6636eedb2 100755 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -100,7 +100,7 @@ Event_worker_thread::print_warnings(THD *thd, Event_job_data *et) err_msg.append(err->msg, strlen(err->msg), system_charset_info); DBUG_ASSERT(err->level < 3); (sql_print_message_handlers[err->level])("%*s", err_msg.length(), - err_msg.c_ptr()); + err_msg.c_ptr_safe()); } DBUG_VOID_RETURN; } diff --git a/sql/events.cc b/sql/events.cc index 1b794edb5ec..3713266aaa6 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -480,7 +480,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, } /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER will be written into the binary log as the definer for the SQL thread. */ - ret= write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); + ret= write_bin_log(thd, TRUE, log_query.ptr(), log_query.length()); } } pthread_mutex_unlock(&LOCK_event_metadata); @@ -779,7 +779,7 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol) protocol->store(et->name.str, et->name.length, system_charset_info); protocol->store(sql_mode.str, sql_mode.length, system_charset_info); protocol->store(tz_name->ptr(), tz_name->length(), system_charset_info); - protocol->store(show_str.c_ptr(), show_str.length(), + protocol->store(show_str.ptr(), show_str.length(), et->creation_ctx->get_client_cs()); protocol->store(et->creation_ctx->get_client_cs()->csname, strlen(et->creation_ctx->get_client_cs()->csname), diff --git a/sql/field.cc b/sql/field.cc index bf496406fd6..4194c6a8939 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1536,9 +1536,9 @@ void Field::make_field(Send_field *field) } else field->org_table_name= field->db_name= ""; - if (orig_table && orig_table->alias) + if (orig_table && orig_table->alias.ptr()) { - field->table_name= orig_table->alias; + field->table_name= orig_table->alias.ptr(); field->org_col_name= field_name; } else diff --git a/sql/field.h b/sql/field.h index ca400caac59..0161f69ac4d 100644 --- a/sql/field.h +++ b/sql/field.h @@ -131,7 +131,8 @@ public: */ struct st_table *table; // Pointer for table struct st_table *orig_table; // Pointer to original table - const char **table_name, *field_name; + const char * const *table_name; + const char *field_name; /** reference to the list of options or NULL */ engine_option_value *option_list; void *option_struct; /* structure with parsed options */ @@ -551,10 +552,14 @@ public: return (op_result == E_DEC_OVERFLOW); } int warn_if_overflow(int op_result); + void set_table_name(String *alias) + { + table_name= &alias->Ptr; + } void init(TABLE *table_arg) { orig_table= table= table_arg; - table_name= &table_arg->alias; + set_table_name(&table_arg->alias); } /* maximum possible display length */ diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index b777b26bab0..78dd353c09d 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1097,7 +1097,8 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, error != HA_ADMIN_ALREADY_DONE && error != HA_ADMIN_TRY_ALTER) { - print_admin_msg(thd, "error", table_share->db.str, table->alias, + print_admin_msg(thd, "error", table_share->db.str, + table->alias.c_ptr(), opt_op_name[flag], "Subpartition %s returned error", sub_elem->partition_name); @@ -1124,7 +1125,8 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, error != HA_ADMIN_ALREADY_DONE && error != HA_ADMIN_TRY_ALTER) { - print_admin_msg(thd, "error", table_share->db.str, table->alias, + print_admin_msg(thd, "error", table_share->db.str, + table->alias.c_ptr(), opt_op_name[flag], "Partition %s returned error", part_elem->partition_name); } diff --git a/sql/handler.cc b/sql/handler.cc index c931b689842..6e5cfb738bb 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2009,7 +2009,8 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, dummy_share.db.length= strlen(db); dummy_share.table_name.str= (char*) alias; dummy_share.table_name.length= strlen(alias); - dummy_table.alias= alias; + dummy_table.alias.set(alias, dummy_share.table_name.length, + table_alias_charset); file->change_table_ptr(&dummy_table, &dummy_share); @@ -2852,11 +2853,12 @@ void handler::print_error(int error, myf errflag) { const char* engine= table_type(); if (temporary) - my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine); + my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.c_ptr(), + engine); else { SET_FATAL_ERROR; - my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine); + my_error(ER_GET_ERRMSG, MYF(0), error, str.c_ptr(), engine); } } else diff --git a/sql/item.cc b/sql/item.cc index 1419c9c3e6e..7b6f6e89a1f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -781,7 +781,8 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs) } if (cs->ctype) { - uint orig_len= length; + const char *str_start= str; + /* This will probably need a better implementation in the future: a function in CHARSET_INFO structure. @@ -791,16 +792,20 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs) length--; str++; } - if (orig_len != length && !is_autogenerated_name) + if (str != str_start && !is_autogenerated_name) { + char buff[SAFE_NAME_LEN]; + strmake(buff, str_start, + min(sizeof(buff)-1, length + (int) (str-str_start))); + if (length == 0) push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NAME_BECOMES_EMPTY, ER(ER_NAME_BECOMES_EMPTY), - str + length - orig_len); + buff); else push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_REMOVED_SPACES, ER(ER_REMOVED_SPACES), - str + length - orig_len); + buff); } } if (!my_charset_same(cs, system_charset_info)) @@ -2566,14 +2571,12 @@ double_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end) tmp= my_strntod(cs, (char*) cptr, end - cptr, &end, &error); if (error || (end != org_end && !check_if_only_end_space(cs, end, org_end))) { - /* - We can use str_value.ptr() here as Item_string is gurantee to put an - end \0 here. - */ + char buff[80]; + strmake(buff, cptr, min(sizeof(buff)-1, (size_t) (org_end-cptr))); push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE, ER(ER_TRUNCATED_WRONG_VALUE), "DOUBLE", - cptr); + buff); } return tmp; } @@ -2582,8 +2585,10 @@ double_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end) double Item_string::val_real() { DBUG_ASSERT(fixed == 1); - return double_from_string_with_check (str_value.charset(), str_value.ptr(), - (char *) str_value.ptr() + str_value.length()); + return double_from_string_with_check(str_value.charset(), + str_value.ptr(), + (char *) str_value.ptr() + + str_value.length()); } diff --git a/sql/item_func.cc b/sql/item_func.cc index c4eb6cdc2aa..a2c8b9f3983 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -5812,7 +5812,7 @@ Item_func_sp::func_name() const qname.append('.'); } append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length); - return qname.ptr(); + return qname.c_ptr_safe(); } @@ -5868,7 +5868,7 @@ Item_func_sp::init_result_field(THD *thd) */ share= dummy_table->s; - dummy_table->alias = ""; + dummy_table->alias.set("", 0, table_alias_charset); dummy_table->maybe_null = maybe_null; dummy_table->in_use= thd; dummy_table->copy_blobs= TRUE; diff --git a/sql/item_sum.h b/sql/item_sum.h index b5516792676..46e5ae76ab1 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1274,8 +1274,13 @@ public: void make_unique(); double val_real() { - String *res; res=val_str(&str_value); - return res ? my_atof(res->c_ptr()) : 0.0; + int error; + const char *end; + String *res; + if (!(res= val_str(&str_value))) + return 0.0; + end= res->ptr() + res->length(); + return (my_strtod(res->ptr(), (char**) &end, &error)); } longlong val_int() { diff --git a/sql/lock.cc b/sql/lock.cc index 566275c5ea2..7c569bf7cfc 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -903,7 +903,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, *write_lock_used=table; if (table->db_stat & HA_READ_ONLY) { - my_error(ER_OPEN_AS_READONLY,MYF(0),table->alias); + my_error(ER_OPEN_AS_READONLY,MYF(0),table->alias.c_ptr()); /* Clear the lock type of the lock data that are stored already. */ sql_lock->lock_count= (uint) (locks - sql_lock->locks); reset_lock_data(sql_lock); diff --git a/sql/log.cc b/sql/log.cc index 07d9890ff78..93a9383f731 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1751,7 +1751,7 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv) log_query.append(thd->lex->ident.str, thd->lex->ident.length)) DBUG_RETURN(1); int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); - Query_log_event qinfo(thd, log_query.c_ptr_safe(), log_query.length(), + Query_log_event qinfo(thd, log_query.ptr(), log_query.length(), TRUE, TRUE, errcode); DBUG_RETURN(mysql_bin_log.write(&qinfo)); } @@ -1773,7 +1773,7 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv) log_query.append(thd->lex->ident.str, thd->lex->ident.length)) DBUG_RETURN(1); int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); - Query_log_event qinfo(thd, log_query.c_ptr_safe(), log_query.length(), + Query_log_event qinfo(thd, log_query.ptr(), log_query.length(), TRUE, TRUE, errcode); DBUG_RETURN(mysql_bin_log.write(&qinfo)); } diff --git a/sql/log_event.cc b/sql/log_event.cc index fa7bb01077d..32552bfe85f 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -568,7 +568,7 @@ append_query_string(CHARSET_INFO *csinfo, if (to->reserve(orig_len + from->length()*2+3)) return 1; - beg= to->c_ptr_quick() + to->length(); + beg= (char*) to->ptr() + to->length(); ptr= beg; if (csinfo->escape_with_backslash_is_dangerous) ptr= str_to_hex(ptr, from->ptr(), from->length()); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index d77893bdb1c..16dec381c8a 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -11130,7 +11130,8 @@ static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map, if (!tmp.length()) tmp.append(STRING_WITH_LEN("(empty)")); - DBUG_PRINT("info", ("SEL_TREE: 0x%lx (%s) scans: %s", (long) tree, msg, tmp.ptr())); + DBUG_PRINT("info", ("SEL_TREE: 0x%lx (%s) scans: %s", (long) tree, msg, + tmp.c_ptr())); DBUG_VOID_RETURN; } @@ -11153,7 +11154,7 @@ static void print_ror_scans_arr(TABLE *table, const char *msg, } if (!tmp.length()) tmp.append(STRING_WITH_LEN("(empty)")); - DBUG_PRINT("info", ("ROR key scans (%s): %s", msg, tmp.ptr())); + DBUG_PRINT("info", ("ROR key scans (%s): %s", msg, tmp.c_ptr())); DBUG_VOID_RETURN; } diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 5973c95d101..5428467b850 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1030,7 +1030,7 @@ int pull_out_semijoin_tables(JOIN *join) pulled_a_table= TRUE; pulled_tables |= tbl->table->map; DBUG_PRINT("info", ("Table %s pulled out (reason: func dep)", - tbl->table->alias)); + tbl->table->alias.c_ptr())); /* Pulling a table out of uncorrelated subquery in general makes makes it correlated. See the NOTE to this funtion. @@ -2605,7 +2605,8 @@ TABLE *create_duplicate_weedout_tmp_table(THD *thd, thd->mem_root= &table->mem_root; table->field=reg_field; - table->alias= "weedout-tmp"; + table->alias.set("weedout-tmp", sizeof("weedout-tmp")-1, + table_alias_charset); table->reginfo.lock_type=TL_WRITE; /* Will be updated */ table->db_stat=HA_OPEN_KEYFILE+HA_OPEN_RNDFILE; table->map=1; @@ -2737,7 +2738,7 @@ TABLE *create_duplicate_weedout_tmp_table(THD *thd, else recinfo->type=FIELD_NORMAL; - field->table_name= &table->alias; + field->set_table_name(&table->alias); } //param->recinfo=recinfo; diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc index 1e4e87ebac7..be1471b7e2c 100644 --- a/sql/opt_table_elimination.cc +++ b/sql/opt_table_elimination.cc @@ -1783,7 +1783,7 @@ static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl) JOIN_TAB *tab= tbl->table->reginfo.join_tab; if (!(join->const_table_map & tab->table->map)) { - DBUG_PRINT("info", ("Eliminated table %s", table->alias)); + DBUG_PRINT("info", ("Eliminated table %s", table->alias.c_ptr())); tab->type= JT_CONST; join->eliminated_tables |= table->map; join->const_table_map|= table->map; @@ -1818,7 +1818,7 @@ void Dep_analysis_context::dbug_print_deps() fprintf(DBUG_FILE, " equality%ld: %s -> %s.%s\n", (long)(eq_mod - equality_mods), str.c_ptr(), - eq_mod->field->table->table->alias, + eq_mod->field->table->table->alias.c_ptr(), eq_mod->field->field->field_name); } else @@ -1836,12 +1836,13 @@ void Dep_analysis_context::dbug_print_deps() if ((table_dep= table_deps[i])) { /* Print table */ - fprintf(DBUG_FILE, " table %s\n", table_dep->table->alias); + fprintf(DBUG_FILE, " table %s\n", table_dep->table->alias.c_ptr()); /* Print fields */ for (Dep_value_field *field_dep= table_dep->fields; field_dep; field_dep= field_dep->next_table_field) { - fprintf(DBUG_FILE, " field %s.%s ->", table_dep->table->alias, + fprintf(DBUG_FILE, " field %s.%s ->", + table_dep->table->alias.c_ptr(), field_dep->field->field_name); uint ofs= field_dep->bitmap_offset; for (uint bit= ofs; bit < ofs + n_equality_mods; bit++) diff --git a/sql/set_var.cc b/sql/set_var.cc index 7e00ae5aa19..193b47704c6 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -990,7 +990,7 @@ bool sys_var_str::check(THD *thd, set_var *var) if ((res=(*check_func)(thd, var)) < 0) my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), - name, var->value->str_value.ptr()); + name, var->value->str_value.c_ptr()); return res; } @@ -2281,11 +2281,15 @@ bool sys_var_character_set::check(THD *thd, set_var *var) } tmp= NULL; } - else if (!(tmp=get_charset_by_csname(res->c_ptr(),MY_CS_PRIMARY,MYF(0))) && - !(tmp=get_old_charset_by_name(res->c_ptr()))) + else { - my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), res->c_ptr()); - return 1; + const char *name= res->c_ptr_safe(); + if (!(tmp=get_charset_by_csname(name,MY_CS_PRIMARY,MYF(0))) && + !(tmp=get_old_charset_by_name(name))) + { + my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), res->c_ptr()); + return 1; + } } } else // INT_RESULT @@ -2622,7 +2626,7 @@ static int sys_check_log_path(THD *thd, set_var *var) if (!(res= var->value->val_str(&str))) goto err; - log_file_str= res->c_ptr(); + log_file_str= res->c_ptr_safe(); bzero(&f_stat, sizeof(MY_STAT)); path_length= unpack_filename(path, log_file_str); @@ -3085,7 +3089,7 @@ bool sys_var_thd_lc_time_names::check(THD *thd, set_var *var) my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL"); return 1; } - const char *locale_str= res->c_ptr(); + const char *locale_str= res->c_ptr_safe(); if (!(locale_match= my_locale_by_name(locale_str))) { my_printf_error(ER_UNKNOWN_ERROR, @@ -4117,7 +4121,7 @@ bool sys_var_thd_optimizer_switch::check(THD *thd, set_var *var) optimizer_switch_typelib.count, thd->variables.optimizer_switch, global_system_variables.optimizer_switch, - res->c_ptr_safe(), res->length(), NULL, + res->ptr(), res->length(), NULL, &error, &error_len, ¬_used); if (error_len) { diff --git a/sql/sp.cc b/sql/sp.cc index 68e2f19fd47..d2c732c2100 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1104,7 +1104,7 @@ sp_create_routine(THD *thd, int type, sp_head *sp) (sp->m_explicit_name ? sp->m_db.length : 0), sp->m_name.str, sp->m_name.length, sp->m_params.str, sp->m_params.length, - retstr.c_ptr(), retstr.length(), + retstr.ptr(), retstr.length(), sp->m_body.str, sp->m_body.length, sp->m_chistics, &(thd->lex->definer->user), &(thd->lex->definer->host))) @@ -1116,7 +1116,7 @@ sp_create_routine(THD *thd, int type, sp_head *sp) thd->variables.sql_mode= saved_mode; /* Such a statement can always go directly to binlog, no trans cache */ if (thd->binlog_query(THD::MYSQL_QUERY_TYPE, - log_query.c_ptr(), log_query.length(), + log_query.ptr(), log_query.length(), FALSE, FALSE, 0)) ret= SP_INTERNAL_ERROR; thd->variables.sql_mode= 0; diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index be8f705a53e..686e1a1346f 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -118,7 +118,7 @@ sp_rcontext::init_var_table(THD *thd) return TRUE; m_var_table->copy_blobs= TRUE; - m_var_table->alias= ""; + m_var_table->alias.set("", 0, table_alias_charset); return FALSE; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e14c8961165..a27d726f370 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1474,12 +1474,11 @@ void close_temporary_tables(THD *thd) /* Better add "if exists", in case a RESET MASTER has been done */ const char stub[]= "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS "; - uint stub_len= sizeof(stub) - 1; - char buf[256]; - String s_query= String(buf, sizeof(buf), system_charset_info); + char buf[FN_REFLEN]; + String s_query(buf, sizeof(buf), system_charset_info); bool found_user_tables= FALSE; - memcpy(buf, stub, stub_len); + s_query.copy(stub, sizeof(stub)-1, system_charset_info); /* Insertion sort of temp tables by pseudo_thread_id to build ordered list @@ -1533,19 +1532,24 @@ void close_temporary_tables(THD *thd) { bool save_thread_specific_used= thd->thread_specific_used; my_thread_id save_pseudo_thread_id= thd->variables.pseudo_thread_id; + char db_buf[FN_REFLEN]; + String db(db_buf, sizeof(db_buf), system_charset_info); + /* Set pseudo_thread_id to be that of the processed table */ thd->variables.pseudo_thread_id= tmpkeyval(thd, table); - String db; - db.append(table->s->db.str); + + db.copy(table->s->db.str, table->s->db.length, system_charset_info); + s_query.length(sizeof(stub)-1); + /* Loop forward through all tables that belong to a common database within the sublist of common pseudo_thread_id to create single DROP query */ - for (s_query.length(stub_len); + for (; table && is_user_table(table) && tmpkeyval(thd, table) == thd->variables.pseudo_thread_id && table->s->db.length == db.length() && - strcmp(table->s->db.str, db.ptr()) == 0; + memcmp(table->s->db.str, db.ptr(), db.length()) == 0; table= next) { /* @@ -1849,7 +1853,7 @@ int drop_temporary_table(THD *thd, TABLE_LIST *table_list) /* Table might be in use by some outer statement. */ if (table->query_id && table->query_id != thd->query_id) { - my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias); + my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias.c_ptr()); DBUG_RETURN(-1); } @@ -1872,7 +1876,7 @@ void close_temporary_table(THD *thd, TABLE *table, DBUG_ENTER("close_temporary_table"); DBUG_PRINT("tmptable", ("closing table: '%s'.'%s' 0x%lx alias: '%s'", table->s->db.str, table->s->table_name.str, - (long) table, table->alias)); + (long) table, table->alias.c_ptr())); /* When closing a MERGE parent or child table, detach the children @@ -2606,7 +2610,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, ("query_id: %lu server_id: %u pseudo_thread_id: %lu", (ulong) table->query_id, (uint) thd->server_id, (ulong) thd->variables.pseudo_thread_id)); - my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias); + my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias.c_ptr()); DBUG_RETURN(0); } table->query_id= thd->query_id; @@ -2643,7 +2647,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, When looking for a usable TABLE, ignore MERGE children, as they belong to their parent and cannot be used explicitly. */ - if (!my_strcasecmp(system_charset_info, table->alias, alias) && + if (!my_strcasecmp(system_charset_info, table->alias.c_ptr(), alias) && table->query_id != thd->query_id && /* skip tables already used */ !(thd->prelocked_mode && table->query_id) && !table->parent) @@ -2999,13 +3003,9 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, table->alias_name_used= my_strcasecmp(table_alias_charset, table->s->table_name.str, alias); /* Fix alias if table name changes */ - if (strcmp(table->alias, alias)) - { - uint length=(uint) strlen(alias)+1; - table->alias= (char*) my_realloc((char*) table->alias, length, - MYF(MY_WME)); - memcpy((char*) table->alias, alias, length); - } + if (strcmp(table->alias.c_ptr(), alias)) + table->alias.copy(alias, strlen(alias), table->alias.charset()); + /* These variables are also set in reopen_table() */ table->tablenr=thd->current_tablenr++; table->used_fields=0; @@ -3089,7 +3089,7 @@ bool reopen_table(TABLE *table) #ifdef EXTRA_DEBUG if (table->db_stat) sql_print_error("Table %s had a open data handler in reopen_table", - table->alias); + table->alias.c_ptr()); #endif bzero((char*) &table_list, sizeof(TABLE_LIST)); table_list.db= table->s->db.str; @@ -3100,7 +3100,7 @@ bool reopen_table(TABLE *table) DBUG_RETURN(1); // Thread was killed if (open_unireg_entry(thd, &tmp, &table_list, - table->alias, + table->alias.c_ptr(), table->s->table_cache_key.str, table->s->table_cache_key.length, thd->mem_root, 0)) @@ -3141,14 +3141,14 @@ bool reopen_table(TABLE *table) VOID(closefrm(table, 1)); // close file, free everything *table= tmp; + table->alias.move(tmp.alias); table->default_column_bitmaps(); table->file->change_table_ptr(table, table->s); - DBUG_ASSERT(table->alias != 0); + DBUG_ASSERT(table->alias.ptr() != 0); for (field=table->field ; *field ; field++) { - (*field)->table= (*field)->orig_table= table; - (*field)->table_name= &table->alias; + (*field)->init(table); } for (key=0 ; key < table->s->keys ; key++) { @@ -3275,7 +3275,7 @@ static bool reattach_merge(THD *thd, TABLE **err_tables_p) DBUG_PRINT("tcache", ("MERGE parent, attach children")); if(table->file->extra(HA_EXTRA_ATTACH_CHILDREN)) { - my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias); + my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias.c_ptr()); error= TRUE; /* Remove table from open_tables. */ *prv_p= next; @@ -3368,7 +3368,8 @@ bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old) if (!tables || (!db_stat && reopen_table(table))) { my_error(ER_CANT_REOPEN_TABLE, MYF(0), - table->alias ? table->alias : table->s->table_name.str); + table->alias.ptr() ? table->alias.c_ptr() : + table->s->table_name.str); /* If we could not allocate 'tables', we may close open tables here. If a MERGE table is affected, detach the children first. @@ -3565,7 +3566,8 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock) char *key= table->s->table_cache_key.str; uint key_length= table->s->table_cache_key.length; - DBUG_PRINT("loop", ("table_name: %s", table->alias ? table->alias : "")); + DBUG_PRINT("loop", ("table_name: %s", + table->alias.ptr() ? table->alias.c_ptr() : "")); HASH_SEARCH_STATE state; for (TABLE *search= (TABLE*) hash_first(&open_cache, (uchar*) key, key_length, &state); @@ -4359,7 +4361,7 @@ void detach_merge_children(TABLE *table, bool clear_refs) Set alias to "" to ensure that table is not used if we are in LOCK TABLES */ - ((char*) child_l->table->alias)[0]= 0; + child_l->table->alias.copy("", 0, child_l->table->alias.charset()); /* Clear the table reference to force new assignment at next open. */ child_l->table= NULL; @@ -4912,7 +4914,7 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table, if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ && (int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ) { - my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0),table->alias); + my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0),table->alias.c_ptr()); DBUG_RETURN(1); } if ((error=table->file->start_stmt(thd, lock_type))) @@ -6024,7 +6026,8 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, Field **field_ptr, *field; uint cached_field_index= *cached_field_index_ptr; DBUG_ENTER("find_field_in_table"); - DBUG_PRINT("enter", ("table: '%s', field name: '%s'", table->alias, name)); + DBUG_PRINT("enter", ("table: '%s', field name: '%s'", table->alias.c_ptr(), + name)); /* We assume here that table->field < NO_CACHED_FIELD_INDEX = UINT_MAX */ if (cached_field_index < table->s->fields && diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a1f8dbab175..688416a61a2 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -4115,8 +4115,8 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, int errcode) { DBUG_ENTER("THD::binlog_query"); - DBUG_PRINT("enter", ("qtype: %s query: '%s'", - show_query_type(qtype), query_arg)); + DBUG_PRINT("enter", ("qtype: %s query: '%-.*s'", + show_query_type(qtype), (int) query_len, query_arg)); DBUG_ASSERT(query_arg && mysql_bin_log.is_open()); /* @@ -4152,7 +4152,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, { sql_print_warning("%s Statement: %.*s", ER(ER_BINLOG_UNSAFE_STATEMENT), - MYSQL_ERRMSG_SIZE, query_arg); + (int) min(MYSQL_ERRMSG_SIZE, query_len), query_arg); binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED; } } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3c2f90e8080..9477d2ca971 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2074,6 +2074,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) TABLE *copy; TABLE_SHARE *share; uchar *bitmap; + char *copy_tmp; DBUG_ENTER("Delayed_insert::get_local_table"); /* First request insert thread to get a lock */ @@ -2106,14 +2107,15 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) the other record buffers and alignment are unnecessary. */ thd_proc_info(client_thd, "allocating local table"); - copy= (TABLE*) client_thd->alloc(sizeof(*copy)+ - (share->fields+1)*sizeof(Field**)+ - share->reclength + - share->column_bitmap_size*3); - if (!copy) + copy_tmp= (char*) client_thd->alloc(sizeof(*copy)+ + (share->fields+1)*sizeof(Field**)+ + share->reclength + + share->column_bitmap_size*3); + if (!copy_tmp) goto error; /* Copy the TABLE object. */ + copy= new (copy_tmp) TABLE; *copy= *table; /* We don't need to change the file handler here */ /* Assign the pointers for the field pointers array and the record. */ @@ -3502,7 +3504,7 @@ int select_create::write_to_binlog(bool is_trans, int errcode) Avoid to use thd->binlog_query() twice, otherwise it will print the unsafe warning twice. */ - Query_log_event ev(thd, query.c_ptr_safe(), query.length(), is_trans, + Query_log_event ev(thd, query.ptr(), query.length(), is_trans, FALSE, errcode); return mysql_bin_log.write(&ev); } diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 366c01b1754..75d9179c3bd 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -604,11 +604,15 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, size_t pl= 0; List fv; Item *item, *val; - String pfield, pfields; int n; const char *tbl= table_name_arg; const char *tdb= (thd->db != NULL ? thd->db : db_arg); - String string_buf; + char name_buffer[SAFE_NAME_LEN*2]; + char command_buffer[1024]; + String string_buf(name_buffer, sizeof(name_buffer), + system_charset_info); + String pfields(command_buffer, sizeof(command_buffer), + system_charset_info); if (!thd->db || strcmp(db_arg, thd->db)) { @@ -617,7 +621,7 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, prefix table name with database name so that it becomes a FQ name. */ - string_buf.set_charset(system_charset_info); + string_buf.length(0); string_buf.append(db_arg); string_buf.append("`"); string_buf.append("."); @@ -638,6 +642,7 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, /* prepare fields-list and SET if needed; print_query won't do that for us. */ + pfields.length(0); if (!thd->lex->field_list.is_empty()) { List_iterator li(thd->lex->field_list); @@ -682,8 +687,8 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, } } - p= pfields.c_ptr_safe(); - pl= strlen(p); + p= pfields.c_ptr_safe(); + pl= pfields.length(); if (!(load_data_query= (char *)thd->alloc(lle.get_query_buffer_length() + 1 + pl))) return TRUE; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 90ebfb8a223..bd14daa09b1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5084,9 +5084,8 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) String str(buff,(uint32) sizeof(buff), system_charset_info); str.length(0); thd->lex->unit.print(&str, QT_ORDINARY); - str.append('\0'); push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_YES, str.ptr()); + ER_YES, str.c_ptr_safe()); } if (res) result->abort(); diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index dd908e1b60e..58cc7dc93a9 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -303,7 +303,7 @@ static const char *item_val_str(struct st_mysql_value *value, Lets be nice and create a temporary string since the buffer was too small */ - return current_thd->strmake(res->c_ptr_quick(), res->length()); + return current_thd->strmake(res->ptr(), res->length()); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8e116c29a38..ec5cc0ab705 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6477,7 +6477,7 @@ static void add_not_null_conds(JOIN *join) if (notnull->fix_fields(join->thd, ¬null)) DBUG_VOID_RETURN; DBUG_EXECUTE("where",print_where(notnull, - referred_tab->table->alias, + referred_tab->table->alias.c_ptr(), QT_ORDINARY);); COND *new_cond= referred_tab->select_cond; add_cond_and_fix(&new_cond, notnull); @@ -6786,7 +6786,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) if (tmp || !cond || tab->type == JT_REF || tab->type == JT_REF_OR_NULL || tab->type == JT_EQ_REF || first_inner_tab) { - DBUG_EXECUTE("where",print_where(tmp,tab->table->alias, QT_ORDINARY);); + DBUG_EXECUTE("where", + print_where(tmp,tab->table->alias.c_ptr(), + QT_ORDINARY);); SQL_SELECT *sel= tab->select= ((SQL_SELECT*) thd->memdup((uchar*) select, sizeof(*select))); @@ -6830,7 +6832,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) } sel->head=tab->table; - DBUG_EXECUTE("where",print_where(tmp,tab->table->alias, QT_ORDINARY);); + DBUG_EXECUTE("where", + print_where(tmp,tab->table->alias.c_ptr(), + QT_ORDINARY);); if (tab->quick) { /* Use quick key read if it's a constant and it's not used @@ -11289,7 +11293,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, thd->mem_root= &table->mem_root; table->field=reg_field; - table->alias= table_alias; + table->alias.set(table_alias, strlen(table_alias), table_alias_charset); + table->reginfo.lock_type=TL_WRITE; /* Will be updated */ table->db_stat=HA_OPEN_KEYFILE+HA_OPEN_RNDFILE; table->map=1; @@ -11665,7 +11670,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, null_count=(null_count+7) & ~7; // move to next byte // fix table name in field entry - field->table_name= &table->alias; + field->set_table_name(&table->alias); } param->copy_field_end=copy; @@ -12482,7 +12487,7 @@ free_tmp_table(THD *thd, TABLE *entry) MEM_ROOT own_root= entry->mem_root; const char *save_proc_info; DBUG_ENTER("free_tmp_table"); - DBUG_PRINT("enter",("table: %s",entry->alias)); + DBUG_PRINT("enter",("table: %s",entry->alias.c_ptr())); save_proc_info=thd->proc_info; thd_proc_info(thd, "removing tmp table"); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index f41b4f8f02e..cdfb982b372 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -816,7 +816,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) protocol->store(table_list->schema_table->table_name, system_charset_info); else - protocol->store(table_list->table->alias, system_charset_info); + protocol->store(table_list->table->alias.c_ptr(), system_charset_info); } if (table_list->view) @@ -1305,7 +1305,7 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, else { if (lower_case_table_names == 2) - alias= table->alias; + alias= table->alias.c_ptr(); else { alias= share->table_name.str; @@ -5662,7 +5662,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) if (et.load_from_row(thd, event_table)) { - my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), event_table->alias); + my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), event_table->alias.c_ptr()); DBUG_RETURN(1); } diff --git a/sql/sql_string.h b/sql/sql_string.h index dc9122a4fcb..b154f0c1667 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -274,6 +274,14 @@ public: bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs); bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto, uint *errors); + void move(String &s) + { + free(); + Ptr=s.Ptr ; str_length=s.str_length ; Alloced_length=s.Alloced_length; + extra_alloc= s.extra_alloc; + alloced= s.alloced; + s.alloced= 0; + } bool append(const String &s); bool append(const char *s); bool append(const char *s,uint32 arg_length); @@ -304,6 +312,7 @@ public: friend int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); friend int stringcmp(const String *a,const String *b); friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); + friend class Field; uint32 numchars(); int charpos(int i,uint32 offset=0); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0ef18a237dd..13b2ea3ae98 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2113,7 +2113,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, { if (!foreign_key_error) my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0), - wrong_tables.c_ptr()); + wrong_tables.c_ptr_safe()); else my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0)); error= 1; @@ -6955,7 +6955,7 @@ view_err: error= 0; push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), - table->alias); + table->alias.c_ptr()); } VOID(pthread_mutex_lock(&LOCK_open)); @@ -7023,7 +7023,7 @@ view_err: error= 0; push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), - table->alias); + table->alias.c_ptr()); } if (!error) diff --git a/sql/sql_test.cc b/sql/sql_test.cc index d26c252f4e0..d2063b48a50 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -65,7 +65,7 @@ print_where(COND *cond,const char *info, enum_query_type query_type) str.append('\0'); DBUG_LOCK_FILE; (void) fprintf(DBUG_FILE,"\nWHERE:(%s) ",info); - (void) fputs(str.ptr(),DBUG_FILE); + (void) fputs(str.c_ptr_safe(),DBUG_FILE); (void) fputc('\n',DBUG_FILE); DBUG_UNLOCK_FILE; } @@ -157,7 +157,7 @@ void TEST_filesort(SORT_FIELD *sortorder,uint s_length) out.append('\0'); // Purify doesn't like c_ptr() DBUG_LOCK_FILE; VOID(fputs("\nInfo about FILESORT\n",DBUG_FILE)); - fprintf(DBUG_FILE,"Sortorder: %s\n",out.ptr()); + fprintf(DBUG_FILE,"Sortorder: %s\n",out.c_ptr_safe()); DBUG_UNLOCK_FILE; DBUG_VOID_RETURN; } @@ -192,7 +192,7 @@ TEST_join(JOIN *join) TABLE *form=tab->table; char key_map_buff[128]; fprintf(DBUG_FILE,"%-16.16s type: %-7s q_keys: %s refs: %d key: %d len: %d\n", - form->alias, + form->alias.c_ptr(), join_type_str[tab->type], tab->keys.print(key_map_buff), tab->ref.key_parts, @@ -216,7 +216,7 @@ TEST_join(JOIN *join) if (tab->ref.key_parts) { fprintf(DBUG_FILE, - " refs: %s\n", ref_key_parts[i].ptr()); + " refs: %s\n", ref_key_parts[i].c_ptr_safe()); } } DBUG_UNLOCK_FILE; diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index f6864add19f..d1e974a2c04 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -802,7 +802,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, stmt_query->append(stmt_definition.str, stmt_definition.length); - trg_def->str= stmt_query->c_ptr(); + trg_def->str= stmt_query->c_ptr_safe(); trg_def->length= stmt_query->length(); /* Create trigger definition file. */ @@ -1039,10 +1039,7 @@ void Table_triggers_list::set_table(TABLE *new_table) { trigger_table= new_table; for (Field **field= new_table->triggers->record1_field ; *field ; field++) - { - (*field)->table= (*field)->orig_table= new_table; - (*field)->table_name= &new_table->alias; - } + (*field)->init(new_table); } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index aa803d6e0dd..ec91f2c64fc 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1602,7 +1602,8 @@ loop_end: do { Field_string *field= new Field_string(tbl->file->ref_length, 0, - tbl->alias, &my_charset_bin); + tbl->alias.c_ptr(), + &my_charset_bin); if (!field) DBUG_RETURN(1); field->init(tbl); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 204100f6034..8b8b7f5c90e 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -848,7 +848,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, thd->variables.sql_mode|= sql_mode; } - DBUG_PRINT("info", ("View: %s", view_query.ptr())); + DBUG_PRINT("info", ("View: %s", view_query.c_ptr_safe())); /* fill structure */ view->source= thd->lex->create_view_select; @@ -1675,7 +1675,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) } if (non_existant_views.length()) { - my_error(ER_BAD_TABLE_ERROR, MYF(0), non_existant_views.c_ptr()); + my_error(ER_BAD_TABLE_ERROR, MYF(0), non_existant_views.c_ptr_safe()); } something_wrong= error || wrong_object_name || non_existant_views.length(); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 87a8dd278c2..e8890dde6cb 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -13111,7 +13111,7 @@ column_list_id: while ((point=iter++)) { if (!my_strcasecmp(system_charset_info, - point->column.ptr(), new_str->ptr())) + point->column.c_ptr(), new_str->c_ptr())) break; } lex->grant_tot_col|= lex->which_columns; diff --git a/sql/table.cc b/sql/table.cc index 8e3c25d67d1..556cbcc96c1 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2085,7 +2085,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); - if (!(outparam->alias= my_strdup(alias, MYF(MY_WME)))) + if (outparam->alias.copy(alias, strlen(alias), table_alias_charset)) goto err; outparam->quick_keys.init(); outparam->covering_keys.init(); @@ -2422,7 +2422,7 @@ partititon_err: outparam->db_stat=0; thd->lex->view_prepare_mode= save_view_prepare_mode; free_root(&outparam->mem_root, MYF(0)); // Safe to call on bzero'd root - my_free((char*) outparam->alias, MYF(MY_ALLOW_ZERO_PTR)); + outparam->alias.free(); DBUG_RETURN (error); } @@ -2448,8 +2448,7 @@ int closefrm(register TABLE *table, bool free_share) table->file->extra(HA_EXTRA_PREPARE_FOR_DROP); error=table->file->close(); } - my_free((char*) table->alias, MYF(MY_ALLOW_ZERO_PTR)); - table->alias= 0; + table->alias.free(); if (table->expr_arena) table->expr_arena->free_items(); if (table->field) @@ -3286,7 +3285,7 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) const TABLE_FIELD_TYPE *field_def= table_def->field; DBUG_ENTER("table_check_intact"); DBUG_PRINT("info",("table: %s expected_count: %d", - table->alias, table_def->count)); + table->alias.c_ptr(), table_def->count)); /* Whether the table definition has already been validated. */ if (table->s->table_field_def_cache == table_def) @@ -3301,14 +3300,15 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) { report_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE), - table->alias, table_def->count, table->s->fields, + table->alias.c_ptr(), table_def->count, table->s->fields, table->s->mysql_version, MYSQL_VERSION_ID); DBUG_RETURN(TRUE); } else if (MYSQL_VERSION_ID == table->s->mysql_version) { report_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED, - ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), table->alias, + ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), + table->alias.c_ptr(), table_def->count, table->s->fields); DBUG_RETURN(TRUE); } @@ -3341,7 +3341,8 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) */ report_error(0, "Incorrect definition of table %s.%s: " "expected column '%s' at position %d, found '%s'.", - table->s->db.str, table->alias, field_def->name.str, i, + table->s->db.str, table->alias.c_ptr(), + field_def->name.str, i, field->field_name); } field->sql_type(sql_type); @@ -3367,7 +3368,8 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) { report_error(0, "Incorrect definition of table %s.%s: " "expected column '%s' at position %d to have type " - "%s, found type %s.", table->s->db.str, table->alias, + "%s, found type %s.", table->s->db.str, + table->alias.c_ptr(), field_def->name.str, i, field_def->type.str, sql_type.c_ptr_safe()); error= TRUE; @@ -3377,7 +3379,8 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) report_error(0, "Incorrect definition of table %s.%s: " "expected the type of column '%s' at position %d " "to have character set '%s' but the type has no " - "character set.", table->s->db.str, table->alias, + "character set.", table->s->db.str, + table->alias.c_ptr(), field_def->name.str, i, field_def->cset.str); error= TRUE; } @@ -3387,7 +3390,8 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) report_error(0, "Incorrect definition of table %s.%s: " "expected the type of column '%s' at position %d " "to have character set '%s' but found " - "character set '%s'.", table->s->db.str, table->alias, + "character set '%s'.", table->s->db.str, + table->alias.c_ptr(), field_def->name.str, i, field_def->cset.str, field->charset()->csname); error= TRUE; @@ -3398,7 +3402,7 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) report_error(0, "Incorrect definition of table %s.%s: " "expected column '%s' at position %d to have type %s " " but the column is not found.", - table->s->db.str, table->alias, + table->s->db.str, table->alias.c_ptr(), field_def->name.str, i, field_def->type.str); error= TRUE; } diff --git a/sql/table.h b/sql/table.h index 99b5601c307..ba037c27020 100644 --- a/sql/table.h +++ b/sql/table.h @@ -720,7 +720,7 @@ struct st_table { Table_triggers_list *triggers; TABLE_LIST *pos_in_table_list;/* Element referring to this table */ ORDER *group; - const char *alias; /* alias or table name */ + String alias; /* alias or table name */ uchar *null_flags; my_bitmap_map *bitmap_init_value; MY_BITMAP def_read_set, def_write_set, def_vcol_set, tmp_set; diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index 2749034cba2..434423b78b3 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -1453,7 +1453,8 @@ static void fill_server(MEM_ROOT *mem_root, FEDERATEDX_SERVER *server, key.q_append('\0'); server->password= (const char *) (intptr) key.length(); key.append(password); - + key.c_ptr_safe(); // Ensure we have end \0 + server->key_length= key.length(); server->key= (uchar *) memdup_root(mem_root, key.ptr(), key.length()+1); @@ -1583,7 +1584,7 @@ static FEDERATEDX_SHARE *get_share(const char *table_name, TABLE *table) tmp_share.table_name_length, ident_quote_char); if (!(share= (FEDERATEDX_SHARE *) memdup_root(&mem_root, (char*)&tmp_share, sizeof(*share))) || - !(share->select_query= (char*) strmake_root(&mem_root, query.ptr(), query.length() + 1))) + !(share->select_query= (char*) strmake_root(&mem_root, query.ptr(), query.length()))) goto error; share->mem_root= mem_root; @@ -3435,11 +3436,13 @@ bool ha_federatedx::get_error_message(int error, String* buf) buf->qs_append(remote_error_number); buf->append(STRING_WITH_LEN(": ")); buf->append(remote_error_buf); + /* Ensure string ends with \0 */ + (void) buf->c_ptr_safe(); remote_error_number= 0; remote_error_buf[0]= '\0'; } - DBUG_PRINT("exit", ("message: %s", buf->ptr())); + DBUG_PRINT("exit", ("message: %s", buf->c_ptr_safe())); DBUG_RETURN(FALSE); } diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 27958285a2e..6463b25e440 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1095,7 +1095,7 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) param.thd= thd; param.op_name= "check"; param.db_name= table->s->db.str; - param.table_name= table->alias; + param.table_name= table->alias.c_ptr(); param.testflag= check_opt->flags | T_CHECK | T_SILENT; param.stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method); @@ -1194,7 +1194,7 @@ int ha_maria::analyze(THD *thd, HA_CHECK_OPT * check_opt) param.thd= thd; param.op_name= "analyze"; param.db_name= table->s->db.str; - param.table_name= table->alias; + param.table_name= table->alias.c_ptr(); param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS | T_DONT_CHECK_CHECKSUM); param.using_global_keycache= 1; @@ -1488,7 +1488,7 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize) _ma_copy_nontrans_state_information(file); param->db_name= table->s->db.str; - param->table_name= table->alias; + param->table_name= table->alias.c_ptr(); param->tmpfile_createflag= O_RDWR | O_TRUNC; param->using_global_keycache= 1; param->thd= thd; diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 368bb0bd4e3..1f58d72469d 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -811,7 +811,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) param.thd = thd; param.op_name = "check"; param.db_name= table->s->db.str; - param.table_name= table->alias; + param.table_name= table->alias.c_ptr(); param.testflag = check_opt->flags | T_CHECK | T_SILENT; param.stats_method= (enum_handler_stats_method)thd->variables.myisam_stats_method; @@ -904,7 +904,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) param.thd = thd; param.op_name= "analyze"; param.db_name= table->s->db.str; - param.table_name= table->alias; + param.table_name= table->alias.c_ptr(); param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS | T_DONT_CHECK_CHECKSUM); param.using_global_keycache = 1; @@ -1129,7 +1129,7 @@ int ha_myisam::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) DBUG_ENTER("ha_myisam::repair"); param.db_name= table->s->db.str; - param.table_name= table->alias; + param.table_name= table->alias.c_ptr(); param.tmpfile_createflag = O_RDWR | O_TRUNC; param.using_global_keycache = 1; param.thd= thd; diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c index 2839d935167..3c73f879b47 100644 --- a/storage/xtradb/row/row0sel.c +++ b/storage/xtradb/row/row0sel.c @@ -2698,16 +2698,6 @@ row_sel_store_mysql_rec( prebuilt->blob_heap = NULL; } -// psergey@askmonty.org: don't take the following: -#if 0 - /* init null bytes with default values as they might be - - left uninitialized in some cases and these uninited bytes - might be copied into mysql record buffer that leads to - valgrind warnings */ - memcpy(mysql_rec, prebuilt->default_rec, prebuilt->null_bitmap_len); -#endif - for (i = start_field_no; i < end_field_no /* prebuilt->n_template */ ; i++) { templ = prebuilt->mysql_template + i; @@ -3445,6 +3435,12 @@ row_search_for_mysql( ut_error; } + /* init null bytes with default values as they might be + left uninitialized in some cases and these uninited bytes + might be copied into mysql record buffer that leads to + valgrind warnings */ + memcpy(buf, prebuilt->default_rec, prebuilt->null_bitmap_len); + #if 0 /* August 19, 2005 by Heikki: temporarily disable this error print until the cursor lock count is done correctly. From 7c56b08216d5ff709d10e4ca662d0215cd823c09 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Sat, 27 Nov 2010 17:29:52 +0200 Subject: [PATCH 5/5] Added TRASH() to table->record[0] to find out if we access not initialzed data. - Changed Cached_item_field not copy data for fields with NULL value - In key_copy() and key_restore() don't copy data for fields with NULL value Fixed code to avoid valgrind warnings - Use c_ptr_safe instead of c_ptr() Removed "QQ" from comments (QQ was ment to be used for internal comments that should be removed before pushing) Fixed wrong alias used (from previous patch) sql/event_db_repository.cc: Update testing if event table is valid (to avoid valgrind errors) sql/ha_partition.cc: m_ordered_scan_ongoing was not initialized Reset null bits in record to avoid valgrind errors sql/handler.h: Added flag if storage engine will write row verbatim and the row contains varchar or null fields (in which case we must clear the row to avoid valgrind warnings) sql/item_buff.cc: Changed Cached_item_field not copy data for fields with NULL value (Optimization and avoids valgrind warnings) sql/item_func.cc: c_ptr() -> c_ptr_safe() sql/key.cc: In key_copy() and key_restore() don't copy data for fields with NULL value sql/opt_range.cc: c_ptr() -> c_ptr_safe() sql/sql_base.cc: Added TRASH() to table->record[0] to find out if we access not initialzed data. Initialize null_bytes to: - Get consistent tests - Ensure we don't get valgrind warnings for null fields (as we may only update a couple of bits in a byte) sql/sql_class.cc: Removed "QQ" from comments sql/sql_insert.cc: Initialize row to default values if we are using valgrind and row will be copied verbatim to disk in storage engine. sql/sql_load.cc: QQ -> TODO sql/sql_parse.cc: Removed old not used code marked QQ and withing "#ifdef REMOVED" sql/sql_select.cc: QQ -> TODO Initialize some variables that was used uninitialized Added DBUG_ASSERT() to find out if thd was not properly initialized for sub queries sql/sql_test.cc: Fixed format for printing to DBUG file Fixed wrong alias used (from previous patch) sql/sql_trigger.h: QQ -> TODO sql/table.cc: QQ -> TODO storage/maria/ha_maria.cc: Mark table with HA_RECORD_MUST_BE_CLEAN_ON_WRITE, if row is written verbatim to disk and contains varchar or null fields. storage/maria/ma_open.c: Added flags if table has varchar or null fields storage/maria/maria_def.h: Added flags if table has varchar or null fields storage/myisam/ha_myisam.cc: Mark table with HA_RECORD_MUST_BE_CLEAN_ON_WRITE, if row is written verbatim to disk and contains varchar or null fields. storage/myisam/mi_open.c: Fixed memory overrun bug when using fulltext keys storage/xtradb/row/row0sel.c: Removed initialization of null bits. (not needed anymore) --- sql/event_db_repository.cc | 6 ++++- sql/ha_partition.cc | 7 ++++++ sql/handler.h | 1 + sql/item_buff.cc | 14 ++++++++--- sql/item_func.cc | 2 +- sql/key.cc | 33 +++++++++++++++++++------ sql/opt_range.cc | 2 +- sql/sql_base.cc | 12 ++++++--- sql/sql_class.cc | 1 - sql/sql_insert.cc | 10 +++++--- sql/sql_load.cc | 2 +- sql/sql_parse.cc | 48 ------------------------------------ sql/sql_select.cc | 8 +++--- sql/sql_test.cc | 12 ++++----- sql/sql_trigger.h | 2 +- sql/table.cc | 2 +- storage/maria/ha_maria.cc | 10 ++++++++ storage/maria/ma_open.c | 4 +++ storage/maria/maria_def.h | 2 ++ storage/myisam/ha_myisam.cc | 10 ++++++++ storage/myisam/mi_open.c | 9 ++++--- storage/xtradb/row/row0sel.c | 6 ----- 22 files changed, 112 insertions(+), 91 deletions(-) diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index c1a64446c12..13a2f8cf7c2 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -896,7 +896,11 @@ Event_db_repository::find_named_event(LEX_STRING db, LEX_STRING name, same fields. */ if (db.length > table->field[ET_FIELD_DB]->field_length || - name.length > table->field[ET_FIELD_NAME]->field_length) + name.length > table->field[ET_FIELD_NAME]->field_length || + table->s->keys == 0 || + table->key_info[0].key_parts != 2 || + table->key_info[0].key_part[0].fieldnr != ET_FIELD_DB+1 || + table->key_info[0].key_part[1].fieldnr != ET_FIELD_NAME+1) DBUG_RETURN(TRUE); table->field[ET_FIELD_DB]->store(db.str, db.length, &my_charset_bin); diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 78dd353c09d..fd0d65a4e73 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3886,6 +3886,7 @@ int ha_partition::index_init(uint inx, bool sorted) m_part_spec.start_part= NO_CURRENT_PART_ID; m_start_key.length= 0; m_ordered= sorted; + m_ordered_scan_ongoing= FALSE; m_curr_key_info[0]= table->key_info+inx; if (m_pkey_is_clustered && table->s->primary_key != MAX_KEY) { @@ -4709,6 +4710,12 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) int error; handler *file= m_file[i]; + /* + Reset null bits (to avoid valgrind warnings) and to give a default + value for not read null fields. + */ + bfill(rec_buf_ptr, table->s->null_bytes, 255); + switch (m_index_scan_type) { case partition_index_read: error= file->ha_index_read_map(rec_buf_ptr, diff --git a/sql/handler.h b/sql/handler.h index f76580b7082..00d6347eb78 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -139,6 +139,7 @@ #define HA_HAS_NEW_CHECKSUM (LL(1) << 36) #define HA_MRR_CANT_SORT (LL(1) << 37) +#define HA_RECORD_MUST_BE_CLEAN_ON_WRITE (LL(1) << 38) /* Set of all binlog flags. Currently only contain the capabilities diff --git a/sql/item_buff.cc b/sql/item_buff.cc index 7d025ef518b..b15083f54a2 100644 --- a/sql/item_buff.cc +++ b/sql/item_buff.cc @@ -121,14 +121,20 @@ bool Cached_item_int::cmp(void) bool Cached_item_field::cmp(void) { - bool tmp= field->cmp(buff) != 0; // This is not a blob! - if (tmp) - field->get_image(buff,length,field->charset()); + bool tmp= FALSE; // Value is identical + /* Note that field can't be a blob here ! */ if (null_value != field->is_null()) { null_value= !null_value; - tmp=TRUE; + tmp= TRUE; // Value has changed } + + /* + If value is not null and value changed (from null to not null or + becasue of value change), then copy the new value to buffer. + */ + if (! null_value && (tmp || (tmp= (field->cmp(buff) != 0)))) + field->get_image(buff,length,field->charset()); return tmp; } diff --git a/sql/item_func.cc b/sql/item_func.cc index a2c8b9f3983..872cdf0185b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2961,7 +2961,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, String *res= arguments[i]->val_str(&buffers[i]); if (arguments[i]->null_value) continue; - f_args.args[i]= (char*) res->c_ptr(); + f_args.args[i]= (char*) res->c_ptr_safe(); f_args.lengths[i]= res->length(); break; } diff --git a/sql/key.cc b/sql/key.cc index 89423e5280e..a1793e9e5f4 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -113,13 +113,24 @@ void key_copy(uchar *to_key, uchar *from_record, KEY *key_info, if (key_length == 0) key_length= key_info->key_length; - for (key_part= key_info->key_part; (int) key_length > 0; key_part++) + for (key_part= key_info->key_part; + (int) key_length > 0; + key_part++, to_key+= length, key_length-= length) { if (key_part->null_bit) { *to_key++= test(from_record[key_part->null_offset] & key_part->null_bit); key_length--; + if (to_key[-1]) + { + /* + Don't copy data for null values + The -1 below is to subtract the null byte which is already handled + */ + length= min(key_length, (uint) key_part->store_length-1); + continue; + } } if (key_part->key_part_flag & HA_BLOB_PART || key_part->key_part_flag & HA_VAR_LENGTH_PART) @@ -138,8 +149,6 @@ void key_copy(uchar *to_key, uchar *from_record, KEY *key_info, if (bytes < length) cs->cset->fill(cs, (char*) to_key + bytes, length - bytes, ' '); } - to_key+= length; - key_length-= length; } } @@ -166,16 +175,28 @@ void key_restore(uchar *to_record, uchar *from_key, KEY *key_info, { key_length= key_info->key_length; } - for (key_part= key_info->key_part ; (int) key_length > 0 ; key_part++) + for (key_part= key_info->key_part ; + (int) key_length > 0 ; + key_part++, from_key+= length, key_length-= length) { uchar used_uneven_bits= 0; if (key_part->null_bit) { - if (*from_key++) + bool null_value; + if ((null_value= *from_key++)) to_record[key_part->null_offset]|= key_part->null_bit; else to_record[key_part->null_offset]&= ~key_part->null_bit; key_length--; + if (null_value) + { + /* + Don't copy data for null bytes + The -1 below is to subtract the null byte which is already handled + */ + length= min(key_length, (uint) key_part->store_length-1); + continue; + } } if (key_part->type == HA_KEYTYPE_BIT) { @@ -229,8 +250,6 @@ void key_restore(uchar *to_record, uchar *from_key, KEY *key_info, memcpy(to_record + key_part->offset, from_key + used_uneven_bits , (size_t) length - used_uneven_bits); } - from_key+= length; - key_length-= length; } } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 16dec381c8a..3818040d781 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -11131,7 +11131,7 @@ static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map, tmp.append(STRING_WITH_LEN("(empty)")); DBUG_PRINT("info", ("SEL_TREE: 0x%lx (%s) scans: %s", (long) tree, msg, - tmp.c_ptr())); + tmp.c_ptr_safe())); DBUG_VOID_RETURN; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a27d726f370..2ae6147a033 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3026,13 +3026,19 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, table->pos_in_table_list= table_list; table_list->updatable= 1; // It is not derived table nor non-updatable VIEW table->clear_column_bitmaps(); -#if !defined(DBUG_OFF) && !defined(HAVE_valgrind) /* Fill record with random values to find bugs where we access fields without first reading them. */ - bfill(table->record[0], table->s->reclength, 254); -#endif + TRASH(table->record[0], table->s->reclength); + /* + Initialize the null marker bits, to ensure that if we are doing a read + of only selected columns (like in keyread), all null markers are + initialized. + */ + bfill(table->record[0], table->s->null_bytes, 255); + bfill(table->record[1], table->s->null_bytes, 255); + DBUG_ASSERT(table->key_read == 0); DBUG_RETURN(table); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 688416a61a2..62651145481 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2363,7 +2363,6 @@ bool select_export::send_data(List &items) { // Fill with space if (item->max_length > used_length) { - /* QQ: Fix by adding a my_b_fill() function */ if (!space_inited) { space_inited=1; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 9477d2ca971..7267d73a29c 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -622,8 +622,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, /* We can't write-delayed into a table locked with LOCK TABLES: this will lead to a deadlock, since the delayed thread will - never be able to get a lock on the table. QQQ: why not - upgrade the lock here instead? + never be able to get a lock on the table. */ if (table_list->lock_type == TL_WRITE_DELAYED && thd->locked_tables && find_locked_table(thd, table_list->db, table_list->table_name)) @@ -808,7 +807,12 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, be overwritten by fill_record() anyway (and fill_record() does not use default values in this case). */ - table->record[0][0]= share->default_values[0]; +#ifdef HAVE_valgrind + if (table->file->ha_table_flags() && HA_RECORD_MUST_BE_CLEAN_ON_WRITE) + restore_record(table,s->default_values); // Get empty record + else +#endif + table->record[0][0]= share->default_values[0]; /* Fix undefined null_bits. */ if (share->null_bytes > 1 && share->last_null_bit_pos) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 75d9179c3bd..48574811f54 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -975,7 +975,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP) ((Field_timestamp*) field)->set_time(); /* - QQ: We probably should not throw warning for each field. + TODO: We probably should not throw warning for each field. But how about intention to always have the same number of warnings in THD::cuted_fields (and get rid of cuted_fields in the end ?) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index bd14daa09b1..3887321f006 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1350,54 +1350,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, error=TRUE; // End server break; -#ifdef REMOVED - case COM_CREATE_DB: // QQ: To be removed - { - LEX_STRING db, alias; - HA_CREATE_INFO create_info; - - status_var_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB]); - if (thd->make_lex_string(&db, packet, packet_length, FALSE) || - thd->make_lex_string(&alias, db.str, db.length, FALSE) || - check_db_name(&db)) - { - my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL"); - break; - } - if (check_access(thd, CREATE_ACL, db.str , 0, 1, 0, - is_schema_db(db.str, db.length))) - break; - general_log_print(thd, command, "%.*s", db.length, db.str); - bzero(&create_info, sizeof(create_info)); - mysql_create_db(thd, (lower_case_table_names == 2 ? alias.str : db.str), - &create_info, 0); - break; - } - case COM_DROP_DB: // QQ: To be removed - { - status_var_increment(thd->status_var.com_stat[SQLCOM_DROP_DB]); - LEX_STRING db; - - if (thd->make_lex_string(&db, packet, packet_length, FALSE) || - check_db_name(&db)) - { - my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL"); - break; - } - if (check_access(thd, DROP_ACL, db.str, 0, 1, 0, - is_schema_db(db.str, db.length))) - break; - if (thd->locked_tables || thd->active_transaction()) - { - my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, - ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); - break; - } - general_log_write(thd, command, "%.*s", db.length, db.str); - mysql_rm_db(thd, db.str, 0, 0); - break; - } -#endif #ifndef EMBEDDED_LIBRARY case COM_BINLOG_DUMP: { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ec5cc0ab705..310774a49e8 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2953,7 +2953,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, { start_keyuse=keyuse; key=keyuse->key; - s->keys.set_bit(key); // QQ: remove this ? + s->keys.set_bit(key); // TODO: remove this ? refs=0; const_ref.clear_all(); @@ -3900,6 +3900,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.ref_table_rows= 0; keyuse.null_rejecting= key_field->null_rejecting; keyuse.cond_guard= key_field->cond_guard; keyuse.sj_pred_no= key_field->sj_pred_no; @@ -6343,8 +6344,8 @@ JOIN::make_simple_join(JOIN *parent, TABLE *temp_table) join_tab->table=temp_table; join_tab->cache_select= 0; join_tab->select=0; + join_tab->select_cond= 0; // Avoid valgrind warning join_tab->set_select_cond(NULL, __LINE__); - join_tab->select_cond=0; join_tab->quick=0; join_tab->type= JT_ALL; /* Map through all records */ join_tab->keys.init(); @@ -19193,7 +19194,8 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str, void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) { - /* QQ: thd may not be set for sub queries, but this should be fixed */ + /* TODO: thd may not be set for sub queries, but this should be fixed */ + DBUG_ASSERT(thd); if (!thd) thd= current_thd; diff --git a/sql/sql_test.cc b/sql/sql_test.cc index d2063b48a50..5bf9cd1f77e 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -241,11 +241,11 @@ void print_keyuse(KEYUSE *keyuse) fieldname= keyuse->table->key_info[keyuse->key].key_part[keyuse->keypart].field->field_name; longlong2str(keyuse->used_tables, buf2, 16, 0); DBUG_LOCK_FILE; - fprintf(DBUG_FILE, "KEYUSE: %s.%s=%s optimize= %d used_tables=%s " - "ref_table_rows= %lu keypart_map= %0lx\n", - keyuse->table->alias, fieldname, str.ptr(), - keyuse->optimize, buf2, (ulong)keyuse->ref_table_rows, - keyuse->keypart_map); + fprintf(DBUG_FILE, "KEYUSE: %s.%s=%s optimize: %u used_tables: %s " + "ref_table_rows: %lu keypart_map: %0lx\n", + keyuse->table->alias.c_ptr(), fieldname, str.ptr(), + (uint) keyuse->optimize, buf2, (ulong) keyuse->ref_table_rows, + (ulong) keyuse->keypart_map); DBUG_UNLOCK_FILE; //key_part_map keypart_map; --?? there can be several? } @@ -371,7 +371,7 @@ void print_sjm(SJ_MATERIALIZATION_INFO *sjm) for (uint i= 0;i < sjm->tables; i++) { fprintf(DBUG_FILE, " %s%s\n", - sjm->positions[i].table->table->alias, + sjm->positions[i].table->table->alias.c_ptr(), (i == sjm->tables -1)? "": ","); } fprintf(DBUG_FILE, " }\n"); diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index f6754a75284..08125f94b43 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -17,7 +17,7 @@ /** This class holds all information about triggers of table. - QQ: Will it be merged into TABLE in the future ? + TODO: Will it be merged into TABLE in the future ? */ class Table_triggers_list: public Sql_alloc diff --git a/sql/table.cc b/sql/table.cc index 556cbcc96c1..17cd9c8dc34 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2925,7 +2925,7 @@ File create_frm(THD *thd, const char *name, const char *db, if (create_info->options & HA_LEX_CREATE_TMP_TABLE) create_flags|= O_EXCL | O_NOFOLLOW; - /* Fix this when we have new .frm files; Current limit is 4G rows (QQ) */ + /* Fix this when we have new .frm files; Current limit is 4G rows (TODO) */ if (create_info->max_rows > UINT_MAX32) create_info->max_rows= UINT_MAX32; if (create_info->min_rows > UINT_MAX32) diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 6463b25e440..b95a6766878 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1036,6 +1036,16 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked) if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) int_table_flags |= HA_HAS_NEW_CHECKSUM; + /* + For static size rows, tell MariaDB that we will access all bytes + in the record when writing it. This signals MariaDB to initalize + the full row to ensure we don't get any errors from valgrind and + that all bytes in the row is properly reset. + */ + if (file->s->data_file_type == STATIC_RECORD && + (file->s->has_varchar_fields | file->s->has_null_fields)) + int_table_flags|= HA_RECORD_MUST_BE_CLEAN_ON_WRITE; + for (i= 0; i < table->s->keys; i++) { plugin_ref parser= table->key_info[i].parser; diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 63e1801a39a..ae3a3918eee 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -763,6 +763,10 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) share->blobs[j].offset= share->columndef[i].offset; j++; } + if (share->columndef[i].type == FIELD_VARCHAR) + share->has_varchar_fields= 1; + if (share->columndef[i].null_bit) + share->has_null_fields= 1; } share->columndef[i].type= FIELD_LAST; /* End marker */ disk_pos= _ma_column_nr_read(disk_pos, share->column_nr, diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index ba97684b1aa..c39aeaabaa6 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -376,6 +376,8 @@ typedef struct st_maria_share my_bool temporary; /* Below flag is needed to make log tables work with concurrent insert */ my_bool is_log_table; + my_bool has_null_fields; + my_bool has_varchar_fields; /* If table has varchar fields */ my_bool changed, /* If changed since lock */ global_changed, /* If changed since open */ diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 1f58d72469d..d012ac053d8 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -745,6 +745,16 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked) int_table_flags|= HA_HAS_OLD_CHECKSUM; } + /* + For static size rows, tell MariaDB that we will access all bytes + in the record when writing it. This signals MariaDB to initalize + the full row to ensure we don't get any errors from valgrind and + that all bytes in the row is properly reset. + */ + if ((file->s->options & HA_OPTION_PACK_RECORD) && + (file->s->has_varchar_fields | file->s->has_null_fields)) + int_table_flags|= HA_RECORD_MUST_BE_CLEAN_ON_WRITE; + for (i= 0; i < table->s->keys; i++) { plugin_ref parser= table->key_info[i].parser; diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index c40f894b14d..e35dd690482 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -79,7 +79,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) { int lock_error,kfile,open_mode,save_errno,have_rtree=0, realpath_err; uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys, - key_parts,unique_key_parts,fulltext_keys,uniques; + key_parts,unique_key_parts,base_key_parts,fulltext_keys,uniques; char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN], data_name[FN_REFLEN]; uchar *disk_cache, *disk_pos, *end_pos; @@ -200,7 +200,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) keys= (uint) share->state.header.keys; uniques= (uint) share->state.header.uniques; fulltext_keys= (uint) share->state.header.fulltext_keys; - key_parts= mi_uint2korr(share->state.header.key_parts); + base_key_parts= key_parts= mi_uint2korr(share->state.header.key_parts); unique_key_parts= mi_uint2korr(share->state.header.unique_key_parts); if (len != MI_STATE_INFO_SIZE) { @@ -298,7 +298,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) if (!my_multi_malloc(MY_WME, &share,sizeof(*share), - &share->state.rec_per_key_part,sizeof(long)*key_parts, + &share->state.rec_per_key_part, + sizeof(long)*base_key_parts, &share->keyinfo,keys*sizeof(MI_KEYDEF), &share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF), &share->keyparts, @@ -322,7 +323,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) errpos=4; *share=share_buff; memcpy((char*) share->state.rec_per_key_part, - (char*) rec_per_key_part, sizeof(long)*key_parts); + (char*) rec_per_key_part, sizeof(long)*base_key_parts); memcpy((char*) share->state.key_root, (char*) key_root, sizeof(my_off_t)*keys); memcpy((char*) share->state.key_del, diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c index 3c73f879b47..42580150ed8 100644 --- a/storage/xtradb/row/row0sel.c +++ b/storage/xtradb/row/row0sel.c @@ -3435,12 +3435,6 @@ row_search_for_mysql( ut_error; } - /* init null bytes with default values as they might be - left uninitialized in some cases and these uninited bytes - might be copied into mysql record buffer that leads to - valgrind warnings */ - memcpy(buf, prebuilt->default_rec, prebuilt->null_bitmap_len); - #if 0 /* August 19, 2005 by Heikki: temporarily disable this error print until the cursor lock count is done correctly.