Browse Source

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

pull/933/head
Oleksandr Byelkin 7 years ago
parent
commit
54b2e1c1be
  1. 1
      include/my_global.h
  2. 21
      mysql-test/main/parser.result
  3. 17
      mysql-test/main/parser.test
  4. 3
      sql/item_subselect.cc
  5. 24
      sql/item_sum.cc
  6. 3
      sql/sql_base.cc
  7. 2
      sql/sql_const.h
  8. 2
      sql/sql_delete.cc
  9. 4
      sql/sql_lex.cc
  10. 4
      sql/sql_lex.h
  11. 2
      sql/sql_partition.cc
  12. 2
      sql/sql_prepare.cc
  13. 12
      sql/sql_select.cc
  14. 2
      sql/sql_update.cc

1
include/my_global.h

@ -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;

21
mysql-test/main/parser.result

@ -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

17
mysql-test/main/parser.test

@ -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

3
sql/item_subselect.cc

@ -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|=
(nesting_map)1 << thd->lex->current_select->nest_level;
thd->lex->allow_sum_func.set_bit(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

24
sql/item_sum.cc

@ -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 &
curr_sel->name_visibility_map);
nesting_map allow_sum_func(thd->lex->allow_sum_func);
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

3
sql/sql_base.cc

@ -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|=
(nesting_map)1 << thd->lex->current_select->nest_level;
thd->lex->allow_sum_func.set_bit(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;

2
sql/sql_const.h

@ -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

2
sql/sql_delete.cc

@ -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,

4
sql/sql_lex.cc

@ -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;

4
sql/sql_lex.h

@ -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 */

2
sql/sql_partition.cc

@ -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);

2
sql/sql_prepare.cc

@ -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;
} }

12
sql/sql_select.cc

@ -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

2
sql/sql_update.cc

@ -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

Loading…
Cancel
Save