diff options
-rw-r--r-- | mysql-test/r/derived.result | 4 | ||||
-rw-r--r-- | mysql-test/t/derived.test | 4 | ||||
-rw-r--r-- | sql/mysql_priv.h | 4 | ||||
-rw-r--r-- | sql/sql_acl.cc | 6 | ||||
-rw-r--r-- | sql/sql_base.cc | 53 | ||||
-rw-r--r-- | sql/sql_derived.cc | 16 | ||||
-rw-r--r-- | sql/sql_handler.cc | 3 | ||||
-rw-r--r-- | sql/sql_parse.cc | 4 |
8 files changed, 62 insertions, 32 deletions
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index dea4dd9b4c2..6f35097e2b8 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -267,12 +267,16 @@ N M 3 0 UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2; ERROR HY000: The target table P2 of the UPDATE is not updatable. +UPDATE `t1` AS P1 INNER JOIN (SELECT aaaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2; +ERROR 42S22: Unknown column 'aaaa' in 'field list' delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; select * from t1; N M 3 0 delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; ERROR HY000: The target table P2 of the DELETE is not updatable. +delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; +ERROR 42S22: Unknown column 'aaa' in 'field list' drop table t1; CREATE TABLE t1 ( OBJECTID int(11) NOT NULL default '0', diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index 988ef30d1dc..0a7e3d41c73 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -153,10 +153,14 @@ UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) select * from t1; -- error 1287 UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2; +-- error 1054 +UPDATE `t1` AS P1 INNER JOIN (SELECT aaaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2; delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; select * from t1; -- error 1287 delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; +-- error 1054 +delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N; drop table t1; # diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4d03feae07c..73e30e72a3c 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -675,10 +675,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); int setup_ftfuncs(SELECT_LEX* select); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); void wait_for_refresh(THD *thd); -int open_tables(THD *thd,TABLE_LIST *tables); +int open_tables(THD *thd, TABLE_LIST *tables, uint *counter); int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables); int open_and_lock_tables(THD *thd,TABLE_LIST *tables); -int lock_tables(THD *thd,TABLE_LIST *tables); +int lock_tables(THD *thd, TABLE_LIST *tables, uint counter); TABLE *open_temporary_table(THD *thd, const char *path, const char *db, const char *table_name, bool link_in_list); bool rm_temporary_table(enum db_type base, char *path); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 8ef6a32a430..21c57d79da4 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -173,7 +173,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ; tables[0].db=tables[1].db=tables[2].db=thd->db; - if (open_tables(thd,tables)) + uint counter; + if (open_tables(thd, tables, &counter)) { sql_print_error("Fatal error: Can't open privilege tables: %s", thd->net.last_error); @@ -2524,7 +2525,8 @@ my_bool grant_init(THD *org_thd) tables[0].lock_type=tables[1].lock_type=TL_READ; tables[0].db=tables[1].db=thd->db; - if (open_tables(thd,tables)) + uint counter; + if (open_tables(thd, tables, &counter)) goto end; TABLE *ptr[2]; // Lock tables for quick update diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 2e8441bb23b..0ededa80ad6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1308,7 +1308,6 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, bzero((char*) &table_list, sizeof(table_list)); // just for safe table_list.db=(char*) db; table_list.real_name=(char*) name; - table_list.next=0; safe_mutex_assert_owner(&LOCK_open); if ((error=lock_table_name(thd,&table_list))) @@ -1357,24 +1356,40 @@ err: DBUG_RETURN(1); } -/***************************************************************************** -** open all tables in list -*****************************************************************************/ +/* + Open all tables in list + + SYNOPSIS + open_tables() + thd - thread handler + start - list of tables + counter - number of opened tables will be return using this parameter -int open_tables(THD *thd,TABLE_LIST *start) + RETURN + 0 - OK + -1 - error +*/ + +int open_tables(THD *thd, TABLE_LIST *start, uint *counter) { TABLE_LIST *tables; bool refresh; int result=0; DBUG_ENTER("open_tables"); + *counter= 0; thd->current_tablenr= 0; restart: thd->proc_info="Opening tables"; for (tables=start ; tables ; tables=tables->next) { + /* + Ignore placeholders for derived tables. After derived tables + processing, link to created temporary table will be put here. + */ if (tables->derived) continue; + (*counter)++; if (!tables->table && !(tables->table= open_table(thd, tables->db, @@ -1533,14 +1548,19 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) thd - thread handler tables - list of tables for open&locking + RETURN + 0 - ok + -1 - error + NOTE The lock will automaticly be freed by close_thread_tables() */ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables) { - DBUG_ENTER("open_n_lock_tables"); - if (open_tables(thd, tables) || lock_tables(thd, tables)) + DBUG_ENTER("simple_open_n_lock_tables"); + uint counter; + if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter)) DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(0); } @@ -1551,10 +1571,14 @@ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables) tables processing. SYNOPSIS - simple_open_n_lock_tables() + open_and_lock_tables() thd - thread handler tables - list of tables for open&locking + RETURN + 0 - ok + -1 - error + NOTE The lock will automaticly be freed by close_thread_tables() */ @@ -1562,7 +1586,8 @@ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables) int open_and_lock_tables(THD *thd, TABLE_LIST *tables) { DBUG_ENTER("open_and_lock_tables"); - if (open_tables(thd, tables) || lock_tables(thd, tables)) + uint counter; + if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter)) DBUG_RETURN(-1); /* purecov: inspected */ fix_tables_pointers(thd->lex->all_selects_list); DBUG_RETURN(mysql_handle_derived(thd->lex)); @@ -1576,6 +1601,7 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables) lock_tables() thd Thread handler tables Tables to lock + count umber of opened tables NOTES You can't call lock_tables twice, as this would break the dead-lock-free @@ -1587,7 +1613,7 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables) -1 Error */ -int lock_tables(THD *thd,TABLE_LIST *tables) +int lock_tables(THD *thd, TABLE_LIST *tables, uint count) { TABLE_LIST *table; if (!tables) @@ -1596,12 +1622,6 @@ int lock_tables(THD *thd,TABLE_LIST *tables) if (!thd->locked_tables) { DBUG_ASSERT(thd->lock == 0); // You must lock everything at once - uint count=0; - for (table = tables ; table ; table=table->next) - { - if (!table->derived) - count++; - } TABLE **start,**ptr; if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count))) return -1; @@ -2207,7 +2227,6 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Ensure that we have access right to all columns */ if (!(table->grant.privilege & SELECT_ACL) && - !tables->derived && check_grant_all_columns(thd,SELECT_ACL,table)) DBUG_RETURN(-1); #endif diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index a307b59b525..6e70fdd46d5 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -25,7 +25,8 @@ #include "sql_select.h" #include "sql_acl.h" -int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); +static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, + TABLE_LIST *t); /* Resolve derived tables in all queries @@ -39,10 +40,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); -1 Error 1 Error and error message given */ + int mysql_handle_derived(LEX *lex) { - int res= 0; if (lex->derived_tables) { for (SELECT_LEX *sl= lex->all_selects_list; @@ -53,13 +54,12 @@ mysql_handle_derived(LEX *lex) cursor; cursor= cursor->next) { + int res; if (cursor->derived && (res=mysql_derived(lex->thd, lex, cursor->derived, cursor))) { - if (res < 0 || lex->thd->net.report_error) - send_error(lex->thd, lex->thd->killed ? ER_SERVER_SHUTDOWN : 0); - return 1; + return res; } } if (lex->describe) @@ -108,8 +108,8 @@ mysql_handle_derived(LEX *lex) */ -int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, - TABLE_LIST *org_table_list) +static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, + TABLE_LIST *org_table_list) { SELECT_LEX *first_select= unit->first_select(); TABLE *table; @@ -197,7 +197,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, table->derived_select_number= first_select->select_number; table->tmp_table= TMP_TABLE; #ifndef NO_EMBEDDED_ACCESS_CHECKS - org_table_list->grant.privilege= SELECT_ACL; + table->grant.privilege= SELECT_ACL; #endif org_table_list->db= (char *)""; // Force read of table stats in the optimizer diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 405cfdb5bdc..897aa37ba11 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -48,7 +48,8 @@ static TABLE **find_table_ptr_by_name(THD *thd,const char *db, int mysql_ha_open(THD *thd, TABLE_LIST *tables) { HANDLER_TABLES_HACK(thd); - int err=open_tables(thd,tables); + uint counter; + int err=open_tables(thd, tables, &counter); HANDLER_TABLES_HACK(thd); if (err) return -1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 14696ce7478..42ea6039b6c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2669,8 +2669,8 @@ mysql_execute_command(THD *thd) { auxi->table= auxi->table_list->table; /* - Multi-delete can't be constucted over-union => we always have - single SELECT on top and have to check underlayed SELECTs of it + Multi-delete can't be constructed over-union => we always have + single SELECT on top and have to check underlaying SELECTs of it */ for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit(); un; |