Skip to content

Commit 5b04acd

Browse files
author
Guilhem Bichot
committed
Bug #14230177 WITH CHECK OPTION NOT WORKING IF CLAUSE CONTAINS SUBQUERY
prevent semijoin on CHECK OPTION clause.
1 parent 15f19fb commit 5b04acd

4 files changed

Lines changed: 54 additions & 18 deletions

File tree

sql/item_cmpfunc.cc

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4742,15 +4742,13 @@ Item_cond::fix_fields(THD *thd, Item **ref)
47424742
DBUG_ASSERT(fixed == 0);
47434743
List_iterator<Item> li(list);
47444744
Item *item;
4745-
st_select_lex::Resolve_place save_resolve=
4746-
thd->lex->current_select->resolve_place;
4745+
Switch_resolve_place SRP(&thd->lex->current_select->resolve_place,
4746+
st_select_lex::RESOLVE_NONE,
4747+
functype() != COND_AND_FUNC);
47474748
uchar buff[sizeof(char*)]; // Max local vars in function
47484749
used_tables_cache= 0;
47494750
const_item_cache= true;
47504751

4751-
if (functype() != COND_AND_FUNC)
4752-
thd->lex->current_select->resolve_place= st_select_lex::RESOLVE_NONE;
4753-
47544752
if (functype() == COND_AND_FUNC && abort_on_null)
47554753
not_null_tables_cache= 0;
47564754
else
@@ -4805,7 +4803,6 @@ Item_cond::fix_fields(THD *thd, Item **ref)
48054803
maybe_null= true;
48064804
}
48074805
thd->lex->current_select->cond_count+= list.elements;
4808-
thd->lex->current_select->resolve_place= save_resolve;
48094806
fix_length_and_dec();
48104807
fixed= true;
48114808
return false;

sql/item_func.cc

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -174,12 +174,10 @@ Item_func::fix_fields(THD *thd, Item **ref)
174174
Item **arg,**arg_end;
175175
uchar buff[STACK_BUFF_ALLOC]; // Max argument in function
176176

177-
st_select_lex::Resolve_place save_resolve= st_select_lex::RESOLVE_NONE;
178-
if (thd->lex->current_select != NULL)
179-
{
180-
save_resolve= thd->lex->current_select->resolve_place;
181-
thd->lex->current_select->resolve_place= st_select_lex::RESOLVE_NONE;
182-
}
177+
Switch_resolve_place SRP(thd->lex->current_select ?
178+
&thd->lex->current_select->resolve_place : NULL,
179+
st_select_lex::RESOLVE_NONE,
180+
thd->lex->current_select);
183181
used_tables_cache= get_initial_pseudo_tables();
184182
not_null_tables_cache= 0;
185183
const_item_cache=1;
@@ -234,8 +232,6 @@ Item_func::fix_fields(THD *thd, Item **ref)
234232
if (thd->is_error()) // An error inside fix_length_and_dec occured
235233
return TRUE;
236234
fixed= 1;
237-
if (thd->lex->current_select != NULL)
238-
thd->lex->current_select->resolve_place= save_resolve;
239235
return FALSE;
240236
}
241237

sql/sql_lex.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,34 @@ inline bool st_select_lex_unit::is_union ()
10091009
first_select()->next_select()->linkage == UNION_TYPE;
10101010
}
10111011

1012+
/// Utility RAII class to save/modify/restore a Resolve_place
1013+
class Switch_resolve_place
1014+
{
1015+
public:
1016+
Switch_resolve_place(SELECT_LEX::Resolve_place *rp_ptr,
1017+
SELECT_LEX::Resolve_place new_rp,
1018+
bool apply)
1019+
{
1020+
if (apply)
1021+
{
1022+
rp= rp_ptr;
1023+
saved_rp= *rp;
1024+
*rp= new_rp;
1025+
}
1026+
else
1027+
rp= NULL;
1028+
}
1029+
~Switch_resolve_place()
1030+
{
1031+
if (rp)
1032+
*rp= saved_rp;
1033+
}
1034+
private:
1035+
SELECT_LEX::Resolve_place *rp;
1036+
SELECT_LEX::Resolve_place saved_rp;
1037+
};
1038+
1039+
10121040
typedef struct struct_slave_connection
10131041
{
10141042
char *user;

sql/table.cc

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3712,16 +3712,31 @@ bool TABLE_LIST::prep_where(THD *thd, Item **conds,
37123712
}
37133713
}
37143714

3715-
if (where)
3715+
if (where && !where_processed)
37163716
{
3717-
if (!where->fixed && !where_processed && where->fix_fields(thd, &where))
3718-
DBUG_RETURN(TRUE);
3717+
3718+
if (!where->fixed)
3719+
{
3720+
/*
3721+
This WHERE will be included in check_option. If it contains a
3722+
subquery, fix_fields() may convert it to semijoin, making it
3723+
impossible to call val_int() on the Item[...]_subselect, preventing
3724+
evaluation of check_option when we insert/update/delete a row.
3725+
So we must forbid semijoin transformation in fix_fields():
3726+
*/
3727+
Switch_resolve_place SRP(&thd->lex->current_select->resolve_place,
3728+
st_select_lex::RESOLVE_NONE,
3729+
effective_with_check != VIEW_CHECK_NONE);
3730+
3731+
if (where->fix_fields(thd, &where))
3732+
DBUG_RETURN(TRUE);
3733+
}
37193734

37203735
/*
37213736
check that it is not VIEW in which we insert with INSERT SELECT
37223737
(in this case we can't add view WHERE condition to main SELECT_LEX)
37233738
*/
3724-
if (!no_where_clause && !where_processed)
3739+
if (!no_where_clause)
37253740
{
37263741
TABLE_LIST *tbl= this;
37273742
Query_arena *arena= thd->stmt_arena, backup;

0 commit comments

Comments
 (0)