mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into neptunus.(none):/home/msvensson/mysql/mysql-5.0 sql/sql_base.cc: Auto merged
This commit is contained in:
@ -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
|
||||||
|
@ -123,3 +123,14 @@ key1a = 2 and key1b is null and key3a = 2 and key3b is null;
|
|||||||
count(*)
|
count(*)
|
||||||
4
|
4
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
create table t1 (
|
||||||
|
id1 int,
|
||||||
|
id2 date ,
|
||||||
|
index idx2 (id1,id2),
|
||||||
|
index idx1 (id2)
|
||||||
|
) engine = innodb;
|
||||||
|
insert into t1 values(1,'20040101'), (2,'20040102');
|
||||||
|
select * from t1 where id1 = 1 and id2= '20040101';
|
||||||
|
id1 id2
|
||||||
|
1 2004-01-01
|
||||||
|
drop table t1;
|
||||||
|
@ -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;
|
||||||
|
@ -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));
|
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;
|
||||||
|
@ -120,3 +120,14 @@ select count(*) from t1 where
|
|||||||
|
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
|
||||||
|
# Test for BUG#8441
|
||||||
|
create table t1 (
|
||||||
|
id1 int,
|
||||||
|
id2 date ,
|
||||||
|
index idx2 (id1,id2),
|
||||||
|
index idx1 (id2)
|
||||||
|
) engine = innodb;
|
||||||
|
insert into t1 values(1,'20040101'), (2,'20040102');
|
||||||
|
select * from t1 where id1 = 1 and id2= '20040101';
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
--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));
|
||||||
|
@ -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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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():
|
|||||||
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):
|
|||||||
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;
|
||||||
|
11
sql/item.h
11
sql/item.h
@ -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:
|
|||||||
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:
|
|||||||
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 */
|
||||||
};
|
};
|
||||||
|
@ -2593,12 +2593,12 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
|
|||||||
{
|
{
|
||||||
tuple_arg= scan->sel_arg;
|
tuple_arg= scan->sel_arg;
|
||||||
/* Here we use the length of the first key part */
|
/* Here we use the length of the first key part */
|
||||||
tuple_arg->store_min(key_part->length, &key_ptr, 0);
|
tuple_arg->store_min(key_part->store_length, &key_ptr, 0);
|
||||||
}
|
}
|
||||||
while (tuple_arg->next_key_part != sel_arg)
|
while (tuple_arg->next_key_part != sel_arg)
|
||||||
{
|
{
|
||||||
tuple_arg= tuple_arg->next_key_part;
|
tuple_arg= tuple_arg->next_key_part;
|
||||||
tuple_arg->store_min(key_part[tuple_arg->part].length, &key_ptr, 0);
|
tuple_arg->store_min(key_part[tuple_arg->part].store_length, &key_ptr, 0);
|
||||||
}
|
}
|
||||||
min_range.length= max_range.length= ((char*) key_ptr - (char*) key_val);
|
min_range.length= max_range.length= ((char*) key_ptr - (char*) key_val);
|
||||||
records= (info->param->table->file->
|
records= (info->param->table->file->
|
||||||
|
@ -2636,7 +2636,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)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -2703,10 +2702,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) &&
|
||||||
@ -2742,6 +2744,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2766,9 +2770,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)
|
||||||
{
|
{
|
||||||
@ -2803,7 +2808,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)
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** 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
|
|||||||
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)
|
|||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -809,13 +809,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 */
|
||||||
@ -957,11 +955,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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
/* 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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
|
|
||||||
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),
|
||||||
|
@ -1824,6 +1824,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));
|
||||||
|
|
||||||
@ -1835,7 +1836,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;
|
||||||
|
|
||||||
@ -1851,7 +1852,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:
|
|||||||
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:
|
||||||
|
Reference in New Issue
Block a user