diff options
author | unknown <dlenev@mysql.com> | 2006-06-21 01:50:20 +0400 |
---|---|---|
committer | unknown <dlenev@mysql.com> | 2006-06-21 01:50:20 +0400 |
commit | e9452db1c1b7fb534a44590312d6608640675350 (patch) | |
tree | 47d48c79ace5fcdbac5cd5c1f69187657896bc25 /sql/sql_parse.cc | |
parent | 375a1894512b80302fb73858759050d3d56b58bf (diff) | |
download | mariadb-git-e9452db1c1b7fb534a44590312d6608640675350.tar.gz |
Fix for bug#19634 "Re-execution of multi-delete which involve trigger/stored
function crashes server".
Attempts to execute prepared multi-delete statement which involved trigger or
stored function caused server crashes (the same happened for such statements
included in stored procedures in cases when one tried to execute them more
than once).
The problem was caused by yet another incorrect usage of check_table_access()
routine (the latter assumes that table list which it gets as argument
corresponds to value LEX::query_tables_own_last). We solve this problem by
juggling with LEX::query_tables_own_last value when we call
check_table_access() for LEX::auxilliary_table_list (better solution is too
intrusive and should be done in 5.1).
mysql-test/r/sp-prelocking.result:
Added test for bug#19634 "Re-execution of multi-delete which involve trigger/
stored function crashes server".
mysql-test/t/sp-prelocking.test:
Added test for bug#19634 "Re-execution of multi-delete which involve trigger/
stored function crashes server".
sql/sql_parse.cc:
To call safely check_table_access() for LEX::auxilliary_table_list we have
to juggle with LEX::query_tables_own_last value.
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r-- | sql/sql_parse.cc | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ba5c2ebf484..7ed96250240 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5202,8 +5202,26 @@ bool check_global_access(THD *thd, ulong want_access) /* - Check the privilege for all used tables. Table privileges are cached - in the table list for GRANT checking + Check the privilege for all used tables. + + SYNOPSYS + check_table_access() + thd Thread context + want_access Privileges requested + tables List of tables to be checked + no_errors FALSE/TRUE - report/don't report error to + the client (using my_error() call). + + NOTES + Table privileges are cached in the table list for GRANT checking. + This functions assumes that table list used and + thd->lex->query_tables_own_last value correspond to each other + (the latter should be either 0 or point to next_global member + of one of elements of this table list). + + RETURN VALUE + FALSE - OK + TRUE - Access denied */ bool @@ -7068,14 +7086,28 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) SELECT_LEX *select_lex= &thd->lex->select_lex; TABLE_LIST *aux_tables= (TABLE_LIST *)thd->lex->auxilliary_table_list.first; + TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; DBUG_ENTER("multi_delete_precheck"); /* sql_yacc guarantees that tables and aux_tables are not zero */ DBUG_ASSERT(aux_tables != 0); if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) || - check_table_access(thd,SELECT_ACL, tables,0) || - check_table_access(thd,DELETE_ACL, aux_tables,0)) + check_table_access(thd, SELECT_ACL, tables, 0)) + DBUG_RETURN(TRUE); + + /* + Since aux_tables list is not part of LEX::query_tables list we + have to juggle with LEX::query_tables_own_last value to be able + call check_table_access() safely. + */ + thd->lex->query_tables_own_last= 0; + if (check_table_access(thd, DELETE_ACL, aux_tables, 0)) + { + thd->lex->query_tables_own_last= save_query_tables_own_last; DBUG_RETURN(TRUE); + } + thd->lex->query_tables_own_last= save_query_tables_own_last; + if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where) { my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, |