mirror of
https://github.com/MariaDB/server.git
synced 2025-01-27 17:33:44 +01:00
MDEV-23071 remove potentially dangerouws casting to Item_in_subselect
Remove types casting with a help of virtual functions.
This commit is contained in:
parent
79c166c56d
commit
846174c5ba
9 changed files with 155 additions and 118 deletions
15
sql/item.h
15
sql/item.h
|
@ -1840,6 +1840,18 @@ public:
|
|||
when they are "top level".
|
||||
*/
|
||||
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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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> ¶meters);
|
||||
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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1425,7 +1425,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())
|
||||
|
@ -5046,7 +5046,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,
|
||||
|
@ -5799,7 +5799,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 &&
|
||||
|
@ -5810,7 +5811,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 &&
|
||||
|
@ -21290,7 +21291,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? */
|
||||
|
|
Loading…
Add table
Reference in a new issue