mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
10.0-monty merge
includes: * remove some remnants of "Bug#14521864: MYSQL 5.1 TO 5.5 BUGS PARTITIONING" * introduce LOCK_share, now LOCK_ha_data is strictly for engines * rea_create_table() always creates .par file (even in "frm-only" mode) * fix a 5.6 bug, temp file leak on dummy ALTER TABLE
This commit is contained in:
277
sql/sql_parse.cc
277
sql/sql_parse.cc
@ -24,7 +24,7 @@
|
||||
// set_handler_table_locks,
|
||||
// lock_global_read_lock,
|
||||
// make_global_read_lock_block_commit
|
||||
#include "sql_base.h" // find_temporary_tablesx
|
||||
#include "sql_base.h" // find_temporary_table
|
||||
#include "sql_cache.h" // QUERY_CACHE_FLAGS_SIZE, query_cache_*
|
||||
#include "sql_show.h" // mysqld_list_*, mysqld_show_*,
|
||||
// calc_sum_of_all_status
|
||||
@ -44,7 +44,6 @@
|
||||
#include "sql_table.h" // mysql_create_like_table,
|
||||
// mysql_create_table,
|
||||
// mysql_alter_table,
|
||||
// mysql_recreate_table,
|
||||
// mysql_backup_table,
|
||||
// mysql_restore_table
|
||||
#include "sql_reload.h" // reload_acl_and_cache
|
||||
@ -499,6 +498,7 @@ void init_update_queries(void)
|
||||
sql_command_flags[SQLCOM_SELECT]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_SET_OPTION]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_DO]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_HA_OPEN]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_CALL]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_CHECKSUM]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_ANALYZE]|= CF_PREOPEN_TMP_TABLES;
|
||||
@ -512,7 +512,7 @@ void init_update_queries(void)
|
||||
DDL statements that should start with closing opened handlers.
|
||||
|
||||
We use this flag only for statements for which open HANDLERs
|
||||
have to be closed before emporary tables are pre-opened.
|
||||
have to be closed before temporary tables are pre-opened.
|
||||
*/
|
||||
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_HA_CLOSE;
|
||||
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_HA_CLOSE;
|
||||
@ -888,7 +888,7 @@ bool do_command(THD *thd)
|
||||
Consider moving to init_connect() instead.
|
||||
*/
|
||||
thd->clear_error(); // Clear error message
|
||||
thd->stmt_da->reset_diagnostics_area();
|
||||
thd->get_stmt_da()->reset_diagnostics_area();
|
||||
|
||||
net_new_transaction(net);
|
||||
|
||||
@ -1158,7 +1158,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||
#endif
|
||||
case COM_CHANGE_USER:
|
||||
{
|
||||
bool rc;
|
||||
int auth_rc;
|
||||
status_var_increment(thd->status_var.com_other);
|
||||
|
||||
thd->change_user();
|
||||
@ -1189,13 +1189,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||
if (thd->failed_com_change_user >= 3)
|
||||
{
|
||||
my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
|
||||
rc= 1;
|
||||
auth_rc= 1;
|
||||
}
|
||||
else
|
||||
rc= acl_authenticate(thd, 0, packet_length);
|
||||
auth_rc= acl_authenticate(thd, 0, packet_length);
|
||||
|
||||
mysql_audit_notify_connection_change_user(thd);
|
||||
if (rc)
|
||||
if (auth_rc)
|
||||
{
|
||||
/* Free user if allocated by acl_authenticate */
|
||||
my_free(thd->security_ctx->user);
|
||||
@ -1294,8 +1294,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||
query_cache_end_of_result(thd);
|
||||
|
||||
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_STATUS,
|
||||
thd->stmt_da->is_error() ? thd->stmt_da->sql_errno()
|
||||
: 0, command_name[command].str);
|
||||
thd->get_stmt_da()->is_error()
|
||||
? thd->get_stmt_da()->sql_errno()
|
||||
: 0,
|
||||
command_name[command].str);
|
||||
|
||||
ulong length= (ulong)(packet_end - beginning_of_next_stmt);
|
||||
|
||||
@ -1331,10 +1333,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||
(char *) thd->security_ctx->host_or_ip);
|
||||
|
||||
/* PSI begin */
|
||||
thd->m_statement_psi=
|
||||
MYSQL_START_STATEMENT(&thd->m_statement_state,
|
||||
com_statement_info[command].m_key,
|
||||
thd->db, thd->db_length);
|
||||
thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
|
||||
com_statement_info[command].m_key,
|
||||
thd->db, thd->db_length,
|
||||
thd->charset());
|
||||
THD_STAGE_INFO(thd, stage_init);
|
||||
MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, beginning_of_next_stmt,
|
||||
length);
|
||||
@ -1427,6 +1429,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||
thd->set_query(fields, query_length);
|
||||
general_log_print(thd, command, "%s %s", table_list.table_name, fields);
|
||||
|
||||
if (open_temporary_tables(thd, &table_list))
|
||||
break;
|
||||
|
||||
if (check_table_access(thd, SELECT_ACL, &table_list,
|
||||
TRUE, UINT_MAX, FALSE))
|
||||
break;
|
||||
@ -1451,7 +1456,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||
/* We don't calculate statistics for this command */
|
||||
general_log_print(thd, command, NullS);
|
||||
net->error=0; // Don't give 'abort' message
|
||||
thd->stmt_da->disable_status(); // Don't send anything back
|
||||
thd->get_stmt_da()->disable_status(); // Don't send anything back
|
||||
error=TRUE; // End server
|
||||
break;
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
@ -1605,7 +1610,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||
#else
|
||||
(void) my_net_write(net, (uchar*) buff, length);
|
||||
(void) net_flush(net);
|
||||
thd->stmt_da->disable_status();
|
||||
thd->get_stmt_da()->disable_status();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -1681,7 +1686,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0);
|
||||
|
||||
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_STATUS,
|
||||
thd->stmt_da->is_error() ? thd->stmt_da->sql_errno() : 0,
|
||||
thd->get_stmt_da()->is_error() ?
|
||||
thd->get_stmt_da()->sql_errno() : 0,
|
||||
command_name[command].str);
|
||||
|
||||
thd->update_all_stats();
|
||||
@ -2057,7 +2063,7 @@ bool sp_process_definer(THD *thd)
|
||||
if (!is_acl_user(lex->definer->host.str, lex->definer->user.str))
|
||||
{
|
||||
push_warning_printf(thd,
|
||||
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_NO_SUCH_USER,
|
||||
ER(ER_NO_SUCH_USER),
|
||||
lex->definer->user.str,
|
||||
@ -2204,12 +2210,12 @@ mysql_execute_command(THD *thd)
|
||||
variables, but for now this is probably good enough.
|
||||
*/
|
||||
if ((sql_command_flags[lex->sql_command] & CF_DIAGNOSTIC_STMT) != 0)
|
||||
thd->warning_info->set_read_only(TRUE);
|
||||
thd->get_stmt_da()->set_warning_info_read_only(TRUE);
|
||||
else
|
||||
{
|
||||
thd->warning_info->set_read_only(FALSE);
|
||||
thd->get_stmt_da()->set_warning_info_read_only(FALSE);
|
||||
if (all_tables)
|
||||
thd->warning_info->opt_clear_warning_info(thd->query_id);
|
||||
thd->get_stmt_da()->opt_clear_warning_info(thd->query_id);
|
||||
}
|
||||
|
||||
#ifdef HAVE_REPLICATION
|
||||
@ -2405,6 +2411,31 @@ mysql_execute_command(THD *thd)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
Close tables open by HANDLERs before executing DDL statement
|
||||
which is going to affect those tables.
|
||||
|
||||
This should happen before temporary tables are pre-opened as
|
||||
otherwise we will get errors about attempt to re-open tables
|
||||
if table to be changed is open through HANDLER.
|
||||
|
||||
Note that even although this is done before any privilege
|
||||
checks there is no security problem here as closing open
|
||||
HANDLER doesn't require any privileges anyway.
|
||||
*/
|
||||
if (sql_command_flags[lex->sql_command] & CF_HA_CLOSE)
|
||||
mysql_ha_rm_tables(thd, all_tables);
|
||||
|
||||
/*
|
||||
Pre-open temporary tables to simplify privilege checking
|
||||
for statements which need this.
|
||||
*/
|
||||
if (sql_command_flags[lex->sql_command] & CF_PREOPEN_TMP_TABLES)
|
||||
{
|
||||
if (open_temporary_tables(thd, all_tables))
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (lex->sql_command) {
|
||||
|
||||
case SQLCOM_SHOW_EVENTS:
|
||||
@ -2412,13 +2443,6 @@ mysql_execute_command(THD *thd)
|
||||
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "embedded server");
|
||||
break;
|
||||
#endif
|
||||
case SQLCOM_SHOW_STATUS_PROC:
|
||||
case SQLCOM_SHOW_STATUS_FUNC:
|
||||
if ((res= check_table_access(thd, SELECT_ACL, all_tables, FALSE,
|
||||
UINT_MAX, FALSE)))
|
||||
goto error;
|
||||
res= execute_sqlcom_select(thd, all_tables);
|
||||
break;
|
||||
case SQLCOM_SHOW_STATUS:
|
||||
{
|
||||
execute_show_status(thd, all_tables);
|
||||
@ -2451,6 +2475,8 @@ mysql_execute_command(THD *thd)
|
||||
}
|
||||
/* no break; fall through */
|
||||
}
|
||||
case SQLCOM_SHOW_STATUS_PROC:
|
||||
case SQLCOM_SHOW_STATUS_FUNC:
|
||||
case SQLCOM_SHOW_DATABASES:
|
||||
case SQLCOM_SHOW_TABLES:
|
||||
case SQLCOM_SHOW_TRIGGERS:
|
||||
@ -2555,16 +2581,16 @@ case SQLCOM_PREPARE:
|
||||
case SQLCOM_SHOW_WARNS:
|
||||
{
|
||||
res= mysqld_show_warnings(thd, (ulong)
|
||||
((1L << (uint) MYSQL_ERROR::WARN_LEVEL_NOTE) |
|
||||
(1L << (uint) MYSQL_ERROR::WARN_LEVEL_WARN) |
|
||||
(1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR)
|
||||
((1L << (uint) Sql_condition::WARN_LEVEL_NOTE) |
|
||||
(1L << (uint) Sql_condition::WARN_LEVEL_WARN) |
|
||||
(1L << (uint) Sql_condition::WARN_LEVEL_ERROR)
|
||||
));
|
||||
break;
|
||||
}
|
||||
case SQLCOM_SHOW_ERRORS:
|
||||
{
|
||||
res= mysqld_show_warnings(thd, (ulong)
|
||||
(1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR));
|
||||
(1L << (uint) Sql_condition::WARN_LEVEL_ERROR));
|
||||
break;
|
||||
}
|
||||
case SQLCOM_SHOW_PROFILES:
|
||||
@ -2634,7 +2660,7 @@ case SQLCOM_PREPARE:
|
||||
mysql_mutex_lock(&LOCK_active_mi);
|
||||
|
||||
mi= master_info_index->get_master_info(&lex_mi->connection_name,
|
||||
MYSQL_ERROR::WARN_LEVEL_NOTE);
|
||||
Sql_condition::WARN_LEVEL_NOTE);
|
||||
|
||||
if (mi == NULL)
|
||||
{
|
||||
@ -2687,7 +2713,7 @@ case SQLCOM_PREPARE:
|
||||
LEX_MASTER_INFO *lex_mi= &thd->lex->mi;
|
||||
Master_info *mi;
|
||||
mi= master_info_index->get_master_info(&lex_mi->connection_name,
|
||||
MYSQL_ERROR::WARN_LEVEL_ERROR);
|
||||
Sql_condition::WARN_LEVEL_ERROR);
|
||||
if (mi != NULL)
|
||||
{
|
||||
res= show_master_info(thd, mi, 0);
|
||||
@ -2795,9 +2821,6 @@ case SQLCOM_PREPARE:
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Close any open handlers for the table. */
|
||||
mysql_ha_rm_tables(thd, create_table);
|
||||
|
||||
if (select_lex->item_list.elements) // With select
|
||||
{
|
||||
select_result *result;
|
||||
@ -2845,7 +2868,7 @@ case SQLCOM_PREPARE:
|
||||
*/
|
||||
if (splocal_refs != thd->query_name_consts)
|
||||
push_warning(thd,
|
||||
MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_UNKNOWN_ERROR,
|
||||
"Invoked routine ran a statement that may cause problems with "
|
||||
"binary log, see 'NAME_CONST issues' in 'Binary Logging of Stored Programs' "
|
||||
@ -2882,7 +2905,7 @@ case SQLCOM_PREPARE:
|
||||
{
|
||||
if (create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS)
|
||||
{
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_TABLE_EXISTS_ERROR,
|
||||
ER(ER_TABLE_EXISTS_ERROR),
|
||||
create_info.alias);
|
||||
@ -2992,7 +3015,7 @@ end_with_restore_list:
|
||||
|
||||
res= mysql_alter_table(thd, first_table->db, first_table->table_name,
|
||||
&create_info, first_table, &alter_info,
|
||||
0, (ORDER*) 0, 0, 0);
|
||||
0, (ORDER*) 0, 0);
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_REPLICATION
|
||||
@ -3008,7 +3031,7 @@ end_with_restore_list:
|
||||
|
||||
if ((mi= (master_info_index->
|
||||
get_master_info(&lex_mi->connection_name,
|
||||
MYSQL_ERROR::WARN_LEVEL_ERROR))))
|
||||
Sql_condition::WARN_LEVEL_ERROR))))
|
||||
{
|
||||
if (load_error)
|
||||
{
|
||||
@ -3061,7 +3084,7 @@ end_with_restore_list:
|
||||
mysql_mutex_lock(&LOCK_active_mi);
|
||||
if ((mi= (master_info_index->
|
||||
get_master_info(&lex_mi->connection_name,
|
||||
MYSQL_ERROR::WARN_LEVEL_ERROR))))
|
||||
Sql_condition::WARN_LEVEL_ERROR))))
|
||||
if (!stop_slave(thd, mi, 1/* net report*/))
|
||||
my_ok(thd);
|
||||
mysql_mutex_unlock(&LOCK_active_mi);
|
||||
@ -3151,6 +3174,13 @@ end_with_restore_list:
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Temporary tables should be opened for SHOW CREATE TABLE, but not
|
||||
for SHOW CREATE VIEW.
|
||||
*/
|
||||
if (open_temporary_tables(thd, all_tables))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
The fact that check_some_access() returned FALSE does not mean that
|
||||
access is granted. We need to check if first_table->grant.privilege
|
||||
@ -3329,6 +3359,18 @@ end_with_restore_list:
|
||||
case SQLCOM_INSERT:
|
||||
{
|
||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||
|
||||
/*
|
||||
Since INSERT DELAYED doesn't support temporary tables, we could
|
||||
not pre-open temporary tables for SQLCOM_INSERT / SQLCOM_REPLACE.
|
||||
Open them here instead.
|
||||
*/
|
||||
if (first_table->lock_type != TL_WRITE_DELAYED)
|
||||
{
|
||||
if ((res= open_temporary_tables(thd, all_tables)))
|
||||
break;
|
||||
}
|
||||
|
||||
if ((res= insert_precheck(thd, all_tables)))
|
||||
break;
|
||||
|
||||
@ -3668,6 +3710,19 @@ end_with_restore_list:
|
||||
thd->mdl_context.release_transactional_locks();
|
||||
if (res)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
Here we have to pre-open temporary tables for LOCK TABLES.
|
||||
|
||||
CF_PREOPEN_TMP_TABLES is not set for this SQL statement simply
|
||||
because LOCK TABLES calls close_thread_tables() as a first thing
|
||||
(it's called from unlock_locked_tables() above). So even if
|
||||
CF_PREOPEN_TMP_TABLES was set and the tables would be pre-opened
|
||||
in a usual way, they would have been closed.
|
||||
*/
|
||||
if (open_temporary_tables(thd, all_tables))
|
||||
goto error;
|
||||
|
||||
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
|
||||
FALSE, UINT_MAX, FALSE))
|
||||
goto error;
|
||||
@ -3970,7 +4025,7 @@ end_with_restore_list:
|
||||
goto error;
|
||||
if (specialflag & SPECIAL_NO_RESOLVE &&
|
||||
hostname_requires_resolving(user->host.str))
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_WARN_HOSTNAME_WONT_WORK,
|
||||
ER(ER_WARN_HOSTNAME_WONT_WORK));
|
||||
// Are we trying to change a password of another user
|
||||
@ -4169,6 +4224,9 @@ end_with_restore_list:
|
||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||
if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE))
|
||||
goto error;
|
||||
/* Close temporary tables which were pre-opened for privilege checking. */
|
||||
close_thread_tables(thd);
|
||||
all_tables->table= NULL;
|
||||
res= mysql_ha_open(thd, first_table, 0);
|
||||
break;
|
||||
case SQLCOM_HA_CLOSE:
|
||||
@ -4376,7 +4434,7 @@ end_with_restore_list:
|
||||
{
|
||||
if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
|
||||
lex->sql_command == SQLCOM_CREATE_PROCEDURE))
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_PROC_AUTO_GRANT_FAIL, ER(ER_PROC_AUTO_GRANT_FAIL));
|
||||
thd->clear_error();
|
||||
}
|
||||
@ -4581,7 +4639,7 @@ create_sp_error:
|
||||
{
|
||||
if (lex->check_exists)
|
||||
{
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
|
||||
"FUNCTION (UDF)", lex->spname->m_name.str);
|
||||
res= FALSE;
|
||||
@ -4634,7 +4692,7 @@ create_sp_error:
|
||||
sp_revoke_privileges(thd, db, name,
|
||||
lex->sql_command == SQLCOM_DROP_PROCEDURE))
|
||||
{
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_PROC_AUTO_REVOKE_FAIL,
|
||||
ER(ER_PROC_AUTO_REVOKE_FAIL));
|
||||
/* If this happens, an error should have been reported. */
|
||||
@ -4651,7 +4709,7 @@ create_sp_error:
|
||||
if (lex->check_exists)
|
||||
{
|
||||
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
|
||||
SP_COM_STRING(lex), lex->spname->m_qname.str);
|
||||
if (!res)
|
||||
@ -4889,10 +4947,12 @@ create_sp_error:
|
||||
/* fall through */
|
||||
case SQLCOM_SIGNAL:
|
||||
case SQLCOM_RESIGNAL:
|
||||
DBUG_ASSERT(lex->m_stmt != NULL);
|
||||
res= lex->m_stmt->execute(thd);
|
||||
case SQLCOM_GET_DIAGNOSTICS:
|
||||
DBUG_ASSERT(lex->m_sql_cmd != NULL);
|
||||
res= lex->m_sql_cmd->execute(thd);
|
||||
break;
|
||||
default:
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
DBUG_ASSERT(0); /* Impossible */
|
||||
#endif
|
||||
@ -4934,7 +4994,7 @@ finish:
|
||||
if (thd->killed_errno())
|
||||
{
|
||||
/* If we already sent 'ok', we can ignore any kill query statements */
|
||||
if (! thd->stmt_da->is_set())
|
||||
if (! thd->get_stmt_da()->is_set())
|
||||
thd->send_kill_message();
|
||||
}
|
||||
if (thd->killed < KILL_CONNECTION)
|
||||
@ -4948,9 +5008,9 @@ finish:
|
||||
else
|
||||
{
|
||||
/* If commit fails, we should be able to reset the OK status. */
|
||||
thd->stmt_da->can_overwrite_status= TRUE;
|
||||
thd->get_stmt_da()->set_overwrite_status(true);
|
||||
trans_commit_stmt(thd);
|
||||
thd->stmt_da->can_overwrite_status= FALSE;
|
||||
thd->get_stmt_da()->set_overwrite_status(false);
|
||||
}
|
||||
#ifdef WITH_ARIA_STORAGE_ENGINE
|
||||
ha_maria::implicit_commit(thd, FALSE);
|
||||
@ -4977,10 +5037,10 @@ 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->stmt_da->can_overwrite_status= TRUE;
|
||||
thd->get_stmt_da()->set_overwrite_status(true);
|
||||
/* Commit the normal transaction if one is active. */
|
||||
trans_commit_implicit(thd);
|
||||
thd->stmt_da->can_overwrite_status= FALSE;
|
||||
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())
|
||||
@ -5046,7 +5106,7 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
|
||||
mysqld_show_warnings().
|
||||
*/
|
||||
thd->lex->unit.print(&str, QT_TO_SYSTEM_CHARSET);
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_YES, str.c_ptr_safe());
|
||||
}
|
||||
if (res)
|
||||
@ -5504,6 +5564,12 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
|
||||
|
||||
DBUG_ASSERT(dst_table);
|
||||
|
||||
/*
|
||||
Open temporary tables to be able to detect them during privilege check.
|
||||
*/
|
||||
if (open_temporary_tables(thd, dst_table))
|
||||
return TRUE;
|
||||
|
||||
if (check_access(thd, SELECT_ACL, dst_table->db,
|
||||
&dst_table->grant.privilege,
|
||||
&dst_table->grant.m_internal,
|
||||
@ -5517,6 +5583,9 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
|
||||
if (check_grant(thd, SELECT_ACL, dst_table, TRUE, UINT_MAX, FALSE))
|
||||
return TRUE; /* Access denied */
|
||||
|
||||
close_thread_tables(thd);
|
||||
dst_table->table= NULL;
|
||||
|
||||
/* Access granted */
|
||||
return FALSE;
|
||||
}
|
||||
@ -5602,10 +5671,10 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
|
||||
|
||||
DBUG_PRINT("info", ("derived: %d view: %d", tables->derived != 0,
|
||||
tables->view != 0));
|
||||
if (tables->is_anonymous_derived_table() ||
|
||||
(tables->table && tables->table->s &&
|
||||
(int)tables->table->s->tmp_table))
|
||||
|
||||
if (tables->is_anonymous_derived_table())
|
||||
continue;
|
||||
|
||||
thd->security_ctx= sctx;
|
||||
|
||||
if (check_access(thd, want_access, tables->get_db_name(),
|
||||
@ -5811,7 +5880,7 @@ bool check_stack_overrun(THD *thd, long margin,
|
||||
return 1;
|
||||
}
|
||||
#ifndef DBUG_OFF
|
||||
max_stack_used= max(max_stack_used, stack_used);
|
||||
max_stack_used= MY_MAX(max_stack_used, stack_used);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -5879,7 +5948,6 @@ void THD::reset_for_next_command(bool calculate_userstat)
|
||||
DBUG_ENTER("mysql_reset_thd_for_next_command");
|
||||
DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */
|
||||
DBUG_ASSERT(! thd->in_sub_stmt);
|
||||
DBUG_ASSERT(thd->transaction.on);
|
||||
thd->free_list= 0;
|
||||
thd->select_number= 1;
|
||||
/*
|
||||
@ -5916,8 +5984,8 @@ void THD::reset_for_next_command(bool calculate_userstat)
|
||||
thd->user_var_events_alloc= thd->mem_root;
|
||||
}
|
||||
thd->clear_error();
|
||||
thd->stmt_da->reset_diagnostics_area();
|
||||
thd->warning_info->reset_for_next_command();
|
||||
thd->get_stmt_da()->reset_diagnostics_area();
|
||||
thd->get_stmt_da()->reset_for_next_command();
|
||||
thd->rand_used= 0;
|
||||
thd->m_sent_row_count= thd->m_examined_row_count= 0;
|
||||
thd->accessed_rows_and_keys= 0;
|
||||
@ -6144,7 +6212,7 @@ void mysql_parse(THD *thd, char *rawbuf, uint length,
|
||||
{
|
||||
LEX *lex= thd->lex;
|
||||
|
||||
bool err= parse_sql(thd, parser_state, NULL);
|
||||
bool err= parse_sql(thd, parser_state, NULL, true);
|
||||
|
||||
if (!err)
|
||||
{
|
||||
@ -6252,7 +6320,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *rawbuf, uint length)
|
||||
lex_start(thd);
|
||||
mysql_reset_thd_for_next_command(thd, opt_userstat_running);
|
||||
|
||||
if (!parse_sql(thd, & parser_state, NULL) &&
|
||||
if (!parse_sql(thd, & parser_state, NULL, true) &&
|
||||
all_tables_not_ok(thd, lex->select_lex.table_list.first))
|
||||
error= 1; /* Ignore question */
|
||||
thd->end_statement();
|
||||
@ -6442,6 +6510,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
thr_lock_type lock_type,
|
||||
enum_mdl_type mdl_type,
|
||||
List<Index_hint> *index_hints_arg,
|
||||
List<String> *partition_names,
|
||||
LEX_STRING *option)
|
||||
{
|
||||
register TABLE_LIST *ptr;
|
||||
@ -6586,6 +6655,9 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
*/
|
||||
table_list.link_in_list(ptr, &ptr->next_local);
|
||||
ptr->next_name_resolution_table= NULL;
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
ptr->partition_names= partition_names;
|
||||
#endif /* WITH_PARTITION_STORAGE_ENGINE */
|
||||
/* Link table in global list (all used tables) */
|
||||
lex->add_to_query_tables(ptr);
|
||||
|
||||
@ -7291,7 +7363,7 @@ bool check_simple_select()
|
||||
char command[80];
|
||||
Lex_input_stream *lip= & thd->m_parser_state->m_lip;
|
||||
strmake(command, lip->yylval->symbol.str,
|
||||
min(lip->yylval->symbol.length, sizeof(command)-1));
|
||||
MY_MIN(lip->yylval->symbol.length, sizeof(command)-1));
|
||||
my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command);
|
||||
return 1;
|
||||
}
|
||||
@ -7464,6 +7536,19 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
|
||||
TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
|
||||
DBUG_ENTER("multi_delete_precheck");
|
||||
|
||||
/*
|
||||
Temporary tables are pre-opened in 'tables' list only. Here we need to
|
||||
initialize TABLE instances in 'aux_tables' list.
|
||||
*/
|
||||
for (TABLE_LIST *tl= aux_tables; tl; tl= tl->next_global)
|
||||
{
|
||||
if (tl->table)
|
||||
continue;
|
||||
|
||||
if (tl->correspondent_table)
|
||||
tl->table= tl->correspondent_table->table;
|
||||
}
|
||||
|
||||
/* sql_yacc guarantees that tables and aux_tables are not zero */
|
||||
DBUG_ASSERT(aux_tables != 0);
|
||||
if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE))
|
||||
@ -7732,9 +7817,9 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||
CREATE TABLE ... SELECT, also require INSERT.
|
||||
*/
|
||||
|
||||
want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
|
||||
CREATE_TMP_ACL : CREATE_ACL) |
|
||||
(select_lex->item_list.elements ? INSERT_ACL : 0);
|
||||
want_priv= (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
|
||||
CREATE_TMP_ACL :
|
||||
(CREATE_ACL | (select_lex->item_list.elements ? INSERT_ACL : 0));
|
||||
|
||||
if (check_access(thd, want_priv, create_table->db,
|
||||
&create_table->grant.privilege,
|
||||
@ -7743,11 +7828,48 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||
goto err;
|
||||
|
||||
/* If it is a merge table, check privileges for merge children. */
|
||||
if (lex->create_info.merge_list.first &&
|
||||
check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
|
||||
lex->create_info.merge_list.first,
|
||||
FALSE, UINT_MAX, FALSE))
|
||||
goto err;
|
||||
if (lex->create_info.merge_list.first)
|
||||
{
|
||||
/*
|
||||
The user must have (SELECT_ACL | UPDATE_ACL | DELETE_ACL) on the
|
||||
underlying base tables, even if there are temporary tables with the same
|
||||
names.
|
||||
|
||||
From user's point of view, it might look as if the user must have these
|
||||
privileges on temporary tables to create a merge table over them. This is
|
||||
one of two cases when a set of privileges is required for operations on
|
||||
temporary tables (see also CREATE TABLE).
|
||||
|
||||
The reason for this behavior stems from the following facts:
|
||||
|
||||
- For merge tables, the underlying table privileges are checked only
|
||||
at CREATE TABLE / ALTER TABLE time.
|
||||
|
||||
In other words, once a merge table is created, the privileges of
|
||||
the underlying tables can be revoked, but the user will still have
|
||||
access to the merge table (provided that the user has privileges on
|
||||
the merge table itself).
|
||||
|
||||
- Temporary tables shadow base tables.
|
||||
|
||||
I.e. there might be temporary and base tables with the same name, and
|
||||
the temporary table takes the precedence in all operations.
|
||||
|
||||
- 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.
|
||||
|
||||
If SELECT_ACL | UPDATE_ACL | DELETE_ACL privileges were not checked for
|
||||
the underlying *base* tables, it would create a security breach as in
|
||||
Bug#12771903.
|
||||
*/
|
||||
|
||||
if (check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
|
||||
lex->create_info.merge_list.first,
|
||||
FALSE, UINT_MAX, FALSE))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (want_priv != CREATE_TMP_ACL &&
|
||||
check_grant(thd, want_priv, create_table, FALSE, 1, FALSE))
|
||||
@ -8105,14 +8227,13 @@ extern int MYSQLparse(void *thd); // from sql_yacc.cc
|
||||
@retval TRUE on parsing error.
|
||||
*/
|
||||
|
||||
bool parse_sql(THD *thd,
|
||||
Parser_state *parser_state,
|
||||
Object_creation_ctx *creation_ctx)
|
||||
bool parse_sql(THD *thd, Parser_state *parser_state,
|
||||
Object_creation_ctx *creation_ctx, bool do_pfs_digest)
|
||||
{
|
||||
bool ret_value;
|
||||
DBUG_ENTER("parse_sql");
|
||||
DBUG_ASSERT(thd->m_parser_state == NULL);
|
||||
DBUG_ASSERT(thd->lex->m_stmt == NULL);
|
||||
DBUG_ASSERT(thd->lex->m_sql_cmd == NULL);
|
||||
|
||||
MYSQL_QUERY_PARSE_START(thd->query());
|
||||
/* Backup creation context. */
|
||||
@ -8129,7 +8250,7 @@ bool parse_sql(THD *thd,
|
||||
#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE
|
||||
/* Start Digest */
|
||||
thd->m_parser_state->m_lip.m_digest_psi=
|
||||
MYSQL_DIGEST_START(thd->m_statement_psi);
|
||||
MYSQL_DIGEST_START(do_pfs_digest ? thd->m_statement_psi : NULL);
|
||||
#endif
|
||||
|
||||
/* Parse the query. */
|
||||
|
Reference in New Issue
Block a user