diff options
author | unknown <gluh@eagle.(none)> | 2007-02-26 15:54:43 +0400 |
---|---|---|
committer | unknown <gluh@eagle.(none)> | 2007-02-26 15:54:43 +0400 |
commit | b10600528dfd92a4d1dcd5d3bff1e0c0f41672a8 (patch) | |
tree | 62234448cb3dc85a182c21b8ef92ed380c119cd6 /sql/sql_insert.cc | |
parent | 5b64b12c7fec848c07475d26a6923dac93a1e5bc (diff) | |
parent | 90d4f80922c7f8873ed8c415303f8d7276f5e32d (diff) | |
download | mariadb-git-b10600528dfd92a4d1dcd5d3bff1e0c0f41672a8.tar.gz |
Merge mysql.com:/home/gluh/MySQL/Merge/5.0-opt
into mysql.com:/home/gluh/MySQL/Merge/5.1-opt
mysql-test/r/innodb.result:
Auto merged
mysql-test/r/insert_update.result:
Auto merged
mysql-test/r/myisam.result:
Auto merged
mysql-test/r/select.result:
Auto merged
mysql-test/r/subselect3.result:
Auto merged
mysql-test/r/type_blob.result:
Auto merged
mysql-test/t/insert_update.test:
Auto merged
mysql-test/t/select.test:
Auto merged
BitKeeper/deleted/.del-bdb.result:
Auto merged
mysql-test/extra/binlog_tests/blackhole.test:
Auto merged
sql/item.cc:
Auto merged
sql/item.h:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_delete.cc:
Auto merged
sql/sql_lex.cc:
Auto merged
sql/sql_lex.h:
Auto merged
sql/sql_prepare.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_union.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
storage/blackhole/ha_blackhole.cc:
Auto merged
mysql-test/r/binlog_stm_blackhole.result:
manual merge
mysql-test/r/insert_select.result:
manual merge
mysql-test/r/subselect.result:
manual merge
mysql-test/r/update.result:
manual merge
mysql-test/t/insert_select.test:
manual merge
mysql-test/t/subselect.test:
manual merge
sql/sql_help.cc:
manual merge
sql/sql_insert.cc:
manual merge
sql/sql_update.cc:
manual merge
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r-- | sql/sql_insert.cc | 95 |
1 files changed, 56 insertions, 39 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 9b66d5c5148..3501675f09f 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -946,6 +946,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 +979,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); @@ -2477,7 +2475,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 +2490,38 @@ 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); |