Skip to content

Commit 2445e6c

Browse files
author
Jorgen Loland
committed
Bug#54511: Assertion failed: cache != 0L in file
sql_select.cc::sub_select_cache on HAVING Code cleanup followup patch: * remove JOIN::having_value and JOIN::cond_value and use select_lex variables with same name instead to avoid duplication of information. * Add documentation about the relationship between st_select_lex::{where|having} and JOIN::{conds|having} * Add documentation about the relationship between st_select_lex::{having|cond}_value and JOIN::{conds|having}
1 parent 0fa1389 commit 2445e6c

File tree

3 files changed

+64
-26
lines changed

3 files changed

+64
-26
lines changed

sql/sql_lex.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,14 @@ class st_select_lex: public st_select_lex_node
639639
Item *where, *having; /* WHERE & HAVING clauses */
640640
Item *prep_where; /* saved WHERE clause for prepared statement processing */
641641
Item *prep_having;/* saved HAVING clause for prepared statement processing */
642-
/* Saved values of the WHERE and HAVING clauses*/
642+
/**
643+
Saved values of the WHERE and HAVING clauses. Allowed values are:
644+
- COND_UNDEF if the condition was not specified in the query or if it
645+
has not been optimized yet
646+
- COND_TRUE if the condition is always true
647+
- COND_FALSE if the condition is impossible
648+
- COND_OK otherwise
649+
*/
643650
Item::cond_result cond_value, having_value;
644651
/* point on lex in which it was created, used in view subquery detection */
645652
LEX *parent_lex;

sql/sql_select.cc

+33-18
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,7 @@ JOIN::optimize()
898898
thd->restore_active_arena(arena, &backup);
899899
}
900900

901-
conds= optimize_cond(this, conds, join_list, &cond_value);
901+
conds= optimize_cond(this, conds, join_list, &select_lex->cond_value);
902902
if (thd->is_error())
903903
{
904904
error= 1;
@@ -907,24 +907,20 @@ JOIN::optimize()
907907
}
908908

