Commit 04f6f63d authored by unknown's avatar unknown

A preparatory patch to help adding JOIN::transform() and move one-time

query transformations to the PREPARE stage (prepared statements).


sql/item.h:
  Remove an unused friend declaration.
sql/mysql_priv.h:
  Change signature of insert_fields()
sql/sp_head.cc:
  Make is_stmt_prepare_or_first_sp_execute really work: reset SP state
  to EXECUTED after execution.
sql/sql_base.cc:
  allocate_view_names flag of insert_fields is removed.
  The purpose of this variable was to amend the case when a view
  is replaced with a base table between subsequent executions of a prepared
  statement: in that case the new table theoretically can be used instead
  of the view. If allocate_view_names was set,
  all the references to the view expressions were replaced with Item_field's
  which in turn could have been resolved by their names.
  But this approach doesn't work for other reasons, so let's not try
  to help what must be solved by TDC.
sql/sql_class.h:
  Add is_first_sp_execute() helper method.
sql/sql_handler.cc:
  insert_fields signature changed.
sql/sql_lex.h:
  Add a comment for variable 'first_execution'.
parent e85b0013
......@@ -716,10 +716,6 @@ class Item_ident :public Item
void cleanup();
bool remove_dependence_processor(byte * arg);
void print(String *str);
friend bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
const char *table_name, List_iterator<Item> *it,
bool any_privileges, bool allocate_view_names);
};
class Item_equal;
......
......@@ -894,8 +894,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
List<String> *index_list);
bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name,
List_iterator<Item> *it, bool any_privileges,
bool allocate_view_names);
List_iterator<Item> *it, bool any_privileges);
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
TABLE_LIST **leaves, bool select_insert);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
......
......@@ -682,6 +682,7 @@ sp_head::execute(THD *thd)
cleanup_items(thd->current_arena->free_list);
thd->current_arena= old_arena;
state= EXECUTED;
done:
DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d",
......
......@@ -3051,7 +3051,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
}
else if (insert_fields(thd,tables,((Item_field*) item)->db_name,
((Item_field*) item)->table_name, &it,
any_privileges, arena != 0))
any_privileges))
{
if (arena)
thd->restore_backup_item_arena(arena, &backup);
......@@ -3304,8 +3304,6 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
any_privileges 0 If we should ensure that we have SELECT privileges
for all columns
1 If any privilege is ok
allocate_view_names if true view names will be copied to current Query_arena
memory (made for SP/PS)
RETURN
0 ok
'it' is updated to point at last inserted
......@@ -3315,7 +3313,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
bool
insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
const char *table_name, List_iterator<Item> *it,
bool any_privileges, bool allocate_view_names)
bool any_privileges)
{
/* allocate variables on stack to avoid pool alloaction */
Field_iterator_table table_iter;
......@@ -3506,25 +3504,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
field->query_id=thd->query_id;
table->used_keys.intersect(field->part_of_key);
}
else if (allocate_view_names &&
thd->lex->current_select->first_execution)
{
Item_field *item;
if (alias_used)
item= new Item_field(0,
thd->strdup(tables->alias),
thd->strdup(field_name));
else
item= new Item_field(thd->strdup(tables->view_db.str),
thd->strdup(tables->view_name.str),
thd->strdup(field_name));
/*
during cleunup() this item will be put in list to replace
expression from VIEW
*/
thd->nocheck_register_item_tree_change(it->ref(), item,
thd->mem_root);
}
}
/*
All fields are used in case if usual tables (in case of view used
......
......@@ -699,6 +699,8 @@ class Query_arena
virtual ~Query_arena() {};
inline bool is_stmt_prepare() const { return state == INITIALIZED; }
inline bool is_first_sp_execute() const
{ return state == INITIALIZED_FOR_SP; }
inline bool is_stmt_prepare_or_first_sp_execute() const
{ return (int)state < (int)PREPARED; }
inline bool is_first_stmt_execute() const { return state == PREPARED; }
......
......@@ -422,7 +422,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
}
}
if (insert_fields(thd, tables, tables->db, tables->alias, &it, 0, 0))
if (insert_fields(thd, tables, tables->db, tables->alias, &it, 0))
goto err0;
protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
......
......@@ -530,7 +530,19 @@ class st_select_lex: public st_select_lex_node
query processing end even if we use temporary table
*/
bool subquery_in_having;
bool first_execution; /* first execution in SP or PS */
/*
This variable is required to ensure proper work of subqueries and
stored procedures. Generally, one should use the states of
Query_arena to determine if it's a statement prepare or first
execution of a stored procedure. However, in case when there was an
error during the first execution of a stored procedure, the SP body
is not expelled from the SP cache. Therefore, a deeply nested
subquery might be left unoptimized. So we need this per-subquery
variable to inidicate the optimization/execution state of every
subquery. Prepared statements work OK in that regard, as in
case of an error during prepare the PS is not created.
*/
bool first_execution;
bool first_cond_optimization;
/* do not wrap view fields with Item_ref */
bool no_wrap_view_item;
......
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