diff options
Diffstat (limited to 'sql/sql_prepare.cc')
-rw-r--r-- | sql/sql_prepare.cc | 245 |
1 files changed, 8 insertions, 237 deletions
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index b10a81d5e56..b9ae058cfb8 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -95,10 +95,8 @@ When one supplies long data for a placeholder: #include "sql_base.h" // open_normal_and_derived_tables #include "sql_cache.h" // query_cache_* #include "sql_view.h" // create_view_precheck -#include "sql_delete.h" // mysql_prepare_delete #include "sql_select.h" // for JOIN #include "sql_insert.h" // upgrade_lock_type_for_insert, mysql_prepare_insert -#include "sql_update.h" // mysql_prepare_update #include "sql_db.h" // mysql_opt_change_db, mysql_change_db #include "sql_derived.h" // mysql_derived_prepare, // mysql_handle_derived @@ -1399,160 +1397,6 @@ static bool mysql_test_insert(Prepared_statement *stmt, } -/** - Validate UPDATE statement. - - @param stmt prepared statement - @param tables list of tables used in this query - - @todo - - here we should send types of placeholders to the client. - - @retval - 0 success - @retval - 1 error, error message is set in THD - @retval - 2 convert to multi_update -*/ - -static int mysql_test_update(Prepared_statement *stmt, - TABLE_LIST *table_list) -{ - int res; - THD *thd= stmt->thd; - uint table_count= 0; - TABLE_LIST *update_source_table; - SELECT_LEX *select= stmt->lex->first_select_lex(); -#ifndef NO_EMBEDDED_ACCESS_CHECKS - privilege_t want_privilege(NO_ACL); -#endif - DBUG_ENTER("mysql_test_update"); - - if (update_precheck(thd, table_list) || - open_tables(thd, &table_list, &table_count, MYSQL_OPEN_FORCE_SHARED_MDL)) - goto error; - - if (mysql_handle_derived(thd->lex, DT_INIT)) - goto error; - - if (((update_source_table= unique_table(thd, table_list, - table_list->next_global, 0)) || - table_list->is_multitable())) - { - DBUG_ASSERT(update_source_table || table_list->view != 0); - DBUG_PRINT("info", ("Switch to multi-update")); - /* pass counter value */ - thd->lex->table_count= table_count; - /* convert to multiupdate */ - DBUG_RETURN(2); - } - - /* - thd->fill_derived_tables() is false here for sure (because it is - preparation of PS, so we even do not check it). - */ - if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT)) - goto error; - if (table_list->handle_derived(thd->lex, DT_PREPARE)) - goto error; - - if (!table_list->single_table_updatable()) - { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "UPDATE"); - goto error; - } - -#ifndef NO_EMBEDDED_ACCESS_CHECKS - /* Force privilege re-checking for views after they have been opened. */ - want_privilege= (table_list->view ? UPDATE_ACL : - table_list->grant.want_privilege); -#endif - - if (mysql_prepare_update(thd, table_list, &select->where, - select->order_list.elements, - select->order_list.first)) - goto error; - -#ifndef NO_EMBEDDED_ACCESS_CHECKS - table_list->grant.want_privilege= want_privilege; - table_list->table->grant.want_privilege= want_privilege; - table_list->register_want_access(want_privilege); -#endif - thd->lex->first_select_lex()->no_wrap_view_item= TRUE; - res= setup_fields(thd, Ref_ptr_array(), - select->item_list, MARK_COLUMNS_READ, 0, NULL, 0); - thd->lex->first_select_lex()->no_wrap_view_item= FALSE; - if (res) - goto error; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - /* Check values */ - table_list->grant.want_privilege= - table_list->table->grant.want_privilege= - (SELECT_ACL & ~table_list->table->grant.privilege); - table_list->register_want_access(SELECT_ACL); -#endif - if (setup_fields(thd, Ref_ptr_array(), - stmt->lex->value_list, COLUMNS_READ, 0, NULL, 0) || - check_unique_table(thd, table_list)) - goto error; - /* TODO: here we should send types of placeholders to the client. */ - DBUG_RETURN(0); -error: - DBUG_RETURN(1); -} - - -/** - Validate DELETE statement. - - @param stmt prepared statement - @param tables list of tables used in this query - - @retval - FALSE success - @retval - TRUE error, error message is set in THD -*/ - -static bool mysql_test_delete(Prepared_statement *stmt, - TABLE_LIST *table_list) -{ - uint table_count= 0; - THD *thd= stmt->thd; - LEX *lex= stmt->lex; - bool delete_while_scanning; - DBUG_ENTER("mysql_test_delete"); - - if (delete_precheck(thd, table_list) || - open_tables(thd, &table_list, &table_count, MYSQL_OPEN_FORCE_SHARED_MDL)) - goto error; - - if (mysql_handle_derived(thd->lex, DT_INIT)) - goto error; - if (mysql_handle_derived(thd->lex, DT_MERGE_FOR_INSERT)) - goto error; - if (mysql_handle_derived(thd->lex, DT_PREPARE)) - goto error; - - if (!table_list->single_table_updatable()) - { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE"); - goto error; - } - if (!table_list->table || !table_list->table->is_created()) - { - my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), - table_list->view_db.str, table_list->view_name.str); - goto error; - } - - DBUG_RETURN(mysql_prepare_delete(thd, table_list, - &lex->first_select_lex()->where, - &delete_while_scanning)); -error: - DBUG_RETURN(TRUE); -} /** @@ -2135,74 +1979,6 @@ err: } -/* - Validate and prepare for execution a multi update statement. - - @param stmt prepared statement - @param tables list of tables used in this query - @param converted converted to multi-update from usual update - - @retval - FALSE success - @retval - TRUE error, error message is set in THD -*/ - -static bool mysql_test_multiupdate(Prepared_statement *stmt, - TABLE_LIST *tables, - bool converted) -{ - /* if we switched from normal update, rights are checked */ - if (!converted && multi_update_precheck(stmt->thd, tables)) - return TRUE; - - return select_like_stmt_test(stmt, &mysql_multi_update_prepare, - OPTION_SETUP_TABLES_DONE); -} - - -/** - Validate and prepare for execution a multi delete statement. - - @param stmt prepared statement - @param tables list of tables used in this query - - @retval - FALSE success - @retval - TRUE error, error message in THD is set. -*/ - -static bool mysql_test_multidelete(Prepared_statement *stmt, - TABLE_LIST *tables) -{ - THD *thd= stmt->thd; - - thd->lex->current_select= thd->lex->first_select_lex(); - if (add_item_to_list(thd, new (thd->mem_root) - Item_null(thd))) - { - my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 0); - goto error; - } - - if (multi_delete_precheck(thd, tables) || - select_like_stmt_test_with_open(stmt, tables, - &mysql_multi_delete_prepare, - OPTION_SETUP_TABLES_DONE)) - goto error; - if (!tables->table) - { - my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), - tables->view_db.str, tables->view_name.str); - goto error; - } - return FALSE; -error: - return TRUE; -} - - /** Wrapper for mysql_insert_select_prepare, to make change of local tables after open_normal_and_derived_tables() call. @@ -2484,18 +2260,14 @@ static bool check_prepared_statement(Prepared_statement *stmt) break; case SQLCOM_UPDATE: - res= mysql_test_update(stmt, tables); - /* mysql_test_update returns 2 if we need to switch to multi-update */ - if (res != 2) - break; - /* fall through */ case SQLCOM_UPDATE_MULTI: - res= mysql_test_multiupdate(stmt, tables, res == 2); - break; - case SQLCOM_DELETE: - res= mysql_test_delete(stmt, tables); + case SQLCOM_DELETE_MULTI: + res = lex->m_sql_cmd->prepare(thd); + if (!res) + lex->m_sql_cmd->unprepare(thd); break; + /* The following allow WHERE clause, so they must be tested like SELECT */ case SQLCOM_SHOW_DATABASES: case SQLCOM_SHOW_TABLES: @@ -2632,10 +2404,6 @@ static bool check_prepared_statement(Prepared_statement *stmt) res= mysql_test_set_fields(stmt, tables, &lex->var_list); break; - case SQLCOM_DELETE_MULTI: - res= mysql_test_multidelete(stmt, tables); - break; - case SQLCOM_INSERT_SELECT: case SQLCOM_REPLACE_SELECT: res= mysql_test_insert_select(stmt, tables); @@ -4373,6 +4141,9 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) thd->is_error() || init_param_array(this)); + if (lex->m_sql_cmd) + lex->m_sql_cmd->set_owner(this); + if (thd->security_ctx->password_expired && lex->sql_command != SQLCOM_SET_OPTION && lex->sql_command != SQLCOM_PREPARE && |