Commit 9cd03942 authored by Tor Didriksen's avatar Tor Didriksen

Merge fix for Bug#11765713 from 5.1

parents b655b931 dd3d9477
...@@ -5058,6 +5058,24 @@ i ...@@ -5058,6 +5058,24 @@ i
DROP TABLE t1,t1s,t2s; DROP TABLE t1,t1s,t2s;
End of 5.1 tests End of 5.1 tests
# #
# Bug #11765713 58705:
# OPTIMIZER LET ENGINE DEPEND ON UNINITIALIZED VALUES
# CREATED BY OPT_SUM_QUERY
#
CREATE TABLE t1(a INT NOT NULL, KEY (a));
INSERT INTO t1 VALUES (0), (1);
SELECT 1 as foo FROM t1 WHERE a < SOME
(SELECT a FROM t1 WHERE a <=>
(SELECT a FROM t1)
);
ERROR 21000: Subquery returns more than 1 row
SELECT 1 as foo FROM t1 WHERE a < SOME
(SELECT a FROM t1 WHERE a <=>
(SELECT a FROM t1 where a is null)
);
foo
DROP TABLE t1;
#
# Bug #57704: Cleanup code dies with void TABLE::set_keyread(bool): # Bug #57704: Cleanup code dies with void TABLE::set_keyread(bool):
# Assertion `file' failed. # Assertion `file' failed.
# #
......
...@@ -3996,6 +3996,28 @@ DROP TABLE t1,t1s,t2s; ...@@ -3996,6 +3996,28 @@ DROP TABLE t1,t1s,t2s;
--echo End of 5.1 tests --echo End of 5.1 tests
--echo #
--echo # Bug #11765713 58705:
--echo # OPTIMIZER LET ENGINE DEPEND ON UNINITIALIZED VALUES
--echo # CREATED BY OPT_SUM_QUERY
--echo #
CREATE TABLE t1(a INT NOT NULL, KEY (a));
INSERT INTO t1 VALUES (0), (1);
--error ER_SUBQUERY_NO_1_ROW
SELECT 1 as foo FROM t1 WHERE a < SOME
(SELECT a FROM t1 WHERE a <=>
(SELECT a FROM t1)
);
SELECT 1 as foo FROM t1 WHERE a < SOME
(SELECT a FROM t1 WHERE a <=>
(SELECT a FROM t1 where a is null)
);
DROP TABLE t1;
--echo # --echo #
--echo # Bug #57704: Cleanup code dies with void TABLE::set_keyread(bool): --echo # Bug #57704: Cleanup code dies with void TABLE::set_keyread(bool):
--echo # Assertion `file' failed. --echo # Assertion `file' failed.
......
...@@ -212,6 +212,7 @@ static int get_index_max_value(TABLE *table, TABLE_REF *ref, uint range_fl) ...@@ -212,6 +212,7 @@ static int get_index_max_value(TABLE *table, TABLE_REF *ref, uint range_fl)
/** /**
Substitutes constants for some COUNT(), MIN() and MAX() functions. Substitutes constants for some COUNT(), MIN() and MAX() functions.
@param thd thread handler
@param tables list of leaves of join table tree @param tables list of leaves of join table tree
@param all_fields All fields to be returned @param all_fields All fields to be returned
@param conds WHERE clause @param conds WHERE clause
...@@ -229,9 +230,12 @@ static int get_index_max_value(TABLE *table, TABLE_REF *ref, uint range_fl) ...@@ -229,9 +230,12 @@ static int get_index_max_value(TABLE *table, TABLE_REF *ref, uint range_fl)
HA_ERR_KEY_NOT_FOUND on impossible conditions HA_ERR_KEY_NOT_FOUND on impossible conditions
@retval @retval
HA_ERR_... if a deadlock or a lock wait timeout happens, for example HA_ERR_... if a deadlock or a lock wait timeout happens, for example
@retval
ER_... e.g. ER_SUBQUERY_NO_1_ROW
*/ */
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) int opt_sum_query(THD *thd,
TABLE_LIST *tables, List<Item> &all_fields, COND *conds)
{ {
List_iterator_fast<Item> it(all_fields); List_iterator_fast<Item> it(all_fields);
int const_result= 1; int const_result= 1;
...@@ -243,6 +247,8 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) ...@@ -243,6 +247,8 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
Item *item; Item *item;
int error; int error;
DBUG_ENTER("opt_sum_query");
if (conds) if (conds)
where_tables= conds->used_tables(); where_tables= conds->used_tables();
...@@ -270,7 +276,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) ...@@ -270,7 +276,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
WHERE t2.field IS NULL; WHERE t2.field IS NULL;
*/ */
if (tl->table->map & where_tables) if (tl->table->map & where_tables)
return 0; DBUG_RETURN(0);
} }
else else
used_tables|= tl->table->map; used_tables|= tl->table->map;
...@@ -297,7 +303,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) ...@@ -297,7 +303,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
if(error) if(error)
{ {
tl->table->file->print_error(error, MYF(ME_FATALERROR)); tl->table->file->print_error(error, MYF(ME_FATALERROR));
return error; DBUG_RETURN(error);
} }
count*= tl->table->file->stats.records; count*= tl->table->file->stats.records;
} }
...@@ -390,10 +396,10 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) ...@@ -390,10 +396,10 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
if (error) if (error)
{ {
if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE) if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
return HA_ERR_KEY_NOT_FOUND; // No rows matching WHERE DBUG_RETURN(HA_ERR_KEY_NOT_FOUND); // No rows matching WHERE
/* HA_ERR_LOCK_DEADLOCK or some other error */ /* HA_ERR_LOCK_DEADLOCK or some other error */
table->file->print_error(error, MYF(0)); table->file->print_error(error, MYF(0));
return(error); DBUG_RETURN(error);
} }
removed_tables|= table->map; removed_tables|= table->map;
} }
...@@ -442,6 +448,10 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) ...@@ -442,6 +448,10 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0; const_result= 0;
} }
} }
if (thd->is_error())
DBUG_RETURN(thd->stmt_da->sql_errno());
/* /*
If we have a where clause, we can only ignore searching in the If we have a where clause, we can only ignore searching in the
tables if MIN/MAX optimisation replaced all used tables tables if MIN/MAX optimisation replaced all used tables
...@@ -451,7 +461,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) ...@@ -451,7 +461,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
*/ */
if (removed_tables && used_tables != removed_tables) if (removed_tables && used_tables != removed_tables)
const_result= 0; // We didn't remove all tables const_result= 0; // We didn't remove all tables
return const_result; DBUG_RETURN(const_result);
} }
...@@ -737,6 +747,12 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, ...@@ -737,6 +747,12 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
if (is_null || (is_null_safe_eq && args[1]->is_null())) if (is_null || (is_null_safe_eq && args[1]->is_null()))
{ {
/*
If we have a non-nullable index, we cannot use it,
since set_null will be ignored, and we will compare uninitialized data.
*/
if (!part->field->real_maybe_null())
DBUG_RETURN(false);
part->field->set_null(); part->field->set_null();
*key_ptr= (uchar) 1; *key_ptr= (uchar) 1;
} }
...@@ -807,8 +823,9 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, ...@@ -807,8 +823,9 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
@param[out] prefix_len Length of prefix for the search range @param[out] prefix_len Length of prefix for the search range
@note @note
This function may set table->key_read to 1, which must be reset after This function may set field->table->key_read to true,
index is used! (This can only happen when function returns 1) which must be reset after index is used!
(This can only happen when function returns 1)
@retval @retval
0 Index can not be used to optimize MIN(field)/MAX(field) 0 Index can not be used to optimize MIN(field)/MAX(field)
...@@ -823,7 +840,9 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, ...@@ -823,7 +840,9 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
uint *range_fl, uint *prefix_len) uint *range_fl, uint *prefix_len)
{ {
if (!(field->flags & PART_KEY_FLAG)) if (!(field->flags & PART_KEY_FLAG))
return 0; // Not key field return false; // Not key field
DBUG_ENTER("find_key_for_maxmin");
TABLE *table= field->table; TABLE *table= field->table;
uint idx= 0; uint idx= 0;
...@@ -848,7 +867,7 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, ...@@ -848,7 +867,7 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
part++, jdx++, key_part_to_use= (key_part_to_use << 1) | 1) part++, jdx++, key_part_to_use= (key_part_to_use << 1) | 1)
{ {
if (!(table->file->index_flags(idx, jdx, 0) & HA_READ_ORDER)) if (!(table->file->index_flags(idx, jdx, 0) & HA_READ_ORDER))
return 0; DBUG_RETURN(false);
/* Check whether the index component is partial */ /* Check whether the index component is partial */
Field *part_field= table->field[part->fieldnr-1]; Field *part_field= table->field[part->fieldnr-1];
...@@ -897,12 +916,12 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, ...@@ -897,12 +916,12 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
*/ */
if (field->part_of_key.is_set(idx)) if (field->part_of_key.is_set(idx))
table->set_keyread(TRUE); table->set_keyread(TRUE);
return 1; DBUG_RETURN(true);
} }
} }
} }
} }
return 0; DBUG_RETURN(false);
} }
......
...@@ -991,7 +991,7 @@ JOIN::optimize() ...@@ -991,7 +991,7 @@ JOIN::optimize()
If all items were resolved by opt_sum_query, there is no need to If all items were resolved by opt_sum_query, there is no need to
open any tables. open any tables.
*/ */
if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds))) if ((res=opt_sum_query(thd, select_lex->leaf_tables, all_fields, conds)))
{ {
if (res == HA_ERR_KEY_NOT_FOUND) if (res == HA_ERR_KEY_NOT_FOUND)
{ {
......
...@@ -619,7 +619,8 @@ bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args); ...@@ -619,7 +619,8 @@ bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args);
/* functions from opt_sum.cc */ /* functions from opt_sum.cc */
bool simple_pred(Item_func *func_item, Item **args, bool *inv_order); bool simple_pred(Item_func *func_item, Item **args, bool *inv_order);
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds); int opt_sum_query(THD* thd,
TABLE_LIST *tables, List<Item> &all_fields, COND *conds);
/* from sql_delete.cc, used by opt_range.cc */ /* from sql_delete.cc, used by opt_range.cc */
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b); extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment