From 8d5277a75ab8e30613a17fe132481bfe68997fd0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Mar 2006 23:30:34 +0400 Subject: Fixed bug#15560: GROUP_CONCAT wasn't ready for WITH ROLLUP queries The GROUP_CONCAT uses its own temporary table. When ROLLUP is present it creates the second copy of Item_func_group_concat. This copy receives the same list of arguments that original group_concat does. When the copy is set up the result_fields of functions from the argument list are reset to the temporary table of this copy. As a result of this action data from functions flow directly to the ROLLUP copy and the original group_concat functions shows wrong result. Since queries with COUNT(DISTINCT ...) use temporary tables to store the results the COUNT function they are also affected by this bug. The idea of the fix is to copy content of the result_field for the function under GROUP_CONCAT/COUNT from the first temporary table to the second one, rather than setting result_field to point to the second temporary table. To achieve this goal force_copy_fields flag is added to Item_func_group_concat and Item_sum_count_distinct classes. This flag is initialized to 0 and set to 1 into the make_unique() member function of both classes. To the TMP_TABLE_PARAM structure is modified to include the similar flag as well. The create_tmp_table() function passes that flag to create_tmp_field(). When the flag is set the create_tmp_field() function will set result_field as a source field and will not reset that result field to newly created field for Item_func_result_field and its descendants. Due to this there will be created copy func to copy data from old result_field to newly created field. mysql-test/t/func_gconcat.test: Added test for bug#15560: GROUP_CONCAT wasn't ready for WITH ROLLUP queries mysql-test/r/func_gconcat.result: Added test for bug#15560: GROUP_CONCAT wasn't ready for WITH ROLLUP queries sql/sql_table.cc: Fixed bug#15560: GROUP_CONCAT wasn't ready for WITH ROLLUP queries Added 0 as a last parameter to create_tmp_field() to force old behaviour. sql/sql_select.cc: Fixed bug#15560: GROUP_CONCAT wasn't ready for WITH ROLLUP queries Added the flag 'make_copy_field' to create_tmp_field(), so that for Item_result_field descendants create_tmp_field() sets the item's result field as a source field and deny resetting that result field to a new value. sql/sql_class.h: Fixed bug#15560: GROUP_CONCAT wasn't ready for WITH ROLLUP queries Added the flag 'force_copy_fields' to the structure TMP_TABLE_PARAM in order to make create_tmp_field() force the creation of 'copy_field' objects. sql/mysql_priv.h: Fixed bug#15560: GROUP_CONCAT wasn't ready for WITH ROLLUP queries Added the bool parameter 'make_copy_field' to create_tmp_field(). sql/item_sum.cc: Fixed bug#15560: GROUP_CONCAT wasn't ready for WITH ROLLUP queries Added initialization of the force_copy_fields flag and passing it to create_tmp_table() through TMP_TBLE_PARAM in the Item_func_group_concat and Item_sum_count_distinct member functions. sql/item_sum.h: Fixed bug#15560: GROUP_CONCAT wasn't ready for WITH ROLLUP queries Added the flag 'force_copy_fields' to the Item_func_group_concat and Item_sum_count_distinct classes. --- mysql-test/r/func_gconcat.result | 15 +++++++++++++++ mysql-test/t/func_gconcat.test | 8 ++++++++ sql/item_sum.cc | 6 ++++++ sql/item_sum.h | 9 ++++++--- sql/mysql_priv.h | 5 +++-- sql/sql_class.h | 5 +++-- sql/sql_select.cc | 21 +++++++++++++++------ sql/sql_table.cc | 2 +- 8 files changed, 57 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 200b4a4d53b..3cb8da7f63f 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -589,3 +589,18 @@ GROUP_CONCAT(a ORDER BY a) ,x ,z DROP TABLE t1; +create table t1(f1 int); +insert into t1 values(1),(2),(3); +select f1, group_concat(f1+1) from t1 group by f1 with rollup; +f1 group_concat(f1+1) +1 2 +2 3 +3 4 +NULL 2,3,4 +select count(distinct (f1+1)) from t1 group by f1 with rollup; +count(distinct (f1+1)) +1 +1 +1 +3 +drop table t1; diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index eb1cbc3d667..f116aa6f164 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -382,4 +382,12 @@ SELECT GROUP_CONCAT(a ORDER BY a) FROM t1 GROUP BY id; DROP TABLE t1; +# +# Bug #15560: GROUP_CONCAT wasn't ready for WITH ROLLUP queries +# +create table t1(f1 int); +insert into t1 values(1),(2),(3); +select f1, group_concat(f1+1) from t1 group by f1 with rollup; +select count(distinct (f1+1)) from t1 group by f1 with rollup; +drop table t1; # End of 4.1 tests diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 43468adea1a..4b522cf06fa 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1185,6 +1185,7 @@ void Item_sum_count_distinct::make_unique() original= 0; use_tree= 0; // to prevent delete_tree call on uninitialized tree tree= &tree_base; + force_copy_fields= 1; } @@ -1219,6 +1220,7 @@ bool Item_sum_count_distinct::setup(THD *thd) free_tmp_table(thd, table); tmp_table_param->cleanup(); } + tmp_table_param->force_copy_fields= force_copy_fields; if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1, 0, select_lex->options | thd->options, @@ -1724,6 +1726,7 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct, String *is_separator) :Item_sum(), tmp_table_param(0), max_elements_in_tree(0), warning(0), key_length(0), tree_mode(0), distinct(is_distinct), warning_for_row(0), + force_copy_fields(0), separator(is_separator), tree(&tree_base), table(0), order(0), tables_list(0), arg_count_order(0), arg_count_field(0), @@ -1785,6 +1788,7 @@ Item_func_group_concat::Item_func_group_concat(THD *thd, tree_mode(item->tree_mode), distinct(item->distinct), warning_for_row(item->warning_for_row), + force_copy_fields(item->force_copy_fields), separator(item->separator), tree(item->tree), table(item->table), @@ -2004,6 +2008,7 @@ bool Item_func_group_concat::setup(THD *thd) free_tmp_table(thd, table); tmp_table_param->cleanup(); } + tmp_table_param->force_copy_fields= force_copy_fields; /* We have to create a temporary table to get descriptions of fields (types, sizes and so on). @@ -2079,6 +2084,7 @@ void Item_func_group_concat::make_unique() original= 0; tree_mode= 0; // to prevent delete_tree call on uninitialized tree tree= &tree_base; + force_copy_fields= 1; } diff --git a/sql/item_sum.h b/sql/item_sum.h index d53d8d861ae..c972240fcba 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -185,6 +185,7 @@ class Item_sum_count_distinct :public Item_sum_int TMP_TABLE_PARAM *tmp_table_param; TREE tree_base; TREE *tree; + bool force_copy_fields; /* Following is 0 normal object and pointer to original one for copy (to correctly free resources) @@ -226,15 +227,16 @@ class Item_sum_count_distinct :public Item_sum_int public: Item_sum_count_distinct(List &list) :Item_sum_int(list), table(0), used_table_cache(~(table_map) 0), - tmp_table_param(0), tree(&tree_base), original(0), use_tree(0), - always_null(0) + tmp_table_param(0), tree(&tree_base), force_copy_fields(0), original(0), + use_tree(0), always_null(0) { quick_group= 0; } Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item) :Item_sum_int(thd, item), table(item->table), used_table_cache(item->used_table_cache), field_lengths(item->field_lengths), tmp_table_param(item->tmp_table_param), - tree(item->tree), original(item), key_length(item->key_length), + tree(item->tree), force_copy_fields(item->force_copy_fields), + original(item), key_length(item->key_length), max_elements_in_tree(item->max_elements_in_tree), rec_offset(item->rec_offset), use_tree(item->use_tree), always_null(item->always_null) @@ -685,6 +687,7 @@ class Item_func_group_concat : public Item_sum bool distinct; bool warning_for_row; bool always_null; + bool force_copy_fields; friend int group_concat_key_cmp_with_distinct(void* arg, byte* key1, byte* key2); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 429a71b4437..72424819078 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -537,8 +537,9 @@ int mysql_union(THD *thd, LEX *lex, select_result *result, SELECT_LEX_UNIT *unit); int mysql_handle_derived(LEX *lex); Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, - Item ***copy_func, Field **from_field, - bool group, bool modify_item, uint convert_blob_length); + Item ***copy_func, Field **from_field, + bool group, bool modify_item, uint convert_blob_length, + bool make_copy_field); int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, List &fields, List &keys, uint &db_options, diff --git a/sql/sql_class.h b/sql/sql_class.h index 41170192892..1bd7dcac03c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1334,10 +1334,11 @@ public: bool using_indirect_summary_function; /* If >0 convert all blob fields to varchar(convert_blob_length) */ uint convert_blob_length; - + bool force_copy_fields; TMP_TABLE_PARAM() :copy_field(0), group_parts(0), - group_length(0), group_null_parts(0), convert_blob_length(0) + group_length(0), group_null_parts(0), convert_blob_length(0), + force_copy_fields(0) {} ~TMP_TABLE_PARAM() { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ec62e80ba13..d7aa617cffd 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4984,7 +4984,8 @@ static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item ***copy_func, Field **from_field, - bool group, bool modify_item, uint convert_blob_length) + bool group, bool modify_item, uint convert_blob_length, + bool make_copy_field) { switch (type) { case Item::SUM_FUNC_ITEM: @@ -5071,7 +5072,13 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, case Item::REF_ITEM: case Item::NULL_ITEM: case Item::VARBIN_ITEM: - return create_tmp_field_from_item(thd, item, table, copy_func, modify_item, + if (make_copy_field) + { + DBUG_ASSERT(((Item_result_field*)item)->result_field); + *from_field= ((Item_result_field*)item)->result_field; + } + return create_tmp_field_from_item(thd, item, table, (make_copy_field ? 0 : + copy_func), modify_item, convert_blob_length); case Item::TYPE_HOLDER: return ((Item_type_holder *)item)->make_field_by_type(table); @@ -5110,7 +5117,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, Item **copy_func; MI_COLUMNDEF *recinfo; uint temp_pool_slot=MY_BIT_NONE; - + bool force_copy_fields= param->force_copy_fields; DBUG_ENTER("create_tmp_table"); DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d", (int) distinct, (int) save_sum_fields, @@ -5241,7 +5248,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, Field *new_field= create_tmp_field(thd, table, arg, arg->type(), ©_func, tmp_from_field, group != 0,not_all_columns, - param->convert_blob_length); + param->convert_blob_length, 0); if (!new_field) goto err; // Should be OOM tmp_from_field++; @@ -5279,8 +5286,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, */ Field *new_field= create_tmp_field(thd, table, item, type, ©_func, tmp_from_field, group != 0, - not_all_columns || group !=0, - param->convert_blob_length); + !force_copy_fields && + (not_all_columns || group !=0), + param->convert_blob_length, + force_copy_fields); if (!new_field) { if (thd->is_fatal_error) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 71cbc0be1e3..1cb49f9933c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1562,7 +1562,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, field=item->tmp_table_field(&tmp_table); else field=create_tmp_field(thd, &tmp_table, item, item->type(), - (Item ***) 0, &tmp_field, 0, 0, 0); + (Item ***) 0, &tmp_field, 0, 0, 0, 0); if (!field || !(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ? ((Item_field *)item)->field : -- cgit v1.2.1 From 0e974fbd2c9ec74d0c90543c74c43d9ef20cb690 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Mar 2006 01:50:52 +0300 Subject: Fix error in prefix compression of keys in MyISAM when key length changed from 254 -> 255 Bug #17705 "FT Index corruption occurs with UTF8 data..." (Actually, the bug had nothing to do with FT index but with general key compression) myisam/mi_search.c: Fix error in prefix compression of keys in MyISAM when key length changed from 254 -> 255 mysql-test/r/ctype_utf8.result: Test of fix for key compression bug mysql-test/t/ctype_utf8.test: Test of fix for key compression bug --- myisam/mi_search.c | 11 ++++------ mysql-test/r/ctype_utf8.result | 46 ++++++++++++++++++++++++++++++++++++++++++ mysql-test/t/ctype_utf8.test | 34 +++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 7 deletions(-) diff --git a/myisam/mi_search.c b/myisam/mi_search.c index 9321f5b87d5..517fc9c25ff 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -1456,7 +1456,7 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, if (!*key++) { s_temp->key=key; - s_temp->ref_length=s_temp->key_length=0; + s_temp->key_length= 0; s_temp->totlength=key_length-1+diff_flag; s_temp->next_key_pos=0; /* No next key */ return (s_temp->totlength); @@ -1611,12 +1611,12 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, s_temp->prev_length= org_key_length; s_temp->n_ref_length=s_temp->n_length= org_key_length; length+= org_key_length; - /* +get_pack_length(org_key_length); */ } return (int) length; } ref_length=n_length; + /* Get information about not packed key suffix */ get_key_pack_length(n_length,next_length_pack,next_key); /* Test if new keys has fewer characters that match the previous key */ @@ -1625,7 +1625,6 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, s_temp->part_of_prev_key= 0; s_temp->prev_length= ref_length; s_temp->n_ref_length= s_temp->n_length= n_length+ref_length; - /* s_temp->prev_key+= get_pack_length(org_key_length); */ return (int) length+ref_length-next_length_pack; } if (ref_length+pack_marker > new_ref_length) @@ -1636,9 +1635,7 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, s_temp->prev_length= ref_length - new_pack_length; s_temp->n_ref_length=s_temp->n_length=n_length + s_temp->prev_length; s_temp->prev_key+= new_pack_length; -/* +get_pack_length(org_key_length); */ - length= length-get_pack_length(ref_length)+ - get_pack_length(new_pack_length); + length-= (next_length_pack - get_pack_length(s_temp->n_length)); return (int) length + s_temp->prev_length; } } @@ -1647,7 +1644,7 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, /* Next key wasn't a prefix of previous key */ ref_length=0; next_length_pack=0; - } + } DBUG_PRINT("test",("length: %d next_key: %lx", length, (long) next_key)); diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index cf9426e6b21..69d7577ee77 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1078,3 +1078,49 @@ LENGTH(bug) 100 DROP TABLE t2; DROP TABLE t1; +SET NAMES utf8; +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 't1' +CREATE TABLE t1(a VARCHAR(255), KEY(a)) ENGINE=MyISAM DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES('uuABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'); +INSERT INTO t1 VALUES('uu'); +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +INSERT INTO t1 VALUES('uU'); +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +INSERT INTO t1 VALUES('uu'); +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +INSERT INTO t1 VALUES('uuABC'); +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +INSERT INTO t1 VALUES('UuABC'); +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +INSERT INTO t1 VALUES('uuABC'); +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +alter table t1 add b int; +INSERT INTO t1 VALUES('uuABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',1); +INSERT INTO t1 VALUES('uuABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',2); +delete from t1 where b=1; +INSERT INTO t1 VALUES('UUABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',1); +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +INSERT INTO t1 VALUES('uuABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',3); +INSERT INTO t1 VALUES('uuABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',4); +delete from t1 where b=3; +INSERT INTO t1 VALUES('uUABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',3); +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 01bffe9492e..5044f7979f1 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -892,4 +892,38 @@ SELECT LENGTH(bug) FROM t2; DROP TABLE t2; DROP TABLE t1; +# +# Bug#17705: Corruption of compressed index when index length changes between +# 254 and 256 +# + +SET NAMES utf8; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(a VARCHAR(255), KEY(a)) ENGINE=MyISAM DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES('uuABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'); +INSERT INTO t1 VALUES('uu'); +check table t1; +INSERT INTO t1 VALUES('uU'); +check table t1; +INSERT INTO t1 VALUES('uu'); +check table t1; +INSERT INTO t1 VALUES('uuABC'); +check table t1; +INSERT INTO t1 VALUES('UuABC'); +check table t1; +INSERT INTO t1 VALUES('uuABC'); +check table t1; +alter table t1 add b int; +INSERT INTO t1 VALUES('uuABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',1); +INSERT INTO t1 VALUES('uuABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',2); +delete from t1 where b=1; +INSERT INTO t1 VALUES('UUABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',1); +check table t1; +INSERT INTO t1 VALUES('uuABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',3); +INSERT INTO t1 VALUES('uuABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',4); +delete from t1 where b=3; +INSERT INTO t1 VALUES('uUABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',3); +check table t1; +drop table t1; + # End of 4.1 tests -- cgit v1.2.1 From dcf6f2702ec64d0b4bbea749388785e2d6c00c9c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Mar 2006 03:11:37 +0300 Subject: Cleanup during review of new pushed code sql/ha_heap.cc: Indentation fixes strings/ctype-ucs2.c: Simplify code tests/mysql_client_test.c: Remove compiler warnings --- sql/ha_heap.cc | 18 +++++++----------- strings/ctype-ucs2.c | 4 ++-- tests/mysql_client_test.c | 6 +++--- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index ab0ab5d8b64..9c680daaf91 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -480,17 +480,13 @@ ha_rows ha_heap::records_in_range(uint inx, key_range *min_key, min_key->flag != HA_READ_KEY_EXACT || max_key->flag != HA_READ_AFTER_KEY) return HA_POS_ERROR; // Can only use exact keys - else - { - if (records <= 1) - return records; - else - { - /* Assert that info() did run. We need current statistics here. */ - DBUG_ASSERT(key_stat_version == file->s->key_stat_version); - return key->rec_per_key[key->key_parts-1]; - } - } + + if (records <= 1) + return records; + + /* Assert that info() did run. We need current statistics here. */ + DBUG_ASSERT(key_stat_version == file->s->key_stat_version); + return key->rec_per_key[key->key_parts-1]; } diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index e172ad3e3d3..2cbd104329e 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -253,8 +253,8 @@ static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)), uint minlen; /* extra safety to make sure the lengths are even numbers */ - slen= (slen >> 1) << 1; - tlen= (tlen >> 1) << 1; + slen= slen & ~(uint) 1; + tlen= tlen & ~(uint) 1; se= s + slen; te= t + tlen; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 71ae5e4f052..5133a9013d2 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11719,13 +11719,13 @@ static void test_bug12744() rc= mysql_kill(mysql, mysql_thread_id(mysql)); DIE_UNLESS(rc==0); - if (rc= mysql_stmt_execute(prep_stmt)) + if ((rc= mysql_stmt_execute(prep_stmt))) { - if (rc= mysql_stmt_reset(prep_stmt)) + if ((rc= mysql_stmt_reset(prep_stmt))) printf("OK!\n"); else { - printf("Error!"); + printf("Error!\n"); DIE_UNLESS(1==0); } } -- cgit v1.2.1 From bcad85f7ed1d306fb775d258f4b3833710a1dfa6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Mar 2006 19:04:21 +0400 Subject: item_sum.cc, sql_select.cc: After merge fix for bug#15560 item_sum.h: After merge fix for bug#15560 sql/sql_select.cc: After merge fix for bug#15560 sql/item_sum.h: After merge fix for bug#15560 sql/item_sum.cc: After merge fix for bug#15560 --- sql/item_sum.cc | 6 +++--- sql/item_sum.h | 4 ++-- sql/sql_select.cc | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 4948e60b309..1cd1741cea6 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3024,14 +3024,14 @@ Item_func_group_concat(Name_resolution_context *context_arg, bool distinct_arg, List *select_list, SQL_LIST *order_list, String *separator_arg) :tmp_table_param(0), warning(0), - force_copy_fields(0), separator(separator_arg), tree(0), table(0), + separator(separator_arg), tree(0), table(0), order(0), context(context_arg), arg_count_order(order_list ? order_list->elements : 0), arg_count_field(select_list->elements), count_cut_values(0), distinct(distinct_arg), warning_for_row(FALSE), - original(0) + force_copy_fields(0), original(0) { Item *item_select; Item **arg_ptr; @@ -3077,7 +3077,6 @@ Item_func_group_concat::Item_func_group_concat(THD *thd, :Item_sum(thd, item), tmp_table_param(item->tmp_table_param), warning(item->warning), - force_copy_fields(item->force_copy_fields), separator(item->separator), tree(item->tree), table(item->table), @@ -3089,6 +3088,7 @@ Item_func_group_concat::Item_func_group_concat(THD *thd, distinct(item->distinct), warning_for_row(item->warning_for_row), always_null(item->always_null), + force_copy_fields(item->force_copy_fields), original(item) { quick_group= item->quick_group; diff --git a/sql/item_sum.h b/sql/item_sum.h index 4bd28d6b1df..328f8dd8400 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -525,13 +525,13 @@ class Item_sum_count_distinct :public Item_sum_int public: Item_sum_count_distinct(List &list) :Item_sum_int(list), table(0), field_lengths(0), tmp_table_param(0), - tree(0), force_copy_fields(0), original(0), always_null(FALSE) + force_copy_fields(0), tree(0), original(0), always_null(FALSE) { quick_group= 0; } Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item) :Item_sum_int(thd, item), table(item->table), field_lengths(item->field_lengths), tmp_table_param(item->tmp_table_param), - tree(item->tree), force_copy_fields(0), original(item), + force_copy_fields(0), tree(item->tree), original(item), tree_key_length(item->tree_key_length), always_null(item->always_null) {} diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7998449a00b..1712819aad4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8669,8 +8669,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, create_tmp_field_for_schema(thd, item, table) : create_tmp_field(thd, table, item, type, ©_func, tmp_from_field, group != 0, - not_all_columns || group != 0, - item->marker == 4, 0, + !force_copy_fields && + (not_all_columns || group !=0), + item->marker == 4, force_copy_fields, param->convert_blob_length); if (!new_field) -- cgit v1.2.1 From 15ca81f5250fd5de5abeb6a383922f2a8f85040f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Mar 2006 22:35:50 +0400 Subject: Fix incorrect merge: put '/*' comment start back. --- tests/mysql_client_test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 87f00a92125..b1ea5f8ea06 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -12992,6 +12992,7 @@ static void test_bug9520() } +/* We can't have more than one cursor open for a prepared statement. Test re-executions of a PS with cursor; mysql_stmt_reset must close the cursor attached to the statement, if there is one. -- cgit v1.2.1 From 62302ad04d779372eef8723d7a841e39ab024975 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 31 Mar 2006 21:26:17 -0800 Subject: Fixed bug #16504. Multiple equalities were not adjusted after reading constant tables. It resulted in neglecting good index based methods that could be used to access of other tables. mysql-test/r/having.result: Adjusted a test case results after fix for bug #16504. mysql-test/r/select.result: Added a test case for bug #16504. mysql-test/r/subselect.result: Adjusted a test case results after fix for bug #16504. mysql-test/r/varbinary.result: Adjusted a test case results after fix for bug #16504. mysql-test/t/select.test: Added a test case for bug #16504. sql/item.cc: Fixed bug #16504. An Item_equal object may contain only a constant member. It may happen after reading constant tables. sql/item_cmpfunc.cc: Fixed bug #16504. Added method Item_equal::check_const that check appearance of new constant items in a multiple equality. sql/item_cmpfunc.h: Fixed bug #16504. Added method Item_equal::check_const that check appearance of new constant items in a multiple equality. sql/sql_select.cc: Fixed bug #16504. Adjusted multiple equalities after reading constant tables. Fixed a few typo in comments. --- mysql-test/r/having.result | 2 +- mysql-test/r/select.result | 19 +++++++++++ mysql-test/r/subselect.result | 2 +- mysql-test/r/varbinary.result | 2 +- mysql-test/t/select.test | 23 +++++++++++++ sql/item.cc | 2 +- sql/item_cmpfunc.cc | 37 ++++++++++++++++++-- sql/item_cmpfunc.h | 1 + sql/sql_select.cc | 78 ++++++++++++++++++++++++++++++++++++++----- 9 files changed, 151 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result index e54f6d7f2a4..225d5a475ff 100644 --- a/mysql-test/r/having.result +++ b/mysql-test/r/having.result @@ -12,7 +12,7 @@ explain extended select count(a) as b from t1 where a=0 having b >=0; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables Warnings: -Note 1003 select count(`test`.`t1`.`a`) AS `b` from `test`.`t1` where (`test`.`t1`.`a` = 0) having (count(`test`.`t1`.`a`) >= 0) +Note 1003 select count(`test`.`t1`.`a`) AS `b` from `test`.`t1` where 0 having (count(`test`.`t1`.`a`) >= 0) drop table t1; CREATE TABLE t1 ( raw_id int(10) NOT NULL default '0', diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index df68cdfff53..02f27423f99 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -3371,3 +3371,22 @@ NULL a NULL drop table t1,t2; select * from (select * left join t on f1=f2) tt; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'on f1=f2) tt' at line 1 +CREATE TABLE t1 (sku int PRIMARY KEY, pr int); +CREATE TABLE t2 (sku int PRIMARY KEY, sppr int, name varchar(255)); +INSERT INTO t1 VALUES +(10, 10), (20, 10), (30, 20), (40, 30), (50, 10), (60, 10); +INSERT INTO t2 VALUES +(10, 10, 'aaa'), (20, 10, 'bbb'), (30, 10, 'ccc'), (40, 20, 'ddd'), +(50, 10, 'eee'), (60, 20, 'fff'), (70, 20, 'ggg'), (80, 30, 'hhh'); +SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr +FROM t2, t1 WHERE t2.sku=20 AND (t2.sku=t1.sku OR t2.sppr=t1.sku); +sku sppr name sku pr +20 10 bbb 10 10 +20 10 bbb 20 10 +EXPLAIN +SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr +FROM t2, t1 WHERE t2.sku=20 AND (t2.sku=t1.sku OR t2.sppr=t1.sku); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 6 Using where +DROP TABLE t1,t2; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index d8561915564..bd0fa5ae661 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -547,7 +547,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 Using index 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away Warnings: -Note 1003 select `test`.`t1`.`numreponse` AS `numreponse` from `test`.`t1` where ((`test`.`t1`.`numreponse` = (select max(`test`.`t1`.`numreponse`) AS `MAX(numreponse)` from `test`.`t1` where (`test`.`t1`.`numeropost` = _latin1'1'))) and (`test`.`t1`.`numeropost` = _latin1'1')) +Note 1003 select `test`.`t1`.`numreponse` AS `numreponse` from `test`.`t1` where ((`test`.`t1`.`numeropost` = _latin1'1')) drop table t1; CREATE TABLE t1 (a int(1)); INSERT INTO t1 VALUES (1); diff --git a/mysql-test/r/varbinary.result b/mysql-test/r/varbinary.result index e55e6b35915..e62051df5cd 100644 --- a/mysql-test/r/varbinary.result +++ b/mysql-test/r/varbinary.result @@ -15,7 +15,7 @@ explain extended select * from t1 where UNIQ=0x38afba1d73e6a18a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 const UNIQ UNIQ 8 const 1 Warnings: -Note 1003 select `test`.`t1`.`ID` AS `ID`,`test`.`t1`.`UNIQ` AS `UNIQ` from `test`.`t1` where (`test`.`t1`.`UNIQ` = 4084688022709641610) +Note 1003 select `test`.`t1`.`ID` AS `ID`,`test`.`t1`.`UNIQ` AS `UNIQ` from `test`.`t1` where 1 drop table t1; select x'hello'; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'x'hello'' at line 1 diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 01d5f2eb4d1..c4fe1906cbc 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2848,3 +2848,26 @@ drop table t1,t2; # --error 1064 select * from (select * left join t on f1=f2) tt; + +# +# Bug #16504: re-evaluation of Item_equal object after reading const table +# + +CREATE TABLE t1 (sku int PRIMARY KEY, pr int); +CREATE TABLE t2 (sku int PRIMARY KEY, sppr int, name varchar(255)); + +INSERT INTO t1 VALUES + (10, 10), (20, 10), (30, 20), (40, 30), (50, 10), (60, 10); + +INSERT INTO t2 VALUES + (10, 10, 'aaa'), (20, 10, 'bbb'), (30, 10, 'ccc'), (40, 20, 'ddd'), + (50, 10, 'eee'), (60, 20, 'fff'), (70, 20, 'ggg'), (80, 30, 'hhh'); + +SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr + FROM t2, t1 WHERE t2.sku=20 AND (t2.sku=t1.sku OR t2.sppr=t1.sku); +EXPLAIN +SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr + FROM t2, t1 WHERE t2.sku=20 AND (t2.sku=t1.sku OR t2.sppr=t1.sku); + + +DROP TABLE t1,t2; diff --git a/sql/item.cc b/sql/item.cc index 8ffe7a6b2fd..e14367c7de1 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3744,7 +3744,7 @@ Item *Item_field::replace_equal_field(byte *arg) if (item_equal) { Item_field *subst= item_equal->get_first(); - if (!field->eq(subst->field)) + if (subst && !field->eq(subst->field)) return subst; } return this; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 2d74ea9c518..53efb65e1cb 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -3602,7 +3602,8 @@ void Item_equal::add(Item *c) Item_func_eq *func= new Item_func_eq(c, const_item); func->set_cmp_func(); func->quick_fix_field(); - cond_false = !(func->val_int()); + if ((cond_false= !func->val_int())) + const_item_cache= 1; } void Item_equal::add(Item_field *f) @@ -3734,13 +3735,45 @@ void Item_equal::sort(Item_field_cmpfunc cmp, void *arg) } while (swap); } + +/* + Check appearance of new constant items in the multiple equality object + + SYNOPSIS + check() + + DESCRIPTION + The function checks appearance of new constant items among + the members of multiple equalities. Each new constant item is + compared with the designated constant item if there is any in the + multiple equality. If there is none the first new constant item + becomes designated. + + RETURN VALUES + none +*/ + +void Item_equal::check_const() +{ + List_iterator it(fields); + Item *item; + while ((item= it++)) + { + if (item->const_item()) + { + it.remove(); + add(item); + } + } +} + bool Item_equal::fix_fields(THD *thd, Item **ref) { List_iterator_fast li(fields); Item *item; not_null_tables_cache= used_tables_cache= 0; const_item_cache= 0; - while ((item=li++)) + while ((item= li++)) { table_map tmp_table_map; used_tables_cache|= item->used_tables(); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 89aafa5721e..3d94832412e 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1196,6 +1196,7 @@ public: bool contains(Field *field); Item_field* get_first() { return fields.head(); } void merge(Item_equal *item); + void check_const(); enum Functype functype() const { return MULT_EQUAL_FUNC; } longlong val_int(); const char *func_name() const { return "multiple equal"; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3fa77a73e41..13e0381349a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -136,7 +136,7 @@ static enum_nested_loop_state end_write_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records); static int test_if_group_changed(List &list); -static int join_read_const_table(JOIN_TAB *tab, POSITION *pos); +static int join_read_const_table(JOIN *join, JOIN_TAB *tab, POSITION *pos); static int join_read_system(JOIN_TAB *tab); static int join_read_const(JOIN_TAB *tab); static int join_read_key(JOIN_TAB *tab); @@ -2111,7 +2111,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, s= p_pos->table; s->type=JT_SYSTEM; join->const_table_map|=s->table->map; - if ((tmp=join_read_const_table(s, p_pos))) + if ((tmp=join_read_const_table(join, s, p_pos))) { if (tmp > 0) DBUG_RETURN(1); // Fatal error @@ -2148,7 +2148,8 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, s->type=JT_SYSTEM; join->const_table_map|=table->map; set_position(join,const_count++,s,(KEYUSE*) 0); - if ((tmp= join_read_const_table(s,join->positions+const_count-1))) + if ((tmp= join_read_const_table(join, s, + join->positions+const_count-1))) { if (tmp > 0) DBUG_RETURN(1); // Fatal error @@ -2200,7 +2201,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if (create_ref_for_key(join, s, start_keyuse, found_const_table_map)) DBUG_RETURN(1); - if ((tmp=join_read_const_table(s, + if ((tmp=join_read_const_table(join, s, join->positions+const_count-1))) { if (tmp > 0) @@ -6796,8 +6797,8 @@ static COND *build_equal_items_for_cond(COND *cond, return item_equal; } /* - For each field reference in cond, not from equalitym predicates, - set a pointer to the multiple equality if belongs to (if there is any) + For each field reference in cond, not from equal item predicates, + set a pointer to the multiple equality it belongs to (if there is any) */ cond= cond->transform(&Item::equal_fields_propagator, (byte *) inherited); @@ -6982,7 +6983,7 @@ static int compare_fields_by_table_order(Item_field *field1, NOTES Before generating an equality function checks that it has not - been generated for multiple equalies of the upper levels. + been generated for multiple equalities of the upper levels. E.g. for the following where condition WHERE a=5 AND ((a=b AND b=c) OR c>4) the upper level AND condition will contain =(5,a), @@ -7155,7 +7156,7 @@ static COND* substitute_for_best_equal_field(COND *cond, { cond= eliminate_item_equal(cond, cond_equal->upper_levels, item_equal); // This occurs when eliminate_item_equal() founds that cond is - // always false and substitues it with Item_int 0. + // always false and substitutes it with Item_int 0. // Due to this, value of item_equal will be 0, so just return it. if (cond->type() != Item::COND_ITEM) break; @@ -7177,6 +7178,45 @@ static COND* substitute_for_best_equal_field(COND *cond, } +/* + Check appearance of new constant items in multiple equalities + of a condition after reading a constant table + + SYNOPSIS + check_const_equal_item() + cond condition whose multiple equalities are to be checked + table constant table that has been read + + DESCRIPTION + The function retrieves the cond condition and for each encountered + multiple equality checks whether new constants have appeared after + reading the constant (single row) table tab. If so it adjusts + the multiple equality appropriately. +*/ + +static void check_const_equal_items(COND *cond, + JOIN_TAB *tab) +{ + if (!(cond->used_tables() & tab->table->map)) + return; + + if (cond->type() == Item::COND_ITEM) + { + List *cond_list= ((Item_cond*) cond)->argument_list(); + List_iterator_fast li(*cond_list); + Item *item; + while ((item= li++)) + check_const_equal_items(item, tab); + } + else if (cond->type() == Item::FUNC_ITEM && + ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC) + { + Item_equal *item_equal= (Item_equal *) cond; + item_equal->check_const(); + } +} + + /* change field = field to field = const for each found field = const in the and_level @@ -10099,7 +10139,7 @@ int safe_index_read(JOIN_TAB *tab) static int -join_read_const_table(JOIN_TAB *tab, POSITION *pos) +join_read_const_table(JOIN *join, JOIN_TAB *tab, POSITION *pos) { int error; DBUG_ENTER("join_read_const_table"); @@ -10151,6 +10191,26 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos) } if (!table->null_row) table->maybe_null=0; + + /* Check appearance of new constant items in Item_equal objects */ + if (join->conds) + check_const_equal_items(join->conds, tab); + TABLE_LIST *tbl; + for (tbl= join->select_lex->leaf_tables; tbl; tbl= tbl->next_leaf) + { + TABLE_LIST *embedded; + TABLE_LIST *embedding= tbl; + do + { + embedded= embedding; + if (embedded->on_expr) + check_const_equal_items(embedded->on_expr, tab); + embedding= embedded->embedding; + } + while (embedding && + embedding->nested_join->join_list.head() == embedded); + } + DBUG_RETURN(0); } -- cgit v1.2.1 From d95837b0f182c13ef985ea532127e952d9f02440 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 31 Mar 2006 23:12:05 -0800 Subject: Added a test case for bug #16504. Results changed after the bug fix. --- mysql-test/r/select.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 02f27423f99..9b9f67efeb5 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -3388,5 +3388,5 @@ SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr FROM t2, t1 WHERE t2.sku=20 AND (t2.sku=t1.sku OR t2.sppr=t1.sku); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 -1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 6 Using where +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using where DROP TABLE t1,t2; -- cgit v1.2.1