summaryrefslogtreecommitdiff
path: root/sql/sql_insert.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r--sql/sql_insert.cc106
1 files changed, 60 insertions, 46 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 9b66d5c5148..00a68086514 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -396,6 +396,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
#ifndef EMBEDDED_LIBRARY
if (lock_type == TL_WRITE_DELAYED)
{
+ res= 1;
if (thd->locked_tables)
{
DBUG_ASSERT(table_list->db); /* Must be set in the parser */
@@ -946,6 +947,8 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d",
(ulong)table_list, (ulong)table,
(int)insert_into_view));
+ /* INSERT should have a SELECT or VALUES clause */
+ DBUG_ASSERT (!select_insert || !values);
/*
For subqueries in VALUES() we should not see the table in which we are
@@ -977,44 +980,40 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
if (mysql_prepare_insert_check_table(thd, table_list, fields, select_insert))
DBUG_RETURN(TRUE);
- /* Save the state of the current name resolution context. */
- ctx_state.save_state(context, table_list);
-
- /*
- Perform name resolution only in the first table - 'table_list',
- which is the table that is inserted into.
- */
- table_list->next_local= 0;
- context->resolve_in_table_list_only(table_list);
/* Prepare the fields in the statement. */
- if (values &&
- !(res= check_insert_fields(thd, context->table_list, fields, *values,
- !insert_into_view, &map) ||
- setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0)) &&
- duplic == DUP_UPDATE)
+ if (values)
{
- select_lex->no_wrap_view_item= TRUE;
- res= check_update_fields(thd, context->table_list, update_fields, &map);
- select_lex->no_wrap_view_item= FALSE;
+ /* if we have INSERT ... VALUES () we cannot have a GROUP BY clause */
+ DBUG_ASSERT (!select_lex->group_list.elements);
+
+ /* Save the state of the current name resolution context. */
+ ctx_state.save_state(context, table_list);
+
/*
- When we are not using GROUP BY we can refer to other tables in the
- ON DUPLICATE KEY part.
- */
- if (select_lex->group_list.elements == 0)
+ Perform name resolution only in the first table - 'table_list',
+ which is the table that is inserted into.
+ */
+ table_list->next_local= 0;
+ context->resolve_in_table_list_only(table_list);
+
+ if (!(res= check_insert_fields(thd, context->table_list, fields, *values,
+ !insert_into_view, &map) ||
+ setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0))
+ && duplic == DUP_UPDATE)
{
- context->table_list->next_local= ctx_state.save_next_local;
- /* first_name_resolution_table was set by resolve_in_table_list_only() */
- context->first_name_resolution_table->
- next_name_resolution_table= ctx_state.save_next_local;
+ select_lex->no_wrap_view_item= TRUE;
+ res= check_update_fields(thd, context->table_list, update_fields, &map);
+ select_lex->no_wrap_view_item= FALSE;
}
+
+ /* Restore the current context. */
+ ctx_state.restore_state(context, table_list);
+
if (!res)
res= setup_fields(thd, 0, update_values, MARK_COLUMNS_READ, 0, 0);
}
- /* Restore the current context. */
- ctx_state.restore_state(context, table_list);
-
if (res)
DBUG_RETURN(res);
@@ -1897,7 +1896,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
pthread_detach_this_thread();
/* Add thread to THD list so that's it's visible in 'show processlist' */
pthread_mutex_lock(&LOCK_thread_count);
- thd->thread_id=thread_id++;
+ thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
thd->end_time();
threads.append(thd);
thd->killed=abort_loop ? THD::KILL_CONNECTION : THD::NOT_KILLED;
@@ -1928,14 +1927,8 @@ pthread_handler_t handle_delayed_insert(void *arg)
strmov(thd->net.last_error,ER(thd->net.last_errno=ER_OUT_OF_RESOURCES));
goto err;
}
-#if !defined(__WIN__) && !defined(__NETWARE__)
- sigset_t set;
- VOID(sigemptyset(&set)); // Get mask in use
- VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
-#endif
/* open table */
-
if (!(di->table=open_ltable(thd,&di->table_list,TL_WRITE_DELAYED)))
{
thd->fatal_error(); // Abort waiting inserts
@@ -2477,7 +2470,6 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
if (info.handle_duplicates == DUP_UPDATE)
{
- /* Save the state of the current name resolution context. */
Name_resolution_context *context= &lex->select_lex.context;
Name_resolution_context_state ctx_state;
@@ -2493,18 +2485,40 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
*info.update_fields, &map);
lex->select_lex.no_wrap_view_item= FALSE;
/*
- When we are not using GROUP BY we can refer to other tables in the
- ON DUPLICATE KEY part
- */
- if (lex->select_lex.group_list.elements == 0)
+ When we are not using GROUP BY and there are no ungrouped aggregate functions
+ we can refer to other tables in the ON DUPLICATE KEY part.
+ We use next_name_resolution_table descructively, so check it first (views?)
+ */
+ DBUG_ASSERT (!table_list->next_name_resolution_table);
+ if (lex->select_lex.group_list.elements == 0 &&
+ !lex->select_lex.with_sum_func)
+ /*
+ We must make a single context out of the two separate name resolution contexts :
+ the INSERT table and the tables in the SELECT part of INSERT ... SELECT.
+ To do that we must concatenate the two lists
+ */
+ table_list->next_name_resolution_table=
+ ctx_state.get_first_name_resolution_table();
+
+ res= res || setup_fields(thd, 0, *info.update_values,
+ MARK_COLUMNS_READ, 0, 0);
+ if (!res)
{
- context->table_list->next_local= ctx_state.save_next_local;
- /* first_name_resolution_table was set by resolve_in_table_list_only() */
- context->first_name_resolution_table->
- next_name_resolution_table= ctx_state.save_next_local;
+ /*
+ Traverse the update values list and substitute fields from the
+ select for references (Item_ref objects) to them. This is done in
+ order to get correct values from those fields when the select
+ employs a temporary table.
+ */
+ List_iterator<Item> li(*info.update_values);
+ Item *item;
+
+ while ((item= li++))
+ {
+ item->transform(&Item::update_value_transformer,
+ (byte*)lex->current_select);
+ }
}
- res= res || setup_fields(thd, 0, *info.update_values, MARK_COLUMNS_READ,
- 0, 0);
/* Restore the current context. */
ctx_state.restore_state(context, table_list);