summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergey Glukhov <sergey.glukhov@oracle.com>2011-08-02 11:33:45 +0400
committerSergey Glukhov <sergey.glukhov@oracle.com>2011-08-02 11:33:45 +0400
commit3468b55a215d1c4b489dbb925f19176e12c9f242 (patch)
tree12ae3424978cad870dff4198962862e5c0573ab0 /sql
parent58cf757f0b28108884fd0c9f641ba31296dc6c45 (diff)
downloadmariadb-git-3468b55a215d1c4b489dbb925f19176e12c9f242.tar.gz
Bug#11766594 59736: SELECT DISTINCT.. INCORRECT RESULT WITH DETERMINISTIC FUNCTION IN WHERE C
There is an optimization of DISTINCT in JOIN::optimize() which depends on THD::used_tables value. Each SELECT statement inside SP resets used_tables value(see mysql_select()) and it leads to wrong result. The fix is to replace THD::used_tables with LEX::used_tables. mysql-test/r/sp.result: test case mysql-test/t/sp.test: test case sql/sql_base.cc: THD::used_tables is replaced with LEX::used_tables sql/sql_class.cc: THD::used_tables is replaced with LEX::used_tables sql/sql_class.h: THD::used_tables is replaced with LEX::used_tables sql/sql_insert.cc: THD::used_tables is replaced with LEX::used_tables sql/sql_lex.cc: THD::used_tables is replaced with LEX::used_tables sql/sql_lex.h: THD::used_tables is replaced with LEX::used_tables sql/sql_prepare.cc: THD::used_tables is replaced with LEX::used_tables sql/sql_select.cc: THD::used_tables is replaced with LEX::used_tables
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_base.cc8
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h7
-rw-r--r--sql/sql_insert.cc4
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_lex.h10
-rw-r--r--sql/sql_prepare.cc4
-rw-r--r--sql/sql_select.cc8
8 files changed, 23 insertions, 20 deletions
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++)