diff options
Diffstat (limited to 'sql/item_subselect.cc')
-rw-r--r-- | sql/item_subselect.cc | 509 |
1 files changed, 329 insertions, 180 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 1ab81d1862d..78dae0aaa1e 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -39,6 +39,7 @@ Item_subselect::Item_subselect(): engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0), const_item_cache(1), engine_changed(0), changed(0) { + with_subselect= 1; reset(); /* item value is NULL if select_subselect not changed this value @@ -53,7 +54,7 @@ void Item_subselect::init(st_select_lex *select_lex, { DBUG_ENTER("Item_subselect::init"); - DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex)); + DBUG_PRINT("enter", ("select_lex: 0x%x", (ulong) select_lex)); unit= select_lex->master_unit(); if (unit->item) @@ -66,7 +67,7 @@ void Item_subselect::init(st_select_lex *select_lex, parsing_place= unit->item->parsing_place; unit->item->engine= 0; unit->item= this; - engine->change_item(this, result); + engine->change_result(this, result); } else { @@ -130,20 +131,20 @@ Item_subselect::select_transformer(JOIN *join) } -bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) +bool Item_subselect::fix_fields(THD *thd_param, Item **ref) { + char const *save_where= thd_param->where; + bool res; + DBUG_ASSERT(fixed == 0); engine->set_thd((thd= thd_param)); - char const *save_where= thd->where; - int res; - - if (check_stack_overrun(thd, (gptr)&res)) - return 1; + if (check_stack_overrun(thd, STACK_MIN_SIZE, (gptr)&res)) + return TRUE; res= engine->prepare(); - // all transformetion is done (used by prepared statements) + // all transformation is done (used by prepared statements) changed= 1; if (!res) @@ -165,7 +166,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) substitution= 0; thd->where= "checking transformed subquery"; if (!(*ref)->fixed) - ret= (*ref)->fix_fields(thd, tables, ref); + ret= (*ref)->fix_fields(thd, ref); thd->where= save_where; return ret; } @@ -173,7 +174,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) if (engine->cols() > max_columns) { my_error(ER_OPERAND_COLUMNS, MYF(0), 1); - return 1; + return TRUE; } fix_length_and_dec(); } @@ -194,15 +195,8 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) bool Item_subselect::exec() { int res; - MEM_ROOT *old_root= thd->mem_root; - /* - As this is execution, all objects should be allocated through the main - mem root - */ - thd->mem_root= &thd->main_mem_root; res= engine->exec(); - thd->mem_root= old_root; if (engine_changed) { @@ -246,7 +240,7 @@ void Item_subselect::update_used_tables() { if (!engine->uncacheable()) { - // did all used tables become ststic? + // did all used tables become static? if (!(used_tables_cache & ~engine->upper_select_const_tables())) const_item_cache= 1; } @@ -271,7 +265,8 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex) DBUG_VOID_RETURN; } -Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent, +Item_maxmin_subselect::Item_maxmin_subselect(THD *thd_param, + Item_subselect *parent, st_select_lex *select_lex, bool max_arg) :Item_singlerow_subselect(), was_values(TRUE) @@ -290,6 +285,12 @@ Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent, used_tables_cache= parent->get_used_tables_cache(); const_item_cache= parent->get_const_item_cache(); + /* + this subquery always creates during preparation, so we can assign + thd here + */ + thd= thd_param; + DBUG_VOID_RETURN; } @@ -333,10 +334,8 @@ Item_singlerow_subselect::select_transformer(JOIN *join) return RES_OK; SELECT_LEX *select_lex= join->select_lex; - - /* Juggle with current arena only if we're in prepared statement prepare */ - Item_arena *arena= join->thd->current_arena; - + Query_arena *arena= thd->stmt_arena; + if (!select_lex->master_unit()->first_select()->next_select() && !select_lex->table_list.elements && select_lex->item_list.elements == 1 && @@ -351,20 +350,20 @@ Item_singlerow_subselect::select_transformer(JOIN *join) !(select_lex->item_list.head()->type() == FIELD_ITEM || select_lex->item_list.head()->type() == REF_ITEM) && /* - switch off this optimisation for prepare statement, + switch off this optimization for prepare statement, because we do not rollback this changes TODO: make rollback for it, or special name resolving mode in 5.0. */ - !arena->is_stmt_prepare() + !arena->is_stmt_prepare_or_first_sp_execute() ) { have_to_be_excluded= 1; - if (join->thd->lex->describe) + if (thd->lex->describe) { char warn_buff[MYSQL_ERRMSG_SIZE]; sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number); - push_warning(join->thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_SELECT_REDUCED, warn_buff); } substitution= select_lex->item_list.head(); @@ -381,6 +380,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) return RES_OK; } + void Item_singlerow_subselect::store(uint i, Item *item) { row[i]->store(item); @@ -404,6 +404,7 @@ void Item_singlerow_subselect::fix_length_and_dec() engine->fix_length_and_dec(row); value= *row; } + unsigned_flag= value->unsigned_flag; /* If there are not tables in subquery then ability to have NULL value depends on SELECT list (if single row subquery have tables then it @@ -443,13 +444,13 @@ void Item_singlerow_subselect::bring_value() exec(); } -double Item_singlerow_subselect::val() +double Item_singlerow_subselect::val_real() { DBUG_ASSERT(fixed == 1); if (!exec() && !value->null_value) { null_value= 0; - return value->val(); + return value->val_real(); } else { @@ -473,7 +474,7 @@ longlong Item_singlerow_subselect::val_int() } } -String *Item_singlerow_subselect::val_str (String *str) +String *Item_singlerow_subselect::val_str(String *str) { if (!exec() && !value->null_value) { @@ -488,24 +489,53 @@ String *Item_singlerow_subselect::val_str (String *str) } +my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value) +{ + if (!exec() && !value->null_value) + { + null_value= 0; + return value->val_decimal(decimal_value); + } + else + { + reset(); + return 0; + } +} + + +bool Item_singlerow_subselect::val_bool() +{ + if (!exec() && !value->null_value) + { + null_value= 0; + return value->val_bool(); + } + else + { + reset(); + return 0; + } +} + + Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex): Item_subselect() { DBUG_ENTER("Item_exists_subselect::Item_exists_subselect"); + bool val_bool(); init(select_lex, new select_exists_subselect(this)); max_columns= UINT_MAX; null_value= 0; //can't be NULL maybe_null= 0; //can't be NULL value= 0; - // We need only 1 row to determinate existence - select_lex->master_unit()->global_parameters->select_limit= 1; DBUG_VOID_RETURN; } void Item_exists_subselect::print(String *str) { - str->append("exists", 6); + str->append(STRING_WITH_LEN("exists")); Item_subselect::print(str); } @@ -565,9 +595,11 @@ void Item_exists_subselect::fix_length_and_dec() decimals= 0; max_length= 1; max_columns= engine->cols(); + /* We need only 1 row to determine existence */ + unit->global_parameters->select_limit= new Item_int((int32) 1); } -double Item_exists_subselect::val() +double Item_exists_subselect::val_real() { DBUG_ASSERT(fixed == 1); if (exec()) @@ -597,12 +629,37 @@ String *Item_exists_subselect::val_str(String *str) reset(); return 0; } - str->set(value,&my_charset_bin); + str->set((ulonglong)value,&my_charset_bin); return str; } -double Item_in_subselect::val() +my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value) +{ + DBUG_ASSERT(fixed == 1); + if (exec()) + { + reset(); + return 0; + } + int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value); + return decimal_value; +} + + +bool Item_exists_subselect::val_bool() +{ + DBUG_ASSERT(fixed == 1); + if (exec()) + { + reset(); + return 0; + } + return value != 0; +} + + +double Item_in_subselect::val_real() { /* As far as Item_in_subselect called only from Item_in_optimizer this @@ -625,6 +682,11 @@ double Item_in_subselect::val() longlong Item_in_subselect::val_int() { + /* + As far as Item_in_subselect called only from Item_in_optimizer this + method should not be used + */ + DBUG_ASSERT(0); DBUG_ASSERT(fixed == 1); null_value= 0; if (exec()) @@ -659,20 +721,55 @@ String *Item_in_subselect::val_str(String *str) null_value= 1; return 0; } - str->set(value, &my_charset_bin); + str->set((ulonglong)value, &my_charset_bin); return str; } +bool Item_in_subselect::val_bool() +{ + DBUG_ASSERT(fixed == 1); + if (exec()) + { + reset(); + null_value= 1; + return 0; + } + if (was_null && !value) + null_value= 1; + return value; +} + +my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value) +{ + /* + As far as Item_in_subselect called only from Item_in_optimizer this + method should not be used + */ + DBUG_ASSERT(0); + DBUG_ASSERT(fixed == 1); + if (exec()) + { + reset(); + null_value= 1; + return 0; + } + if (was_null && !value) + null_value= 1; + int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value); + return decimal_value; +} + + /* Rewrite a single-column IN/ALL/ANY subselect. */ Item_subselect::trans_res Item_in_subselect::single_value_transformer(JOIN *join, Comp_creator *func) { - DBUG_ENTER("Item_in_subselect::single_value_transformer"); - + Item_subselect::trans_res result= RES_ERROR; SELECT_LEX *select_lex= join->select_lex; + DBUG_ENTER("Item_in_subselect::single_value_transformer"); /* Check that the right part of the subselect contains no more than one @@ -712,6 +809,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, select_lex->table_list.elements) { Item_sum_hybrid *item; + nesting_map save_allow_sum_func; if (func->l_op()) { /* @@ -737,12 +835,16 @@ Item_in_subselect::single_value_transformer(JOIN *join, it.replace(item); } + save_allow_sum_func= thd->lex->allow_sum_func; + thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; /* Item_sum_(max|min) can't substitute other item => we can use 0 as - reference + reference, also Item_sum_(max|min) can't be fixed after creation, so + we do not check item->fixed */ - if (item->fix_fields(thd, join->tables_list, 0)) + if (item->fix_fields(thd, 0)) DBUG_RETURN(RES_ERROR); + thd->lex->allow_sum_func= save_allow_sum_func; /* we added aggregate function => we have to change statistic */ count_field_types(&join->tmp_table_param, join->all_fields, 0); @@ -751,10 +853,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, else { Item_maxmin_subselect *item; - // remove LIMIT placed by ALL/ANY subquery - select_lex->master_unit()->global_parameters->select_limit= - HA_POS_ERROR; - subs= item= new Item_maxmin_subselect(this, select_lex, func->l_op()); + subs= item= new Item_maxmin_subselect(thd, this, select_lex, func->l_op()); if (upper_item) upper_item->set_sub_test(item); } @@ -773,7 +872,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, thd->lex->current_select= up= current->return_after_parsing(); //optimizer never use Item **ref => we can pass 0 as parameter - if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0)) + if (!optimizer || optimizer->fix_left(thd, 0)) { thd->lex->current_select= current; DBUG_RETURN(RES_ERROR); @@ -781,10 +880,11 @@ Item_in_subselect::single_value_transformer(JOIN *join, thd->lex->current_select= current; /* - As far as Item_ref_in_optimizer do not substitude itself on fix_fields + As far as Item_ref_in_optimizer do not substitute itself on fix_fields we can use same item for all selects. */ - expr= new Item_direct_ref((Item**)optimizer->get_cache(), + expr= new Item_direct_ref(&select_lex->context, + (Item**)optimizer->get_cache(), (char *)"<no matter>", (char *)in_left_expr_name); @@ -792,9 +892,6 @@ Item_in_subselect::single_value_transformer(JOIN *join, } select_lex->uncacheable|= UNCACHEABLE_DEPENDENT; - Item *item; - - item= (Item*) select_lex->item_list.head(); /* Add the left part of a subselect to a WHERE or HAVING clause of the right part, e.g. SELECT 1 IN (SELECT a FROM t1) => @@ -805,11 +902,18 @@ Item_in_subselect::single_value_transformer(JOIN *join, if (join->having || select_lex->with_sum_func || select_lex->group_list.elements) { - item= func->create(expr, - new Item_ref_null_helper(this, - select_lex->ref_pointer_array, - (char *)"<ref>", - this->full_name())); + bool tmp; + Item *item= func->create(expr, + new Item_ref_null_helper(&select_lex->context, + this, + select_lex-> + ref_pointer_array, + (char *)"<ref>", + this->full_name())); +#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE + if (!abort_on_null && left_expr->maybe_null) + item= new Item_cond_or(new Item_func_isnull(left_expr), item); +#endif /* AND and comparison functions can't be changed during fix_fields() we can assign select_lex->having here, and pass 0 as last @@ -817,17 +921,22 @@ Item_in_subselect::single_value_transformer(JOIN *join, */ select_lex->having= join->having= and_items(join->having, item); select_lex->having_fix_field= 1; - if (join->having->fix_fields(thd, join->tables_list, 0)) - { - select_lex->having_fix_field= 0; - DBUG_RETURN(RES_ERROR); - } + /* + we do not check join->having->fixed, because Item_and (from and_items) + or comparison function (from func->create) can't be fixed after creation + */ + tmp= join->having->fix_fields(thd, 0); select_lex->having_fix_field= 0; + if (tmp) + DBUG_RETURN(RES_ERROR); } else { + Item *item= (Item*) select_lex->item_list.head(); + if (select_lex->table_list.elements) { + bool tmp; Item *having= item, *orig_item= item; select_lex->item_list.empty(); select_lex->item_list.push_back(new Item_int("Not_used", @@ -847,14 +956,21 @@ Item_in_subselect::single_value_transformer(JOIN *join, new Item_cond_and(having, join->having) : having); select_lex->having_fix_field= 1; - if (join->having->fix_fields(thd, join->tables_list, 0)) - { - select_lex->having_fix_field= 0; + /* + we do not check join->having->fixed, because Item_and (from + and_items) or comparison function (from func->create) can't be + fixed after creation + */ + tmp= join->having->fix_fields(thd, 0); + select_lex->having_fix_field= 0; + if (tmp) DBUG_RETURN(RES_ERROR); - } - select_lex->having_fix_field= 0; item= new Item_cond_or(item, new Item_func_isnull(orig_item)); +#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE + if (left_expr->maybe_null) + item= new Item_cond_or(new Item_func_isnull(left_expr), item); +#endif } item->name= (char *)in_additional_cond; /* @@ -864,11 +980,16 @@ Item_in_subselect::single_value_transformer(JOIN *join, */ select_lex->where= join->conds= and_items(join->conds, item); select_lex->where->top_level_item(); - if (join->conds->fix_fields(thd, join->tables_list, 0)) + /* + we do not check join->conds->fixed, because Item_and can't be fixed + after creation + */ + if (join->conds->fix_fields(thd, 0)) DBUG_RETURN(RES_ERROR); } else { + bool tmp; if (select_lex->master_unit()->first_select()->next_select()) { /* @@ -879,25 +1000,26 @@ Item_in_subselect::single_value_transformer(JOIN *join, select_lex->having= join->having= func->create(expr, - new Item_ref_null_helper(this, + new Item_ref_null_helper(&select_lex->context, this, select_lex->ref_pointer_array, (char *)"<no matter>", (char *)"<result>")); select_lex->having_fix_field= 1; - if (join->having->fix_fields(thd, join->tables_list, - 0)) - { - select_lex->having_fix_field= 0; + /* + we do not check join->having->fixed, because comparison function + (from func->create) can't be fixed after creation + */ + tmp= join->having->fix_fields(thd, 0); + select_lex->having_fix_field= 0; + if (tmp) DBUG_RETURN(RES_ERROR); - } - select_lex->having_fix_field= 0; } else { // it is single select without tables => possible optimization item= func->create(left_expr, item); - // fix_field of item will be done in time of substituting + // fix_field of item will be done in time of substituting substitution= item; have_to_be_excluded= 1; if (thd->lex->describe) @@ -942,13 +1064,13 @@ Item_in_subselect::row_value_transformer(JOIN *join) SELECT_LEX *current= thd->lex->current_select, *up; thd->lex->current_select= up= current->return_after_parsing(); //optimizer never use Item **ref => we can pass 0 as parameter - if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0)) + if (!optimizer || optimizer->fix_left(thd, 0)) { thd->lex->current_select= current; DBUG_RETURN(RES_ERROR); } - // we will refer to apper level cache array => we have to save it in PS + // we will refer to upper level cache array => we have to save it in PS optimizer->keep_top_level_cache(); thd->lex->current_select= current; @@ -979,21 +1101,23 @@ Item_in_subselect::row_value_transformer(JOIN *join) DBUG_RETURN(RES_ERROR); Item *item_eq= new Item_func_eq(new - Item_ref((*optimizer->get_cache())-> - addr(i), - (char *)"<no matter>", - (char *)in_left_expr_name), + Item_ref(&select_lex->context, + (*optimizer->get_cache())-> + addr(i), + (char *)"<no matter>", + (char *)in_left_expr_name), new - Item_ref(select_lex->ref_pointer_array + i, - (char *)"<no matter>", - (char *)"<list ref>") + Item_ref(&select_lex->context, + select_lex->ref_pointer_array + i, + (char *)"<no matter>", + (char *)"<list ref>") ); Item *item_isnull= new Item_func_isnull(new - Item_ref( select_lex-> - ref_pointer_array+i, - (char *)"<no matter>", - (char *)"<list ref>") + Item_ref(&select_lex->context, + select_lex->ref_pointer_array+i, + (char *)"<no matter>", + (char *)"<list ref>") ); having_item= and_items(having_item, @@ -1003,10 +1127,11 @@ Item_in_subselect::row_value_transformer(JOIN *join) new Item_is_not_null_test(this, new - Item_ref(select_lex-> - ref_pointer_array + i, - (char *)"<no matter>", - (char *)"<list ref>") + Item_ref(&select_lex->context, + select_lex-> + ref_pointer_array + i, + (char *)"<no matter>", + (char *)"<list ref>") ) ); item_having_part2->top_level_item(); @@ -1043,15 +1168,17 @@ Item_in_subselect::row_value_transformer(JOIN *join) DBUG_RETURN(RES_ERROR); item= new Item_func_eq(new - Item_direct_ref((*optimizer->get_cache())-> + Item_direct_ref(&select_lex->context, + (*optimizer->get_cache())-> addr(i), (char *)"<no matter>", (char *)in_left_expr_name), new - Item_direct_ref( select_lex-> - ref_pointer_array+i, - (char *)"<no matter>", - (char *)"<list ref>") + Item_direct_ref(&select_lex->context, + select_lex-> + ref_pointer_array+i, + (char *)"<no matter>", + (char *)"<list ref>") ); if (!abort_on_null) { @@ -1060,18 +1187,20 @@ Item_in_subselect::row_value_transformer(JOIN *join) new Item_is_not_null_test(this, new - Item_ref(select_lex-> - ref_pointer_array + i, - (char *)"<no matter>", - (char *)"<list ref>") + Item_ref(&select_lex->context, + select_lex-> + ref_pointer_array + i, + (char *)"<no matter>", + (char *)"<list ref>") ) ); item_isnull= new Item_func_isnull(new - Item_direct_ref( select_lex-> - ref_pointer_array+i, - (char *)"<no matter>", - (char *)"<list ref>") + Item_direct_ref(&select_lex->context, + select_lex-> + ref_pointer_array+i, + (char *)"<no matter>", + (char *)"<list ref>") ); item= new Item_cond_or(item, item_isnull); @@ -1086,7 +1215,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) */ select_lex->where= join->conds= and_items(join->conds, where_item); select_lex->where->top_level_item(); - if (join->conds->fix_fields(thd, join->tables_list, 0)) + if (join->conds->fix_fields(thd, 0)) DBUG_RETURN(RES_ERROR); } if (having_item) @@ -1100,13 +1229,14 @@ Item_in_subselect::row_value_transformer(JOIN *join) argument (reference) to fix_fields() */ select_lex->having_fix_field= 1; - res= join->having->fix_fields(thd, join->tables_list, 0); + res= join->having->fix_fields(thd, 0); select_lex->having_fix_field= 0; if (res) { DBUG_RETURN(RES_ERROR); } } + DBUG_RETURN(RES_OK); } @@ -1142,7 +1272,7 @@ Item_in_subselect::select_transformer(JOIN *join) Item_subselect::trans_res Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func) { - Item_arena *arena, backup; + Query_arena *arena, backup; SELECT_LEX *current= thd->lex->current_select, *up; const char *save_where= thd->where; Item_subselect::trans_res res= RES_ERROR; @@ -1164,18 +1294,17 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func) */ if (!optimizer) { - arena= thd->change_arena_if_needed(&backup); + arena= thd->activate_stmt_arena_if_needed(&backup); result= (!(optimizer= new Item_in_optimizer(left_expr, this))); if (arena) - thd->restore_backup_item_arena(arena, &backup); + thd->restore_active_arena(arena, &backup); if (result) goto err; } thd->lex->current_select= up= current->return_after_parsing(); result= (!left_expr->fixed && - left_expr->fix_fields(thd, up->get_table_list(), - optimizer->arguments())); + left_expr->fix_fields(thd, optimizer->arguments())); /* fix_fields can change reference to left_expr, we need reassign it */ left_expr= optimizer->arguments()[0]; @@ -1184,7 +1313,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func) goto err; transformed= 1; - arena= thd->change_arena_if_needed(&backup); + arena= thd->activate_stmt_arena_if_needed(&backup); /* Both transformers call fix_fields() only for Items created inside them, and all that items do not make permanent changes in current item arena @@ -1200,14 +1329,14 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func) if (func != &eq_creator) { if (arena) - thd->restore_backup_item_arena(arena, &backup); + thd->restore_active_arena(arena, &backup); my_error(ER_OPERAND_COLUMNS, MYF(0), 1); DBUG_RETURN(RES_ERROR); } res= row_value_transformer(join); } if (arena) - thd->restore_backup_item_arena(arena, &backup); + thd->restore_active_arena(arena, &backup); err: thd->where= save_where; DBUG_RETURN(res); @@ -1217,16 +1346,27 @@ err: void Item_in_subselect::print(String *str) { if (transformed) - str->append("<exists>", 8); + str->append(STRING_WITH_LEN("<exists>")); else { left_expr->print(str); - str->append(" in ", 4); + str->append(STRING_WITH_LEN(" in ")); } Item_subselect::print(str); } +bool Item_in_subselect::fix_fields(THD *thd, Item **ref) +{ + bool result = 0; + + if(thd->lex->view_prepare_mode && left_expr && !left_expr->fixed) + result = left_expr->fix_fields(thd, &left_expr); + + return result || Item_subselect::fix_fields(thd, ref); +} + + Item_subselect::trans_res Item_allany_subselect::select_transformer(JOIN *join) { @@ -1240,7 +1380,7 @@ Item_allany_subselect::select_transformer(JOIN *join) void Item_allany_subselect::print(String *str) { if (transformed) - str->append("<exists>", 8); + str->append(STRING_WITH_LEN("<exists>")); else { left_expr->print(str); @@ -1252,24 +1392,23 @@ void Item_allany_subselect::print(String *str) } +void subselect_engine::set_thd(THD *thd_arg) +{ + thd= thd_arg; + if (result) + result->set_thd(thd_arg); +} + + subselect_single_select_engine:: subselect_single_select_engine(st_select_lex *select, select_subselect *result, Item_subselect *item) :subselect_engine(item, result), - prepared(0), optimized(0), executed(0), join(0) + prepared(0), optimized(0), executed(0), + select_lex(select), join(0) { - select_lex= select; - SELECT_LEX_UNIT *unit= select_lex->master_unit(); - unit->offset_limit_cnt= unit->global_parameters->offset_limit; - unit->select_limit_cnt= unit->global_parameters->select_limit+ - unit->global_parameters ->offset_limit; - if (unit->select_limit_cnt < unit->global_parameters->select_limit) - unit->select_limit_cnt= HA_POS_ERROR; // no limit - if (unit->select_limit_cnt == HA_POS_ERROR) - select_lex->options&= ~OPTION_FOUND_ROWS; - unit->item= item; - this->select_lex= select_lex; + select_lex->master_unit()->item= item; } @@ -1292,6 +1431,12 @@ void subselect_union_engine::cleanup() } +bool subselect_union_engine::is_executed() const +{ + return unit->executed; +} + + void subselect_uniquesubquery_engine::cleanup() { DBUG_ENTER("subselect_uniquesubquery_engine::cleanup"); @@ -1347,7 +1492,7 @@ int subselect_single_select_engine::prepare() int subselect_union_engine::prepare() { - return unit->prepare(thd, result, SELECT_NO_UNLOCK, ""); + return unit->prepare(thd, result, SELECT_NO_UNLOCK); } int subselect_uniquesubquery_engine::prepare() @@ -1368,6 +1513,7 @@ static Item_result set_row(List<Item> &item_list, Item *item, item->max_length= sel_item->max_length; res_type= sel_item->result_type(); item->decimals= sel_item->decimals; + item->unsigned_flag= sel_item->unsigned_flag; *maybe_null= sel_item->maybe_null; if (!(row[i]= Item_cache::get_cache(res_type))) return STRING_RESULT; // we should return something @@ -1412,17 +1558,20 @@ void subselect_uniquesubquery_engine::fix_length_and_dec(Item_cache **row) int subselect_single_select_engine::exec() { DBUG_ENTER("subselect_single_select_engine::exec"); - char const *save_where= join->thd->where; - SELECT_LEX *save_select= join->thd->lex->current_select; - join->thd->lex->current_select= select_lex; + char const *save_where= thd->where; + SELECT_LEX *save_select= thd->lex->current_select; + thd->lex->current_select= select_lex; if (!optimized) { - optimized=1; + SELECT_LEX_UNIT *unit= select_lex->master_unit(); + + optimized= 1; + unit->set_limit(unit->global_parameters); if (join->optimize()) { - join->thd->where= save_where; + thd->where= save_where; executed= 1; - join->thd->lex->current_select= save_select; + thd->lex->current_select= save_select; DBUG_RETURN(join->error ? join->error : 1); } if (item->engine_changed) @@ -1434,8 +1583,8 @@ int subselect_single_select_engine::exec() { if (join->reinit()) { - join->thd->where= save_where; - join->thd->lex->current_select= save_select; + thd->where= save_where; + thd->lex->current_select= save_select; DBUG_RETURN(1); } item->reset(); @@ -1446,20 +1595,20 @@ int subselect_single_select_engine::exec() item->reset_value_registration(); join->exec(); executed= 1; - join->thd->where= save_where; - join->thd->lex->current_select= save_select; + thd->where= save_where; + thd->lex->current_select= save_select; DBUG_RETURN(join->error||thd->is_fatal_error); } - join->thd->where= save_where; - join->thd->lex->current_select= save_select; + thd->where= save_where; + thd->lex->current_select= save_select; DBUG_RETURN(0); } int subselect_union_engine::exec() { - char const *save_where= unit->thd->where; + char const *save_where= thd->where; int res= unit->exec(); - unit->thd->where= save_where; + thd->where= save_where; return res; } @@ -1582,7 +1731,7 @@ int subselect_indexsubquery_engine::exec() uint subselect_single_select_engine::cols() { - DBUG_ASSERT(select_lex->join); // should be called after fix_fields() + DBUG_ASSERT(select_lex->join != 0); // should be called after fix_fields() return select_lex->join->fields_list.elements; } @@ -1627,7 +1776,7 @@ void subselect_uniquesubquery_engine::exclude() table_map subselect_engine::calc_const_tables(TABLE_LIST *table) { table_map map= 0; - for (; table; table= table->next) + for (; table; table= table->next_leaf) { TABLE *tbl= table->table; if (tbl && tbl->const_table) @@ -1640,14 +1789,13 @@ table_map subselect_engine::calc_const_tables(TABLE_LIST *table) table_map subselect_single_select_engine::upper_select_const_tables() { return calc_const_tables((TABLE_LIST *) select_lex->outer_select()-> - table_list.first); + leaf_tables); } table_map subselect_union_engine::upper_select_const_tables() { - return calc_const_tables((TABLE_LIST *) unit->outer_select()-> - table_list.first); + return calc_const_tables((TABLE_LIST *) unit->outer_select()->leaf_tables); } @@ -1665,16 +1813,16 @@ void subselect_union_engine::print(String *str) void subselect_uniquesubquery_engine::print(String *str) { - str->append("<primary_index_lookup>(", 23); + str->append(STRING_WITH_LEN("<primary_index_lookup>(")); tab->ref.items[0]->print(str); - str->append(" in ", 4); - str->append(tab->table->real_name); + str->append(STRING_WITH_LEN(" in ")); + str->append(tab->table->s->table_name); KEY *key_info= tab->table->key_info+ tab->ref.key; - str->append(" on ", 4); + str->append(STRING_WITH_LEN(" on ")); str->append(key_info->name); if (cond) { - str->append(" where ", 7); + str->append(STRING_WITH_LEN(" where ")); cond->print(str); } str->append(')'); @@ -1683,18 +1831,18 @@ void subselect_uniquesubquery_engine::print(String *str) void subselect_indexsubquery_engine::print(String *str) { - str->append("<index_lookup>(", 15); + str->append(STRING_WITH_LEN("<index_lookup>(")); tab->ref.items[0]->print(str); - str->append(" in ", 4); - str->append(tab->table->real_name); + str->append(STRING_WITH_LEN(" in ")); + str->append(tab->table->s->table_name); KEY *key_info= tab->table->key_info+ tab->ref.key; - str->append(" on ", 4); + str->append(STRING_WITH_LEN(" on ")); str->append(key_info->name); if (check_null) - str->append(" chicking NULL", 14); + str->append(STRING_WITH_LEN(" checking NULL")); if (cond) { - str->append(" where ", 7); + str->append(STRING_WITH_LEN(" where ")); cond->print(str); } str->append(')'); @@ -1703,18 +1851,18 @@ void subselect_indexsubquery_engine::print(String *str) /* change select_result object of engine - SINOPSYS + SYNOPSIS subselect_single_select_engine::change_result() si new subselect Item res new select_result object RETURN - 0 OK - -1 error + FALSE OK + TRUE error */ -int subselect_single_select_engine::change_item(Item_subselect *si, - select_subselect *res) +bool subselect_single_select_engine::change_result(Item_subselect *si, + select_subselect *res) { item= si; result= res; @@ -1725,18 +1873,18 @@ int subselect_single_select_engine::change_item(Item_subselect *si, /* change select_result object of engine - SINOPSYS + SYNOPSIS subselect_single_select_engine::change_result() si new subselect Item res new select_result object RETURN - 0 OK - -1 error + FALSE OK + TRUE error */ -int subselect_union_engine::change_item(Item_subselect *si, - select_subselect *res) +bool subselect_union_engine::change_result(Item_subselect *si, + select_subselect *res) { item= si; int rc= unit->change_result(res, result); @@ -1748,27 +1896,28 @@ int subselect_union_engine::change_item(Item_subselect *si, /* change select_result emulation, never should be called - SINOPSYS + SYNOPSIS subselect_single_select_engine::change_result() si new subselect Item res new select_result object RETURN - -1 error + FALSE OK + TRUE error */ -int subselect_uniquesubquery_engine::change_item(Item_subselect *si, - select_subselect *res) +bool subselect_uniquesubquery_engine::change_result(Item_subselect *si, + select_subselect *res) { DBUG_ASSERT(0); - return -1; + return TRUE; } /* Report about presence of tables in subquery - SINOPSYS + SYNOPSIS subselect_single_select_engine::no_tables() RETURN @@ -1784,7 +1933,7 @@ bool subselect_single_select_engine::no_tables() /* Report about presence of tables in subquery - SINOPSYS + SYNOPSIS subselect_union_engine::no_tables() RETURN @@ -1805,7 +1954,7 @@ bool subselect_union_engine::no_tables() /* Report about presence of tables in subquery - SINOPSYS + SYNOPSIS subselect_uniquesubquery_engine::no_tables() RETURN |