Commit 04e9cd42 authored by unknown's avatar unknown

post merge fixes


mysql-test/t/merge.test:
  additional test
sql/item.h:
  parameter to detect need of saving view field names
sql/item_subselect.cc:
  arena fix
  used nearest thd pointer
sql/item_sum.cc:
  after merge fix
sql/mysql_priv.h:
  after merge fix
sql/sql_base.cc:
  fixed unique test
  fixed postmerge arena mamgement
sql/sql_class.h:
  mey method to detect conventional execution
sql/sql_handler.cc:
  new parameter
sql/sql_lex.cc:
  fixed postmerge arena mamgement
sql/sql_parse.cc:
  fixed unique test
sql/sql_select.cc:
  fixed postmerge arena mamgement
sql/sql_union.cc:
  fixed postmerge arena mamgement
sql/sql_view.cc:
  fixed postmerge arena mamgement
sql/table.cc:
  fixed postmerge arena mamgement
parent 4d64a5a6
...@@ -284,4 +284,6 @@ insert into t2 values (1); ...@@ -284,4 +284,6 @@ insert into t2 values (1);
create table t3 engine=merge union=(t1, t2) select * from t1; create table t3 engine=merge union=(t1, t2) select * from t1;
--error 1093 --error 1093
create table t3 engine=merge union=(t1, t2) select * from t2; create table t3 engine=merge union=(t1, t2) select * from t2;
--error 1093
create table t3 engine=merge union=(t1, t2) select (select max(a) from t2);
drop table t1, t2; drop table t1, t2;
...@@ -434,7 +434,7 @@ class Item_ident :public Item ...@@ -434,7 +434,7 @@ class Item_ident :public Item
friend bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, friend bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
const char *table_name, List_iterator<Item> *it, const char *table_name, List_iterator<Item> *it,
bool any_privileges); bool any_privileges, bool allocate_view_names);
}; };
......
...@@ -316,9 +316,9 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -316,9 +316,9 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
SELECT_LEX *select_lex= join->select_lex; SELECT_LEX *select_lex= join->select_lex;
/* Juggle with current arena only if we're in prepared statement prepare */ /* Juggle with current arena only if we're in prepared statement prepare */
Item_arena *arena= join->thd->current_arena; Item_arena *arena= thd->current_arena;
Item_arena backup; Item_arena backup;
if (!arena->is_stmt_prepare()) if (arena->is_conventional())
arena= 0; // For easier test arena= 0; // For easier test
if (!select_lex->master_unit()->first_select()->next_select() && if (!select_lex->master_unit()->first_select()->next_select() &&
...@@ -337,11 +337,11 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -337,11 +337,11 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
{ {
have_to_be_excluded= 1; have_to_be_excluded= 1;
if (join->thd->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(join->thd, MYSQL_ERROR::WARN_LEVEL_NOTE, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff); ER_SELECT_REDUCED, warn_buff);
} }
substitution= select_lex->item_list.head(); substitution= select_lex->item_list.head();
...@@ -367,9 +367,9 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -367,9 +367,9 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
if (!(substitution= new Item_func_if(cond, substitution, if (!(substitution= new Item_func_if(cond, substitution,
new Item_null()))) new Item_null())))
goto err; goto err;
}
if (arena) if (arena)
thd->restore_backup_item_arena(arena, &backup); thd->restore_backup_item_arena(arena, &backup);
}
return RES_REDUCE; return RES_REDUCE;
} }
return RES_OK; return RES_OK;
...@@ -654,11 +654,11 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -654,11 +654,11 @@ Item_in_subselect::single_value_transformer(JOIN *join,
} }
SELECT_LEX *select_lex= join->select_lex; SELECT_LEX *select_lex= join->select_lex;
Item_arena *arena= join->thd->current_arena, backup; Item_arena *arena= thd->current_arena, backup;
thd->where= "scalar IN/ALL/ANY subquery"; thd->where= "scalar IN/ALL/ANY subquery";
if (!arena->is_stmt_prepare()) if (arena->is_conventional())
arena= 0; // For easier test arena= 0; // For easier test
else else
thd->set_n_backup_item_arena(arena, &backup); thd->set_n_backup_item_arena(arena, &backup);
...@@ -900,7 +900,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) ...@@ -900,7 +900,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
thd->where= "row IN/ALL/ANY subquery"; thd->where= "row IN/ALL/ANY subquery";
Item_arena *arena= join->thd->current_arena, backup; Item_arena *arena= join->thd->current_arena, backup;
if (!arena->is_stmt_prepare()) if (arena->is_conventional())
arena= 0; arena= 0;
else else
thd->set_n_backup_item_arena(arena, &backup); thd->set_n_backup_item_arena(arena, &backup);
...@@ -1192,17 +1192,17 @@ void subselect_uniquesubquery_engine::fix_length_and_dec(Item_cache **row) ...@@ -1192,17 +1192,17 @@ void subselect_uniquesubquery_engine::fix_length_and_dec(Item_cache **row)
int subselect_single_select_engine::exec() int subselect_single_select_engine::exec()
{ {
DBUG_ENTER("subselect_single_select_engine::exec"); DBUG_ENTER("subselect_single_select_engine::exec");
char const *save_where= join->thd->where; char const *save_where= thd->where;
SELECT_LEX *save_select= join->thd->lex->current_select; SELECT_LEX *save_select= thd->lex->current_select;
join->thd->lex->current_select= select_lex; thd->lex->current_select= select_lex;
if (!optimized) if (!optimized)
{ {
optimized=1; optimized=1;
if (join->optimize()) if (join->optimize())
{ {
join->thd->where= save_where; thd->where= save_where;
executed= 1; executed= 1;
join->thd->lex->current_select= save_select; thd->lex->current_select= save_select;
DBUG_RETURN(join->error ? join->error : 1); DBUG_RETURN(join->error ? join->error : 1);
} }
if (item->engine_changed) if (item->engine_changed)
...@@ -1214,8 +1214,8 @@ int subselect_single_select_engine::exec() ...@@ -1214,8 +1214,8 @@ int subselect_single_select_engine::exec()
{ {
if (join->reinit()) if (join->reinit())
{ {
join->thd->where= save_where; thd->where= save_where;
join->thd->lex->current_select= save_select; thd->lex->current_select= save_select;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
item->reset(); item->reset();
...@@ -1225,20 +1225,20 @@ int subselect_single_select_engine::exec() ...@@ -1225,20 +1225,20 @@ int subselect_single_select_engine::exec()
{ {
join->exec(); join->exec();
executed= 1; executed= 1;
join->thd->where= save_where; thd->where= save_where;
join->thd->lex->current_select= save_select; thd->lex->current_select= save_select;
DBUG_RETURN(join->error||thd->is_fatal_error); DBUG_RETURN(join->error||thd->is_fatal_error);
} }
join->thd->where= save_where; thd->where= save_where;
join->thd->lex->current_select= save_select; thd->lex->current_select= save_select;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
int subselect_union_engine::exec() int subselect_union_engine::exec()
{ {
char const *save_where= unit->thd->where; char const *save_where= thd->where;
int res= unit->exec(); int res= unit->exec();
unit->thd->where= save_where; thd->where= save_where;
return res; return res;
} }
......
...@@ -77,7 +77,7 @@ Item_sum::Item_sum(THD *thd, Item_sum *item): ...@@ -77,7 +77,7 @@ Item_sum::Item_sum(THD *thd, Item_sum *item):
*/ */
bool Item_sum::save_args_for_prepared_statement(THD *thd) bool Item_sum::save_args_for_prepared_statement(THD *thd)
{ {
if (thd->current_arena->is_stmt_prepare() && args_copy == 0) if (!thd->current_arena->is_conventional() && args_copy == 0)
return save_args(thd->current_arena); return save_args(thd->current_arena);
return 0; return 0;
} }
......
...@@ -756,7 +756,8 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, ...@@ -756,7 +756,8 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
List<String> *index_list); List<String> *index_list);
bool insert_fields(THD *thd,TABLE_LIST *tables, bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
List_iterator<Item> *it, bool any_privileges); List_iterator<Item> *it, bool any_privileges,
bool allocate_view_names);
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds); bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num); List<Item> *sum_func_list, uint wild_num);
...@@ -782,7 +783,7 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, ...@@ -782,7 +783,7 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
uint offset_to_list, uint offset_to_list,
const char *db_name, const char *db_name,
const char *table_name); const char *table_name);
bool unique_table(TABLE_LIST *table, TABLE_LIST *table_list); TABLE_LIST *unique_table(TABLE_LIST *table, TABLE_LIST *table_list);
TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name); TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name);
bool close_temporary_table(THD *thd, const char *db, const char *table_name); bool close_temporary_table(THD *thd, const char *db, const char *table_name);
void close_temporary(TABLE *table, bool delete_table=1); void close_temporary(TABLE *table, bool delete_table=1);
......
...@@ -613,14 +613,15 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, ...@@ -613,14 +613,15 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
table_list list of tables table_list list of tables
RETURN RETURN
TRUE test failed found duplicate
FALSE table is unique 0 if table is unique
*/ */
bool unique_table(TABLE_LIST *table, TABLE_LIST *table_list) TABLE_LIST* unique_table(TABLE_LIST *table, TABLE_LIST *table_list)
{ {
char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME]; TABLE_LIST *res;
const char *d_name= table->db, *t_name= table->real_name; const char *d_name= table->db, *t_name= table->real_name;
char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME];
if (table->view) if (table->view)
{ {
/* it is view and table opened */ /* it is view and table opened */
...@@ -640,11 +641,17 @@ bool unique_table(TABLE_LIST *table, TABLE_LIST *table_list) ...@@ -640,11 +641,17 @@ bool unique_table(TABLE_LIST *table, TABLE_LIST *table_list)
} }
if (d_name == 0) if (d_name == 0)
{ {
/* it's temporary table */ /* it's temporary table => always unique */
return FALSE; return 0;
} }
} }
return find_table_in_global_list(table_list, d_name, t_name); if ((res= find_table_in_global_list(table_list, d_name, t_name)) &&
res->table && res->table == table->table)
{
// we found entry of this table try again.
return find_table_in_global_list(res->next_global, d_name, t_name);
}
return res;
} }
...@@ -2504,7 +2511,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -2504,7 +2511,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
Don't use arena if we are not in prepared statements or stored procedures Don't use arena if we are not in prepared statements or stored procedures
For PS/SP we have to use arena to remember the changes For PS/SP we have to use arena to remember the changes
*/ */
if (arena->state == Item_arena::CONVENTIONAL_EXECUTION) if (arena->is_conventional())
arena= 0; // For easier test later one arena= 0; // For easier test later one
else else
thd->set_n_backup_item_arena(arena, &backup); thd->set_n_backup_item_arena(arena, &backup);
...@@ -2531,7 +2538,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -2531,7 +2538,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
} }
else if (insert_fields(thd,tables,((Item_field*) item)->db_name, else if (insert_fields(thd,tables,((Item_field*) item)->db_name,
((Item_field*) item)->table_name, &it, ((Item_field*) item)->table_name, &it,
any_privileges)) any_privileges, arena != 0))
{ {
if (arena) if (arena)
thd->restore_backup_item_arena(arena, &backup); thd->restore_backup_item_arena(arena, &backup);
...@@ -2717,6 +2724,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, ...@@ -2717,6 +2724,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
any_privileges 0 If we should ensure that we have SELECT privileges any_privileges 0 If we should ensure that we have SELECT privileges
for all columns for all columns
1 If any privilege is ok 1 If any privilege is ok
allocate_view_names if true view names will be copied to current Item_arena memory (made for SP/PS)
RETURN RETURN
0 ok 0 ok
'it' is updated to point at last inserted 'it' is updated to point at last inserted
...@@ -2726,7 +2734,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, ...@@ -2726,7 +2734,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
bool bool
insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
const char *table_name, List_iterator<Item> *it, const char *table_name, List_iterator<Item> *it,
bool any_privileges) bool any_privileges, bool allocate_view_names)
{ {
/* allocate variables on stack to avoid pool alloaction */ /* allocate variables on stack to avoid pool alloaction */
Field_iterator_table table_iter; Field_iterator_table table_iter;
...@@ -2886,7 +2894,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, ...@@ -2886,7 +2894,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
field->query_id=thd->query_id; field->query_id=thd->query_id;
table->used_keys.intersect(field->part_of_key); table->used_keys.intersect(field->part_of_key);
} }
else if (thd->current_arena->is_stmt_prepare() && else if (allocate_view_names &&
thd->lex->current_select->first_execution) thd->lex->current_select->first_execution)
{ {
Item_field *item= new Item_field(thd->strdup(tables->view_db.str), Item_field *item= new Item_field(thd->strdup(tables->view_db.str),
...@@ -2931,7 +2939,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2931,7 +2939,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
DBUG_ENTER("setup_conds"); DBUG_ENTER("setup_conds");
if (select_lex->conds_processed_with_permanent_arena || if (select_lex->conds_processed_with_permanent_arena ||
!arena->is_stmt_prepare()) arena->is_conventional())
arena= 0; // For easier test arena= 0; // For easier test
thd->set_query_id=1; thd->set_query_id=1;
......
...@@ -476,6 +476,8 @@ class Item_arena ...@@ -476,6 +476,8 @@ class Item_arena
inline bool is_stmt_prepare() const { return (int)state < (int)PREPARED; } inline bool is_stmt_prepare() const { return (int)state < (int)PREPARED; }
inline bool is_first_stmt_execute() const { return state == PREPARED; } inline bool is_first_stmt_execute() const { return state == PREPARED; }
inline bool is_conventional() const
{ return state == CONVENTIONAL_EXECUTION; }
inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); } inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
inline gptr calloc(unsigned int size) inline gptr calloc(unsigned int size)
{ {
......
...@@ -249,7 +249,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -249,7 +249,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
it++; // Skip first NULL field it++; // Skip first NULL field
insert_fields(thd, tables, tables->db, tables->alias, &it, 0); insert_fields(thd, tables, tables->db, tables->alias, &it, 0, 0);
select_limit+=offset_limit; select_limit+=offset_limit;
protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
......
...@@ -1795,7 +1795,7 @@ void st_lex::link_first_table_back(TABLE_LIST *first, ...@@ -1795,7 +1795,7 @@ void st_lex::link_first_table_back(TABLE_LIST *first,
void st_select_lex::fix_prepare_information(THD *thd, Item **conds) void st_select_lex::fix_prepare_information(THD *thd, Item **conds)
{ {
if (thd->current_arena->is_stmt_prepare() && first_execution) if (!thd->current_arena->is_conventional() && first_execution)
{ {
first_execution= 0; first_execution= 0;
prep_where= where; prep_where= where;
......
...@@ -2404,20 +2404,6 @@ mysql_execute_command(THD *thd) ...@@ -2404,20 +2404,6 @@ mysql_execute_command(THD *thd)
if (select_lex->item_list.elements) // With select if (select_lex->item_list.elements) // With select
{ {
select_result *result; select_result *result;
if (lex->create_info.used_fields & HA_CREATE_USED_UNION)
{
TABLE_LIST *tab;
for (tab= select_tables; tab; tab= tab->next_local)
{
if (find_table_in_local_list((TABLE_LIST*) lex->create_info.
merge_list.first,
select_tables->db, tab->real_name))
{
net_printf(thd, ER_UPDATE_TABLE_USED, tab->real_name);
goto create_error;
}
}
}
if (select_tables && if (select_tables &&
check_table_access(thd, SELECT_ACL, select_tables, 0)) check_table_access(thd, SELECT_ACL, select_tables, 0))
...@@ -2437,6 +2423,21 @@ mysql_execute_command(THD *thd) ...@@ -2437,6 +2423,21 @@ mysql_execute_command(THD *thd)
net_printf(thd, ER_UPDATE_TABLE_USED, create_table->real_name); net_printf(thd, ER_UPDATE_TABLE_USED, create_table->real_name);
goto create_error; goto create_error;
} }
/* If we create merge table, we have to test tables in merge, too */
if (lex->create_info.used_fields & HA_CREATE_USED_UNION)
{
TABLE_LIST *tab;
for (tab= (TABLE_LIST*) lex->create_info.merge_list.first;
tab;
tab= tab->next_local)
{
if (unique_table(tab, select_tables))
{
net_printf(thd, ER_UPDATE_TABLE_USED, tab->real_name);
goto create_error;
}
}
}
if ((result= new select_create(create_table, if ((result= new select_create(create_table,
&lex->create_info, &lex->create_info,
......
...@@ -6156,15 +6156,20 @@ optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value) ...@@ -6156,15 +6156,20 @@ optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value)
MEMROOT for prepared statements and stored procedures. MEMROOT for prepared statements and stored procedures.
*/ */
Item_arena *arena=thd->current_arena, backup; Item_arena *arena= thd->current_arena, backup;
select->first_cond_optimization= 0; if (arena->is_conventional())
arena= 0; // For easier test
else
thd->set_n_backup_item_arena(arena, &backup); thd->set_n_backup_item_arena(arena, &backup);
select->first_cond_optimization= 0;
/* Convert all outer joins to inner joins if possible */ /* Convert all outer joins to inner joins if possible */
conds= simplify_joins(join, join->join_list, conds, TRUE); conds= simplify_joins(join, join->join_list, conds, TRUE);
select->prep_where= conds ? conds->copy_andor_structure(thd) : 0; select->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
if (arena)
thd->restore_backup_item_arena(arena, &backup); thd->restore_backup_item_arena(arena, &backup);
} }
......
...@@ -293,7 +293,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, ...@@ -293,7 +293,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
Field **field; Field **field;
Item_arena *arena= thd->current_arena; Item_arena *arena= thd->current_arena;
Item_arena backup; Item_arena backup;
if (!arena->is_stmt_prepare()) if (arena->is_conventional())
arena= 0; arena= 0;
else else
thd->set_n_backup_item_arena(arena, &backup); thd->set_n_backup_item_arena(arena, &backup);
......
...@@ -523,7 +523,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) ...@@ -523,7 +523,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
will be TRUE as far as we make new table cache). will be TRUE as far as we make new table cache).
*/ */
Item_arena *arena= thd->current_arena, backup; Item_arena *arena= thd->current_arena, backup;
if (!arena->is_stmt_prepare()) if (arena->is_conventional())
arena= 0; arena= 0;
else else
thd->set_n_backup_item_arena(arena, &backup); thd->set_n_backup_item_arena(arena, &backup);
......
...@@ -1583,7 +1583,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) ...@@ -1583,7 +1583,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
if (where) if (where)
{ {
Item_arena *arena= thd->current_arena, backup; Item_arena *arena= thd->current_arena, backup;
if (!arena->is_stmt_prepare()) if (arena->is_conventional())
arena= 0; // For easier test arena= 0; // For easier test
if (!where->fixed && where->fix_fields(thd, ancestor, &where)) if (!where->fixed && where->fix_fields(thd, ancestor, &where))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment