diff options
author | evgen@moonbone.local <> | 2005-06-22 07:18:42 +0400 |
---|---|---|
committer | evgen@moonbone.local <> | 2005-06-22 07:18:42 +0400 |
commit | 2235ea9593eac1fa40c6c13cb7345f6356428505 (patch) | |
tree | da44d153c0a60ceb5f7abf6e089ae58aca2d0274 /sql | |
parent | a24336cdcb62371b04c319936235980a34851489 (diff) | |
download | mariadb-git-2235ea9593eac1fa40c6c13cb7345f6356428505.tar.gz |
Fix bug #9728 decreased functionality in "on duplicate key update"
Remove changes made by bug fix #8147. They strips list of insert_table_list to
only insert table, which results in error reported in bug #9728.
Added flag to Item to resolve ambigous fields reported in bug #8147.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 4 | ||||
-rw-r--r-- | sql/item.h | 11 | ||||
-rw-r--r-- | sql/sql_base.cc | 7 | ||||
-rw-r--r-- | sql/sql_parse.cc | 9 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 15 |
5 files changed, 37 insertions, 9 deletions
diff --git a/sql/item.cc b/sql/item.cc index c96794ff482..9c5bf499d11 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -65,6 +65,7 @@ Item::Item(): place == IN_HAVING) thd->lex->current_select->select_n_having_items++; } + item_flags= 0; } /* @@ -83,7 +84,8 @@ Item::Item(THD *thd, Item *item): unsigned_flag(item->unsigned_flag), with_sum_func(item->with_sum_func), fixed(item->fixed), - collation(item->collation) + collation(item->collation), + item_flags(item->item_flags) { next= thd->free_list; // Put in free list thd->free_list= this; diff --git a/sql/item.h b/sql/item.h index 8de2adeb730..d9a40cbdfb6 100644 --- a/sql/item.h +++ b/sql/item.h @@ -107,6 +107,11 @@ public: typedef bool (Item::*Item_processor)(byte *arg); +/* + See comments for sql_yacc.yy: insert_update_elem rule + */ +#define MY_ITEM_PREFER_1ST_TABLE 1 + class Item { Item(const Item &); /* Prevent use of these */ void operator=(Item &); @@ -142,6 +147,7 @@ public: my_bool with_sum_func; my_bool fixed; /* If item fixed with fix_fields */ DTCollation collation; + uint8 item_flags; /* Flags on how item should be processed */ // alloc & destruct is done as start of select using sql_alloc Item(); @@ -327,6 +333,11 @@ public: cleanup(); delete this; } + virtual bool set_flags_processor(byte *args) + { + this->item_flags|= *((uint8*)args); + return true; + } }; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e3c0efb83b8..84c03bee917 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2086,7 +2086,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, return (Field*) 0; } bool allow_rowid= tables && !tables->next; // Only one table - for (; tables ; tables=tables->next) + uint table_idx= 0; + for (; tables ; tables=tables->next, table_idx++) { if (!tables->table) { @@ -2114,7 +2115,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, name,thd->where); return (Field*) 0; } - found=field; + found= field; + if (table_idx == 0 && item->item_flags & MY_ITEM_PREFER_1ST_TABLE) + break; } } if (found) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4d339fc6a0e..233104c9a90 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2856,17 +2856,14 @@ unsent_create_error: if ((res= open_and_lock_tables(thd, tables))) break; - TABLE *table= tables->table; /* Skip first table, which is the table we are inserting in */ select_lex->table_list.first= (byte*) first_local_table->next; - tables= (TABLE_LIST *) select_lex->table_list.first; - first_local_table->next= 0; if (!(res= mysql_prepare_insert(thd, tables, first_local_table, - table, lex->field_list, 0, + tables->table, lex->field_list, 0, lex->update_list, lex->value_list, lex->duplicates)) && - (result= new select_insert(table, &lex->field_list, + (result= new select_insert(tables->table, &lex->field_list, &lex->update_list, &lex->value_list, lex->duplicates, lex->ignore))) { @@ -2879,7 +2876,7 @@ unsent_create_error: /* revert changes for SP */ lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; delete result; - table->insert_values= 0; + tables->table->insert_values= 0; if (thd->net.report_error) res= -1; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index bc21649fe54..460234de156 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4239,9 +4239,24 @@ insert_update_elem: simple_ident equal expr_or_default { LEX *lex= Lex; + uint8 tmp= MY_ITEM_PREFER_1ST_TABLE; if (lex->update_list.push_back($1) || lex->value_list.push_back($3)) YYABORT; + /* + INSERT INTO a1(a) SELECT b1.a FROM b1 ON DUPLICATE KEY + UPDATE a= a + b1.b + + Set MY_ITEM_PREFER_1ST_TABLE flag to $1 and $3 items + to prevent find_field_in_tables() doing further item searching + if it finds item occurence in first table in insert_table_list. + This allows to avoid ambiguity in resolving 'a' field in + example above. + */ + $1->walk(&Item::set_flags_processor, + (byte *) &tmp); + $3->walk(&Item::set_flags_processor, + (byte *) &tmp); }; opt_low_priority: |