Commit 61f0e69c authored by unknown's avatar unknown

ufter revview fix (BUG#2120)


mysql-test/r/derived.result:
  test of error handling in derived tables with UPDATE & DELETE
mysql-test/t/derived.test:
  test of error handling in derived tables with UPDATE & DELETE
sql/mysql_priv.h:
  opened tables counter added to avoid loop of tables calculating in lock_tables
sql/sql_acl.cc:
  opened tables counter added to avoid loop of tables calculating in lock_tables, here it is just for compatibility
sql/sql_base.cc:
  removed unneeded assignment
  opened tables counter added to avoid loop of tables calculating in lock_tables
  commentary fixed
sql/sql_derived.cc:
  mysql_derived made static
  variable res moved in place where it used
  priveleges written in correct place
sql/sql_handler.cc:
  opened tables counter added to avoid loop of tables calculating in lock_tables
sql/sql_parse.cc:
  mistyping in commentary fixed
parent 584ddfda
...@@ -267,12 +267,16 @@ N M ...@@ -267,12 +267,16 @@ N M
3 0 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; 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. 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; 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; select * from t1;
N M N M
3 0 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; 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. 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; drop table t1;
CREATE TABLE t1 ( CREATE TABLE t1 (
OBJECTID int(11) NOT NULL default '0', OBJECTID int(11) NOT NULL default '0',
......
...@@ -153,10 +153,14 @@ UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) ...@@ -153,10 +153,14 @@ UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1)
select * from t1; select * from t1;
-- error 1287 -- 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; 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; 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; select * from t1;
-- error 1287 -- 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; 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; drop table t1;
# #
......
...@@ -675,10 +675,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); ...@@ -675,10 +675,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
int setup_ftfuncs(SELECT_LEX* select); int setup_ftfuncs(SELECT_LEX* select);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
void wait_for_refresh(THD *thd); 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 simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables);
int open_and_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, TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list); const char *table_name, bool link_in_list);
bool rm_temporary_table(enum db_type base, char *path); bool rm_temporary_table(enum db_type base, char *path);
......
...@@ -173,7 +173,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) ...@@ -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].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ;
tables[0].db=tables[1].db=tables[2].db=thd->db; 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", sql_print_error("Fatal error: Can't open privilege tables: %s",
thd->net.last_error); thd->net.last_error);
...@@ -2524,7 +2525,8 @@ my_bool grant_init(THD *org_thd) ...@@ -2524,7 +2525,8 @@ my_bool grant_init(THD *org_thd)
tables[0].lock_type=tables[1].lock_type=TL_READ; tables[0].lock_type=tables[1].lock_type=TL_READ;
tables[0].db=tables[1].db=thd->db; tables[0].db=tables[1].db=thd->db;
if (open_tables(thd,tables)) uint counter;
if (open_tables(thd, tables, &counter))
goto end; goto end;
TABLE *ptr[2]; // Lock tables for quick update TABLE *ptr[2]; // Lock tables for quick update
......
...@@ -1308,7 +1308,6 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, ...@@ -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 bzero((char*) &table_list, sizeof(table_list)); // just for safe
table_list.db=(char*) db; table_list.db=(char*) db;
table_list.real_name=(char*) name; table_list.real_name=(char*) name;
table_list.next=0;
safe_mutex_assert_owner(&LOCK_open); safe_mutex_assert_owner(&LOCK_open);
if ((error=lock_table_name(thd,&table_list))) if ((error=lock_table_name(thd,&table_list)))
...@@ -1357,24 +1356,40 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, ...@@ -1357,24 +1356,40 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
DBUG_RETURN(1); 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; TABLE_LIST *tables;
bool refresh; bool refresh;
int result=0; int result=0;
DBUG_ENTER("open_tables"); DBUG_ENTER("open_tables");
*counter= 0;
thd->current_tablenr= 0; thd->current_tablenr= 0;
restart: restart:
thd->proc_info="Opening tables"; thd->proc_info="Opening tables";
for (tables=start ; tables ; tables=tables->next) 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) if (tables->derived)
continue; continue;
(*counter)++;
if (!tables->table && if (!tables->table &&
!(tables->table= open_table(thd, !(tables->table= open_table(thd,
tables->db, tables->db,
...@@ -1533,14 +1548,19 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) ...@@ -1533,14 +1548,19 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
thd - thread handler thd - thread handler
tables - list of tables for open&locking tables - list of tables for open&locking
RETURN
0 - ok
-1 - error
NOTE NOTE
The lock will automaticly be freed by close_thread_tables() The lock will automaticly be freed by close_thread_tables()
*/ */
int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables) int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables)
{ {
DBUG_ENTER("open_n_lock_tables"); DBUG_ENTER("simple_open_n_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 */ DBUG_RETURN(-1); /* purecov: inspected */
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1551,10 +1571,14 @@ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables) ...@@ -1551,10 +1571,14 @@ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables)
tables processing. tables processing.
SYNOPSIS SYNOPSIS
simple_open_n_lock_tables() open_and_lock_tables()
thd - thread handler thd - thread handler
tables - list of tables for open&locking tables - list of tables for open&locking
RETURN
0 - ok
-1 - error
NOTE NOTE
The lock will automaticly be freed by close_thread_tables() 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) ...@@ -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) int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
{ {
DBUG_ENTER("open_and_lock_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 */ DBUG_RETURN(-1); /* purecov: inspected */
fix_tables_pointers(thd->lex->all_selects_list); fix_tables_pointers(thd->lex->all_selects_list);
DBUG_RETURN(mysql_handle_derived(thd->lex)); DBUG_RETURN(mysql_handle_derived(thd->lex));
...@@ -1576,6 +1601,7 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables) ...@@ -1576,6 +1601,7 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
lock_tables() lock_tables()
thd Thread handler thd Thread handler
tables Tables to lock tables Tables to lock
count umber of opened tables
NOTES NOTES
You can't call lock_tables twice, as this would break the dead-lock-free 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) ...@@ -1587,7 +1613,7 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
-1 Error -1 Error
*/ */
int lock_tables(THD *thd,TABLE_LIST *tables) int lock_tables(THD *thd, TABLE_LIST *tables, uint count)
{ {
TABLE_LIST *table; TABLE_LIST *table;
if (!tables) if (!tables)
...@@ -1596,12 +1622,6 @@ int lock_tables(THD *thd,TABLE_LIST *tables) ...@@ -1596,12 +1622,6 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
if (!thd->locked_tables) if (!thd->locked_tables)
{ {
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once 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; TABLE **start,**ptr;
if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count))) if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count)))
return -1; return -1;
...@@ -2207,7 +2227,6 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, ...@@ -2207,7 +2227,6 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Ensure that we have access right to all columns */ /* Ensure that we have access right to all columns */
if (!(table->grant.privilege & SELECT_ACL) && if (!(table->grant.privilege & SELECT_ACL) &&
!tables->derived &&
check_grant_all_columns(thd,SELECT_ACL,table)) check_grant_all_columns(thd,SELECT_ACL,table))
DBUG_RETURN(-1); DBUG_RETURN(-1);
#endif #endif
......
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
#include "sql_select.h" #include "sql_select.h"
#include "sql_acl.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 Resolve derived tables in all queries
...@@ -39,10 +40,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); ...@@ -39,10 +40,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
-1 Error -1 Error
1 Error and error message given 1 Error and error message given
*/ */
int int
mysql_handle_derived(LEX *lex) mysql_handle_derived(LEX *lex)
{ {
int res= 0;
if (lex->derived_tables) if (lex->derived_tables)
{ {
for (SELECT_LEX *sl= lex->all_selects_list; for (SELECT_LEX *sl= lex->all_selects_list;
...@@ -53,13 +54,12 @@ mysql_handle_derived(LEX *lex) ...@@ -53,13 +54,12 @@ mysql_handle_derived(LEX *lex)
cursor; cursor;
cursor= cursor->next) cursor= cursor->next)
{ {
int res;
if (cursor->derived && (res=mysql_derived(lex->thd, lex, if (cursor->derived && (res=mysql_derived(lex->thd, lex,
cursor->derived, cursor->derived,
cursor))) cursor)))
{ {
if (res < 0 || lex->thd->net.report_error) return res;
send_error(lex->thd, lex->thd->killed ? ER_SERVER_SHUTDOWN : 0);
return 1;
} }
} }
if (lex->describe) if (lex->describe)
...@@ -108,8 +108,8 @@ mysql_handle_derived(LEX *lex) ...@@ -108,8 +108,8 @@ mysql_handle_derived(LEX *lex)
*/ */
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
TABLE_LIST *org_table_list) TABLE_LIST *org_table_list)
{ {
SELECT_LEX *first_select= unit->first_select(); SELECT_LEX *first_select= unit->first_select();
TABLE *table; TABLE *table;
...@@ -197,7 +197,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, ...@@ -197,7 +197,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
table->derived_select_number= first_select->select_number; table->derived_select_number= first_select->select_number;
table->tmp_table= TMP_TABLE; table->tmp_table= TMP_TABLE;
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
org_table_list->grant.privilege= SELECT_ACL; table->grant.privilege= SELECT_ACL;
#endif #endif
org_table_list->db= (char *)""; org_table_list->db= (char *)"";
// Force read of table stats in the optimizer // Force read of table stats in the optimizer
......
...@@ -48,7 +48,8 @@ static TABLE **find_table_ptr_by_name(THD *thd,const char *db, ...@@ -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) int mysql_ha_open(THD *thd, TABLE_LIST *tables)
{ {
HANDLER_TABLES_HACK(thd); HANDLER_TABLES_HACK(thd);
int err=open_tables(thd,tables); uint counter;
int err=open_tables(thd, tables, &counter);
HANDLER_TABLES_HACK(thd); HANDLER_TABLES_HACK(thd);
if (err) if (err)
return -1; return -1;
......
...@@ -2669,8 +2669,8 @@ mysql_execute_command(THD *thd) ...@@ -2669,8 +2669,8 @@ mysql_execute_command(THD *thd)
{ {
auxi->table= auxi->table_list->table; auxi->table= auxi->table_list->table;
/* /*
Multi-delete can't be constucted over-union => we always have Multi-delete can't be constructed over-union => we always have
single SELECT on top and have to check underlayed SELECTs of it single SELECT on top and have to check underlaying SELECTs of it
*/ */
for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit(); for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit();
un; un;
......
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