From 694103472b92b91e5d3f35b565f9d64b290fa8e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Aug 2004 17:31:23 +0300 Subject: [PATCH 01/12] in case of compound index fill all parts in optimized IN (BUG#4435) mysql-test/r/subselect.result: Optimized IN with compound index test mysql-test/t/subselect.test: Optimized IN with compound index test sql/item_subselect.cc: in case of compound index fill all parts --- mysql-test/r/subselect.result | 21 ++++++ mysql-test/t/subselect.test | 16 +++++ sql/item_subselect.cc | 127 +++++++++++++++++----------------- 3 files changed, 102 insertions(+), 62 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 77339473142..ffcff534219 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1899,3 +1899,24 @@ select t000.a, count(*) `C` FROM t1 t000 GROUP BY t000.a HAVING count(*) > ALL ( a C 1 1 drop table t1,t2; +CREATE TABLE `t1` ( `aid` int(11) NOT NULL default '0', `bid` int(11) NOT NULL default '0', PRIMARY KEY (`aid`,`bid`)); +CREATE TABLE `t2` ( `aid` int(11) NOT NULL default '0', `bid` int(11) NOT NULL default '0', PRIMARY KEY (`aid`,`bid`)); +insert into t1 values (1,1),(1,2),(2,1),(2,2); +insert into t2 values (1,2),(2,2); +select * from t1 where t1.aid not in (select aid from t2 where bid=t1.bid); +aid bid +1 1 +2 1 +alter table t2 drop primary key; +alter table t2 add key KEY1 (aid, bid); +select * from t1 where t1.aid not in (select aid from t2 where bid=t1.bid); +aid bid +1 1 +2 1 +alter table t2 drop key KEY1; +alter table t2 add primary key (bid, aid); +select * from t1 where t1.aid not in (select aid from t2 where bid=t1.bid); +aid bid +1 1 +2 1 +drop table t1,t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index eb4b1f33b14..55ec001ba26 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1222,3 +1222,19 @@ CREATE TABLE `t2` ( `b` int(11) default NULL, `a` int(11) default NULL) ENGINE=M insert into t2 values (1,2); select t000.a, count(*) `C` FROM t1 t000 GROUP BY t000.a HAVING count(*) > ALL (SELECT count(*) FROM t2 t001 WHERE t001.a=1); drop table t1,t2; + +# +# Optimized IN with compound index +# +CREATE TABLE `t1` ( `aid` int(11) NOT NULL default '0', `bid` int(11) NOT NULL default '0', PRIMARY KEY (`aid`,`bid`)); +CREATE TABLE `t2` ( `aid` int(11) NOT NULL default '0', `bid` int(11) NOT NULL default '0', PRIMARY KEY (`aid`,`bid`)); +insert into t1 values (1,1),(1,2),(2,1),(2,2); +insert into t2 values (1,2),(2,2); +select * from t1 where t1.aid not in (select aid from t2 where bid=t1.bid); +alter table t2 drop primary key; +alter table t2 add key KEY1 (aid, bid); +select * from t1 where t1.aid not in (select aid from t2 where bid=t1.bid); +alter table t2 drop key KEY1; +alter table t2 add primary key (bid, aid); +select * from t1 where t1.aid not in (select aid from t2 where bid=t1.bid); +drop table t1,t2; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 8c4dae92ddc..36f5c891186 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1243,29 +1243,31 @@ int subselect_uniquesubquery_engine::exec() DBUG_ENTER("subselect_uniquesubquery_engine::exec"); int error; TABLE *table= tab->table; - if ((tab->ref.key_err= (*tab->ref.key_copy)->copy())) + for (store_key **copy=tab->ref.key_copy ; *copy ; copy++) { - table->status= STATUS_NOT_FOUND; - error= -1; - } - else - { - if (!table->file->inited) - table->file->ha_index_init(tab->ref.key); - error= table->file->index_read(table->record[0], - tab->ref.key_buff, - tab->ref.key_length,HA_READ_KEY_EXACT); - if (error && error != HA_ERR_KEY_NOT_FOUND) - error= report_error(table, error); - else + if (tab->ref.key_err= (*copy)->copy()) { - error= 0; - table->null_row= 0; - ((Item_in_subselect *) item)->value= (!table->status && - (!cond || cond->val_int()) ? 1 : - 0); + table->status= STATUS_NOT_FOUND; + DBUG_RETURN(1); } } + + if (!table->file->inited) + table->file->ha_index_init(tab->ref.key); + error= table->file->index_read(table->record[0], + tab->ref.key_buff, + tab->ref.key_length,HA_READ_KEY_EXACT); + if (error && error != HA_ERR_KEY_NOT_FOUND) + error= report_error(table, error); + else + { + error= 0; + table->null_row= 0; + ((Item_in_subselect *) item)->value= (!table->status && + (!cond || cond->val_int()) ? 1 : + 0); + } + DBUG_RETURN(error != 0); } @@ -1293,55 +1295,56 @@ int subselect_indexsubquery_engine::exec() ((Item_in_subselect *) item)->was_null= 0; } - if ((*tab->ref.key_copy) && (tab->ref.key_err= (*tab->ref.key_copy)->copy())) + for (store_key **copy=tab->ref.key_copy ; *copy ; copy++) { - table->status= STATUS_NOT_FOUND; - error= -1; + if (tab->ref.key_err= (*copy)->copy()) + { + table->status= STATUS_NOT_FOUND; + DBUG_RETURN(1); + } } + + if (!table->file->inited) + table->file->ha_index_init(tab->ref.key); + error= table->file->index_read(table->record[0], + tab->ref.key_buff, + tab->ref.key_length,HA_READ_KEY_EXACT); + if (error && error != HA_ERR_KEY_NOT_FOUND) + error= report_error(table, error); else { - if (!table->file->inited) - table->file->ha_index_init(tab->ref.key); - error= table->file->index_read(table->record[0], - tab->ref.key_buff, - tab->ref.key_length,HA_READ_KEY_EXACT); - if (error && error != HA_ERR_KEY_NOT_FOUND) - error= report_error(table, error); - else + for (;;) { - for (;;) + error= 0; + table->null_row= 0; + if (!table->status) { - error= 0; - table->null_row= 0; - if (!table->status) - { - if (!cond || cond->val_int()) - { - if (null_finding) - ((Item_in_subselect *) item)->was_null= 1; - else - ((Item_in_subselect *) item)->value= 1; - break; - } - error= table->file->index_next_same(table->record[0], - tab->ref.key_buff, - tab->ref.key_length); - if (error && error != HA_ERR_END_OF_FILE) - { - error= report_error(table, error); - break; - } - } - else - { - if (!check_null || null_finding) - break; /* We don't need to check nulls */ - *tab->ref.null_ref_key= 1; - null_finding= 1; - /* Check if there exists a row with a null value in the index */ - if ((error= (safe_index_read(tab) == 1))) - break; - } + if (!cond || cond->val_int()) + { + if (null_finding) + ((Item_in_subselect *) item)->was_null= 1; + else + ((Item_in_subselect *) item)->value= 1; + break; + } + error= table->file->index_next_same(table->record[0], + tab->ref.key_buff, + tab->ref.key_length); + if (error && error != HA_ERR_END_OF_FILE) + { + error= report_error(table, error); + break; + } + } + else + { + if (!check_null || null_finding) + break; /* We don't need to check nulls */ + *tab->ref.null_ref_key= 1; + null_finding= 1; + /* Check if there exists a row with a null value in the index */ + if ((error= (safe_index_read(tab) == 1))) + break; } } } From d0c87702f70ff6c0116555fd40e92aef7bb79b46 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Aug 2004 10:01:30 +0300 Subject: [PATCH 02/12] skip resolving field in table list if table list is not accessable due to groupping (BUG#4814) mysql-test/r/func_gconcat.result: fix of test queries mysql-test/r/subselect.result: resolving fields of grouped outer SELECT mysql-test/t/func_gconcat.test: fix of test queries mysql-test/t/subselect.test: resolving fields of grouped outer SELECT sql/item.cc: skip resolving field in table list if table list is not accessable due to groupping layout fixed sql/item_subselect.cc: detection of place of subquery sql/item_subselect.h: detection of place of subquery sql/mysql_priv.h: enum_parsing_place made global type sql/sql_lex.cc: enum_parsing_place made global type sql/sql_lex.h: enum_parsing_place made global type sql/sql_yacc.yy: enum_parsing_place made global type --- mysql-test/r/func_gconcat.result | 24 +++++++---- mysql-test/r/subselect.result | 22 ++++++++++ mysql-test/t/func_gconcat.test | 6 +-- mysql-test/t/subselect.test | 11 +++++ sql/item.cc | 70 +++++++++++++++++++++----------- sql/item_subselect.cc | 4 +- sql/item_subselect.h | 2 + sql/mysql_priv.h | 7 ++++ sql/sql_lex.cc | 2 +- sql/sql_lex.h | 6 --- sql/sql_yacc.yy | 24 +++++------ 11 files changed, 122 insertions(+), 56 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 1ddbc18d965..180719c092a 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -285,15 +285,21 @@ insert into t2 values (1, 5), (2, 4), (3, 3), (3,3); select group_concat(c) from t1; group_concat(c) 2,3,4,5 -select group_concat(c order by (select c from t2 where t2.a=t1.a limit 1)) as grp from t1; -grp -5,4,3,2 -select group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a)) as grp from t1; -grp -5,4,3,2 -select group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a) desc) as grp from t1; -grp -2,4,3,5 +select t1.a, group_concat(c order by (select c from t2 where t2.a=t1.a limit 1)) as grp from t1 group by 1; +a grp +1 2 +2 4,3 +3 5 +select t1.a, group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a)) as grp from t1 group by 1; +a grp +1 2 +2 4,3 +3 5 +select t1.a, group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a) desc) as grp from t1 group by 1; +a grp +1 2 +2 4,3 +3 5 select a,c,(select group_concat(c order by a) from t2 where a=t1.a) as grp from t1 order by grp; a c grp 3 5 3,3 diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index ffcff534219..9ece7c5b6ce 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1920,3 +1920,25 @@ aid bid 1 1 2 1 drop table t1,t2; +CREATE TABLE t1 (howmanyvalues bigint, avalue int); +INSERT INTO t1 VALUES (1, 1),(2, 1),(2, 2),(3, 1),(3, 2),(3, 3),(4, 1),(4, 2),(4, 3),(4, 4); +SELECT howmanyvalues, count(*) from t1 group by howmanyvalues; +howmanyvalues count(*) +1 1 +2 2 +3 3 +4 4 +SELECT a.howmanyvalues, (SELECT count(*) from t1 b where b.howmanyvalues = a.howmanyvalues) as mycount from t1 a group by a.howmanyvalues; +howmanyvalues mycount +1 1 +2 2 +3 3 +4 4 +CREATE INDEX t1_howmanyvalues_idx ON t1 (howmanyvalues); +SELECT a.howmanyvalues, (SELECT count(*) from t1 b where b.howmanyvalues+1 = a.howmanyvalues+1) as mycount from t1 a group by a.howmanyvalues; +howmanyvalues mycount +1 1 +2 2 +3 3 +4 4 +drop table t1; diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index d27e5d7d77f..921ad4f5618 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -168,10 +168,10 @@ insert into t1 values (1, 2), (2, 3), (2, 4), (3, 5); create table t2 (a int, c int); insert into t2 values (1, 5), (2, 4), (3, 3), (3,3); select group_concat(c) from t1; -select group_concat(c order by (select c from t2 where t2.a=t1.a limit 1)) as grp from t1; +select t1.a, group_concat(c order by (select c from t2 where t2.a=t1.a limit 1)) as grp from t1 group by 1; -select group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a)) as grp from t1; -select group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a) desc) as grp from t1; +select t1.a, group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a)) as grp from t1 group by 1; +select t1.a, group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a) desc) as grp from t1 group by 1; # The following returns random results as we are sorting on blob addresses # select group_concat(c order by (select group_concat(c order by a) from t2 where t2.a=t1.a)) as grp from t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 55ec001ba26..5bff28dca77 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1238,3 +1238,14 @@ alter table t2 drop key KEY1; alter table t2 add primary key (bid, aid); select * from t1 where t1.aid not in (select aid from t2 where bid=t1.bid); drop table t1,t2; + +# +# resolving fields of grouped outer SELECT +# +CREATE TABLE t1 (howmanyvalues bigint, avalue int); +INSERT INTO t1 VALUES (1, 1),(2, 1),(2, 2),(3, 1),(3, 2),(3, 3),(4, 1),(4, 2),(4, 3),(4, 4); +SELECT howmanyvalues, count(*) from t1 group by howmanyvalues; +SELECT a.howmanyvalues, (SELECT count(*) from t1 b where b.howmanyvalues = a.howmanyvalues) as mycount from t1 a group by a.howmanyvalues; +CREATE INDEX t1_howmanyvalues_idx ON t1 (howmanyvalues); +SELECT a.howmanyvalues, (SELECT count(*) from t1 b where b.howmanyvalues+1 = a.howmanyvalues+1) as mycount from t1 a group by a.howmanyvalues; +drop table t1; diff --git a/sql/item.cc b/sql/item.cc index 658f5c42a43..09d5ee0a6ed 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -60,10 +60,10 @@ Item::Item(): */ if (thd->lex->current_select) { - SELECT_LEX_NODE::enum_parsing_place place= + enum_parsing_place place= thd->lex->current_select->parsing_place; - if (place == SELECT_LEX_NODE::SELECT_LIST || - place == SELECT_LEX_NODE::IN_HAVING) + if (place == SELECT_LIST || + place == IN_HAVING) thd->lex->current_select->select_n_having_items++; } } @@ -1228,21 +1228,34 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) table_list= (last= sl)->get_table_list(); if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) { - // it is primary INSERT st_select_lex => skip first table resolving + /* + it is primary INSERT st_select_lex => skip first table + resolving + */ table_list= table_list->next; } Item_subselect *prev_subselect_item= prev_unit->item; - if ((tmp= find_field_in_tables(thd, this, - table_list, &where, - 0)) != not_found_field) - { - if (!tmp) - return -1; - prev_subselect_item->used_tables_cache|= tmp->table->map; - prev_subselect_item->const_item_cache= 0; - break; - } + enum_parsing_place place= + prev_subselect_item->parsing_place; + /* + check table fields only if subquery used somewhere out of HAVING + or SELECT list or outer SELECT do not use groupping (i.e. tables + are accessable) + */ + if (((place != IN_HAVING && + place != SELECT_LIST) || + (sl->with_sum_func == 0 && sl->group_list.elements == 0)) && + (tmp= find_field_in_tables(thd, this, + table_list, &where, + 0)) != not_found_field) + { + if (!tmp) + return -1; + prev_subselect_item->used_tables_cache|= tmp->table->map; + prev_subselect_item->const_item_cache= 0; + break; + } if (sl->resolve_mode == SELECT_LEX::SELECT_MODE && (refer= find_item_in_list(this, sl->item_list, &counter, REPORT_EXCEPT_NOT_FOUND)) != @@ -1901,16 +1914,25 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) // it is primary INSERT st_select_lex => skip first table resolving table_list= table_list->next; } - if ((tmp= find_field_in_tables(thd, this, - table_list, &where, - 0)) != not_found_field) - { - prev_subselect_item->used_tables_cache|= tmp->table->map; - prev_subselect_item->const_item_cache= 0; - break; - } - - // Reference is not found => depend from outer (or just error) + enum_parsing_place place= + prev_subselect_item->parsing_place; + /* + check table fields only if subquery used somewhere out of HAVING + or SELECT list or outer SELECT do not use groupping (i.e. tables + are accessable) + */ + if (((place != IN_HAVING && + place != SELECT_LIST) || + (sl->with_sum_func == 0 && sl->group_list.elements == 0)) && + (tmp= find_field_in_tables(thd, this, + table_list, &where, + 0)) != not_found_field) + { + prev_subselect_item->used_tables_cache|= tmp->table->map; + prev_subselect_item->const_item_cache= 0; + break; + } + // Reference is not found => depend from outer (or just error) prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; prev_subselect_item->const_item_cache= 0; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 36f5c891186..750fd4aa4af 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -63,12 +63,14 @@ void Item_subselect::init(st_select_lex *select_lex, => we do not copy old_engine here */ engine= unit->item->engine; + parsing_place= unit->item->parsing_place; unit->item->engine= 0; unit->item= this; engine->change_item(this, result); } else { + parsing_place= unit->outer_select()->parsing_place; if (select_lex->next_select()) engine= new subselect_union_engine(unit, result, this); else @@ -76,7 +78,7 @@ void Item_subselect::init(st_select_lex *select_lex, } { SELECT_LEX *upper= unit->outer_select(); - if (upper->parsing_place == SELECT_LEX_NODE::IN_HAVING) + if (upper->parsing_place == IN_HAVING) upper->subquery_in_having= 1; } DBUG_VOID_RETURN; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 6b8b8b0b3a7..5668b91263f 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -50,6 +50,8 @@ protected: table_map used_tables_cache; /* allowed number of columns (1 for single value subqueries) */ uint max_columns; + /* where subquery is placed */ + enum_parsing_place parsing_place; /* work with 'substitution' */ bool have_to_be_excluded; /* cache of constant state */ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b3b79c16787..2f785e3f502 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -293,6 +293,13 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); */ #define MAX_DATE_REP_LENGTH 30 +enum enum_parsing_place +{ + NO_MATTER, + IN_HAVING, + SELECT_LIST +}; + struct st_table; class THD; class Statement; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 2b6a307092c..f39cbc43b8b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1017,7 +1017,7 @@ void st_select_lex::init_query() select_n_having_items= 0; prep_where= 0; subquery_in_having= explicit_limit= 0; - parsing_place= SELECT_LEX_NODE::NO_MATTER; + parsing_place= NO_MATTER; } void st_select_lex::init_select() diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 053c85166f6..da2c3fba097 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -220,12 +220,6 @@ protected: *master, *slave, /* vertical links */ *link_next, **link_prev; /* list of whole SELECT_LEX */ public: - enum enum_parsing_place - { - NO_MATTER, - IN_HAVING, - SELECT_LIST - }; ulong options; /* diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 8e3fb0884a9..de560041ba7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1113,11 +1113,11 @@ create_select: lex->sql_command= SQLCOM_REPLACE_SELECT; lex->current_select->table_list.save_and_clear(&lex->save_list); mysql_init_select(lex); - lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST; + lex->current_select->parsing_place= SELECT_LIST; } select_options select_item_list { - Select->parsing_place= SELECT_LEX_NODE::NO_MATTER; + Select->parsing_place= NO_MATTER; } opt_select_from { Lex->current_select->table_list.push_front(&Lex->save_list); } @@ -2370,11 +2370,11 @@ select_part2: lex->lock_option= TL_READ; if (sel->linkage != UNION_TYPE) mysql_init_select(lex); - lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST; + lex->current_select->parsing_place= SELECT_LIST; } select_options select_item_list { - Select->parsing_place= SELECT_LEX_NODE::NO_MATTER; + Select->parsing_place= NO_MATTER; } select_into select_lock_type; @@ -3438,11 +3438,11 @@ select_derived: YYABORT; mysql_init_select(lex); lex->current_select->linkage= DERIVED_TABLE_TYPE; - lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST; + lex->current_select->parsing_place= SELECT_LIST; } select_options select_item_list { - Select->parsing_place= SELECT_LEX_NODE::NO_MATTER; + Select->parsing_place= NO_MATTER; } opt_select_from union_opt ; @@ -3572,13 +3572,13 @@ having_clause: /* empty */ | HAVING { - Select->parsing_place= SELECT_LEX_NODE::IN_HAVING; + Select->parsing_place= IN_HAVING; } expr { SELECT_LEX *sel= Select; sel->having= $3; - sel->parsing_place= SELECT_LEX_NODE::NO_MATTER; + sel->parsing_place= NO_MATTER; if ($3) $3->top_level_item(); } @@ -4813,7 +4813,7 @@ simple_ident: ident { SELECT_LEX *sel=Select; - $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || + $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(0,0, NullS,NullS,$1.str); @@ -4829,7 +4829,7 @@ simple_ident: ER(ER_TABLENAME_NOT_ALLOWED_HERE), MYF(0), $1.str, thd->where); } - $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || + $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(0,0,NullS,$1.str,$3.str); @@ -4845,7 +4845,7 @@ simple_ident: ER(ER_TABLENAME_NOT_ALLOWED_HERE), MYF(0), $2.str, thd->where); } - $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || + $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(0,0,NullS,$2.str,$4.str); @@ -4861,7 +4861,7 @@ simple_ident: ER(ER_TABLENAME_NOT_ALLOWED_HERE), MYF(0), $3.str, thd->where); } - $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING || + $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? (Item*) new Item_field((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str), From 38b8c98543e68b3185a491b3cb9fb9d48662ef14 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Aug 2004 13:43:55 +0200 Subject: [PATCH 03/12] unnecessary LINT_INIT removed --- myisammrg/myrg_open.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c index 2d6b6dcf167..4c6ffb98ad5 100644 --- a/myisammrg/myrg_open.c +++ b/myisammrg/myrg_open.c @@ -32,20 +32,16 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) { - int save_errno,errpos; - uint files,i,dir_length,length,key_parts; + int save_errno,errpos=0; + uint files=0,i,dir_length,length,key_parts; ulonglong file_offset; char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end; - MYRG_INFO *m_info; + MYRG_INFO *m_info=0; File fd; IO_CACHE file; - MI_INFO *isam; + MI_INFO *isam=0; DBUG_ENTER("myrg_open"); - LINT_INIT(m_info); - m_info=0; - isam=0; - errpos=files=0; bzero((char*) &file,sizeof(file)); if ((fd=my_open(fn_format(name_buff,name,"",MYRG_NAME_EXT,4), O_RDONLY | O_SHARE,MYF(0))) < 0) From d40349fbf9cb41ccb84aa83a1e7854e8c98d61e4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Aug 2004 13:55:40 +0200 Subject: [PATCH 04/12] bdb bugfix: LTLIBOBJS didn't take --disable-shared into account fix for bdb not ending up into libmysqld.a bdb/dist/configure.ac: bdb bugfix: LTLIBOBJS didn't take --disable-shared into account configure.in: build bdb with --disable-shared for libdb.a to go into libmysqld.a libmysqld/examples/Makefile.am: incorrect "bugfix" undone. bdb should be in libmysqld.a --- bdb/dist/configure.ac | 2 +- configure.in | 2 +- libmysqld/examples/Makefile.am | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bdb/dist/configure.ac b/bdb/dist/configure.ac index a61b8595322..98cf0f63b39 100644 --- a/bdb/dist/configure.ac +++ b/bdb/dist/configure.ac @@ -555,7 +555,7 @@ fi LIB@&t@OBJS=`echo "$LIB@&t@OBJS" | sed 's,\.[[^.]]* ,$U&,g;s,\.[[^.]]*$,$U&,'` LTLIBOBJS=`echo "$LIB@&t@OBJS" | - sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'` + sed "s,\.[[^.]]* ,$o ,g;s,\.[[^.]]*$,$o,"` AC_SUBST(LTLIBOBJS) # Initial output file list. diff --git a/configure.in b/configure.in index 664ffd2a4a1..bbd0f93bfcf 100644 --- a/configure.in +++ b/configure.in @@ -2823,7 +2823,7 @@ then AC_CONFIG_FILES(bdb/Makefile) echo "CONFIGURING FOR BERKELEY DB" - bdb_conf_flags= + bdb_conf_flags="--disable-shared" if test $with_debug = "yes" then bdb_conf_flags="$bdb_conf_flags --enable-debug --enable-diagnostic" diff --git a/libmysqld/examples/Makefile.am b/libmysqld/examples/Makefile.am index b3db54d305a..2712e0dff48 100644 --- a/libmysqld/examples/Makefile.am +++ b/libmysqld/examples/Makefile.am @@ -16,7 +16,7 @@ DEFS = -DEMBEDDED_LIBRARY INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include -I$(srcdir) \ -I$(top_srcdir) -I$(top_srcdir)/client $(openssl_includes) LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@ -LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysqld.a @innodb_system_libs@ @bdb_libs_with_path@ @LIBDL@ $(CXXLDFLAGS) +LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysqld.a @innodb_system_libs@ @LIBDL@ $(CXXLDFLAGS) mysqltest_LINK = $(CXXLINK) From 8522f83038f1021374a565e70ab842511d4dae97 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Aug 2004 15:12:38 +0000 Subject: [PATCH 05/12] reverted default setting of --ndbcluster if --ndb-connectstring is given --- mysql-test/mysql-test-run.sh | 4 ++-- sql/mysqld.cc | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 4c021cd9aa0..58d7af75284 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -1451,9 +1451,9 @@ then then echo "Starting ndbcluster" ./ndb/ndbcluster --port-base=$NDBCLUSTER_PORT --small --diskless --initial --data-dir=$MYSQL_TEST_DIR/var || exit 1 - USE_NDBCLUSTER="--ndb-connectstring=\"host=localhost:$NDBCLUSTER_PORT\"" + USE_NDBCLUSTER="$USE_NDBCLUSTER --ndb-connectstring=\"host=localhost:$NDBCLUSTER_PORT\"" else - USE_NDBCLUSTER="--ndb-connectstring=\"$USE_RUNNING_NDBCLUSTER\"" + USE_NDBCLUSTER="$USE_NDBCLUSTER --ndb-connectstring=\"$USE_RUNNING_NDBCLUSTER\"" echo "Using ndbcluster at $USE_NDBCLUSTER" fi fi diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3a1c66a52f3..8dfca2bb684 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6004,11 +6004,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), have_ndbcluster= SHOW_OPTION_DISABLED; #endif break; -#ifdef HAVE_NDBCLUSTER_DB - case OPT_NDB_CONNECTSTRING: - have_ndbcluster= SHOW_OPTION_YES; - break; -#endif case OPT_INNODB: #ifdef HAVE_INNOBASE_DB if (opt_innodb) From c3c483e0918aaba7925a86a53018fd4cb5e03a82 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Aug 2004 20:12:39 +0500 Subject: [PATCH 06/12] Bug#4594: column index make = failed for gbk, but like works Fix for HEAP+HASH prefix keys. --- mysql-test/r/ctype_utf8.result | 10 ++++++++++ mysql-test/t/ctype_utf8.test | 12 ++++++++++++ sql/key.cc | 15 +++++++++++---- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 6a0bd21c551..ef5ec012078 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -560,3 +560,13 @@ select * from t1 where str='str'; str str drop table t1; +create table t1 ( +str varchar(255) character set utf8 not null, +key str using hash (str(2)) +) engine=heap; +INSERT INTO t1 VALUES ('str'); +INSERT INTO t1 VALUES ('str2'); +select * from t1 where str='str'; +str +str +drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 17b89ba1050..83055d05830 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -417,3 +417,15 @@ INSERT INTO t1 VALUES ('str'); INSERT INTO t1 VALUES ('str2'); select * from t1 where str='str'; drop table t1; + +# the same for HEAP+HASH +# + +create table t1 ( + str varchar(255) character set utf8 not null, + key str using hash (str(2)) +) engine=heap; +INSERT INTO t1 VALUES ('str'); +INSERT INTO t1 VALUES ('str2'); +select * from t1 where str='str'; +drop table t1; diff --git a/sql/key.cc b/sql/key.cc index 9425a368669..b1f4c9533a9 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -211,10 +211,17 @@ bool key_cmp_if_same(TABLE *table,const byte *key,uint idx,uint key_length) if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+ FIELDFLAG_PACK))) { - if (my_strnncoll(key_part->field->charset(), - (const uchar*) key, length, - (const uchar*) table->record[0]+key_part->offset, - length)) + CHARSET_INFO *cs= key_part->field->charset(); + uint char_length= key_part->length / cs->mbmaxlen; + const byte *pos= table->record[0] + key_part->offset; + if (length > char_length) + { + char_length= my_charpos(cs, pos, pos + length, char_length); + set_if_smaller(char_length, length); + } + if (cs->coll->strnncollsp(cs, + (const uchar*) key, length, + (const uchar*) pos, char_length)) return 1; } else if (memcmp(key,table->record[0]+key_part->offset,length)) From 4f1230a5a9088d923a243ebef1d2e9dbb0d9698f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Aug 2004 20:12:40 +0500 Subject: [PATCH 07/12] show_check.test, show_check.result: Don't do this test for now: it fails on Mac OSX. mysql-test/r/show_check.result: Don't do this test for now: it fails on Mac OSX. mysql-test/t/show_check.test: Don't do this test for now: it fails on Mac OSX. --- mysql-test/r/show_check.result | 7 ------- mysql-test/t/show_check.test | 14 ++++++++------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 3bea4c4509d..b78748b7726 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -401,10 +401,3 @@ where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; delete from mysql.db where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; flush privileges; -set names latin1; -create database `ä`; -create table `ä`.`ä` (a int) engine=heap; -show table status from `ä` LIKE 'ä'; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -ä HEAP 9 Fixed 0 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL -drop database `ä`; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index ac0c9a43010..de391fbe288 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -307,9 +307,11 @@ where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; flush privileges; #Bug #4374 SHOW TABLE STATUS FROM ignores collation_connection -set names latin1; -create database `ä`; -create table `ä`.`ä` (a int) engine=heap; ---replace_column 7 # 8 # 9 # -show table status from `ä` LIKE 'ä'; -drop database `ä`; +# This test fails on MAC OSX, so it is temporary disabled. +# This needs WL#1324 to be done. +#set names latin1; +#create database `ä`; +#create table `ä`.`ä` (a int) engine=heap; +#--replace_column 7 # 8 # 9 # +#show table status from `ä` LIKE 'ä'; +#drop database `ä`; From a3e0b69bfb736367fa840465766dc266bcc361fb Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Aug 2004 17:24:03 +0200 Subject: [PATCH 08/12] Fix for bug#5171 --- mysql-test/r/ndb_blob.result | 50 ++++++++++++++++++++++++++++ mysql-test/t/ndb_blob.test | 26 +++++++++++++++ ndb/include/ndbapi/NdbBlob.hpp | 3 +- ndb/include/ndbapi/NdbDictionary.hpp | 4 +++ ndb/src/ndbapi/NdbBlob.cpp | 13 ++++---- ndb/src/ndbapi/NdbDictionary.cpp | 8 +++++ ndb/src/ndbapi/NdbDictionaryImpl.cpp | 24 ++++++++++++- ndb/src/ndbapi/NdbDictionaryImpl.hpp | 5 ++- 8 files changed, 122 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/ndb_blob.result b/mysql-test/r/ndb_blob.result index 89b53aea7d1..0e99c939ea7 100644 --- a/mysql-test/r/ndb_blob.result +++ b/mysql-test/r/ndb_blob.result @@ -1,4 +1,5 @@ drop table if exists t1; +drop database if exists test2; set autocommit=0; create table t1 ( a int not null primary key, @@ -220,6 +221,55 @@ a b c d 7 7xb7 777 7xdd7 8 8xb8 888 8xdd8 9 9xb9 999 9xdd9 +select * from t1 order by a; +a b c d +1 1xb1 111 1xdd1 +2 2xb2 222 2xdd2 +3 3xb3 333 3xdd3 +4 4xb4 444 4xdd4 +5 5xb5 555 5xdd5 +6 6xb6 666 6xdd6 +7 7xb7 777 7xdd7 +8 8xb8 888 8xdd8 +9 9xb9 999 9xdd9 +alter table t1 add x int; +select * from t1 order by a; +a b c d x +1 1xb1 111 1xdd1 NULL +2 2xb2 222 2xdd2 NULL +3 3xb3 333 3xdd3 NULL +4 4xb4 444 4xdd4 NULL +5 5xb5 555 5xdd5 NULL +6 6xb6 666 6xdd6 NULL +7 7xb7 777 7xdd7 NULL +8 8xb8 888 8xdd8 NULL +9 9xb9 999 9xdd9 NULL +alter table t1 drop x; +select * from t1 order by a; +a b c d +1 1xb1 111 1xdd1 +2 2xb2 222 2xdd2 +3 3xb3 333 3xdd3 +4 4xb4 444 4xdd4 +5 5xb5 555 5xdd5 +6 6xb6 666 6xdd6 +7 7xb7 777 7xdd7 +8 8xb8 888 8xdd8 +9 9xb9 999 9xdd9 +create database test2; +use test2; +CREATE TABLE t2 ( +a bigint unsigned NOT NULL PRIMARY KEY, +b int unsigned not null, +c int unsigned +) engine=ndbcluster; +insert into t2 values (1,1,1),(2,2,2); +select * from test.t1,t2 where test.t1.a = t2.a order by test.t1.a; +a b c d a b c +1 1xb1 111 1xdd1 1 1 1 +2 2xb2 222 2xdd2 2 2 2 +drop table t2; +use test; delete from t1 where c >= 100; commit; select count(*) from t1; diff --git a/mysql-test/t/ndb_blob.test b/mysql-test/t/ndb_blob.test index c1166a7a90c..d33168d9da6 100644 --- a/mysql-test/t/ndb_blob.test +++ b/mysql-test/t/ndb_blob.test @@ -2,6 +2,7 @@ --disable_warnings drop table if exists t1; +drop database if exists test2; --enable_warnings # @@ -203,6 +204,31 @@ where c >= 100; commit; select * from t1 where c >= 100 order by a; +# alter table + +select * from t1 order by a; +alter table t1 add x int; +select * from t1 order by a; +alter table t1 drop x; +select * from t1 order by a; + +# multi db + +create database test2; +use test2; + +CREATE TABLE t2 ( + a bigint unsigned NOT NULL PRIMARY KEY, + b int unsigned not null, + c int unsigned +) engine=ndbcluster; + +insert into t2 values (1,1,1),(2,2,2); +select * from test.t1,t2 where test.t1.a = t2.a order by test.t1.a; + +drop table t2; +use test; + # range scan delete delete from t1 where c >= 100; commit; diff --git a/ndb/include/ndbapi/NdbBlob.hpp b/ndb/include/ndbapi/NdbBlob.hpp index af4c049d4a7..dc47115d16f 100644 --- a/ndb/include/ndbapi/NdbBlob.hpp +++ b/ndb/include/ndbapi/NdbBlob.hpp @@ -234,14 +234,13 @@ private: // define blob table static void getBlobTableName(char* btname, const NdbTableImpl* t, const NdbColumnImpl* c); static void getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnImpl* c); - // table name - char theBlobTableName[BlobTableNameSize]; // ndb api stuff Ndb* theNdb; NdbConnection* theNdbCon; NdbOperation* theNdbOp; NdbTableImpl* theTable; NdbTableImpl* theAccessTable; + NdbTableImpl* theBlobTable; const NdbColumnImpl* theColumn; char theFillChar; // sizes diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp index a69ec355ce8..b5c3985c6cb 100644 --- a/ndb/include/ndbapi/NdbDictionary.hpp +++ b/ndb/include/ndbapi/NdbDictionary.hpp @@ -144,6 +144,8 @@ public: FragAllLarge = 4 ///< Eight fragments per node group. }; }; + + class Table; // forward declaration /** * @class Column @@ -365,6 +367,8 @@ public: void setIndexOnlyStorage(bool); bool getIndexOnlyStorage() const; + const Table * getBlobTable() const; + /** * @name ODBC Specific methods * @{ diff --git a/ndb/src/ndbapi/NdbBlob.cpp b/ndb/src/ndbapi/NdbBlob.cpp index 431be574bbf..65e1aeedda7 100644 --- a/ndb/src/ndbapi/NdbBlob.cpp +++ b/ndb/src/ndbapi/NdbBlob.cpp @@ -140,7 +140,6 @@ void NdbBlob::init() { theState = Idle; - theBlobTableName[0] = 0; theNdb = NULL; theNdbCon = NULL; theNdbOp = NULL; @@ -865,7 +864,7 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count) DBG("readParts part=" << part << " count=" << count); Uint32 n = 0; while (n < count) { - NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName); + NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable); if (tOp == NULL || tOp->readTuple() == -1 || setPartKeyValue(tOp, part + n) == -1 || @@ -887,7 +886,7 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count) DBG("insertParts part=" << part << " count=" << count); Uint32 n = 0; while (n < count) { - NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName); + NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable); if (tOp == NULL || tOp->insertTuple() == -1 || setPartKeyValue(tOp, part + n) == -1 || @@ -909,7 +908,7 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count) DBG("updateParts part=" << part << " count=" << count); Uint32 n = 0; while (n < count) { - NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName); + NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable); if (tOp == NULL || tOp->updateTuple() == -1 || setPartKeyValue(tOp, part + n) == -1 || @@ -931,7 +930,7 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count) DBG("deleteParts part=" << part << " count=" << count); Uint32 n = 0; while (n < count) { - NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTableName); + NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable); if (tOp == NULL || tOp->deleteTuple() == -1 || setPartKeyValue(tOp, part + n) == -1) { @@ -1029,12 +1028,11 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* // sanity check assert((NDB_BLOB_HEAD_SIZE << 2) == sizeof(Head)); assert(theColumn->m_attrSize * theColumn->m_arraySize == sizeof(Head) + theInlineSize); - getBlobTableName(theBlobTableName, theTable, theColumn); const NdbDictionary::Table* bt; const NdbDictionary::Column* bc; if (thePartSize > 0) { if (theStripeSize == 0 || - (bt = theNdb->theDictionary->getTable(theBlobTableName)) == NULL || + (bt = theColumn->getBlobTable()) == NULL || (bc = bt->getColumn("DATA")) == NULL || bc->getType() != partType || bc->getLength() != (int)thePartSize) { @@ -1042,6 +1040,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* return -1; } } + theBlobTable = & NdbTableImpl::getImpl(*bt); // buffers theKeyBuf.alloc(theTable->m_sizeOfKeysInWords << 2); theAccessKeyBuf.alloc(theAccessTable->m_sizeOfKeysInWords << 2); diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp index d5a16546071..4b30f41b51d 100644 --- a/ndb/src/ndbapi/NdbDictionary.cpp +++ b/ndb/src/ndbapi/NdbDictionary.cpp @@ -174,6 +174,14 @@ NdbDictionary::Column::getIndexOnlyStorage() const { return m_impl.m_indexOnly; } +const NdbDictionary::Table * +NdbDictionary::Column::getBlobTable() const { + NdbTableImpl * t = m_impl.m_blobTable; + if (t) + return t->m_facade; + return 0; +} + void NdbDictionary::Column::setAutoIncrement(bool val){ m_impl.m_autoIncrement = val; diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 45a9f300aab..cb5e3b3c821 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -79,6 +79,7 @@ NdbColumnImpl::operator=(const NdbColumnImpl& col) m_attrSize = col.m_attrSize; m_arraySize = col.m_arraySize; m_keyInfoPos = col.m_keyInfoPos; + m_blobTable = col.m_blobTable; // Do not copy m_facade !! return *this; @@ -104,6 +105,7 @@ NdbColumnImpl::init() m_arraySize = 1, m_autoIncrement = false; m_autoIncrementInitialValue = 1; + m_blobTable = NULL; } NdbColumnImpl::~NdbColumnImpl() @@ -1211,7 +1213,6 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, } if (col->getBlobType()) blobCount++; - NdbColumnImpl * null = 0; impl->m_columns.fill(attrDesc.AttributeId, null); if(impl->m_columns[attrDesc.AttributeId] != 0){ @@ -1266,7 +1267,28 @@ NdbDictionaryImpl::createBlobTables(NdbTableImpl &t) NdbBlob::getBlobTable(bt, &t, &c); if (createTable(bt) != 0) return -1; + // Save BLOB table handle + NdbTableImpl * cachedBlobTable = getTable(bt.m_externalName.c_str()); + c.m_blobTable = cachedBlobTable; } + + return 0; +} + +int +NdbDictionaryImpl::addBlobTables(NdbTableImpl &t) +{ + for (unsigned i = 0; i < t.m_columns.size(); i++) { + NdbColumnImpl & c = *t.m_columns[i]; + if (! c.getBlobType() || c.getPartSize() == 0) + continue; + char btname[NdbBlob::BlobTableNameSize]; + NdbBlob::getBlobTableName(btname, &t, &c); + // Save BLOB table handle + NdbTableImpl * cachedBlobTable = getTable(btname);; + c.m_blobTable = cachedBlobTable; + } + return 0; } diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp index 3bf7eef3a06..9a890f02575 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp @@ -71,6 +71,7 @@ public: bool m_autoIncrement; Uint64 m_autoIncrementInitialValue; BaseString m_defaultValue; + NdbTableImpl * m_blobTable; /** * Internal types and sizes, and aggregates @@ -362,6 +363,7 @@ public: int createTable(NdbTableImpl &t); int createBlobTables(NdbTableImpl &); + int addBlobTables(NdbTableImpl &); int alterTable(NdbTableImpl &t); int dropTable(const char * name); int dropTable(NdbTableImpl &); @@ -616,7 +618,6 @@ NdbDictionaryImpl::getTableImpl(const char * internalTableName) if (ret == 0){ ret = m_receiver.getTable(internalTableName, m_ndb.usingFullyQualifiedNames()); - m_globalHash->lock(); m_globalHash->put(internalTableName, ret); m_globalHash->unlock(); @@ -629,6 +630,8 @@ NdbDictionaryImpl::getTableImpl(const char * internalTableName) m_ndb.theFirstTupleId[ret->getTableId()] = ~0; m_ndb.theLastTupleId[ret->getTableId()] = ~0; + + addBlobTables(*ret); return ret; } From 21fa12734fa53d5cfea11cc9d5d306274790b7e8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Aug 2004 20:17:14 +0400 Subject: [PATCH 09/12] Fix for bug #5134: WHERE x = 'bar' AND x LIKE BINARY 'bar' returns wrong results(for 4.1 tree) mysql-test/r/binary.result: Fix for bug #5134: WHERE x = 'bar' AND x LIKE BINARY 'bar' returns wrong results mysql-test/t/binary.test: Fix for bug #5134: WHERE x = 'bar' AND x LIKE BINARY 'bar' returns wrong results sql/sql_select.cc: Fix for bug #5134: WHERE x = 'bar' AND x LIKE BINARY 'bar' returns wrong results --- mysql-test/r/binary.result | 18 ++++++++++++++++++ mysql-test/t/binary.test | 13 +++++++++++++ sql/sql_select.cc | 10 ++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/binary.result b/mysql-test/r/binary.result index a4ced14bb12..68b507d1089 100644 --- a/mysql-test/r/binary.result +++ b/mysql-test/r/binary.result @@ -116,3 +116,21 @@ select collation(a), collation(b), collation(binary 'ccc') from t1 limit 1; collation(a) collation(b) collation(binary 'ccc') latin1_bin binary latin1_bin drop table t1; +create table t1( firstname char(20), lastname char(20)); +insert into t1 values ("john","doe"),("John","Doe"); +select * from t1 where firstname='john' and firstname like binary 'john'; +firstname lastname +john doe +select * from t1 where firstname='john' and binary 'john' = firstname; +firstname lastname +john doe +select * from t1 where firstname='john' and firstname = binary 'john'; +firstname lastname +john doe +select * from t1 where firstname='John' and firstname like binary 'john'; +firstname lastname +john doe +select * from t1 where firstname='john' and firstname like binary 'John'; +firstname lastname +John Doe +drop table t1; diff --git a/mysql-test/t/binary.test b/mysql-test/t/binary.test index 9f63c2ed445..3e702fd5257 100644 --- a/mysql-test/t/binary.test +++ b/mysql-test/t/binary.test @@ -67,3 +67,16 @@ select * from t1 where lower(b)='bbb'; select charset(a), charset(b), charset(binary 'ccc') from t1 limit 1; select collation(a), collation(b), collation(binary 'ccc') from t1 limit 1; drop table t1; + +# +# Bug5134: WHERE x = 'bar' AND x LIKE BINARY 'bar' returns wrong results +# + +create table t1( firstname char(20), lastname char(20)); +insert into t1 values ("john","doe"),("John","Doe"); +select * from t1 where firstname='john' and firstname like binary 'john'; +select * from t1 where firstname='john' and binary 'john' = firstname; +select * from t1 where firstname='john' and firstname = binary 'john'; +select * from t1 where firstname='John' and firstname like binary 'john'; +select * from t1 where firstname='john' and firstname like binary 'John'; +drop table t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 70fec408753..ca17f246929 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4186,7 +4186,10 @@ change_cond_ref_to_const(I_List *save_list,Item *and_father, Item *right_item= func->arguments()[1]; Item_func::Functype functype= func->functype(); - if (right_item->eq(field,0) && left_item != value) + if (right_item->eq(field,0) && left_item != value && + (left_item->result_type() != STRING_RESULT || + value->result_type() != STRING_RESULT || + left_item->collation.collation == value->collation.collation)) { Item *tmp=value->new_item(); if (tmp) @@ -4204,7 +4207,10 @@ change_cond_ref_to_const(I_List *save_list,Item *and_father, func->set_cmp_func(); } } - else if (left_item->eq(field,0) && right_item != value) + else if (left_item->eq(field,0) && right_item != value && + (right_item->result_type() != STRING_RESULT || + value->result_type() != STRING_RESULT || + right_item->collation.collation == value->collation.collation)) { Item *tmp=value->new_item(); if (tmp) From 93a894ac865de4c63bafd03c10159dccf6d4cd73 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Aug 2004 20:58:56 +0200 Subject: [PATCH 10/12] - removed mysql-test/t/flush_block_commit-master.opt as it collided with the sleep value we use for the test suite run during the release builds BitKeeper/deleted/.del-flush_block_commit-master.opt~3bcd295d5bf68796: Delete: mysql-test/t/flush_block_commit-master.opt --- mysql-test/t/flush_block_commit-master.opt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 mysql-test/t/flush_block_commit-master.opt diff --git a/mysql-test/t/flush_block_commit-master.opt b/mysql-test/t/flush_block_commit-master.opt deleted file mode 100644 index a25aa115e06..00000000000 --- a/mysql-test/t/flush_block_commit-master.opt +++ /dev/null @@ -1 +0,0 @@ ---loose-innodb_lock_wait_timeout=5 From 8dd14b45e3261f46f3d028fe3c73dc75e056430b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Aug 2004 12:28:28 -0700 Subject: [PATCH 11/12] Changing version information. configure.in: Update for gamma status. --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 664ffd2a4a1..91e9b7db7a2 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 4.1.4-beta) +AM_INIT_AUTOMAKE(mysql, 4.1.4-gamma) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 From 13f7338a3f09195be66fd7868d474126c51b708d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Aug 2004 22:31:01 +0300 Subject: [PATCH 12/12] after review fixes: allowed parsing of table fields inside aggregate functions added new tests of fields resolving in grouping mysql-test/r/func_gconcat.result: allowed parsing of table fields inside aggregate functions mysql-test/r/subselect.result: added new tests of fields resolving in grouping mysql-test/t/func_gconcat.test: allowed parsing of table fields inside aggregate functions mysql-test/t/subselect.test: added new tests of fields resolving in grouping sql/item_subselect.cc: allowed parsing of table fields inside aggregate functions --- mysql-test/r/func_gconcat.result | 9 +++++++++ mysql-test/r/subselect.result | 8 ++++++++ mysql-test/t/func_gconcat.test | 4 +++- mysql-test/t/subselect.test | 3 +++ sql/item_subselect.cc | 9 ++++++++- 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 180719c092a..5c98bc5b612 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -285,6 +285,15 @@ insert into t2 values (1, 5), (2, 4), (3, 3), (3,3); select group_concat(c) from t1; group_concat(c) 2,3,4,5 +select group_concat(c order by (select c from t2 where t2.a=t1.a limit 1)) as grp from t1; +grp +5,4,3,2 +select group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a)) as grp from t1; +grp +5,4,3,2 +select group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a) desc) as grp from t1; +grp +2,4,3,5 select t1.a, group_concat(c order by (select c from t2 where t2.a=t1.a limit 1)) as grp from t1 group by 1; a grp 1 2 diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 7b9e6d0d1f2..bc91eabf2bf 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1954,4 +1954,12 @@ howmanyvalues mycount 2 2 3 3 4 4 +SELECT a.howmanyvalues, (SELECT count(*) from t1 b where b.howmanyvalues = a.howmanyvalues) as mycount from t1 a group by a.howmanyvalues; +howmanyvalues mycount +1 1 +2 2 +3 3 +4 4 +SELECT a.howmanyvalues, (SELECT count(*) from t1 b where b.howmanyvalues = a.avalue) as mycount from t1 a group by a.howmanyvalues; +ERROR 42S22: Unknown column 'a.avalue' in 'where clause' drop table t1; diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 6cb98f6da0d..3f671377c4e 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -168,8 +168,10 @@ insert into t1 values (1, 2), (2, 3), (2, 4), (3, 5); create table t2 (a int, c int); insert into t2 values (1, 5), (2, 4), (3, 3), (3,3); select group_concat(c) from t1; +select group_concat(c order by (select c from t2 where t2.a=t1.a limit 1)) as grp from t1; +select group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a)) as grp from t1; +select group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a) desc) as grp from t1; select t1.a, group_concat(c order by (select c from t2 where t2.a=t1.a limit 1)) as grp from t1 group by 1; - select t1.a, group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a)) as grp from t1 group by 1; select t1.a, group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a) desc) as grp from t1 group by 1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index d02e3d8c2d3..d7a13167978 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1259,4 +1259,7 @@ SELECT howmanyvalues, count(*) from t1 group by howmanyvalues; SELECT a.howmanyvalues, (SELECT count(*) from t1 b where b.howmanyvalues = a.howmanyvalues) as mycount from t1 a group by a.howmanyvalues; CREATE INDEX t1_howmanyvalues_idx ON t1 (howmanyvalues); SELECT a.howmanyvalues, (SELECT count(*) from t1 b where b.howmanyvalues+1 = a.howmanyvalues+1) as mycount from t1 a group by a.howmanyvalues; +SELECT a.howmanyvalues, (SELECT count(*) from t1 b where b.howmanyvalues = a.howmanyvalues) as mycount from t1 a group by a.howmanyvalues; +-- error 1054 +SELECT a.howmanyvalues, (SELECT count(*) from t1 b where b.howmanyvalues = a.avalue) as mycount from t1 a group by a.howmanyvalues; drop table t1; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 395c5589dec..8d140efac5f 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -70,7 +70,14 @@ void Item_subselect::init(st_select_lex *select_lex, } else { - parsing_place= unit->outer_select()->parsing_place; + SELECT_LEX *outer_select= unit->outer_select(); + /* + do not take into account expression inside aggregate functions because + they can access original table fields + */ + parsing_place= (outer_select->in_sum_expr ? + NO_MATTER : + outer_select->parsing_place); if (select_lex->next_select()) engine= new subselect_union_engine(unit, result, this); else