mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
merge
This commit is contained in:
@ -969,8 +969,10 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||||||
|
|
||||||
void Item_field::cleanup()
|
void Item_field::cleanup()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Item_field::cleanup");
|
||||||
Item_ident::cleanup();
|
Item_ident::cleanup();
|
||||||
field= result_field= 0;
|
field= result_field= 0;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::init_make_field(Send_field *tmp_field,
|
void Item::init_make_field(Send_field *tmp_field,
|
||||||
@ -1613,9 +1615,11 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
|
|||||||
|
|
||||||
void Item_ref::cleanup()
|
void Item_ref::cleanup()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Item_ref::cleanup");
|
||||||
Item_ident::cleanup();
|
Item_ident::cleanup();
|
||||||
if (hook_ptr)
|
if (hook_ptr)
|
||||||
*hook_ptr= orig_item;
|
*hook_ptr= orig_item;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
25
sql/item.h
25
sql/item.h
@ -128,7 +128,13 @@ public:
|
|||||||
virtual ~Item() { name=0; } /*lint -e1509 */
|
virtual ~Item() { name=0; } /*lint -e1509 */
|
||||||
void set_name(const char *str,uint length, CHARSET_INFO *cs);
|
void set_name(const char *str,uint length, CHARSET_INFO *cs);
|
||||||
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
|
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
|
||||||
virtual void cleanup() { fixed=0; }
|
virtual void cleanup()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item::cleanup");
|
||||||
|
DBUG_PRINT("info", ("Type: %d", (int)type()));
|
||||||
|
fixed=0;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
virtual void make_field(Send_field *field);
|
virtual void make_field(Send_field *field);
|
||||||
virtual bool fix_fields(THD *, struct st_table_list *, Item **);
|
virtual bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||||
virtual int save_in_field(Field *field, bool no_conversions);
|
virtual int save_in_field(Field *field, bool no_conversions);
|
||||||
@ -413,6 +419,7 @@ public:
|
|||||||
int save_in_field(Field *field, bool no_conversions);
|
int save_in_field(Field *field, bool no_conversions);
|
||||||
bool basic_const_item() const { return 1; }
|
bool basic_const_item() const { return 1; }
|
||||||
Item *new_item() { return new Item_int(name,value,max_length); }
|
Item *new_item() { return new Item_int(name,value,max_length); }
|
||||||
|
void cleanup() { fixed= 1; } // to privent drop fixed flag
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -900,6 +907,8 @@ public:
|
|||||||
enum Type type() const { return CACHE_ITEM; }
|
enum Type type() const { return CACHE_ITEM; }
|
||||||
static Item_cache* get_cache(Item_result type);
|
static Item_cache* get_cache(Item_result type);
|
||||||
table_map used_tables() const { return used_table_map; }
|
table_map used_tables() const { return used_table_map; }
|
||||||
|
virtual void keep_array() {}
|
||||||
|
void cleanup() { fixed= 1; } // to privent drop fixed flag
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -952,8 +961,10 @@ class Item_cache_row: public Item_cache
|
|||||||
{
|
{
|
||||||
Item_cache **values;
|
Item_cache **values;
|
||||||
uint item_count;
|
uint item_count;
|
||||||
|
bool save_array;
|
||||||
public:
|
public:
|
||||||
Item_cache_row(): Item_cache(), values(0), item_count(2) {}
|
Item_cache_row()
|
||||||
|
:Item_cache(), values(0), item_count(2), save_array(0) {}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
'allocate' used only in row transformer, to preallocate space for row
|
'allocate' used only in row transformer, to preallocate space for row
|
||||||
@ -994,10 +1005,16 @@ public:
|
|||||||
bool check_cols(uint c);
|
bool check_cols(uint c);
|
||||||
bool null_inside();
|
bool null_inside();
|
||||||
void bring_value();
|
void bring_value();
|
||||||
|
void keep_array() { save_array= 1; }
|
||||||
void cleanup()
|
void cleanup()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Item_cache_row::cleanup");
|
||||||
Item_cache::cleanup();
|
Item_cache::cleanup();
|
||||||
values= 0;
|
if (save_array)
|
||||||
|
bzero(values, item_count*sizeof(Item**));
|
||||||
|
else
|
||||||
|
values= 0;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1023,8 +1040,10 @@ public:
|
|||||||
Field *example() { return field_example; }
|
Field *example() { return field_example; }
|
||||||
void cleanup()
|
void cleanup()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Item_type_holder::cleanup");
|
||||||
Item::cleanup();
|
Item::cleanup();
|
||||||
item_type= orig_type;
|
item_type= orig_type;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -500,7 +500,6 @@ bool Item_in_optimizer::fix_left(THD *thd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
|
bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
|
||||||
Item ** ref)
|
Item ** ref)
|
||||||
{
|
{
|
||||||
@ -526,6 +525,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_in_optimizer::val_int()
|
longlong Item_in_optimizer::val_int()
|
||||||
{
|
{
|
||||||
cache->store(args[0]);
|
cache->store(args[0]);
|
||||||
@ -539,18 +539,38 @@ longlong Item_in_optimizer::val_int()
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_in_optimizer::keep_top_level_cache()
|
||||||
|
{
|
||||||
|
cache->keep_array();
|
||||||
|
save_cache= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_in_optimizer::cleanup()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_in_optimizer::cleanup");
|
||||||
|
Item_bool_func::cleanup();
|
||||||
|
if (!save_cache)
|
||||||
|
cache= 0;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_in_optimizer::is_null()
|
bool Item_in_optimizer::is_null()
|
||||||
{
|
{
|
||||||
cache->store(args[0]);
|
cache->store(args[0]);
|
||||||
return (null_value= (cache->null_value || args[1]->is_null()));
|
return (null_value= (cache->null_value || args[1]->is_null()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_func_eq::val_int()
|
longlong Item_func_eq::val_int()
|
||||||
{
|
{
|
||||||
int value= cmp.compare();
|
int value= cmp.compare();
|
||||||
return value == 0 ? 1 : 0;
|
return value == 0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Same as Item_func_eq, but NULL = NULL */
|
/* Same as Item_func_eq, but NULL = NULL */
|
||||||
|
|
||||||
void Item_func_equal::fix_length_and_dec()
|
void Item_func_equal::fix_length_and_dec()
|
||||||
|
@ -93,9 +93,10 @@ class Item_in_optimizer: public Item_bool_func
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
Item_cache *cache;
|
Item_cache *cache;
|
||||||
|
bool save_cache;
|
||||||
public:
|
public:
|
||||||
Item_in_optimizer(Item *a, Item_in_subselect *b):
|
Item_in_optimizer(Item *a, Item_in_subselect *b):
|
||||||
Item_bool_func(a, (Item *)b), cache(0) {}
|
Item_bool_func(a, (Item *)b), cache(0), save_cache(0) {}
|
||||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||||
bool fix_left(THD *thd, struct st_table_list *tables, Item **ref);
|
bool fix_left(THD *thd, struct st_table_list *tables, Item **ref);
|
||||||
bool is_null();
|
bool is_null();
|
||||||
@ -107,8 +108,10 @@ public:
|
|||||||
Item_in_optimizer return NULL, else it evaluate Item_in_subselect.
|
Item_in_optimizer return NULL, else it evaluate Item_in_subselect.
|
||||||
*/
|
*/
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
|
void cleanup();
|
||||||
const char *func_name() const { return "<in_optimizer>"; }
|
const char *func_name() const { return "<in_optimizer>"; }
|
||||||
Item_cache **get_cache() { return &cache; }
|
Item_cache **get_cache() { return &cache; }
|
||||||
|
void keep_top_level_cache();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Comp_creator
|
class Comp_creator
|
||||||
@ -209,9 +212,11 @@ public:
|
|||||||
}
|
}
|
||||||
void cleanup()
|
void cleanup()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Item_bool_rowready_func2::cleanup");
|
||||||
Item_bool_func2::cleanup();
|
Item_bool_func2::cleanup();
|
||||||
tmp_arg[0]= orig_a;
|
tmp_arg[0]= orig_a;
|
||||||
tmp_arg[1]= orig_b;
|
tmp_arg[1]= orig_b;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -720,10 +725,12 @@ class Item_func_in :public Item_int_func
|
|||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
void cleanup()
|
void cleanup()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Item_func_in::cleanup");
|
||||||
delete array;
|
delete array;
|
||||||
delete in_item;
|
delete in_item;
|
||||||
array= 0;
|
array= 0;
|
||||||
in_item= 0;
|
in_item= 0;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
optimize_type select_optimize() const
|
optimize_type select_optimize() const
|
||||||
{ return array ? OPTIMIZE_KEY : OPTIMIZE_NONE; }
|
{ return array ? OPTIMIZE_KEY : OPTIMIZE_NONE; }
|
||||||
|
@ -999,6 +999,7 @@ public:
|
|||||||
join_key(0), ft_handler(0), table(0), master(0), concat(0) { }
|
join_key(0), ft_handler(0), table(0), master(0), concat(0) { }
|
||||||
void cleanup()
|
void cleanup()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Item_func_match");
|
||||||
if (!master && ft_handler)
|
if (!master && ft_handler)
|
||||||
{
|
{
|
||||||
ft_handler->please->close_search(ft_handler);
|
ft_handler->please->close_search(ft_handler);
|
||||||
@ -1009,6 +1010,7 @@ public:
|
|||||||
}
|
}
|
||||||
if (concat)
|
if (concat)
|
||||||
delete concat;
|
delete concat;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
enum Functype functype() const { return FT_FUNC; }
|
enum Functype functype() const { return FT_FUNC; }
|
||||||
const char *func_name() const { return "match"; }
|
const char *func_name() const { return "match"; }
|
||||||
|
@ -35,9 +35,9 @@ inline Item * and_items(Item* cond, Item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item_subselect::Item_subselect():
|
Item_subselect::Item_subselect():
|
||||||
Item_result_field(), value_assigned(0), substitution(0),
|
Item_result_field(), value_assigned(0), thd(0), substitution(0),
|
||||||
engine(0), used_tables_cache(0), have_to_be_excluded(0),
|
engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0),
|
||||||
const_item_cache(1), engine_changed(0)
|
const_item_cache(1), engine_changed(0), changed(0)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
/*
|
/*
|
||||||
@ -54,9 +54,10 @@ void Item_subselect::init(st_select_lex *select_lex,
|
|||||||
|
|
||||||
DBUG_ENTER("Item_subselect::init");
|
DBUG_ENTER("Item_subselect::init");
|
||||||
DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex));
|
DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex));
|
||||||
|
unit= select_lex->master_unit();
|
||||||
|
|
||||||
if (select_lex->next_select())
|
if (select_lex->next_select())
|
||||||
engine= new subselect_union_engine(select_lex->master_unit(), result,
|
engine= new subselect_union_engine(unit, result,
|
||||||
this);
|
this);
|
||||||
else
|
else
|
||||||
engine= new subselect_single_select_engine(select_lex, result, this);
|
engine= new subselect_single_select_engine(select_lex, result, this);
|
||||||
@ -65,8 +66,26 @@ void Item_subselect::init(st_select_lex *select_lex,
|
|||||||
|
|
||||||
void Item_subselect::cleanup()
|
void Item_subselect::cleanup()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Item_subselect::cleanup");
|
||||||
Item_result_field::cleanup();
|
Item_result_field::cleanup();
|
||||||
|
if (old_engine)
|
||||||
|
{
|
||||||
|
engine->cleanup();
|
||||||
|
engine= old_engine;
|
||||||
|
old_engine= 0;
|
||||||
|
}
|
||||||
engine->cleanup();
|
engine->cleanup();
|
||||||
|
reset();
|
||||||
|
value_assigned= 0;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Item_singlerow_subselect::cleanup()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_singlerow_subselect::cleanup");
|
||||||
|
value= 0; row= 0;
|
||||||
|
Item_subselect::cleanup();
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item_subselect::~Item_subselect()
|
Item_subselect::~Item_subselect()
|
||||||
@ -85,13 +104,22 @@ 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, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
engine->set_thd((thd= thd_param));
|
engine->set_thd((thd= thd_param));
|
||||||
|
stmt= thd->current_statement;
|
||||||
|
|
||||||
char const *save_where= thd->where;
|
char const *save_where= thd->where;
|
||||||
int res= engine->prepare();
|
int res= engine->prepare();
|
||||||
|
|
||||||
|
// all transformetion is done (used by prepared statements)
|
||||||
|
changed= 1;
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
if (substitution)
|
if (substitution)
|
||||||
{
|
{
|
||||||
|
// did we changed top item of WHERE condition
|
||||||
|
if (unit->outer_select()->where == (*ref))
|
||||||
|
unit->outer_select()->where= substitution; // correct WHERE for PS
|
||||||
|
|
||||||
(*ref)= substitution;
|
(*ref)= substitution;
|
||||||
substitution->name= name;
|
substitution->name= name;
|
||||||
if (have_to_be_excluded)
|
if (have_to_be_excluded)
|
||||||
@ -240,7 +268,11 @@ void Item_singlerow_subselect::reset()
|
|||||||
Item_subselect::trans_res
|
Item_subselect::trans_res
|
||||||
Item_singlerow_subselect::select_transformer(JOIN *join)
|
Item_singlerow_subselect::select_transformer(JOIN *join)
|
||||||
{
|
{
|
||||||
|
if (changed)
|
||||||
|
return RES_OK;
|
||||||
|
|
||||||
SELECT_LEX *select_lex= join->select_lex;
|
SELECT_LEX *select_lex= join->select_lex;
|
||||||
|
Statement backup;
|
||||||
|
|
||||||
if (!select_lex->master_unit()->first_select()->next_select() &&
|
if (!select_lex->master_unit()->first_select()->next_select() &&
|
||||||
!select_lex->table_list.elements &&
|
!select_lex->table_list.elements &&
|
||||||
@ -275,20 +307,30 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
|
|||||||
if (join->conds || join->having)
|
if (join->conds || join->having)
|
||||||
{
|
{
|
||||||
Item *cond;
|
Item *cond;
|
||||||
|
if (stmt)
|
||||||
|
thd->set_n_backup_item_arena(stmt, &backup);
|
||||||
|
|
||||||
if (!join->having)
|
if (!join->having)
|
||||||
cond= join->conds;
|
cond= join->conds;
|
||||||
else if (!join->conds)
|
else if (!join->conds)
|
||||||
cond= join->having;
|
cond= join->having;
|
||||||
else
|
else
|
||||||
if (!(cond= new Item_cond_and(join->conds, join->having)))
|
if (!(cond= new Item_cond_and(join->conds, join->having)))
|
||||||
return RES_ERROR;
|
goto err;
|
||||||
if (!(substitution= new Item_func_if(cond, substitution,
|
if (!(substitution= new Item_func_if(cond, substitution,
|
||||||
new Item_null())))
|
new Item_null())))
|
||||||
return RES_ERROR;
|
goto err;
|
||||||
}
|
}
|
||||||
|
if (stmt)
|
||||||
|
thd->restore_backup_item_arena(stmt, &backup);
|
||||||
return RES_REDUCE;
|
return RES_REDUCE;
|
||||||
}
|
}
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (stmt)
|
||||||
|
thd->restore_backup_item_arena(stmt, &backup);
|
||||||
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item_singlerow_subselect::store(uint i, Item *item)
|
void Item_singlerow_subselect::store(uint i, Item *item)
|
||||||
@ -550,15 +592,22 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("Item_in_subselect::single_value_transformer");
|
DBUG_ENTER("Item_in_subselect::single_value_transformer");
|
||||||
|
|
||||||
SELECT_LEX *select_lex= join->select_lex;
|
if (changed)
|
||||||
|
{
|
||||||
|
DBUG_RETURN(RES_OK);
|
||||||
|
}
|
||||||
|
|
||||||
THD *thd_tmp= join->thd;
|
SELECT_LEX *select_lex= join->select_lex;
|
||||||
thd_tmp->where= "scalar IN/ALL/ANY subquery";
|
Statement backup;
|
||||||
|
|
||||||
|
thd->where= "scalar IN/ALL/ANY subquery";
|
||||||
|
if (stmt)
|
||||||
|
thd->set_n_backup_item_arena(stmt, &backup);
|
||||||
|
|
||||||
if (select_lex->item_list.elements > 1)
|
if (select_lex->item_list.elements > 1)
|
||||||
{
|
{
|
||||||
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
|
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
|
||||||
DBUG_RETURN(RES_ERROR);
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((abort_on_null || (upper_not && upper_not->top_level())) &&
|
if ((abort_on_null || (upper_not && upper_not->top_level())) &&
|
||||||
@ -567,7 +616,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
if (substitution)
|
if (substitution)
|
||||||
{
|
{
|
||||||
// It is second (third, ...) SELECT of UNION => All is done
|
// It is second (third, ...) SELECT of UNION => All is done
|
||||||
DBUG_RETURN(RES_OK);
|
goto ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item *subs;
|
Item *subs;
|
||||||
@ -597,10 +646,9 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
select_lex->item_list.empty();
|
select_lex->item_list.empty();
|
||||||
select_lex->item_list.push_back(item);
|
select_lex->item_list.push_back(item);
|
||||||
|
|
||||||
if (item->fix_fields(thd_tmp, join->tables_list, &item))
|
if (item->fix_fields(thd, join->tables_list, &item))
|
||||||
{
|
goto err;
|
||||||
DBUG_RETURN(RES_ERROR);
|
|
||||||
}
|
|
||||||
subs= new Item_singlerow_subselect(select_lex);
|
subs= new Item_singlerow_subselect(select_lex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -611,16 +659,16 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
subs= new Item_maxmin_subselect(this, select_lex, func->l_op());
|
subs= new Item_maxmin_subselect(this, select_lex, func->l_op());
|
||||||
}
|
}
|
||||||
// left expression belong to outer select
|
// left expression belong to outer select
|
||||||
SELECT_LEX *current= thd_tmp->lex->current_select, *up;
|
SELECT_LEX *current= thd->lex->current_select, *up;
|
||||||
thd_tmp->lex->current_select= up= current->return_after_parsing();
|
thd->lex->current_select= up= current->return_after_parsing();
|
||||||
if (left_expr->fix_fields(thd_tmp, up->get_table_list(), &left_expr))
|
if (left_expr->fix_fields(thd, up->get_table_list(), &left_expr))
|
||||||
{
|
{
|
||||||
thd_tmp->lex->current_select= current;
|
thd->lex->current_select= current;
|
||||||
DBUG_RETURN(RES_ERROR);
|
goto err;
|
||||||
}
|
}
|
||||||
thd_tmp->lex->current_select= current;
|
thd->lex->current_select= current;
|
||||||
substitution= func->create(left_expr, subs);
|
substitution= func->create(left_expr, subs);
|
||||||
DBUG_RETURN(RES_OK);
|
goto ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!substitution)
|
if (!substitution)
|
||||||
@ -629,16 +677,16 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
||||||
substitution= optimizer= new Item_in_optimizer(left_expr, this);
|
substitution= optimizer= new Item_in_optimizer(left_expr, this);
|
||||||
|
|
||||||
SELECT_LEX *current= thd_tmp->lex->current_select, *up;
|
SELECT_LEX *current= thd->lex->current_select, *up;
|
||||||
|
|
||||||
thd_tmp->lex->current_select= up= current->return_after_parsing();
|
thd->lex->current_select= up= current->return_after_parsing();
|
||||||
//optimizer never use Item **ref => we can pass 0 as parameter
|
//optimizer never use Item **ref => we can pass 0 as parameter
|
||||||
if (!optimizer || optimizer->fix_left(thd_tmp, up->get_table_list(), 0))
|
if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
|
||||||
{
|
{
|
||||||
thd_tmp->lex->current_select= current;
|
thd->lex->current_select= current;
|
||||||
DBUG_RETURN(RES_ERROR);
|
goto err;
|
||||||
}
|
}
|
||||||
thd_tmp->lex->current_select= current;
|
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 substitude itself on fix_fields
|
||||||
@ -665,12 +713,12 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
select_lex->ref_pointer_array,
|
select_lex->ref_pointer_array,
|
||||||
(char *)"<ref>",
|
(char *)"<ref>",
|
||||||
this->full_name()));
|
this->full_name()));
|
||||||
join->having= and_items(join->having, item);
|
select_lex->having= join->having= and_items(join->having, item);
|
||||||
select_lex->having_fix_field= 1;
|
select_lex->having_fix_field= 1;
|
||||||
if (join->having->fix_fields(thd_tmp, join->tables_list, &join->having))
|
if (join->having->fix_fields(thd, join->tables_list, &join->having))
|
||||||
{
|
{
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
DBUG_RETURN(RES_ERROR);
|
goto err;
|
||||||
}
|
}
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
}
|
}
|
||||||
@ -687,39 +735,42 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
if (!abort_on_null)
|
if (!abort_on_null)
|
||||||
{
|
{
|
||||||
having= new Item_is_not_null_test(this, having);
|
having= new Item_is_not_null_test(this, having);
|
||||||
join->having= (join->having ?
|
select_lex->having=
|
||||||
new Item_cond_and(having, join->having) :
|
join->having= (join->having ?
|
||||||
having);
|
new Item_cond_and(having, join->having) :
|
||||||
|
having);
|
||||||
select_lex->having_fix_field= 1;
|
select_lex->having_fix_field= 1;
|
||||||
if (join->having->fix_fields(thd_tmp, join->tables_list,
|
if (join->having->fix_fields(thd, join->tables_list,
|
||||||
&join->having))
|
&join->having))
|
||||||
{
|
{
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
DBUG_RETURN(RES_ERROR);
|
goto err;
|
||||||
}
|
}
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
item= new Item_cond_or(item,
|
item= new Item_cond_or(item,
|
||||||
new Item_func_isnull(isnull));
|
new Item_func_isnull(isnull));
|
||||||
}
|
}
|
||||||
item->name= (char *)in_additional_cond;
|
item->name= (char *)in_additional_cond;
|
||||||
join->conds= and_items(join->conds, item);
|
select_lex->where= join->conds= and_items(join->conds, item);
|
||||||
if (join->conds->fix_fields(thd_tmp, join->tables_list, &join->conds))
|
if (join->conds->fix_fields(thd, join->tables_list, &join->conds))
|
||||||
DBUG_RETURN(RES_ERROR);
|
goto err;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (select_lex->master_unit()->first_select()->next_select())
|
if (select_lex->master_unit()->first_select()->next_select())
|
||||||
{
|
{
|
||||||
join->having= func->create(expr,
|
select_lex->having=
|
||||||
new Item_null_helper(this, item,
|
join->having=
|
||||||
(char *)"<no matter>",
|
func->create(expr,
|
||||||
(char *)"<result>"));
|
new Item_null_helper(this, item,
|
||||||
|
(char *)"<no matter>",
|
||||||
|
(char *)"<result>"));
|
||||||
select_lex->having_fix_field= 1;
|
select_lex->having_fix_field= 1;
|
||||||
if (join->having->fix_fields(thd_tmp, join->tables_list,
|
if (join->having->fix_fields(thd, join->tables_list,
|
||||||
&join->having))
|
&join->having))
|
||||||
{
|
{
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
DBUG_RETURN(RES_ERROR);
|
goto err;
|
||||||
}
|
}
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
}
|
}
|
||||||
@ -730,18 +781,29 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
// fix_field of item will be done in time of substituting
|
// fix_field of item will be done in time of substituting
|
||||||
substitution= item;
|
substitution= item;
|
||||||
have_to_be_excluded= 1;
|
have_to_be_excluded= 1;
|
||||||
if (thd_tmp->lex->describe)
|
if (thd->lex->describe)
|
||||||
{
|
{
|
||||||
char warn_buff[MYSQL_ERRMSG_SIZE];
|
char warn_buff[MYSQL_ERRMSG_SIZE];
|
||||||
sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number);
|
sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number);
|
||||||
push_warning(thd_tmp, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
ER_SELECT_REDUCED, warn_buff);
|
ER_SELECT_REDUCED, warn_buff);
|
||||||
}
|
}
|
||||||
|
if (stmt)
|
||||||
|
thd->restore_backup_item_arena(stmt, &backup);
|
||||||
DBUG_RETURN(RES_REDUCE);
|
DBUG_RETURN(RES_REDUCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ok:
|
||||||
|
if (stmt)
|
||||||
|
thd->restore_backup_item_arena(stmt, &backup);
|
||||||
DBUG_RETURN(RES_OK);
|
DBUG_RETURN(RES_OK);
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (stmt)
|
||||||
|
thd->restore_backup_item_arena(stmt, &backup);
|
||||||
|
DBUG_RETURN(RES_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -750,15 +812,23 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("Item_in_subselect::row_value_transformer");
|
DBUG_ENTER("Item_in_subselect::row_value_transformer");
|
||||||
|
|
||||||
THD *thd_tmp= join->thd;
|
if (changed)
|
||||||
thd_tmp->where= "row IN/ALL/ANY subquery";
|
{
|
||||||
|
DBUG_RETURN(RES_OK);
|
||||||
|
}
|
||||||
|
Statement backup;
|
||||||
|
Item *item= 0;
|
||||||
|
|
||||||
|
thd->where= "row IN/ALL/ANY subquery";
|
||||||
|
if (stmt)
|
||||||
|
thd->set_n_backup_item_arena(stmt, &backup);
|
||||||
|
|
||||||
SELECT_LEX *select_lex= join->select_lex;
|
SELECT_LEX *select_lex= join->select_lex;
|
||||||
|
|
||||||
if (select_lex->item_list.elements != left_expr->cols())
|
if (select_lex->item_list.elements != left_expr->cols())
|
||||||
{
|
{
|
||||||
my_error(ER_OPERAND_COLUMNS, MYF(0), left_expr->cols());
|
my_error(ER_OPERAND_COLUMNS, MYF(0), left_expr->cols());
|
||||||
DBUG_RETURN(RES_ERROR);
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!substitution)
|
if (!substitution)
|
||||||
@ -767,62 +837,72 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
|||||||
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
||||||
substitution= optimizer= new Item_in_optimizer(left_expr, this);
|
substitution= optimizer= new Item_in_optimizer(left_expr, this);
|
||||||
|
|
||||||
SELECT_LEX *current= thd_tmp->lex->current_select, *up;
|
SELECT_LEX *current= thd->lex->current_select, *up;
|
||||||
thd_tmp->lex->current_select= up= current->return_after_parsing();
|
thd->lex->current_select= up= current->return_after_parsing();
|
||||||
//optimizer never use Item **ref => we can pass 0 as parameter
|
//optimizer never use Item **ref => we can pass 0 as parameter
|
||||||
if (!optimizer || optimizer->fix_left(thd_tmp, up->get_table_list(), 0))
|
if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
|
||||||
{
|
{
|
||||||
thd_tmp->lex->current_select= current;
|
thd->lex->current_select= current;
|
||||||
DBUG_RETURN(RES_ERROR);
|
goto err;
|
||||||
}
|
}
|
||||||
thd_tmp->lex->current_select= current;
|
|
||||||
|
// we will refer to apper level cache array => we have to save it in PS
|
||||||
|
optimizer->keep_top_level_cache();
|
||||||
|
|
||||||
|
thd->lex->current_select= current;
|
||||||
unit->uncacheable|= UNCACHEABLE_DEPENDENT;
|
unit->uncacheable|= UNCACHEABLE_DEPENDENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint n= left_expr->cols();
|
|
||||||
|
|
||||||
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
|
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
|
||||||
select_lex->setup_ref_array(thd_tmp,
|
select_lex->setup_ref_array(thd,
|
||||||
select_lex->order_list.elements +
|
select_lex->order_list.elements +
|
||||||
select_lex->group_list.elements);
|
select_lex->group_list.elements);
|
||||||
Item *item= 0;
|
|
||||||
List_iterator_fast<Item> li(select_lex->item_list);
|
|
||||||
for (uint i= 0; i < n; i++)
|
|
||||||
{
|
{
|
||||||
Item *func= new Item_ref_null_helper(this,
|
uint n= left_expr->cols();
|
||||||
select_lex->ref_pointer_array+i,
|
List_iterator_fast<Item> li(select_lex->item_list);
|
||||||
(char *) "<no matter>",
|
for (uint i= 0; i < n; i++)
|
||||||
(char *) "<list ref>");
|
{
|
||||||
func=
|
Item *func= new Item_ref_null_helper(this,
|
||||||
eq_creator.create(new Item_ref((*optimizer->get_cache())->
|
select_lex->ref_pointer_array+i,
|
||||||
addr(i),
|
(char *) "<no matter>",
|
||||||
NULL,
|
(char *) "<list ref>");
|
||||||
(char *)"<no matter>",
|
func=
|
||||||
|
eq_creator.create(new Item_ref((*optimizer->get_cache())->
|
||||||
|
addr(i),
|
||||||
|
NULL,
|
||||||
|
(char *)"<no matter>",
|
||||||
(char *)in_left_expr_name),
|
(char *)in_left_expr_name),
|
||||||
func);
|
func);
|
||||||
item= and_items(item, func);
|
item= and_items(item, func);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (join->having || select_lex->with_sum_func ||
|
if (join->having || select_lex->with_sum_func ||
|
||||||
select_lex->group_list.first ||
|
select_lex->group_list.first ||
|
||||||
!select_lex->table_list.elements)
|
!select_lex->table_list.elements)
|
||||||
{
|
{
|
||||||
join->having= and_items(join->having, item);
|
select_lex->having= join->having= and_items(join->having, item);
|
||||||
select_lex->having_fix_field= 1;
|
select_lex->having_fix_field= 1;
|
||||||
if (join->having->fix_fields(thd_tmp, join->tables_list, &join->having))
|
if (join->having->fix_fields(thd, join->tables_list, &join->having))
|
||||||
{
|
{
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
DBUG_RETURN(RES_ERROR);
|
goto err;
|
||||||
}
|
}
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
join->conds= and_items(join->conds, item);
|
select_lex->where= join->conds= and_items(join->conds, item);
|
||||||
if (join->conds->fix_fields(thd_tmp, join->tables_list, &join->having))
|
if (join->conds->fix_fields(thd, join->tables_list, &join->having))
|
||||||
DBUG_RETURN(RES_ERROR);
|
goto err;
|
||||||
}
|
}
|
||||||
|
if (stmt)
|
||||||
|
thd->restore_backup_item_arena(stmt, &backup);
|
||||||
DBUG_RETURN(RES_OK);
|
DBUG_RETURN(RES_OK);
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (stmt)
|
||||||
|
thd->restore_backup_item_arena(stmt, &backup);
|
||||||
|
DBUG_RETURN(RES_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -894,13 +974,31 @@ subselect_single_select_engine(st_select_lex *select,
|
|||||||
this->select_lex= select_lex;
|
this->select_lex= select_lex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void subselect_single_select_engine::cleanup()
|
void subselect_single_select_engine::cleanup()
|
||||||
{
|
{
|
||||||
prepared= 0;
|
DBUG_ENTER("subselect_single_select_engine::cleanup");
|
||||||
optimized= 0;
|
prepared= optimized= executed= 0;
|
||||||
executed= 0;
|
join= 0;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void subselect_union_engine::cleanup()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("subselect_union_engine::cleanup");
|
||||||
|
unit->reinit_exec_mechanism();
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void subselect_uniquesubquery_engine::cleanup()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("subselect_uniquesubquery_engine::cleanup");
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
subselect_union_engine::subselect_union_engine(st_select_lex_unit *u,
|
subselect_union_engine::subselect_union_engine(st_select_lex_unit *u,
|
||||||
select_subselect *result_arg,
|
select_subselect *result_arg,
|
||||||
Item_subselect *item_arg)
|
Item_subselect *item_arg)
|
||||||
|
@ -26,6 +26,7 @@ class JOIN;
|
|||||||
class select_subselect;
|
class select_subselect;
|
||||||
class subselect_engine;
|
class subselect_engine;
|
||||||
class Item_bool_func2;
|
class Item_bool_func2;
|
||||||
|
class Statement;
|
||||||
|
|
||||||
/* base class for subselects */
|
/* base class for subselects */
|
||||||
|
|
||||||
@ -35,22 +36,30 @@ class Item_subselect :public Item_result_field
|
|||||||
protected:
|
protected:
|
||||||
/* thread handler, will be assigned in fix_fields only */
|
/* thread handler, will be assigned in fix_fields only */
|
||||||
THD *thd;
|
THD *thd;
|
||||||
|
/* prepared statement, or 0 */
|
||||||
|
Statement *stmt;
|
||||||
/* substitution instead of subselect in case of optimization */
|
/* substitution instead of subselect in case of optimization */
|
||||||
Item *substitution;
|
Item *substitution;
|
||||||
|
/* unit of subquery */
|
||||||
|
st_select_lex_unit *unit;
|
||||||
/* engine that perform execution of subselect (single select or union) */
|
/* engine that perform execution of subselect (single select or union) */
|
||||||
subselect_engine *engine;
|
subselect_engine *engine;
|
||||||
|
/* old engine if engine was changed */
|
||||||
|
subselect_engine *old_engine;
|
||||||
/* cache of used external tables */
|
/* cache of used external tables */
|
||||||
table_map used_tables_cache;
|
table_map used_tables_cache;
|
||||||
/* allowed number of columns (1 for single value subqueries) */
|
/* allowed number of columns (1 for single value subqueries) */
|
||||||
uint max_columns;
|
uint max_columns;
|
||||||
/* work with 'substitution' */
|
/* work with 'substitution' */
|
||||||
bool have_to_be_excluded;
|
bool have_to_be_excluded;
|
||||||
/* cache of constante state */
|
/* cache of constant state */
|
||||||
bool const_item_cache;
|
bool const_item_cache;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* changed engine indicator */
|
/* changed engine indicator */
|
||||||
bool engine_changed;
|
bool engine_changed;
|
||||||
|
/* subquery is transformed */
|
||||||
|
bool changed;
|
||||||
|
|
||||||
enum trans_res {RES_OK, RES_REDUCE, RES_ERROR};
|
enum trans_res {RES_OK, RES_REDUCE, RES_ERROR};
|
||||||
enum subs_type {UNKNOWN_SUBS, SINGLEROW_SUBS,
|
enum subs_type {UNKNOWN_SUBS, SINGLEROW_SUBS,
|
||||||
@ -94,6 +103,7 @@ public:
|
|||||||
void print(String *str);
|
void print(String *str);
|
||||||
bool change_engine(subselect_engine *eng)
|
bool change_engine(subselect_engine *eng)
|
||||||
{
|
{
|
||||||
|
old_engine= engine;
|
||||||
engine= eng;
|
engine= eng;
|
||||||
engine_changed= 1;
|
engine_changed= 1;
|
||||||
return eng == 0;
|
return eng == 0;
|
||||||
@ -116,6 +126,7 @@ public:
|
|||||||
Item_singlerow_subselect(st_select_lex *select_lex);
|
Item_singlerow_subselect(st_select_lex *select_lex);
|
||||||
Item_singlerow_subselect() :Item_subselect(), value(0), row (0) {}
|
Item_singlerow_subselect() :Item_subselect(), value(0), row (0) {}
|
||||||
|
|
||||||
|
void cleanup();
|
||||||
subs_type substype() { return SINGLEROW_SUBS; }
|
subs_type substype() { return SINGLEROW_SUBS; }
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
@ -200,13 +211,6 @@ public:
|
|||||||
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void cleanup()
|
|
||||||
{
|
|
||||||
Item_exists_subselect::cleanup();
|
|
||||||
abort_on_null= 0;
|
|
||||||
transformed= 0;
|
|
||||||
upper_not= 0;
|
|
||||||
}
|
|
||||||
subs_type substype() { return IN_SUBS; }
|
subs_type substype() { return IN_SUBS; }
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
@ -269,7 +273,7 @@ public:
|
|||||||
maybe_null= 0;
|
maybe_null= 0;
|
||||||
}
|
}
|
||||||
virtual ~subselect_engine() {}; // to satisfy compiler
|
virtual ~subselect_engine() {}; // to satisfy compiler
|
||||||
virtual void cleanup() {}
|
virtual void cleanup()= 0;
|
||||||
|
|
||||||
// set_thd should be called before prepare()
|
// set_thd should be called before prepare()
|
||||||
void set_thd(THD *thd_arg) { thd= thd_arg; }
|
void set_thd(THD *thd_arg) { thd= thd_arg; }
|
||||||
@ -318,6 +322,7 @@ public:
|
|||||||
subselect_union_engine(st_select_lex_unit *u,
|
subselect_union_engine(st_select_lex_unit *u,
|
||||||
select_subselect *result,
|
select_subselect *result,
|
||||||
Item_subselect *item);
|
Item_subselect *item);
|
||||||
|
void cleanup();
|
||||||
int prepare();
|
int prepare();
|
||||||
void fix_length_and_dec(Item_cache** row);
|
void fix_length_and_dec(Item_cache** row);
|
||||||
int exec();
|
int exec();
|
||||||
@ -345,6 +350,7 @@ public:
|
|||||||
set_thd(thd_arg);
|
set_thd(thd_arg);
|
||||||
}
|
}
|
||||||
~subselect_uniquesubquery_engine();
|
~subselect_uniquesubquery_engine();
|
||||||
|
void cleanup();
|
||||||
int prepare();
|
int prepare();
|
||||||
void fix_length_and_dec(Item_cache** row);
|
void fix_length_and_dec(Item_cache** row);
|
||||||
int exec();
|
int exec();
|
||||||
|
@ -1084,6 +1084,7 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
|
|||||||
|
|
||||||
void Item_sum_count_distinct::cleanup()
|
void Item_sum_count_distinct::cleanup()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Item_sum_count_distinct::cleanup");
|
||||||
Item_sum_int::cleanup();
|
Item_sum_int::cleanup();
|
||||||
/*
|
/*
|
||||||
Free table and tree if they belong to this item (if item have not pointer
|
Free table and tree if they belong to this item (if item have not pointer
|
||||||
@ -1104,6 +1105,7 @@ void Item_sum_count_distinct::cleanup()
|
|||||||
use_tree= 0;
|
use_tree= 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1672,6 +1674,7 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
|
|||||||
|
|
||||||
void Item_func_group_concat::cleanup()
|
void Item_func_group_concat::cleanup()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Item_func_group_concat::cleanup");
|
||||||
/*
|
/*
|
||||||
Free table and tree if they belong to this item (if item have not pointer
|
Free table and tree if they belong to this item (if item have not pointer
|
||||||
to original item from which was made copy => it own its objects )
|
to original item from which was made copy => it own its objects )
|
||||||
@ -1692,6 +1695,7 @@ void Item_func_group_concat::cleanup()
|
|||||||
delete_tree(tree);
|
delete_tree(tree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,8 +60,10 @@ public:
|
|||||||
Item_sum(THD *thd, Item_sum *item);
|
Item_sum(THD *thd, Item_sum *item);
|
||||||
void cleanup()
|
void cleanup()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Item_sum::cleanup");
|
||||||
Item_result_field::cleanup();
|
Item_result_field::cleanup();
|
||||||
result_field=0;
|
result_field=0;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Type type() const { return SUM_FUNC_ITEM; }
|
enum Type type() const { return SUM_FUNC_ITEM; }
|
||||||
|
@ -350,6 +350,11 @@ inline THD *_current_thd(void)
|
|||||||
#include "sql_udf.h"
|
#include "sql_udf.h"
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
typedef Comp_creator* (*chooser_compare_func_creator)(bool invert);
|
typedef Comp_creator* (*chooser_compare_func_creator)(bool invert);
|
||||||
|
/* sql_parse.cc */
|
||||||
|
void free_items(Item *item);
|
||||||
|
void cleanup_items(Item *item);
|
||||||
|
class THD;
|
||||||
|
void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0);
|
||||||
#include "sql_class.h"
|
#include "sql_class.h"
|
||||||
#include "opt_range.h"
|
#include "opt_range.h"
|
||||||
|
|
||||||
@ -411,7 +416,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
|
|||||||
bool mysql_change_db(THD *thd,const char *name);
|
bool mysql_change_db(THD *thd,const char *name);
|
||||||
void mysql_parse(THD *thd,char *inBuf,uint length);
|
void mysql_parse(THD *thd,char *inBuf,uint length);
|
||||||
bool is_update_query(enum enum_sql_command command);
|
bool is_update_query(enum enum_sql_command command);
|
||||||
void free_items(Item *item);
|
|
||||||
bool alloc_query(THD *thd, char *packet, ulong packet_length);
|
bool alloc_query(THD *thd, char *packet, ulong packet_length);
|
||||||
void mysql_init_select(LEX *lex);
|
void mysql_init_select(LEX *lex);
|
||||||
void mysql_init_query(THD *thd);
|
void mysql_init_query(THD *thd);
|
||||||
@ -688,7 +692,6 @@ bool rm_temporary_table(enum db_type base, char *path);
|
|||||||
void free_io_cache(TABLE *entry);
|
void free_io_cache(TABLE *entry);
|
||||||
void intern_close_table(TABLE *entry);
|
void intern_close_table(TABLE *entry);
|
||||||
bool close_thread_table(THD *thd, TABLE **table_ptr);
|
bool close_thread_table(THD *thd, TABLE **table_ptr);
|
||||||
void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0);
|
|
||||||
void close_temporary_tables(THD *thd);
|
void close_temporary_tables(THD *thd);
|
||||||
TABLE_LIST * find_table_in_list(TABLE_LIST *table,
|
TABLE_LIST * find_table_in_list(TABLE_LIST *table,
|
||||||
const char *db_name, const char *table_name);
|
const char *db_name, const char *table_name);
|
||||||
@ -766,9 +769,6 @@ uint check_word(TYPELIB *lib, const char *val, const char *end,
|
|||||||
|
|
||||||
bool is_keyword(const char *name, uint len);
|
bool is_keyword(const char *name, uint len);
|
||||||
|
|
||||||
/* sql_parse.cc */
|
|
||||||
void free_items(Item *item);
|
|
||||||
void cleanup_items(Item *item);
|
|
||||||
|
|
||||||
#define MY_DB_OPT_FILE "db.opt"
|
#define MY_DB_OPT_FILE "db.opt"
|
||||||
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create);
|
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create);
|
||||||
|
@ -1631,6 +1631,14 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
|
|||||||
if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter))
|
if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter))
|
||||||
DBUG_RETURN(-1); /* purecov: inspected */
|
DBUG_RETURN(-1); /* purecov: inspected */
|
||||||
fix_tables_pointers(thd->lex->all_selects_list);
|
fix_tables_pointers(thd->lex->all_selects_list);
|
||||||
|
|
||||||
|
/*
|
||||||
|
open temporary memory pool, which will be closed in
|
||||||
|
mysql_test_select_fields, mysql_test_upd_fields or
|
||||||
|
mysql_test_insert_fields
|
||||||
|
*/
|
||||||
|
if (thd->current_statement)
|
||||||
|
thd->ps_setup_prepare_memory();
|
||||||
DBUG_RETURN(mysql_handle_derived(thd->lex));
|
DBUG_RETURN(mysql_handle_derived(thd->lex));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2080,6 +2088,9 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
|||||||
{
|
{
|
||||||
if (!wild_num)
|
if (!wild_num)
|
||||||
return 0;
|
return 0;
|
||||||
|
Statement *stmt= thd->current_statement, backup;
|
||||||
|
if (stmt)
|
||||||
|
thd->set_n_backup_item_arena(stmt, &backup);
|
||||||
reg2 Item *item;
|
reg2 Item *item;
|
||||||
List_iterator<Item> it(fields);
|
List_iterator<Item> it(fields);
|
||||||
while ( wild_num && (item= it++))
|
while ( wild_num && (item= it++))
|
||||||
@ -2091,7 +2102,11 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
|||||||
uint elem= fields.elements;
|
uint elem= fields.elements;
|
||||||
if (insert_fields(thd,tables,((Item_field*) item)->db_name,
|
if (insert_fields(thd,tables,((Item_field*) item)->db_name,
|
||||||
((Item_field*) item)->table_name, &it))
|
((Item_field*) item)->table_name, &it))
|
||||||
|
{
|
||||||
|
if (stmt)
|
||||||
|
thd->restore_backup_item_arena(stmt, &backup);
|
||||||
return (-1);
|
return (-1);
|
||||||
|
}
|
||||||
if (sum_func_list)
|
if (sum_func_list)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -2104,6 +2119,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
|||||||
wild_num--;
|
wild_num--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (stmt)
|
||||||
|
thd->restore_backup_item_arena(stmt, &backup);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ extern "C" void free_user_var(user_var_entry *entry)
|
|||||||
** Thread specific functions
|
** Thread specific functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
THD::THD():user_time(0), is_fatal_error(0),
|
THD::THD():user_time(0), current_statement(0), is_fatal_error(0),
|
||||||
last_insert_id_used(0),
|
last_insert_id_used(0),
|
||||||
insert_id_used(0), rand_used(0), in_lock_tables(0),
|
insert_id_used(0), rand_used(0), in_lock_tables(0),
|
||||||
global_read_lock(0), bootstrap(0)
|
global_read_lock(0), bootstrap(0)
|
||||||
@ -1247,6 +1247,27 @@ void Statement::set_statement(Statement *stmt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Statement::set_n_backup_item_arena(Statement *set, Statement *backup)
|
||||||
|
{
|
||||||
|
backup->set_item_arena(this);
|
||||||
|
set_item_arena(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Statement::restore_backup_item_arena(Statement *set, Statement *backup)
|
||||||
|
{
|
||||||
|
set->set_item_arena(this);
|
||||||
|
set_item_arena(backup);
|
||||||
|
// reset backup mem_root to avoid its freeing
|
||||||
|
init_alloc_root(&backup->mem_root, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Statement::set_item_arena(Statement *set)
|
||||||
|
{
|
||||||
|
mem_root= set->mem_root;
|
||||||
|
free_list= set->free_list;
|
||||||
|
}
|
||||||
|
|
||||||
Statement::~Statement()
|
Statement::~Statement()
|
||||||
{
|
{
|
||||||
free_root(&mem_root, MYF(0));
|
free_root(&mem_root, MYF(0));
|
||||||
|
@ -427,7 +427,7 @@ class Statement
|
|||||||
public:
|
public:
|
||||||
/* FIXME: must be private */
|
/* FIXME: must be private */
|
||||||
LEX main_lex;
|
LEX main_lex;
|
||||||
public:
|
|
||||||
/*
|
/*
|
||||||
Uniquely identifies each statement object in thread scope; change during
|
Uniquely identifies each statement object in thread scope; change during
|
||||||
statement lifetime. FIXME: must be const
|
statement lifetime. FIXME: must be const
|
||||||
@ -503,6 +503,32 @@ public:
|
|||||||
void set_statement(Statement *stmt);
|
void set_statement(Statement *stmt);
|
||||||
/* return class type */
|
/* return class type */
|
||||||
virtual Type type() const;
|
virtual Type type() const;
|
||||||
|
|
||||||
|
inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
|
||||||
|
inline gptr calloc(unsigned int size)
|
||||||
|
{
|
||||||
|
gptr ptr;
|
||||||
|
if ((ptr=alloc_root(&mem_root,size)))
|
||||||
|
bzero((char*) ptr,size);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
inline char *strdup(const char *str)
|
||||||
|
{ return strdup_root(&mem_root,str); }
|
||||||
|
inline char *strmake(const char *str, uint size)
|
||||||
|
{ return strmake_root(&mem_root,str,size); }
|
||||||
|
inline char *memdup(const char *str, uint size)
|
||||||
|
{ return memdup_root(&mem_root,str,size); }
|
||||||
|
inline char *memdup_w_gap(const char *str, uint size, uint gap)
|
||||||
|
{
|
||||||
|
gptr ptr;
|
||||||
|
if ((ptr=alloc_root(&mem_root,size+gap)))
|
||||||
|
memcpy(ptr,str,size);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_n_backup_item_arena(Statement *set, Statement *backup);
|
||||||
|
void restore_backup_item_arena(Statement *set, Statement *backup);
|
||||||
|
void Statement::set_item_arena(Statement *set);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -689,6 +715,10 @@ public:
|
|||||||
#ifdef SIGNAL_WITH_VIO_CLOSE
|
#ifdef SIGNAL_WITH_VIO_CLOSE
|
||||||
Vio* active_vio;
|
Vio* active_vio;
|
||||||
#endif
|
#endif
|
||||||
|
/*
|
||||||
|
Current prepared Statement if there one, or 0
|
||||||
|
*/
|
||||||
|
Statement *current_statement;
|
||||||
/*
|
/*
|
||||||
next_insert_id is set on SET INSERT_ID= #. This is used as the next
|
next_insert_id is set on SET INSERT_ID= #. This is used as the next
|
||||||
generated auto_increment value in handler.cc
|
generated auto_increment value in handler.cc
|
||||||
@ -850,34 +880,14 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
|
|
||||||
inline gptr calloc(unsigned int size)
|
|
||||||
{
|
|
||||||
gptr ptr;
|
|
||||||
if ((ptr=alloc_root(&mem_root,size)))
|
|
||||||
bzero((char*) ptr,size);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
inline char *strdup(const char *str)
|
|
||||||
{ return strdup_root(&mem_root,str); }
|
|
||||||
inline char *strmake(const char *str, uint size)
|
|
||||||
{ return strmake_root(&mem_root,str,size); }
|
|
||||||
inline char *memdup(const char *str, uint size)
|
|
||||||
{ return memdup_root(&mem_root,str,size); }
|
|
||||||
inline char *memdup_w_gap(const char *str, uint size, uint gap)
|
|
||||||
{
|
|
||||||
gptr ptr;
|
|
||||||
if ((ptr=alloc_root(&mem_root,size+gap)))
|
|
||||||
memcpy(ptr,str,size);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
bool convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
|
|
||||||
const char *from, uint from_length,
|
|
||||||
CHARSET_INFO *from_cs);
|
|
||||||
inline gptr trans_alloc(unsigned int size)
|
inline gptr trans_alloc(unsigned int size)
|
||||||
{
|
{
|
||||||
return alloc_root(&transaction.mem_root,size);
|
return alloc_root(&transaction.mem_root,size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
|
||||||
|
const char *from, uint from_length,
|
||||||
|
CHARSET_INFO *from_cs);
|
||||||
void add_changed_table(TABLE *table);
|
void add_changed_table(TABLE *table);
|
||||||
void add_changed_table(const char *key, long key_length);
|
void add_changed_table(const char *key, long key_length);
|
||||||
CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
|
CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
|
||||||
@ -900,6 +910,33 @@ public:
|
|||||||
}
|
}
|
||||||
inline CHARSET_INFO *charset() { return variables.character_set_client; }
|
inline CHARSET_INFO *charset() { return variables.character_set_client; }
|
||||||
void update_charset();
|
void update_charset();
|
||||||
|
|
||||||
|
inline void ps_setup_prepare_memory()
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(current_statement!=0);
|
||||||
|
/*
|
||||||
|
We do not want to have in PS memory all that junk,
|
||||||
|
which will be created by preparation => substitute memory
|
||||||
|
from original thread pool.
|
||||||
|
|
||||||
|
We know that PS memory pool is now copied to THD, we move it back
|
||||||
|
to allow some code use it.
|
||||||
|
*/
|
||||||
|
current_statement->set_item_arena(this);
|
||||||
|
init_sql_alloc(&mem_root,
|
||||||
|
variables.query_alloc_block_size,
|
||||||
|
variables.query_prealloc_size);
|
||||||
|
free_list= 0;
|
||||||
|
}
|
||||||
|
inline void ps_setup_free_memory()
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(current_statement!=0);
|
||||||
|
cleanup_items(current_statement->free_list);
|
||||||
|
free_items(free_list);
|
||||||
|
close_thread_tables(this); // to close derived tables
|
||||||
|
free_root(&mem_root, MYF(0));
|
||||||
|
set_item_arena(current_statement);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Flags for the THD::system_thread (bitmap) variable */
|
/* Flags for the THD::system_thread (bitmap) variable */
|
||||||
|
@ -1500,11 +1500,17 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
|
|||||||
{
|
{
|
||||||
if (ref_pointer_array)
|
if (ref_pointer_array)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
We have to create array in prepared statement memory if it is
|
||||||
|
prepared statement
|
||||||
|
*/
|
||||||
|
Statement *stmt= thd->current_statement ? thd->current_statement : thd;
|
||||||
return (ref_pointer_array=
|
return (ref_pointer_array=
|
||||||
(Item **)thd->alloc(sizeof(Item*) *
|
(Item **)stmt->alloc(sizeof(Item*) *
|
||||||
(item_list.elements +
|
(item_list.elements +
|
||||||
select_n_having_items +
|
select_n_having_items +
|
||||||
order_group_num)* 5)) == 0;
|
order_group_num)* 5)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1629,7 +1635,11 @@ void st_select_lex::print_limit(THD *thd, String *str)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
There are st_select_lex::add_table_to_list &
|
There are st_select_lex::add_table_to_list &
|
||||||
st_select_lex::set_lock_for_tables in sql_parse.cc
|
st_select_lex::set_lock_for_tables are in sql_parse.cc
|
||||||
|
|
||||||
st_select_lex::print is in sql_select.h
|
st_select_lex::print is in sql_select.h
|
||||||
|
|
||||||
|
st_select_lex_unit::prepare, st_select_lex_unit::exec,
|
||||||
|
st_select_lex_unit::cleanup, st_select_lex_unit::reinit_exec_mechanism
|
||||||
|
are in sql_union.cc
|
||||||
*/
|
*/
|
||||||
|
@ -355,6 +355,8 @@ public:
|
|||||||
int prepare(THD *thd, select_result *result, ulong additional_options);
|
int prepare(THD *thd, select_result *result, ulong additional_options);
|
||||||
int exec();
|
int exec();
|
||||||
int cleanup();
|
int cleanup();
|
||||||
|
inline void unclean() { cleaned= 0; }
|
||||||
|
void reinit_exec_mechanism();
|
||||||
|
|
||||||
bool check_updateable(char *db, char *table);
|
bool check_updateable(char *db, char *table);
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
|
@ -622,7 +622,12 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
#endif
|
#endif
|
||||||
if (open_and_lock_tables(thd, table_list))
|
if (open_and_lock_tables(thd, table_list))
|
||||||
|
{
|
||||||
|
// this memory pool was opened in open_and_lock_tables
|
||||||
|
thd->ps_setup_free_memory();
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
table= table_list->table;
|
table= table_list->table;
|
||||||
|
|
||||||
if ((values= its++))
|
if ((values= its++))
|
||||||
@ -631,7 +636,12 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
|
|||||||
ulong counter= 0;
|
ulong counter= 0;
|
||||||
|
|
||||||
if (check_insert_fields(thd,table,fields,*values,1))
|
if (check_insert_fields(thd,table,fields,*values,1))
|
||||||
|
{
|
||||||
|
thd->ps_setup_free_memory();
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
// this memory pool was opened in open_and_lock_tables
|
||||||
|
thd->ps_setup_free_memory();
|
||||||
|
|
||||||
value_count= values->elements;
|
value_count= values->elements;
|
||||||
its.rewind();
|
its.rewind();
|
||||||
@ -648,6 +658,11 @@ static bool mysql_test_insert_fields(Prepared_statement *stmt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// this memory pool was opened in open_and_lock_tables
|
||||||
|
thd->ps_setup_free_memory();
|
||||||
|
}
|
||||||
if (send_prep_stmt(stmt, 0))
|
if (send_prep_stmt(stmt, 0))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
@ -678,11 +693,20 @@ static bool mysql_test_upd_fields(Prepared_statement *stmt,
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
#endif
|
#endif
|
||||||
if (open_and_lock_tables(thd, table_list))
|
if (open_and_lock_tables(thd, table_list))
|
||||||
|
{
|
||||||
|
// this memory pool was opened in open_and_lock_tables
|
||||||
|
thd->ps_setup_free_memory();
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
if (setup_tables(table_list) ||
|
if (setup_tables(table_list) ||
|
||||||
setup_fields(thd, 0, table_list, fields, 1, 0, 0) ||
|
setup_fields(thd, 0, table_list, fields, 1, 0, 0) ||
|
||||||
setup_conds(thd, table_list, &conds) || thd->net.report_error)
|
setup_conds(thd, table_list, &conds) || thd->net.report_error)
|
||||||
|
{
|
||||||
|
// this memory pool was opened in open_and_lock_tables
|
||||||
|
thd->ps_setup_free_memory();
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
// this memory pool was opened in open_and_lock_tables
|
||||||
|
thd->ps_setup_free_memory();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Currently return only column list info only, and we are not
|
Currently return only column list info only, and we are not
|
||||||
@ -737,39 +761,50 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
if (open_and_lock_tables(thd, tables))
|
if (open_and_lock_tables(thd, tables))
|
||||||
|
{
|
||||||
|
// this memory pool was opened in open_and_lock_tables
|
||||||
|
thd->ps_setup_free_memory();
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (lex->describe)
|
if (lex->describe)
|
||||||
{
|
{
|
||||||
if (send_prep_stmt(stmt, 0))
|
if (send_prep_stmt(stmt, 0))
|
||||||
DBUG_RETURN(1);
|
goto err;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!result && !(result= new select_send()))
|
if (!result && !(result= new select_send()))
|
||||||
{
|
{
|
||||||
send_error(thd, ER_OUT_OF_RESOURCES);
|
send_error(thd, ER_OUT_OF_RESOURCES);
|
||||||
DBUG_RETURN(1);
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
JOIN *join= new JOIN(thd, fields, select_options, result);
|
|
||||||
thd->used_tables= 0; // Updated by setup_fields
|
thd->used_tables= 0; // Updated by setup_fields
|
||||||
|
|
||||||
if (join->prepare(&select_lex->ref_pointer_array,
|
if (unit->prepare(thd, result, 0))
|
||||||
(TABLE_LIST*)select_lex->get_table_list(),
|
goto err_prep;
|
||||||
wild_num, conds, og_num, order, group, having, proc,
|
|
||||||
select_lex, unit))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
if (send_prep_stmt(stmt, fields.elements) ||
|
if (send_prep_stmt(stmt, fields.elements) ||
|
||||||
thd->protocol_simple.send_fields(&fields, 0)
|
thd->protocol_simple.send_fields(&fields, 0)
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
|| net_flush(&thd->net)
|
|| net_flush(&thd->net)
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
DBUG_RETURN(1);
|
goto err_prep;
|
||||||
join->cleanup();
|
|
||||||
|
unit->cleanup();
|
||||||
}
|
}
|
||||||
|
// this memory pool was opened in open_and_lock_tables
|
||||||
|
thd->ps_setup_free_memory();
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
err_prep:
|
||||||
|
unit->cleanup();
|
||||||
|
err:
|
||||||
|
// this memory pool was opened in open_and_lock_tables
|
||||||
|
thd->ps_setup_free_memory();
|
||||||
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -898,6 +933,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
|
|||||||
|
|
||||||
thd->stmt_backup.set_statement(thd);
|
thd->stmt_backup.set_statement(thd);
|
||||||
thd->set_statement(stmt);
|
thd->set_statement(stmt);
|
||||||
|
thd->current_statement= stmt;
|
||||||
|
|
||||||
if (alloc_query(thd, packet, packet_length))
|
if (alloc_query(thd, packet, packet_length))
|
||||||
goto alloc_query_err;
|
goto alloc_query_err;
|
||||||
@ -925,9 +961,9 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
|
|||||||
sl->prep_where= sl->where;
|
sl->prep_where= sl->where;
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup_items(thd->free_list);
|
|
||||||
stmt->set_statement(thd);
|
stmt->set_statement(thd);
|
||||||
thd->set_statement(&thd->stmt_backup);
|
thd->set_statement(&thd->stmt_backup);
|
||||||
|
thd->current_statement= 0;
|
||||||
|
|
||||||
if (init_param_items(stmt))
|
if (init_param_items(stmt))
|
||||||
goto init_param_err;
|
goto init_param_err;
|
||||||
@ -944,8 +980,10 @@ init_param_err:
|
|||||||
alloc_query_err:
|
alloc_query_err:
|
||||||
/* Statement map deletes statement on erase */
|
/* Statement map deletes statement on erase */
|
||||||
thd->stmt_map.erase(stmt);
|
thd->stmt_map.erase(stmt);
|
||||||
|
thd->current_statement= 0;
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
insert_stmt_err:
|
insert_stmt_err:
|
||||||
|
thd->current_statement= 0;
|
||||||
delete stmt;
|
delete stmt;
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
@ -1010,24 +1048,36 @@ void mysql_stmt_execute(THD *thd, char *packet)
|
|||||||
/* Fix ORDER list */
|
/* Fix ORDER list */
|
||||||
for (order=(ORDER *)sl->order_list.first ; order ; order=order->next)
|
for (order=(ORDER *)sl->order_list.first ; order ; order=order->next)
|
||||||
order->item= (Item **)(order+1);
|
order->item= (Item **)(order+1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: When the new table structure is ready, then have a status bit
|
||||||
|
to indicate the table is altered, and re-do the setup_*
|
||||||
|
and open the tables back.
|
||||||
|
*/
|
||||||
|
for (TABLE_LIST *tables= (TABLE_LIST*) sl->table_list.first;
|
||||||
|
tables;
|
||||||
|
tables= tables->next)
|
||||||
|
{
|
||||||
|
tables->table= 0; // safety - nasty init
|
||||||
|
tables->table_list= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SELECT_LEX_UNIT *unit= sl->master_unit();
|
||||||
|
unit->unclean();
|
||||||
|
unit->types.empty();
|
||||||
|
// for derived tables & PS (which can't be reset bu Item_subquery)
|
||||||
|
unit->reinit_exec_mechanism();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
TODO: When the new table structure is ready, then have a status bit
|
|
||||||
to indicate the table is altered, and re-do the setup_*
|
|
||||||
and open the tables back.
|
|
||||||
*/
|
|
||||||
for (TABLE_LIST *tables= (TABLE_LIST*) stmt->lex->select_lex.table_list.first;
|
|
||||||
tables;
|
|
||||||
tables= tables->next)
|
|
||||||
tables->table= 0; // safety - nasty init
|
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
if (stmt->param_count && setup_params_data(stmt))
|
if (stmt->param_count && setup_params_data(stmt))
|
||||||
DBUG_VOID_RETURN;
|
goto end;
|
||||||
#else
|
#else
|
||||||
if (stmt->param_count && (*stmt->setup_params_data)(stmt))
|
if (stmt->param_count && (*stmt->setup_params_data)(stmt))
|
||||||
DBUG_VOID_RETURN;
|
goto end;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||||
@ -1048,8 +1098,10 @@ void mysql_stmt_execute(THD *thd, char *packet)
|
|||||||
|
|
||||||
free_items(thd->free_list);
|
free_items(thd->free_list);
|
||||||
cleanup_items(stmt->free_list);
|
cleanup_items(stmt->free_list);
|
||||||
|
close_thread_tables(thd); // to close derived tables
|
||||||
free_root(&thd->mem_root, MYF(0));
|
free_root(&thd->mem_root, MYF(0));
|
||||||
thd->set_statement(&thd->stmt_backup);
|
thd->set_statement(&thd->stmt_backup);
|
||||||
|
end:
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,8 +327,7 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
// Is it subselect
|
// Is it subselect
|
||||||
{
|
{
|
||||||
Item_subselect *subselect;
|
Item_subselect *subselect;
|
||||||
if ((subselect= select_lex->master_unit()->item) &&
|
if ((subselect= select_lex->master_unit()->item))
|
||||||
select_lex->linkage != GLOBAL_OPTIONS_TYPE)
|
|
||||||
{
|
{
|
||||||
Item_subselect::trans_res res;
|
Item_subselect::trans_res res;
|
||||||
if ((res= subselect->select_transformer(this)) !=
|
if ((res= subselect->select_transformer(this)) !=
|
||||||
@ -1519,10 +1518,10 @@ JOIN::cleanup()
|
|||||||
|
|
||||||
lock=0; // It's faster to unlock later
|
lock=0; // It's faster to unlock later
|
||||||
join_free(1);
|
join_free(1);
|
||||||
if (exec_tmp_table1)
|
if (exec_tmp_table1)
|
||||||
free_tmp_table(thd, exec_tmp_table1);
|
free_tmp_table(thd, exec_tmp_table1);
|
||||||
if (exec_tmp_table2)
|
if (exec_tmp_table2)
|
||||||
free_tmp_table(thd, exec_tmp_table2);
|
free_tmp_table(thd, exec_tmp_table2);
|
||||||
delete select;
|
delete select;
|
||||||
delete_dynamic(&keyuse);
|
delete_dynamic(&keyuse);
|
||||||
delete procedure;
|
delete procedure;
|
||||||
|
@ -453,3 +453,9 @@ int st_select_lex_unit::cleanup()
|
|||||||
}
|
}
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void st_select_lex_unit::reinit_exec_mechanism()
|
||||||
|
{
|
||||||
|
prepared= optimized= executed= 0;
|
||||||
|
}
|
||||||
|
@ -8189,6 +8189,90 @@ static void test_bug2247()
|
|||||||
fprintf(stdout, "OK");
|
fprintf(stdout, "OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void test_subqueries()
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt;
|
||||||
|
int rc, i;
|
||||||
|
const char *query= "SELECT (SELECT SUM(a+b) FROM t2 where t1.b=t2.b GROUP BY t1.a LIMIT 1) as scalar_s, exists (select 1 from t2 where t2.a/2=t1.a) as exists_s, a in (select a+3 from t2) as in_s, (a-1,b-1) in (select a,b from t2) as in_row_s FROM t1, (select a x, b y from t2) tt WHERE x=a";
|
||||||
|
|
||||||
|
myheader("test_subquery");
|
||||||
|
|
||||||
|
rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,"CREATE TABLE t1 (a int , b int);");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,
|
||||||
|
"insert into t1 values (1,1), (2, 2), (3,3), (4,4), (5,5);");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,"create table t2 select * from t1;");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
stmt= mysql_prepare(mysql, query, strlen(query));
|
||||||
|
mystmt_init(stmt);
|
||||||
|
for (i= 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
rc= mysql_execute(stmt);
|
||||||
|
mystmt(stmt, rc);
|
||||||
|
assert(5 == my_process_stmt_result(stmt));
|
||||||
|
}
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE t1,t2");
|
||||||
|
myquery(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_bad_union()
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt;
|
||||||
|
const char *query= "SELECT 1, 2 union SELECT 1";
|
||||||
|
|
||||||
|
myheader("test_bad_union");
|
||||||
|
|
||||||
|
stmt= mysql_prepare(mysql, query, strlen(query));
|
||||||
|
assert(stmt == 0);
|
||||||
|
myerror(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_distinct()
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt;
|
||||||
|
int rc, i;
|
||||||
|
const char *query=
|
||||||
|
"SELECT 2+count(distinct b), group_concat(a) FROM t1 group by a";
|
||||||
|
|
||||||
|
myheader("test_subquery");
|
||||||
|
|
||||||
|
rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,"CREATE TABLE t1 (a int , b int);");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,
|
||||||
|
"insert into t1 values (1,1), (2, 2), (3,3), (4,4), (5,5),\
|
||||||
|
(1,10), (2, 20), (3,30), (4,40), (5,50)\;");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
for (i= 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
stmt= mysql_prepare(mysql, query, strlen(query));
|
||||||
|
mystmt_init(stmt);
|
||||||
|
rc= mysql_execute(stmt);
|
||||||
|
mystmt(stmt, rc);
|
||||||
|
assert(5 == my_process_stmt_result(stmt));
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE t1");
|
||||||
|
myquery(rc);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test for bug#2248 "mysql_fetch without prior mysql_execute hangs"
|
Test for bug#2248 "mysql_fetch without prior mysql_execute hangs"
|
||||||
*/
|
*/
|
||||||
@ -8385,6 +8469,9 @@ int main(int argc, char **argv)
|
|||||||
test_count= 1;
|
test_count= 1;
|
||||||
|
|
||||||
start_time= time((time_t *)0);
|
start_time= time((time_t *)0);
|
||||||
|
|
||||||
|
test_subqueries();
|
||||||
|
|
||||||
client_query(); /* simple client query test */
|
client_query(); /* simple client query test */
|
||||||
#if NOT_YET_WORKING
|
#if NOT_YET_WORKING
|
||||||
/* Used for internal new development debugging */
|
/* Used for internal new development debugging */
|
||||||
@ -8437,7 +8524,8 @@ int main(int argc, char **argv)
|
|||||||
client_use_result(); /* usage of mysql_use_result() */
|
client_use_result(); /* usage of mysql_use_result() */
|
||||||
test_tran_bdb(); /* transaction test on BDB table type */
|
test_tran_bdb(); /* transaction test on BDB table type */
|
||||||
test_tran_innodb(); /* transaction test on InnoDB table type */
|
test_tran_innodb(); /* transaction test on InnoDB table type */
|
||||||
test_prepare_ext(); /* test prepare with all types conversion -- TODO */
|
test_prepare_ext(); /* test prepare with all types
|
||||||
|
conversion -- TODO */
|
||||||
test_prepare_syntax(); /* syntax check for prepares */
|
test_prepare_syntax(); /* syntax check for prepares */
|
||||||
test_field_names(); /* test for field names */
|
test_field_names(); /* test for field names */
|
||||||
test_field_flags(); /* test to help .NET provider team */
|
test_field_flags(); /* test to help .NET provider team */
|
||||||
@ -8450,7 +8538,7 @@ int main(int argc, char **argv)
|
|||||||
test_stmt_close(); /* mysql_stmt_close() test -- hangs */
|
test_stmt_close(); /* mysql_stmt_close() test -- hangs */
|
||||||
test_prepare_field_result(); /* prepare meta info */
|
test_prepare_field_result(); /* prepare meta info */
|
||||||
test_multi_stmt(); /* multi stmt test */
|
test_multi_stmt(); /* multi stmt test */
|
||||||
test_multi_statements(); /* test multi statement execution */
|
/* test_multi_statements(); *//* test multi statement execution */
|
||||||
test_store_result(); /* test the store_result */
|
test_store_result(); /* test the store_result */
|
||||||
test_store_result1(); /* test store result without buffers */
|
test_store_result1(); /* test store result without buffers */
|
||||||
test_store_result2(); /* test store result for misc case */
|
test_store_result2(); /* test store result for misc case */
|
||||||
@ -8497,6 +8585,10 @@ int main(int argc, char **argv)
|
|||||||
test_bug2247(); /* test that mysql_stmt_affected_rows() returns
|
test_bug2247(); /* test that mysql_stmt_affected_rows() returns
|
||||||
number of rows affected by last prepared
|
number of rows affected by last prepared
|
||||||
statement execution */
|
statement execution */
|
||||||
|
test_subqueries(); /* repeatable subqueries */
|
||||||
|
test_bad_union(); /* correct setup of UNION */
|
||||||
|
test_distinct(); /* distinct aggregate functions */
|
||||||
|
|
||||||
|
|
||||||
end_time= time((time_t *)0);
|
end_time= time((time_t *)0);
|
||||||
total_time+= difftime(end_time, start_time);
|
total_time+= difftime(end_time, start_time);
|
||||||
|
Reference in New Issue
Block a user