From 0bc8837943cff36d4784f2b8960d66146aeb2750 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 13:35:12 -0500 Subject: [PATCH 1/7] Bug #9148 Denial of Service my_access.c: Fixed problem where in some cases check_if_legal_filename was returning 0 for illegal names mysys/my_access.c: Fixed problem where in some cases check_if_legal_filename was returning 0 for illegal names --- mysys/my_access.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mysys/my_access.c b/mysys/my_access.c index 89e90e16f18..1b9ad6ff380 100644 --- a/mysys/my_access.c +++ b/mysys/my_access.c @@ -93,18 +93,20 @@ int check_if_legal_filename(const char *path) path+= dirname_length(path); /* To start of filename */ if (!(end= strchr(path, FN_EXTCHAR))) end= strend(path); - if (path == end || (uint) (path - end) > MAX_RESERVED_NAME_LENGTH) + if (path == end || (uint) (end - path) > MAX_RESERVED_NAME_LENGTH) DBUG_RETURN(0); /* Simplify inner loop */ for (reserved_name= reserved_names; *reserved_name; reserved_name++) { const char *name= path; - while (name != end) + const char *current_reserved_name= *reserved_name; + + while (name != end && *current_reserved_name) { - if (my_toupper(&my_charset_latin1, *path) != - my_toupper(&my_charset_latin1, *name)) + if (*current_reserved_name != my_toupper(&my_charset_latin1, *name)) break; - if (name++ == end) + current_reserved_name++; + if (++name == end) DBUG_RETURN(1); /* Found wrong path */ } } From a6c7fb455ae6114ae53be58c49d4ef7dbdcd5e3e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 07:18:42 +0400 Subject: [PATCH 2/7] 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. sql/item.h: Fix bug#9728 decreased functionality in "on duplicate key update". sql/item.cc: Fix bug#9728 decreased functionality in "on duplicate key update" sql/sql_parse.cc: Fix bug#9728 decreased functionality in "on duplicate key update" sql/sql_base.cc: Fix bug#9728 decreased functionality in "on duplicate key update". sql/sql_yacc.yy: Fix bug#9728 decreased functionality in "on duplicate key update" mysql-test/t/insert_select.test: Test case for bug#9728 Decreased functionality in "on duplicate key update". mysql-test/r/insert_select.result: Test case for bug#9728 Decreased functionality in "on duplicate key update". --- mysql-test/r/insert_select.result | 15 +++++++++++++++ mysql-test/t/insert_select.test | 14 ++++++++++++++ sql/item.cc | 4 +++- sql/item.h | 11 +++++++++++ sql/sql_base.cc | 7 +++++-- sql/sql_parse.cc | 9 +++------ sql/sql_yacc.yy | 15 +++++++++++++++ 7 files changed, 66 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 082b7098a1a..69eb64f08ea 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -634,3 +634,18 @@ ff1 ff2 1 2 2 1 drop table t1, t2; +create table t1 (a int unique); +create table t2 (a int, b int); +insert into t1 values (1),(2); +insert into t2 values (1,2); +select * from t1; +a +1 +2 +insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b; +select * from t1; +a +2 +3 +drop table t1; +drop table t2; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 613c97dc4f1..7402940fa52 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -175,3 +175,17 @@ insert into t1 values (1),(1),(2); insert into t2(ff1) select f1 from t1 on duplicate key update ff2=ff2+1; select * from t2; drop table t1, t2; +# +# BUGS #9728 - 'Decreased functionality in "on duplicate key update"' +# #8147 - 'a column proclaimed ambigous in INSERT ... SELECT .. ON +# DUPLICATE' +# +create table t1 (a int unique); +create table t2 (a int, b int); +insert into t1 values (1),(2); +insert into t2 values (1,2); +select * from t1; +insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b; +select * from t1; +drop table t1; +drop table t2; 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: From 2e7df19baddcf500dd89a43c81272cfcf8cfbefd Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 05:18:43 +0200 Subject: [PATCH 3/7] fix README file to be more verbose match actual situation (recomitted to push into 4.1) mysql-test/README: fix README file to be more verbose match actual situation --- mysql-test/README | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/mysql-test/README b/mysql-test/README index 65e6186613a..10d64784ed4 100644 --- a/mysql-test/README +++ b/mysql-test/README @@ -2,8 +2,17 @@ This directory contains a test suite for mysql daemon. To run the currently existing test cases, simply execute ./mysql-test-run in this directory. It will fire up the newly built mysqld and test it. -If you want to run the test with a running MySQL server use the --external -option to mysql-test-run. +If you want to run a test with a running MySQL server use the --extern +option to mysql-test-run. Please note that in this mode the test suite +expects user to specify test names to run. Otherwise it falls back to the +normal "non-extern" behaviour. The reason is that some tests +could not run with external server. Here is the sample command +to test "alias" and "analyze" tests on external server: + +mysql-test-run --extern alias analyze + +To match your setup you might also need to provide --socket, --user and +other relevant options. Note that you do not have to have to do make install, and you could actually have a co-existing MySQL installation - the tests will not From f837c0add5ae96119e7ed7704396994d88beff32 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 19:29:34 +0200 Subject: [PATCH 4/7] Bug# 9926, This is the same as changeset 1.1934, which was approved by Monty sql/ha_federated.cc: Added auto-reconnect to allow foreign server restarts. --- sql/ha_federated.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 89210a2f3cd..77db17608bc 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -462,6 +462,12 @@ static int check_foreign_data_source(FEDERATED_SHARE *share) } else { + /* + Since we do not support transactions at this version, we can let the client + API silently reconnect. For future versions, we will need more logic to deal + with transactions + */ + mysql->reconnect= 1; /* Note: I am not using INORMATION_SCHEMA because this needs to work with < 5.0 if we can connect, then make sure the table exists @@ -988,6 +994,12 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked) my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql)); DBUG_RETURN(ER_CONNECT_TO_MASTER); } + /* + Since we do not support transactions at this version, we can let the client + API silently reconnect. For future versions, we will need more logic to deal + with transactions + */ + mysql->reconnect= 1; DBUG_RETURN(0); } From 256c99fdb282512d87f5e6db59cc207024bd06c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 22:58:44 +0400 Subject: [PATCH 5/7] item.h: Fix for fix for bug#9728 decreased functionality in "on duplicate key update" Have to return false to set flag for whole expression. sql/item.h: Fix for fix for bug#9728 decreased functionality in "on duplicate key update" Have to return false to set flag for whole expression. --- sql/item.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item.h b/sql/item.h index d9a40cbdfb6..82ab5a66cfb 100644 --- a/sql/item.h +++ b/sql/item.h @@ -336,7 +336,7 @@ public: virtual bool set_flags_processor(byte *args) { this->item_flags|= *((uint8*)args); - return true; + return false; } }; From 60d6b877758e5f3dc6af3abd2dcaff19960ab87c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 23:12:25 +0400 Subject: [PATCH 6/7] Remove THD::stmt_backup sql/sql_class.cc: Statement constructor for the case when it's used for backup only was removed. sql/sql_class.h: Remove THD::stmt_backup and simplify Statement constructors. sql/sql_prepare.cc: Use an object on stack instead of THD::stmt_backup sql/sql_select.cc: Use an object on stack instead of THD::stmt_backup --- sql/sql_class.cc | 43 ++++++++++++------------------------------- sql/sql_class.h | 15 ++++----------- sql/sql_prepare.cc | 36 ++++++++++++++++++++---------------- sql/sql_select.cc | 5 +++-- 4 files changed, 39 insertions(+), 60 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f54135ea8cb..8abd7cbbe7d 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -156,9 +156,15 @@ bool foreign_key_prefix(Key *a, Key *b) /**************************************************************************** ** Thread specific functions ****************************************************************************/ +/* + Pass nominal parameters to Statement constructor only to ensure that + the destructor works OK in case of error. The main_mem_root will be + re-initialized in init(). +*/ THD::THD() - :user_time(0), global_read_lock(0), is_fatal_error(0), + :Statement(CONVENTIONAL_EXECUTION, 0, ALLOC_ROOT_MIN_BLOCK_SIZE, 0), + user_time(0), global_read_lock(0), is_fatal_error(0), rand_used(0), time_zone_used(0), last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0), in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE), @@ -1483,9 +1489,10 @@ Query_arena::Type Query_arena::type() const Statement functions */ -Statement::Statement(THD *thd) - :Query_arena(&main_mem_root, INITIALIZED), - id(++thd->statement_id_counter), +Statement::Statement(enum enum_state state_arg, ulong id_arg, + ulong alloc_block_size, ulong prealloc_size) + :Query_arena(&main_mem_root, state_arg), + id(id_arg), set_query_id(1), allow_sum_func(0), lex(&main_lex), @@ -1494,33 +1501,7 @@ Statement::Statement(THD *thd) cursor(0) { name.str= NULL; - init_sql_alloc(&main_mem_root, - thd->variables.query_alloc_block_size, - thd->variables.query_prealloc_size); -} - -/* - This constructor is called when Statement is a parent of THD and - for the backup statement. Some variables are initialized in - THD::init due to locking problems. -*/ - -Statement::Statement() - :Query_arena(&main_mem_root, CONVENTIONAL_EXECUTION), - id(0), - set_query_id(1), - allow_sum_func(0), /* initialized later */ - lex(&main_lex), - query(0), /* these two are set */ - query_length(0), /* in alloc_query() */ - cursor(0) -{ - /* - This is just to ensure that the destructor works correctly in - case of an error and the backup statement. The memory root will - be re-initialized in THD::init. - */ - init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0); + init_sql_alloc(&main_mem_root, alloc_block_size, prealloc_size); } diff --git a/sql/sql_class.h b/sql/sql_class.h index fff789d3066..a635a126f84 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -809,13 +809,11 @@ public: public: - /* - This constructor is called when statement is a subobject of THD: - some variables are initialized in THD::init due to locking problems - */ - Statement(); + /* This constructor is called for backup statements */ + Statement() { clear_alloc_root(&main_mem_root); } - Statement(THD *thd); + Statement(enum enum_state state_arg, ulong id_arg, + ulong alloc_block_size, ulong prealloc_size); virtual ~Statement(); /* Assign execution context (note: not all members) of given stmt to self */ @@ -957,11 +955,6 @@ public: pthread_mutex_t LOCK_delete; // Locked before thd is deleted /* all prepared statements and cursors of this connection */ Statement_map stmt_map; - /* - keeps THD state while it is used for active statement - Note: we perform special cleanup for it in THD destructor. - */ - Statement stmt_backup; /* A pointer to the stack frame of handle_one_connection(), which is called first in the thread for handling a client diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 73bbea79760..eeea493d868 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1706,6 +1706,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, LEX_STRING *name) { LEX *lex; + Statement stmt_backup; Prepared_statement *stmt= new Prepared_statement(thd); bool error; DBUG_ENTER("mysql_stmt_prepare"); @@ -1739,13 +1740,13 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, DBUG_RETURN(TRUE); } - thd->set_n_backup_statement(stmt, &thd->stmt_backup); - thd->set_n_backup_item_arena(stmt, &thd->stmt_backup); + thd->set_n_backup_statement(stmt, &stmt_backup); + thd->set_n_backup_item_arena(stmt, &stmt_backup); if (alloc_query(thd, packet, packet_length)) { - thd->restore_backup_statement(stmt, &thd->stmt_backup); - thd->restore_backup_item_arena(stmt, &thd->stmt_backup); + thd->restore_backup_statement(stmt, &stmt_backup); + thd->restore_backup_item_arena(stmt, &stmt_backup); /* Statement map deletes statement on erase */ thd->stmt_map.erase(stmt); DBUG_RETURN(TRUE); @@ -1770,7 +1771,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, transformation can be reused on execute, we set again thd->mem_root from stmt->mem_root (see setup_wild for one place where we do that). */ - thd->restore_backup_item_arena(stmt, &thd->stmt_backup); + thd->restore_backup_item_arena(stmt, &stmt_backup); if (!error) error= check_prepared_statement(stmt, test(name)); @@ -1786,7 +1787,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, lex_end(lex); close_thread_tables(thd); cleanup_stmt_and_thd_after_use(stmt, thd); - thd->restore_backup_statement(stmt, &thd->stmt_backup); + thd->restore_backup_statement(stmt, &stmt_backup); thd->current_arena= thd; if (error) @@ -1949,6 +1950,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) { ulong stmt_id= uint4korr(packet); ulong flags= (ulong) ((uchar) packet[4]); + Statement stmt_backup; Cursor *cursor; /* Query text for binary log, or empty string if the query is not put into @@ -2026,8 +2028,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) if (stmt->param_count && stmt->set_params_data(stmt, &expanded_query)) goto set_params_data_err; #endif - thd->stmt_backup.set_statement(thd); - thd->set_statement(stmt); + thd->set_n_backup_statement(stmt, &stmt_backup); thd->current_arena= stmt; reinit_stmt_before_use(thd, stmt->lex); /* From now cursors assume that thd->mem_root is clean */ @@ -2064,7 +2065,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) reset_stmt_params(stmt); } - thd->set_statement(&thd->stmt_backup); + thd->set_statement(&stmt_backup); thd->current_arena= thd; DBUG_VOID_RETURN; @@ -2089,6 +2090,7 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name) binary log. */ String expanded_query; + Statement stmt_backup; DBUG_ENTER("mysql_sql_stmt_execute"); DBUG_ASSERT(thd->free_list == NULL); @@ -2110,16 +2112,16 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name) /* Must go before setting variables, as it clears thd->user_var_events */ mysql_reset_thd_for_next_command(thd); - thd->set_n_backup_statement(stmt, &thd->stmt_backup); - thd->set_statement(stmt); + thd->set_n_backup_statement(stmt, &stmt_backup); if (stmt->set_params_from_vars(stmt, - thd->stmt_backup.lex->prepared_stmt_params, + stmt_backup.lex->prepared_stmt_params, &expanded_query)) { my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE"); } thd->command= COM_STMT_EXECUTE; /* For nice messages in general log */ execute_stmt(thd, stmt, &expanded_query); + thd->set_statement(&stmt_backup); DBUG_VOID_RETURN; } @@ -2176,7 +2178,6 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt, close_thread_tables(thd); // to close derived tables cleanup_stmt_and_thd_after_use(stmt, thd); reset_stmt_params(stmt); - thd->set_statement(&thd->stmt_backup); thd->current_arena= thd; if (stmt->state == Query_arena::PREPARED) @@ -2201,6 +2202,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) ulong stmt_id= uint4korr(packet); ulong num_rows= uint4korr(packet+4); Prepared_statement *stmt; + Statement stmt_backup; DBUG_ENTER("mysql_stmt_fetch"); statistic_increment(thd->status_var.com_stmt_fetch, &LOCK_status); @@ -2214,7 +2216,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) } thd->current_arena= stmt; - thd->set_n_backup_statement(stmt, &thd->stmt_backup); + thd->set_n_backup_statement(stmt, &stmt_backup); if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), QUERY_PRIOR); @@ -2226,7 +2228,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); - thd->restore_backup_statement(stmt, &thd->stmt_backup); + thd->restore_backup_statement(stmt, &stmt_backup); thd->current_arena= thd; if (!stmt->cursor->is_open()) @@ -2386,7 +2388,9 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) Prepared_statement::Prepared_statement(THD *thd_arg) - :Statement(thd_arg), + :Statement(INITIALIZED, ++thd_arg->statement_id_counter, + thd_arg->variables.query_alloc_block_size, + thd_arg->variables.query_prealloc_size), thd(thd_arg), param_array(0), param_count(0), diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b72cce30bbc..1487dfbb436 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1824,6 +1824,7 @@ Cursor::fetch(ulong num_rows) THD *thd= join->thd; JOIN_TAB *join_tab= join->join_tab + join->const_tables; enum_nested_loop_state error= NESTED_LOOP_OK; + Query_arena backup_arena; DBUG_ENTER("Cursor::fetch"); DBUG_PRINT("enter",("rows: %lu", num_rows)); @@ -1835,7 +1836,7 @@ Cursor::fetch(ulong num_rows) thd->lock= lock; thd->query_id= query_id; /* save references to memory, allocated during fetch */ - thd->set_n_backup_item_arena(this, &thd->stmt_backup); + thd->set_n_backup_item_arena(this, &backup_arena); join->fetch_limit+= num_rows; @@ -1851,7 +1852,7 @@ Cursor::fetch(ulong num_rows) ha_release_temporary_latches(thd); #endif - thd->restore_backup_item_arena(this, &thd->stmt_backup); + thd->restore_backup_item_arena(this, &backup_arena); DBUG_ASSERT(thd->free_list == 0); reset_thd(thd); From 557184734f3b4c11710e42aa5ad8ff6d658576d0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 03:51:10 +0400 Subject: [PATCH 7/7] insert_update.result, insert_update.test, sql_base.cc: Fix for bugfix #9728 merge sql/sql_base.cc: Fix for bugfix #9728 merge mysql-test/t/insert_update.test: Fix for bugfix #9728 merge mysql-test/r/insert_update.result: Fix for bugfix #9728 merge --- mysql-test/r/insert_update.result | 2 +- mysql-test/t/insert_update.test | 2 +- sql/sql_base.cc | 13 +++++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index 6d3aa941c8c..739beea6286 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -1,4 +1,4 @@ -DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t1, t2; CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B)); INSERT t1 VALUES (1,2,10), (3,4,20); INSERT t1 VALUES (5,6,30) ON DUPLICATE KEY UPDATE c=c+100; diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test index f5857840588..7653fd8dd42 100644 --- a/mysql-test/t/insert_update.test +++ b/mysql-test/t/insert_update.test @@ -1,5 +1,5 @@ --disable_warnings -DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t1, t2; --enable_warnings CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B)); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index d4ded4a4772..e9af684767d 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2626,7 +2626,6 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, uint length=(uint) strlen(name); char name_buff[NAME_LEN+1]; - if (item->cached_table) { /* @@ -2693,10 +2692,13 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, db= name_buff; } + bool search_global= item->item_flags & MY_ITEM_PREFER_1ST_TABLE; if (table_name && table_name[0]) { /* Qualified field */ - bool found_table=0; - for (; tables; tables= tables->next_local) + bool found_table=0; + uint table_idx= 0; + for (; tables; tables= search_global?tables->next_global:tables->next_local, + table_idx++) { /* TODO; Ensure that db and tables->db always points to something ! */ if (!my_strcasecmp(table_alias_charset, tables->alias, table_name) && @@ -2732,6 +2734,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, return (Field*) 0; } found=find; + if (table_idx == 0 && item->item_flags & MY_ITEM_PREFER_1ST_TABLE) + break; } } } @@ -2758,7 +2762,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, } bool allow_rowid= tables && !tables->next_local; // Only one table uint table_idx= 0; - for (; tables ; tables= tables->next_local, table_idx++) + for (; tables ; tables= search_global?tables->next_global:tables->next_local, + table_idx++) { if (!tables->table && !tables->ancestor) {