summaryrefslogtreecommitdiff
path: root/sql/item_subselect.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_subselect.cc')
-rw-r--r--sql/item_subselect.cc171
1 files changed, 107 insertions, 64 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index e12deb22797..7412c517262 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -47,6 +47,8 @@ double get_post_group_estimate(JOIN* join, double join_op_rows);
LEX_CSTRING exists_outer_expr_name= { STRING_WITH_LEN("<exists outer expr>") };
+LEX_CSTRING no_matter_name= {STRING_WITH_LEN("<no matter>") };
+
int check_and_do_in_subquery_rewrites(JOIN *join);
Item_subselect::Item_subselect(THD *thd_arg):
@@ -710,6 +712,40 @@ int walk_items_for_table_list(Item_processor processor,
}
+bool Item_subselect::unknown_splocal_processor(void *argument)
+{
+ SELECT_LEX *sl= unit->first_select();
+ if (sl->top_join_list.elements)
+ return 0;
+ if (sl->tvc && sl->tvc->walk_values(&Item::unknown_splocal_processor,
+ false, argument))
+ return true;
+ for (SELECT_LEX *lex= unit->first_select(); lex; lex= lex->next_select())
+ {
+ /*
+ TODO: walk through GROUP BY and ORDER yet eventually.
+ This will require checking aliases in SELECT list:
+ SELECT 1 AS a GROUP BY a;
+ SELECT 1 AS a ORDER BY a;
+ */
+ List_iterator<Item> li(lex->item_list);
+ Item *item;
+ if (lex->where && (lex->where)->walk(&Item::unknown_splocal_processor,
+ false, argument))
+ return true;
+ if (lex->having && (lex->having)->walk(&Item::unknown_splocal_processor,
+ false, argument))
+ return true;
+ while ((item=li++))
+ {
+ if (item->walk(&Item::unknown_splocal_processor, false, argument))
+ return true;
+ }
+ }
+ return false;
+}
+
+
bool Item_subselect::walk(Item_processor processor, bool walk_subquery,
void *argument)
{
@@ -780,8 +816,8 @@ bool Item_subselect::exec()
QT_WITHOUT_INTRODUCERS));
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
- ER_UNKNOWN_ERROR, "DBUG: Item_subselect::exec %.*s",
- print.length(),print.ptr());
+ ER_UNKNOWN_ERROR, "DBUG: Item_subselect::exec %.*b",
+ print.length(),print.ptr());
);
/*
Do not execute subselect in case of a fatal error
@@ -2027,8 +2063,8 @@ Item_in_subselect::single_value_transformer(JOIN *join)
*/
expr= new (thd->mem_root) Item_direct_ref(thd, &select_lex->context,
(Item**)optimizer->get_cache(),
- "<no matter>",
- &in_left_expr_name);
+ no_matter_name,
+ in_left_expr_name);
}
DBUG_RETURN(false);
@@ -2259,8 +2295,8 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
this,
&select_lex->
ref_pointer_array[0],
- (char *)"<ref>",
- &field_name));
+ {STRING_WITH_LEN("<ref>")},
+ field_name));
if (!abort_on_null && left_expr->maybe_null)
{
/*
@@ -2344,13 +2380,13 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
&select_lex->context,
this,
&select_lex->ref_pointer_array[0],
- (char *)"<no matter>",
- &field_name));
+ no_matter_name,
+ field_name));
if (!abort_on_null && left_expr->maybe_null)
{
disable_cond_guard_for_const_null_left_expr(0);
- if (!(new_having= new (thd->mem_root) Item_func_trig_cond(thd, new_having,
- get_cond_guard(0))))
+ if (!(new_having= new (thd->mem_root)
+ Item_func_trig_cond(thd, new_having, get_cond_guard(0))))
DBUG_RETURN(true);
}
@@ -2527,21 +2563,21 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
Item_direct_ref(thd, &select_lex->context,
(*optimizer->get_cache())->
addr(i),
- (char *)"<no matter>",
- &in_left_expr_name),
+ no_matter_name,
+ in_left_expr_name),
new (thd->mem_root)
Item_ref(thd, &select_lex->context,
&select_lex->ref_pointer_array[i],
- (char *)"<no matter>",
- &list_ref));
+ no_matter_name,
+ list_ref));
Item *item_isnull=
new (thd->mem_root)
Item_func_isnull(thd,
new (thd->mem_root)
Item_ref(thd, &select_lex->context,
&select_lex->ref_pointer_array[i],
- (char *)"<no matter>",
- &list_ref));
+ no_matter_name,
+ list_ref));
Item *col_item= new (thd->mem_root)
Item_cond_or(thd, item_eq, item_isnull);
if (!abort_on_null && left_expr->element_index(i)->maybe_null &&
@@ -2561,8 +2597,8 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
Item_ref(thd, &select_lex->context,
&select_lex->
ref_pointer_array[i],
- (char *)"<no matter>",
- &list_ref));
+ no_matter_name,
+ list_ref));
if (!abort_on_null && left_expr->element_index(i)->maybe_null &&
get_cond_guard(i) )
{
@@ -2596,14 +2632,14 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
Item_direct_ref(thd, &select_lex->context,
(*optimizer->get_cache())->
addr(i),
- (char *)"<no matter>",
- &in_left_expr_name),
+ no_matter_name,
+ in_left_expr_name),
new (thd->mem_root)
Item_direct_ref(thd, &select_lex->context,
&select_lex->
ref_pointer_array[i],
- (char *)"<no matter>",
- &list_ref));
+ no_matter_name,
+ list_ref));
if (!abort_on_null && select_lex->ref_pointer_array[i]->maybe_null)
{
Item *having_col_item=
@@ -2612,8 +2648,8 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
new (thd->mem_root)
Item_ref(thd, &select_lex->context,
&select_lex->ref_pointer_array[i],
- (char *)"<no matter>",
- &list_ref));
+ no_matter_name,
+ list_ref));
item_isnull= new (thd->mem_root)
Item_func_isnull(thd,
@@ -2621,8 +2657,8 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
Item_direct_ref(thd, &select_lex->context,
&select_lex->
ref_pointer_array[i],
- (char *)"<no matter>",
- &list_ref));
+ no_matter_name,
+ list_ref));
item= new (thd->mem_root) Item_cond_or(thd, item, item_isnull);
if (left_expr->element_index(i)->maybe_null && get_cond_guard(i))
{
@@ -2828,7 +2864,7 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg)
join_arg->thd->change_item_tree(&unit->global_parameters()->select_limit,
new (thd->mem_root)
Item_int(thd, (int32) 1));
- unit->select_limit_cnt= 1;
+ unit->lim.set_single_row();
DBUG_RETURN(false);
}
@@ -3185,8 +3221,8 @@ bool Item_exists_subselect::exists2in_processor(void *opt_arg)
in_subs->expr= new (thd->mem_root)
Item_direct_ref(thd, &first_select->context,
(Item**)optimizer->get_cache(),
- (char *)"<no matter>",
- &in_left_expr_name);
+ no_matter_name,
+ in_left_expr_name);
if (in_subs->fix_fields(thd, optimizer->arguments() + 1))
{
res= TRUE;
@@ -3256,8 +3292,8 @@ bool Item_exists_subselect::exists2in_processor(void *opt_arg)
Item_direct_ref(thd,
&unit->outer_select()->context,
optimizer->arguments(),
- (char *)"<no matter>",
- &exists_outer_expr_name)),
+ no_matter_name,
+ exists_outer_expr_name)),
optimizer) :
(Item *)optimizer);
}
@@ -3280,8 +3316,8 @@ bool Item_exists_subselect::exists2in_processor(void *opt_arg)
Item_direct_ref(thd,
&unit->outer_select()->context,
optimizer->arguments()[0]->addr((int)i),
- (char *)"<no matter>",
- &exists_outer_expr_name)),
+ no_matter_name,
+ exists_outer_expr_name)),
thd->mem_root);
}
}
@@ -3820,7 +3856,6 @@ int subselect_single_select_engine::prepare(THD *thd)
SELECT_LEX *save_select= thd->lex->current_select;
thd->lex->current_select= select_lex;
if (join->prepare(select_lex->table_list.first,
- select_lex->with_wild,
select_lex->where,
select_lex->order_list.elements +
select_lex->group_list.elements,
@@ -4209,7 +4244,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);
@@ -4254,11 +4290,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);
@@ -4297,9 +4333,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);
}
@@ -4369,9 +4405,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;
@@ -4379,7 +4415,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())
@@ -4431,9 +4467,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],
@@ -4539,9 +4575,10 @@ void subselect_single_select_engine::print(String *str,
enum_query_type query_type)
{
With_clause* with_clause= select_lex->get_with_clause();
+ THD *thd= get_thd();
if (with_clause)
- with_clause->print(str, query_type);
- select_lex->print(get_thd(), str, query_type);
+ with_clause->print(thd, str, query_type);
+ select_lex->print(thd, str, query_type);
}
@@ -4818,7 +4855,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;
@@ -4865,7 +4902,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;
@@ -5116,8 +5153,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;
}
@@ -5157,9 +5195,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() ||
@@ -5208,7 +5249,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);
@@ -5270,7 +5311,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;
@@ -5292,7 +5333,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));
}
@@ -5339,7 +5380,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)
{
@@ -5579,7 +5620,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;
@@ -5912,8 +5953,9 @@ bool Ordered_key::alloc_keys_buffers()
{
DBUG_ASSERT(key_buff_elements > 0);
- if (!(key_buff= (rownum_t*) my_malloc((size_t)(key_buff_elements *
- sizeof(rownum_t)), MYF(MY_WME | MY_THREAD_SPECIFIC))))
+ if (!(key_buff= (rownum_t*) my_malloc(PSI_INSTRUMENT_ME,
+ static_cast<size_t>(key_buff_elements * sizeof(rownum_t)),
+ MYF(MY_WME | MY_THREAD_SPECIFIC))))
return TRUE;
/*
@@ -6195,7 +6237,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() &&
@@ -6317,7 +6359,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)
@@ -6344,14 +6386,15 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts,
sizeof(Ordered_key*))) ||
!(null_bitmaps= (MY_BITMAP**) thd->alloc(merge_keys_count *
sizeof(MY_BITMAP*))) ||
- !(row_num_to_rowid= (uchar*) my_malloc((size_t)(row_count * rowid_length),
- MYF(MY_WME | MY_THREAD_SPECIFIC))))
+ !(row_num_to_rowid= (uchar*) my_malloc(PSI_INSTRUMENT_ME,
+ static_cast<size_t>(row_count * rowid_length),
+ MYF(MY_WME | MY_THREAD_SPECIFIC))))
return TRUE;
/* 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;
@@ -6383,7 +6426,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),