Commit 3690c549 authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

MDEV-24454 Crash at change_item_tree

Use in_sum_func (and so nest_level) only in LEX to which SELECT lex belong to

Reduce usage of current_select (because it does not always point on the correct
 SELECT_LEX, for example with prepare.

Change context for all classes inherited from Item_ident (was only for Item_field) in case of pushing down it to HAVING.

Now name resolution context have to have SELECT_LEX reference if the context is present.

Fixed feedback plugin stack usage.
parent 1a62c878
...@@ -6833,5 +6833,48 @@ sum(z) ...@@ -6833,5 +6833,48 @@ sum(z)
DROP TABLE t1; DROP TABLE t1;
DROP VIEW v1; DROP VIEW v1;
# #
# MDEV-24454: Crash at change_item_tree
#
CREATE TABLE t1(f0 INT);
CREATE VIEW v1 AS
SELECT
f0 AS f1
FROM t1;
CREATE VIEW v2 AS
SELECT
(SELECT GROUP_CONCAT(v1.f1 SEPARATOR ', ')
FROM v1 n) AS f2,
GROUP_CONCAT('' SEPARATOR ', ') AS f3
FROM v1;
CREATE VIEW v3 AS
SELECT 1 as f4 FROM v2;
CREATE PROCEDURE p1()
SELECT * FROM v3;
CALL p1();
f4
1
CALL p1();
f4
1
drop procedure p1;
drop view v1,v2,v3;
drop table t1;
#
# MDEV-25631: Crash in st_select_lex::mark_as_dependent with
# VIEW, aggregate and subquery
#
CREATE TABLE t1 (i1 int);
insert into t1 values (1),(2),(3);
CREATE VIEW v1 AS
SELECT t1.i1 FROM (t1 a JOIN t1 ON (t1.i1 = (SELECT t1.i1 FROM t1 b)));
SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ;
ERROR 21000: Subquery returns more than 1 row
delete from t1 where i1 > 1;
SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ;
1
1
drop view v1;
drop table t1;
#
# End of 10.2 tests # End of 10.2 tests
# #
...@@ -24,3 +24,19 @@ VARIABLE_VALUE>0 VARIABLE_NAME ...@@ -24,3 +24,19 @@ VARIABLE_VALUE>0 VARIABLE_NAME
1 Collation used latin1_swedish_ci 1 Collation used latin1_swedish_ci
1 Collation used utf8_bin 1 Collation used utf8_bin
1 Collation used utf8_general_ci 1 Collation used utf8_general_ci
prepare stmt from "SELECT VARIABLE_VALUE>0, VARIABLE_NAME FROM INFORMATION_SCHEMA.FEEDBACK WHERE VARIABLE_NAME LIKE 'Collation used %' ORDER BY VARIABLE_NAME";
execute stmt;
VARIABLE_VALUE>0 VARIABLE_NAME
1 Collation used binary
1 Collation used latin1_bin
1 Collation used latin1_swedish_ci
1 Collation used utf8_bin
1 Collation used utf8_general_ci
execute stmt;
VARIABLE_VALUE>0 VARIABLE_NAME
1 Collation used binary
1 Collation used latin1_bin
1 Collation used latin1_swedish_ci
1 Collation used utf8_bin
1 Collation used utf8_general_ci
deallocate prepare stmt;
...@@ -42,3 +42,10 @@ if (`SELECT VERSION() LIKE '%embedded%'`) ...@@ -42,3 +42,10 @@ if (`SELECT VERSION() LIKE '%embedded%'`)
SELECT VARIABLE_VALUE>0, VARIABLE_NAME FROM INFORMATION_SCHEMA.FEEDBACK SELECT VARIABLE_VALUE>0, VARIABLE_NAME FROM INFORMATION_SCHEMA.FEEDBACK
WHERE VARIABLE_NAME LIKE 'Collation used %' WHERE VARIABLE_NAME LIKE 'Collation used %'
ORDER BY VARIABLE_NAME; ORDER BY VARIABLE_NAME;
prepare stmt from "SELECT VARIABLE_VALUE>0, VARIABLE_NAME FROM INFORMATION_SCHEMA.FEEDBACK WHERE VARIABLE_NAME LIKE 'Collation used %' ORDER BY VARIABLE_NAME";
execute stmt;
execute stmt;
deallocate prepare stmt;
...@@ -6559,6 +6559,55 @@ SELECT sum(z) FROM v1; ...@@ -6559,6 +6559,55 @@ SELECT sum(z) FROM v1;
DROP TABLE t1; DROP TABLE t1;
DROP VIEW v1; DROP VIEW v1;
--echo #
--echo # MDEV-24454: Crash at change_item_tree
--echo #
CREATE TABLE t1(f0 INT);
CREATE VIEW v1 AS
SELECT
f0 AS f1
FROM t1;
CREATE VIEW v2 AS
SELECT
(SELECT GROUP_CONCAT(v1.f1 SEPARATOR ', ')
FROM v1 n) AS f2,
GROUP_CONCAT('' SEPARATOR ', ') AS f3
FROM v1;
CREATE VIEW v3 AS
SELECT 1 as f4 FROM v2;
CREATE PROCEDURE p1()
SELECT * FROM v3;
CALL p1();
CALL p1();
drop procedure p1;
drop view v1,v2,v3;
drop table t1;
--echo #
--echo # MDEV-25631: Crash in st_select_lex::mark_as_dependent with
--echo # VIEW, aggregate and subquery
--echo #
CREATE TABLE t1 (i1 int);
insert into t1 values (1),(2),(3); #not important
CREATE VIEW v1 AS
SELECT t1.i1 FROM (t1 a JOIN t1 ON (t1.i1 = (SELECT t1.i1 FROM t1 b)));
--error ER_SUBQUERY_NO_1_ROW
SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ;
delete from t1 where i1 > 1;
SELECT 1 FROM (SELECT count(((SELECT i1 FROM v1))) FROM v1) dt ;
drop view v1;
drop table t1;
--echo # --echo #
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # --echo #
...@@ -92,16 +92,18 @@ static COND * const OOM= (COND*)1; ...@@ -92,16 +92,18 @@ static COND * const OOM= (COND*)1;
static COND* make_cond(THD *thd, TABLE_LIST *tables, LEX_STRING *filter) static COND* make_cond(THD *thd, TABLE_LIST *tables, LEX_STRING *filter)
{ {
Item_cond_or *res= NULL; Item_cond_or *res= NULL;
Name_resolution_context nrc; /* A reference to this context will be stored in Item_field */
Name_resolution_context *nrc= new (thd->mem_root) Name_resolution_context;
const char *db= tables->db, *table= tables->alias, const char *db= tables->db, *table= tables->alias,
*field= tables->table->field[0]->field_name; *field= tables->table->field[0]->field_name;
CHARSET_INFO *cs= &my_charset_latin1; CHARSET_INFO *cs= &my_charset_latin1;
if (!filter->str) if (!filter->str || !nrc)
return 0; return 0;
nrc.init(); nrc->init();
nrc.resolve_in_table_list_only(tables); nrc->resolve_in_table_list_only(tables);
nrc->select_lex= tables->select_lex;
res= new (thd->mem_root) Item_cond_or(thd); res= new (thd->mem_root) Item_cond_or(thd);
if (!res) if (!res)
...@@ -109,7 +111,7 @@ static COND* make_cond(THD *thd, TABLE_LIST *tables, LEX_STRING *filter) ...@@ -109,7 +111,7 @@ static COND* make_cond(THD *thd, TABLE_LIST *tables, LEX_STRING *filter)
for (; filter->str; filter++) for (; filter->str; filter++)
{ {
Item_field *fld= new (thd->mem_root) Item_field(thd, &nrc, db, table, Item_field *fld= new (thd->mem_root) Item_field(thd, nrc, db, table,
field); field);
Item_string *pattern= new (thd->mem_root) Item_string(thd, filter->str, Item_string *pattern= new (thd->mem_root) Item_string(thd, filter->str,
(uint) filter->length, cs); (uint) filter->length, cs);
......
This diff is collapsed.
...@@ -2630,6 +2630,7 @@ class Item_ident :public Item_result_field ...@@ -2630,6 +2630,7 @@ class Item_ident :public Item_result_field
Collect outer references Collect outer references
*/ */
virtual bool collect_outer_ref_processor(void *arg); virtual bool collect_outer_ref_processor(void *arg);
Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
friend bool insert_fields(THD *thd, Name_resolution_context *context, friend bool insert_fields(THD *thd, Name_resolution_context *context,
const char *db_name, const char *db_name,
const char *table_name, List_iterator<Item> *it, const char *table_name, List_iterator<Item> *it,
......
...@@ -5190,8 +5190,9 @@ bool subselect_hash_sj_engine::make_semi_join_conds() ...@@ -5190,8 +5190,9 @@ bool subselect_hash_sj_engine::make_semi_join_conds()
NULL, TL_READ); NULL, TL_READ);
tmp_table_ref->table= tmp_table; tmp_table_ref->table= tmp_table;
context= new Name_resolution_context; context= new (thd->mem_root) Name_resolution_context;
context->init(); context->init();
context->select_lex= item_in->unit->first_select();
context->first_name_resolution_table= context->first_name_resolution_table=
context->last_name_resolution_table= tmp_table_ref; context->last_name_resolution_table= tmp_table_ref;
semi_join_conds_context= context; semi_join_conds_context= context;
......
...@@ -68,6 +68,7 @@ size_t Item_sum::ram_limitation(THD *thd) ...@@ -68,6 +68,7 @@ size_t Item_sum::ram_limitation(THD *thd)
bool Item_sum::init_sum_func_check(THD *thd) bool Item_sum::init_sum_func_check(THD *thd)
{ {
SELECT_LEX *curr_sel= thd->lex->current_select; SELECT_LEX *curr_sel= thd->lex->current_select;
LEX *lex_s= (curr_sel ? curr_sel->parent_lex : thd->lex);
if (curr_sel && !curr_sel->name_visibility_map) if (curr_sel && !curr_sel->name_visibility_map)
{ {
for (SELECT_LEX *sl= curr_sel; sl; sl= sl->context.outer_select()) for (SELECT_LEX *sl= curr_sel; sl; sl= sl->context.outer_select())
...@@ -82,9 +83,9 @@ bool Item_sum::init_sum_func_check(THD *thd) ...@@ -82,9 +83,9 @@ bool Item_sum::init_sum_func_check(THD *thd)
return TRUE; return TRUE;
} }
/* Set a reference to the nesting set function if there is any */ /* Set a reference to the nesting set function if there is any */
in_sum_func= thd->lex->in_sum_func; in_sum_func= lex_s->in_sum_func;
/* Save a pointer to object to be used in items for nested set functions */ /* Save a pointer to object to be used in items for nested set functions */
thd->lex->in_sum_func= this; lex_s->in_sum_func= this;
nest_level= thd->lex->current_select->nest_level; nest_level= thd->lex->current_select->nest_level;
ref_by= 0; ref_by= 0;
aggr_level= -1; aggr_level= -1;
...@@ -151,6 +152,7 @@ bool Item_sum::init_sum_func_check(THD *thd) ...@@ -151,6 +152,7 @@ bool Item_sum::init_sum_func_check(THD *thd)
bool Item_sum::check_sum_func(THD *thd, Item **ref) bool Item_sum::check_sum_func(THD *thd, Item **ref)
{ {
SELECT_LEX *curr_sel= thd->lex->current_select; SELECT_LEX *curr_sel= thd->lex->current_select;
LEX *lex_s= curr_sel->parent_lex;
nesting_map allow_sum_func= (thd->lex->allow_sum_func & nesting_map allow_sum_func= (thd->lex->allow_sum_func &
curr_sel->name_visibility_map); curr_sel->name_visibility_map);
bool invalid= FALSE; bool invalid= FALSE;
...@@ -310,7 +312,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) ...@@ -310,7 +312,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
} }
aggr_sel->set_agg_func_used(true); aggr_sel->set_agg_func_used(true);
update_used_tables(); update_used_tables();
thd->lex->in_sum_func= in_sum_func; lex_s->in_sum_func= in_sum_func;
return FALSE; return FALSE;
} }
......
...@@ -6440,6 +6440,7 @@ set_new_item_local_context(THD *thd, Item_ident *item, TABLE_LIST *table_ref) ...@@ -6440,6 +6440,7 @@ set_new_item_local_context(THD *thd, Item_ident *item, TABLE_LIST *table_ref)
if (!(context= new (thd->mem_root) Name_resolution_context)) if (!(context= new (thd->mem_root) Name_resolution_context))
return TRUE; return TRUE;
context->init(); context->init();
context->select_lex= table_ref->select_lex;
context->first_name_resolution_table= context->first_name_resolution_table=
context->last_name_resolution_table= table_ref; context->last_name_resolution_table= table_ref;
item->context= context; item->context= context;
......
...@@ -3060,6 +3060,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) ...@@ -3060,6 +3060,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
} }
for (; sl; sl= sl->next_select_in_list()) for (; sl; sl= sl->next_select_in_list())
{ {
sl->parent_lex->in_sum_func= NULL;
if (sl->changed_elements & TOUCHED_SEL_COND) if (sl->changed_elements & TOUCHED_SEL_COND)
{ {
/* remove option which was put by mysql_explain_union() */ /* remove option which was put by mysql_explain_union() */
...@@ -3190,7 +3191,6 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) ...@@ -3190,7 +3191,6 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
lex->result->set_thd(thd); lex->result->set_thd(thd);
} }
lex->allow_sum_func= 0; lex->allow_sum_func= 0;
lex->in_sum_func= NULL;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
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