diff options
-rw-r--r-- | mysql-test/r/sp.result | 19 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 27 | ||||
-rw-r--r-- | sql/sql_base.cc | 8 | ||||
-rw-r--r-- | sql/sql_class.cc | 1 | ||||
-rw-r--r-- | sql/sql_class.h | 7 | ||||
-rw-r--r-- | sql/sql_insert.cc | 4 | ||||
-rw-r--r-- | sql/sql_lex.cc | 1 | ||||
-rw-r--r-- | sql/sql_lex.h | 10 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 4 | ||||
-rw-r--r-- | sql/sql_select.cc | 8 |
10 files changed, 69 insertions, 20 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 2180a23b91a..1ce14d38166 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -7053,6 +7053,25 @@ init_connect SET @@GLOBAL.init_connect= @old_init_connect; DROP PROCEDURE p2; DROP PROCEDURE p5; +# +# Bug#11766594 59736: SELECT DISTINCT.. INCORRECT RESULT WITH DETERMINISTIC FUNCTION IN WHERE C +# +CREATE TABLE t1 (a INT, b INT, KEY(b)); +CREATE TABLE t2 (c INT, d INT, KEY(c)); +INSERT INTO t1 VALUES (1,1),(1,1),(1,2); +INSERT INTO t2 VALUES (1,1),(1,2); +CREATE FUNCTION f1() RETURNS INT DETERMINISTIC +BEGIN +DECLARE a int; +-- SQL statement inside +SELECT 1 INTO a; +RETURN a; +END $ +SELECT COUNT(DISTINCT d) FROM t1, t2 WHERE a = c AND b = f1(); +COUNT(DISTINCT d) +2 +DROP FUNCTION f1; +DROP TABLE t1, t2; # ------------------------------------------------------------------ # -- End of 5.1 tests # ------------------------------------------------------------------ diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 5cf050146dd..9207ea22290 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -8350,6 +8350,33 @@ SET @@GLOBAL.init_connect= @old_init_connect; DROP PROCEDURE p2; DROP PROCEDURE p5; +--echo # +--echo # Bug#11766594 59736: SELECT DISTINCT.. INCORRECT RESULT WITH DETERMINISTIC FUNCTION IN WHERE C +--echo # + +CREATE TABLE t1 (a INT, b INT, KEY(b)); +CREATE TABLE t2 (c INT, d INT, KEY(c)); +INSERT INTO t1 VALUES (1,1),(1,1),(1,2); +INSERT INTO t2 VALUES (1,1),(1,2); + +DELIMITER $; + +CREATE FUNCTION f1() RETURNS INT DETERMINISTIC +BEGIN + DECLARE a int; + -- SQL statement inside + SELECT 1 INTO a; + RETURN a; +END $ + +DELIMITER ;$ + +SELECT COUNT(DISTINCT d) FROM t1, t2 WHERE a = c AND b = f1(); + +DROP FUNCTION f1; +DROP TABLE t1, t2; + + --echo # ------------------------------------------------------------------ --echo # -- End of 5.1 tests --echo # ------------------------------------------------------------------ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 87d28402e01..ab1ba156905 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7576,7 +7576,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && sum_func_list) item->split_sum_func(thd, ref_pointer_array, *sum_func_list); - thd->used_tables|= item->used_tables(); + thd->lex->used_tables|= item->used_tables(); thd->lex->current_select->cur_pos_in_select_list++; } thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup; @@ -7923,7 +7923,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, views and natural joins this update is performed inside the loop below. */ if (table) - thd->used_tables|= table->map; + thd->lex->used_tables|= table->map; /* Initialize a generic field iterator for the current table reference. @@ -8008,7 +8008,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, field_table= nj_col->table_ref->table; if (field_table) { - thd->used_tables|= field_table->map; + thd->lex->used_tables|= field_table->map; field_table->covering_keys.intersect(field->part_of_key); field_table->merge_keys.merge(field->part_of_key); field_table->used_fields++; @@ -8016,7 +8016,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, } } else - thd->used_tables|= item->used_tables(); + thd->lex->used_tables|= item->used_tables(); thd->lex->current_select->cur_pos_in_select_list++; } /* diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b9df35fe8be..7fb1d2ade5f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -649,7 +649,6 @@ THD::THD() is_slave_error= thread_specific_used= FALSE; hash_clear(&handler_tables_hash); tmp_table=0; - used_tables=0; cuted_fields= sent_row_count= row_count= 0L; limit_found_rows= 0; row_count_func= -1; diff --git a/sql/sql_class.h b/sql/sql_class.h index bf197fee9c3..3c1b2c1330f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1734,13 +1734,6 @@ public: */ ha_rows examined_row_count; - /* - The set of those tables whose fields are referenced in all subqueries - of the query. - TODO: possibly this it is incorrect to have used tables in THD because - with more than one subquery, it is not clear what does the field mean. - */ - table_map used_tables; USER_CONN *user_connect; CHARSET_INFO *db_charset; /* diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index baf5af16e2b..e176e5c9b6d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -631,7 +631,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, lock_type= table_list->lock_type; thd_proc_info(thd, "init"); - thd->used_tables=0; + thd->lex->used_tables=0; values= its++; value_count= values->elements; @@ -779,7 +779,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, } else { - if (thd->used_tables) // Column used in values() + if (thd->lex->used_tables) // Column used in values() restore_record(table,s->default_values); // Get empty record else { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index f0289ab86ce..6e40f9b9614 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -360,6 +360,7 @@ void lex_start(THD *thd) lex->server_options.port= -1; lex->is_lex_started= TRUE; + lex->used_tables= 0; DBUG_VOID_RETURN; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index b4dbbc5162e..035fa1fde91 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1836,6 +1836,16 @@ typedef struct st_lex : public Query_tables_list uint create_select_pos; bool create_select_in_comment; + /* + The set of those tables whose fields are referenced in all subqueries + of the query. + TODO: possibly this it is incorrect to have used tables in LEX because + with subquery, it is not clear what does the field mean. To fix this + we should aggregate used tables information for selected expressions + into the select_lex. + */ + table_map used_tables; + st_lex(); virtual ~st_lex() diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index b296eb22cdb..ec7a7fb73b8 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1382,7 +1382,7 @@ static int mysql_test_select(Prepared_statement *stmt, if (open_normal_and_derived_tables(thd, tables, 0)) goto error; - thd->used_tables= 0; // Updated by setup_fields + thd->lex->used_tables= 0; // Updated by setup_fields /* JOIN::prepare calls @@ -1551,7 +1551,7 @@ static bool select_like_stmt_test(Prepared_statement *stmt, if (specific_prepare && (*specific_prepare)(thd)) DBUG_RETURN(TRUE); - thd->used_tables= 0; // Updated by setup_fields + thd->lex->used_tables= 0; // Updated by setup_fields /* Calls JOIN::prepare */ DBUG_RETURN(lex->unit.prepare(thd, 0, setup_tables_done_option)); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2346f744b47..516c9c37473 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -406,7 +406,7 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select, if (!ref->fixed && ref->fix_fields(thd, 0)) return TRUE; - thd->used_tables|= item->used_tables(); + thd->lex->used_tables|= item->used_tables(); } return false; } @@ -1632,7 +1632,7 @@ JOIN::optimize() if (exec_tmp_table1->distinct) { - table_map used_tables= thd->used_tables; + table_map used_tables= thd->lex->used_tables; JOIN_TAB *last_join_tab= join_tab+tables-1; do { @@ -2526,7 +2526,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, if (!(join= new JOIN(thd, fields, select_options, result))) DBUG_RETURN(TRUE); thd_proc_info(thd, "init"); - thd->used_tables=0; // Updated by setup_fields + thd->lex->used_tables=0; // Updated by setup_fields err= join->prepare(rref_pointer_array, tables, wild_num, conds, og_num, order, group, having, proc_param, select_lex, unit); @@ -16949,7 +16949,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, need_order=0; extra.append(STRING_WITH_LEN("; Using filesort")); } - if (distinct & test_all_bits(used_tables,thd->used_tables)) + if (distinct & test_all_bits(used_tables, thd->lex->used_tables)) extra.append(STRING_WITH_LEN("; Distinct")); for (uint part= 0; part < tab->ref.key_parts; part++) |