diff options
author | unknown <timour@mysql.com> | 2005-08-12 19:27:54 +0300 |
---|---|---|
committer | unknown <timour@mysql.com> | 2005-08-12 19:27:54 +0300 |
commit | 2b53b711d8c36fadf3ce123a678795876fb67be4 (patch) | |
tree | 47cfdff5ea22001b614037779ee931abbc209636 /sql/sql_insert.cc | |
parent | c9415c77b5ce586b4134b91a92447fe175c4e7b2 (diff) | |
parent | 7517d7e11298da9ce9aaea8e2e42c25a640d5be9 (diff) | |
download | mariadb-git-2b53b711d8c36fadf3ce123a678795876fb67be4.tar.gz |
Merge mysql.com:/home/timka/mysql/src/5.0-virgin
into mysql.com:/home/timka/mysql/src/5.0-2486-merge
mysql-test/r/errors.result:
Auto merged
mysql-test/r/fulltext.result:
Auto merged
mysql-test/r/fulltext_order_by.result:
Auto merged
mysql-test/r/innodb.result:
Auto merged
mysql-test/r/join_nested.result:
Auto merged
mysql-test/r/subselect.result:
Auto merged
mysql-test/t/errors.test:
Auto merged
mysql-test/t/fulltext.test:
Auto merged
mysql-test/t/fulltext_order_by.test:
Auto merged
mysql-test/t/innodb.test:
Auto merged
mysql-test/t/join_nested.test:
Auto merged
mysql-test/t/subselect.test:
Auto merged
sql/item.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/sp.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_delete.cc:
Auto merged
sql/sql_lex.cc:
Auto merged
sql/sql_lex.h:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_update.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
sql/table.h:
Auto merged
tests/mysql_client_test.c:
Auto merged
sql/sql_insert.cc:
merge WL#2486
sql/sql_show.cc:
merge WL#2486
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r-- | sql/sql_insert.cc | 176 |
1 files changed, 140 insertions, 36 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index f9923283911..62b96d567c3 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -106,12 +106,15 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, } else { // Part field list - Name_resolution_context *context= &thd->lex->select_lex.context; - TABLE_LIST *save_next= table_list->next_local, - *save_context= context->table_list; - bool save_resolve_in_select_list= - thd->lex->select_lex.context.resolve_in_select_list; + SELECT_LEX *select_lex= &thd->lex->select_lex; + Name_resolution_context *context= &select_lex->context; + TABLE_LIST *save_next_local; + TABLE_LIST *save_table_list; + TABLE_LIST *save_first_name_resolution_table; + TABLE_LIST *save_next_name_resolution_table; + bool save_resolve_in_select_list; int res; + if (fields.elements != values.elements) { my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L); @@ -119,17 +122,39 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, } thd->dupp_field=0; - thd->lex->select_lex.no_wrap_view_item= TRUE; - /* fields only from first table */ + select_lex->no_wrap_view_item= TRUE; + + /* Save the state of the current name resolution context. */ + save_table_list= context->table_list; + save_first_name_resolution_table= context->first_name_resolution_table; + save_next_name_resolution_table= (context->first_name_resolution_table) ? + context->first_name_resolution_table-> + next_name_resolution_table : + NULL; + save_resolve_in_select_list= context->resolve_in_select_list; + save_next_local= table_list->next_local; + + /* + 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); res= setup_fields(thd, 0, fields, 1, 0, 0); - table_list->next_local= save_next; + + /* Restore the current context. */ + table_list->next_local= save_next_local; + context->table_list= save_table_list; + context->first_name_resolution_table= save_first_name_resolution_table; + if (context->first_name_resolution_table) + context->first_name_resolution_table-> + next_name_resolution_table= save_next_name_resolution_table; + context->resolve_in_select_list= save_resolve_in_select_list; thd->lex->select_lex.no_wrap_view_item= FALSE; - context->table_list= save_context; - context->resolve_in_select_list= save_resolve_in_select_list; + if (res) return -1; + if (table_list->effective_algorithm == VIEW_ALGORITHM_MERGE) { /* it is join view => we need to find table for update */ @@ -254,9 +279,13 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ulonglong id; COPY_INFO info; TABLE *table= 0; - TABLE_LIST *next_local; + TABLE_LIST *save_table_list; + TABLE_LIST *save_next_local; + TABLE_LIST *save_first_name_resolution_table; + TABLE_LIST *save_next_name_resolution_table; List_iterator_fast<List_item> its(values_list); List_item *values; + Name_resolution_context *context; #ifndef EMBEDDED_LIBRARY char *query= thd->query; #endif @@ -335,9 +364,23 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, /* mysql_prepare_insert set table_list->table if it was not set */ table= table_list->table; - next_local= table_list->next_local; + context= &thd->lex->select_lex.context; + /* Save the state of the current name resolution context. */ + save_table_list= context->table_list; + save_first_name_resolution_table= context->first_name_resolution_table; + save_next_name_resolution_table= (context->first_name_resolution_table) ? + context->first_name_resolution_table-> + next_name_resolution_table : + NULL; + save_next_local= table_list->next_local; + + /* + Perform name resolution only in the first table - 'table_list', + which is the table that is inserted into. + */ table_list->next_local= 0; - thd->lex->select_lex.context.resolve_in_table_list_only(table_list); + context->resolve_in_table_list_only(table_list); + value_count= values->elements; while ((values= its++)) { @@ -351,7 +394,14 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, goto abort; } its.rewind (); - table_list->next_local= next_local; + + /* Restore the current context. */ + table_list->next_local= save_next_local; + context->first_name_resolution_table= save_first_name_resolution_table; + if (context->first_name_resolution_table) + context->first_name_resolution_table-> + next_name_resolution_table= save_next_name_resolution_table; + /* Fill in the given fields and dump it to the table file */ @@ -707,6 +757,7 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, DBUG_ENTER("mysql_prepare_insert_check_table"); if (setup_tables(thd, &thd->lex->select_lex.context, + &thd->lex->select_lex.top_join_list, table_list, where, &thd->lex->select_lex.leaf_tables, select_insert)) DBUG_RETURN(TRUE); @@ -761,10 +812,13 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, COND **where, bool select_insert) { SELECT_LEX *select_lex= &thd->lex->select_lex; + Name_resolution_context *context= &select_lex->context; TABLE_LIST *save_table_list; TABLE_LIST *save_next_local; + TABLE_LIST *save_first_name_resolution_table; + TABLE_LIST *save_next_name_resolution_table; + bool save_resolve_in_select_list; bool insert_into_view= (table_list->view != 0); - bool save_resolve_in_select_list; bool res= 0; DBUG_ENTER("mysql_prepare_insert"); DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d", @@ -802,35 +856,57 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, select_insert)) DBUG_RETURN(TRUE); - save_table_list= select_lex->context.table_list; - save_resolve_in_select_list= select_lex->context.resolve_in_select_list; - save_next_local= table_list->next_local; + /* Save the state of the current name resolution context. */ + save_table_list= context->table_list; + /* Here first_name_resolution_table points to the first select table. */ + save_first_name_resolution_table= context->first_name_resolution_table; + save_next_name_resolution_table= (context->first_name_resolution_table) ? + context->first_name_resolution_table-> + next_name_resolution_table : + NULL; + save_resolve_in_select_list= context->resolve_in_select_list; + save_next_local= table_list->next_local; + /* + Perform name resolution only in the first table - 'table_list', + which is the table that is inserted into. + */ table_list->next_local= 0; - select_lex->context.resolve_in_table_list_only(table_list); + context->resolve_in_table_list_only(table_list); + + /* Prepare the fields in the statement. */ if (values && - !(res= check_insert_fields(thd, table_list, fields, *values, - !insert_into_view) || - setup_fields(thd, 0, *values, 0, 0, 0)) && + !(res= check_insert_fields(thd, context->table_list, fields, *values, + !insert_into_view) || + setup_fields(thd, 0, *values, 0, 0, 0)) && duplic == DUP_UPDATE) { select_lex->no_wrap_view_item= TRUE; - res= check_update_fields(thd, table_list, update_fields); + res= check_update_fields(thd, context->table_list, update_fields); 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 (select_lex->group_list.elements == 0) { - /* - When we are not using GROUP BY we can refer to other tables in the - ON DUPLICATE KEY part - */ - table_list->next_local= save_next_local; + context->table_list->next_local= save_next_local; + context->first_name_resolution_table-> + next_name_resolution_table= save_next_local; } if (!res) res= setup_fields(thd, 0, update_values, 1, 0, 0); } + + /* Restore the current context. */ table_list->next_local= save_next_local; - select_lex->context.table_list= save_table_list; - select_lex->context.resolve_in_select_list= save_resolve_in_select_list; + context->table_list= save_table_list; + context->first_name_resolution_table= save_first_name_resolution_table; + if (context->first_name_resolution_table) + context->first_name_resolution_table-> + next_name_resolution_table= save_next_name_resolution_table; + context->resolve_in_select_list= save_resolve_in_select_list; + if (res) DBUG_RETURN(res); @@ -2091,24 +2167,52 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) res= check_insert_fields(thd, table_list, *fields, values, !insert_into_view) || setup_fields(thd, 0, values, 0, 0, 0); + if (info.handle_duplicates == DUP_UPDATE) { - TABLE_LIST *save_next_local= table_list->next_local; + /* Save the state of the current name resolution context. */ + Name_resolution_context *context= &lex->select_lex.context; + TABLE_LIST *save_table_list; + TABLE_LIST *save_next_local; + TABLE_LIST *save_first_name_resolution_table; + TABLE_LIST *save_next_name_resolution_table; + save_table_list= context->table_list; + save_first_name_resolution_table= context->first_name_resolution_table; + save_next_name_resolution_table= (context->first_name_resolution_table) ? + context->first_name_resolution_table-> + next_name_resolution_table : + NULL; + save_next_local= table_list->next_local; + + /* Perform name resolution only in the first table - 'table_list'. */ table_list->next_local= 0; - lex->select_lex.context.resolve_in_table_list_only(table_list); + context->resolve_in_table_list_only(table_list); + lex->select_lex.no_wrap_view_item= TRUE; - res= res || check_update_fields(thd, table_list, *info.update_fields); + res= res || check_update_fields(thd, context->table_list, + *info.update_fields); 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) - table_list->next_local= save_next_local; + if (lex->select_lex.group_list.elements == 0) + { + context->table_list->next_local= save_next_local; + context->first_name_resolution_table-> + next_name_resolution_table= save_next_local; + } res= res || setup_fields(thd, 0, *info.update_values, 1, 0, 0); + + /* Restore the current context. */ table_list->next_local= save_next_local; + context->first_name_resolution_table= save_first_name_resolution_table; + if (context->first_name_resolution_table) + context->first_name_resolution_table-> + next_name_resolution_table= save_next_name_resolution_table; + } + lex->current_select= lex_current_select_save; if (res) DBUG_RETURN(1); |