diff options
author | unknown <bell@sanja.is.com.ua> | 2002-11-25 17:53:03 +0200 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2002-11-25 17:53:03 +0200 |
commit | 4383ef137748d3cbfc38fa1e220f4b9268062a1d (patch) | |
tree | d6eead8490a6ad0cd9313da254073c017901ba23 | |
parent | cfb331bf9048aa30ec439d2e49627830fabeebff (diff) | |
parent | 27f2c605531ee8c9e2e629a6cb1d51fa2f81e0a6 (diff) | |
download | mariadb-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.result | 76 | ||||
-rw-r--r-- | mysql-test/r/subselect.result | 16 | ||||
-rw-r--r-- | mysql-test/t/innodb-non-simple.test | 76 | ||||
-rw-r--r-- | mysql-test/t/subselect.test | 13 | ||||
-rw-r--r-- | sql/sql_base.cc | 1 | ||||
-rw-r--r-- | sql/sql_lex.cc | 8 | ||||
-rw-r--r-- | sql/sql_parse.cc | 24 | ||||
-rw-r--r-- | sql/sql_select.cc | 3 | ||||
-rw-r--r-- | sql/sql_update.cc | 18 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 27 |
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; }; |