909909
{
910-
having= optimize_cond(this, having, join_list, &having_value);
910+
having= optimize_cond(this, having, join_list, &select_lex->having_value);
911911
if (thd->is_error())
912912
{
913913
error= 1;
914914
DBUG_PRINT("error",("Error from optimize_cond"));
915915
DBUG_RETURN(1);
916916
}
917-
if (select_lex->where)
918-
select_lex->cond_value= cond_value;
919-
if (select_lex->having)
920-
select_lex->having_value= having_value;
921-
922-
if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
917+
if (select_lex->cond_value == Item::COND_FALSE ||
918+
select_lex->having_value == Item::COND_FALSE ||
923919
(!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
924920
{ /* Impossible cond */
925-
DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
921+
DBUG_PRINT("info", (select_lex->having_value == Item::COND_FALSE ?
926922
"Impossible HAVING" : "Impossible WHERE"));
927-
zero_result_cause= having_value == Item::COND_FALSE ?
923+
zero_result_cause= select_lex->having_value == Item::COND_FALSE ?
928924
"Impossible HAVING" : "Impossible WHERE";
929925
tables= 0;
930926
error= 0;
@@ -1149,10 +1145,9 @@ JOIN::optimize()
11491145
if (having && const_table_map)
11501146
{
11511147
having->update_used_tables();
1152-
having= remove_eq_conds(thd, having, &having_value);
1153-
if (having_value == Item::COND_FALSE)
1148+
having= remove_eq_conds(thd, having, &select_lex->having_value);
1149+
if (select_lex->having_value == Item::COND_FALSE)
11541150
{
1155-
having= new Item_int((longlong) 0,1);
11561151
zero_result_cause= "Impossible HAVING noticed after reading const tables";
11571152
error= 0;
11581153
DBUG_RETURN(0);
@@ -1823,8 +1818,8 @@ JOIN::exec()
18231818
In this case JOIN::exec must check for JOIN::having_value, in the
18241819
same way it checks for JOIN::cond_value.
18251820
*/
1826-
if (cond_value != Item::COND_FALSE &&
1827-
having_value != Item::COND_FALSE &&
1821+
if (select_lex->cond_value != Item::COND_FALSE &&
1822+
select_lex->having_value != Item::COND_FALSE &&
18281823
(!conds || conds->val_int()) &&
18291824
(!having || having->val_int()))
18301825
{
@@ -9278,16 +9273,36 @@ static void restore_prev_nj_state(JOIN_TAB *last)
92789273
}
92799274

92809275

9276+
/**
9277+
Optimize conditions by
9278+
9279+
a) applying transitivity to build multiple equality predicates
9280+
(MEP): if x=y and y=z the MEP x=y=z is built.
9281+
b) apply constants where possible. If the value of x is known to be
9282+
42, x is replaced with a constant of value 42. By transitivity, this
9283+
also applies to MEPs, so the MEP in a) will become 42=x=y=z.
9284+
c) remove conditions that are impossible or always true
9285+
9286+
@param join pointer to the structure providing all context info
9287+
for the query
9288+
@param conds conditions to optimize
9289+
@param join_list list of join tables to which the condition
9290+
refers to
9291+
@param[out] cond_value Not changed if conds was empty
9292+
COND_TRUE if conds is always true
9293+
COND_FALSE if conds is impossible
9294+
COND_OK otherwise
9295+
9296+
@return optimized conditions
9297+
*/
92819298
static COND *
92829299
optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list,
92839300
Item::cond_result *cond_value)
92849301
{
92859302
THD *thd= join->thd;
92869303
DBUG_ENTER("optimize_cond");
92879304

9288-
if (!conds)
9289-
*cond_value= Item::COND_TRUE;
9290-
else
9305+
if (conds)
92919306
{
92929307
/*
92939308
Build all multiple equality predicates and eliminate equality

sql/sql_select.h

+23-7
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,6 @@ class JOIN :public Sql_alloc
349349
/** second copy of sumfuncs (for queries with 2 temporary tables */
350350
Item_sum **sum_funcs2, ***sum_funcs_end2;
351351
Procedure *procedure;
352-
Item *having;
353-
Item *tmp_having; ///< To store having when processed temporary table
354-
Item *having_history; ///< Store having for explain
355352
ulonglong select_options;
356353
select_result *result;
357354
TMP_TABLE_PARAM tmp_table_param;
@@ -418,7 +415,6 @@ class JOIN :public Sql_alloc
418415

419416
bool need_tmp, hidden_group_fields;
420417
DYNAMIC_ARRAY keyuse;
421-
Item::cond_result cond_value, having_value;
422418
List<Item> all_fields; ///< to store all fields that used in query
423419
///Above list changed to use temporary table
424420
List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
@@ -429,8 +425,28 @@ class JOIN :public Sql_alloc
429425
int error;
430426

431427
ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select
432-
COND *conds; // ---"---
433-
Item *conds_history; // store WHERE for explain
428+
/**
429+
JOIN::having is initially equal to select_lex->having, but may
430+
later be changed by optimizations performed by JOIN.
431+
The relationship between the JOIN::having condition and the
432+
associated variable select_lex->having_value is so that
433+
having_value can be:
434+
- COND_UNDEF if a having clause was not specified in the query or
435+
if it has not been optimized yet
436+
- COND_TRUE if the having clause is always true, in which case
437+
JOIN::having is set to NULL.
438+
- COND_FALSE if the having clause is impossible, in which case
439+
JOIN::having is set to NULL
440+
- COND_OK otherwise, meaning that the having clause needs to be
441+
further evaluated
442+
All of the above also applies to the conds/select_lex->cond_value
443+
pair.
444+
*/
445+
COND *conds; ///< The where clause item tree
446+
Item *having; ///< The having clause item tree
447+
Item *conds_history; ///< store WHERE for explain
448+
Item *having_history; ///< Store having for explain
449+
Item *tmp_having; ///< To store having when processed temporary table
434450
TABLE_LIST *tables_list; ///<hold 'tables' parameter of mysql_select
435451
List<TABLE_LIST> *join_list; ///< list of joined tables in reverse order
436452
COND_EQUAL *cond_equal;
@@ -573,7 +589,7 @@ class JOIN :public Sql_alloc
573589
bool send_row_on_empty_set()
574590
{
575591
return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
576-
!group_list && having_value != Item::COND_FALSE);
592+
!group_list && select_lex->having_value != Item::COND_FALSE);
577593
}
578594
bool change_result(select_result *result);
579595
bool is_top_level_join() const

0 commit comments

Comments
 (0)