Commit ed439bc6 authored by unknown's avatar unknown

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
parents 81a7a93f 9dfb7aab
...@@ -140,6 +140,7 @@ magnus@msdesk.mysql.com ...@@ -140,6 +140,7 @@ magnus@msdesk.mysql.com
magnus@neptunus.(none) magnus@neptunus.(none)
magnus@shellback.(none) magnus@shellback.(none)
marko@hundin.mysql.fi marko@hundin.mysql.fi
marty@flipper.bredbandsbolaget.se
marty@linux.site marty@linux.site
marty@shark. marty@shark.
mats@mysql.com mats@mysql.com
......
...@@ -2,8 +2,17 @@ This directory contains a test suite for mysql daemon. To run ...@@ -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 the currently existing test cases, simply execute ./mysql-test-run in
this directory. It will fire up the newly built mysqld and test it. 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 If you want to run a test with a running MySQL server use the --extern
option to mysql-test-run. 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 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 actually have a co-existing MySQL installation - the tests will not
......
...@@ -154,6 +154,14 @@ sub collect_one_test_case($$$$$) { ...@@ -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 ?! # FIXME what about embedded_server + ndbcluster, skip ?!
my $master_opt_file= "$testdir/$tname-master.opt"; my $master_opt_file= "$testdir/$tname-master.opt";
......
...@@ -634,3 +634,18 @@ ff1 ff2 ...@@ -634,3 +634,18 @@ ff1 ff2
1 2 1 2
2 1 2 1
drop table t1, t2; 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;
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B)); 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 (1,2,10), (3,4,20);
INSERT t1 VALUES (5,6,30) ON DUPLICATE KEY UPDATE c=c+100; INSERT t1 VALUES (5,6,30) ON DUPLICATE KEY UPDATE c=c+100;
......
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;
...@@ -173,3 +173,17 @@ insert into t1 values (1),(1),(2); ...@@ -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; insert into t2(ff1) select f1 from t1 on duplicate key update ff2=ff2+1;
select * from t2; select * from t2;
drop table t1, 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;
--disable_warnings --disable_warnings
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1, t2;
--enable_warnings --enable_warnings
CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B)); CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B));
......
# 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;
...@@ -93,18 +93,20 @@ int check_if_legal_filename(const char *path) ...@@ -93,18 +93,20 @@ int check_if_legal_filename(const char *path)
path+= dirname_length(path); /* To start of filename */ path+= dirname_length(path); /* To start of filename */
if (!(end= strchr(path, FN_EXTCHAR))) if (!(end= strchr(path, FN_EXTCHAR)))
end= strend(path); 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 */ DBUG_RETURN(0); /* Simplify inner loop */
for (reserved_name= reserved_names; *reserved_name; reserved_name++) for (reserved_name= reserved_names; *reserved_name; reserved_name++)
{ {
const char *name= path; 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) != if (*current_reserved_name != my_toupper(&my_charset_latin1, *name))
my_toupper(&my_charset_latin1, *name))
break; break;
if (name++ == end) current_reserved_name++;
if (++name == end)
DBUG_RETURN(1); /* Found wrong path */ DBUG_RETURN(1); /* Found wrong path */
} }
} }
......
...@@ -462,6 +462,12 @@ static int check_foreign_data_source(FEDERATED_SHARE *share) ...@@ -462,6 +462,12 @@ static int check_foreign_data_source(FEDERATED_SHARE *share)
} }
else 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 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 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) ...@@ -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)); my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql));
DBUG_RETURN(ER_CONNECT_TO_MASTER); 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); DBUG_RETURN(0);
} }
......
...@@ -338,6 +338,7 @@ Item::Item(): ...@@ -338,6 +338,7 @@ Item::Item():
place == IN_HAVING) place == IN_HAVING)
thd->lex->current_select->select_n_having_items++; thd->lex->current_select->select_n_having_items++;
} }
item_flags= 0;
} }
/* /*
...@@ -358,7 +359,8 @@ Item::Item(THD *thd, Item *item): ...@@ -358,7 +359,8 @@ Item::Item(THD *thd, Item *item):
unsigned_flag(item->unsigned_flag), unsigned_flag(item->unsigned_flag),
with_sum_func(item->with_sum_func), with_sum_func(item->with_sum_func),
fixed(item->fixed), fixed(item->fixed),
collation(item->collation) collation(item->collation),
item_flags(item->item_flags)
{ {
next= thd->free_list; // Put in free list next= thd->free_list; // Put in free list
thd->free_list= this; thd->free_list= this;
......
...@@ -225,6 +225,11 @@ typedef Item* (Item::*Item_transformer) (byte *arg); ...@@ -225,6 +225,11 @@ typedef Item* (Item::*Item_transformer) (byte *arg);
typedef void (*Cond_traverser) (const Item *item, void *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 { class Item {
Item(const Item &); /* Prevent use of these */ Item(const Item &); /* Prevent use of these */
void operator=(Item &); void operator=(Item &);
...@@ -272,6 +277,7 @@ public: ...@@ -272,6 +277,7 @@ public:
my_bool is_autogenerated_name; /* indicate was name of this Item my_bool is_autogenerated_name; /* indicate was name of this Item
autogenerated or set by user */ autogenerated or set by user */
DTCollation collation; DTCollation collation;
uint8 item_flags; /* Flags on how item should be processed */
// alloc & destruct is done as start of select using sql_alloc // alloc & destruct is done as start of select using sql_alloc
Item(); Item();
...@@ -584,6 +590,11 @@ public: ...@@ -584,6 +590,11 @@ public:
cleanup(); cleanup();
delete this; 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 */ virtual bool is_splocal() { return 0; } /* Needed for error checking */
}; };
......
...@@ -2628,7 +2628,6 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, ...@@ -2628,7 +2628,6 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
uint length=(uint) strlen(name); uint length=(uint) strlen(name);
char name_buff[NAME_LEN+1]; char name_buff[NAME_LEN+1];
if (item->cached_table) if (item->cached_table)
{ {
/* /*
...@@ -2695,10 +2694,13 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, ...@@ -2695,10 +2694,13 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
db= name_buff; db= name_buff;
} }
bool search_global= item->item_flags & MY_ITEM_PREFER_1ST_TABLE;
if (table_name && table_name[0]) if (table_name && table_name[0])
{ /* Qualified field */ { /* Qualified field */
bool found_table=0; bool found_table=0;
for (; tables; tables= tables->next_local) 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 ! */ /* TODO; Ensure that db and tables->db always points to something ! */
if (!my_strcasecmp(table_alias_charset, tables->alias, table_name) && 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, ...@@ -2734,6 +2736,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
return (Field*) 0; return (Field*) 0;
} }
found=find; 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, ...@@ -2758,9 +2762,10 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
return (Field*) not_found_field; return (Field*) not_found_field;
return (Field*) 0; return (Field*) 0;
} }
bool allow_rowid= tables && !tables->next_local; // Only one table 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) if (!tables->table && !tables->ancestor)
{ {
...@@ -2795,7 +2800,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, ...@@ -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); my_error(ER_NON_UNIQ_ERROR, MYF(0), name, thd->where);
return (Field*) 0; return (Field*) 0;
} }
found=field; found= field;
if (table_idx == 0 && item->item_flags & MY_ITEM_PREFER_1ST_TABLE)
break;
} }
} }
if (found) if (found)
......
...@@ -156,9 +156,15 @@ bool foreign_key_prefix(Key *a, Key *b) ...@@ -156,9 +156,15 @@ bool foreign_key_prefix(Key *a, Key *b)
/**************************************************************************** /****************************************************************************
** Thread specific functions ** 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() 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), rand_used(0), time_zone_used(0),
last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(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), in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE),
...@@ -1483,9 +1489,10 @@ Query_arena::Type Query_arena::type() const ...@@ -1483,9 +1489,10 @@ Query_arena::Type Query_arena::type() const
Statement functions Statement functions
*/ */
Statement::Statement(THD *thd) Statement::Statement(enum enum_state state_arg, ulong id_arg,
:Query_arena(&main_mem_root, INITIALIZED), ulong alloc_block_size, ulong prealloc_size)
id(++thd->statement_id_counter), :Query_arena(&main_mem_root, state_arg),
id(id_arg),
set_query_id(1), set_query_id(1),
allow_sum_func(0), allow_sum_func(0),
lex(&main_lex), lex(&main_lex),
...@@ -1494,33 +1501,7 @@ Statement::Statement(THD *thd) ...@@ -1494,33 +1501,7 @@ Statement::Statement(THD *thd)
cursor(0) cursor(0)
{ {
name.str= NULL; name.str= NULL;
init_sql_alloc(&main_mem_root, init_sql_alloc(&main_mem_root, alloc_block_size, prealloc_size);
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);
} }
......
...@@ -817,13 +817,11 @@ public: ...@@ -817,13 +817,11 @@ public:
public: public:
/* /* This constructor is called for backup statements */
This constructor is called when statement is a subobject of THD: Statement() { clear_alloc_root(&main_mem_root); }
some variables are initialized in THD::init due to locking problems
*/
Statement();
Statement(THD *thd); Statement(enum enum_state state_arg, ulong id_arg,
ulong alloc_block_size, ulong prealloc_size);
virtual ~Statement(); virtual ~Statement();
/* Assign execution context (note: not all members) of given stmt to self */ /* Assign execution context (note: not all members) of given stmt to self */
...@@ -965,11 +963,6 @@ public: ...@@ -965,11 +963,6 @@ public:
pthread_mutex_t LOCK_delete; // Locked before thd is deleted pthread_mutex_t LOCK_delete; // Locked before thd is deleted
/* all prepared statements and cursors of this connection */ /* all prepared statements and cursors of this connection */
Statement_map stmt_map; 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(), A pointer to the stack frame of handle_one_connection(),
which is called first in the thread for handling a client which is called first in the thread for handling a client
......
...@@ -1706,6 +1706,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, ...@@ -1706,6 +1706,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
LEX_STRING *name) LEX_STRING *name)
{ {
LEX *lex; LEX *lex;
Statement stmt_backup;
Prepared_statement *stmt= new Prepared_statement(thd); Prepared_statement *stmt= new Prepared_statement(thd);
bool error; bool error;
DBUG_ENTER("mysql_stmt_prepare"); DBUG_ENTER("mysql_stmt_prepare");
...@@ -1739,13 +1740,13 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, ...@@ -1739,13 +1740,13 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
thd->set_n_backup_statement(stmt, &thd->stmt_backup); thd->set_n_backup_statement(stmt, &stmt_backup);
thd->set_n_backup_item_arena(stmt, &thd->stmt_backup); thd->set_n_backup_item_arena(stmt, &stmt_backup);
if (alloc_query(thd, packet, packet_length)) if (alloc_query(thd, packet, packet_length))
{ {
thd->restore_backup_statement(stmt, &thd->stmt_backup); thd->restore_backup_statement(stmt, &stmt_backup);
thd->restore_backup_item_arena(stmt, &thd->stmt_backup); thd->restore_backup_item_arena(stmt, &stmt_backup);
/* Statement map deletes statement on erase */ /* Statement map deletes statement on erase */
thd->stmt_map.erase(stmt); thd->stmt_map.erase(stmt);
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -1770,7 +1771,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, ...@@ -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 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). 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) if (!error)
error= check_prepared_statement(stmt, test(name)); error= check_prepared_statement(stmt, test(name));
...@@ -1786,7 +1787,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, ...@@ -1786,7 +1787,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
lex_end(lex); lex_end(lex);
close_thread_tables(thd); close_thread_tables(thd);
cleanup_stmt_and_thd_after_use(stmt, 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; thd->current_arena= thd;
if (error) if (error)
...@@ -1949,6 +1950,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) ...@@ -1949,6 +1950,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
{ {
ulong stmt_id= uint4korr(packet); ulong stmt_id= uint4korr(packet);
ulong flags= (ulong) ((uchar) packet[4]); ulong flags= (ulong) ((uchar) packet[4]);
Statement stmt_backup;
Cursor *cursor; Cursor *cursor;
/* /*
Query text for binary log, or empty string if the query is not put into 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) ...@@ -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)) if (stmt->param_count && stmt->set_params_data(stmt, &expanded_query))
goto set_params_data_err; goto set_params_data_err;
#endif #endif
thd->stmt_backup.set_statement(thd); thd->set_n_backup_statement(stmt, &stmt_backup);
thd->set_statement(stmt);
thd->current_arena= stmt; thd->current_arena= stmt;
reinit_stmt_before_use(thd, stmt->lex); reinit_stmt_before_use(thd, stmt->lex);
/* From now cursors assume that thd->mem_root is clean */ /* 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) ...@@ -2064,7 +2065,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
reset_stmt_params(stmt); reset_stmt_params(stmt);
} }
thd->set_statement(&thd->stmt_backup); thd->set_statement(&stmt_backup);
thd->current_arena= thd; thd->current_arena= thd;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -2089,6 +2090,7 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name) ...@@ -2089,6 +2090,7 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
binary log. binary log.
*/ */
String expanded_query; String expanded_query;
Statement stmt_backup;
DBUG_ENTER("mysql_sql_stmt_execute"); DBUG_ENTER("mysql_sql_stmt_execute");
DBUG_ASSERT(thd->free_list == NULL); DBUG_ASSERT(thd->free_list == NULL);
...@@ -2110,16 +2112,16 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name) ...@@ -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 */ /* Must go before setting variables, as it clears thd->user_var_events */
mysql_reset_thd_for_next_command(thd); mysql_reset_thd_for_next_command(thd);
thd->set_n_backup_statement(stmt, &thd->stmt_backup); thd->set_n_backup_statement(stmt, &stmt_backup);
thd->set_statement(stmt);
if (stmt->set_params_from_vars(stmt, if (stmt->set_params_from_vars(stmt,
thd->stmt_backup.lex->prepared_stmt_params, stmt_backup.lex->prepared_stmt_params,
&expanded_query)) &expanded_query))
{ {
my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE"); my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
} }
thd->command= COM_STMT_EXECUTE; /* For nice messages in general log */ thd->command= COM_STMT_EXECUTE; /* For nice messages in general log */
execute_stmt(thd, stmt, &expanded_query); execute_stmt(thd, stmt, &expanded_query);
thd->set_statement(&stmt_backup);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2176,7 +2178,6 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt, ...@@ -2176,7 +2178,6 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
close_thread_tables(thd); // to close derived tables close_thread_tables(thd); // to close derived tables
cleanup_stmt_and_thd_after_use(stmt, thd); cleanup_stmt_and_thd_after_use(stmt, thd);
reset_stmt_params(stmt); reset_stmt_params(stmt);
thd->set_statement(&thd->stmt_backup);
thd->current_arena= thd; thd->current_arena= thd;
if (stmt->state == Query_arena::PREPARED) if (stmt->state == Query_arena::PREPARED)
...@@ -2201,6 +2202,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) ...@@ -2201,6 +2202,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
ulong stmt_id= uint4korr(packet); ulong stmt_id= uint4korr(packet);
ulong num_rows= uint4korr(packet+4); ulong num_rows= uint4korr(packet+4);
Prepared_statement *stmt; Prepared_statement *stmt;
Statement stmt_backup;
DBUG_ENTER("mysql_stmt_fetch"); DBUG_ENTER("mysql_stmt_fetch");
statistic_increment(thd->status_var.com_stmt_fetch, &LOCK_status); 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) ...@@ -2214,7 +2216,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
} }
thd->current_arena= stmt; 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)) if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), QUERY_PRIOR); my_pthread_setprio(pthread_self(), QUERY_PRIOR);
...@@ -2226,7 +2228,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) ...@@ -2226,7 +2228,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
if (!(specialflag & SPECIAL_NO_PRIOR)) if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_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; thd->current_arena= thd;
if (!stmt->cursor->is_open()) if (!stmt->cursor->is_open())
...@@ -2386,7 +2388,9 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) ...@@ -2386,7 +2388,9 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
Prepared_statement::Prepared_statement(THD *thd_arg) 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), thd(thd_arg),
param_array(0), param_array(0),
param_count(0), param_count(0),
......
...@@ -1820,6 +1820,7 @@ Cursor::fetch(ulong num_rows) ...@@ -1820,6 +1820,7 @@ Cursor::fetch(ulong num_rows)
THD *thd= join->thd; THD *thd= join->thd;
JOIN_TAB *join_tab= join->join_tab + join->const_tables; JOIN_TAB *join_tab= join->join_tab + join->const_tables;
enum_nested_loop_state error= NESTED_LOOP_OK; enum_nested_loop_state error= NESTED_LOOP_OK;
Query_arena backup_arena;
DBUG_ENTER("Cursor::fetch"); DBUG_ENTER("Cursor::fetch");
DBUG_PRINT("enter",("rows: %lu", num_rows)); DBUG_PRINT("enter",("rows: %lu", num_rows));
...@@ -1831,7 +1832,7 @@ Cursor::fetch(ulong num_rows) ...@@ -1831,7 +1832,7 @@ Cursor::fetch(ulong num_rows)
thd->lock= lock; thd->lock= lock;
thd->query_id= query_id; thd->query_id= query_id;
/* save references to memory, allocated during fetch */ /* 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; join->fetch_limit+= num_rows;
...@@ -1847,7 +1848,7 @@ Cursor::fetch(ulong num_rows) ...@@ -1847,7 +1848,7 @@ Cursor::fetch(ulong num_rows)
ha_release_temporary_latches(thd); ha_release_temporary_latches(thd);
#endif #endif
thd->restore_backup_item_arena(this, &thd->stmt_backup); thd->restore_backup_item_arena(this, &backup_arena);
DBUG_ASSERT(thd->free_list == 0); DBUG_ASSERT(thd->free_list == 0);
reset_thd(thd); reset_thd(thd);
......
...@@ -6120,9 +6120,24 @@ insert_update_elem: ...@@ -6120,9 +6120,24 @@ insert_update_elem:
simple_ident_nospvar equal expr_or_default simple_ident_nospvar equal expr_or_default
{ {
LEX *lex= Lex; LEX *lex= Lex;
uint8 tmp= MY_ITEM_PREFER_1ST_TABLE;
if (lex->update_list.push_back($1) || if (lex->update_list.push_back($1) ||
lex->value_list.push_back($3)) lex->value_list.push_back($3))
YYABORT; 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: opt_low_priority:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment