MDEV-16697: Fix difference between 32bit/windows and 64bit systems in allowed select nest level

This commit is contained in:
Oleksandr Byelkin 2018-07-05 17:49:44 +02:00
parent 89a87e8e42
commit 54b2e1c1be
14 changed files with 70 additions and 29 deletions

View File

@ -986,7 +986,6 @@ typedef unsigned long my_off_t;
TODO Convert these to use Bitmap class. TODO Convert these to use Bitmap class.
*/ */
typedef ulonglong table_map; /* Used for table bits in join */ typedef ulonglong table_map; /* Used for table bits in join */
typedef ulong nesting_map; /* Used for flags of nesting constructs */
/* often used type names - opaque declarations */ /* often used type names - opaque declarations */
typedef const struct charset_info_st CHARSET_INFO; typedef const struct charset_info_st CHARSET_INFO;

View File

@ -1680,3 +1680,24 @@ SELECT without VERSIONING FROM t1
SELECT without WITHOUT FROM t1 SELECT without WITHOUT FROM t1
DROP PROCEDURE p2; DROP PROCEDURE p2;
DROP PROCEDURE p1; DROP PROCEDURE p1;
#
# MDEV-16697: Fix difference between 32bit/windows and 64bit
# systems in allowed select nest level
#
SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
1
)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))));
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT
1
End of 10.3 tests

View File

@ -1443,3 +1443,20 @@ CALL p2('without');
DROP PROCEDURE p2; DROP PROCEDURE p2;
DROP PROCEDURE p1; DROP PROCEDURE p1;
--echo #
--echo # MDEV-16697: Fix difference between 32bit/windows and 64bit
--echo # systems in allowed select nest level
--echo #
SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
(SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT
1
)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))));
--echo End of 10.3 tests

View File

