summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2020-06-30 15:20:11 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2020-07-03 20:17:20 +0200
commit94da0ff82e1f795644c5e9416518073d7d4ea8c8 (patch)
treef96bc393a8b8a1b03d7a90a85adfb1fd2f1411d3
parent263f8aff651edf1e43e385b7390c0e67ae51d358 (diff)
downloadmariadb-git-bb-10.5-virtual.tar.gz
MDEV-23071 remove potentially dangerouws casting to Item_in_subselectbb-10.5-virtual
Remove types casting with a help of virtual functions.
-rw-r--r--sql/item.h15
-rw-r--r--sql/item_cmpfunc.cc28
-rw-r--r--sql/item_cmpfunc.h6
-rw-r--r--sql/item_subselect.cc53
-rw-r--r--sql/item_subselect.h31
-rw-r--r--sql/opt_subselect.cc107
-rw-r--r--sql/sql_base.cc11
-rw-r--r--sql/sql_lex.cc11
-rw-r--r--sql/sql_select.cc11
9 files changed, 155 insertions, 118 deletions
diff --git a/sql/item.h b/sql/item.h
index 8118b079ca1..ad746a4c3eb 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1841,6 +1841,18 @@ public:
*/
virtual void top_level_item() {}
/*
+ Return TRUE if it is item of top WHERE level (AND/OR) and it is
+ important, return FALSE if it not important (we can not use to simplify
+ calculations) or not top level
+ */
+ virtual bool is_top_level_item() const
+ { return FALSE; /* not important */}
+ /*
+ return IN/ALL/ANY subquery or NULL
+ */
+ virtual Item_in_subselect* get_IN_subquery()
+ { return NULL; /* in is not IN/ALL/ANY */ }
+ /*
set field of temporary table for Item which can be switched on temporary
table during query processing (grouping and so on)
*/
@@ -2435,7 +2447,8 @@ public:
}
bool pushable_cond_checker_for_subquery(uchar *arg)
{
- return excl_dep_on_in_subq_left_part((Item_in_subselect *)arg);
+ DBUG_ASSERT(((Item*) arg)->get_IN_subquery());
+ return excl_dep_on_in_subq_left_part(((Item*)arg)->get_IN_subquery());
}
Item *build_pushable_cond(THD *thd,
Pushdown_checker checker,
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 24914accc6f..8203af5c7dc 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1197,11 +1197,9 @@ longlong Item_func_truth::val_int()
}
-bool Item_in_optimizer::is_top_level_item()
+bool Item_in_optimizer::is_top_level_item() const
{
- if (invisible_mode())
- return FALSE;
- return ((Item_in_subselect *)args[1])->is_top_level_item();
+ return args[1]->is_top_level_item();
}
@@ -1265,10 +1263,9 @@ void Item_in_optimizer::print(String *str, enum_query_type query_type)
void Item_in_optimizer::restore_first_argument()
{
- if (!invisible_mode())
- {
- args[0]= ((Item_in_subselect *)args[1])->left_expr;
- }
+ Item_in_subselect *in_subs= args[1]->get_IN_subquery();
+ if (in_subs)
+ args[0]= in_subs->left_exp();
}
@@ -1292,8 +1289,8 @@ bool Item_in_optimizer::fix_left(THD *thd)
the pointer to the post-transformation item. Because of that, on the
next execution we need to copy args[1]->left_expr again.
*/
- ref0= &(((Item_in_subselect *)args[1])->left_expr);
- args[0]= ((Item_in_subselect *)args[1])->left_expr;
+ ref0= args[1]->get_IN_subquery()->left_exp_ptr();
+ args[0]= (*ref0);
}
if ((*ref0)->fix_fields_if_needed(thd, ref0) ||
(!cache && !(cache= (*ref0)->get_cache(thd))))
@@ -1419,9 +1416,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
bool Item_in_optimizer::invisible_mode()
{
/* MAX/MIN transformed or EXISTS->IN prepared => do nothing */
- return (args[1]->type() != Item::SUBSELECT_ITEM ||
- ((Item_subselect *)args[1])->substype() ==
- Item_subselect::EXISTS_SUBS);
+ return (args[1]->get_IN_subquery() == NULL);
}
@@ -1583,7 +1578,7 @@ longlong Item_in_optimizer::val_int()
"<outer_value_list> [NOT] IN (SELECT <inner_value_list>...)"
where one or more of the outer values is NULL.
*/
- if (((Item_in_subselect*)args[1])->is_top_level_item())
+ if (args[1]->is_top_level_item())
{
/*
We're evaluating a top level item, e.g.
@@ -1606,7 +1601,7 @@ longlong Item_in_optimizer::val_int()
SELECT evaluated over the non-NULL values produces at least
one row, FALSE otherwise
*/
- Item_in_subselect *item_subs=(Item_in_subselect*)args[1];
+ Item_in_subselect *item_subs= args[1]->get_IN_subquery();
bool all_left_cols_null= true;
const uint ncols= cache->cols();
@@ -1752,8 +1747,7 @@ Item *Item_in_optimizer::transform(THD *thd, Item_transformer transformer,
((Item_subselect*)(args[1]))->substype() ==
Item_subselect::ANY_SUBS));
- Item_in_subselect *in_arg= (Item_in_subselect*)args[1];
- thd->change_item_tree(&in_arg->left_expr, args[0]);
+ thd->change_item_tree(args[1]->get_IN_subquery()->left_exp_ptr(), args[0]);
}
return (this->*transformer)(thd, argument);
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 6d02d6642e2..4b64ac82c72 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -384,7 +384,7 @@ public:
void set_join_tab_idx(uint join_tab_idx_arg)
{ args[1]->set_join_tab_idx(join_tab_idx_arg); }
virtual void get_cache_parameters(List<Item> &parameters);
- bool is_top_level_item();
+ bool is_top_level_item() const override;
bool eval_not_null_tables(void *opt_arg);
bool find_not_null_fields(table_map allowed);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
@@ -602,7 +602,7 @@ public:
Item_func_not(THD *thd, Item *a):
Item_bool_func(thd, a), abort_on_null(FALSE) {}
virtual void top_level_item() { abort_on_null= 1; }
- bool is_top_level_item() { return abort_on_null; }
+ bool is_top_level_item() const override { return abort_on_null; }
longlong val_int();
enum Functype functype() const { return NOT_FUNC; }
const char *func_name() const { return "not"; }
@@ -890,7 +890,7 @@ public:
Item_bool_func(thd, list), negated(0), pred_level(0) {}
public:
inline void top_level_item() { pred_level= 1; }
- bool is_top_level_item() const { return pred_level; }
+ bool is_top_level_item() const override { return pred_level; }
Item *neg_transformer(THD *thd)
{
negated= !negated;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 23ff906e3cf..9bf6ab3b797 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -4141,7 +4141,8 @@ int subselect_uniquesubquery_engine::exec()
TABLE *table= tab->table;
empty_result_set= TRUE;
table->status= 0;
- Item_in_subselect *in_subs= (Item_in_subselect *) item;
+ Item_in_subselect *in_subs= item->get_IN_subquery();
+ DBUG_ASSERT(in_subs);
if (!tab->preread_init_done && tab->preread_init())
DBUG_RETURN(1);
@@ -4186,11 +4187,11 @@ int subselect_uniquesubquery_engine::exec()
table->null_row= 0;
if (!table->status && (!cond || cond->val_int()))
{
- ((Item_in_subselect *) item)->value= 1;
+ in_subs->value= 1;
empty_result_set= FALSE;
}
else
- ((Item_in_subselect *) item)->value= 0;
+ in_subs->value= 0;
}
DBUG_RETURN(error != 0);
@@ -4229,9 +4230,9 @@ int subselect_uniquesubquery_engine::index_lookup()
table->null_row= 0;
if (!error && (!cond || cond->val_int()))
- ((Item_in_subselect *) item)->value= 1;
+ item->get_IN_subquery()->value= 1;
else
- ((Item_in_subselect *) item)->value= 0;
+ item->get_IN_subquery()->value= 0;
DBUG_RETURN(0);
}
@@ -4301,9 +4302,9 @@ int subselect_indexsubquery_engine::exec()
int error;
bool null_finding= 0;
TABLE *table= tab->table;
- Item_in_subselect *in_subs= (Item_in_subselect *) item;
+ Item_in_subselect *in_subs= item->get_IN_subquery();
- ((Item_in_subselect *) item)->value= 0;
+ in_subs->value= 0;
empty_result_set= TRUE;
table->status= 0;
@@ -4311,7 +4312,7 @@ int subselect_indexsubquery_engine::exec()
{
/* We need to check for NULL if there wasn't a matching value */
*tab->ref.null_ref_key= 0; // Search first for not null
- ((Item_in_subselect *) item)->was_null= 0;
+ in_subs->was_null= 0;
}
if (!tab->preread_init_done && tab->preread_init())
@@ -4363,9 +4364,9 @@ int subselect_indexsubquery_engine::exec()
{
empty_result_set= FALSE;
if (null_finding)
- ((Item_in_subselect *) item)->was_null= 1;
+ in_subs->was_null= 1;
else
- ((Item_in_subselect *) item)->value= 1;
+ in_subs->value= 1;
break;
}
error= table->file->ha_index_next_same(table->record[0],
@@ -4751,7 +4752,7 @@ bool subselect_uniquesubquery_engine::no_tables()
subselect_hash_sj_engine::exec_strategy
subselect_hash_sj_engine::get_strategy_using_schema()
{
- Item_in_subselect *item_in= (Item_in_subselect *) item;
+ Item_in_subselect *item_in= item->get_IN_subquery();
if (item_in->is_top_level_item())
return COMPLETE_MATCH;
@@ -4798,7 +4799,7 @@ subselect_hash_sj_engine::get_strategy_using_schema()
subselect_hash_sj_engine::exec_strategy
subselect_hash_sj_engine::get_strategy_using_data()
{
- Item_in_subselect *item_in= (Item_in_subselect *) item;
+ Item_in_subselect *item_in= item->get_IN_subquery();
select_materialize_with_stats *result_sink=
(select_materialize_with_stats *) result;
Item *outer_col;
@@ -5049,8 +5050,9 @@ bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id)
DBUG_RETURN(TRUE);
result_sink->get_tmp_table_param()->materialized_subquery= true;
- if (item->substype() == Item_subselect::IN_SUBS &&
- ((Item_in_subselect*)item)->is_jtbm_merged)
+
+ if (item->substype() == Item_subselect::IN_SUBS &&
+ (item->get_IN_subquery()->is_jtbm_merged))
{
result_sink->get_tmp_table_param()->force_not_null_cols= true;
}
@@ -5090,9 +5092,12 @@ bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id)
/*
Make sure there is only one index on the temp table, and it doesn't have
the extra key part created when s->uniques > 0.
+
+ NOTE: item have to be Item_in_subselect, because class constructor
+ accept Item_in_subselect as the parmeter.
*/
DBUG_ASSERT(tmp_table->s->keys == 1 &&
- ((Item_in_subselect *) item)->left_expr->cols() ==
+ item->get_IN_subquery()->left_expr->cols() ==
tmp_table->key_info->user_defined_key_parts);
if (make_semi_join_conds() ||
@@ -5141,7 +5146,7 @@ bool subselect_hash_sj_engine::make_semi_join_conds()
TABLE_LIST *tmp_table_ref;
/* Name resolution context for all tmp_table columns created below. */
Name_resolution_context *context;
- Item_in_subselect *item_in= (Item_in_subselect *) item;
+ Item_in_subselect *item_in= item->get_IN_subquery();
LEX_CSTRING table_name;
DBUG_ENTER("subselect_hash_sj_engine::make_semi_join_conds");
DBUG_ASSERT(semi_join_conds == NULL);
@@ -5203,7 +5208,7 @@ bool subselect_hash_sj_engine::make_semi_join_conds()
subselect_uniquesubquery_engine*
subselect_hash_sj_engine::make_unique_engine()
{
- Item_in_subselect *item_in= (Item_in_subselect *) item;
+ Item_in_subselect *item_in= item->get_IN_subquery();
Item_iterator_row it(item_in->left_expr);
/* The only index on the temporary table. */
KEY *tmp_key= tmp_table->key_info;
@@ -5225,7 +5230,7 @@ subselect_hash_sj_engine::make_unique_engine()
tab->preread_init_done= FALSE;
tab->ref.tmp_table_index_lookup_init(thd, tmp_key, it, FALSE);
- DBUG_RETURN(new subselect_uniquesubquery_engine(thd, tab, item,
+ DBUG_RETURN(new subselect_uniquesubquery_engine(thd, tab, item_in,
semi_join_conds));
}
@@ -5272,7 +5277,7 @@ void subselect_hash_sj_engine::cleanup()
at parse time and stored across executions, while all other materialization
related engines are created and chosen for each execution.
*/
- ((Item_in_subselect *) item)->engine= materialize_engine;
+ item->get_IN_subquery()->engine= materialize_engine;
if (lookup_engine_type == TABLE_SCAN_ENGINE ||
lookup_engine_type == ROWID_MERGE_ENGINE)
{
@@ -5512,7 +5517,7 @@ double get_post_group_estimate(JOIN* join, double join_op_rows)
int subselect_hash_sj_engine::exec()
{
- Item_in_subselect *item_in= (Item_in_subselect *) item;
+ Item_in_subselect *item_in= item->get_IN_subquery();
SELECT_LEX *save_select= thd->lex->current_select;
subselect_partial_match_engine *pm_engine= NULL;
int res= 0;
@@ -6129,7 +6134,7 @@ subselect_partial_match_engine::subselect_partial_match_engine(
int subselect_partial_match_engine::exec()
{
- Item_in_subselect *item_in= (Item_in_subselect *) item;
+ Item_in_subselect *item_in= item->get_IN_subquery();
int lookup_res;
DBUG_ASSERT(!(item_in->left_expr_has_null() &&
@@ -6251,7 +6256,7 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts,
select_materialize_with_stats *result_sink=
(select_materialize_with_stats *) result;
uint cur_keyid= 0;
- Item_in_subselect *item_in= (Item_in_subselect*) item;
+ Item *left= item->get_IN_subquery()->left_exp();
int error;
if (merge_keys_count == 0)
@@ -6286,7 +6291,7 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts,
/* Create the only non-NULL key if there is any. */
if (non_null_key_parts)
{
- non_null_key= new Ordered_key(cur_keyid, tmp_table, item_in->left_expr,
+ non_null_key= new Ordered_key(cur_keyid, tmp_table, left,
0, 0, 0, row_num_to_rowid);
if (non_null_key->init(non_null_key_parts))
return TRUE;
@@ -6318,7 +6323,7 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts,
merge_keys[cur_keyid]= new Ordered_key(
cur_keyid, tmp_table,
- item_in->left_expr->element_index(i),
+ left->element_index(i),
result_sink->get_null_count_of_col(i),
result_sink->get_min_null_of_col(i),
result_sink->get_max_null_of_col(i),
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 8f6e4836ac7..e2c82554b73 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -151,9 +151,7 @@ public:
virtual subs_type substype() { return UNKNOWN_SUBS; }
bool is_in_predicate()
{
- return (substype() == Item_subselect::IN_SUBS ||
- substype() == Item_subselect::ALL_SUBS ||
- substype() == Item_subselect::ANY_SUBS);
+ return get_IN_subquery() != NULL;
}
/*
@@ -416,7 +414,7 @@ public:
void print(String *str, enum_query_type query_type);
bool select_transformer(JOIN *join);
void top_level_item() { abort_on_null=1; }
- inline bool is_top_level_item() { return abort_on_null; }
+ bool is_top_level_item() const override { return abort_on_null; }
bool exists2in_processor(void *opt_arg);
Item* expr_cache_insert_transformer(THD *thd, uchar *unused);
@@ -507,7 +505,6 @@ protected:
bool create_row_in_to_exists_cond(JOIN * join,
Item **where_item,
Item **having_item);
-public:
Item *left_expr;
/*
Important for PS/SP: left_expr_orig is the item that left_expr originally
@@ -515,6 +512,7 @@ public:
left_expr could later be changed to something on the execution arena.
*/
Item *left_expr_orig;
+public:
/* Priority of this predicate in the convert-to-semi-join-nest process. */
int sj_convert_priority;
/* May be TRUE only for the candidates to semi-join conversion */
@@ -752,6 +750,15 @@ public:
bool pushdown_cond_for_in_subquery(THD *thd, Item *cond);
+ Item_in_subselect *get_IN_subquery() override
+ { return this; }
+ inline Item** left_exp_ptr()
+ { return &left_expr; }
+ inline Item* left_exp() const
+ { return left_expr; }
+ inline Item* left_exp_orig() const
+ { return left_expr_orig; }
+
friend class Item_ref_null_helper;
friend class Item_is_not_null_test;
friend class Item_in_optimizer;
@@ -964,9 +971,9 @@ public:
// constructor can assign THD because it will be called after JOIN::prepare
subselect_uniquesubquery_engine(THD *thd_arg, st_join_table *tab_arg,
- Item_subselect *subs, Item *where)
+ Item_in_subselect *subs, Item *where)
:subselect_engine(subs, 0), tab(tab_arg), cond(where)
- {}
+ { DBUG_ASSERT(subs); }
~subselect_uniquesubquery_engine();
void cleanup();
int prepare(THD *);
@@ -1027,12 +1034,12 @@ public:
// constructor can assign THD because it will be called after JOIN::prepare
subselect_indexsubquery_engine(THD *thd_arg, st_join_table *tab_arg,
- Item_subselect *subs, Item *where,
+ Item_in_subselect *subs, Item *where,
Item *having_arg, bool chk_null)
:subselect_uniquesubquery_engine(thd_arg, tab_arg, subs, where),
check_null(chk_null),
having(having_arg)
- {}
+ { DBUG_ASSERT(subs); }
int exec();
void print (String *str, enum_query_type query_type);
virtual enum_engine_type engine_type() { return INDEXSUBQUERY_ENGINE; }
@@ -1095,14 +1102,14 @@ public:
Name_resolution_context *semi_join_conds_context;
- subselect_hash_sj_engine(THD *thd_arg, Item_subselect *in_predicate,
+ subselect_hash_sj_engine(THD *thd_arg, Item_in_subselect *in_predicate,
subselect_single_select_engine *old_engine)
: subselect_engine(in_predicate, NULL),
tmp_table(NULL), is_materialized(FALSE), materialize_engine(old_engine),
materialize_join(NULL), semi_join_conds(NULL), lookup_engine(NULL),
count_partial_match_columns(0), count_null_only_columns(0),
count_columns_with_nulls(0), strategy(UNDEFINED)
- {}
+ { DBUG_ASSERT(in_predicate); }
~subselect_hash_sj_engine();
bool init(List<Item> *tmp_columns, uint subquery_id);
@@ -1410,7 +1417,7 @@ public:
from Item_in_optimizer::val_int() sets Item_in_optimizer::null_value
correctly.
*/
- return !(((Item_in_subselect *) item)->null_value);
+ return !(item->get_IN_subquery()->null_value);
}
void print(String*, enum_query_type);
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 1e0a5398f6a..8e2467b813a 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -592,10 +592,11 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
Item_subselect::subs_type substype= subselect->substype();
switch (substype) {
case Item_subselect::IN_SUBS:
- in_subs= (Item_in_subselect *)subselect;
+ in_subs= subselect->get_IN_subquery();
break;
case Item_subselect::ALL_SUBS:
case Item_subselect::ANY_SUBS:
+ DBUG_ASSERT(subselect->get_IN_subquery());
allany_subs= (Item_allany_subselect *)subselect;
break;
default:
@@ -640,13 +641,15 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
char const *save_where= thd->where;
thd->where= "IN/ALL/ANY subquery";
- bool failure= in_subs->left_expr->fix_fields_if_needed(thd,
- &in_subs->left_expr);
+ Item **left= in_subs->left_exp_ptr();
+ bool failure= (*left)->fix_fields_if_needed(thd, left);
thd->lex->current_select= current;
thd->where= save_where;
if (failure)
DBUG_RETURN(-1); /* purecov: deadcode */
+ // fix_field above can rewrite left expression
+ uint ncols= (*left)->cols();
/*
Check if the left and right expressions have the same # of
columns, i.e. we don't have a case like
@@ -655,9 +658,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
TODO why do we have this duplicated in IN->EXISTS transformers?
psergey-todo: fix these: grep for duplicated_subselect_card_check
*/
- if (select_lex->item_list.elements != in_subs->left_expr->cols())
+ if (select_lex->item_list.elements != ncols)
{
- my_error(ER_OPERAND_COLUMNS, MYF(0), in_subs->left_expr->cols());
+ my_error(ER_OPERAND_COLUMNS, MYF(0), ncols);
DBUG_RETURN(-1);
}
}
@@ -847,9 +850,10 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
static
bool subquery_types_allow_materialization(THD* thd, Item_in_subselect *in_subs)
{
+ Item *left_exp= in_subs->left_exp();
DBUG_ENTER("subquery_types_allow_materialization");
- DBUG_ASSERT(in_subs->left_expr->is_fixed());
+ DBUG_ASSERT(left_exp->is_fixed());
List_iterator<Item> it(in_subs->unit->first_select()->item_list);
uint elements= in_subs->unit->first_select()->item_list.elements;
@@ -871,7 +875,7 @@ bool subquery_types_allow_materialization(THD* thd, Item_in_subselect *in_subs)
uint32 total_key_length = 0;
for (uint i= 0; i < elements; i++)
{
- Item *outer= in_subs->left_expr->element_index(i);
+ Item *outer= left_exp->element_index(i);
Item *inner= it++;
all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM &&
inner->real_item()->type() == Item::FIELD_ITEM);
@@ -1706,7 +1710,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
sj_nest->alias= sj_nest_name;
sj_nest->sj_subq_pred= subq_pred;
sj_nest->original_subq_pred_used_tables= subq_pred->used_tables() |
- subq_pred->left_expr->used_tables();
+ subq_pred->left_exp()->used_tables();
/* Nests do not participate in those 'chains', so: */
/* sj_nest->next_leaf= sj_nest->next_local= sj_nest->next_global == NULL*/
emb_join_list->push_back(sj_nest, thd->mem_root);
@@ -1794,14 +1798,17 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
*/
SELECT_LEX *save_lex= thd->lex->current_select;
thd->lex->current_select=subq_lex;
- if (subq_pred->left_expr->fix_fields_if_needed(thd, &subq_pred->left_expr))
+ Item **left= subq_pred->left_exp_ptr();
+ if ((*left)->fix_fields_if_needed(thd, left))
DBUG_RETURN(TRUE);
+ Item *left_exp= *left;
+ Item *left_exp_orig= subq_pred->left_exp_orig();
thd->lex->current_select=save_lex;
table_map subq_pred_used_tables= subq_pred->used_tables();
sj_nest->nested_join->sj_corr_tables= subq_pred_used_tables;
sj_nest->nested_join->sj_depends_on= subq_pred_used_tables |
- subq_pred->left_expr->used_tables();
+ left_exp->used_tables();
sj_nest->sj_on_expr= subq_lex->join->conds;
/*
@@ -1819,14 +1826,14 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
Item_direct_view_refs doesn't substitute itself with anything in
Item_direct_view_ref::fix_fields.
*/
- sj_nest->sj_in_exprs= subq_pred->left_expr->cols();
+ uint ncols= sj_nest->sj_in_exprs= left_exp->cols();
sj_nest->nested_join->sj_outer_expr_list.empty();
reset_equality_number_for_subq_conds(sj_nest->sj_on_expr);
- if (subq_pred->left_expr->cols() == 1)
+ if (ncols == 1)
{
/* add left = select_list_element */
- nested_join->sj_outer_expr_list.push_back(&subq_pred->left_expr,
+ nested_join->sj_outer_expr_list.push_back(left,
thd->mem_root);
/*
Create Item_func_eq. Note that
@@ -1838,36 +1845,36 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
with thd->change_item_tree
*/
Item_func_eq *item_eq=
- new (thd->mem_root) Item_func_eq(thd, subq_pred->left_expr_orig,
+ new (thd->mem_root) Item_func_eq(thd, left_exp_orig,
subq_lex->ref_pointer_array[0]);
if (!item_eq)
DBUG_RETURN(TRUE);
- if (subq_pred->left_expr_orig != subq_pred->left_expr)
- thd->change_item_tree(item_eq->arguments(), subq_pred->left_expr);
+ if (left_exp_orig != left_exp)
+ thd->change_item_tree(item_eq->arguments(), left_exp);
item_eq->in_equality_no= 0;
sj_nest->sj_on_expr= and_items(thd, sj_nest->sj_on_expr, item_eq);
}
- else if (subq_pred->left_expr->type() == Item::ROW_ITEM)
+ else if (left_exp->type() == Item::ROW_ITEM)
{
/*
disassemple left expression and add
left1 = select_list_element1 and left2 = select_list_element2 ...
*/
- for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
+ for (uint i= 0; i < ncols; i++)
{
- nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr->addr(i),
+ nested_join->sj_outer_expr_list.push_back(left_exp->addr(i),
thd->mem_root);
Item_func_eq *item_eq=
new (thd->mem_root)
- Item_func_eq(thd, subq_pred->left_expr_orig->element_index(i),
+ Item_func_eq(thd, left_exp_orig->element_index(i),
subq_lex->ref_pointer_array[i]);
if (!item_eq)
DBUG_RETURN(TRUE);
- DBUG_ASSERT(subq_pred->left_expr->element_index(i)->is_fixed());
- if (subq_pred->left_expr_orig->element_index(i) !=
- subq_pred->left_expr->element_index(i))
+ DBUG_ASSERT(left_exp->element_index(i)->is_fixed());
+ if (left_exp_orig->element_index(i) !=
+ left_exp->element_index(i))
thd->change_item_tree(item_eq->arguments(),
- subq_pred->left_expr->element_index(i));
+ left_exp->element_index(i));
item_eq->in_equality_no= i;
sj_nest->sj_on_expr= and_items(thd, sj_nest->sj_on_expr, item_eq);
}
@@ -1882,10 +1889,10 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
/* fix fields on subquery was call so they should be the same */
if (!row)
DBUG_RETURN(TRUE);
- DBUG_ASSERT(subq_pred->left_expr->cols() == row->cols());
- nested_join->sj_outer_expr_list.push_back(&subq_pred->left_expr);
+ DBUG_ASSERT(ncols == row->cols());
+ nested_join->sj_outer_expr_list.push_back(left);
Item_func_eq *item_eq=
- new (thd->mem_root) Item_func_eq(thd, subq_pred->left_expr_orig, row);
+ new (thd->mem_root) Item_func_eq(thd, left_exp_orig, row);
if (!item_eq)
DBUG_RETURN(TRUE);
for (uint i= 0; i < row->cols(); i++)
@@ -4140,7 +4147,8 @@ bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab)
for (i= 0; i < tmp_key_parts; i++, cur_key_part++, ref_key++)
{
- tab_ref->items[i]= emb_sj_nest->sj_subq_pred->left_expr->element_index(i);
+ tab_ref->items[i]=
+ emb_sj_nest->sj_subq_pred->left_exp()->element_index(i);
int null_count= MY_TEST(cur_key_part->field->real_maybe_null());
*ref_key= new store_key_item(thd, cur_key_part->field,
/* TODO:
@@ -4325,18 +4333,20 @@ static Item *create_subq_in_equalities(THD *thd, SJ_MATERIALIZATION_INFO *sjm,
Item_in_subselect *subq_pred)
{
Item *res= NULL;
- if (subq_pred->left_expr->cols() == 1)
+ Item *left_exp= subq_pred->left_exp();
+ uint ncols= left_exp->cols();
+ if (ncols == 1)
{
- if (!(res= new (thd->mem_root) Item_func_eq(thd, subq_pred->left_expr,
+ if (!(res= new (thd->mem_root) Item_func_eq(thd, left_exp,
new (thd->mem_root) Item_field(thd, sjm->table->field[0]))))
return NULL; /* purecov: inspected */
}
else
{
Item *conj;
- for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
+ for (uint i= 0; i < ncols; i++)
{
- if (!(conj= new (thd->mem_root) Item_func_eq(thd, subq_pred->left_expr->element_index(i),
+ if (!(conj= new (thd->mem_root) Item_func_eq(thd, left_exp->element_index(i),
new (thd->mem_root) Item_field(thd, sjm->table->field[i]))) ||
!(res= and_items(thd, res, conj)))
return NULL; /* purecov: inspected */
@@ -5404,7 +5414,7 @@ int rewrite_to_index_subquery_engine(JOIN *join)
change_engine(new
subselect_uniquesubquery_engine(thd,
join_tab,
- unit->item,
+ unit->item->get_IN_subquery(),
where)));
}
else if (join_tab[0].type == JT_REF &&
@@ -5418,7 +5428,7 @@ int rewrite_to_index_subquery_engine(JOIN *join)
change_engine(new
subselect_indexsubquery_engine(thd,
join_tab,
- unit->item,
+ unit->item->get_IN_subquery(),
where,
NULL,
0)));
@@ -5434,7 +5444,7 @@ int rewrite_to_index_subquery_engine(JOIN *join)
DBUG_RETURN(unit->item->
change_engine(new subselect_indexsubquery_engine(thd,
join_tab,
- unit->item,
+ unit->item->get_IN_subquery(),
join->conds,
join->having,
1)));
@@ -6109,11 +6119,13 @@ bool execute_degenerate_jtbm_semi_join(THD *thd,
subq_pred->jtbm_const_row_found= TRUE;
Item *eq_cond;
- for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
+ Item *left_exp= subq_pred->left_exp();
+ uint ncols= left_exp->cols();
+ for (uint i= 0; i < ncols; i++)
{
eq_cond=
new (thd->mem_root) Item_func_eq(thd,
- subq_pred->left_expr->element_index(i),
+ left_exp->element_index(i),
new_sink->row[i]);
if (!eq_cond || eq_cond->fix_fields(thd, NULL) ||
eq_list.push_back(eq_cond, thd->mem_root))
@@ -6408,7 +6420,7 @@ bool JOIN::choose_subquery_plan(table_map join_tables)
if (is_in_subquery())
{
- in_subs= (Item_in_subselect*) unit->item;
+ in_subs= unit->item->get_IN_subquery();
if (in_subs->create_in_to_exists_cond(this))
return true;
}
@@ -6692,12 +6704,12 @@ bool JOIN::choose_tableless_subquery_plan()
everything as-is, setup_jtbm_semi_joins() has special handling for cases
like this.
*/
- if (subs_predicate->is_in_predicate() &&
- !(subs_predicate->substype() == Item_subselect::IN_SUBS &&
- ((Item_in_subselect*)subs_predicate)->is_jtbm_merged))
+ Item_in_subselect *in_subs;
+ in_subs= subs_predicate->get_IN_subquery();
+ if (in_subs &&
+ !(subs_predicate->substype() == Item_subselect::IN_SUBS &&
+ in_subs->is_jtbm_merged))
{
- Item_in_subselect *in_subs;
- in_subs= (Item_in_subselect*) subs_predicate;
in_subs->set_strategy(SUBS_IN_TO_EXISTS);
if (in_subs->create_in_to_exists_cond(this) ||
in_subs->inject_in_to_exists_cond(this))
@@ -6714,7 +6726,8 @@ bool Item::pushable_equality_checker_for_subquery(uchar *arg)
{
return
get_corresponding_field_pair(this,
- ((Item_in_subselect *)arg)->corresponding_fields);
+ ((Item *)arg)->get_IN_subquery()->
+ corresponding_fields);
}
@@ -6853,7 +6866,7 @@ Item *get_corresponding_item(THD *thd, Item *item,
Item *Item_field::in_subq_field_transformer_for_where(THD *thd, uchar *arg)
{
- Item_in_subselect *subq_pred= (Item_in_subselect *)arg;
+ Item_in_subselect *subq_pred= ((Item *)arg)->get_IN_subquery();
Item *producing_item= get_corresponding_item(thd, this, subq_pred);
if (producing_item)
return producing_item->build_clone(thd);
@@ -6866,7 +6879,7 @@ Item *Item_direct_view_ref::in_subq_field_transformer_for_where(THD *thd,
{
if (item_equal)
{
- Item_in_subselect *subq_pred= (Item_in_subselect *)arg;
+ Item_in_subselect *subq_pred= ((Item *)arg)->get_IN_subquery();
Item *producing_item= get_corresponding_item(thd, this, subq_pred);
DBUG_ASSERT (producing_item != NULL);
return producing_item->build_clone(thd);
@@ -6916,6 +6929,7 @@ get_corresponding_item_for_in_subq_having(THD *thd, Item *in_item,
Item *Item_field::in_subq_field_transformer_for_having(THD *thd, uchar *arg)
{
+ DBUG_ASSERT(((Item *)arg)->get_IN_subquery());
return get_corresponding_item_for_in_subq_having(thd, this,
(Item_in_subselect *)arg);
}
@@ -6928,6 +6942,7 @@ Item *Item_direct_view_ref::in_subq_field_transformer_for_having(THD *thd,
return this;
else
{
+ DBUG_ASSERT(((Item *)arg)->get_IN_subquery());
Item *new_item= get_corresponding_item_for_in_subq_having(thd, this,
(Item_in_subselect *)arg);
if (!new_item)
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 88a28c470c0..fb546966bda 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -6328,10 +6328,11 @@ find_field_in_tables(THD *thd, Item_ident *item,
for (SELECT_LEX *sl= current_sel; sl && sl!=last_select;
sl=sl->outer_select())
{
- Item *subs= sl->master_unit()->item;
- if (subs->type() == Item::SUBSELECT_ITEM &&
- ((Item_subselect*)subs)->substype() == Item_subselect::IN_SUBS &&
- ((Item_in_subselect*)subs)->test_strategy(SUBS_SEMI_JOIN))
+ Item_in_subselect *in_subs=
+ sl->master_unit()->item->get_IN_subquery();
+ if (in_subs &&
+ in_subs->substype() == Item_subselect::IN_SUBS &&
+ in_subs->test_strategy(SUBS_SEMI_JOIN))
{
continue;
}
@@ -8230,7 +8231,7 @@ bool setup_on_expr(THD *thd, TABLE_LIST *table, bool is_update)
*/
if (embedded->sj_subq_pred)
{
- Item **left_expr= &embedded->sj_subq_pred->left_expr;
+ Item **left_expr= embedded->sj_subq_pred->left_exp_ptr();
if ((*left_expr)->fix_fields_if_needed(thd, left_expr))
return TRUE;
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index f39f88fe843..4cc93c31b38 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -4740,7 +4740,7 @@ bool st_select_lex::optimize_unflattened_subqueries(bool const_only)
}
if (subquery_predicate->substype() == Item_subselect::IN_SUBS)
{
- Item_in_subselect *in_subs= (Item_in_subselect*) subquery_predicate;
+ Item_in_subselect *in_subs= subquery_predicate->get_IN_subquery();
if (in_subs->is_jtbm_merged)
continue;
}
@@ -5167,7 +5167,7 @@ void SELECT_LEX::update_used_tables()
*/
if (tl->jtbm_subselect)
{
- Item *left_expr= tl->jtbm_subselect->left_expr;
+ Item *left_expr= tl->jtbm_subselect->left_exp();
left_expr->walk(&Item::update_table_bitmaps_processor, FALSE, NULL);
}
@@ -5324,7 +5324,7 @@ void st_select_lex::set_explain_type(bool on_the_fly)
if ((parent_item= master_unit()->item) &&
parent_item->substype() == Item_subselect::IN_SUBS)
{
- Item_in_subselect *in_subs= (Item_in_subselect*)parent_item;
+ Item_in_subselect *in_subs= parent_item->get_IN_subquery();
/*
Surprisingly, in_subs->is_set_strategy() can return FALSE here,
even for the last invocation of this function for the select.
@@ -5613,9 +5613,10 @@ bool st_select_lex::is_merged_child_of(st_select_lex *ancestor)
sl=sl->outer_select())
{
Item *subs= sl->master_unit()->item;
- if (subs && subs->type() == Item::SUBSELECT_ITEM &&
+ Item_in_subselect *in_subs= (subs ? subs->get_IN_subquery() : NULL);
+ if (in_subs &&
((Item_subselect*)subs)->substype() == Item_subselect::IN_SUBS &&
- ((Item_in_subselect*)subs)->test_strategy(SUBS_SEMI_JOIN))
+ in_subs->test_strategy(SUBS_SEMI_JOIN))
{
continue;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 52e6b905638..352d00290df 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1422,7 +1422,7 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && !group_list &&
!(select_lex->master_unit()->item &&
select_lex->master_unit()->item->is_in_predicate() &&
- ((Item_in_subselect*)select_lex->master_unit()->item)->
+ select_lex->master_unit()->item->get_IN_subquery()->
test_set_strategy(SUBS_MAXMIN_INJECTED)) &&
select_lex->non_agg_field_used() &&
select_lex->agg_func_used())
@@ -5043,7 +5043,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
*/
bool skip_unprefixed_keyparts=
!(join->is_in_subquery() &&
- ((Item_in_subselect*)join->unit->item)->test_strategy(SUBS_IN_TO_EXISTS));
+ join->unit->item->get_IN_subquery()->test_strategy(SUBS_IN_TO_EXISTS));
if (keyuse_array->elements &&
sort_and_filter_keyuse(thd, keyuse_array,
@@ -5796,7 +5796,8 @@ static uint get_semi_join_select_list_index(Field *field)
{
Item_in_subselect *subq_pred= emb_sj_nest->sj_subq_pred;
st_select_lex *subq_lex= subq_pred->unit->first_select();
- if (subq_pred->left_expr->cols() == 1)
+ uint ncols= subq_pred->left_exp()->cols();
+ if (ncols == 1)
{
Item *sel_item= subq_lex->ref_pointer_array[0];
if (sel_item->type() == Item::FIELD_ITEM &&
@@ -5807,7 +5808,7 @@ static uint get_semi_join_select_list_index(Field *field)
}
else
{
- for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
+ for (uint i= 0; i < ncols; i++)
{
Item *sel_item= subq_lex->ref_pointer_array[i];
if (sel_item->type() == Item::FIELD_ITEM &&
@@ -21253,7 +21254,7 @@ int join_read_key2(THD *thd, JOIN_TAB *tab, TABLE *table, TABLE_REF *table_ref)
if (tab && tab->bush_children)
{
TABLE_LIST *emb_sj_nest= tab->bush_children->start->emb_sj_nest;
- emb_sj_nest->sj_subq_pred->left_expr->bring_value();
+ emb_sj_nest->sj_subq_pred->left_exp()->bring_value();
}
/* TODO: Why don't we do "Late NULLs Filtering" here? */