Commit 1a96948e authored by monty@mashka.mysql.fi's avatar monty@mashka.mysql.fi

Small improvement to alloc_root

Add support for LIMIT # OFFSET #
Changed lock handling:  Now all locks should be stored in TABLE_LIST instead of passed to functions.
Don't call query_cache_invalidate() twice in some cases
mysql_change_user() now clears states to be equal to close + connect.
Fixed a bug with multi-table-update and multi-table-delete when used with LOCK TABLES
Fixed a bug with replicate-do and UPDATE
parent aa67a796
...@@ -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;
} }
......
...@@ -3785,6 +3785,7 @@ ha_innobase::external_lock( ...@@ -3785,6 +3785,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);
......
...@@ -912,7 +912,7 @@ void ha_myisam::info(uint flag) ...@@ -912,7 +912,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)
{
my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,
ER(ER_TABLE_NOT_LOCKED_FOR_WRITE),
MYF(0),table_list->alias);
table=0;
} }
else if ((error=table->file->start_stmt(thd))) else
{ {
table->file->print_error(error,MYF(0)); if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
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))) if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
DBUG_RETURN(0); table= 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 ((thd->options & OPTION_SAFE_UPDATES) && !conds) if ((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)
{
if (ha_autocommit_or_rollback(thd,error >= 0))
error=1; error=1;
if (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 (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,6 +200,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -200,6 +200,7 @@ 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);
if (thd->variables.bulk_insert_buff_size)
table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN, table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
thd->variables.bulk_insert_buff_size); thd->variables.bulk_insert_buff_size);
table->bulk_insert= 1; table->bulk_insert= 1;
...@@ -266,11 +267,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -266,11 +267,8 @@ 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
{ {
if (bulk_insert) if (bulk_insert)
...@@ -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);
} }
......
This diff is collapsed.
...@@ -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; bool using_limit=limit != HA_POS_ERROR;
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);
...@@ -316,9 +315,19 @@ int mysql_update(THD *thd, ...@@ -316,9 +315,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)
{
if (ha_autocommit_or_rollback(thd, error >= 0))
error=1; error=1;
if (updated) }
/*
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);
} }
...@@ -351,9 +360,11 @@ int mysql_update(THD *thd, ...@@ -351,9 +360,11 @@ int mysql_update(THD *thd,
***************************************************************************/ ***************************************************************************/
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
...@@ -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; limit_options
;
limit_options:
ULONG_NUM
{
SELECT_LEX *sel= Select;
sel->select_limit= $1;
sel->offset_limit= 0L; sel->offset_limit= 0L;
} }
| LIMIT ULONG_NUM ',' ULONG_NUM | ULONG_NUM ',' ULONG_NUM
{ {
LEX *lex=Lex; SELECT_LEX *sel= Select;
if (lex->select->olap != UNSPECIFIED_OLAP_TYPE) sel->select_limit= $3;
sel->offset_limit= $1;
}
| ULONG_NUM OFFSET_SYM ULONG_NUM
{ {
net_printf(&lex->thd->net, ER_WRONG_USAGE, "CUBE/ROLLUP", SELECT_LEX *sel= Select;
"LIMIT"); sel->select_limit= $1;
YYABORT; sel->offset_limit= $3;
} }
SELECT_LEX *sel=lex->select; ;
sel->select_limit= $4;
sel->offset_limit= $2;
};
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,10 +2637,17 @@ delete: ...@@ -2618,10 +2637,17 @@ 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
...@@ -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,
Lex->lock_option))
YYABORT; 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,6 +2946,7 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING ...@@ -2916,6 +2946,7 @@ 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->lock_option= $3;
lex->local_file= $4; lex->local_file= $4;
if (!(lex->exchange= new sql_exchange($6.str,0))) if (!(lex->exchange= new sql_exchange($6.str,0)))
YYABORT; YYABORT;
...@@ -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