@ -1983,8 +1983,7 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join)
print_where(item, "rewrite with MIN/MAX", QT_ORDINARY);); print_where(item, "rewrite with MIN/MAX", QT_ORDINARY););
save_allow_sum_func= thd->lex->allow_sum_func; save_allow_sum_func= thd->lex->allow_sum_func;
thd->lex->allow_sum_func|= thd->lex->allow_sum_func.set_bit(thd->lex->current_select->nest_level);
(nesting_map)1 << thd->lex->current_select->nest_level;
/* /*
Item_sum_(max|min) can't substitute other item => we can use 0 as Item_sum_(max|min) can't substitute other item => we can use 0 as
reference, also Item_sum_(max|min) can't be fixed after creation, so reference, also Item_sum_(max|min) can't be fixed after creation, so

View File

@ -72,14 +72,15 @@ 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;
if (curr_sel && !curr_sel->name_visibility_map) if (curr_sel && curr_sel->name_visibility_map.is_clear_all())
{ {
for (SELECT_LEX *sl= curr_sel; sl; sl= sl->context.outer_select()) for (SELECT_LEX *sl= curr_sel; sl; sl= sl->context.outer_select())
{ {
curr_sel->name_visibility_map|= (1 << sl-> nest_level); curr_sel->name_visibility_map.set_bit(sl->nest_level);
} }
} }
if (!curr_sel || !(thd->lex->allow_sum_func & curr_sel->name_visibility_map)) if (!curr_sel ||
!(thd->lex->allow_sum_func.is_overlapping(curr_sel->name_visibility_map)))
{ {
my_message(ER_INVALID_GROUP_FUNC_USE, ER_THD(thd, ER_INVALID_GROUP_FUNC_USE), my_message(ER_INVALID_GROUP_FUNC_USE, ER_THD(thd, ER_INVALID_GROUP_FUNC_USE),
MYF(0)); MYF(0));
@ -155,10 +156,11 @@ 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;
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); allow_sum_func.intersect(curr_sel->name_visibility_map);
bool invalid= FALSE; bool invalid= FALSE;
DBUG_ASSERT(curr_sel->name_visibility_map); // should be set already // should be set already
DBUG_ASSERT(!curr_sel->name_visibility_map.is_clear_all());
/* /*
Window functions can not be used as arguments to sum functions. Window functions can not be used as arguments to sum functions.
@ -189,10 +191,10 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
If it is there under a construct where it is not allowed If it is there under a construct where it is not allowed
we report an error. we report an error.
*/ */
invalid= !(allow_sum_func & ((nesting_map)1 << max_arg_level)); invalid= !(allow_sum_func.is_set(max_arg_level));
} }
else if (max_arg_level >= 0 || else if (max_arg_level >= 0 ||
!(allow_sum_func & ((nesting_map)1 << nest_level))) !(allow_sum_func.is_set(nest_level)))
{ {
/* /*
The set function can be aggregated only in outer subqueries. The set function can be aggregated only in outer subqueries.
@ -202,7 +204,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
if (register_sum_func(thd, ref)) if (register_sum_func(thd, ref))
return TRUE; return TRUE;
invalid= aggr_level < 0 && invalid= aggr_level < 0 &&
!(allow_sum_func & ((nesting_map)1 << nest_level)); !(allow_sum_func.is_set(nest_level));
if (!invalid && thd->variables.sql_mode & MODE_ANSI) if (!invalid && thd->variables.sql_mode & MODE_ANSI)
invalid= aggr_level < 0 && max_arg_level < nest_level; invalid= aggr_level < 0 && max_arg_level < nest_level;
} }
@ -354,14 +356,14 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref)
sl= sl->context.outer_select()) sl= sl->context.outer_select())
{ {
if (aggr_level < 0 && if (aggr_level < 0 &&
(allow_sum_func & ((nesting_map)1 << sl->nest_level))) (allow_sum_func.is_set(sl->nest_level)))
{ {
/* Found the most nested subquery where the function can be aggregated */ /* Found the most nested subquery where the function can be aggregated */
aggr_level= sl->nest_level; aggr_level= sl->nest_level;
aggr_sel= sl; aggr_sel= sl;
} }
} }
if (sl && (allow_sum_func & ((nesting_map)1 << sl->nest_level))) if (sl && (allow_sum_func.is_set(sl->nest_level)))
{ {
/* /*
We reached the subquery of level max_arg_level and checked We reached the subquery of level max_arg_level and checked

View File

@ -7372,8 +7372,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
thd->column_usage= column_usage; thd->column_usage= column_usage;
DBUG_PRINT("info", ("thd->column_usage: %d", thd->column_usage)); DBUG_PRINT("info", ("thd->column_usage: %d", thd->column_usage));
if (allow_sum_func) if (allow_sum_func)
thd->lex->allow_sum_func|= thd->lex->allow_sum_func.set_bit(thd->lex->current_select->nest_level);
(nesting_map)1 << thd->lex->current_select->nest_level;
thd->where= THD::DEFAULT_WHERE; thd->where= THD::DEFAULT_WHERE;
save_is_item_list_lookup= thd->lex->current_select->is_item_list_lookup; save_is_item_list_lookup= thd->lex->current_select->is_item_list_lookup;
thd->lex->current_select->is_item_list_lookup= 0; thd->lex->current_select->is_item_list_lookup= 0;

View File

@ -84,7 +84,7 @@
#define MAX_FIELDS 4096 /* Limit in the .frm file */ #define MAX_FIELDS 4096 /* Limit in the .frm file */
#define MAX_PARTITIONS 8192 #define MAX_PARTITIONS 8192
#define MAX_SELECT_NESTING (sizeof(nesting_map)*8-1) #define MAX_SELECT_NESTING (SELECT_NESTING_MAP_SIZE - 1)
#define MAX_SORT_MEMORY 2048*1024 #define MAX_SORT_MEMORY 2048*1024
#define MIN_SORT_MEMORY 1024 #define MIN_SORT_MEMORY 1024

View File

@ -936,7 +936,7 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
List<Item> all_fields; List<Item> all_fields;
*delete_while_scanning= true; *delete_while_scanning= true;
thd->lex->allow_sum_func= 0; thd->lex->allow_sum_func.clear_all();
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list, &thd->lex->select_lex.top_join_list,
table_list, table_list,

View File

@ -734,7 +734,7 @@ void LEX::start(THD *thd_arg)
profile_options= PROFILE_NONE; profile_options= PROFILE_NONE;
nest_level=0 ; nest_level=0 ;
select_lex.nest_level_base= &unit; select_lex.nest_level_base= &unit;
allow_sum_func= 0; allow_sum_func.clear_all();
in_sum_func= NULL; in_sum_func= NULL;
used_tables= 0; used_tables= 0;
@ -2335,7 +2335,7 @@ void st_select_lex::init_select()
m_non_agg_field_used= false; m_non_agg_field_used= false;
m_agg_func_used= false; m_agg_func_used= false;
m_custom_agg_func_used= false; m_custom_agg_func_used= false;
name_visibility_map= 0; name_visibility_map.clear_all();
with_dep= 0; with_dep= 0;
join= 0; join= 0;
lock_type= TL_READ_DEFAULT; lock_type= TL_READ_DEFAULT;

View File

@ -33,6 +33,10 @@
#include "sql_tvc.h" #include "sql_tvc.h"
#include "item.h" #include "item.h"
/* Used for flags of nesting constructs */
#define SELECT_NESTING_MAP_SIZE 64
typedef Bitmap<SELECT_NESTING_MAP_SIZE> nesting_map;
/* YACC and LEX Definitions */ /* YACC and LEX Definitions */

View File

@ -857,7 +857,7 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
const bool save_agg_field= thd->lex->current_select->non_agg_field_used(); const bool save_agg_field= thd->lex->current_select->non_agg_field_used();
const bool save_agg_func= thd->lex->current_select->agg_func_used(); const bool save_agg_func= thd->lex->current_select->agg_func_used();
const nesting_map saved_allow_sum_func= thd->lex->allow_sum_func; const nesting_map saved_allow_sum_func= thd->lex->allow_sum_func;
thd->lex->allow_sum_func= 0; thd->lex->allow_sum_func.clear_all();
if (likely(!(error= func_expr->fix_fields_if_needed(thd, (Item**)&func_expr)))) if (likely(!(error= func_expr->fix_fields_if_needed(thd, (Item**)&func_expr))))
func_expr->walk(&Item::post_fix_fields_part_expr_processor, 0, NULL); func_expr->walk(&Item::post_fix_fields_part_expr_processor, 0, NULL);

View File

@ -3041,7 +3041,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
lex->result->cleanup(); lex->result->cleanup();
lex->result->set_thd(thd); lex->result->set_thd(thd);
} }
lex->allow_sum_func= 0; lex->allow_sum_func.clear_all();
lex->in_sum_func= NULL; lex->in_sum_func= NULL;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }

