Skip to content

Commit c2c93fc

Browse files
committed
MDEV-14164: Unknown column error when adding aggregate to function in oracle style procedure FOR loop
Make differentiation between pullout for merge and pulout of outer field during exists2in transformation. In last case the field was outer and so we can safely start from name resolution context of the SELECT where it was pulled. Old behavior lead to inconsistence between list of tables and outer name resolution context (which skips one SELECT for merge purposes) which creates problem vor name resolution.
1 parent ca69588 commit c2c93fc

14 files changed

+153
-45
lines changed

mysql-test/r/subselect_exists2in.result

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,5 +934,42 @@ f2
934934
foo
935935
set optimizer_switch= @optimizer_switch_save;
936936
DROP TABLE t1;
937+
#
938+
# MDEV-14164: Unknown column error when adding aggregate to function
939+
# in oracle style procedure FOR loop
940+
#
941+
CREATE TABLE t1(id INT, val INT);
942+
CREATE PROCEDURE p1()
943+
BEGIN
944+
DECLARE cur1 CURSOR FOR SELECT * FROM (
945+
SELECT DISTINCT id FROM t1) a
946+
WHERE NOT EXISTS (SELECT * FROM ( SELECT id FROM t1) b
947+
WHERE a.id=b.id);
948+
OPEN cur1;
949+
CLOSE cur1;
950+
OPEN cur1;
951+
CLOSE cur1;
952+
END;
953+
//
954+
CALL p1();
955+
DROP PROCEDURE p1;
956+
DROP TABLE t1;
957+
CREATE TABLE t1(id INT, val INT);
958+
CREATE PROCEDURE p1()
959+
BEGIN
960+
SELECT * FROM (SELECT DISTINCT id FROM t1) a
961+
WHERE NOT a.id IN (SELECT b.id FROM t1 b);
962+
SELECT * FROM (SELECT DISTINCT id FROM t1) a
963+
WHERE NOT EXISTS (SELECT * FROM t1 b WHERE a.id=b.id);
964+
END;
965+
//
966+
CALL p1();
967+
id
968+
id
969+
CALL p1();
970+
id
971+
id
972+
DROP PROCEDURE p1;
973+
DROP TABLE t1;
937974
# End of 10.0 tests
938975
set optimizer_switch=default;

mysql-test/t/subselect_exists2in.test

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,46 @@ set optimizer_switch= @optimizer_switch_save;
786786

787787
DROP TABLE t1;
788788

789+
--echo #
790+
--echo # MDEV-14164: Unknown column error when adding aggregate to function
791+
--echo # in oracle style procedure FOR loop
792+
--echo #
793+
794+
CREATE TABLE t1(id INT, val INT);
795+
DELIMITER //;
796+
CREATE PROCEDURE p1()
797+
BEGIN
798+
DECLARE cur1 CURSOR FOR SELECT * FROM (
799+
SELECT DISTINCT id FROM t1) a
800+
WHERE NOT EXISTS (SELECT * FROM ( SELECT id FROM t1) b
801+
WHERE a.id=b.id);
802+
OPEN cur1;
803+
CLOSE cur1;
804+
OPEN cur1;
805+
CLOSE cur1;
806+
END;
807+
//
808+
DELIMITER ;//
809+
CALL p1();
810+
DROP PROCEDURE p1;
811+
DROP TABLE t1;
812+
813+
CREATE TABLE t1(id INT, val INT);
814+
DELIMITER //;
815+
CREATE PROCEDURE p1()
816+
BEGIN
817+
SELECT * FROM (SELECT DISTINCT id FROM t1) a
818+
WHERE NOT a.id IN (SELECT b.id FROM t1 b);
819+
SELECT * FROM (SELECT DISTINCT id FROM t1) a
820+
WHERE NOT EXISTS (SELECT * FROM t1 b WHERE a.id=b.id);
821+
END;
822+
//
823+
DELIMITER ;//
824+
CALL p1();
825+
CALL p1();
826+
DROP PROCEDURE p1;
827+
DROP TABLE t1;
828+
789829
--echo # End of 10.0 tests
790830

791831
#restore defaults

