summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc756
1 files changed, 382 insertions, 374 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ddc5a25bd07..04baf5737c6 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -354,7 +354,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
ulong setup_tables_done_option)
{
bool res;
- SELECT_LEX *select_lex = &lex->select_lex;
+ SELECT_LEX *select_lex= lex->first_select_lex();
DBUG_ENTER("handle_select");
MYSQL_SELECT_START(thd->query());
@@ -1051,7 +1051,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
while ((select_el= select_it++))
{
- if (select_el->with_sum_func)
+ if (select_el->with_sum_func())
found_sum_func_elem= true;
if (select_el->with_field)
found_field_elem= true;
@@ -1219,14 +1219,14 @@ JOIN::prepare(TABLE_LIST *tables_init,
item->max_length)))
real_order= TRUE;
- if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
+ if (item->with_sum_func() && item->type() != Item::SUM_FUNC_ITEM)
item->split_sum_func(thd, ref_ptrs, all_fields, 0);
}
if (!real_order)
order= NULL;
}
- if (having && having->with_sum_func)
+ if (having && having->with_sum_func())
having->split_sum_func2(thd, ref_ptrs, all_fields,
&having, SPLIT_SUM_SKIP_REGISTERED);
if (select_lex->inner_sum_func_list)
@@ -1396,6 +1396,7 @@ err:
bool JOIN::build_explain()
{
+ DBUG_ENTER("JOIN::build_explain");
create_explain_query_if_not_exists(thd->lex, thd->mem_root);
have_query_plan= QEP_AVAILABLE;
@@ -1413,8 +1414,7 @@ bool JOIN::build_explain()
thd->mem_root= old_mem_root;
DBUG_ASSERT(thd->free_list == old_free_list); // no Items were created
if (res)
- return 1;
-
+ DBUG_RETURN(1);
uint select_nr= select_lex->select_number;
JOIN_TAB *curr_tab= join_tab + exec_join_tab_cnt();
for (uint i= 0; i < aggr_tables; i++, curr_tab++)
@@ -1432,7 +1432,7 @@ bool JOIN::build_explain()
get_using_temporary_read_tracker();
}
}
- return 0;
+ DBUG_RETURN(0);
}
@@ -1597,7 +1597,7 @@ JOIN::optimize_inner()
{
/*
Item_cond_and can't be fixed after creation, so we do not check
- conds->fixed
+ conds->is_fixed()
*/
conds->fix_fields(thd, &conds);
conds->change_ref_to_fields(thd, tables_list);
@@ -1641,7 +1641,7 @@ JOIN::optimize_inner()
if (arena)
thd->restore_active_arena(arena, &backup);
}
-
+
if (optimize_constant_subqueries())
DBUG_RETURN(1);
@@ -1652,9 +1652,28 @@ JOIN::optimize_inner()
(void) having->walk(&Item::cleanup_is_expensive_cache_processor,
0, (void *) 0);
- if (setup_jtbm_semi_joins(this, join_list, &conds))
+ List<Item> eq_list;
+
+ if (setup_degenerate_jtbm_semi_joins(this, join_list, eq_list))
DBUG_RETURN(1);
+ if (eq_list.elements != 0)
+ {
+ Item *new_cond;
+
+ if (eq_list.elements == 1)
+ new_cond= eq_list.pop();
+ else
+ new_cond= new (thd->mem_root) Item_cond_and(thd, eq_list);
+
+ if (new_cond &&
+ ((new_cond->fix_fields(thd, &new_cond) ||
+ !(conds= and_items(thd, conds, new_cond)) ||
+ conds->fix_fields(thd, &conds))))
+ DBUG_RETURN(TRUE);
+ }
+ eq_list.empty();
+
if (select_lex->cond_pushed_into_where)
{
conds= and_conds(thd, conds, select_lex->cond_pushed_into_where);
@@ -1685,6 +1704,31 @@ JOIN::optimize_inner()
DBUG_RETURN(1);
}
+ if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY))
+ {
+ TABLE_LIST *tbl;
+ List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
+ while ((tbl= li++))
+ if (tbl->jtbm_subselect)
+ {
+ if (tbl->jtbm_subselect->pushdown_cond_for_in_subquery(thd, conds))
+ DBUG_RETURN(1);
+ }
+ }
+
+ if (setup_jtbm_semi_joins(this, join_list, eq_list))
+ DBUG_RETURN(1);
+
+ if (eq_list.elements != 0)
+ {
+ conds= and_new_conditions_to_optimized_cond(thd, conds, &cond_equal,
+ eq_list, &cond_value);
+
+ if (!conds &&
+ cond_value != Item::COND_FALSE && cond_value != Item::COND_TRUE)
+ DBUG_RETURN(TRUE);
+ }
+
if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED))
{
TABLE_LIST *tbl;
@@ -1991,7 +2035,7 @@ int JOIN::optimize_stage2()
if (!conds && outer_join)
{
/* Handle the case where we have an OUTER JOIN without a WHERE */
- conds= new (thd->mem_root) Item_int(thd, (longlong) 1,1); // Always true
+ conds= new (thd->mem_root) Item_bool(thd, true); // Always true
}
if (impossible_where)
@@ -2130,7 +2174,7 @@ int JOIN::optimize_stage2()
if (conds && const_table_map != found_const_table_map &&
(select_options & SELECT_DESCRIBE))
{
- conds=new (thd->mem_root) Item_int(thd, (longlong) 0, 1); // Always false
+ conds=new (thd->mem_root) Item_bool(thd, false); // Always false
}
/* Cache constant expressions in WHERE, HAVING, ON clauses. */
@@ -2413,13 +2457,13 @@ int JOIN::optimize_stage2()
elements may be lost during further having
condition transformation in JOIN::exec.
*/
- if (having && const_table_map && !having->with_sum_func)
+ if (having && const_table_map && !having->with_sum_func())
{
having->update_used_tables();
having= having->remove_eq_conds(thd, &select_lex->having_value, true);
if (select_lex->having_value == Item::COND_FALSE)
{
- having= new (thd->mem_root) Item_int(thd, (longlong) 0,1);
+ having= new (thd->mem_root) Item_bool(thd, false);
zero_result_cause= "Impossible HAVING noticed after reading const tables";
error= 0;
select_lex->mark_const_derived(zero_result_cause);
@@ -2457,7 +2501,7 @@ int JOIN::optimize_stage2()
{
JOIN_TAB *tab= &join_tab[const_tables];
- if (order)
+ if (order && !need_tmp)
{
/*
Force using of tmp table if sorting by a SP or UDF function due to
@@ -3162,7 +3206,7 @@ bool JOIN::make_aggr_tables_info()
or end_write_group()) if JOIN::group is set to false.
*/
// the temporary table was explicitly requested
- DBUG_ASSERT(MY_TEST(select_options & OPTION_BUFFER_RESULT));
+ DBUG_ASSERT(select_options & OPTION_BUFFER_RESULT);
// the temporary table does not have a grouping expression
DBUG_ASSERT(!curr_tab->table->group);
}
@@ -3765,6 +3809,15 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
bool need_tmp_table, bool need_order,
bool distinct)
{
+ DBUG_ENTER("JOIN::save_explain_data");
+ DBUG_PRINT("enter", ("Save explain Select_lex: %u (%p) parent lex: %p stmt_lex: %p present select: %u (%p)",
+ select_lex->select_number, select_lex,
+ select_lex->parent_lex, thd->lex->stmt_lex,
+ (output->get_select(select_lex->select_number) ?
+ select_lex->select_number : 0),
+ (output->get_select(select_lex->select_number) ?
+ output->get_select(select_lex->select_number)
+ ->select_lex : NULL)));
/*
If there is SELECT in this statement with the same number it must be the
same SELECT
@@ -3791,8 +3844,9 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
/* It's a degenerate join */
message= zero_result_cause ? zero_result_cause : "No tables used";
}
- return save_explain_data_intern(thd->lex->explain, need_tmp_table, need_order,
- distinct, message);
+ bool rc= save_explain_data_intern(thd->lex->explain, need_tmp_table,
+ need_order, distinct, message);
+ DBUG_RETURN(rc);
}
/*
@@ -3814,11 +3868,11 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite,
{
if (!(join_tab[i].filesort->tracker=
new Filesort_tracker(thd->lex->analyze_stmt)))
- return 1;
+ DBUG_RETURN(1);
}
}
}
- return 0;
+ DBUG_RETURN(0);
}
@@ -4175,10 +4229,10 @@ mysql_select(THD *thd,
is it single SELECT in derived table, called in derived table
creation
*/
- if (select_lex->linkage != DERIVED_TABLE_TYPE ||
+ if (select_lex->get_linkage() != DERIVED_TABLE_TYPE ||
(select_options & SELECT_DESCRIBE))
{
- if (select_lex->linkage != GLOBAL_OPTIONS_TYPE)
+ if (select_lex->get_linkage() != GLOBAL_OPTIONS_TYPE)
{
/*
Original join tabs might be overwritten at first
@@ -4870,7 +4924,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
if (join->cond_value == Item::COND_FALSE)
{
join->impossible_where= true;
- conds= new (join->thd->mem_root) Item_int(join->thd, (longlong) 0, 1);
+ conds= new (join->thd->mem_root) Item_bool(join->thd, false);
}
join->cond_equal= NULL;
@@ -10632,7 +10686,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
below to check if we should use 'quick' instead.
*/
DBUG_PRINT("info", ("Item_int"));
- tmp= new (thd->mem_root) Item_int(thd, (longlong) 1, 1); // Always true
+ tmp= new (thd->mem_root) Item_bool(thd, true); // Always true
}
}
@@ -10760,7 +10814,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
Yet attributes of the just built condition are not needed.
Thus we call sel->cond->quick_fix_field for safety.
*/
- if (sel->cond && !sel->cond->fixed)
+ if (sel->cond && !sel->cond->is_fixed())
sel->cond->quick_fix_field();
if (sel->test_quick_select(thd, tab->keys,
@@ -12769,7 +12823,8 @@ void JOIN::join_free()
!(select_options & SELECT_NO_UNLOCK) &&
!select_lex->subquery_in_having &&
(select_lex == (thd->lex->unit.fake_select_lex ?
- thd->lex->unit.fake_select_lex : &thd->lex->select_lex)))
+ thd->lex->unit.fake_select_lex :
+ thd->lex->first_select_lex())))
{
/*
TODO: unlock tables even if the join isn't top level select in the
@@ -13061,7 +13116,7 @@ static void update_depend_map_for_order(JOIN *join, ORDER *order)
order->used= 0;
// Not item_sum(), RAND() and no reference to table outside of sub select
if (!(order->depend_map & (OUTER_REF_TABLE_BIT | RAND_TABLE_BIT))
- && !order->item[0]->with_sum_func &&
+ && !order->item[0]->with_sum_func() &&
join->join_tab)
{
for (JOIN_TAB **tab=join->map2table;
@@ -13136,7 +13191,23 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
tab++)
tab->cached_eq_ref_table= FALSE;
- *simple_order= *join->join_tab[join->const_tables].on_expr_ref ? 0 : 1;
+ JOIN_TAB *head= join->join_tab + join->const_tables;
+ *simple_order= head->on_expr_ref[0] == NULL;
+ if (*simple_order && head->table->file->ha_table_flags() & HA_SLOW_RND_POS)
+ {
+ uint u1, u2, u3;
+ /*
+ normally the condition is (see filesort_use_addons())
+
+ length + sortlength <= max_length_for_sort_data
+
+ but for HA_SLOW_RND_POS tables we relax it a bit, as the alternative
+ is to use a temporary table, which is rather expensive.
+
+ TODO proper cost estimations
+ */
+ *simple_order= filesort_use_addons(head->table, 0, &u1, &u2, &u3);
+ }
}
else
{
@@ -13152,7 +13223,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
for (order=first_order; order ; order=order->next)
{
table_map order_tables=order->item[0]->used_tables();
- if (order->item[0]->with_sum_func ||
+ if (order->item[0]->with_sum_func() ||
/*
If the outer table of an outer join is const (either by itself or
after applying WHERE condition), grouping on a field from such a
@@ -13328,7 +13399,7 @@ ORDER *simple_remove_const(ORDER *order, COND *where)
ORDER *first= NULL, *prev= NULL;
for (; order; order= order->next)
{
- DBUG_ASSERT(!order->item[0]->with_sum_func); // should never happen
+ DBUG_ASSERT(!order->item[0]->with_sum_func()); // should never happen
if (!const_expression_in_where(where, order->item[0]))
{
if (!first)
@@ -13577,9 +13648,9 @@ finish:
FALSE otherwise
*/
-static bool check_simple_equality(THD *thd, const Item::Context &ctx,
- Item *left_item, Item *right_item,
- COND_EQUAL *cond_equal)
+bool check_simple_equality(THD *thd, const Item::Context &ctx,
+ Item *left_item, Item *right_item,
+ COND_EQUAL *cond_equal)
{
Item *orig_left_item= left_item;
Item *orig_right_item= right_item;
@@ -14032,7 +14103,7 @@ COND *Item_cond_and::build_equal_items(THD *thd,
if (!cond_args->elements &&
!cond_equal.current_level.elements &&
!eq_list.elements)
- return new (thd->mem_root) Item_int(thd, (longlong) 1, 1);
+ return new (thd->mem_root) Item_bool(thd, true);
List_iterator_fast<Item_equal> it(cond_equal.current_level);
while ((item_equal= it++))
@@ -14139,7 +14210,7 @@ COND *Item_func_eq::build_equal_items(THD *thd,
Item_equal *item_equal;
int n= cond_equal.current_level.elements + eq_list.elements;
if (n == 0)
- return new (thd->mem_root) Item_int(thd, (longlong) 1, 1);
+ return new (thd->mem_root) Item_bool(thd, true);
else if (n == 1)
{
if ((item_equal= cond_equal.current_level.pop()))
@@ -14530,7 +14601,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
List<Item> eq_list;
Item_func_eq *eq_item= 0;
if (((Item *) item_equal)->const_item() && !item_equal->val_int())
- return new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ return new (thd->mem_root) Item_bool(thd, false);
Item *item_const= item_equal->get_const();
Item_equal_fields_iterator it(*item_equal);
Item *head;
@@ -14538,7 +14609,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
Item *current_sjm_head= NULL;
DBUG_ASSERT(!cond ||
- cond->type() == Item::INT_ITEM ||
+ cond->is_bool_literal() ||
(cond->type() == Item::FUNC_ITEM &&
((Item_func *) cond)->functype() == Item_func::EQ_FUNC) ||
(cond->type() == Item::COND_ITEM &&
@@ -14659,13 +14730,13 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
cond AND eq_1 AND eq_2 AND eq_3 AND ...
- 'cond' is a parameter for this function, which may be NULL, an Item_int(1),
+ 'cond' is a parameter for this function, which may be NULL, an Item_bool(1),
or an Item_func_eq or an Item_cond_and.
We want to return a well-formed condition: no nested Item_cond_and objects,
or Item_cond_and with a single child:
- if 'cond' is an Item_cond_and, we add eq_i as its tail
- - if 'cond' is Item_int(1), we return eq_i
+ - if 'cond' is Item_bool(1), we return eq_i
- otherwise, we create our own Item_cond_and and put 'cond' at the front of
it.
- if we have only one condition to return, we don't create an Item_cond_and
@@ -14677,10 +14748,10 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
switch (eq_list.elements)
{
case 0:
- res= cond ? cond : new (thd->mem_root) Item_int(thd, (longlong) 1, 1);
+ res= cond ? cond : new (thd->mem_root) Item_bool(thd, true);
break;
case 1:
- if (!cond || cond->type() == Item::INT_ITEM)
+ if (!cond || cond->is_bool_literal())
res= eq_item;
break;
default:
@@ -14822,7 +14893,7 @@ static COND* substitute_for_best_equal_field(THD *thd, JOIN_TAB *context_tab,
eq_cond= 0;
break;
}
- else if (eq_cond->type() == Item::INT_ITEM && !eq_cond->val_bool())
+ else if (eq_cond->is_bool_literal() && !eq_cond->val_bool())
{
/*
This occurs when eliminate_item_equal() founds that cond is
@@ -14847,7 +14918,7 @@ static COND* substitute_for_best_equal_field(THD *thd, JOIN_TAB *context_tab,
else
{
/* Do not add an equality condition if it's always true */
- if (eq_cond->type() != Item::INT_ITEM &&
+ if (!eq_cond->is_bool_literal() &&
cond_list->push_front(eq_cond, thd->mem_root))
eq_cond= 0;
}
@@ -15361,7 +15432,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top,
conds= and_conds(join->thd, conds, table->on_expr);
conds->top_level_item();
/* conds is always a new item as both cond and on_expr existed */
- DBUG_ASSERT(!conds->fixed);
+ DBUG_ASSERT(!conds->is_fixed());
conds->fix_fields(join->thd, &conds);
}
else
@@ -16429,9 +16500,8 @@ Item_func_isnull::remove_eq_conds(THD *thd, Item::cond_result *cond_value,
{
Field *field= ((Item_field*) real_item)->field;
- if (((field->type() == MYSQL_TYPE_DATE) ||
- (field->type() == MYSQL_TYPE_DATETIME)) &&
- (field->flags & NOT_NULL_FLAG))
+ if ((field->flags & NOT_NULL_FLAG) &&
+ field->type_handler()->cond_notnull_field_isnull_to_field_eq_zero())
{
/* fix to replace 'NULL' dates with '0' (shreeve@uci.edu) */
/*
@@ -16447,7 +16517,7 @@ Item_func_isnull::remove_eq_conds(THD *thd, Item::cond_result *cond_value,
*/
- Item *item0= new(thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ Item *item0= new(thd->mem_root) Item_bool(thd, false);
Item *eq_cond= new(thd->mem_root) Item_func_eq(thd, args[0], item0);
if (!eq_cond)
return this;
@@ -16517,7 +16587,7 @@ Item_func_isnull::remove_eq_conds(THD *thd, Item::cond_result *cond_value,
cond= new_cond;
/*
Item_func_eq can't be fixed after creation so we do not check
- cond->fixed, also it do not need tables so we use 0 as second
+ cond->is_fixed(), also it do not need tables so we use 0 as second
argument.
*/
cond->fix_fields(thd, &cond);
@@ -16677,60 +16747,6 @@ const_expression_in_where(COND *cond, Item *comp_item, Field *comp_field,
Create internal temporary table
****************************************************************************/
-/**
- Create field for temporary table from given field.
-
- @param thd Thread handler
- @param org_field field from which new field will be created
- @param name New field name
- @param table Temporary table
- @param item !=NULL if item->result_field should point to new field.
- This is relevant for how fill_record() is going to work:
- If item != NULL then fill_record() will update
- the record in the original table.
- If item == NULL then fill_record() will update
- the temporary table
-
- @retval
- NULL on error
- @retval
- new_created field
-*/
-
-Field *create_tmp_field_from_field(THD *thd, Field *org_field,
- LEX_CSTRING *name, TABLE *table,
- Item_field *item)
-{
- Field *new_field;
-
- new_field= org_field->make_new_field(thd->mem_root, table,
- table == org_field->table);
- if (new_field)
- {
- new_field->init(table);
- new_field->orig_table= org_field->orig_table;
- if (item)
- item->result_field= new_field;
- else
- new_field->field_name= *name;
- new_field->flags|= org_field->flags & NO_DEFAULT_VALUE_FLAG;
- if (org_field->maybe_null() || (item && item->maybe_null))
- new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
- if (org_field->type() == MYSQL_TYPE_VAR_STRING ||
- org_field->type() == MYSQL_TYPE_VARCHAR)
- table->s->db_create_options|= HA_OPTION_PACK_RECORD;
- else if (org_field->type() == FIELD_TYPE_DOUBLE)
- ((Field_double *) new_field)->not_fixed= TRUE;
- new_field->vcol_info= 0;
- new_field->cond_selectivity= 1.0;
- new_field->next_equal_field= NULL;
- new_field->option_list= NULL;
- new_field->option_struct= NULL;
- }
- return new_field;
-}
-
-
Field *Item::create_tmp_field_int(TABLE *table, uint convert_int_length)
{
const Type_handler *h= &type_handler_long;
@@ -16740,6 +16756,22 @@ Field *Item::create_tmp_field_int(TABLE *table, uint convert_int_length)
*this, table);
}
+Field *Item::tmp_table_field_from_field_type_maybe_null(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param,
+ bool is_explicit_null)
+{
+ DBUG_ASSERT(!param->make_copy_field());
+ DBUG_ASSERT(!is_result_field());
+ Field *result;
+ if ((result= tmp_table_field_from_field_type(table)))
+ {
+ if (result && is_explicit_null)
+ result->is_created_from_null_item= true;
+ }
+ return result;
+}
+
Field *Item_sum::create_tmp_field(bool group, TABLE *table)
{
@@ -16771,57 +16803,6 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table)
}
-static void create_tmp_field_from_item_finalize(THD *thd,
- Field *new_field,
- Item *item,
- Item ***copy_func,
- bool modify_item)
-{
- if (copy_func &&
- (item->is_result_field() ||
- (item->real_item()->is_result_field())))
- *((*copy_func)++) = item; // Save for copy_funcs
- if (modify_item)
- item->set_result_field(new_field);
- if (item->type() == Item::NULL_ITEM)
- new_field->is_created_from_null_item= TRUE;
-}
-
-
-/**
- Create field for temporary table using type of given item.
-
- @param thd Thread handler
- @param item Item to create a field for
- @param table Temporary table
- @param copy_func If set and item is a function, store copy of
- item in this array
- @param modify_item 1 if item->result_field should point to new
- item. This is relevent for how fill_record()
- is going to work:
- If modify_item is 1 then fill_record() will
- update the record in the original table.
- If modify_item is 0 then fill_record() will
- update the temporary table
-
- @retval
- 0 on error
- @retval
- new_created field
-*/
-
-static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
- Item ***copy_func, bool modify_item)
-{
- Field *UNINIT_VAR(new_field);
- DBUG_ASSERT(thd == table->in_use);
- if ((new_field= item->create_tmp_field(false, table)))
- create_tmp_field_from_item_finalize(thd, new_field, item,
- copy_func, modify_item);
- return new_field;
-}
-
-
/**
Create field for information schema table.
@@ -16859,19 +16840,182 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table)
/**
+ Create a temporary field for Item_field (or its descendant),
+ either direct or referenced by an Item_ref.
+*/
+Field *
+Item_field::create_tmp_field_from_item_field(TABLE *new_table,
+ Item_ref *orig_item,
+ const Tmp_field_param *param)
+{
+ DBUG_ASSERT(!is_result_field());
+ Field *result;
+ /*
+ If item have to be able to store NULLs but underlaid field can't do it,
+ create_tmp_field_from_field() can't be used for tmp field creation.
+ */
+ if (((maybe_null && in_rollup) ||
+ (new_table->in_use->create_tmp_table_for_derived && /* for mat. view/dt */
+ orig_item && orig_item->maybe_null)) &&
+ !field->maybe_null())
+ {
+ /*
+ The item the ref points to may have maybe_null flag set while
+ the ref doesn't have it. This may happen for outer fields
+ when the outer query decided at some point after name resolution phase
+ that this field might be null. Take this into account here.
+ */
+ Record_addr rec(orig_item ? orig_item->maybe_null : maybe_null);
+ const Type_handler *handler= type_handler()->
+ type_handler_for_tmp_table(this);
+ result= handler->make_and_init_table_field(orig_item ? &orig_item->name : &name,
+ rec, *this, new_table);
+ }
+ else if (param->table_cant_handle_bit_fields() &&
+ field->type() == MYSQL_TYPE_BIT)
+ {
+ const Type_handler *handler= type_handler_long_or_longlong();
+ result= handler->make_and_init_table_field(&name,
+ Record_addr(maybe_null),
+ *this, new_table);
+ }
+ else
+ {
+ LEX_CSTRING *tmp= orig_item ? &orig_item->name : &name;
+ bool tmp_maybe_null= param->modify_item() ? maybe_null :
+ field->maybe_null();
+ result= field->create_tmp_field(new_table->in_use->mem_root, new_table,
+ tmp_maybe_null);
+ if (result)
+ result->field_name= *tmp;
+ }
+ if (result && param->modify_item())
+ result_field= result;
+ return result;
+}
+
+
+Field *Item_field::create_tmp_field_ex(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ DBUG_ASSERT(!is_result_field());
+ Field *result;
+ src->set_field(field);
+ if (!(result= create_tmp_field_from_item_field(table, NULL, param)))
+ return NULL;
+ /*
+ Fields that are used as arguments to the DEFAULT() function already have
+ their data pointers set to the default value during name resolution. See
+ Item_default_value::fix_fields.
+ */
+ if (type() != Item::DEFAULT_VALUE_ITEM && field->eq_def(result))
+ src->set_default_field(field);
+ return result;
+}
+
+
+Field *Item_ref::create_tmp_field_ex(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ Item *item= real_item();
+ DBUG_ASSERT(is_result_field());
+ if (item->type() == Item::FIELD_ITEM)
+ {
+ Field *result;
+ Item_field *field= (Item_field*) item;
+ Tmp_field_param prm2(*param);
+ prm2.set_modify_item(false);
+ src->set_field(field->field);
+ if (!(result= field->create_tmp_field_from_item_field(table, this, &prm2)))
+ return NULL;
+ if (param->modify_item())
+ result_field= result;
+ return result;
+ }
+ return Item_result_field::create_tmp_field_ex(table, src, param);
+}
+
+
+void Item_result_field::get_tmp_field_src(Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ if (param->make_copy_field())
+ {
+ DBUG_ASSERT(result_field);
+ src->set_field(result_field);
+ }
+ else
+ {
+ src->set_item_result_field(this); // Save for copy_funcs
+ }
+}
+
+
+Field *Item_result_field::create_tmp_field_ex(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ /*
+ Possible Item types:
+ - Item_cache_wrapper (only for CREATE..SELECT ?)
+ - Item_func
+ - Item_subselect
+ */
+ DBUG_ASSERT(is_result_field());
+ DBUG_ASSERT(type() != NULL_ITEM);
+ get_tmp_field_src(src, param);
+ Field *result;
+ if ((result= tmp_table_field_from_field_type(table)) && param->modify_item())
+ result_field= result;
+ return result;
+}
+
+
+Field *Item_func_user_var::create_tmp_field_ex(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ DBUG_ASSERT(is_result_field());
+ DBUG_ASSERT(type() != NULL_ITEM);
+ get_tmp_field_src(src, param);
+ Field *result;
+ if ((result= create_table_field_from_handler(table)) && param->modify_item())
+ result_field= result;
+ return result;
+}
+
+
+Field *Item_func_sp::create_tmp_field_ex(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ Field *result;
+ get_tmp_field_src(src, param);
+ if ((result= sp_result_field->create_tmp_field(table->in_use->mem_root,
+ table)))
+ {
+ result->field_name= name;
+ if (param->modify_item())
+ result_field= result;
+ }
+ return result;
+}
+
+/**
Create field for temporary table.
- @param thd Thread handler
- @param table Temporary table
- @param item Item to create a field for
- @param type Type of item (normally item->type)
- @param copy_func If set and item is a function, store copy of item
+ @param table Temporary table
+ @param item Item to create a field for
+ @param type Type of item (normally item->type)
+ @param copy_func If set and item is a function, store copy of item
in this array
@param from_field if field will be created using other field as example,
pointer example field will be written here
- @param default_field If field has a default value field, store it here
- @param group 1 if we are going to do a relative group by on result
- @param modify_item 1 if item->result_field should point to new item.
+ @param default_field If field has a default value field, store it here
+ @param group 1 if we are going to do a relative group by on result
+ @param modify_item 1 if item->result_field should point to new item.
This is relevent for how fill_record() is going to
work:
If modify_item is 1 then fill_record() will update
@@ -16880,175 +17024,28 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table)
the temporary table
@retval
- 0 on error
+ 0 on error
@retval
new_created field
+ Create a temporary field for Item_field (or its descendant),
+ either direct or referenced by an Item_ref.
*/
-
-Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
+Field *create_tmp_field(TABLE *table, Item *item,
Item ***copy_func, Field **from_field,
Field **default_field,
bool group, bool modify_item,
bool table_cant_handle_bit_fields,
bool make_copy_field)
{
- Field *result;
- Item::Type orig_type= type;
- Item *orig_item= 0;
-
- DBUG_ASSERT(thd == table->in_use);
-
- if (type != Item::FIELD_ITEM &&
- item->real_item()->type() == Item::FIELD_ITEM)
- {
- orig_item= item;
- item= item->real_item();
- type= Item::FIELD_ITEM;
- }
-
- switch (type) {
- case Item::TYPE_HOLDER:
- case Item::SUM_FUNC_ITEM:
- {
- result= item->create_tmp_field(group, table);
- if (!result)
- my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
- return result;
- }
- case Item::FIELD_ITEM:
- case Item::DEFAULT_VALUE_ITEM:
- case Item::INSERT_VALUE_ITEM:
- case Item::TRIGGER_FIELD_ITEM:
- {
- Item_field *field= (Item_field*) item;
- bool orig_modify= modify_item;
- if (orig_type == Item::REF_ITEM)
- modify_item= 0;
- /*
- If item have to be able to store NULLs but underlaid field can't do it,
- create_tmp_field_from_field() can't be used for tmp field creation.
- */
- if (((field->maybe_null && field->in_rollup) ||
- (thd->create_tmp_table_for_derived && /* for mat. view/dt */
- orig_item && orig_item->maybe_null)) &&
- !field->field->maybe_null())
- {
- bool save_maybe_null= FALSE;
- /*
- The item the ref points to may have maybe_null flag set while
- the ref doesn't have it. This may happen for outer fields
- when the outer query decided at some point after name resolution phase
- that this field might be null. Take this into account here.
- */
- if (orig_item)
- {
- save_maybe_null= item->maybe_null;
- item->maybe_null= orig_item->maybe_null;
- }
- result= create_tmp_field_from_item(thd, item, table, NULL,
- modify_item);
- *from_field= field->field;
- if (result && modify_item)
- field->result_field= result;
- if (orig_item)
- {
- item->maybe_null= save_maybe_null;
- result->field_name= orig_item->name;
- }
- }
- else if (table_cant_handle_bit_fields && field->field->type() ==
- MYSQL_TYPE_BIT)
- {
- const Type_handler *handler= item->type_handler_long_or_longlong();
- *from_field= field->field;
- if ((result=
- handler->make_and_init_table_field(&item->name,
- Record_addr(item->maybe_null),
- *item, table)))
- create_tmp_field_from_item_finalize(thd, result, item,
- copy_func, modify_item);
- if (result && modify_item)
- field->result_field= result;
- }
- else
- {
- LEX_CSTRING *tmp= orig_item ? &orig_item->name : &item->name;
- result= create_tmp_field_from_field(thd, (*from_field= field->field),
- tmp, table,
- modify_item ? field :
- NULL);
- }
-
- if (orig_type == Item::REF_ITEM && orig_modify)
- ((Item_ref*)orig_item)->set_result_field(result);
- /*
- Fields that are used as arguments to the DEFAULT() function already have
- their data pointers set to the default value during name resolution. See
- Item_default_value::fix_fields.
- */
- if (orig_type != Item::DEFAULT_VALUE_ITEM && field->field->eq_def(result))
- *default_field= field->field;
- return result;
- }
- /* Fall through */
- case Item::FUNC_ITEM:
- if (((Item_func *) item)->functype() == Item_func::FUNC_SP)
- {
- Item_func_sp *item_func_sp= (Item_func_sp *) item;
- Field *sp_result_field= item_func_sp->get_sp_result_field();
-
- if (make_copy_field)
- {
- DBUG_ASSERT(item_func_sp->result_field);
- *from_field= item_func_sp->result_field;
- }
- else
- {
- *((*copy_func)++)= item;
- }
- Field *result_field=
- create_tmp_field_from_field(thd,
- sp_result_field,
- &item_func_sp->name,
- table,
- NULL);
-
- if (modify_item)
- item->set_result_field(result_field);
-
- return result_field;
- }
-
- /* Fall through */
- case Item::COND_ITEM:
- case Item::FIELD_AVG_ITEM:
- case Item::FIELD_STD_ITEM:
- case Item::SUBSELECT_ITEM:
- /* The following can only happen with 'CREATE TABLE ... SELECT' */
- case Item::PROC_ITEM:
- case Item::INT_ITEM:
- case Item::REAL_ITEM:
- case Item::DECIMAL_ITEM:
- case Item::STRING_ITEM:
- case Item::DATE_ITEM:
- case Item::REF_ITEM:
- case Item::NULL_ITEM:
- case Item::VARBIN_ITEM:
- case Item::CACHE_ITEM:
- case Item::WINDOW_FUNC_ITEM: // psergey-winfunc:
- case Item::EXPR_CACHE_ITEM:
- case Item::PARAM_ITEM:
- if (make_copy_field)
- {
- DBUG_ASSERT(((Item_result_field*)item)->result_field);
- *from_field= ((Item_result_field*)item)->result_field;
- }
- return create_tmp_field_from_item(thd, item, table,
- (make_copy_field ? 0 : copy_func),
- modify_item);
- default: // Dosen't have to be stored
- return 0;
- }
+ Tmp_field_src src;
+ Tmp_field_param prm(group, modify_item, table_cant_handle_bit_fields,
+ make_copy_field);
+ Field *result= item->create_tmp_field_ex(table, &src, &prm);
+ *from_field= src.field();
+ *default_field= src.default_field();
+ if (src.item_result_field())
+ *((*copy_func)++)= src.item_result_field();
+ return result;
}
/*
@@ -17064,7 +17061,7 @@ setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps, uint field_count)
{
uint bitmap_size= bitmap_buffer_size(field_count);
- DBUG_ASSERT(table->s->virtual_fields == 0 && table->def_vcol_set == 0);
+ DBUG_ASSERT(table->s->virtual_fields == 0);
my_bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count,
FALSE);
@@ -17329,7 +17326,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
}
if (not_all_columns)
{
- if (item->with_sum_func && type != Item::SUM_FUNC_ITEM)
+ if (item->with_sum_func() && type != Item::SUM_FUNC_ITEM)
{
if (item->used_tables() & OUTER_REF_TABLE_BIT)
item->update_used_tables();
@@ -17359,7 +17356,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
{
Item *tmp_item;
Field *new_field=
- create_tmp_field(thd, table, arg, arg->type(), &copy_func,
+ create_tmp_field(table, arg, &copy_func,
tmp_from_field, &default_field[fieldnr],
group != 0,not_all_columns,
distinct, false);
@@ -17409,7 +17406,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
else
{
/*
- The last parameter to create_tmp_field() is a bit tricky:
+ The last parameter to create_tmp_field_ex() is a bit tricky:
We need to set it to 0 in union, to get fill_record() to modify the
temporary table.
@@ -17423,7 +17420,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
*/
Field *new_field= (param->schema_table) ?
item->create_field_for_schema(thd, table) :
- create_tmp_field(thd, table, item, type, &copy_func,
+ create_tmp_field(table, item, &copy_func,
tmp_from_field, &default_field[fieldnr],
group != 0,
!force_copy_fields &&
@@ -17437,8 +17434,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
*/
item->marker == 4 || param->bit_fields_as_long,
force_copy_fields);
-
- if (unlikely(!new_field))
+ if (!new_field)
{
if (unlikely(thd->is_fatal_error))
goto err; // Got OOM
@@ -18019,12 +18015,10 @@ bool Virtual_tmp_table::add(List<Spvar_definition> &field_list)
while ((cdef= it++))
{
Field *tmp;
- if (!(tmp= cdef->make_field(s, in_use->mem_root, 0,
- (uchar*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
- f_maybe_null(cdef->pack_flag) ? 1 : 0,
- &cdef->field_name)))
+ Record_addr addr(f_maybe_null(cdef->pack_flag));
+ if (!(tmp= cdef->make_field(s, in_use->mem_root, &addr, &cdef->field_name)))
DBUG_RETURN(true);
- add(tmp);
+ add(tmp);
}
DBUG_RETURN(false);
}
@@ -18144,7 +18138,7 @@ bool Virtual_tmp_table::sp_set_all_fields_from_item_list(THD *thd,
bool Virtual_tmp_table::sp_set_all_fields_from_item(THD *thd, Item *value)
{
- DBUG_ASSERT(value->fixed);
+ DBUG_ASSERT(value->is_fixed());
DBUG_ASSERT(value->cols() == s->fields);
for (uint i= 0; i < value->cols(); i++)
{
@@ -18567,7 +18561,7 @@ create_internal_tmp_table_from_heap(THD *thd, TABLE *table,
We don't want this error to be converted to a warning, e.g. in case of
INSERT IGNORE ... SELECT.
*/
- table->file->print_error(error, MYF(ME_FATALERROR));
+ table->file->print_error(error, MYF(ME_FATAL));
DBUG_RETURN(1);
}
new_table= *table;
@@ -18590,7 +18584,7 @@ create_internal_tmp_table_from_heap(THD *thd, TABLE *table,
new_table.no_rows= table->no_rows;
if (create_internal_tmp_table(&new_table, table->key_info, start_recinfo,
recinfo,
- thd->lex->select_lex.options |
+ thd->lex->first_select_lex()->options |
thd->variables.option_bits))
goto err2;
if (open_tmp_table(&new_table))
@@ -22741,7 +22735,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
if (unlikely(copy_blobs(first_field)))
{
my_message(ER_OUTOFMEMORY, ER_THD(thd,ER_OUTOFMEMORY),
- MYF(ME_FATALERROR));
+ MYF(ME_FATAL));
error=0;
goto err;
}
@@ -23018,12 +23012,7 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array,
uint counter;
enum_resolution_type resolution;
- /*
- Local SP variables may be int but are expressions, not positions.
- (And they can't be used before fix_fields is called for them).
- */
- if (order_item->type() == Item::INT_ITEM && order_item->basic_const_item() &&
- !from_window_spec)
+ if (order_item->is_order_clause_position() && !from_window_spec)
{ /* Order by position */
uint count;
if (order->counter_used)
@@ -23137,7 +23126,7 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array,
inspite of that fix_fields() calls find_item_in_list() one more
time.
- We check order_item->fixed because Item_func_group_concat can put
+ We check order_item->is_fixed() because Item_func_group_concat can put
arguments for which fix_fields already was called.
*/
if (order_item->fix_fields_if_needed_for_order_by(thd, order->item) ||
@@ -23247,7 +23236,7 @@ setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
all_fields, true, true, from_window_spec))
return 1;
(*ord->item)->marker= UNDEF_POS; /* Mark found */
- if ((*ord->item)->with_sum_func && context_analysis_place == IN_GROUP_BY)
+ if ((*ord->item)->with_sum_func() && context_analysis_place == IN_GROUP_BY)
{
my_error(ER_WRONG_GROUP_FIELD, MYF(0), (*ord->item)->full_name());
return 1;
@@ -23406,7 +23395,7 @@ create_distinct_group(THD *thd, Ref_ptr_array ref_pointer_array,
li.rewind();
while ((item=li++))
{
- if (!item->const_item() && !item->with_sum_func && !item->marker)
+ if (!item->const_item() && !item->with_sum_func() && !item->marker)
{
/*
Don't put duplicate columns from the SELECT list into the
@@ -23503,9 +23492,11 @@ count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param,
}
else
{
+ With_sum_func_cache *cache= field->get_with_sum_func_cache();
param->func_count++;
- if (reset_with_sum_func)
- field->with_sum_func=0;
+ // "field" can point to Item_std_field, so "cache" can be NULL here.
+ if (reset_with_sum_func && cache)
+ cache->reset_with_sum_func();
}
}
}
@@ -23645,7 +23636,7 @@ void calc_group_buffer(TMP_TABLE_PARAM *param, ORDER *group)
{
/*
Group strings are taken as varstrings and require an length field.
- A field is not yet created by create_tmp_field()
+ A field is not yet created by create_tmp_field_ex()
and the sizes should match up.
*/
key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH;
@@ -23655,7 +23646,7 @@ void calc_group_buffer(TMP_TABLE_PARAM *param, ORDER *group)
default:
/* This case should never be choosen */
DBUG_ASSERT(0);
- my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL));
}
}
parts++;
@@ -23909,7 +23900,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
real_pos->real_type() == Item::SUBSELECT_ITEM ||
real_pos->type() == Item::CACHE_ITEM ||
real_pos->type() == Item::COND_ITEM) &&
- !real_pos->with_sum_func)
+ !real_pos->with_sum_func())
{ // Save for send fields
pos= real_pos;
/* TODO:
@@ -23918,7 +23909,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
on how the value is to be used: In some cases this may be an
argument in a group function, like: IF(ISNULL(col),0,COUNT(*))
*/
- if (!(pos=new (thd->mem_root) Item_copy_string(thd, pos)))
+ if (!(pos= pos->type_handler()->create_item_copy(thd, pos)))
goto err;
if (i < border) // HAVING, ORDER and GROUP BY
{
@@ -24116,7 +24107,7 @@ change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
for (uint i= 0; (item= it++); i++)
{
Field *field;
- if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
+ if (item->with_sum_func() && item->type() != Item::SUM_FUNC_ITEM)
item_field= item;
else if (item->type() == Item::FIELD_ITEM)
{
@@ -24424,7 +24415,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
}
if (unlikely(thd->is_fatal_error))
DBUG_RETURN(TRUE);
- if (!cond->fixed)
+ if (!cond->is_fixed())
{
Item *tmp_item= (Item*) cond;
cond->fix_fields(thd, &tmp_item);
@@ -24643,7 +24634,7 @@ bool JOIN::rollup_init()
Marking the expression item as 'with_sum_func' will ensure this.
*/
if (changed)
- item->with_sum_func= 1;
+ item->get_with_sum_func_cache()->set_with_sum_func();
}
}
return 0;
@@ -25131,7 +25122,8 @@ bool JOIN_TAB::save_explain_data(Explain_table_access *eta,
*/
if (real_table->merged_for_insert)
{
- TABLE_LIST *view_child= real_table->view->select_lex.table_list.first;
+ TABLE_LIST *view_child=
+ real_table->view->first_select_lex()->table_list.first;
for (;view_child; view_child= view_child->next_local)
{
if (view_child->table == table)
@@ -25584,8 +25576,9 @@ int JOIN::save_explain_data_intern(Explain_query *output,
{
JOIN *join= this; /* Legacy: this code used to be a non-member function */
DBUG_ENTER("JOIN::save_explain_data_intern");
- DBUG_PRINT("info", ("Select %p, type %s, message %s",
- join->select_lex, join->select_lex->type,
+ DBUG_PRINT("info", ("Select %p (%u), type %s, message %s",
+ join->select_lex, join->select_lex->select_number,
+ join->select_lex->type,
message ? message : "NULL"));
DBUG_ASSERT(have_query_plan == QEP_AVAILABLE);
/* fake_select_lex is created/printed by Explain_union */
@@ -25611,7 +25604,7 @@ int JOIN::save_explain_data_intern(Explain_query *output,
explain->select_id= join->select_lex->select_number;
explain->select_type= join->select_lex->type;
- explain->linkage= select_lex->linkage;
+ explain->linkage= select_lex->get_linkage();
explain->using_temporary= need_tmp;
explain->using_filesort= need_order_arg;
/* Setting explain->message means that all other members are invalid */
@@ -25634,7 +25627,7 @@ int JOIN::save_explain_data_intern(Explain_query *output,
explain->select_id= select_lex->select_number;
explain->select_type= select_lex->type;
- explain->linkage= select_lex->linkage;
+ explain->linkage= select_lex->get_linkage();
explain->using_temporary= need_tmp;
explain->using_filesort= need_order_arg;
explain->message= "Storage engine handles GROUP BY";
@@ -25657,7 +25650,7 @@ int JOIN::save_explain_data_intern(Explain_query *output,
join->select_lex->set_explain_type(true);
xpl_sel->select_id= join->select_lex->select_number;
xpl_sel->select_type= join->select_lex->type;
- xpl_sel->linkage= select_lex->linkage;
+ xpl_sel->linkage= select_lex->get_linkage();
if (select_lex->master_unit()->derived)
xpl_sel->connection_type= Explain_node::EXPLAIN_NODE_DERIVED;
@@ -25801,7 +25794,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
for such queries, we'll get here before having called
subquery_expr->fix_fields(), which will cause failure to
*/
- if (unit->item && !unit->item->fixed)
+ if (unit->item && !unit->item->is_fixed())
{
Item *ref= unit->item;
if (unit->item->fix_fields(thd, &ref))
@@ -26241,6 +26234,18 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
{
str->append("/* select#");
str->append_ulonglong(select_number);
+ if (thd->lex->describe & DESCRIBE_EXTENDED2)
+ {
+ str->append("/");
+ str->append_ulonglong(nest_level);
+
+ if (master_unit()->fake_select_lex &&
+ master_unit()->first_select() == this)
+ {
+ str->append(" Filter Select: ");
+ master_unit()->fake_select_lex->print(thd, str, query_type);
+ }
+ }
str->append(" */ ");
}
@@ -26272,18 +26277,21 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
str->append(STRING_WITH_LEN("sql_buffer_result "));
if (options & OPTION_FOUND_ROWS)
str->append(STRING_WITH_LEN("sql_calc_found_rows "));
- switch (sql_cache)
+ if (this == parent_lex->first_select_lex())
{
- case SQL_NO_CACHE:
- str->append(STRING_WITH_LEN("sql_no_cache "));
- break;
- case SQL_CACHE:
- str->append(STRING_WITH_LEN("sql_cache "));
- break;
- case SQL_CACHE_UNSPECIFIED:
- break;
- default:
- DBUG_ASSERT(0);
+ switch (parent_lex->sql_cache)
+ {
+ case LEX::SQL_NO_CACHE:
+ str->append(STRING_WITH_LEN("sql_no_cache "));
+ break;
+ case LEX::SQL_CACHE:
+ str->append(STRING_WITH_LEN("sql_cache "));
+ break;
+ case LEX::SQL_CACHE_UNSPECIFIED:
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
}
//Item List