summaryrefslogtreecommitdiff
path: root/sql/sql_update.cc
diff options
context:
space:
mode:
authorChad MILLER <chad@mysql.com>2008-12-17 15:01:34 -0500
committerChad MILLER <chad@mysql.com>2008-12-17 15:01:34 -0500
commit926e5f6694d1bb1dd5b8074efd526fd8983b620f (patch)
tree14bfefa872195990d45ab8f3ee850730cd31ed1b /sql/sql_update.cc
parent27d35e3517a063c9259a0f8b9638bf3073cf020b (diff)
parent4d1a042df0c52fd7c721313ec84d39e2b2c0a2f6 (diff)
downloadmariadb-git-926e5f6694d1bb1dd5b8074efd526fd8983b620f.tar.gz
Merged from 5.0 (enterprise).
Diffstat (limited to 'sql/sql_update.cc')
-rw-r--r--sql/sql_update.cc63
1 files changed, 60 insertions, 3 deletions
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 7c619092df1..ad7cb87514d 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -358,7 +358,7 @@ int mysql_update(THD *thd,
Full index scan must be started with init_read_record_idx
*/
if (used_index == MAX_KEY || (select && select->quick))
- init_read_record(&info,thd,table,select,0,1);
+ init_read_record(&info, thd, table, select, 0, 1, FALSE);
else
init_read_record_idx(&info, thd, table, 1, used_index);
@@ -422,7 +422,7 @@ int mysql_update(THD *thd,
if (select && select->quick && select->quick->reset())
goto err;
- init_read_record(&info,thd,table,select,0,1);
+ init_read_record(&info, thd, table, select, 0, 1, FALSE);
updated= found= 0;
thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */
@@ -852,11 +852,14 @@ reopen_tables:
}
/* now lock and fill tables */
- if (lock_tables(thd, table_list, table_count, &need_reopen))
+ if (!thd->stmt_arena->is_stmt_prepare() &&
+ lock_tables(thd, table_list, table_count, &need_reopen))
{
if (!need_reopen)
DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("lock_tables failed, reopening"));
+
/*
We have to reopen tables since some of them were altered or dropped
during lock_tables() or something was done with their triggers.
@@ -872,6 +875,34 @@ reopen_tables:
for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global)
tbl->cleanup_items();
+ /*
+ To not to hog memory (as a result of the
+ unit->reinit_exec_mechanism() call below):
+ */
+ lex->unit.cleanup();
+
+ for (SELECT_LEX *sl= lex->all_selects_list;
+ sl;
+ sl= sl->next_select_in_list())
+ {
+ SELECT_LEX_UNIT *unit= sl->master_unit();
+ unit->reinit_exec_mechanism(); // reset unit->prepared flags
+ /*
+ Reset 'clean' flag back to force normal execution of
+ unit->cleanup() in Prepared_statement::cleanup_stmt()
+ (call to lex->unit.cleanup() above sets this flag to TRUE).
+ */
+ unit->unclean();
+ }
+
+ /*
+ Also we need to cleanup Natural_join_column::table_field items.
+ To not to traverse a join tree we will cleanup whole
+ thd->free_list (in PS execution mode that list may not contain
+ items from 'fields' list, so the cleanup above is necessary to.
+ */
+ cleanup_items(thd->free_list);
+
close_tables_for_reopen(thd, &table_list);
goto reopen_tables;
}
@@ -1218,6 +1249,32 @@ multi_update::initialize_tables(JOIN *join)
}
}
+ /*
+ enable uncacheable flag if we update a view with check option
+ and check option has a subselect, otherwise, the check option
+ can be evaluated after the subselect was freed as independent
+ (See full_local in JOIN::join_free()).
+ */
+ if (table_ref->check_option && !join->select_lex->uncacheable)
+ {
+ SELECT_LEX_UNIT *tmp_unit;
+ SELECT_LEX *sl;
+ for (tmp_unit= join->select_lex->first_inner_unit();
+ tmp_unit;
+ tmp_unit= tmp_unit->next_unit())
+ {
+ for (sl= tmp_unit->first_select(); sl; sl= sl->next_select())
+ {
+ if (sl->master_unit()->item)
+ {
+ join->select_lex->uncacheable|= UNCACHEABLE_CHECKOPTION;
+ goto loop_end;
+ }
+ }
+ }
+ }
+loop_end:
+
if (table == first_table_for_update && table_ref->check_option)
{
table_map unupdated_tables= table_ref->check_option->used_tables() &