Commit d40bec68 authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

Merge

parents 3d1af24f 0c546b65
drop table if exists t1, t2;
create table t1 (id integer, x integer) type=INNODB;
create table t2 (b integer, a integer) type=INNODB;
insert into t1 values(0, 0), (300, 300);
insert into t2 values(0, 10), (1, 20), (2, 30);
set autocommit=0;
select * from t2;
b a
0 10
1 20
2 30
update t2 set a=100 where b=(SELECT x from t1 where id = b FOR UPDATE);
select * from t2;
b a
0 100
1 20
2 30
select * from t1;
id x
0 0
300 300
set autocommit=0;
update t1 set x=2 where id = 0;
update t1 set x=1 where id = 0;
select * from t1;
id x
0 1
300 300
commit;
commit;
select * from t1;
id x
0 2
300 300
commit;
drop table t1, t2;
create table t1 (id integer, x integer) type=INNODB;
create table t2 (b integer, a integer) type=INNODB;
insert into t1 values(0, 0), (300, 300);
insert into t2 values(0, 0), (1, 20), (2, 30);
commit;
select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE;
a b
0 0
20 1
30 2
300 300
select * from t2;
b a
0 0
1 20
2 30
select * from t1;
id x
0 0
300 300
update t2 set a=2 where b = 0;
select * from t2;
b a
0 2
1 20
2 30
update t1 set x=2 where id = 0;
update t1 set x=1 where id = 0;
select * from t1;
id x
0 1
300 300
commit;
commit;
select * from t1;
id x
0 2
300 300
commit;
drop table t1, t2;
...@@ -319,3 +319,19 @@ SELECT 1 FROM (SELECT a FROM t1) HAVING (SELECT a)=1; ...@@ -319,3 +319,19 @@ SELECT 1 FROM (SELECT a FROM t1) HAVING (SELECT a)=1;
1 1
1 1
drop table t1; drop table t1;
create table t1 (a int NOT NULL, b int, primary key (a));
create table t2 (a int NOT NULL, b int, primary key (a));
insert into t1 values (0, 10),(1, 11),(2, 12);
insert into t2 values (1, 21),(2, 22),(3, 23);
select * from t1;
a b
0 10
1 11
2 12
update t1 set b= (select b from t2 where t1.a = t2.a);
select * from t1;
a b
0 NULL
1 21
2 22
drop table t1, t2;
-- source include/have_innodb.inc
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
drop table if exists t1, t2;
#
# Testing of FOR UPDATE
#
connection con1;
create table t1 (id integer, x integer) type=INNODB;
create table t2 (b integer, a integer) type=INNODB;
insert into t1 values(0, 0), (300, 300);
insert into t2 values(0, 10), (1, 20), (2, 30);
set autocommit=0;
select * from t2;
update t2 set a=100 where b=(SELECT x from t1 where id = b FOR UPDATE);
select * from t2;
select * from t1;
connection con2;
set autocommit=0;
# The following query should hang because con1 is locking the page
--send
update t1 set x=2 where id = 0;
--sleep 2;
connection con1;
update t1 set x=1 where id = 0;
select * from t1;
commit;
connection con2;
reap;
commit;
connection con1;
select * from t1;
commit;
drop table t1, t2;
create table t1 (id integer, x integer) type=INNODB;
create table t2 (b integer, a integer) type=INNODB;
insert into t1 values(0, 0), (300, 300);
insert into t2 values(0, 0), (1, 20), (2, 30);
commit;
connection con1;
select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE;
select * from t2;
select * from t1;
connection con2;
# The following query should hang because con1 is locking the page
update t2 set a=2 where b = 0;
select * from t2;
--send
update t1 set x=2 where id = 0;
--sleep 2;
connection con1;
update t1 set x=1 where id = 0;
select * from t1;
commit;
connection con2;
reap;
commit;
connection con1;
select * from t1;
commit;
drop table t1, t2;
\ No newline at end of file
...@@ -203,4 +203,15 @@ drop table t1; ...@@ -203,4 +203,15 @@ drop table t1;
CREATE TABLE t1 (a int(1)); CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
SELECT 1 FROM (SELECT a FROM t1) HAVING (SELECT a)=1; SELECT 1 FROM (SELECT a FROM t1) HAVING (SELECT a)=1;
drop table t1; drop table t1;
\ No newline at end of file
#update with subselects
create table t1 (a int NOT NULL, b int, primary key (a));
create table t2 (a int NOT NULL, b int, primary key (a));
insert into t1 values (0, 10),(1, 11),(2, 12);
insert into t2 values (1, 21),(2, 22),(3, 23);
select * from t1;
update t1 set b= (select b from t2 where t1.a = t2.a);
select * from t1;
drop table t1, t2;
...@@ -1625,6 +1625,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) ...@@ -1625,6 +1625,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
while (!(table=open_table(thd,table_list->db, while (!(table=open_table(thd,table_list->db,
table_list->real_name,table_list->alias, table_list->real_name,table_list->alias,
&refresh)) && refresh) ; &refresh)) && refresh) ;
if (table) if (table)
{ {
#if defined( __WIN__) || defined(OS2) #if defined( __WIN__) || defined(OS2)
......
...@@ -163,6 +163,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) ...@@ -163,6 +163,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->select_lex.expr_list.empty(); lex->select_lex.expr_list.empty();
lex->select_lex.ftfunc_list_alloc.empty(); lex->select_lex.ftfunc_list_alloc.empty();
lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc; lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
lex->current_select= &lex->select_lex;
lex->convert_set= (lex->thd= thd)->variables.convert_set; lex->convert_set= (lex->thd= thd)->variables.convert_set;
lex->yacc_yyss=lex->yacc_yyvs=0; lex->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE); lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE);
...@@ -970,6 +971,7 @@ void st_select_lex::init_query() ...@@ -970,6 +971,7 @@ void st_select_lex::init_query()
item_list.empty(); item_list.empty();
join= 0; join= 0;
olap= UNSPECIFIED_OLAP_TYPE; olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0;
} }
void st_select_lex::init_select() void st_select_lex::init_select()
...@@ -987,7 +989,6 @@ void st_select_lex::init_select() ...@@ -987,7 +989,6 @@ void st_select_lex::init_select()
ftfunc_list_alloc.empty(); ftfunc_list_alloc.empty();
ftfunc_list= &ftfunc_list_alloc; ftfunc_list= &ftfunc_list_alloc;
linkage= UNSPECIFIED_TYPE; linkage= UNSPECIFIED_TYPE;
having_fix_field= 0;
} }
/* /*
...@@ -1293,4 +1294,7 @@ List<String>* st_select_lex::get_ignore_index() ...@@ -1293,4 +1294,7 @@ List<String>* st_select_lex::get_ignore_index()
return ignore_index_ptr; return ignore_index_ptr;
} }
// There are st_select_lex::add_table_to_list in sql_parse.cc /*
There are st_select_lex::add_table_to_list &
st_select_lex::set_lock_for_tables in sql_parse.cc
*/
...@@ -1426,20 +1426,7 @@ mysql_execute_command(THD *thd) ...@@ -1426,20 +1426,7 @@ mysql_execute_command(THD *thd)
{ {
if (!result) if (!result)
{ {
if ((result=new select_send())) if (!(result=new select_send()))
{
/*
Normal select:
Change lock if we are using SELECT HIGH PRIORITY,
FOR UPDATE or IN SHARE MODE
TODO: Delete the following loop when locks is set by sql_yacc
*/
TABLE_LIST *table;
for (table = tables ; table ; table=table->next)
table->lock_type= lex->lock_option;
}
else
{ {
res= -1; res= -1;
#ifdef DELETE_ITEMS #ifdef DELETE_ITEMS
...@@ -1663,9 +1650,6 @@ mysql_execute_command(THD *thd) ...@@ -1663,9 +1650,6 @@ mysql_execute_command(THD *thd)
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)
table->lock_type= lex->lock_option;
} }
unit->offset_limit_cnt= select_lex->offset_limit; unit->offset_limit_cnt= select_lex->offset_limit;
unit->select_limit_cnt= select_lex->select_limit+ unit->select_limit_cnt= select_lex->select_limit+
...@@ -2023,12 +2007,6 @@ mysql_execute_command(THD *thd) ...@@ -2023,12 +2007,6 @@ mysql_execute_command(THD *thd)
net_printf(thd,ER_INSERT_TABLE_USED,tables->real_name); net_printf(thd,ER_INSERT_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
{
/* TODO: Delete the following loop when locks is set by sql_yacc */
TABLE_LIST *table;
for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option;
}
/* Skip first table, which is the table we are inserting in */ /* Skip first table, which is the table we are inserting in */
lex->select_lex.table_list.first= lex->select_lex.table_list.first=
......
...@@ -5716,6 +5716,9 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table) ...@@ -5716,6 +5716,9 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
static Item * static Item *
part_of_refkey(TABLE *table,Field *field) part_of_refkey(TABLE *table,Field *field)
{ {
if (!table->reginfo.join_tab)
return (Item*) 0; // field from outer non-select (UPDATE,...)
uint ref_parts=table->reginfo.join_tab->ref.key_parts; uint ref_parts=table->reginfo.join_tab->ref.key_parts;
if (ref_parts) if (ref_parts)
{ {
......
...@@ -62,12 +62,17 @@ int mysql_update(THD *thd, ...@@ -62,12 +62,17 @@ int mysql_update(THD *thd,
TABLE *table; TABLE *table;
SQL_SELECT *select; SQL_SELECT *select;
READ_RECORD info; READ_RECORD info;
TABLE_LIST *update_table_list= (TABLE_LIST*)
thd->lex.select_lex.table_list.first;
DBUG_ENTER("mysql_update"); DBUG_ENTER("mysql_update");
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,table_list->lock_type))) if ((open_and_lock_tables(thd, table_list)))
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1);
fix_tables_pointers(&thd->lex.select_lex);
table= table_list->table;
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);
thd->proc_info="init"; thd->proc_info="init";
...@@ -77,8 +82,9 @@ int mysql_update(THD *thd, ...@@ -77,8 +82,9 @@ int mysql_update(THD *thd,
table->quick_keys=0; table->quick_keys=0;
want_privilege=table->grant.want_privilege; want_privilege=table->grant.want_privilege;
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege); table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
if (setup_tables(table_list) || setup_conds(thd,table_list,&conds) if (setup_tables(update_table_list) ||
|| setup_ftfuncs(&thd->lex.select_lex)) setup_conds(thd,update_table_list,&conds)
|| setup_ftfuncs(&thd->lex.select_lex))
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
old_used_keys=table->used_keys; // Keys used in WHERE old_used_keys=table->used_keys; // Keys used in WHERE
...@@ -94,7 +100,7 @@ int mysql_update(THD *thd, ...@@ -94,7 +100,7 @@ int mysql_update(THD *thd,
/* Check the fields we are going to modify */ /* Check the fields we are going to modify */
table->grant.want_privilege=want_privilege; table->grant.want_privilege=want_privilege;
if (setup_fields(thd,table_list,fields,1,0,0)) if (setup_fields(thd,update_table_list,fields,1,0,0))
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
if (table->timestamp_field) if (table->timestamp_field)
{ {
...@@ -107,7 +113,7 @@ int mysql_update(THD *thd, ...@@ -107,7 +113,7 @@ int mysql_update(THD *thd,
/* Check values */ /* Check values */
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege); table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
if (setup_fields(thd,table_list,values,0,0,0)) if (setup_fields(thd,update_table_list,values,0,0,0))
{ {
table->time_stamp=save_time_stamp; // Restore timestamp pointer table->time_stamp=save_time_stamp; // Restore timestamp pointer
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
......
...@@ -798,7 +798,10 @@ create: ...@@ -798,7 +798,10 @@ create:
($2 & ($2 &
HA_LEX_CREATE_TMP_TABLE ? HA_LEX_CREATE_TMP_TABLE ?
&tmp_table_alias : &tmp_table_alias :
(LEX_STRING*) 0),1)) (LEX_STRING*) 0),1,
((using_update_log)?
TL_READ_NO_INSERT:
TL_READ)))
YYABORT; YYABORT;
lex->create_list.empty(); lex->create_list.empty();
lex->key_list.empty(); lex->key_list.empty();
...@@ -1646,8 +1649,9 @@ select_init: ...@@ -1646,8 +1649,9 @@ select_init:
select_part2: select_part2:
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->lock_option=TL_READ; if (lex->current_select == &lex->select_lex)
mysql_init_select(lex); lex->lock_option= TL_READ; /* Only for global SELECT */
mysql_init_select(lex);
} }
select_options select_item_list select_into select_lock_type; select_options select_item_list select_into select_lock_type;
...@@ -1704,17 +1708,14 @@ select_lock_type: ...@@ -1704,17 +1708,14 @@ select_lock_type:
| FOR_SYM UPDATE_SYM | FOR_SYM UPDATE_SYM
{ {
LEX *lex=Lex; LEX *lex=Lex;
if (check_simple_select()) lex->current_select->set_lock_for_tables(TL_WRITE);
YYABORT;
lex->lock_option= TL_WRITE;
lex->safe_to_cache_query=0; lex->safe_to_cache_query=0;
} }
| LOCK_SYM IN_SYM SHARE_SYM MODE_SYM | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM
{ {
LEX *lex=Lex; LEX *lex=Lex;
if (check_simple_select()) lex->current_select->
YYABORT; set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
lex->lock_option= TL_READ_WITH_SHARED_LOCKS;
lex->safe_to_cache_query=0; lex->safe_to_cache_query=0;
} }
; ;
...@@ -2394,8 +2395,9 @@ join_table: ...@@ -2394,8 +2395,9 @@ join_table:
} }
table_ident opt_table_alias opt_key_definition table_ident opt_table_alias opt_key_definition
{ {
SELECT_LEX_NODE *sel=Select; LEX *lex= Lex;
if (!($$= sel->add_table_to_list($2, $3, 0, TL_UNLOCK, SELECT_LEX_NODE *sel= lex->current_select;
if (!($$= sel->add_table_to_list($2, $3, 0, lex->lock_option,
sel->get_use_index(), sel->get_use_index(),
sel->get_ignore_index()))) sel->get_ignore_index())))
YYABORT; YYABORT;
...@@ -2408,7 +2410,8 @@ join_table: ...@@ -2408,7 +2410,8 @@ join_table:
SELECT_LEX_UNIT *unit= lex->current_select->master_unit(); SELECT_LEX_UNIT *unit= lex->current_select->master_unit();
lex->current_select= unit->outer_select(); lex->current_select= unit->outer_select();
if (!($$= lex->current_select-> if (!($$= lex->current_select->
add_table_to_list(new Table_ident(unit), $5, 0, TL_UNLOCK))) add_table_to_list(new Table_ident(unit), $5, 0,
lex->lock_option)))
YYABORT; YYABORT;
}; };
......
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