From c81300691327066b954fb34116f6d1f88e0d49d6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Oct 2002 22:59:29 +0300 Subject: [PATCH] fixed update with subselect (FOR REVIEW) mysql-test/r/subselect.result: update with subselect test mysql-test/t/subselect.test: update with subselect test sql/mysql_priv.h: fixed update with subselect sql/sql_base.cc: fixed update with subselect sql/sql_lex.cc: fixed update with subselect sql/sql_select.cc: fixed update with subselect sql/sql_update.cc: fixed update with subselect sql/sql_yacc.yy: fixed update with subselect --- mysql-test/r/subselect.result | 16 ++++++++++++++++ mysql-test/t/subselect.test | 13 ++++++++++++- sql/mysql_priv.h | 3 ++- sql/sql_base.cc | 16 ++++++++++++---- sql/sql_lex.cc | 4 +++- sql/sql_select.cc | 3 +++ sql/sql_update.cc | 18 ++++++++++++------ sql/sql_yacc.yy | 5 +++-- 8 files changed, 63 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 3f89f546ca3..60312ca46a3 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -205,3 +205,19 @@ SELECT (SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03') (SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03') 2002-08-03 drop table searchconthardwarefr3; +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/subselect.test b/mysql-test/t/subselect.test index 6e585883f1c..a2c9d4dbb7b 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -110,4 +110,15 @@ EXPLAIN SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03'; EXPLAIN SELECT (SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03'); SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03'; SELECT (SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03'); -drop table searchconthardwarefr3; \ No newline at end of file +drop table searchconthardwarefr3; + +#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/mysql_priv.h b/sql/mysql_priv.h index d1a3c7e235a..f81d8ce7af6 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -444,7 +444,8 @@ void kill_delayed_threads(void); int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order, ha_rows rows, thr_lock_type lock_type, ulong options); 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, + bool multiopen= 0); TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias, bool *refresh); TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 46afddf0967..425784dada2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1567,16 +1567,24 @@ int open_tables(THD *thd,TABLE_LIST *start) } -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, + bool multiopen) { TABLE *table; bool refresh; DBUG_ENTER("open_ltable"); thd->proc_info="Opening table"; - while (!(table=open_table(thd,table_list->db, - table_list->real_name,table_list->alias, - &refresh)) && refresh) ; + if (table_list->next && multiopen) + { + while (open_tables(thd,table_list) && refresh) ; + table= table_list->table; + } + else + while (!(table= open_table(thd,table_list->db, + table_list->real_name,table_list->alias, + &refresh)) && refresh) ; + if (table) { int error; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9f09afc78a6..132c760267f 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -148,6 +148,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->ftfunc_list_alloc; + lex->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); @@ -956,6 +957,7 @@ void st_select_lex::init_query() table_list.next= (byte**) &table_list.first; item_list.empty(); join= 0; + having_fix_field= 0; } void st_select_lex::init_select() @@ -973,7 +975,7 @@ void st_select_lex::init_select() ftfunc_list_alloc.empty(); ftfunc_list= &ftfunc_list_alloc; linkage= UNSPECIFIED_TYPE; - depended= having_fix_field= 0; + depended= 0; } /* diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6a48f56443c..c3cc4c1041c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5641,6 +5641,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 c146b07284f..d47e539f610 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,lock_type))) - DBUG_RETURN(-1); /* purecov: inspected */ + table_list->lock_type= lock_type; + if (!(table = open_ltable(thd,table_list,lock_type, 1))) + DBUG_RETURN(-1); + fix_tables_pointers(&thd->lex.select_lex); + 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)) + if (setup_tables(update_table_list) || + setup_conds(thd,update_table_list,&conds) + || setup_ftfuncs(thd)) 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 f5b8c6e4b24..a6bfbafe46a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1572,8 +1572,9 @@ select_init: select_part2: { LEX *lex=Lex; - lex->lock_option=TL_READ; - mysql_init_select(lex); + if (lex->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;