summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2002-11-25 17:53:03 +0200
committerunknown <bell@sanja.is.com.ua>2002-11-25 17:53:03 +0200
commit4383ef137748d3cbfc38fa1e220f4b9268062a1d (patch)
treed6eead8490a6ad0cd9313da254073c017901ba23
parentcfb331bf9048aa30ec439d2e49627830fabeebff (diff)
parent27f2c605531ee8c9e2e629a6cb1d51fa2f81e0a6 (diff)
downloadmariadb-git-4383ef137748d3cbfc38fa1e220f4b9268062a1d.tar.gz
Merge
sql/mysql_priv.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_update.cc: Auto merged sql/sql_yacc.yy: Auto merged mysql-test/r/subselect.result: SCCS merged mysql-test/t/subselect.test: SCCS merged
-rw-r--r--mysql-test/r/innodb-non-simple.result76
-rw-r--r--mysql-test/r/subselect.result16
-rw-r--r--mysql-test/t/innodb-non-simple.test76
-rw-r--r--mysql-test/t/subselect.test13
-rw-r--r--sql/sql_base.cc1
-rw-r--r--sql/sql_lex.cc8
-rw-r--r--sql/sql_parse.cc24
-rw-r--r--sql/sql_select.cc3
-rw-r--r--sql/sql_update.cc18
-rw-r--r--sql/sql_yacc.yy27
10 files changed, 218 insertions, 44 deletions
diff --git a/mysql-test/r/innodb-non-simple.result b/mysql-test/r/innodb-non-simple.result
new file mode 100644
index 00000000000..8461b9d8d4d
--- /dev/null
+++ b/mysql-test/r/innodb-non-simple.result
@@ -0,0 +1,76 @@
+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;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 5a8ff20aa33..a2d29b1c0cf 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -319,3 +319,19 @@ SELECT 1 FROM (SELECT a FROM t1) HAVING (SELECT a)=1;
1
1
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;
diff --git a/mysql-test/t/innodb-non-simple.test b/mysql-test/t/innodb-non-simple.test
new file mode 100644
index 00000000000..1d890896d3f
--- /dev/null
+++ b/mysql-test/t/innodb-non-simple.test
@@ -0,0 +1,76 @@
+-- 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
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 00f3a4f6e44..6bba9d4f3cd 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -203,4 +203,15 @@ drop table t1;
CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1);
SELECT 1 FROM (SELECT a FROM t1) HAVING (SELECT a)=1;
-drop table t1; \ No newline at end of file
+drop table t1;
+
+#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;
+
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 08a17ed1197..09b29c6b41d 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -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,
table_list->real_name,table_list->alias,
&refresh)) && refresh) ;
+
if (table)
{
#if defined( __WIN__) || defined(OS2)
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index e5860346863..35c1847a8aa 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -163,6 +163,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->select_lex.expr_list.empty();
lex->select_lex.ftfunc_list_alloc.empty();
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->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE);
@@ -970,6 +971,7 @@ void st_select_lex::init_query()
item_list.empty();
join= 0;
olap= UNSPECIFIED_OLAP_TYPE;
+ having_fix_field= 0;
}
void st_select_lex::init_select()
@@ -987,7 +989,6 @@ void st_select_lex::init_select()
ftfunc_list_alloc.empty();
ftfunc_list= &ftfunc_list_alloc;
linkage= UNSPECIFIED_TYPE;
- having_fix_field= 0;
}
/*
@@ -1293,4 +1294,7 @@ List<String>* st_select_lex::get_ignore_index()
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
+*/
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 4e5f0019ad6..86333552837 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1426,20 +1426,7 @@ mysql_execute_command(THD *thd)
{
if (!result)
{
- 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
+ if (!(result=new select_send()))
{
res= -1;
#ifdef DELETE_ITEMS
@@ -1663,9 +1650,6 @@ mysql_execute_command(THD *thd)
TABLE_LIST *table;
if (check_table_access(thd, SELECT_ACL, tables->next))
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->select_limit_cnt= select_lex->select_limit+
@@ -2023,12 +2007,6 @@ mysql_execute_command(THD *thd)
net_printf(thd,ER_INSERT_TABLE_USED,tables->real_name);
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 */
lex->select_lex.table_list.first=
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index db0219ae23c..8f406efc030 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -5716,6 +5716,9 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
static Item *
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;
if (ref_parts)
{
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index f2a24eda530..409b00b5703 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -62,12 +62,17 @@ int mysql_update(THD *thd,
TABLE *table;
SQL_SELECT *select;
READ_RECORD info;
+ TABLE_LIST *update_table_list= (TABLE_LIST*)
+ thd->lex.select_lex.table_list.first;
DBUG_ENTER("mysql_update");
LINT_INIT(used_index);
LINT_INIT(timestamp_query_id);
- if (!(table = open_ltable(thd,table_list,table_list->lock_type)))
- DBUG_RETURN(-1); /* purecov: inspected */
+ if ((open_and_lock_tables(thd, table_list)))
+ DBUG_RETURN(-1);
+ fix_tables_pointers(&thd->lex.select_lex);
+ table= table_list->table;
+
save_time_stamp=table->time_stamp;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init";
@@ -77,8 +82,9 @@ int mysql_update(THD *thd,
table->quick_keys=0;
want_privilege=table->grant.want_privilege;
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
- if (setup_tables(table_list) || setup_conds(thd,table_list,&conds)
- || setup_ftfuncs(&thd->lex.select_lex))
+ if (setup_tables(update_table_list) ||
+ setup_conds(thd,update_table_list,&conds)
+ || setup_ftfuncs(&thd->lex.select_lex))
DBUG_RETURN(-1); /* purecov: inspected */
old_used_keys=table->used_keys; // Keys used in WHERE
@@ -94,7 +100,7 @@ int mysql_update(THD *thd,
/* Check the fields we are going to modify */
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 */
if (table->timestamp_field)
{
@@ -107,7 +113,7 @@ int mysql_update(THD *thd,
/* Check values */
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
DBUG_RETURN(-1); /* purecov: inspected */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index fad0fb39020..4465a6d8695 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -798,7 +798,10 @@ create:
($2 &
HA_LEX_CREATE_TMP_TABLE ?
&tmp_table_alias :
- (LEX_STRING*) 0),1))
+ (LEX_STRING*) 0),1,
+ ((using_update_log)?
+ TL_READ_NO_INSERT:
+ TL_READ)))
YYABORT;
lex->create_list.empty();
lex->key_list.empty();
@@ -1646,8 +1649,9 @@ select_init:
select_part2:
{
LEX *lex=Lex;
- lex->lock_option=TL_READ;
- mysql_init_select(lex);
+ if (lex->current_select == &lex->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;
@@ -1704,17 +1708,14 @@ select_lock_type:
| FOR_SYM UPDATE_SYM
{
LEX *lex=Lex;
- if (check_simple_select())
- YYABORT;
- lex->lock_option= TL_WRITE;
+ lex->current_select->set_lock_for_tables(TL_WRITE);
lex->safe_to_cache_query=0;
}
| LOCK_SYM IN_SYM SHARE_SYM MODE_SYM
{
LEX *lex=Lex;
- if (check_simple_select())
- YYABORT;
- lex->lock_option= TL_READ_WITH_SHARED_LOCKS;
+ lex->current_select->
+ set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
lex->safe_to_cache_query=0;
}
;
@@ -2394,8 +2395,9 @@ join_table:
}
table_ident opt_table_alias opt_key_definition
{
- SELECT_LEX_NODE *sel=Select;
- if (!($$= sel->add_table_to_list($2, $3, 0, TL_UNLOCK,
+ LEX *lex= Lex;
+ 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_ignore_index())))
YYABORT;
@@ -2408,7 +2410,8 @@ join_table:
SELECT_LEX_UNIT *unit= lex->current_select->master_unit();
lex->current_select= unit->outer_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;
};