sql/item.cc

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2745,7 +2745,8 @@ table_map Item_field::all_used_tables() const
27452745
return (get_depended_from() ? OUTER_REF_TABLE_BIT : field->table->map);
27462746
}
27472747

2748-
void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref)
2748+
void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref,
2749+
bool merge)
27492750
{
27502751
if (new_parent == get_depended_from())
27512752
depended_from= NULL;
@@ -2789,6 +2790,19 @@ void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref)
27892790
if (!need_change)
27902791
return;
27912792

2793+
if (!merge)
2794+
{
2795+
/*
2796+
It is transformation without merge.
2797+
This field was "outer" for the inner SELECT where it was taken and
2798+
moved up.
2799+
"Outer" fields uses normal SELECT_LEX context of upper SELECTs for
2800+
name resolution, so we can switch everything to it safely.
2801+
*/
2802+
this->context= &new_parent->context;
2803+
return;
2804+
}
2805+
27922806
Name_resolution_context *ctx= new Name_resolution_context();
27932807
if (context->select_lex == new_parent)
27942808
{
@@ -8107,18 +8121,20 @@ bool Item_outer_ref::fix_fields(THD *thd, Item **reference)
81078121
}
81088122

81098123

8110-
void Item_outer_ref::fix_after_pullout(st_select_lex *new_parent, Item **ref)
8124+
void Item_outer_ref::fix_after_pullout(st_select_lex *new_parent,
8125+
Item **ref, bool merge)
81118126
{
81128127
if (get_depended_from() == new_parent)
81138128
{
81148129
*ref= outer_ref;
8115-
(*ref)->fix_after_pullout(new_parent, ref);
8130+
(*ref)->fix_after_pullout(new_parent, ref, merge);
81168131
}
81178132
}
81188133

8119-
void Item_ref::fix_after_pullout(st_select_lex *new_parent, Item **refptr)
8134+
void Item_ref::fix_after_pullout(st_select_lex *new_parent, Item **refptr,
8135+
bool merge)
81208136
{
8121-
(*ref)->fix_after_pullout(new_parent, ref);
8137+
(*ref)->fix_after_pullout(new_parent, ref, merge);
81228138
if (get_depended_from() == new_parent)
81238139
depended_from= NULL;
81248140
}

sql/item.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,9 @@ class Item {
706706
Fix after some tables has been pulled out. Basically re-calculate all
707707
attributes that are dependent on the tables.
708708
*/
709-
virtual void fix_after_pullout(st_select_lex *new_parent, Item **ref) {};
709+
virtual void fix_after_pullout(st_select_lex *new_parent, Item **ref,
710+
bool merge)
711+
{};
710712

711713
/*
712714
This method should be used in case where we are sure that we do not need
@@ -2256,7 +2258,7 @@ class Item_field :public Item_ident
22562258
bool send(Protocol *protocol, String *str_arg);
22572259
void reset_field(Field *f);
22582260
bool fix_fields(THD *, Item **);
2259-
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
2261+
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
22602262
void make_field(Send_field *tmp_field);
22612263
int save_in_field(Field *field,bool no_conversions);
22622264
void save_org_in_field(Field *field, fast_field_copier optimizer_data);
@@ -3410,7 +3412,7 @@ class Item_ref :public Item_ident
34103412
bool send(Protocol *prot, String *tmp);
34113413
void make_field(Send_field *field);
34123414
bool fix_fields(THD *, Item **);
3413-
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
3415+
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
34143416
int save_in_field(Field *field, bool no_conversions);
34153417
void save_org_in_field(Field *field, fast_field_copier optimizer_data);
34163418
fast_field_copier setup_fast_field_copier(Field *field)
@@ -3664,9 +3666,9 @@ class Item_cache_wrapper :public Item_result_field
36643666
Item *it= ((Item *) item)->real_item();
36653667
return orig_item->eq(it, binary_cmp);
36663668
}
3667-
void fix_after_pullout(st_select_lex *new_parent, Item **refptr)
3669+
void fix_after_pullout(st_select_lex *new_parent, Item **refptr, bool merge)
36683670
{
3669-
orig_item->fix_after_pullout(new_parent, &orig_item);
3671+
orig_item->fix_after_pullout(new_parent, &orig_item, merge);
36703672
}
36713673
int save_in_field(Field *to, bool no_conversions);
36723674
enum Item_result result_type () const { return orig_item->result_type(); }
@@ -3924,7 +3926,7 @@ class Item_outer_ref :public Item_direct_ref
39243926
outer_ref->save_org_in_field(result_field, NULL);
39253927
}
39263928
bool fix_fields(THD *, Item **);
3927-
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
3929+
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
39283930
table_map used_tables() const
39293931
{
39303932
return (*ref)->const_item() ? 0 : OUTER_REF_TABLE_BIT;

sql/item_cmpfunc.cc

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,10 +1442,11 @@ bool Item_in_optimizer::is_top_level_item()
14421442
}
14431443

14441444

1445-
void Item_in_optimizer::fix_after_pullout(st_select_lex *new_parent, Item **ref)
1445+
void Item_in_optimizer::fix_after_pullout(st_select_lex *new_parent,
1446+
Item **ref, bool merge)
14461447
{
14471448
/* This will re-calculate attributes of our Item_in_subselect: */
1448-
Item_bool_func::fix_after_pullout(new_parent, ref);
1449+
Item_bool_func::fix_after_pullout(new_parent, ref, merge);
14491450

14501451
/* Then, re-calculate not_null_tables_cache: */
14511452
eval_not_null_tables(NULL);
@@ -2288,10 +2289,11 @@ bool Item_func_between::count_sargable_conds(uchar *arg)
22882289
}
22892290

