1
0
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:
Nirbhay Choubey
2014-03-26 14:27:24 -04:00
2568 changed files with 69289 additions and 22937 deletions

View File

@ -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);
}