mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
* bzr merge -rtag:mariadb-10.0.9 maria/10.0
* Fix for post-merge build failures.
This commit is contained in:
177
sql/sql_parse.cc
177
sql/sql_parse.cc
@ -201,6 +201,8 @@ static bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables)
|
||||
@param thd Thread handle.
|
||||
@param mask Bitmask used for the SQL command match.
|
||||
|
||||
@return 0 No implicit commit
|
||||
@return 1 Do a commit
|
||||
*/
|
||||
static bool stmt_causes_implicit_commit(THD *thd, uint mask)
|
||||
{
|
||||
@ -213,12 +215,22 @@ static bool stmt_causes_implicit_commit(THD *thd, uint mask)
|
||||
|
||||
switch (lex->sql_command) {
|
||||
case SQLCOM_DROP_TABLE:
|
||||
skip= lex->drop_temporary;
|
||||
skip= (lex->drop_temporary ||
|
||||
(thd->variables.option_bits & OPTION_GTID_BEGIN));
|
||||
break;
|
||||
case SQLCOM_ALTER_TABLE:
|
||||
/* If ALTER TABLE of non-temporary table, do implicit commit */
|
||||
skip= (lex->create_info.tmp_table());
|
||||
break;
|
||||
case SQLCOM_CREATE_TABLE:
|
||||
/* If CREATE TABLE of non-temporary table, do implicit commit */
|
||||
skip= lex->create_info.tmp_table();
|
||||
/*
|
||||
If CREATE TABLE of non-temporary table and the table is not part
|
||||
if a BEGIN GTID ... COMMIT group, do a implicit commit.
|
||||
This ensures that CREATE ... SELECT will in the same GTID group on the
|
||||
master and slave.
|
||||
*/
|
||||
skip= (lex->create_info.tmp_table() ||
|
||||
(thd->variables.option_bits & OPTION_GTID_BEGIN));
|
||||
break;
|
||||
case SQLCOM_SET_OPTION:
|
||||
skip= lex->autocommit ? FALSE : TRUE;
|
||||
@ -2440,6 +2452,7 @@ mysql_execute_command(THD *thd)
|
||||
Rpl_filter *rpl_filter= thd->rpl_filter;
|
||||
#endif
|
||||
DBUG_ENTER("mysql_execute_command");
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
thd->work_part_info= 0;
|
||||
#endif
|
||||
@ -2681,8 +2694,8 @@ mysql_execute_command(THD *thd)
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
status_var_increment(thd->status_var.com_stat[lex->sql_command]);
|
||||
thd->progress.report_to_client= test(sql_command_flags[lex->sql_command] &
|
||||
CF_REPORT_PROGRESS);
|
||||
thd->progress.report_to_client= MY_TEST(sql_command_flags[lex->sql_command] &
|
||||
CF_REPORT_PROGRESS);
|
||||
|
||||
DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table == FALSE);
|
||||
|
||||
@ -2717,15 +2730,18 @@ mysql_execute_command(THD *thd)
|
||||
DBUG_ASSERT(! thd->in_sub_stmt);
|
||||
/* Statement transaction still should not be started. */
|
||||
DBUG_ASSERT(thd->transaction.stmt.is_empty());
|
||||
/* Commit the normal transaction if one is active. */
|
||||
if (trans_commit_implicit(thd))
|
||||
if (!(thd->variables.option_bits & OPTION_GTID_BEGIN))
|
||||
{
|
||||
/* Commit the normal transaction if one is active. */
|
||||
if (trans_commit_implicit(thd))
|
||||
{
|
||||
thd->mdl_context.release_transactional_locks();
|
||||
WSREP_DEBUG("implicit commit failed, MDL released: %lu", thd->thread_id);
|
||||
goto error;
|
||||
}
|
||||
/* Release metadata locks acquired in this transaction. */
|
||||
thd->mdl_context.release_transactional_locks();
|
||||
WSREP_DEBUG("implicit commit failed, MDL released: %lu", thd->thread_id);
|
||||
goto error;
|
||||
}
|
||||
/* Release metadata locks acquired in this transaction. */
|
||||
thd->mdl_context.release_transactional_locks();
|
||||
}
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
@ -3124,6 +3140,7 @@ case SQLCOM_PREPARE:
|
||||
goto end_with_restore_list;
|
||||
}
|
||||
|
||||
/* Check privileges */
|
||||
if ((res= create_table_precheck(thd, select_tables, create_table)))
|
||||
goto end_with_restore_list;
|
||||
|
||||
@ -3158,6 +3175,23 @@ case SQLCOM_PREPARE:
|
||||
create_info.table_charset= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
For CREATE TABLE we should not open the table even if it exists.
|
||||
If the table exists, we should either not create it or replace it
|
||||
*/
|
||||
lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
|
||||
|
||||
/*
|
||||
If we are a slave, we should add OR REPLACE if we don't have
|
||||
IF EXISTS. This will help a slave to recover from
|
||||
CREATE TABLE OR EXISTS failures by dropping the table and
|
||||
retrying the create.
|
||||
*/
|
||||
if (thd->slave_thread &&
|
||||
slave_ddl_exec_mode_options == SLAVE_EXEC_MODE_IDEMPOTENT &&
|
||||
!(lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS))
|
||||
create_info.options|= HA_LEX_CREATE_REPLACE;
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
{
|
||||
partition_info *part_info= thd->lex->part_info;
|
||||
@ -3246,28 +3280,25 @@ case SQLCOM_PREPARE:
|
||||
/* Got error or warning. Set res to 1 if error */
|
||||
if (!(res= thd->is_error()))
|
||||
my_ok(thd); // CREATE ... IF NOT EXISTS
|
||||
goto end_with_restore_list;
|
||||
}
|
||||
else
|
||||
|
||||
/* Ensure we don't try to create something from which we select from */
|
||||
if ((create_info.options & HA_LEX_CREATE_REPLACE) &&
|
||||
!create_info.tmp_table())
|
||||
{
|
||||
/* The table already exists */
|
||||
if (create_table->table)
|
||||
TABLE_LIST *duplicate;
|
||||
if ((duplicate= unique_table(thd, lex->query_tables,
|
||||
lex->query_tables->next_global,
|
||||
0)))
|
||||
{
|
||||
if (create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS)
|
||||
{
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_TABLE_EXISTS_ERROR,
|
||||
ER(ER_TABLE_EXISTS_ERROR),
|
||||
create_info.alias);
|
||||
my_ok(thd);
|
||||
}
|
||||
else
|
||||
{
|
||||
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_info.alias);
|
||||
res= 1;
|
||||
}
|
||||
update_non_unique_table_error(lex->query_tables, "CREATE",
|
||||
duplicate);
|
||||
res= TRUE;
|
||||
goto end_with_restore_list;
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
/*
|
||||
Remove target table from main select and name resolution
|
||||
context. This can't be done earlier as it will break view merging in
|
||||
@ -3275,9 +3306,8 @@ case SQLCOM_PREPARE:
|
||||
*/
|
||||
lex->unlink_first_table(&link_to_local);
|
||||
|
||||
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
|
||||
if (create_info.tmp_table())
|
||||
thd->variables.option_bits|= OPTION_KEEP_LOG;
|
||||
/* Store reference to table in case of LOCK TABLES */
|
||||
create_info.table= create_table->table;
|
||||
|
||||
/*
|
||||
select_create is currently not re-execution friendly and
|
||||
@ -3295,18 +3325,18 @@ case SQLCOM_PREPARE:
|
||||
CREATE from SELECT give its SELECT_LEX for SELECT,
|
||||
and item_list belong to SELECT
|
||||
*/
|
||||
res= handle_select(thd, lex, result, 0);
|
||||
if (!(res= handle_select(thd, lex, result, 0)))
|
||||
{
|
||||
if (create_info.tmp_table())
|
||||
thd->variables.option_bits|= OPTION_KEEP_LOG;
|
||||
}
|
||||
delete result;
|
||||
}
|
||||
|
||||
lex->link_first_table_back(create_table, link_to_local);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
|
||||
if (create_info.tmp_table())
|
||||
thd->variables.option_bits|= OPTION_KEEP_LOG;
|
||||
/* regular create */
|
||||
if (create_info.options & HA_LEX_CREATE_TABLE_LIKE)
|
||||
{
|
||||
@ -3330,7 +3360,12 @@ case SQLCOM_PREPARE:
|
||||
&create_info, &alter_info);
|
||||
}
|
||||
if (!res)
|
||||
{
|
||||
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
|
||||
if (create_info.tmp_table())
|
||||
thd->variables.option_bits|= OPTION_KEEP_LOG;
|
||||
my_ok(thd);
|
||||
}
|
||||
}
|
||||
|
||||
end_with_restore_list:
|
||||
@ -3780,7 +3815,7 @@ end_with_restore_list:
|
||||
case SQLCOM_INSERT_SELECT:
|
||||
{
|
||||
select_result *sel_result;
|
||||
bool explain= test(lex->describe);
|
||||
bool explain= MY_TEST(lex->describe);
|
||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||
if ((res= insert_precheck(thd, all_tables)))
|
||||
break;
|
||||
@ -3903,7 +3938,7 @@ end_with_restore_list:
|
||||
{
|
||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||
TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
|
||||
bool explain= test(lex->describe);
|
||||
bool explain= MY_TEST(lex->describe);
|
||||
multi_delete *result;
|
||||
|
||||
if ((res= multi_delete_precheck(thd, all_tables)))
|
||||
@ -3987,6 +4022,16 @@ end_with_restore_list:
|
||||
}
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
/*
|
||||
If we are a slave, we should add IF EXISTS if the query executed
|
||||
on the master without an error. This will help a slave to
|
||||
recover from multi-table DROP TABLE that was aborted in the
|
||||
middle.
|
||||
*/
|
||||
if (thd->slave_thread && !thd->slave_expected_error &&
|
||||
slave_ddl_exec_mode_options == SLAVE_EXEC_MODE_IDEMPOTENT)
|
||||
lex->check_exists= 1;
|
||||
|
||||
/* DDL and binlog write order are protected by metadata locks. */
|
||||
res= mysql_rm_table(thd, first_table, lex->check_exists,
|
||||
lex->drop_temporary);
|
||||
@ -4570,14 +4615,16 @@ end_with_restore_list:
|
||||
if (check_global_access(thd,RELOAD_ACL))
|
||||
goto error;
|
||||
|
||||
if (first_table && lex->type & REFRESH_READ_LOCK)
|
||||
if (first_table && lex->type & (REFRESH_READ_LOCK|REFRESH_FOR_EXPORT))
|
||||
{
|
||||
/* Check table-level privileges. */
|
||||
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
|
||||
FALSE, UINT_MAX, FALSE))
|
||||
goto error;
|
||||
|
||||
if (flush_tables_with_read_lock(thd, all_tables))
|
||||
goto error;
|
||||
|
||||
my_ok(thd);
|
||||
break;
|
||||
}
|
||||
@ -4777,6 +4824,7 @@ end_with_restore_list:
|
||||
bool tx_release= (lex->tx_release == TVL_YES ||
|
||||
(thd->variables.completion_type == 2 &&
|
||||
lex->tx_release != TVL_NO));
|
||||
|
||||
if (trans_rollback(thd))
|
||||
{
|
||||
thd->mdl_context.release_transactional_locks();
|
||||
@ -5498,6 +5546,7 @@ finish:
|
||||
DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() ||
|
||||
thd->in_multi_stmt_transaction_mode());
|
||||
|
||||
lex->unit.cleanup();
|
||||
|
||||
if (! thd->in_sub_stmt)
|
||||
{
|
||||
@ -5529,7 +5578,6 @@ finish:
|
||||
ha_maria::implicit_commit(thd, FALSE);
|
||||
#endif
|
||||
}
|
||||
lex->unit.cleanup();
|
||||
|
||||
/* Free tables */
|
||||
THD_STAGE_INFO(thd, stage_closing_tables);
|
||||
@ -5562,12 +5610,15 @@ finish:
|
||||
{
|
||||
/* No transaction control allowed in sub-statements. */
|
||||
DBUG_ASSERT(! thd->in_sub_stmt);
|
||||
/* If commit fails, we should be able to reset the OK status. */
|
||||
thd->get_stmt_da()->set_overwrite_status(true);
|
||||
/* Commit the normal transaction if one is active. */
|
||||
trans_commit_implicit(thd);
|
||||
thd->get_stmt_da()->set_overwrite_status(false);
|
||||
thd->mdl_context.release_transactional_locks();
|
||||
if (!(thd->variables.option_bits & OPTION_GTID_BEGIN))
|
||||
{
|
||||
/* If commit fails, we should be able to reset the OK status. */
|
||||
thd->get_stmt_da()->set_overwrite_status(true);
|
||||
/* Commit the normal transaction if one is active. */
|
||||
trans_commit_implicit(thd);
|
||||
thd->get_stmt_da()->set_overwrite_status(false);
|
||||
thd->mdl_context.release_transactional_locks();
|
||||
}
|
||||
}
|
||||
else if (! thd->in_sub_stmt && ! thd->in_multi_stmt_transaction_mode())
|
||||
{
|
||||
@ -6549,6 +6600,8 @@ void THD::reset_for_next_command()
|
||||
thd->query_start_used= 0;
|
||||
thd->query_start_sec_part_used= 0;
|
||||
thd->is_fatal_error= thd->time_zone_used= 0;
|
||||
thd->log_current_statement= 0;
|
||||
|
||||
/*
|
||||
Clear the status flag that are expected to be cleared at the
|
||||
beginning of each SQL statement.
|
||||
@ -7165,6 +7218,7 @@ bool add_to_list(THD *thd, SQL_I_List<ORDER> &list, Item *item,bool asc)
|
||||
order->free_me=0;
|
||||
order->used=0;
|
||||
order->counter_used= 0;
|
||||
order->fast_field_copier_setup= 0;
|
||||
list.link_in_list(order, &order->next);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -7210,7 +7264,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
if (!table)
|
||||
DBUG_RETURN(0); // End of memory
|
||||
alias_str= alias ? alias->str : table->table.str;
|
||||
if (!test(table_options & TL_OPTION_ALIAS) &&
|
||||
if (!MY_TEST(table_options & TL_OPTION_ALIAS) &&
|
||||
check_table_name(table->table.str, table->table.length, FALSE))
|
||||
{
|
||||
my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
|
||||
@ -7255,10 +7309,10 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
ptr->table_name=table->table.str;
|
||||
ptr->table_name_length=table->table.length;
|
||||
ptr->lock_type= lock_type;
|
||||
ptr->updating= test(table_options & TL_OPTION_UPDATING);
|
||||
ptr->updating= MY_TEST(table_options & TL_OPTION_UPDATING);
|
||||
/* TODO: remove TL_OPTION_FORCE_INDEX as it looks like it's not used */
|
||||
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
|
||||
ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
|
||||
ptr->force_index= MY_TEST(table_options & TL_OPTION_FORCE_INDEX);
|
||||
ptr->ignore_leaves= MY_TEST(table_options & TL_OPTION_IGNORE_LEAVES);
|
||||
ptr->derived= table->sel;
|
||||
if (!ptr->derived && is_infoschema_db(ptr->db, ptr->db_length))
|
||||
{
|
||||
@ -7292,7 +7346,11 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
ptr->schema_table= schema_table;
|
||||
}
|
||||
ptr->select_lex= lex->current_select;
|
||||
ptr->cacheable_table= 1;
|
||||
/*
|
||||
We can't cache internal temporary tables between prepares as the
|
||||
table may be deleted before next exection.
|
||||
*/
|
||||
ptr->cacheable_table= !table->is_derived_table();
|
||||
ptr->index_hints= index_hints_arg;
|
||||
ptr->option= option ? option->str : 0;
|
||||
/* check that used name is unique */
|
||||
@ -7349,7 +7407,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
lex->add_to_query_tables(ptr);
|
||||
|
||||
// Pure table aliases do not need to be locked:
|
||||
if (!test(table_options & TL_OPTION_ALIAS))
|
||||
if (!MY_TEST(table_options & TL_OPTION_ALIAS))
|
||||
{
|
||||
ptr->mdl_request.init(MDL_key::TABLE, ptr->db, ptr->table_name, mdl_type,
|
||||
MDL_TRANSACTION);
|
||||
@ -8515,6 +8573,11 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||
want_priv= lex->create_info.tmp_table() ? CREATE_TMP_ACL :
|
||||
(CREATE_ACL | (select_lex->item_list.elements ? INSERT_ACL : 0));
|
||||
|
||||
/* CREATE OR REPLACE on not temporary tables require DROP_ACL */
|
||||
if ((lex->create_info.options & HA_LEX_CREATE_REPLACE) &&
|
||||
!lex->create_info.tmp_table())
|
||||
want_priv|= DROP_ACL;
|
||||
|
||||
if (check_access(thd, want_priv, create_table->db,
|
||||
&create_table->grant.privilege,
|
||||
&create_table->grant.m_internal,
|
||||
@ -8551,8 +8614,8 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||
|
||||
- For temporary MERGE tables we do not track if their child tables are
|
||||
base or temporary. As result we can't guarantee that privilege check
|
||||
which was done in presence of temporary child will stay relevant later
|
||||
as this temporary table might be removed.
|
||||
which was done in presence of temporary child will stay relevant
|
||||
later as this temporary table might be removed.
|
||||
|
||||
If SELECT_ACL | UPDATE_ACL | DELETE_ACL privileges were not checked for
|
||||
the underlying *base* tables, it would create a security breach as in
|
||||
@ -8583,6 +8646,12 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||
}
|
||||
error= FALSE;
|
||||
|
||||
/*
|
||||
For CREATE TABLE we should not open the table even if it exists.
|
||||
If the table exists, we should either not create it or replace it
|
||||
*/
|
||||
lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
|
||||
|
||||
err:
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
Reference in New Issue
Block a user