From c703954578ce3c806112bbc2319988fc289ab8a1 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Mar 2005 17:15:47 +0400 Subject: [PATCH 01/12] # Bug#8785 Problem with nested concats and character set conversion of a string constant. mysql-test/r/ctype_utf8.result: Adding test mysql-test/t/ctype_utf8.test: Addign test sql/item_strfunc.cc: Remove previous fix: it was not 100% correct. A non const_item() can return a constant String. sql/sql_string.h: A new method to cut Alloced_length to str_length for string constants, to avoid reusing them as a buffer in things like CONCAT(). --- mysql-test/r/ctype_utf8.result | 7 +++++++ mysql-test/t/ctype_utf8.test | 9 +++++++++ sql/item.cc | 12 ++++++++++++ sql/item_strfunc.cc | 3 +-- sql/sql_string.h | 4 ++++ 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 13105e2276c..314567a1544 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -861,6 +861,13 @@ user c one two DROP TABLE t1; +create table t1 (f1 varchar(1) not null) default charset utf8; +insert into t1 values (''), (''); +select concat(concat(_latin1'->',f1),_latin1'<-') from t1; +concat(concat(_latin1'->',f1),_latin1'<-') +-><- +-><- +drop table t1; select convert(_koi8r'É' using utf8) < convert(_koi8r'Ê' using utf8); convert(_koi8r'É' using utf8) < convert(_koi8r'Ê' using utf8) 1 diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 35f2b2642be..2c498cd1922 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -694,6 +694,15 @@ SELECT CHARSET('a'); SELECT user, CONCAT('<', user, '>') AS c FROM t1; DROP TABLE t1; +# +# Bug#8785 +# the same problem with the above, but with nested CONCATs +# +create table t1 (f1 varchar(1) not null) default charset utf8; +insert into t1 values (''), (''); +select concat(concat(_latin1'->',f1),_latin1'<-') from t1; +drop table t1; + # # Bug#8385: utf8_general_ci treats Cyrillic letters I and SHORT I as the same # diff --git a/sql/item.cc b/sql/item.cc index 690ada2d660..2250bd9b32c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -236,6 +236,18 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) return NULL; } conv->str_value.copy(); + /* + The above line executes str_value.realloc() internally, + which alligns Alloced_length using ALLIGN_SIZE. + In the case of Item_string::str_value we don't want + Alloced_length to be longer than str_length. + Otherwise, some functions like Item_func_concat::val_str() + try to reuse str_value as a buffer for concatenation result + for optimization purposes, so our string constant become + corrupted. See bug#8785 for more details. + Let's shrink Alloced_length to str_length to avoid this problem. + */ + conv->str_value.shrink_to_length(); return conv; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 54dd3b2d1b0..b4f75859469 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -277,8 +277,7 @@ String *Item_func_concat::val_str(String *str) current_thd->variables.max_allowed_packet); goto null; } - if (!args[0]->const_item() && - res->alloced_length() >= res->length()+res2->length()) + if (res->alloced_length() >= res->length()+res2->length()) { // Use old buffer res->append(*res2); } diff --git a/sql/sql_string.h b/sql/sql_string.h index 3ad4689cf36..8dff5558120 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -177,6 +177,10 @@ public: } } } + inline void shrink_to_length() + { + Alloced_length= str_length; + } bool is_alloced() { return alloced; } inline String& operator = (const String &s) { From 0e802637ccd18f1e237b43416b4855bfab93d745 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Mar 2005 16:23:02 +0100 Subject: [PATCH 02/12] BUG#9123: If a table name is given with an underscore, then this must be properly quoted when sent to SHOW TABLES LIKE ... --- client/mysqldump.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index a53dc319b2e..cfff4d4e7ed 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2109,7 +2109,9 @@ static void get_actual_table_name(const char *old_table_name, char query[ NAME_LEN + 50 ]; DBUG_ENTER("get_actual_table_name"); - sprintf( query, "SHOW TABLES LIKE '%s'", old_table_name); + char show_name_buff[FN_REFLEN]; + sprintf(query, "SHOW TABLES LIKE %s", + quote_for_like(old_table_name, show_name_buff)); if (mysql_query_with_error_report(sock, 0, query)) { safe_exit(EX_MYSQLERR); From da911ec8f150102029708f0abd7d1718c475702b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Mar 2005 01:15:45 +0200 Subject: [PATCH 03/12] Partly reverty back patch (in heap-auto-increment-key detection) to ensure that auto_key and auto_key_type are calculated the same way heap/hp_create.c: Partly reverty back patch to ensure that auto_key and auto_key_type are calculated the same way include/heap.h: Partly reverty back patch to ensure that auto_key and auto_key_type are calculated the same way mysql-test/mysql-test-run.sh: made --skip-ndb a synonyme for --skip-ndbcluster sql/ha_heap.cc: Partly reverty back patch to ensure that auto_key and auto_key_type are calculated the same way --- heap/hp_create.c | 3 +-- include/heap.h | 2 ++ mysql-test/mysql-test-run.sh | 2 +- sql/ha_heap.cc | 20 +++++++++++--------- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/heap/hp_create.c b/heap/hp_create.c index b1b132a16fb..af32fefea1b 100644 --- a/heap/hp_create.c +++ b/heap/hp_create.c @@ -137,8 +137,6 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, keyinfo->write_key= hp_write_key; keyinfo->hash_buckets= 0; } - if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment) - share->auto_key= i + 1; } share->min_records= min_records; share->max_records= max_records; @@ -149,6 +147,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, share->keys= keys; share->max_key_length= max_length; share->changed= 0; + share->auto_key= create_info->auto_key; share->auto_key_type= create_info->auto_key_type; share->auto_increment= create_info->auto_increment; /* Must be allocated separately for rename to work */ diff --git a/include/heap.h b/include/heap.h index 51f7b0cfa6a..badec9ce2ef 100644 --- a/include/heap.h +++ b/include/heap.h @@ -181,8 +181,10 @@ typedef struct st_heap_info LIST open_list; } HP_INFO; + typedef struct st_heap_create_info { + uint auto_key; /* keynr [1 - maxkey] for auto key */ uint auto_key_type; ulong max_table_size; ulonglong auto_increment; diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 90846a2711a..aab2b1d7da2 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -426,7 +426,7 @@ while test $# -gt 0; do TMP=`$ECHO "$1" | $SED -e "s;--valgrind-options=;;"` VALGRIND="$VALGRIND $TMP" ;; - --skip-ndbcluster) + --skip-ndbcluster | --skip-ndb) USE_NDBCLUSTER="" EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1" EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT $1" diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index c483ab8fffa..4dc48c7422b 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -446,7 +446,6 @@ int ha_heap::create(const char *name, TABLE *table_arg, HA_KEYSEG *seg; char buff[FN_REFLEN]; int error; - bool found_real_auto_increment= 0; for (key= parts= 0; key < table_arg->keys; key++) parts+= table_arg->key_info[key].key_parts; @@ -507,20 +506,23 @@ int ha_heap::create(const char *name, TABLE *table_arg, seg->null_bit= 0; seg->null_pos= 0; } - // We have to store field->key_type() as seg->type can differ from it - if (field->flags & AUTO_INCREMENT_FLAG) + if (field->flags & AUTO_INCREMENT_FLAG && + table_arg->found_next_number_field && + key == table_arg->next_number_index) + { + /* + Store key number and type for found auto_increment key + We have to store type as seg->type can differ from it + */ + auto_key= key+ 1; auto_key_type= field->key_type(); + } } } - if (table_arg->found_next_number_field) - { - keydef[table_arg->next_number_index].flag|= HA_AUTO_KEY; - found_real_auto_increment= table_arg->next_number_key_offset == 0; - } mem_per_row+= MY_ALIGN(table_arg->reclength + 1, sizeof(char*)); HP_CREATE_INFO hp_create_info; + hp_create_info.auto_key= auto_key; hp_create_info.auto_key_type= auto_key_type; - hp_create_info.with_auto_increment= found_real_auto_increment; 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; From e16535ce1957567b1f176bdbcda766a8104a5072 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Mar 2005 22:50:54 -0800 Subject: [PATCH 04/12] olap.result, olap.test: Added a test case for bug #8616. item.h: Fixed bug #8616. Added class Item_null_result used in rollup processing. sql_select.h, sql_select.cc: Fixed bug #8616. Added JOIN::rollup_write_data to cover rollup queries with DISTINCT. Modified other rollup methods. sql/sql_select.cc: Fixed bug #8616. Added JOIN::rollup_write_data to cover rollup queries with DISTINCT. Modified other rollup methods. sql/sql_select.h: Fixed bug #8616. Added JOIN::rollup_write_data to cover rollup queries with DISTINCT. Modified other rollup methods. sql/item.h: Fixed bug #8616. Added class Item_null_result used in rollup processing. mysql-test/t/olap.test: Added a test case for bug #8616. mysql-test/r/olap.result: Added a test case for bug #8616. --- mysql-test/r/olap.result | 54 ++++++++++++++++++ mysql-test/t/olap.test | 27 +++++++++ sql/item.h | 11 ++++ sql/sql_select.cc | 118 ++++++++++++++++++++++++++++++--------- sql/sql_select.h | 3 +- 5 files changed, 186 insertions(+), 27 deletions(-) diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index bcbe5a8791c..67610108c61 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -307,3 +307,57 @@ day sample not_cancelled 2004-06-07 1 0 NULL 3 1 DROP TABLE user_day; +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES +(1,4), +(2,2), (2,2), +(4,1), (4,1), (4,1), (4,1), +(2,1), (2,1); +SELECT SUM(b) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) +4 +6 +4 +14 +SELECT DISTINCT SUM(b) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) +4 +6 +14 +SELECT SUM(b), COUNT(DISTINCT b) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) COUNT(DISTINCT b) +4 1 +6 2 +4 1 +14 3 +SELECT DISTINCT SUM(b), COUNT(DISTINCT b) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) COUNT(DISTINCT b) +4 1 +6 2 +14 3 +SELECT SUM(b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) COUNT(*) +4 1 +6 4 +4 4 +14 9 +SELECT DISTINCT SUM(b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) COUNT(*) +4 1 +6 4 +4 4 +14 9 +SELECT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) COUNT(DISTINCT b) COUNT(*) +4 1 1 +6 2 4 +4 1 4 +14 3 9 +SELECT DISTINCT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 +GROUP BY a WITH ROLLUP; +SUM(b) COUNT(DISTINCT b) COUNT(*) +4 1 1 +6 2 4 +4 1 4 +14 3 9 +DROP TABLE t1; diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test index 674b4ade097..d2ea582e58c 100644 --- a/mysql-test/t/olap.test +++ b/mysql-test/t/olap.test @@ -125,3 +125,30 @@ SELECT DROP TABLE user_day; +# +# Test for bug #8616: distinct sum with rollup +# + +CREATE TABLE t1 (a int, b int); + +INSERT INTO t1 VALUES + (1,4), + (2,2), (2,2), + (4,1), (4,1), (4,1), (4,1), + (2,1), (2,1); + +SELECT SUM(b) FROM t1 GROUP BY a WITH ROLLUP; +SELECT DISTINCT SUM(b) FROM t1 GROUP BY a WITH ROLLUP; + +SELECT SUM(b), COUNT(DISTINCT b) FROM t1 GROUP BY a WITH ROLLUP; +SELECT DISTINCT SUM(b), COUNT(DISTINCT b) FROM t1 GROUP BY a WITH ROLLUP; + +SELECT SUM(b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; +SELECT DISTINCT SUM(b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; + +SELECT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; +SELECT DISTINCT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 + GROUP BY a WITH ROLLUP; + +DROP TABLE t1; + diff --git a/sql/item.h b/sql/item.h index adc780677e1..e34a5f889d2 100644 --- a/sql/item.h +++ b/sql/item.h @@ -470,6 +470,17 @@ public: Item *safe_charset_converter(CHARSET_INFO *tocs); }; +class Item_null_result :public Item_null +{ +public: + Field *result_field; + Item_null_result() : Item_null(), result_field(0) {} + bool is_result_field() { return result_field != 0; } + void save_in_result_field(bool no_conversions) + { + save_in_field(result_field, no_conversions); + } +}; /* Item represents one placeholder ('?') of prepared statement */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b00f9e422a1..0bb4c6a9402 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -157,7 +157,7 @@ static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array, uint elements, List &items); static void init_tmptable_sum_functions(Item_sum **func); static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table); -static void copy_sum_funcs(Item_sum **func_ptr); +static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end); static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab); static bool init_sum_functions(Item_sum **func, Item_sum **end); static bool update_sum_func(Item_sum **func); @@ -1328,7 +1328,7 @@ JOIN::exec() if (curr_join->tmp_having) curr_join->tmp_having->update_used_tables(); if (remove_duplicates(curr_join, curr_tmp_table, - curr_join->fields_list, curr_join->tmp_having)) + *curr_fields_list, curr_join->tmp_having)) DBUG_VOID_RETURN; curr_join->tmp_having=0; curr_join->select_distinct=0; @@ -6740,26 +6740,32 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { if (join->procedure) join->procedure->end_group(); - if (idx < (int) join->send_group_parts) + int send_group_parts= join->send_group_parts; + if (idx < send_group_parts) { if (!join->first_record) { /* No matching rows for group function */ join->clear(); } - copy_sum_funcs(join->sum_funcs); - if (!join->having || join->having->val_int()) + copy_sum_funcs(join->sum_funcs, + join->sum_funcs_end[send_group_parts]); + if (join->having && join->having->val_int() == 0) + error= -1; + else if ((error=table->file->write_row(table->record[0]))) { - if ((error=table->file->write_row(table->record[0]))) - { - if (create_myisam_from_heap(join->thd, table, - &join->tmp_table_param, - error, 0)) - DBUG_RETURN(-1); // Not a table_is_full error - } - else - join->send_records++; + if (create_myisam_from_heap(join->thd, table, + &join->tmp_table_param, + error, 0)) + DBUG_RETURN(-1); + } + if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0) + { + if (join->rollup_write_data((uint) (idx+1), table)) + error= 1; } + if (error > 0) + DBUG_RETURN(-1); if (end_of_records) DBUG_RETURN(0); } @@ -8888,11 +8894,10 @@ update_tmptable_sum_func(Item_sum **func_ptr, /* Copy result of sum functions to record in tmp_table */ static void -copy_sum_funcs(Item_sum **func_ptr) +copy_sum_funcs(Item_sum **func_ptr, Item_sum **end_ptr) { - Item_sum *func; - for (; (func = *func_ptr) ; func_ptr++) - (void) func->save_in_result_field(1); + for (; func_ptr != end_ptr ; func_ptr++) + (void) (*func_ptr)->save_in_result_field(1); return; } @@ -9013,14 +9018,16 @@ bool JOIN::rollup_init() */ tmp_table_param.group_parts= send_group_parts; - if (!(rollup.fields= (List*) thd->alloc((sizeof(Item*) + - sizeof(List) + - ref_pointer_array_size) - * send_group_parts))) + if (!(rollup.null_items= (Item_null_result**) thd->alloc((sizeof(Item*) + + sizeof(Item**) + + sizeof(List) + + ref_pointer_array_size) + * send_group_parts ))) return 1; + + rollup.fields= (List*) (rollup.null_items + send_group_parts); rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts); ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts); - rollup.item_null= new (thd->mem_root) Item_null(); /* Prepare space for field list for the different levels @@ -9028,12 +9035,16 @@ bool JOIN::rollup_init() */ for (i= 0 ; i < send_group_parts ; i++) { + rollup.null_items[i]= new (thd->mem_root) Item_null_result(); List *rollup_fields= &rollup.fields[i]; rollup_fields->empty(); rollup.ref_pointer_arrays[i]= ref_array; ref_array+= all_fields.elements; + } + for (i= 0 ; i < send_group_parts; i++) + { for (j=0 ; j < fields_list.elements ; j++) - rollup_fields->push_back(rollup.item_null); + rollup.fields[i].push_back(rollup.null_items[i]); } return 0; } @@ -9137,7 +9148,8 @@ bool JOIN::rollup_make_fields(List &fields_arg, List &sel_fields, { /* Check if this is something that is part of this group by */ ORDER *group_tmp; - for (group_tmp= start_group ; group_tmp ; group_tmp= group_tmp->next) + for (group_tmp= start_group, i-- ; + group_tmp ; group_tmp= group_tmp->next, i++) { if (*group_tmp->item == item) { @@ -9146,7 +9158,9 @@ bool JOIN::rollup_make_fields(List &fields_arg, List &sel_fields, set to NULL in this level */ item->maybe_null= 1; // Value will be null sometimes - item= rollup.item_null; + Item_null_result *null_item= rollup.null_items[i]; + null_item->result_field= ((Item_field *) item)->result_field; + item= null_item; break; } } @@ -9206,6 +9220,58 @@ int JOIN::rollup_send_data(uint idx) return 0; } +/* + Write all rollup levels higher than the current one to a temp table + + SYNOPSIS: + rollup_write_data() + idx Level we are on: + 0 = Total sum level + 1 = First group changed (a) + 2 = Second group changed (a,b) + table reference to temp table + + SAMPLE + SELECT a, b, SUM(c) FROM t1 GROUP BY a,b WITH ROLLUP + + RETURN + 0 ok + 1 if write_data_failed() +*/ + +int JOIN::rollup_write_data(uint idx, TABLE *table) +{ + uint i; + for (i= send_group_parts ; i-- > idx ; ) + { + /* Get reference pointers to sum functions in place */ + memcpy((char*) ref_pointer_array, + (char*) rollup.ref_pointer_arrays[i], + ref_pointer_array_size); + if ((!having || having->val_int())) + { + int error; + Item *item; + List_iterator_fast it(rollup.fields[i]); + while ((item= it++)) + { + if (item->type() == Item::NULL_ITEM && item->is_result_field()) + item->save_in_result_field(1); + } + copy_sum_funcs(sum_funcs_end[i+1], sum_funcs_end[i]); + if ((error= table->file->write_row(table->record[0]))) + { + if (create_myisam_from_heap(thd, table, &tmp_table_param, + error, 0)) + return 1; + } + } + } + /* Restore ref_pointer_array */ + set_items_ref_array(current_ref_pointer_array); + return 0; +} + /* clear results if there are not rows found for group (end_send_group/end_write_group) diff --git a/sql/sql_select.h b/sql/sql_select.h index bbd169d1850..4ea7e1b23e7 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -124,7 +124,7 @@ typedef struct st_rollup { enum State { STATE_NONE, STATE_INITED, STATE_READY }; State state; - Item *item_null; + Item_null_result **null_items; Item ***ref_pointer_arrays; List *fields; } ROLLUP; @@ -295,6 +295,7 @@ class JOIN :public Sql_alloc bool rollup_make_fields(List &all_fields, List &fields, Item_sum ***func); int rollup_send_data(uint idx); + int rollup_write_data(uint idx, TABLE *table); bool test_in_subselect(Item **where); void join_free(bool full); void clear(); From 9245168429bc963a73cbc16259535e612badd8e3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Mar 2005 15:57:57 +0300 Subject: [PATCH 05/12] Fix for bug #7100: relay_log_space_max missing from SHOW VARIABLES --- mysql-test/r/rpl000005.result | 3 +++ mysql-test/t/rpl000005.test | 5 +++++ sql/set_var.cc | 1 + 3 files changed, 9 insertions(+) diff --git a/mysql-test/r/rpl000005.result b/mysql-test/r/rpl000005.result index 0202e43dcb2..8acfa2cbfac 100644 --- a/mysql-test/r/rpl000005.result +++ b/mysql-test/r/rpl000005.result @@ -4,6 +4,9 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +SHOW VARIABLES LIKE 'relay_log_space_limit'; +Variable_name Value +relay_log_space_limit 0 CREATE TABLE t1 (name varchar(64), age smallint(3)); INSERT INTO t1 SET name='Andy', age=31; INSERT t1 SET name='Jacob', age=2; diff --git a/mysql-test/t/rpl000005.test b/mysql-test/t/rpl000005.test index ae713633df3..b94695c72e1 100644 --- a/mysql-test/t/rpl000005.test +++ b/mysql-test/t/rpl000005.test @@ -1,5 +1,10 @@ source include/master-slave.inc; +# +# Bug#7100 relay_log_space_max missing from SHOW VARIABLES +# +SHOW VARIABLES LIKE 'relay_log_space_limit'; + CREATE TABLE t1 (name varchar(64), age smallint(3)); INSERT INTO t1 SET name='Andy', age=31; INSERT t1 SET name='Jacob', age=2; diff --git a/sql/set_var.cc b/sql/set_var.cc index 257d0a92171..d989c7d8fd2 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -845,6 +845,7 @@ struct show_var_st init_vars[]= { {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, #ifdef HAVE_REPLICATION {sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS}, + {"relay_log_space_limit", (char*) &relay_log_space_limit, SHOW_LONGLONG}, #endif {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS}, {"secure_auth", (char*) &sys_secure_auth, SHOW_SYS}, From 43a954666f7dc547403976244a596e35b28914e5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Mar 2005 13:57:59 +0100 Subject: [PATCH 06/12] BUG#9123: Updates after Mats review --- client/mysqldump.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 8df17ace780..438c338c5ef 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2107,10 +2107,10 @@ static void get_actual_table_name(const char *old_table_name, { MYSQL_RES *tableRes; MYSQL_ROW row; - char query[ NAME_LEN + 50 ]; + char query[2*NAME_LEN+50]; + char show_name_buff[FN_REFLEN]; DBUG_ENTER("get_actual_table_name"); - char show_name_buff[FN_REFLEN]; sprintf(query, "SHOW TABLES LIKE %s", quote_for_like(old_table_name, show_name_buff)); if (mysql_query_with_error_report(sock, 0, query)) From 36c3583618a13446472c5cb2a69db1ad8f5660c6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Mar 2005 15:32:43 +0200 Subject: [PATCH 07/12] Fix to get --skip-ndb to work --- mysql-test/mysql-test-run.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index aab2b1d7da2..ddf69044645 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -428,8 +428,8 @@ while test $# -gt 0; do ;; --skip-ndbcluster | --skip-ndb) USE_NDBCLUSTER="" - EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1" - EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT $1" + EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-ndbcluster" + EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-ndbcluster" ;; --skip-*) EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1" From a5c87958a6ae43bd4b998dd4d54a19043a8e3b0f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Mar 2005 16:44:28 +0300 Subject: [PATCH 08/12] Fix for bug#8656: Crash with group_concat on alias in outer table fixed result_field support of Item_ref --- mysql-test/r/func_gconcat.result | 7 +++++++ mysql-test/t/func_gconcat.test | 8 ++++++++ sql/item.h | 1 + 3 files changed, 16 insertions(+) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 390b33fdddc..c1ac1c084df 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -462,3 +462,10 @@ SELECT GROUP_CONCAT(id) AS gc FROM t1 HAVING gc IS NULL; gc NULL DROP TABLE t1; +create table r2 (a int, b int); +insert into r2 values (1,1), (2,2); +select b x, (select group_concat(x) from r2) from r2; +x (select group_concat(x) from r2) +1 1,1 +2 2,2 +drop table r2; diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 6a91a7ac9c7..d32c8796075 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -284,3 +284,11 @@ drop table t1; CREATE TABLE t1 (id int); SELECT GROUP_CONCAT(id) AS gc FROM t1 HAVING gc IS NULL; DROP TABLE t1; + +# +# Bug #8656: Crash with group_concat on alias in outer table +# +create table r2 (a int, b int); +insert into r2 values (1,1), (2,2); +select b x, (select group_concat(x) from r2) from r2; +drop table r2; diff --git a/sql/item.h b/sql/item.h index adc780677e1..78de2a1f58e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -902,6 +902,7 @@ public: void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); } enum Item_result result_type () const { return (*ref)->result_type(); } enum_field_types field_type() const { return (*ref)->field_type(); } + Field *get_tmp_table_field() { return result_field; } table_map used_tables() const { return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables(); From b3a5e5b1fd80885b0d0763280d259b4c3ae21c2b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Mar 2005 17:44:29 +0400 Subject: [PATCH 09/12] Bugs#9129: CHARSET(), COLLATION(), COERCIBILITY() not always correct for NULL values. Now they always result a non NULL value even the argument is NULL. It is more usefull for debugging purposes. mysql-test/r/func_str.result: Bugs#9129: CHARSET(), COLLATION(), COERCIBILITY() not always correct for NULL values. Also, a mistake in EXPORT_SET was fixed. mysql-test/t/func_str.test: Bugs#9129: CHARSET(), COLLATION(), COERCIBILITY() not always correct for NULL values. sql/item_func.cc: Bugs#9129: CHARSET(), COLLATION(), COERCIBILITY() not always correct for NULL values. sql/item_strfunc.cc: Bugs#9129: CHARSET(), COLLATION(), COERCIBILITY() not always correct for NULL values. A minor mistake in EXPORT_SET() was fixed. --- mysql-test/r/func_str.result | 11 ++++++++++- mysql-test/t/func_str.test | 9 +++++++++ sql/item_func.cc | 5 ----- sql/item_strfunc.cc | 15 +++++++-------- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 855473bdc08..ab652b9d850 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -512,7 +512,7 @@ collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')) coercibility(make_set( latin2_general_ci 4 select collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')), coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' ')); collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')) coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' ')) -binary 4 +latin2_general_ci 4 select collation(trim(_latin2' a ')), coercibility(trim(_latin2' a ')); collation(trim(_latin2' a ')) coercibility(trim(_latin2' a ')) latin2_general_ci 4 @@ -627,6 +627,15 @@ t1 CREATE TABLE `t1` ( `encode('abcd','ab')` binary(4) NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +create table t1 (a char character set latin2); +insert into t1 values (null); +select charset(a), collation(a), coercibility(a) from t1; +charset(a) collation(a) coercibility(a) +latin2 latin2_general_ci 2 +drop table t1; +select charset(null), collation(null), coercibility(null); +charset(null) collation(null) coercibility(null) +binary binary 5 select SUBSTR('abcdefg',3,2); SUBSTR('abcdefg',3,2) cd diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 4e504797a48..e7069c41716 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -368,6 +368,15 @@ select show create table t1; drop table t1; +# +# Bug#9129 +# +create table t1 (a char character set latin2); +insert into t1 values (null); +select charset(a), collation(a), coercibility(a) from t1; +drop table t1; +select charset(null), collation(null), coercibility(null); + # # test for SUBSTR # diff --git a/sql/item_func.cc b/sql/item_func.cc index 96250522c4a..ade394f90d3 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1346,11 +1346,6 @@ longlong Item_func_char_length::val_int() longlong Item_func_coercibility::val_int() { DBUG_ASSERT(fixed == 1); - if (args[0]->null_value) - { - null_value= 1; - return 0; - } null_value= 0; return (longlong) args[0]->collation.derivation; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index b4f75859469..8b9351d95a5 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2290,12 +2290,11 @@ bool Item_func_set_collation::eq(const Item *item, bool binary_cmp) const String *Item_func_charset::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res = args[0]->val_str(str); uint dummy_errors; - if ((null_value=(args[0]->null_value || !res->charset()))) - return 0; - str->copy(res->charset()->csname,strlen(res->charset()->csname), + CHARSET_INFO *cs= args[0]->collation.collation; + null_value= 0; + str->copy(cs->csname, strlen(cs->csname), &my_charset_latin1, collation.collation, &dummy_errors); return str; } @@ -2303,12 +2302,11 @@ String *Item_func_charset::val_str(String *str) String *Item_func_collation::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res = args[0]->val_str(str); uint dummy_errors; + CHARSET_INFO *cs= args[0]->collation.collation; - if ((null_value=(args[0]->null_value || !res->charset()))) - return 0; - str->copy(res->charset()->name,strlen(res->charset()->name), + null_value= 0; + str->copy(cs->name, strlen(cs->name), &my_charset_latin1, collation.collation, &dummy_errors); return str; } @@ -2472,6 +2470,7 @@ String* Item_func_export_set::val_str(String* str) uint num_set_values = 64; ulonglong mask = 0x1; str->length(0); + str->set_charset(collation.collation); /* Check if some argument is a NULL value */ if (args[0]->null_value || args[1]->null_value || args[2]->null_value) From 74007170b58a8b84521487685fd2993f310b8b14 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Mar 2005 21:56:56 +0100 Subject: [PATCH 10/12] Fixes after Sinisa and Serg comments after push of patch for BUG#9123. BUG#9123 is solved earlier than this patch though. --- client/mysqldump.c | 93 ++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 438c338c5ef..0ff88bcbc73 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -871,8 +871,8 @@ static int dbConnect(char *host, char *user,char *passwd) cannot reconnect. */ sock->reconnect= 0; - sprintf(buff, "/*!40100 SET @@SQL_MODE='%s' */", - compatible_mode_normal_str); + my_snprintf(buff, sizeof(buff), "/*!40100 SET @@SQL_MODE='%s' */", + compatible_mode_normal_str); if (mysql_query_with_error_report(sock, 0, buff)) { mysql_close(sock); @@ -1107,8 +1107,9 @@ static uint getTableStructure(char *table, char* db) if (verbose) fprintf(stderr, "-- Retrieving table structure for table %s...\n", table); - sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", - (opt_quoted || opt_keywords)); + my_snprintf(insert_pat, sizeof(insert_pat), + "SET OPTION SQL_QUOTE_SHOW_CREATE=%d", + (opt_quoted || opt_keywords)); if (!create_options) strmov(strend(insert_pat), "/*!40102 ,SQL_MODE=concat(@@sql_mode, _utf8 ',NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS') */"); @@ -1126,7 +1127,7 @@ static uint getTableStructure(char *table, char* db) /* Make an sql-file, if path was given iow. option -T was given */ char buff[20+FN_REFLEN]; - sprintf(buff,"show create table %s", result_table); + my_snprintf(buff, sizeof(buff), "show create table %s", result_table); if (mysql_query_with_error_report(sock, 0, buff)) { safe_exit(EX_MYSQLERR); @@ -1164,7 +1165,8 @@ static uint getTableStructure(char *table, char* db) check_io(sql_file); mysql_free_result(tableRes); } - sprintf(insert_pat,"show fields from %s", result_table); + my_snprintf(insert_pat, sizeof(insert_pat), "show fields from %s", + result_table); if (mysql_query_with_error_report(sock, &tableRes, insert_pat)) { if (path) @@ -1174,11 +1176,12 @@ static uint getTableStructure(char *table, char* db) } if (cFlag) - sprintf(insert_pat, "INSERT %sINTO %s (", delayed, opt_quoted_table); + my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s (", + delayed, opt_quoted_table); else { - sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, - opt_quoted_table); + my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s VALUES ", + delayed, opt_quoted_table); if (!extended_insert) strcat(insert_pat,"("); } @@ -1205,7 +1208,8 @@ static uint getTableStructure(char *table, char* db) "%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n", my_progname, mysql_error(sock)); - sprintf(insert_pat,"show fields from %s", result_table); + my_snprintf(insert_pat, sizeof(insert_pat), "show fields from %s", + result_table); if (mysql_query_with_error_report(sock, &tableRes, insert_pat)) { safe_exit(EX_MYSQLERR); @@ -1240,10 +1244,12 @@ static uint getTableStructure(char *table, char* db) check_io(sql_file); } if (cFlag) - sprintf(insert_pat, "INSERT %sINTO %s (", delayed, result_table); + my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s (", + delayed, result_table); else { - sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, result_table); + my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s VALUES ", + delayed, result_table); if (!extended_insert) strcat(insert_pat,"("); } @@ -1300,7 +1306,7 @@ static uint getTableStructure(char *table, char* db) /* Make an sql-file, if path was given iow. option -T was given */ char buff[20+FN_REFLEN]; uint keynr,primary_key; - sprintf(buff,"show keys from %s", result_table); + my_snprintf(buff, sizeof(buff), "show keys from %s", result_table); if (mysql_query_with_error_report(sock, &tableRes, buff)) { if (path) @@ -1370,8 +1376,12 @@ static uint getTableStructure(char *table, char* db) if (create_options) { char show_name_buff[FN_REFLEN]; - sprintf(buff,"show table status like %s", - quote_for_like(table, show_name_buff)); + + /* Check memory for quote_for_like() */ + DBUG_ASSERT(2*sizeof(table) < sizeof(show_name_buff)); + my_snprintf(buff, sizeof(buff), "show table status like %s", + quote_for_like(table, show_name_buff)); + if (mysql_query_with_error_report(sock, &tableRes, buff)) { if (mysql_errno(sock) != ER_PARSE_ERROR) @@ -1531,8 +1541,9 @@ static void dumpTable(uint numFields, char *table) my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if filename wasn't deleted */ to_unix_path(filename); - sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'", - filename); + my_snprintf(query, QUERY_LENGTH, + "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'", + filename); end= strend(query); if (fields_terminated || enclosed || opt_enclosed || escaped) @@ -1544,7 +1555,7 @@ static void dumpTable(uint numFields, char *table) end= add_load_option(end, lines_terminated, " LINES TERMINATED BY"); *end= '\0'; - sprintf(buff," FROM %s", result_table); + my_snprintf(buff, sizeof(buff), " FROM %s", result_table); end= strmov(end,buff); if (where || order_by) { @@ -1572,8 +1583,9 @@ static void dumpTable(uint numFields, char *table) result_table); check_io(md_result_file); } - sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s", - result_table); + my_snprintf(query, QUERY_LENGTH, + "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s", + result_table); if (where || order_by) { query = alloc_query_str((ulong) (strlen(query) + 1 + @@ -1671,8 +1683,9 @@ static void dumpTable(uint numFields, char *table) int is_blob; if (!(field = mysql_fetch_field(res))) { - sprintf(query,"%s: Not enough fields from table %s! Aborting.\n", - my_progname, result_table); + my_snprintf(query, QUERY_LENGTH, + "%s: Not enough fields from table %s! Aborting.\n", + my_progname, result_table); fputs(query,stderr); error= EX_CONSCHECK; goto err; @@ -1873,12 +1886,13 @@ static void dumpTable(uint numFields, char *table) check_io(md_result_file); if (mysql_errno(sock)) { - sprintf(query,"%s: Error %d: %s when dumping table %s at row: %ld\n", - my_progname, - mysql_errno(sock), - mysql_error(sock), - result_table, - rownr); + my_snprintf(query, QUERY_LENGTH, + "%s: Error %d: %s when dumping table %s at row: %ld\n", + my_progname, + mysql_errno(sock), + mysql_error(sock), + result_table, + rownr); fputs(query,stderr); error= EX_CONSCHECK; goto err; @@ -1994,8 +2008,9 @@ static int init_dumping(char *database) MYSQL_ROW row; MYSQL_RES *dbinfo; - sprintf(qbuf,"SHOW CREATE DATABASE IF NOT EXISTS %s", - qdatabase); + my_snprintf(qbuf, sizeof(qbuf), + "SHOW CREATE DATABASE IF NOT EXISTS %s", + qdatabase); if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock))) { @@ -2107,12 +2122,15 @@ static void get_actual_table_name(const char *old_table_name, { MYSQL_RES *tableRes; MYSQL_ROW row; - char query[2*NAME_LEN+50]; + char query[50 + 2*NAME_LEN]; char show_name_buff[FN_REFLEN]; DBUG_ENTER("get_actual_table_name"); - sprintf(query, "SHOW TABLES LIKE %s", - quote_for_like(old_table_name, show_name_buff)); + /* Check memory for quote_for_like() */ + DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff)); + my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s", + quote_for_like(old_table_name, show_name_buff)); + if (mysql_query_with_error_report(sock, 0, query)) { safe_exit(EX_MYSQLERR); @@ -2357,8 +2375,10 @@ static const char *check_if_ignore_table(const char *table_name) MYSQL_ROW row; const char *result= 0; - sprintf(buff,"show table status like %s", - quote_for_like(table_name, show_name_buff)); + /* Check memory for quote_for_like() */ + DBUG_ASSERT(2*sizeof(table_name) < sizeof(show_name_buff)); + my_snprintf(buff, sizeof(buff), "show table status like %s", + quote_for_like(table_name, show_name_buff)); if (mysql_query_with_error_report(sock, &res, buff)) { if (mysql_errno(sock) != ER_PARSE_ERROR) @@ -2411,7 +2431,8 @@ static char *primary_key_fields(const char *table_name) uint result_length = 0; char *result = 0; - sprintf(show_keys_buff, "SHOW KEYS FROM %s", table_name); + my_snprintf(show_keys_buff, sizeof(show_keys_buff), + "SHOW KEYS FROM %s", table_name); if (mysql_query(sock, show_keys_buff) || !(res = mysql_store_result(sock))) { From 31f6b0dde83e7c4fc1626958f40f2c22ca51f23b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Mar 2005 15:55:04 -0800 Subject: [PATCH 11/12] olap.result, olap.test: Added a test for bug #8615. sql_select.cc: Fixed bug #8615. This fix only removed the cause of the reported crash. It does not resolve other problems of rollup queries with DISTINCT. They were fixed in the previous patch for bug 8616. sql/sql_select.cc: Fixed bug #8615. This fix only removed the cause of the reported crash. It does not resolve other problems of rollup queries with DISTINCT. They were fixed in the previous patch for bug 8616. mysql-test/t/olap.test: Added a test for bug #8615. mysql-test/r/olap.result: Added a test for bug #8615. --- mysql-test/r/olap.result | 18 ++++++++++++++++++ mysql-test/t/olap.test | 5 ++++- sql/sql_select.cc | 7 ++++--- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 67610108c61..fe83800f658 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -360,4 +360,22 @@ SUM(b) COUNT(DISTINCT b) COUNT(*) 6 2 4 4 1 4 14 3 9 +SELECT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +a sum(b) +1 4 +1 4 +2 2 +2 4 +2 6 +4 4 +4 4 +NULL 14 +SELECT DISTINCT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +a sum(b) +1 4 +2 2 +2 4 +2 6 +4 4 +NULL 14 DROP TABLE t1; diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test index d2ea582e58c..6778af3d533 100644 --- a/mysql-test/t/olap.test +++ b/mysql-test/t/olap.test @@ -126,7 +126,7 @@ SELECT DROP TABLE user_day; # -# Test for bug #8616: distinct sum with rollup +# Tests for bugs #8616, #8615: distinct sum with rollup # CREATE TABLE t1 (a int, b int); @@ -150,5 +150,8 @@ SELECT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; SELECT DISTINCT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; +SELECT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +SELECT DISTINCT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; + DROP TABLE t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0bb4c6a9402..5bfe1346568 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1269,7 +1269,6 @@ JOIN::exec() { DBUG_VOID_RETURN; } - curr_join->group_list= 0; } thd->proc_info="Copying to group table"; @@ -1289,8 +1288,10 @@ JOIN::exec() } } if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list, - 1) || - (tmp_error= do_select(curr_join, (List *) 0, curr_tmp_table, + 1)) + DBUG_VOID_RETURN; + curr_join->group_list= 0; + if ((tmp_error= do_select(curr_join, (List *) 0, curr_tmp_table, 0))) { error= tmp_error; From 7ceb5c6cef7c1b9bebe3869e9836035fbb177601 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 Mar 2005 10:24:50 +0400 Subject: [PATCH 12/12] A fix (bug #8942: SUBSTRING_INDEX in UPDATE causes internal loop). sql/key.cc: A fix (bug #8942: SUBSTRING_INDEX in UPDATE causes internal loop). For "partial" key parts (e.g. key(a(20), ...) we create different key_part->field, see sql/table.cc; so we have to use the eq() function here to compare fields. --- mysql-test/r/update.result | 7 +++++++ mysql-test/t/update.test | 10 ++++++++++ sql/key.cc | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 7810d52d156..9ca92fe75df 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -209,3 +209,10 @@ insert into t1 values (1, "t1c2-1", 10), (2, "t1c2-2", 20); update t1 left join t2 on t1.c1 = t2.c1 set t2.c2 = "t2c2-1"; update t1 left join t2 on t1.c1 = t2.c1 set t2.c2 = "t2c2-1" where t1.c3 = 10; drop table t1, t2; +create table t1 (a int, b char(255), key(a, b(20))); +insert into t1 values (0, '1'); +update t1 set b = b + 1 where a = 0; +select * from t1; +a b +0 2 +drop table t1; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index 62439dcc51b..6c7b450f763 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -164,3 +164,13 @@ insert into t1 values (1, "t1c2-1", 10), (2, "t1c2-2", 20); update t1 left join t2 on t1.c1 = t2.c1 set t2.c2 = "t2c2-1"; update t1 left join t2 on t1.c1 = t2.c1 set t2.c2 = "t2c2-1" where t1.c3 = 10; drop table t1, t2; + +# +# Bug #8942: a problem with update and partial key part +# + +create table t1 (a int, b char(255), key(a, b(20))); +insert into t1 values (0, '1'); +update t1 set b = b + 1 where a = 0; +select * from t1; +drop table t1; diff --git a/sql/key.cc b/sql/key.cc index 0a5937fc881..52eb108a5df 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -265,7 +265,7 @@ bool check_if_key_used(TABLE *table, uint idx, List &fields) f.rewind(); while ((field=(Item_field*) f++)) { - if (key_part->field == field->field) + if (key_part->field->eq(field->field)) return 1; } }