22902291

2291-
void Item_func_between::fix_after_pullout(st_select_lex *new_parent, Item **ref)
2292+
void Item_func_between::fix_after_pullout(st_select_lex *new_parent,
2293+
Item **ref, bool merge)
22922294
{
22932295
/* This will re-calculate attributes of the arguments */
2294-
Item_func_opt_neg::fix_after_pullout(new_parent, ref);
2296+
Item_func_opt_neg::fix_after_pullout(new_parent, ref, merge);
22952297
/* Then, re-calculate not_null_tables_cache according to our special rules */
22962298
eval_not_null_tables(NULL);
22972299
}
@@ -2681,10 +2683,11 @@ Item_func_if::eval_not_null_tables(uchar *opt_arg)
26812683
}
26822684

26832685

2684-
void Item_func_if::fix_after_pullout(st_select_lex *new_parent, Item **ref)
2686+
void Item_func_if::fix_after_pullout(st_select_lex *new_parent,
2687+
Item **ref, bool merge)
26852688
{
26862689
/* This will re-calculate attributes of the arguments */
2687-
Item_func::fix_after_pullout(new_parent, ref);
2690+
Item_func::fix_after_pullout(new_parent, ref, merge);
26882691
/* Then, re-calculate not_null_tables_cache according to our special rules */
26892692
eval_not_null_tables(NULL);
26902693
}
@@ -4010,10 +4013,11 @@ Item_func_in::eval_not_null_tables(uchar *opt_arg)
40104013
}
40114014

40124015

4013-
void Item_func_in::fix_after_pullout(st_select_lex *new_parent, Item **ref)
4016+
void Item_func_in::fix_after_pullout(st_select_lex *new_parent, Item **ref,
4017+
bool merge)
40144018
{
40154019
/* This will re-calculate attributes of the arguments */
4016-
Item_func_opt_neg::fix_after_pullout(new_parent, ref);
4020+
Item_func_opt_neg::fix_after_pullout(new_parent, ref, merge);
40174021
/* Then, re-calculate not_null_tables_cache according to our special rules */
40184022
eval_not_null_tables(NULL);
40194023
}
@@ -4497,7 +4501,8 @@ Item_cond::eval_not_null_tables(uchar *opt_arg)
44974501
}
44984502

44994503

