diff options
author | unknown <marty@flipper.bredbandsbolaget.se> | 2005-06-23 10:58:37 +0200 |
---|---|---|
committer | unknown <marty@flipper.bredbandsbolaget.se> | 2005-06-23 10:58:37 +0200 |
commit | ed439bc6a2b1b02c65f0a93078488ddd9e8a13fc (patch) | |
tree | cb7fd7068d67fac6b8197f74309105291303b970 | |
parent | 81a7a93f421547640afcdb0ecef1c1717152d27a (diff) | |
parent | 9dfb7aab152881736329e66bf1ea1e471753ebe9 (diff) | |
download | mariadb-git-ed439bc6a2b1b02c65f0a93078488ddd9e8a13fc.tar.gz |
Merge flipper.bredbandsbolaget.se:/home/marty/MySQL/mysql-5.0
into flipper.bredbandsbolaget.se:/home/marty/MySQL/mysql-5.1
sql/ha_federated.cc:
Auto merged
sql/item.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
BitKeeper/etc/logging_ok:
Logging to logging@openlogging.org accepted
-rw-r--r-- | BitKeeper/etc/logging_ok | 1 | ||||
-rw-r--r-- | mysql-test/README | 13 | ||||
-rw-r--r-- | mysql-test/lib/mtr_cases.pl | 8 | ||||
-rw-r--r-- | mysql-test/r/insert_select.result | 15 | ||||
-rw-r--r-- | mysql-test/r/insert_update.result | 2 | ||||
-rw-r--r-- | mysql-test/r/rpl_multi_update3.result | 43 | ||||
-rw-r--r-- | mysql-test/t/insert_select.test | 14 | ||||
-rw-r--r-- | mysql-test/t/insert_update.test | 2 | ||||
-rw-r--r-- | mysql-test/t/rpl_multi_update3.test | 34 | ||||
-rw-r--r-- | mysys/my_access.c | 12 | ||||
-rw-r--r-- | sql/ha_federated.cc | 12 | ||||
-rw-r--r-- | sql/item.cc | 4 | ||||
-rw-r--r-- | sql/item.h | 11 | ||||
-rw-r--r-- | sql/sql_base.cc | 19 | ||||
-rw-r--r-- | sql/sql_class.cc | 43 | ||||
-rw-r--r-- | sql/sql_class.h | 15 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 36 | ||||
-rw-r--r-- | sql/sql_select.cc | 5 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 15 |
19 files changed, 228 insertions, 76 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 4c3233817ab..416ab8dbbde 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -140,6 +140,7 @@ magnus@msdesk.mysql.com magnus@neptunus.(none) magnus@shellback.(none) marko@hundin.mysql.fi +marty@flipper.bredbandsbolaget.se marty@linux.site marty@shark. mats@mysql.com 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 diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 72cbe72bc0a..2babaabc24c 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -154,6 +154,14 @@ sub collect_one_test_case($$$$$) { } } + if ( defined mtr_match_prefix($tname,"federated") ) + { + $tinfo->{'slave_num'}= 1; # Default, use one slave + + # FIXME currently we always restart slaves + $tinfo->{'slave_restart'}= 1; + } + # FIXME what about embedded_server + ndbcluster, skip ?! my $master_opt_file= "$testdir/$tname-master.opt"; diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 11384b0feff..026dae8381a 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/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/r/rpl_multi_update3.result b/mysql-test/r/rpl_multi_update3.result new file mode 100644 index 00000000000..708b230b19f --- /dev/null +++ b/mysql-test/r/rpl_multi_update3.result @@ -0,0 +1,43 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t1 ( +a int unsigned not null auto_increment primary key, +b int unsigned +) ENGINE=MyISAM; +CREATE TABLE t2 ( +a int unsigned not null auto_increment primary key, +b int unsigned +) ENGINE=MyISAM; +INSERT INTO t1 VALUES (NULL, 0); +INSERT INTO t1 SELECT NULL, 0 FROM t1; +INSERT INTO t2 VALUES (NULL, 0), (NULL,1); +SELECT * FROM t1 ORDER BY a; +a b +1 0 +2 0 +SELECT * FROM t2 ORDER BY a; +a b +1 0 +2 1 +UPDATE t2, (SELECT a FROM t1) AS t SET t2.b = t.a+5 ; +SELECT * FROM t1 ORDER BY a; +a b +1 0 +2 0 +SELECT * FROM t2 ORDER BY a; +a b +1 6 +2 6 +SELECT * FROM t1 ORDER BY a; +a b +1 0 +2 0 +SELECT * FROM t2 ORDER BY a; +a b +1 6 +2 6 +drop table t1,t2; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 834561ed5f7..a6468c52645 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -173,3 +173,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/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/mysql-test/t/rpl_multi_update3.test b/mysql-test/t/rpl_multi_update3.test new file mode 100644 index 00000000000..b8c8ed79532 --- /dev/null +++ b/mysql-test/t/rpl_multi_update3.test @@ -0,0 +1,34 @@ +# Let's verify that multi-update with a subselect does not cause the slave to crash +# (BUG#10442) + +source include/master-slave.inc; + +CREATE TABLE t1 ( + a int unsigned not null auto_increment primary key, + b int unsigned +) ENGINE=MyISAM; + +CREATE TABLE t2 ( + a int unsigned not null auto_increment primary key, + b int unsigned +) ENGINE=MyISAM; + +INSERT INTO t1 VALUES (NULL, 0); +INSERT INTO t1 SELECT NULL, 0 FROM t1; + +INSERT INTO t2 VALUES (NULL, 0), (NULL,1); + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +UPDATE t2, (SELECT a FROM t1) AS t SET t2.b = t.a+5 ; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +save_master_pos; +connection slave; +sync_with_master; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +drop table t1,t2; diff --git a/mysys/my_access.c b/mysys/my_access.c index 28210bdfc7d..c01031827c0 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 */ } } diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 844612e0643..c18ca5d7915 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); } diff --git a/sql/item.cc b/sql/item.cc index 29d580cad00..ec685982304 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -338,6 +338,7 @@ Item::Item(): place == IN_HAVING) thd->lex->current_select->select_n_having_items++; } + item_flags= 0; } /* @@ -358,7 +359,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 c912ad3f0a7..c8180b4932a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -225,6 +225,11 @@ typedef Item* (Item::*Item_transformer) (byte *arg); typedef void (*Cond_traverser) (const Item *item, void *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 &); @@ -272,6 +277,7 @@ public: my_bool is_autogenerated_name; /* indicate was name of this Item autogenerated or set by user */ DTCollation collation; + uint8 item_flags; /* Flags on how item should be processed */ // alloc & destruct is done as start of select using sql_alloc Item(); @@ -584,6 +590,11 @@ public: cleanup(); delete this; } + virtual bool set_flags_processor(byte *args) + { + this->item_flags|= *((uint8*)args); + return false; + } virtual bool is_splocal() { return 0; } /* Needed for error checking */ }; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 312bc3b187b..b112ca971c3 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2628,7 +2628,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) { /* @@ -2695,10 +2694,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) && @@ -2734,6 +2736,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,9 +2762,10 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, return (Field*) not_found_field; return (Field*) 0; } - bool allow_rowid= tables && !tables->next_local; // Only one table - for (; tables ; tables= tables->next_local) + uint table_idx= 0; + for (; tables ; tables= search_global?tables->next_global:tables->next_local, + table_idx++) { if (!tables->table && !tables->ancestor) { @@ -2795,7 +2800,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, my_error(ER_NON_UNIQ_ERROR, MYF(0), 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_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 4a4754583df..fbc5e5f85bf 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -817,13 +817,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 */ @@ -966,11 +964,6 @@ public: /* 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 92a0b68ffa5..bea68bf4da5 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1820,6 +1820,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)); @@ -1831,7 +1832,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; @@ -1847,7 +1848,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); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f987063642e..edca9cf3c5f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6120,9 +6120,24 @@ insert_update_elem: simple_ident_nospvar 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: |