Commit c5dc4ab3 authored by unknown's avatar unknown

Merge work:/my/mysql-4.0 into mashka.mysql.fi:/home/my/mysql-4.0


sql/ha_innodb.cc:
  Auto merged
sql/ha_myisam.cc:
  Auto merged
sql/sql_delete.cc:
  Auto merged
sql/sql_update.cc:
  Auto merged
parents 2c349012 bd1c2d65
...@@ -497,3 +497,6 @@ vio/test-ssl ...@@ -497,3 +497,6 @@ vio/test-ssl
vio/test-sslclient vio/test-sslclient
vio/test-sslserver vio/test-sslserver
vio/viotest-ssl vio/viotest-ssl
autom4te.cache/*
bdb/dist/autom4te.cache/*
innobase/autom4te.cache/*
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
#ifndef _my_alloc_h #ifndef _my_alloc_h
#define _my_alloc_h #define _my_alloc_h
#define MAX_BLOCK_USAGE_BEFORE_DROP 10 #define ALLOC_MAX_BLOCK_TO_DROP 4096
#define ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP 10
typedef struct st_used_mem typedef struct st_used_mem
{ /* struct for once_alloc (block) */ { /* struct for once_alloc (block) */
......
...@@ -1524,6 +1524,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -1524,6 +1524,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
#endif #endif
init_sigpipe_variables init_sigpipe_variables
DBUG_ENTER("mysql_real_connect"); DBUG_ENTER("mysql_real_connect");
LINT_INIT(host_info);
DBUG_PRINT("enter",("host: %s db: %s user: %s", DBUG_PRINT("enter",("host: %s db: %s user: %s",
host ? host : "(Null)", host ? host : "(Null)",
......
...@@ -66,7 +66,9 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -66,7 +66,9 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
page+keyinfo->block_length > info->state->key_file_length || page+keyinfo->block_length > info->state->key_file_length ||
(page & (MI_MIN_KEY_BLOCK_LENGTH-1))) (page & (MI_MIN_KEY_BLOCK_LENGTH-1)))
{ {
DBUG_PRINT("error",("Trying to write inside key status region: %lu", DBUG_PRINT("error",("Trying to write inside key status region: key_start: %lu length: %lu page: %lu",
(long) info->s->base.keystart,
(long) info->state->key_file_length,
(long) page)); (long) page));
my_errno=EINVAL; my_errno=EINVAL;
return(-1); return(-1);
......
...@@ -150,4 +150,29 @@ n n ...@@ -150,4 +150,29 @@ n n
delete t1,t2 from t2 left outer join t1 using (n); delete t1,t2 from t2 left outer join t1 using (n);
select * from t2 left outer join t1 using (n); select * from t2 left outer join t1 using (n);
n n n n
drop table if exists t1,t2 ; drop table t1,t2 ;
create table t1 (n int(10) not null primary key, d int(10));
create table t2 (n int(10) not null primary key, d int(10));
insert into t1 values(1,1);
insert into t2 values(1,10),(2,20);
LOCK TABLES t1 write, t2 read;
DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n;
Table 't2' was locked with a READ lock and can't be updated
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
Table 't2' was locked with a READ lock and can't be updated
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
Table 't2' was locked with a READ lock and can't be updated
unlock tables;
LOCK TABLES t1 write, t2 write;
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
select * from t1;
n d
1 10
DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n;
select * from t1;
n d
select * from t2;
n d
2 20
unlock tables;
drop table t1,t2;
slave stop;
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;
slave start;
drop table if exists foo;
create table foo (n int);
insert into foo values(4);
drop table if exists foo;
create table foo (s char(20));
load data infile '../../std_data/words.dat' into table foo;
insert into foo values('five');
drop table if exists bar;
create table bar (m int);
insert into bar values(15);
select foo.n,bar.m from foo,bar;
n m
4 15
drop table if exists bar,foo;
slave stop;
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;
slave start;
drop table if exists t11;
drop table if exists t11;
create table t2 (n int);
insert into t2 values(4);
create table t2 (s char(20));
load data infile '../../std_data/words.dat' into table t2;
insert into t2 values('five');
create table t1 (m int);
insert into t1 values(15),(16),(17);
update t1 set m=20 where m=16;
delete from t1 where m=17;
create table t11 select * from t1;
select * from t1;
m
15
20
select * from t2;
n
4
select * from t11;
Table 'test.t11' doesn't exist
drop table if exists t1,t2,t3,t11;
drop table if exists t1, t2, t3, t4;
drop table if exists t1, t2, t3, t4;
slave start; slave start;
Could not initialize master info structure, check permisions on master.info Could not initialize master info structure, check permisions on master.info
slave start; slave start;
...@@ -8,7 +10,6 @@ reset slave; ...@@ -8,7 +10,6 @@ reset slave;
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root'; change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
reset master; reset master;
slave start; slave start;
drop table if exists t1, t2, t3, t4;
create temporary table temp_table (a char(80) not null); create temporary table temp_table (a char(80) not null);
insert into temp_table values ("testing temporary tables"); insert into temp_table values ("testing temporary tables");
create table t1 (s text); create table t1 (s text);
......
...@@ -147,4 +147,30 @@ insert into t2 values (1),(2),(4),(8),(16),(32); ...@@ -147,4 +147,30 @@ insert into t2 values (1),(2),(4),(8),(16),(32);
select * from t2 left outer join t1 using (n); select * from t2 left outer join t1 using (n);
delete t1,t2 from t2 left outer join t1 using (n); delete t1,t2 from t2 left outer join t1 using (n);
select * from t2 left outer join t1 using (n); select * from t2 left outer join t1 using (n);
drop table if exists t1,t2 ; drop table t1,t2 ;
#
# Test with locking
#
create table t1 (n int(10) not null primary key, d int(10));
create table t2 (n int(10) not null primary key, d int(10));
insert into t1 values(1,1);
insert into t2 values(1,10),(2,20);
LOCK TABLES t1 write, t2 read;
--error 1099
DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n;
--error 1099
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
# The following should be fixed to not give an error
--error 1099
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
unlock tables;
LOCK TABLES t1 write, t2 write;
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
select * from t1;
DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n;
select * from t1;
select * from t2;
unlock tables;
drop table t1,t2;
--replicate-do-table=test.bar
#this one assumes we are ignoring updates on table foo, but doing
#the ones on bar
source include/master-slave.inc;
connection slave;
drop table if exists foo;
create table foo (n int);
insert into foo values(4);
connection master;
drop table if exists foo;
create table foo (s char(20));
load data infile '../../std_data/words.dat' into table foo;
insert into foo values('five');
drop table if exists bar;
create table bar (m int);
insert into bar values(15);
save_master_pos;
connection slave;
sync_with_master;
select foo.n,bar.m from foo,bar;
connection master;
drop table if exists bar,foo;
save_master_pos;
connection slave;
sync_with_master;
--replicate-do-table=test.t1
# This test assumes we are ignoring updates on table t2, but doing
# updates on t1
source include/master-slave.inc;
drop table if exists t11;
connection slave;
drop table if exists t11;
create table t2 (n int);
insert into t2 values(4);
connection master;
create table t2 (s char(20));
load data infile '../../std_data/words.dat' into table t2;
insert into t2 values('five');
create table t1 (m int);
insert into t1 values(15),(16),(17);
update t1 set m=20 where m=16;
delete from t1 where m=17;
create table t11 select * from t1;
save_master_pos;
connection slave;
sync_with_master;
select * from t1;
select * from t2;
--error 1146
select * from t11;
connection master;
drop table if exists t1,t2,t3,t11;
save_master_pos;
connection slave;
sync_with_master;
...@@ -10,10 +10,12 @@ ...@@ -10,10 +10,12 @@
# - Test creating a duplicate key error and recover from it # - Test creating a duplicate key error and recover from it
# #
connect (master,localhost,root,,test,0,master.sock); connect (master,localhost,root,,test,0,master.sock);
drop table if exists t1, t2, t3, t4;
connect (slave,localhost,root,,test,0,slave.sock); connect (slave,localhost,root,,test,0,slave.sock);
system cat /dev/null > var/slave-data/master.info; system cat /dev/null > var/slave-data/master.info;
system chmod 000 var/slave-data/master.info; system chmod 000 var/slave-data/master.info;
connection slave; connection slave;
drop table if exists t1, t2, t3, t4;
--error 1201 --error 1201
slave start; slave start;
system chmod 600 var/slave-data/master.info; system chmod 600 var/slave-data/master.info;
...@@ -31,8 +33,6 @@ connection slave; ...@@ -31,8 +33,6 @@ connection slave;
slave start; slave start;
connection master; connection master;
drop table if exists t1, t2, t3, t4;
# #
# Test FLUSH LOGS # Test FLUSH LOGS
# #
......
...@@ -29,7 +29,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size, ...@@ -29,7 +29,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
mem_root->min_malloc= 32; mem_root->min_malloc= 32;
mem_root->block_size= block_size-MALLOC_OVERHEAD-sizeof(USED_MEM)-8; mem_root->block_size= block_size-MALLOC_OVERHEAD-sizeof(USED_MEM)-8;
mem_root->error_handler= 0; mem_root->error_handler= 0;
mem_root->block_num= 0; mem_root->block_num= 4; /* We shift this with >>2 */
mem_root->first_block_usage= 0; mem_root->first_block_usage= 0;
#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG)) #if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
if (pre_alloc_size) if (pre_alloc_size)
...@@ -69,10 +69,11 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) ...@@ -69,10 +69,11 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
reg2 USED_MEM **prev; reg2 USED_MEM **prev;
Size= ALIGN_SIZE(Size); Size= ALIGN_SIZE(Size);
if ( (*(prev= &mem_root->free)) != NULL ) if ((*(prev= &mem_root->free)) != NULL)
{ {
if( (*prev)->left < Size && if ((*prev)->left < Size &&
mem_root->first_block_usage++ >= MAX_BLOCK_USAGE_BEFORE_DROP ) mem_root->first_block_usage++ >= ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP &&
(*prev)->left < ALLOC_MAX_BLOCK_TO_DROP)
{ {
next= *prev; next= *prev;
*prev= next->next; /* Remove block from list */ *prev= next->next; /* Remove block from list */
...@@ -85,7 +86,7 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) ...@@ -85,7 +86,7 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
} }
if (! next) if (! next)
{ /* Time to alloc new block */ { /* Time to alloc new block */
block_size= mem_root->block_size*((mem_root->block_num>>2)+1); block_size= mem_root->block_size * (mem_root->block_num >> 2);
get_size= Size+ALIGN_SIZE(sizeof(USED_MEM)); get_size= Size+ALIGN_SIZE(sizeof(USED_MEM));
get_size= max(get_size, block_size); get_size= max(get_size, block_size);
...@@ -177,10 +178,8 @@ void free_root(MEM_ROOT *root, myf MyFlags) ...@@ -177,10 +178,8 @@ void free_root(MEM_ROOT *root, myf MyFlags)
root->free=root->pre_alloc; root->free=root->pre_alloc;
root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(USED_MEM)); root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(USED_MEM));
root->free->next=0; root->free->next=0;
root->block_num= 1;
} }
else root->block_num= 4;
root->block_num= 0;
root->first_block_usage= 0; root->first_block_usage= 0;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -3804,6 +3804,7 @@ ha_innobase::external_lock( ...@@ -3804,6 +3804,7 @@ ha_innobase::external_lock(
trx_t* trx; trx_t* trx;
DBUG_ENTER("ha_innobase::external_lock"); DBUG_ENTER("ha_innobase::external_lock");
DBUG_PRINT("enter",("lock_type: %d", lock_type));
update_thd(thd); update_thd(thd);
......
...@@ -908,7 +908,7 @@ void ha_myisam::info(uint flag) ...@@ -908,7 +908,7 @@ void ha_myisam::info(uint flag)
if (table->key_parts) if (table->key_parts)
memcpy((char*) table->key_info[0].rec_per_key, memcpy((char*) table->key_info[0].rec_per_key,
(char*) info.rec_per_key, (char*) info.rec_per_key,
sizeof(ulong)*table->key_parts); sizeof(table->key_info[0].rec_per_key)*table->key_parts);
raid_type=info.raid_type; raid_type=info.raid_type;
raid_chunks=info.raid_chunks; raid_chunks=info.raid_chunks;
raid_chunksize=info.raid_chunksize; raid_chunksize=info.raid_chunksize;
......
...@@ -255,6 +255,7 @@ static SYMBOL symbols[] = { ...@@ -255,6 +255,7 @@ static SYMBOL symbols[] = {
{ "NOT", SYM(NOT),0,0}, { "NOT", SYM(NOT),0,0},
{ "NULL", SYM(NULL_SYM),0,0}, { "NULL", SYM(NULL_SYM),0,0},
{ "NUMERIC", SYM(NUMERIC_SYM),0,0}, { "NUMERIC", SYM(NUMERIC_SYM),0,0},
{ "OFFSET", SYM(OFFSET_SYM),0,0},
{ "ON", SYM(ON),0,0}, { "ON", SYM(ON),0,0},
{ "OPEN", SYM(OPEN_SYM),0,0}, { "OPEN", SYM(OPEN_SYM),0,0},
{ "OPTIMIZE", SYM(OPTIMIZE),0,0}, { "OPTIMIZE", SYM(OPTIMIZE),0,0},
......
...@@ -167,6 +167,7 @@ static int lock_external(THD *thd, TABLE **tables, uint count) ...@@ -167,6 +167,7 @@ static int lock_external(THD *thd, TABLE **tables, uint count)
for (i=1 ; i <= count ; i++, tables++) for (i=1 ; i <= count ; i++, tables++)
{ {
DBUG_ASSERT((*tables)->reginfo.lock_type >= TL_READ);
lock_type=F_WRLCK; /* Lock exclusive */ lock_type=F_WRLCK; /* Lock exclusive */
if ((*tables)->db_stat & HA_READ_ONLY || if ((*tables)->db_stat & HA_READ_ONLY ||
((*tables)->reginfo.lock_type >= TL_READ && ((*tables)->reginfo.lock_type >= TL_READ &&
......
...@@ -413,14 +413,12 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ...@@ -413,14 +413,12 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds, List<Item> &values,COND *conds,
ORDER *order, ha_rows limit, ORDER *order, ha_rows limit,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates);
thr_lock_type lock_type);
int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields, int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
List<List_item> &values, enum_duplicates flag, List<List_item> &values, enum_duplicates flag);
thr_lock_type lock_type);
void kill_delayed_threads(void); void kill_delayed_threads(void);
int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order, int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order,
ha_rows rows, thr_lock_type lock_type, ulong options); ha_rows rows, ulong options);
int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0); int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0);
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update); TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias, TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias,
...@@ -496,6 +494,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table,LEX_STRING *alias, ...@@ -496,6 +494,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table,LEX_STRING *alias,
thr_lock_type flags=TL_UNLOCK, thr_lock_type flags=TL_UNLOCK,
List<String> *use_index=0, List<String> *use_index=0,
List<String> *ignore_index=0); List<String> *ignore_index=0);
void set_lock_for_tables(thr_lock_type lock_type);
void add_join_on(TABLE_LIST *b,Item *expr); void add_join_on(TABLE_LIST *b,Item *expr);
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b); void add_join_natural(TABLE_LIST *a,TABLE_LIST *b);
bool add_proc_to_list(Item *item); bool add_proc_to_list(Item *item);
...@@ -586,6 +585,8 @@ bool open_log(MYSQL_LOG *log, const char *hostname, ...@@ -586,6 +585,8 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
const char *index_file_name, const char *index_file_name,
enum_log_type type, bool read_append = 0, enum_log_type type, bool read_append = 0,
bool no_auto_events = 0); bool no_auto_events = 0);
/* mysqld.cc */
void clear_error_message(THD *thd);
/* /*
External variables External variables
......
...@@ -1663,6 +1663,17 @@ extern "C" int my_message_sql(uint error, const char *str, ...@@ -1663,6 +1663,17 @@ extern "C" int my_message_sql(uint error, const char *str,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/*
Forget last error message (if we got one)
*/
void clear_error_message(THD *thd)
{
thd->net.last_error[0]= 0;
}
#ifdef __WIN__ #ifdef __WIN__
struct utsname struct utsname
......
...@@ -1403,6 +1403,61 @@ int open_tables(THD *thd,TABLE_LIST *start) ...@@ -1403,6 +1403,61 @@ int open_tables(THD *thd,TABLE_LIST *start)
} }
/*
Check that lock is ok for tables; Call start stmt if ok
SYNOPSIS
check_lock_and_start_stmt()
thd Thread handle
table_list Table to check
lock_type Lock used for table
RETURN VALUES
0 ok
1 error
*/
static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
thr_lock_type lock_type)
{
int error;
DBUG_ENTER("check_lock_and_start_stmt");
if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ &&
(int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ)
{
my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,
ER(ER_TABLE_NOT_LOCKED_FOR_WRITE),
MYF(0),table->table_name);
DBUG_RETURN(1);
}
if ((error=table->file->start_stmt(thd)))
{
table->file->print_error(error,MYF(0));
DBUG_RETURN(1);
}
DBUG_RETURN(0);
}
/*
Open and lock one table
SYNOPSIS
open_ltable()
thd Thread handler
table_list Table to open is first table in this list
lock_type Lock to use for open
RETURN VALUES
table Opened table
0 Error
If ok, the following are also set:
table_list->lock_type lock_type
table_list->table table
*/
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
{ {
TABLE *table; TABLE *table;
...@@ -1415,8 +1470,6 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) ...@@ -1415,8 +1470,6 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
&refresh)) && refresh) ; &refresh)) && refresh) ;
if (table) if (table)
{ {
int error;
#if defined( __WIN__) || defined(OS2) #if defined( __WIN__) || defined(OS2)
/* Win32 can't drop a file that is open */ /* Win32 can't drop a file that is open */
if (lock_type == TL_WRITE_ALLOW_READ) if (lock_type == TL_WRITE_ALLOW_READ)
...@@ -1424,39 +1477,29 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) ...@@ -1424,39 +1477,29 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
lock_type= TL_WRITE; lock_type= TL_WRITE;
} }
#endif /* __WIN__ || OS2 */ #endif /* __WIN__ || OS2 */
table_list->lock_type= lock_type;
table_list->table=table; table_list->table= table;
table->grant= table_list->grant; table->grant= table_list->grant;
if (thd->locked_tables) if (thd->locked_tables)
{ {
thd->proc_info=0; if (check_lock_and_start_stmt(thd, table, lock_type))
if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ && table= 0;
(int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ) }
{ else
my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, {
ER(ER_TABLE_NOT_LOCKED_FOR_WRITE), if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
MYF(0),table_list->alias); if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
table=0; table= 0;
}
else if ((error=table->file->start_stmt(thd)))
{
table->file->print_error(error,MYF(0));
table=0;
}
thd->proc_info=0;
DBUG_RETURN(table);
} }
if ((table->reginfo.lock_type=lock_type) != TL_UNLOCK)
if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
DBUG_RETURN(0);
} }
thd->proc_info=0; thd->proc_info=0;
DBUG_RETURN(table); DBUG_RETURN(table);
} }
/* /*
** Open all tables in list and locks them for read. Open all tables in list and locks them for read.
** The lock will automaticly be freed by the close_thread_tables The lock will automaticly be freed by close_thread_tables()
*/ */
int open_and_lock_tables(THD *thd,TABLE_LIST *tables) int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
...@@ -1466,10 +1509,27 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables) ...@@ -1466,10 +1509,27 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
return 0; return 0;
} }
/*
Lock all tables in list
SYNOPSIS
lock_tables()
thd Thread handler
tables Tables to lock
RETURN VALUES
0 ok
-1 Error
*/
int lock_tables(THD *thd,TABLE_LIST *tables) int lock_tables(THD *thd,TABLE_LIST *tables)
{ {
TABLE_LIST *table; TABLE_LIST *table;
if (tables && !thd->locked_tables) if (!tables)
return 0;
if (!thd->locked_tables)
{ {
uint count=0; uint count=0;
for (table = tables ; table ; table=table->next) for (table = tables ; table ; table=table->next)
...@@ -1486,10 +1546,9 @@ int lock_tables(THD *thd,TABLE_LIST *tables) ...@@ -1486,10 +1546,9 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
{ {
for (table = tables ; table ; table=table->next) for (table = tables ; table ; table=table->next)
{ {
int error; if (check_lock_and_start_stmt(thd, table->table, table->lock_type))
if ((error=table->table->file->start_stmt(thd)))
{ {
table->table->file->print_error(error,MYF(0)); ha_rollback_stmt(thd);
return -1; return -1;
} }
} }
...@@ -1497,10 +1556,11 @@ int lock_tables(THD *thd,TABLE_LIST *tables) ...@@ -1497,10 +1556,11 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
return 0; return 0;
} }
/* /*
** Open a single table without table caching and don't set it in open_list Open a single table without table caching and don't set it in open_list
** Used by alter_table to open a temporary table and when creating Used by alter_table to open a temporary table and when creating
** a temporary table with CREATE TEMPORARY ... a temporary table with CREATE TEMPORARY ...
*/ */
TABLE *open_temporary_table(THD *thd, const char *path, const char *db, TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
......
...@@ -87,9 +87,6 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), ...@@ -87,9 +87,6 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
host_or_ip="unknown ip"; host_or_ip="unknown ip";
locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password= locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password=
query_start_used=safe_to_cache_query=0; query_start_used=safe_to_cache_query=0;
pthread_mutex_lock(&LOCK_global_system_variables);
variables= global_system_variables;
pthread_mutex_unlock(&LOCK_global_system_variables);
db_length=query_length=col_access=0; db_length=query_length=col_access=0;
query_error=0; query_error=0;
next_insert_id=last_insert_id=0; next_insert_id=last_insert_id=0;
...@@ -129,19 +126,12 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), ...@@ -129,19 +126,12 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
server_id = ::server_id; server_id = ::server_id;
slave_net = 0; slave_net = 0;
log_pos = 0; log_pos = 0;
server_status= SERVER_STATUS_AUTOCOMMIT;
update_lock_default= (variables.low_priority_updates ?
TL_WRITE_LOW_PRIORITY :
TL_WRITE);
options= thd_startup_options;
sql_mode=(uint) opt_sql_mode;
open_options=ha_open_options;
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
command=COM_CONNECT; command=COM_CONNECT;
set_query_id=1; set_query_id=1;
db_access=NO_ACCESS; db_access=NO_ACCESS;
version=refresh_version; // For boot version=refresh_version; // For boot
init();
/* Initialize sub structures */ /* Initialize sub structures */
bzero((char*) &mem_root,sizeof(mem_root)); bzero((char*) &mem_root,sizeof(mem_root));
bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root)); bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root));
...@@ -174,6 +164,48 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), ...@@ -174,6 +164,48 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
} }
} }
/*
Init common variables that has to be reset on start and on change_user
*/
void THD::init(void)
{
server_status= SERVER_STATUS_AUTOCOMMIT;
update_lock_default= (variables.low_priority_updates ?
TL_WRITE_LOW_PRIORITY :
TL_WRITE);
options= thd_startup_options;
sql_mode=(uint) opt_sql_mode;
open_options=ha_open_options;
pthread_mutex_lock(&LOCK_global_system_variables);
variables= global_system_variables;
pthread_mutex_unlock(&LOCK_global_system_variables);
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
}
/*
Do what's needed when one invokes change user
SYNOPSIS
change_user()
IMPLEMENTATION
Reset all resources that are connection specific
*/
void THD::change_user(void)
{
cleanup();
cleanup_done=0;
init();
hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
(hash_free_key) free_user_var,0);
}
/* Do operations that may take a long time */ /* Do operations that may take a long time */
void THD::cleanup(void) void THD::cleanup(void)
...@@ -191,17 +223,21 @@ void THD::cleanup(void) ...@@ -191,17 +223,21 @@ void THD::cleanup(void)
close_thread_tables(this); close_thread_tables(this);
} }
close_temporary_tables(this); close_temporary_tables(this);
#ifdef USING_TRANSACTIONS hash_free(&user_vars);
if (opt_using_transactions) if (global_read_lock)
unlock_global_read_lock(this);
if (ull)
{ {
close_cached_file(&transaction.trans_log); pthread_mutex_lock(&LOCK_user_locks);
ha_close_connection(this); item_user_lock_release(ull);
pthread_mutex_unlock(&LOCK_user_locks);
ull= 0;
} }
#endif
cleanup_done=1; cleanup_done=1;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
THD::~THD() THD::~THD()
{ {
THD_CHECK_SENTRY(this); THD_CHECK_SENTRY(this);
...@@ -218,15 +254,13 @@ THD::~THD() ...@@ -218,15 +254,13 @@ THD::~THD()
} }
if (!cleanup_done) if (!cleanup_done)
cleanup(); cleanup();
if (global_read_lock) #ifdef USING_TRANSACTIONS
unlock_global_read_lock(this); if (opt_using_transactions)
if (ull)
{ {
pthread_mutex_lock(&LOCK_user_locks); close_cached_file(&transaction.trans_log);
item_user_lock_release(ull); ha_close_connection(this);
pthread_mutex_unlock(&LOCK_user_locks);
} }
hash_free(&user_vars); #endif
DBUG_PRINT("info", ("freeing host")); DBUG_PRINT("info", ("freeing host"));
if (host != localhost) // If not pointer to constant if (host != localhost) // If not pointer to constant
......
...@@ -461,6 +461,8 @@ class THD :public ilink { ...@@ -461,6 +461,8 @@ class THD :public ilink {
THD(); THD();
~THD(); ~THD();
void init(void);
void change_user(void);
void cleanup(void); void cleanup(void);
bool store_globals(); bool store_globals();
#ifdef SIGNAL_WITH_VIO_CLOSE #ifdef SIGNAL_WITH_VIO_CLOSE
...@@ -804,11 +806,9 @@ class Unique :public Sql_alloc ...@@ -804,11 +806,9 @@ class Unique :public Sql_alloc
ha_rows deleted; ha_rows deleted;
uint num_of_tables; uint num_of_tables;
int error; int error;
thr_lock_type lock_option;
bool do_delete, transactional_tables, log_delayed, normal_tables; bool do_delete, transactional_tables, log_delayed, normal_tables;
public: public:
multi_delete(THD *thd, TABLE_LIST *dt, thr_lock_type lock_option_arg, multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
uint num_of_tables);
~multi_delete(); ~multi_delete();
int prepare(List<Item> &list); int prepare(List<Item> &list);
bool send_fields(List<Item> &list, bool send_fields(List<Item> &list,
...@@ -829,7 +829,6 @@ class Unique :public Sql_alloc ...@@ -829,7 +829,6 @@ class Unique :public Sql_alloc
ha_rows updated, found; ha_rows updated, found;
List<Item> fields; List<Item> fields;
List <Item> **fields_by_tables; List <Item> **fields_by_tables;
thr_lock_type lock_option;
enum enum_duplicates dupl; enum enum_duplicates dupl;
uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence; uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence;
int error; int error;
...@@ -837,7 +836,7 @@ class Unique :public Sql_alloc ...@@ -837,7 +836,7 @@ class Unique :public Sql_alloc
public: public:
multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs, multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
thr_lock_type lock_option_arg, uint num); uint num);
~multi_update(); ~multi_update();
int prepare(List<Item> &list); int prepare(List<Item> &list);
bool send_fields(List<Item> &list, bool send_fields(List<Item> &list,
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "sql_select.h" #include "sql_select.h"
int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
ha_rows limit, thr_lock_type lock_type, ulong options) ha_rows limit, ulong options)
{ {
int error; int error;
TABLE *table; TABLE *table;
...@@ -39,15 +39,13 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -39,15 +39,13 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
ha_rows deleted; ha_rows deleted;
DBUG_ENTER("mysql_delete"); DBUG_ENTER("mysql_delete");
if (!table_list->db)
table_list->db=thd->db;
if (((safe_update=thd->options & OPTION_SAFE_UPDATES)) && !conds) if (((safe_update=thd->options & OPTION_SAFE_UPDATES)) && !conds)
{ {
send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (!(table = open_ltable(thd,table_list, lock_type))) if (!(table = open_ltable(thd, table_list, table_list->lock_type)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init"; thd->proc_info="init";
...@@ -176,9 +174,19 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -176,9 +174,19 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
if (!log_delayed) if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
} }
if (transactional_table && ha_autocommit_or_rollback(thd,error >= 0)) if (transactional_table)
error=1; {
if (deleted) if (ha_autocommit_or_rollback(thd,error >= 0))
error=1;
}
/*
Only invalidate the query cache if something changed or if we
didn't commit the transacion (query cache is automaticly
invalidated on commit)
*/
if (deleted &&
(!transactional_table ||
thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{ {
query_cache_invalidate3(thd, table_list, 1); query_cache_invalidate3(thd, table_list, 1);
} }
...@@ -211,10 +219,9 @@ extern "C" int refposcmp2(void* arg, const void *a,const void *b) ...@@ -211,10 +219,9 @@ extern "C" int refposcmp2(void* arg, const void *a,const void *b)
} }
multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
thr_lock_type lock_option_arg,
uint num_of_tables_arg) uint num_of_tables_arg)
: delete_tables (dt), thd(thd_arg), deleted(0), : delete_tables (dt), thd(thd_arg), deleted(0),
num_of_tables(num_of_tables_arg), error(0), lock_option(lock_option_arg), num_of_tables(num_of_tables_arg), error(0),
do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0) do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0)
{ {
tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1)); tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1));
...@@ -553,8 +560,9 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) ...@@ -553,8 +560,9 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
if (!ha_supports_generate(table_type)) if (!ha_supports_generate(table_type))
{ {
/* Probably InnoDB table */ /* Probably InnoDB table */
DBUG_RETURN(mysql_delete(thd,table_list, (COND*) 0, (ORDER*) 0, table_list->lock_type= TL_WRITE;
HA_POS_ERROR, TL_WRITE, 0)); DBUG_RETURN(mysql_delete(thd, table_list, (COND*) 0, (ORDER*) 0,
HA_POS_ERROR, 0));
} }
if (lock_and_wait_for_table_name(thd, table_list)) if (lock_and_wait_for_table_name(thd, table_list))
DBUG_RETURN(-1); DBUG_RETURN(-1);
......
...@@ -98,8 +98,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields, ...@@ -98,8 +98,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
List<List_item> &values_list,enum_duplicates duplic, List<List_item> &values_list,enum_duplicates duplic)
thr_lock_type lock_type)
{ {
int error; int error;
bool log_on= ((thd->options & OPTION_UPDATE_LOG) || bool log_on= ((thd->options & OPTION_UPDATE_LOG) ||
...@@ -114,6 +113,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -114,6 +113,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
List_iterator_fast<List_item> its(values_list); List_iterator_fast<List_item> its(values_list);
List_item *values; List_item *values;
char *query=thd->query; char *query=thd->query;
thr_lock_type lock_type = table_list->lock_type;
DBUG_ENTER("mysql_insert"); DBUG_ENTER("mysql_insert");
/* /*
...@@ -200,8 +200,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -200,8 +200,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
{ {
table->file->extra_opt(HA_EXTRA_WRITE_CACHE, table->file->extra_opt(HA_EXTRA_WRITE_CACHE,
thd->variables.read_buff_size); thd->variables.read_buff_size);
table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN, if (thd->variables.bulk_insert_buff_size)
thd->variables.bulk_insert_buff_size); table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
thd->variables.bulk_insert_buff_size);
table->bulk_insert= 1; table->bulk_insert= 1;
} }
...@@ -266,10 +267,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -266,10 +267,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
info.copied=values_list.elements; info.copied=values_list.elements;
end_delayed_insert(thd); end_delayed_insert(thd);
} }
if (info.copied || info.deleted) query_cache_invalidate3(thd, table_list, 1);
{
query_cache_invalidate3(thd, table_list, 1);
}
} }
else else
{ {
...@@ -315,7 +313,15 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -315,7 +313,15 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
} }
if (transactional_table) if (transactional_table)
error=ha_autocommit_or_rollback(thd,error); error=ha_autocommit_or_rollback(thd,error);
if (info.copied || info.deleted)
/*
Only invalidate the query cache if something changed or if we
didn't commit the transacion (query cache is automaticly
invalidated on commit)
*/
if ((info.copied || info.deleted) &&
(!transactional_table ||
thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{ {
query_cache_invalidate3(thd, table_list, 1); query_cache_invalidate3(thd, table_list, 1);
} }
......
...@@ -99,7 +99,17 @@ static void init_signals(void) ...@@ -99,7 +99,17 @@ static void init_signals(void)
} }
#endif #endif
inline bool end_active_trans(THD *thd) static void unlock_locked_tables(THD *thd)
{
if (thd->locked_tables)
{
thd->lock=thd->locked_tables;
thd->locked_tables=0; // Will be automaticly closed
close_thread_tables(thd); // Free tables
}
}
static bool end_active_trans(THD *thd)
{ {
int error=0; int error=0;
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
...@@ -698,7 +708,7 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -698,7 +708,7 @@ pthread_handler_decl(handle_one_connection,arg)
(net->last_errno ? ER(net->last_errno) : (net->last_errno ? ER(net->last_errno) :
ER(ER_UNKNOWN_ERROR))); ER(ER_UNKNOWN_ERROR)));
send_error(net,net->last_errno,NullS); send_error(net,net->last_errno,NullS);
thread_safe_increment(aborted_threads,&LOCK_status); statistic_increment(aborted_threads,&LOCK_status);
} }
end_thread: end_thread:
...@@ -911,7 +921,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -911,7 +921,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->lex.select_lex.options=0; // We store status here thd->lex.select_lex.options=0; // We store status here
switch (command) { switch (command) {
case COM_INIT_DB: case COM_INIT_DB:
thread_safe_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status); statistic_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status);
if (!mysql_change_db(thd,packet)) if (!mysql_change_db(thd,packet))
mysql_log.write(thd,command,"%s",thd->db); mysql_log.write(thd,command,"%s",thd->db);
break; break;
...@@ -923,7 +933,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -923,7 +933,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
} }
case COM_TABLE_DUMP: case COM_TABLE_DUMP:
{ {
thread_safe_increment(com_other, &LOCK_status); statistic_increment(com_other, &LOCK_status);
slow_command = TRUE; slow_command = TRUE;
uint db_len = *(uchar*)packet; uint db_len = *(uchar*)packet;
uint tbl_len = *(uchar*)(packet + db_len + 1); uint tbl_len = *(uchar*)(packet + db_len + 1);
...@@ -940,7 +950,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -940,7 +950,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
} }
case COM_CHANGE_USER: case COM_CHANGE_USER:
{ {
thread_safe_increment(com_other,&LOCK_status); thd->change_user();
clear_error_message(thd); // If errors from rollback
statistic_increment(com_other,&LOCK_status);
char *user= (char*) packet; char *user= (char*) packet;
char *passwd= strend(user)+1; char *passwd= strend(user)+1;
char *db= strend(passwd)+1; char *db= strend(passwd)+1;
...@@ -1020,7 +1033,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1020,7 +1033,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{ {
char *fields; char *fields;
TABLE_LIST table_list; TABLE_LIST table_list;
thread_safe_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status); statistic_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status);
bzero((char*) &table_list,sizeof(table_list)); bzero((char*) &table_list,sizeof(table_list));
if (!(table_list.db=thd->db)) if (!(table_list.db=thd->db))
{ {
...@@ -1055,7 +1068,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1055,7 +1068,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_CREATE_DB: // QQ: To be removed case COM_CREATE_DB: // QQ: To be removed
{ {
thread_safe_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status); statistic_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status);
char *db=thd->strdup(packet); char *db=thd->strdup(packet);
// null test to handle EOM // null test to handle EOM
if (!db || !strip_sp(db) || check_db_name(db)) if (!db || !strip_sp(db) || check_db_name(db))
...@@ -1073,7 +1086,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1073,7 +1086,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
} }
case COM_DROP_DB: // QQ: To be removed case COM_DROP_DB: // QQ: To be removed
{ {
thread_safe_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status); statistic_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status);
char *db=thd->strdup(packet); char *db=thd->strdup(packet);
// null test to handle EOM // null test to handle EOM
if (!db || !strip_sp(db) || check_db_name(db)) if (!db || !strip_sp(db) || check_db_name(db))
...@@ -1094,7 +1107,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1094,7 +1107,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
} }
case COM_BINLOG_DUMP: case COM_BINLOG_DUMP:
{ {
thread_safe_increment(com_other,&LOCK_status); statistic_increment(com_other,&LOCK_status);
slow_command = TRUE; slow_command = TRUE;
if (check_global_access(thd, REPL_SLAVE_ACL)) if (check_global_access(thd, REPL_SLAVE_ACL))
break; break;
...@@ -1118,7 +1131,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1118,7 +1131,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
} }
case COM_REFRESH: case COM_REFRESH:
{ {
thread_safe_increment(com_stat[SQLCOM_FLUSH],&LOCK_status); statistic_increment(com_stat[SQLCOM_FLUSH],&LOCK_status);
ulong options= (ulong) (uchar) packet[0]; ulong options= (ulong) (uchar) packet[0];
if (check_global_access(thd,RELOAD_ACL)) if (check_global_access(thd,RELOAD_ACL))
break; break;
...@@ -1130,7 +1143,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1130,7 +1143,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break; break;
} }
case COM_SHUTDOWN: case COM_SHUTDOWN:
thread_safe_increment(com_other,&LOCK_status); statistic_increment(com_other,&LOCK_status);
if (check_global_access(thd,SHUTDOWN_ACL)) if (check_global_access(thd,SHUTDOWN_ACL))
break; /* purecov: inspected */ break; /* purecov: inspected */
DBUG_PRINT("quit",("Got shutdown command")); DBUG_PRINT("quit",("Got shutdown command"));
...@@ -1153,7 +1166,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1153,7 +1166,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_STATISTICS: case COM_STATISTICS:
{ {
mysql_log.write(thd,command,NullS); mysql_log.write(thd,command,NullS);
thread_safe_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status); statistic_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status);
char buff[200]; char buff[200];
ulong uptime = (ulong) (thd->start_time - start_time); ulong uptime = (ulong) (thd->start_time - start_time);
sprintf((char*) buff, sprintf((char*) buff,
...@@ -1172,11 +1185,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1172,11 +1185,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break; break;
} }
case COM_PING: case COM_PING:
thread_safe_increment(com_other,&LOCK_status); statistic_increment(com_other,&LOCK_status);
send_ok(net); // Tell client we are alive send_ok(net); // Tell client we are alive
break; break;
case COM_PROCESS_INFO: case COM_PROCESS_INFO:
thread_safe_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status); statistic_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status);
if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL)) if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL))
break; break;
mysql_log.write(thd,command,NullS); mysql_log.write(thd,command,NullS);
...@@ -1185,13 +1198,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1185,13 +1198,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break; break;
case COM_PROCESS_KILL: case COM_PROCESS_KILL:
{ {
thread_safe_increment(com_stat[SQLCOM_KILL],&LOCK_status); statistic_increment(com_stat[SQLCOM_KILL],&LOCK_status);
ulong id=(ulong) uint4korr(packet); ulong id=(ulong) uint4korr(packet);
kill_one_thread(thd,id); kill_one_thread(thd,id);
break; break;
} }
case COM_DEBUG: case COM_DEBUG:
thread_safe_increment(com_other,&LOCK_status); statistic_increment(com_other,&LOCK_status);
if (check_global_access(thd, SUPER_ACL)) if (check_global_access(thd, SUPER_ACL))
break; /* purecov: inspected */ break; /* purecov: inspected */
mysql_print_status(thd); mysql_print_status(thd);
...@@ -1291,7 +1304,7 @@ mysql_execute_command(void) ...@@ -1291,7 +1304,7 @@ mysql_execute_command(void)
!tables_ok(thd,tables))) !tables_ok(thd,tables)))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
thread_safe_increment(com_stat[lex->sql_command],&LOCK_status); statistic_increment(com_stat[lex->sql_command],&LOCK_status);
switch (lex->sql_command) { switch (lex->sql_command) {
case SQLCOM_SELECT: case SQLCOM_SELECT:
{ {
...@@ -1355,6 +1368,8 @@ mysql_execute_command(void) ...@@ -1355,6 +1368,8 @@ mysql_execute_command(void)
Normal select: Normal select:
Change lock if we are using SELECT HIGH PRIORITY, Change lock if we are using SELECT HIGH PRIORITY,
FOR UPDATE or IN SHARE MODE FOR UPDATE or IN SHARE MODE
TODO: Delete the following loop when locks is set by sql_yacc
*/ */
TABLE_LIST *table; TABLE_LIST *table;
for (table = tables ; table ; table=table->next) for (table = tables ; table ; table=table->next)
...@@ -1561,6 +1576,7 @@ mysql_execute_command(void) ...@@ -1561,6 +1576,7 @@ mysql_execute_command(void)
TABLE_LIST *table; TABLE_LIST *table;
if (check_table_access(thd, SELECT_ACL, tables->next)) if (check_table_access(thd, SELECT_ACL, tables->next))
goto error; // Error message is given goto error; // Error message is given
/* TODO: Delete the following loop when locks is set by sql_yacc */
for (table = tables->next ; table ; table=table->next) for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option; table->lock_type= lex->lock_option;
} }
...@@ -1802,18 +1818,13 @@ mysql_execute_command(void) ...@@ -1802,18 +1818,13 @@ mysql_execute_command(void)
} }
if (select_lex->table_list.elements == 1) if (select_lex->table_list.elements == 1)
{ {
res = mysql_update(thd,tables, res= mysql_update(thd,tables,
select_lex->item_list, select_lex->item_list,
lex->value_list, lex->value_list,
select_lex->where, select_lex->where,
(ORDER *) select_lex->order_list.first, (ORDER *) select_lex->order_list.first,
select_lex->select_limit, select_lex->select_limit,
lex->duplicates, lex->duplicates);
lex->lock_option);
#ifdef DELETE_ITEMS
delete select_lex->where;
#endif
} }
else else
{ {
...@@ -1824,10 +1835,7 @@ mysql_execute_command(void) ...@@ -1824,10 +1835,7 @@ mysql_execute_command(void)
lex->sql_command=SQLCOM_MULTI_UPDATE; lex->sql_command=SQLCOM_MULTI_UPDATE;
for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next) for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next)
{
table_count++; table_count++;
auxi->lock_type=TL_WRITE;
}
if (select_lex->order_list.elements) if (select_lex->order_list.elements)
msg="ORDER BY"; msg="ORDER BY";
else if (select_lex->select_limit && select_lex->select_limit != else if (select_lex->select_limit && select_lex->select_limit !=
...@@ -1848,8 +1856,7 @@ mysql_execute_command(void) ...@@ -1848,8 +1856,7 @@ mysql_execute_command(void)
!setup_fields(thd,tables,lex->value_list,0,0,0) && !setup_fields(thd,tables,lex->value_list,0,0,0) &&
! thd->fatal_error && ! thd->fatal_error &&
(result=new multi_update(thd,tables,select_lex->item_list, (result=new multi_update(thd,tables,select_lex->item_list,
lex->duplicates, lex->lock_option, lex->duplicates, table_count)))
table_count)))
{ {
List <Item> total_list; List <Item> total_list;
List_iterator <Item> field_list(select_lex->item_list); List_iterator <Item> field_list(select_lex->item_list);
...@@ -1880,8 +1887,7 @@ mysql_execute_command(void) ...@@ -1880,8 +1887,7 @@ mysql_execute_command(void)
if (grant_option && check_grant(thd,INSERT_ACL,tables)) if (grant_option && check_grant(thd,INSERT_ACL,tables))
goto error; goto error;
res = mysql_insert(thd,tables,lex->field_list,lex->many_values, res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
lex->duplicates, lex->duplicates);
lex->lock_option);
break; break;
case SQLCOM_REPLACE: case SQLCOM_REPLACE:
if (check_access(thd,INSERT_ACL | DELETE_ACL, if (check_access(thd,INSERT_ACL | DELETE_ACL,
...@@ -1892,8 +1898,7 @@ mysql_execute_command(void) ...@@ -1892,8 +1898,7 @@ mysql_execute_command(void)
goto error; goto error;
res = mysql_insert(thd,tables,lex->field_list,lex->many_values, res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
DUP_REPLACE, DUP_REPLACE);
lex->lock_option);
break; break;
case SQLCOM_REPLACE_SELECT: case SQLCOM_REPLACE_SELECT:
case SQLCOM_INSERT_SELECT: case SQLCOM_INSERT_SELECT:
...@@ -1928,8 +1933,8 @@ mysql_execute_command(void) ...@@ -1928,8 +1933,8 @@ mysql_execute_command(void)
net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name); net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
tables->lock_type=TL_WRITE; // update first table
{ {
/* TODO: Delete the following loop when locks is set by sql_yacc */
TABLE_LIST *table; TABLE_LIST *table;
for (table = tables->next ; table ; table=table->next) for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option; table->lock_type= lex->lock_option;
...@@ -1972,8 +1977,7 @@ mysql_execute_command(void) ...@@ -1972,8 +1977,7 @@ mysql_execute_command(void)
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
res = mysql_delete(thd,tables, select_lex->where, res = mysql_delete(thd,tables, select_lex->where,
(ORDER*) select_lex->order_list.first, (ORDER*) select_lex->order_list.first,
select_lex->select_limit, lex->lock_option, select_lex->select_limit, select_lex->options);
select_lex->options);
break; break;
} }
case SQLCOM_DELETE_MULTI: case SQLCOM_DELETE_MULTI:
...@@ -2009,12 +2013,12 @@ mysql_execute_command(void) ...@@ -2009,12 +2013,12 @@ mysql_execute_command(void)
net_printf(&thd->net,ER_NONUNIQ_TABLE,auxi->real_name); net_printf(&thd->net,ER_NONUNIQ_TABLE,auxi->real_name);
goto error; goto error;
} }
auxi->lock_type=walk->lock_type=TL_WRITE; walk->lock_type= auxi->lock_type;
auxi->table= (TABLE *) walk; // Remember corresponding table auxi->table= (TABLE *) walk; // Remember corresponding table
} }
if (add_item_to_list(new Item_null())) if (add_item_to_list(new Item_null()))
{ {
res = -1; res= -1;
break; break;
} }
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
...@@ -2025,7 +2029,6 @@ mysql_execute_command(void) ...@@ -2025,7 +2029,6 @@ mysql_execute_command(void)
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next) for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
auxi->table= ((TABLE_LIST*) auxi->table)->table; auxi->table= ((TABLE_LIST*) auxi->table)->table;
if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables, if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables,
lex->lock_option,
table_count))) table_count)))
{ {
res=mysql_select(thd,tables,select_lex->item_list, res=mysql_select(thd,tables,select_lex->item_list,
...@@ -2212,11 +2215,7 @@ mysql_execute_command(void) ...@@ -2212,11 +2215,7 @@ mysql_execute_command(void)
send_ok(&thd->net); send_ok(&thd->net);
break; break;
case SQLCOM_UNLOCK_TABLES: case SQLCOM_UNLOCK_TABLES:
if (thd->locked_tables) unlock_locked_tables(thd);
{
thd->lock=thd->locked_tables;
thd->locked_tables=0; // Will be automaticly closed
}
if (thd->options & OPTION_TABLE_LOCK) if (thd->options & OPTION_TABLE_LOCK)
{ {
end_active_trans(thd); end_active_trans(thd);
...@@ -2227,12 +2226,7 @@ mysql_execute_command(void) ...@@ -2227,12 +2226,7 @@ mysql_execute_command(void)
send_ok(&thd->net); send_ok(&thd->net);
break; break;
case SQLCOM_LOCK_TABLES: case SQLCOM_LOCK_TABLES:
if (thd->locked_tables) unlock_locked_tables(thd);
{
thd->lock=thd->locked_tables;
thd->locked_tables=0; // Will be automaticly closed
close_thread_tables(thd);
}
if (check_db_used(thd,tables) || end_active_trans(thd)) if (check_db_used(thd,tables) || end_active_trans(thd))
goto error; goto error;
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, tables)) if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, tables))
...@@ -3258,6 +3252,37 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, ...@@ -3258,6 +3252,37 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
DBUG_RETURN(ptr); DBUG_RETURN(ptr);
} }
/*
Set lock for all tables in current select level
SYNOPSIS:
set_lock_for_tables()
lock_type Lock to set for tables
NOTE:
If lock is a write lock, then tables->updating is set 1
This is to get tables_ok to know that the table is updated by the
query
*/
void set_lock_for_tables(thr_lock_type lock_type)
{
THD *thd=current_thd;
bool for_update= lock_type >= TL_READ_NO_INSERT;
DBUG_ENTER("set_lock_for_tables");
DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type,
for_update));
for (TABLE_LIST *tables= (TABLE_LIST*) thd->lex.select->table_list.first ;
tables ;
tables=tables->next)
{
tables->lock_type= lock_type;
tables->updating= for_update;
}
DBUG_VOID_RETURN;
}
/* /*
** This is used for UNION to create a new table list of all used tables ** This is used for UNION to create a new table list of all used tables
...@@ -3301,7 +3326,6 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result) ...@@ -3301,7 +3326,6 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result)
if (!cursor) if (!cursor)
{ {
/* Add not used table to the total table list */ /* Add not used table to the total table list */
aux->lock_type= lex->lock_option;
if (!(cursor = (TABLE_LIST *) thd->memdup((char*) aux, if (!(cursor = (TABLE_LIST *) thd->memdup((char*) aux,
sizeof(*aux)))) sizeof(*aux))))
{ {
......
...@@ -50,8 +50,7 @@ int mysql_update(THD *thd, ...@@ -50,8 +50,7 @@ int mysql_update(THD *thd,
COND *conds, COND *conds,
ORDER *order, ORDER *order,
ha_rows limit, ha_rows limit,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates)
thr_lock_type lock_type)
{ {
bool using_limit=limit != HA_POS_ERROR, safe_update= thd->options & OPTION_SAFE_UPDATES; bool using_limit=limit != HA_POS_ERROR, safe_update= thd->options & OPTION_SAFE_UPDATES;
bool used_key_is_modified, transactional_table, log_delayed; bool used_key_is_modified, transactional_table, log_delayed;
...@@ -66,7 +65,7 @@ int mysql_update(THD *thd, ...@@ -66,7 +65,7 @@ int mysql_update(THD *thd,
LINT_INIT(used_index); LINT_INIT(used_index);
LINT_INIT(timestamp_query_id); LINT_INIT(timestamp_query_id);
if (!(table = open_ltable(thd,table_list,lock_type))) if (!(table = open_ltable(thd,table_list,table_list->lock_type)))
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
save_time_stamp=table->time_stamp; save_time_stamp=table->time_stamp;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
...@@ -314,9 +313,19 @@ int mysql_update(THD *thd, ...@@ -314,9 +313,19 @@ int mysql_update(THD *thd,
if (!log_delayed) if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
} }
if (transactional_table && ha_autocommit_or_rollback(thd, error >= 0)) if (transactional_table)
error=1; {
if (updated) if (ha_autocommit_or_rollback(thd, error >= 0))
error=1;
}
/*
Only invalidate the query cache if something changed or if we
didn't commit the transacion (query cache is automaticly
invalidated on commit)
*/
if (updated &&
(!transactional_table ||
thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{ {
query_cache_invalidate3(thd, table_list, 1); query_cache_invalidate3(thd, table_list, 1);
} }
...@@ -348,10 +357,12 @@ int mysql_update(THD *thd, ...@@ -348,10 +357,12 @@ int mysql_update(THD *thd,
Update multiple tables from join Update multiple tables from join
***************************************************************************/ ***************************************************************************/
multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs, multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
enum enum_duplicates handle_duplicates, thr_lock_type lock_option_arg, uint num) enum enum_duplicates handle_duplicates,
: update_tables (ut), thd(thd_arg), updated(0), found(0), fields(fs), lock_option(lock_option_arg), uint num)
dupl(handle_duplicates), num_of_tables(num), num_fields(0), num_updated(0) , error(0), do_update(false) : update_tables (ut), thd(thd_arg), updated(0), found(0), fields(fs),
dupl(handle_duplicates), num_of_tables(num), num_fields(0), num_updated(0),
error(0), do_update(false)
{ {
save_time_stamps = (uint *) sql_calloc (sizeof(uint) * num_of_tables); save_time_stamps = (uint *) sql_calloc (sizeof(uint) * num_of_tables);
tmp_tables = (TABLE **)NULL; tmp_tables = (TABLE **)NULL;
......
...@@ -66,6 +66,7 @@ inline Item *or_or_concat(Item* A, Item* B) ...@@ -66,6 +66,7 @@ inline Item *or_or_concat(Item* A, Item* B)
enum enum_tx_isolation tx_isolation; enum enum_tx_isolation tx_isolation;
enum Item_cast cast_type; enum Item_cast cast_type;
enum Item_udftype udf_type; enum Item_udftype udf_type;
thr_lock_type lock_type;
interval_type interval; interval_type interval;
} }
...@@ -263,6 +264,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -263,6 +264,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token NO_SYM %token NO_SYM
%token NULL_SYM %token NULL_SYM
%token NUM %token NUM
%token OFFSET_SYM
%token ON %token ON
%token OPEN_SYM %token OPEN_SYM
%token OPTION %token OPTION
...@@ -513,7 +515,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -513,7 +515,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
type int_type real_type order_dir opt_field_spec lock_option type int_type real_type order_dir opt_field_spec lock_option
udf_type if_exists opt_local opt_table_options table_options udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_var_type opt_var_ident_type table_option opt_if_not_exists opt_var_type opt_var_ident_type
opt_temporary opt_temporary
%type <ulong_num> %type <ulong_num>
ULONG_NUM raid_types merge_insert_types ULONG_NUM raid_types merge_insert_types
...@@ -521,6 +523,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -521,6 +523,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <ulonglong_number> %type <ulonglong_number>
ulonglong_num ulonglong_num
%type <lock_type>
replace_lock_option opt_low_priority insert_lock_option load_data_lock
%type <item> %type <item>
literal text_literal insert_ident order_ident literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
...@@ -582,11 +587,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -582,11 +587,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
field_opt_list opt_binary table_lock_list table_lock varchar field_opt_list opt_binary table_lock_list table_lock varchar
references opt_on_delete opt_on_delete_list opt_on_delete_item use references opt_on_delete opt_on_delete_list opt_on_delete_item use
opt_delete_options opt_delete_option opt_delete_options opt_delete_option
opt_outer table_list table_name opt_option opt_place opt_low_priority opt_outer table_list table_name opt_option opt_place
opt_attribute opt_attribute_list attribute column_list column_list_id opt_attribute opt_attribute_list attribute column_list column_list_id
opt_column_list grant_privileges opt_table user_list grant_option opt_column_list grant_privileges opt_table user_list grant_option
grant_privilege grant_privilege_list grant_privilege grant_privilege_list
flush_options flush_option insert_lock_option replace_lock_option flush_options flush_option
equal optional_braces opt_key_definition key_usage_list2 equal optional_braces opt_key_definition key_usage_list2
opt_mi_check_type opt_to mi_check_types normal_join opt_mi_check_type opt_to mi_check_types normal_join
table_to_table_list table_to_table opt_table_list opt_as table_to_table_list table_to_table opt_table_list opt_as
...@@ -2249,11 +2254,6 @@ order_clause: ...@@ -2249,11 +2254,6 @@ order_clause:
ORDER_SYM BY ORDER_SYM BY
{ {
LEX *lex=Lex; LEX *lex=Lex;
if (lex->sql_command == SQLCOM_MULTI_UPDATE)
{
net_printf(&lex->thd->net, ER_WRONG_USAGE, "UPDATE", "ORDER BY");
YYABORT;
}
if (lex->select->olap != UNSPECIFIED_OLAP_TYPE) if (lex->select->olap != UNSPECIFIED_OLAP_TYPE)
{ {
net_printf(&lex->thd->net, ER_WRONG_USAGE, net_printf(&lex->thd->net, ER_WRONG_USAGE,
...@@ -2278,7 +2278,7 @@ order_dir: ...@@ -2278,7 +2278,7 @@ order_dir:
limit_clause: limit_clause:
/* empty */ {} /* empty */ {}
| LIMIT ULONG_NUM | LIMIT
{ {
LEX *lex=Lex; LEX *lex=Lex;
if (lex->select->olap != UNSPECIFIED_OLAP_TYPE) if (lex->select->olap != UNSPECIFIED_OLAP_TYPE)
...@@ -2287,33 +2287,35 @@ limit_clause: ...@@ -2287,33 +2287,35 @@ limit_clause:
"LIMIT"); "LIMIT");
YYABORT; YYABORT;
} }
SELECT_LEX *sel=Select;
sel->select_limit= $2;
sel->offset_limit= 0L;
} }
| LIMIT ULONG_NUM ',' ULONG_NUM limit_options
;
limit_options:
ULONG_NUM
{ {
LEX *lex=Lex; SELECT_LEX *sel= Select;
if (lex->select->olap != UNSPECIFIED_OLAP_TYPE) sel->select_limit= $1;
{ sel->offset_limit= 0L;
net_printf(&lex->thd->net, ER_WRONG_USAGE, "CUBE/ROLLUP", }
"LIMIT"); | ULONG_NUM ',' ULONG_NUM
YYABORT; {
} SELECT_LEX *sel= Select;
SELECT_LEX *sel=lex->select; sel->select_limit= $3;
sel->select_limit= $4; sel->offset_limit= $1;
sel->offset_limit= $2; }
}; | ULONG_NUM OFFSET_SYM ULONG_NUM
{
SELECT_LEX *sel= Select;
sel->select_limit= $1;
sel->offset_limit= $3;
}
;
delete_limit_clause: delete_limit_clause:
/* empty */ /* empty */
{ {
LEX *lex=Lex; LEX *lex=Lex;
if (lex->sql_command == SQLCOM_MULTI_UPDATE)
{
net_printf(&lex->thd->net, ER_WRONG_USAGE, "DELETE", "LIMIT");
YYABORT;
}
lex->select->select_limit= HA_POS_ERROR; lex->select->select_limit= HA_POS_ERROR;
} }
| LIMIT ulonglong_num | LIMIT ulonglong_num
...@@ -2448,7 +2450,13 @@ opt_temporary: ...@@ -2448,7 +2450,13 @@ opt_temporary:
*/ */
insert: insert:
INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option opt_ignore insert2 insert_field_spec; INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option
opt_ignore insert2
{
set_lock_for_tables($3);
}
insert_field_spec
;
replace: replace:
REPLACE REPLACE
...@@ -2457,17 +2465,23 @@ replace: ...@@ -2457,17 +2465,23 @@ replace:
lex->sql_command = SQLCOM_REPLACE; lex->sql_command = SQLCOM_REPLACE;
lex->duplicates= DUP_REPLACE; lex->duplicates= DUP_REPLACE;
} }
replace_lock_option insert2 insert_field_spec; replace_lock_option insert2
{
set_lock_for_tables($3);
}
insert_field_spec
;
insert_lock_option: insert_lock_option:
/* empty */ { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT; } /* empty */ { $$= TL_WRITE_CONCURRENT_INSERT; }
| LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; } | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
| DELAYED_SYM { Lex->lock_option= TL_WRITE_DELAYED; } | DELAYED_SYM { $$= TL_WRITE_DELAYED; }
| HIGH_PRIORITY { Lex->lock_option= TL_WRITE; }; | HIGH_PRIORITY { $$= TL_WRITE; }
;
replace_lock_option: replace_lock_option:
opt_low_priority {} opt_low_priority { $$= $1; }
| DELAYED_SYM { Lex->lock_option= TL_WRITE_DELAYED; }; | DELAYED_SYM { $$= TL_WRITE_DELAYED; };
insert2: insert2:
INTO insert_table {} INTO insert_table {}
...@@ -2588,7 +2602,12 @@ update: ...@@ -2588,7 +2602,12 @@ update:
lex->select->order_list.first=0; lex->select->order_list.first=0;
lex->select->order_list.next= (byte**) &lex->select->order_list.first; lex->select->order_list.next= (byte**) &lex->select->order_list.first;
} }
opt_low_priority opt_ignore join_table_list SET update_list where_clause opt_order_clause delete_limit_clause; opt_low_priority opt_ignore join_table_list
SET update_list where_clause opt_order_clause delete_limit_clause
{
set_lock_for_tables($3);
}
;
update_list: update_list:
update_list ',' simple_ident equal expr update_list ',' simple_ident equal expr
...@@ -2603,8 +2622,8 @@ update_list: ...@@ -2603,8 +2622,8 @@ update_list:
}; };
opt_low_priority: opt_low_priority:
/* empty */ { Lex->lock_option= current_thd->update_lock_default; } /* empty */ { $$= current_thd->update_lock_default; }
| LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; }; | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; };
/* Delete rows from a table */ /* Delete rows from a table */
...@@ -2618,13 +2637,20 @@ delete: ...@@ -2618,13 +2637,20 @@ delete:
lex->select->order_list.first=0; lex->select->order_list.first=0;
lex->select->order_list.next= (byte**) &lex->select->order_list.first; lex->select->order_list.next= (byte**) &lex->select->order_list.first;
} }
opt_delete_options single_multi {}; opt_delete_options single_multi {}
;
single_multi: single_multi:
FROM table_name where_clause opt_order_clause delete_limit_clause {} FROM table_ident
{
if (!add_table_to_list($2, NULL, 1, Lex->lock_option))
YYABORT;
}
where_clause opt_order_clause
delete_limit_clause
| table_wild_list | table_wild_list
{ mysql_init_multi_delete(Lex); } { mysql_init_multi_delete(Lex); }
FROM join_table_list where_clause FROM join_table_list where_clause
| FROM table_wild_list | FROM table_wild_list
{ mysql_init_multi_delete(Lex); } { mysql_init_multi_delete(Lex); }
USING join_table_list where_clause; USING join_table_list where_clause;
...@@ -2636,14 +2662,17 @@ table_wild_list: ...@@ -2636,14 +2662,17 @@ table_wild_list:
table_wild_one: table_wild_one:
ident opt_wild ident opt_wild
{ {
if (!add_table_to_list(new Table_ident($1),NULL,1,TL_WRITE)) if (!add_table_to_list(new Table_ident($1), NULL, 1,
YYABORT; Lex->lock_option))
YYABORT;
} }
| ident '.' ident opt_wild | ident '.' ident opt_wild
{ {
if (!add_table_to_list(new Table_ident($1,$3,0),NULL,1,TL_WRITE)) if (!add_table_to_list(new Table_ident($1,$3,0), NULL, 1,
Lex->lock_option))
YYABORT; YYABORT;
}; }
;
opt_wild: opt_wild:
/* empty */ {} /* empty */ {}
...@@ -2667,7 +2696,8 @@ truncate: ...@@ -2667,7 +2696,8 @@ truncate:
lex->select->order_list.elements=0; lex->select->order_list.elements=0;
lex->select->order_list.first=0; lex->select->order_list.first=0;
lex->select->order_list.next= (byte**) &lex->select->order_list.first; lex->select->order_list.next= (byte**) &lex->select->order_list.first;
lex->lock_option= current_thd->update_lock_default; }; }
;
opt_table_sym: opt_table_sym:
/* empty */ /* empty */
...@@ -2916,7 +2946,8 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING ...@@ -2916,7 +2946,8 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command= SQLCOM_LOAD; lex->sql_command= SQLCOM_LOAD;
lex->local_file= $4; lex->lock_option= $3;
lex->local_file= $4;
if (!(lex->exchange= new sql_exchange($6.str,0))) if (!(lex->exchange= new sql_exchange($6.str,0)))
YYABORT; YYABORT;
lex->field_list.empty(); lex->field_list.empty();
...@@ -2946,9 +2977,9 @@ opt_local: ...@@ -2946,9 +2977,9 @@ opt_local:
| LOCAL_SYM { $$=1;}; | LOCAL_SYM { $$=1;};
load_data_lock: load_data_lock:
/* empty */ { Lex->lock_option= current_thd->update_lock_default; } /* empty */ { $$= current_thd->update_lock_default; }
| CONCURRENT { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT ; } | CONCURRENT { $$= TL_WRITE_CONCURRENT_INSERT ; }
| LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; }; | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; };
opt_duplicate: opt_duplicate:
...@@ -3201,6 +3232,7 @@ keyword: ...@@ -3201,6 +3232,7 @@ keyword:
| NEW_SYM {} | NEW_SYM {}
| NO_SYM {} | NO_SYM {}
| NONE_SYM {} | NONE_SYM {}
| OFFSET_SYM {}
| OPEN_SYM {} | OPEN_SYM {}
| PACK_KEYS_SYM {} | PACK_KEYS_SYM {}
| PASSWORD {} | PASSWORD {}
......
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