View File

@ -645,7 +645,7 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
const bool saved_non_agg_field_used= select->non_agg_field_used(); const bool saved_non_agg_field_used= select->non_agg_field_used();
DBUG_ENTER("setup_without_group"); DBUG_ENTER("setup_without_group");
thd->lex->allow_sum_func&= ~((nesting_map)1 << select->nest_level); thd->lex->allow_sum_func.clear_bit(select->nest_level);
res= setup_conds(thd, tables, leaves, conds); res= setup_conds(thd, tables, leaves, conds);
if (thd->lex->current_select->first_cond_optimization) if (thd->lex->current_select->first_cond_optimization)
{ {
@ -658,18 +658,18 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
/* it's not wrong to have non-aggregated columns in a WHERE */ /* it's not wrong to have non-aggregated columns in a WHERE */
select->set_non_agg_field_used(saved_non_agg_field_used); select->set_non_agg_field_used(saved_non_agg_field_used);
thd->lex->allow_sum_func|= (nesting_map)1 << select->nest_level; thd->lex->allow_sum_func.set_bit(select->nest_level);
save_place= thd->lex->current_select->context_analysis_place; save_place= thd->lex->current_select->context_analysis_place;
thd->lex->current_select->context_analysis_place= IN_ORDER_BY; thd->lex->current_select->context_analysis_place= IN_ORDER_BY;
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields, res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
order); order);
thd->lex->allow_sum_func&= ~((nesting_map)1 << select->nest_level); thd->lex->allow_sum_func.clear_bit(select->nest_level);
thd->lex->current_select->context_analysis_place= IN_GROUP_BY; thd->lex->current_select->context_analysis_place= IN_GROUP_BY;
res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields, res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields,
group, hidden_group_fields); group, hidden_group_fields);
thd->lex->current_select->context_analysis_place= save_place; thd->lex->current_select->context_analysis_place= save_place;
thd->lex->allow_sum_func|= (nesting_map)1 << select->nest_level; thd->lex->allow_sum_func.set_bit(select->nest_level);
res= res || setup_windows(thd, ref_pointer_array, tables, fields, all_fields, res= res || setup_windows(thd, ref_pointer_array, tables, fields, all_fields,
win_specs, win_funcs); win_specs, win_funcs);
thd->lex->allow_sum_func= save_allow_sum_func; thd->lex->allow_sum_func= save_allow_sum_func;
@ -1117,7 +1117,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
select_lex->master_unit()->global_parameters()) select_lex->master_unit()->global_parameters())
{ {
nesting_map save_allow_sum_func= thd->lex->allow_sum_func; nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
thd->lex->allow_sum_func|= (nesting_map)1 << select_lex->nest_level; thd->lex->allow_sum_func.set_bit(select_lex->nest_level);
thd->where= "order clause"; thd->where= "order clause";
for (ORDER *order= select_lex->order_list.first; order; order= order->next) for (ORDER *order= select_lex->order_list.first; order; order= order->next)
{ {
@ -1135,7 +1135,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
{ {
nesting_map save_allow_sum_func= thd->lex->allow_sum_func; nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
thd->where="having clause"; thd->where="having clause";
thd->lex->allow_sum_func|= (nesting_map)1 << select_lex_arg->nest_level; thd->lex->allow_sum_func.set_bit(select_lex_arg->nest_level);
select_lex->having_fix_field= 1; select_lex->having_fix_field= 1;
/* /*
Wrap alone field in HAVING clause in case it will be outer field Wrap alone field in HAVING clause in case it will be outer field

View File

@ -1255,7 +1255,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
table_list->register_want_access(SELECT_ACL); table_list->register_want_access(SELECT_ACL);
#endif #endif
thd->lex->allow_sum_func= 0; thd->lex->allow_sum_func.clear_all();
/* /*
We do not call DT_MERGE_FOR_INSERT because it has no sense for simple We do not call DT_MERGE_FOR_INSERT because it has no sense for simple