mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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.
This commit is contained in:
@ -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
|
|||||||
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%'`)
|
|||||||
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;
|
|||||||
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;
|
|||||||
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)
|
|||||||
|
|
||||||
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);
|
||||||
|
104
sql/item.cc
104
sql/item.cc
@ -61,11 +61,12 @@ bool cmp_items(Item *a, Item *b)
|
|||||||
/**
|
/**
|
||||||
Set max_sum_func_level if it is needed
|
Set max_sum_func_level if it is needed
|
||||||
*/
|
*/
|
||||||
inline void set_max_sum_func_level(THD *thd, SELECT_LEX *select)
|
inline void set_max_sum_func_level(SELECT_LEX *select)
|
||||||
{
|
{
|
||||||
if (thd->lex->in_sum_func &&
|
LEX *lex_s= select->parent_lex;
|
||||||
thd->lex->in_sum_func->nest_level >= select->nest_level)
|
if (lex_s->in_sum_func &&
|
||||||
set_if_bigger(thd->lex->in_sum_func->max_sum_func_level,
|
lex_s->in_sum_func->nest_level >= select->nest_level)
|
||||||
|
set_if_bigger(lex_s->in_sum_func->max_sum_func_level,
|
||||||
select->nest_level - 1);
|
select->nest_level - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,6 +781,7 @@ Item_ident::Item_ident(THD *thd, Name_resolution_context *context_arg,
|
|||||||
{
|
{
|
||||||
name = (char*) field_name_arg;
|
name = (char*) field_name_arg;
|
||||||
name_length= name ? strlen(name) : 0;
|
name_length= name ? strlen(name) : 0;
|
||||||
|
DBUG_ASSERT(!context || context->select_lex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -794,6 +796,7 @@ Item_ident::Item_ident(THD *thd, TABLE_LIST *view_arg, const char *field_name_ar
|
|||||||
{
|
{
|
||||||
name = (char*) field_name_arg;
|
name = (char*) field_name_arg;
|
||||||
name_length= name ? strlen(name) : 0;
|
name_length= name ? strlen(name) : 0;
|
||||||
|
DBUG_ASSERT(!context || context->select_lex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -815,7 +818,9 @@ Item_ident::Item_ident(THD *thd, Item_ident *item)
|
|||||||
cached_table(item->cached_table),
|
cached_table(item->cached_table),
|
||||||
depended_from(item->depended_from),
|
depended_from(item->depended_from),
|
||||||
can_be_depended(item->can_be_depended)
|
can_be_depended(item->can_be_depended)
|
||||||
{}
|
{
|
||||||
|
DBUG_ASSERT(!context || context->select_lex);
|
||||||
|
}
|
||||||
|
|
||||||
void Item_ident::cleanup()
|
void Item_ident::cleanup()
|
||||||
{
|
{
|
||||||
@ -5117,7 +5122,14 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
|
|||||||
*/
|
*/
|
||||||
Name_resolution_context *last_checked_context= context;
|
Name_resolution_context *last_checked_context= context;
|
||||||
Item **ref= (Item **) not_found_item;
|
Item **ref= (Item **) not_found_item;
|
||||||
SELECT_LEX *current_sel= thd->lex->current_select;
|
/*
|
||||||
|
There are cases when name resolution context is absent (when we are not
|
||||||
|
doing name resolution), but here the name resolution context should
|
||||||
|
be present because we are doing name resolution
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(context);
|
||||||
|
SELECT_LEX *current_sel= context->select_lex;
|
||||||
|
LEX *lex_s= context->select_lex->parent_lex;
|
||||||
Name_resolution_context *outer_context= 0;
|
Name_resolution_context *outer_context= 0;
|
||||||
SELECT_LEX *select= 0;
|
SELECT_LEX *select= 0;
|
||||||
/* Currently derived tables cannot be correlated */
|
/* Currently derived tables cannot be correlated */
|
||||||
@ -5218,18 +5230,18 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
|
|||||||
return -1;
|
return -1;
|
||||||
thd->change_item_tree(reference, rf);
|
thd->change_item_tree(reference, rf);
|
||||||
select->inner_refs_list.push_back(rf, thd->mem_root);
|
select->inner_refs_list.push_back(rf, thd->mem_root);
|
||||||
rf->in_sum_func= thd->lex->in_sum_func;
|
rf->in_sum_func= lex_s->in_sum_func;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
A reference is resolved to a nest level that's outer or the same as
|
A reference is resolved to a nest level that's outer or the same as
|
||||||
the nest level of the enclosing set function : adjust the value of
|
the nest level of the enclosing set function : adjust the value of
|
||||||
max_arg_level for the function if it's needed.
|
max_arg_level for the function if it's needed.
|
||||||
*/
|
*/
|
||||||
if (thd->lex->in_sum_func &&
|
if (lex_s->in_sum_func &&
|
||||||
thd->lex->in_sum_func->nest_level >= select->nest_level)
|
lex_s->in_sum_func->nest_level >= select->nest_level)
|
||||||
{
|
{
|
||||||
Item::Type ref_type= (*reference)->type();
|
Item::Type ref_type= (*reference)->type();
|
||||||
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
set_if_bigger(lex_s->in_sum_func->max_arg_level,
|
||||||
select->nest_level);
|
select->nest_level);
|
||||||
set_field(*from_field);
|
set_field(*from_field);
|
||||||
fixed= 1;
|
fixed= 1;
|
||||||
@ -5250,10 +5262,10 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
|
|||||||
((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ?
|
((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ?
|
||||||
(Item_ident*) (*reference) :
|
(Item_ident*) (*reference) :
|
||||||
0), false);
|
0), false);
|
||||||
if (thd->lex->in_sum_func &&
|
if (lex_s->in_sum_func &&
|
||||||
thd->lex->in_sum_func->nest_level >= select->nest_level)
|
lex_s->in_sum_func->nest_level >= select->nest_level)
|
||||||
{
|
{
|
||||||
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
set_if_bigger(lex_s->in_sum_func->max_arg_level,
|
||||||
select->nest_level);
|
select->nest_level);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -5345,7 +5357,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
|
|||||||
{
|
{
|
||||||
outer_context->select_lex->inner_refs_list.push_back((Item_outer_ref*)rf,
|
outer_context->select_lex->inner_refs_list.push_back((Item_outer_ref*)rf,
|
||||||
thd->mem_root);
|
thd->mem_root);
|
||||||
((Item_outer_ref*)rf)->in_sum_func= thd->lex->in_sum_func;
|
((Item_outer_ref*)rf)->in_sum_func= lex_s->in_sum_func;
|
||||||
}
|
}
|
||||||
thd->change_item_tree(reference, rf);
|
thd->change_item_tree(reference, rf);
|
||||||
/*
|
/*
|
||||||
@ -5360,7 +5372,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
|
|||||||
We can not "move" aggregate function in the place where
|
We can not "move" aggregate function in the place where
|
||||||
its arguments are not defined.
|
its arguments are not defined.
|
||||||
*/
|
*/
|
||||||
set_max_sum_func_level(thd, select);
|
set_max_sum_func_level(select);
|
||||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
context->select_lex, rf,
|
context->select_lex, rf,
|
||||||
rf, false);
|
rf, false);
|
||||||
@ -5373,7 +5385,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
|
|||||||
We can not "move" aggregate function in the place where
|
We can not "move" aggregate function in the place where
|
||||||
its arguments are not defined.
|
its arguments are not defined.
|
||||||
*/
|
*/
|
||||||
set_max_sum_func_level(thd, select);
|
set_max_sum_func_level(select);
|
||||||
mark_as_dependent(thd, last_checked_context->select_lex,
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
context->select_lex,
|
context->select_lex,
|
||||||
this, (Item_ident*)*reference, false);
|
this, (Item_ident*)*reference, false);
|
||||||
@ -5450,7 +5462,20 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
Field *from_field= (Field *)not_found_field;
|
Field *from_field= (Field *)not_found_field;
|
||||||
bool outer_fixed= false;
|
bool outer_fixed= false;
|
||||||
SELECT_LEX *select= thd->lex->current_select;
|
SELECT_LEX *select;
|
||||||
|
LEX *lex_s;
|
||||||
|
if (context)
|
||||||
|
{
|
||||||
|
select= context->select_lex;
|
||||||
|
lex_s= context->select_lex->parent_lex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No real name resolution, used somewhere in SP
|
||||||
|
DBUG_ASSERT(field);
|
||||||
|
select= NULL;
|
||||||
|
lex_s= NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!field) // If field is not checked
|
if (!field) // If field is not checked
|
||||||
{
|
{
|
||||||
@ -5511,7 +5536,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
We can not "move" aggregate function in the place where
|
We can not "move" aggregate function in the place where
|
||||||
its arguments are not defined.
|
its arguments are not defined.
|
||||||
*/
|
*/
|
||||||
set_max_sum_func_level(thd, select);
|
set_max_sum_func_level(select);
|
||||||
set_field(new_field);
|
set_field(new_field);
|
||||||
depended_from= (*((Item_field**)res))->depended_from;
|
depended_from= (*((Item_field**)res))->depended_from;
|
||||||
return 0;
|
return 0;
|
||||||
@ -5540,7 +5565,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
We can not "move" aggregate function in the place where
|
We can not "move" aggregate function in the place where
|
||||||
its arguments are not defined.
|
its arguments are not defined.
|
||||||
*/
|
*/
|
||||||
set_max_sum_func_level(thd, select);
|
set_max_sum_func_level(select);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5577,10 +5602,11 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
goto mark_non_agg_field;
|
goto mark_non_agg_field;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thd->lex->in_sum_func &&
|
if (lex_s &&
|
||||||
thd->lex->in_sum_func->nest_level ==
|
lex_s->in_sum_func &&
|
||||||
|
lex_s->in_sum_func->nest_level ==
|
||||||
select->nest_level)
|
select->nest_level)
|
||||||
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
set_if_bigger(lex_s->in_sum_func->max_arg_level,
|
||||||
select->nest_level);
|
select->nest_level);
|
||||||
/*
|
/*
|
||||||
if it is not expression from merged VIEW we will set this field.
|
if it is not expression from merged VIEW we will set this field.
|
||||||
@ -5646,8 +5672,9 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
|||||||
if (field->vcol_info)
|
if (field->vcol_info)
|
||||||
fix_session_vcol_expr_for_read(thd, field, field->vcol_info);
|
fix_session_vcol_expr_for_read(thd, field, field->vcol_info);
|
||||||
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
|
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
|
||||||
!outer_fixed && !thd->lex->in_sum_func &&
|
!outer_fixed &&
|
||||||
select &&
|
select &&
|
||||||
|
!lex_s->in_sum_func &&
|
||||||
select->cur_pos_in_select_list != UNDEF_POS &&
|
select->cur_pos_in_select_list != UNDEF_POS &&
|
||||||
select->join)
|
select->join)
|
||||||
{
|
{
|
||||||
@ -5682,13 +5709,13 @@ mark_non_agg_field:
|
|||||||
*/
|
*/
|
||||||
select_lex= context->select_lex;
|
select_lex= context->select_lex;
|
||||||
}
|
}
|
||||||
if (!thd->lex->in_sum_func)
|
if (!lex_s || !lex_s->in_sum_func)
|
||||||
select_lex->set_non_agg_field_used(true);
|
select_lex->set_non_agg_field_used(true);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (outer_fixed)
|
if (outer_fixed)
|
||||||
thd->lex->in_sum_func->outer_fields.push_back(this, thd->mem_root);
|
lex_s->in_sum_func->outer_fields.push_back(this, thd->mem_root);
|
||||||
else if (thd->lex->in_sum_func->nest_level !=
|
else if (lex_s->in_sum_func->nest_level !=
|
||||||
select->nest_level)
|
select->nest_level)
|
||||||
select_lex->set_non_agg_field_used(true);
|
select_lex->set_non_agg_field_used(true);
|
||||||
}
|
}
|
||||||
@ -7181,6 +7208,12 @@ Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item *Item_ident::derived_field_transformer_for_having(THD *thd, uchar *arg)
|
||||||
|
{
|
||||||
|
st_select_lex *sel= (st_select_lex *)arg;
|
||||||
|
context= &sel->context;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
Item *Item_field::derived_field_transformer_for_having(THD *thd, uchar *arg)
|
Item *Item_field::derived_field_transformer_for_having(THD *thd, uchar *arg)
|
||||||
{
|
{
|
||||||
@ -7200,12 +7233,13 @@ Item *Item_field::derived_field_transformer_for_having(THD *thd, uchar *arg)
|
|||||||
Item *Item_direct_view_ref::derived_field_transformer_for_having(THD *thd,
|
Item *Item_direct_view_ref::derived_field_transformer_for_having(THD *thd,
|
||||||
uchar *arg)
|
uchar *arg)
|
||||||
{
|
{
|
||||||
|
st_select_lex *sel= (st_select_lex *)arg;
|
||||||
|
context= &sel->context;
|
||||||
if ((*ref)->marker & SUBSTITUTION_FL)
|
if ((*ref)->marker & SUBSTITUTION_FL)
|
||||||
{
|
{
|
||||||
this->marker|= SUBSTITUTION_FL;
|
this->marker|= SUBSTITUTION_FL;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
st_select_lex *sel= (st_select_lex *)arg;
|
|
||||||
table_map tab_map= sel->master_unit()->derived->table->map;
|
table_map tab_map= sel->master_unit()->derived->table->map;
|
||||||
if ((item_equal && !(item_equal->used_tables() & tab_map)) ||
|
if ((item_equal && !(item_equal->used_tables() & tab_map)) ||
|
||||||
!item_equal)
|
!item_equal)
|
||||||
@ -7501,7 +7535,9 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
|
|||||||
{
|
{
|
||||||
enum_parsing_place place= NO_MATTER;
|
enum_parsing_place place= NO_MATTER;
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
SELECT_LEX *current_sel= thd->lex->current_select;
|
|
||||||
|
SELECT_LEX *current_sel= context->select_lex;
|
||||||
|
LEX *lex_s= context->select_lex->parent_lex;
|
||||||
|
|
||||||
if (set_properties_only)
|
if (set_properties_only)
|
||||||
{
|
{
|
||||||
@ -7662,10 +7698,10 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
|
|||||||
the nest level of the enclosing set function : adjust the value of
|
the nest level of the enclosing set function : adjust the value of
|
||||||
max_arg_level for the function if it's needed.
|
max_arg_level for the function if it's needed.
|
||||||
*/
|
*/
|
||||||
if (thd->lex->in_sum_func &&
|
if (lex_s->in_sum_func &&
|
||||||
thd->lex->in_sum_func->nest_level >=
|
lex_s->in_sum_func->nest_level >=
|
||||||
last_checked_context->select_lex->nest_level)
|
last_checked_context->select_lex->nest_level)
|
||||||
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
set_if_bigger(lex_s->in_sum_func->max_arg_level,
|
||||||
last_checked_context->select_lex->nest_level);
|
last_checked_context->select_lex->nest_level);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -7685,10 +7721,10 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
|
|||||||
the nest level of the enclosing set function : adjust the value of
|
the nest level of the enclosing set function : adjust the value of
|
||||||
max_arg_level for the function if it's needed.
|
max_arg_level for the function if it's needed.
|
||||||
*/
|
*/
|
||||||
if (thd->lex->in_sum_func &&
|
if (lex_s->in_sum_func &&
|
||||||
thd->lex->in_sum_func->nest_level >=
|
lex_s->in_sum_func->nest_level >=
|
||||||
last_checked_context->select_lex->nest_level)
|
last_checked_context->select_lex->nest_level)
|
||||||
set_if_bigger(thd->lex->in_sum_func->max_arg_level,
|
set_if_bigger(lex_s->in_sum_func->max_arg_level,
|
||||||
last_checked_context->select_lex->nest_level);
|
last_checked_context->select_lex->nest_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2630,6 +2630,7 @@ public:
|
|||||||
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()
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user