4500-
void Item_cond::fix_after_pullout(st_select_lex *new_parent, Item **ref)
4504+
void Item_cond::fix_after_pullout(st_select_lex *new_parent, Item **ref,
4505+
bool merge)
45014506
{
45024507
List_iterator<Item> li(list);
45034508
Item *item;
@@ -4511,7 +4516,7 @@ void Item_cond::fix_after_pullout(st_select_lex *new_parent, Item **ref)
45114516
while ((item=li++))
45124517
{
45134518
table_map tmp_table_map;
4514-
item->fix_after_pullout(new_parent, li.ref());
4519+
item->fix_after_pullout(new_parent, li.ref(), merge);
45154520
item= *li.ref();
45164521
used_tables_cache|= item->used_tables();
45174522
const_item_cache&= item->const_item();

sql/item_cmpfunc.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ class Item_in_optimizer: public Item_bool_func
272272
virtual void get_cache_parameters(List<Item> &parameters);
273273
bool is_top_level_item();
274274
bool eval_not_null_tables(uchar *opt_arg);
275-
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
275+
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
276276
bool invisible_mode();
277277
void reset_cache() { cache= NULL; }
278278
};
@@ -689,7 +689,7 @@ class Item_func_between :public Item_func_opt_neg
689689
virtual void print(String *str, enum_query_type query_type);
690690
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
691691
bool eval_not_null_tables(uchar *opt_arg);
692-
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
692+
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
693693
bool count_sargable_conds(uchar *arg);
694694
};
695695

@@ -791,7 +791,7 @@ class Item_func_if :public Item_func_hybrid_field_type
791791
uint decimal_precision() const;
792792
const char *func_name() const { return "if"; }
793793
bool eval_not_null_tables(uchar *opt_arg);
794-
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
794+
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
795795
private:
796796
void cache_type_info(Item *source);
797797
};
@@ -1337,7 +1337,7 @@ class Item_func_in :public Item_func_opt_neg
13371337
bool nulls_in_row();
13381338
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
13391339
bool eval_not_null_tables(uchar *opt_arg);
1340-
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
1340+
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
13411341
};
13421342

13431343
class cmp_item_row :public cmp_item
@@ -1729,7 +1729,7 @@ class Item_cond :public Item_bool_func
17291729
list.concat(nlist);
17301730
}
17311731
bool fix_fields(THD *, Item **ref);
1732-
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
1732+
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
17331733

17341734
enum Type type() const { return COND_ITEM; }
17351735
List<Item>* argument_list() { return &list; }

sql/item_func.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,8 @@ Item_func::eval_not_null_tables(uchar *opt_arg)
265265
}
266266

267267

268-
void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref)
268+
void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref,
269+
bool merge)
269270
{
270271
Item **arg,**arg_end;
271272

@@ -276,7 +277,7 @@ void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref)
276277
{
277278
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
278279
{
279-
(*arg)->fix_after_pullout(new_parent, arg);
280+
(*arg)->fix_after_pullout(new_parent, arg, merge);
280281
Item *item= *arg;
281282

282283
used_tables_cache|= item->used_tables();

sql/item_func.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ class Item_func :public Item_result_field
143143
// Constructor used for Item_cond_and/or (see Item comment)
144144
Item_func(THD *thd, Item_func *item);
145145
bool fix_fields(THD *, Item **ref);
146-
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
146+
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
147147
void quick_fix_field();
148148
table_map used_tables() const;
149149
table_map not_null_tables() const;

sql/item_row.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,15 @@ void Item_row::update_used_tables()
184184
}
185185

186186

187-
void Item_row::fix_after_pullout(st_select_lex *new_parent, Item **ref)
187+
void Item_row::fix_after_pullout(st_select_lex *new_parent, Item **ref,
188+
bool merge)
188189
{
189190
used_tables_cache= 0;
190191
const_item_cache= 1;
191192
not_null_tables_cache= 0;
192193
for (uint i= 0; i < arg_count; i++)
193194
{
194-
items[i]->fix_after_pullout(new_parent, &items[i]);
195+
items[i]->fix_after_pullout(new_parent, &items[i], merge);
195196
used_tables_cache|= items[i]->used_tables();
196197
const_item_cache&= items[i]->const_item();
197198
not_null_tables_cache|= items[i]->not_null_tables();

sql/item_row.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class Item_row: public Item
6565
return 0;
6666
};
6767
bool fix_fields(THD *thd, Item **ref);
68-
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
68+
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
6969
void cleanup();
7070
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
7171
table_map used_tables() const { return used_tables_cache; };

0 commit comments

Comments
 (0)