summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc1552
1 files changed, 805 insertions, 747 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index d6bbefc3be7..0e17370e93c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -15,7 +15,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#define MYSQL_LEX 1
-#include <my_global.h>
+#include "mariadb.h"
#include "sql_priv.h"
#include "sql_parse.h" // sql_kill, *_precheck, *_prepare
#include "lock.h" // try_transactional_lock,
@@ -82,7 +82,6 @@
#include <m_ctype.h>
#include <myisam.h>
#include <my_dir.h>
-#include "rpl_handler.h"
#include "rpl_mi.h"
#include "sql_digest.h"
@@ -99,8 +98,8 @@
#include "debug_sync.h"
#include "probes_mysql.h"
#include "set_var.h"
-#include "log_slow.h"
#include "sql_bootstrap.h"
+#include "sql_sequence.h"
#include "my_json_writer.h"
@@ -123,14 +122,6 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
@{
*/
-/* Used in error handling only */
-#define SP_COM_STRING(LP) \
- ((LP)->sql_command == SQLCOM_CREATE_SPFUNCTION || \
- (LP)->sql_command == SQLCOM_ALTER_FUNCTION || \
- (LP)->sql_command == SQLCOM_SHOW_CREATE_FUNC || \
- (LP)->sql_command == SQLCOM_DROP_FUNCTION ? \
- "FUNCTION" : "PROCEDURE")
-
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
static void sql_kill(THD *thd, longlong id, killed_state state, killed_type type);
static void sql_kill_user(THD *thd, LEX_USER *user, killed_state state);
@@ -140,39 +131,39 @@ static bool check_rename_table(THD *, TABLE_LIST *, TABLE_LIST *);
const char *any_db="*any*"; // Special symbol for check_access
-const LEX_STRING command_name[257]={
- { C_STRING_WITH_LEN("Sleep") }, //0
- { C_STRING_WITH_LEN("Quit") }, //1
- { C_STRING_WITH_LEN("Init DB") }, //2
- { C_STRING_WITH_LEN("Query") }, //3
- { C_STRING_WITH_LEN("Field List") }, //4
- { C_STRING_WITH_LEN("Create DB") }, //5
- { C_STRING_WITH_LEN("Drop DB") }, //6
- { C_STRING_WITH_LEN("Refresh") }, //7
- { C_STRING_WITH_LEN("Shutdown") }, //8
- { C_STRING_WITH_LEN("Statistics") }, //9
- { C_STRING_WITH_LEN("Processlist") }, //10
- { C_STRING_WITH_LEN("Connect") }, //11
- { C_STRING_WITH_LEN("Kill") }, //12
- { C_STRING_WITH_LEN("Debug") }, //13
- { C_STRING_WITH_LEN("Ping") }, //14
- { C_STRING_WITH_LEN("Time") }, //15
- { C_STRING_WITH_LEN("Delayed insert") }, //16
- { C_STRING_WITH_LEN("Change user") }, //17
- { C_STRING_WITH_LEN("Binlog Dump") }, //18
- { C_STRING_WITH_LEN("Table Dump") }, //19
- { C_STRING_WITH_LEN("Connect Out") }, //20
- { C_STRING_WITH_LEN("Register Slave") }, //21
- { C_STRING_WITH_LEN("Prepare") }, //22
- { C_STRING_WITH_LEN("Execute") }, //23
- { C_STRING_WITH_LEN("Long Data") }, //24
- { C_STRING_WITH_LEN("Close stmt") }, //25
- { C_STRING_WITH_LEN("Reset stmt") }, //26
- { C_STRING_WITH_LEN("Set option") }, //27
- { C_STRING_WITH_LEN("Fetch") }, //28
- { C_STRING_WITH_LEN("Daemon") }, //29
- { C_STRING_WITH_LEN("Unimpl get tid") }, //30
- { C_STRING_WITH_LEN("Reset connection") },//31
+const LEX_CSTRING command_name[257]={
+ { STRING_WITH_LEN("Sleep") }, //0
+ { STRING_WITH_LEN("Quit") }, //1
+ { STRING_WITH_LEN("Init DB") }, //2
+ { STRING_WITH_LEN("Query") }, //3
+ { STRING_WITH_LEN("Field List") }, //4
+ { STRING_WITH_LEN("Create DB") }, //5
+ { STRING_WITH_LEN("Drop DB") }, //6
+ { STRING_WITH_LEN("Refresh") }, //7
+ { STRING_WITH_LEN("Shutdown") }, //8
+ { STRING_WITH_LEN("Statistics") }, //9
+ { STRING_WITH_LEN("Processlist") }, //10
+ { STRING_WITH_LEN("Connect") }, //11
+ { STRING_WITH_LEN("Kill") }, //12
+ { STRING_WITH_LEN("Debug") }, //13
+ { STRING_WITH_LEN("Ping") }, //14
+ { STRING_WITH_LEN("Time") }, //15
+ { STRING_WITH_LEN("Delayed insert") }, //16
+ { STRING_WITH_LEN("Change user") }, //17
+ { STRING_WITH_LEN("Binlog Dump") }, //18
+ { STRING_WITH_LEN("Table Dump") }, //19
+ { STRING_WITH_LEN("Connect Out") }, //20
+ { STRING_WITH_LEN("Register Slave") }, //21
+ { STRING_WITH_LEN("Prepare") }, //22
+ { STRING_WITH_LEN("Execute") }, //23
+ { STRING_WITH_LEN("Long Data") }, //24
+ { STRING_WITH_LEN("Close stmt") }, //25
+ { STRING_WITH_LEN("Reset stmt") }, //26
+ { STRING_WITH_LEN("Set option") }, //27
+ { STRING_WITH_LEN("Fetch") }, //28
+ { STRING_WITH_LEN("Daemon") }, //29
+ { STRING_WITH_LEN("Unimpl get tid") }, //30
+ { STRING_WITH_LEN("Reset connection") },//31
{ 0, 0 }, //32
{ 0, 0 }, //33
{ 0, 0 }, //34
@@ -391,12 +382,12 @@ const LEX_STRING command_name[257]={
{ 0, 0 }, //247
{ 0, 0 }, //248
{ 0, 0 }, //249
- { C_STRING_WITH_LEN("Bulk_execute") }, //250
- { C_STRING_WITH_LEN("Slave_worker") }, //251
- { C_STRING_WITH_LEN("Slave_IO") }, //252
- { C_STRING_WITH_LEN("Slave_SQL") }, //253
- { C_STRING_WITH_LEN("Com_multi") }, //254
- { C_STRING_WITH_LEN("Error") } // Last command number 255
+ { STRING_WITH_LEN("Bulk_execute") }, //250
+ { STRING_WITH_LEN("Slave_worker") }, //251
+ { STRING_WITH_LEN("Slave_IO") }, //252
+ { STRING_WITH_LEN("Slave_SQL") }, //253
+ { STRING_WITH_LEN("Com_multi") }, //254
+ { STRING_WITH_LEN("Error") } // Last command number 255
};
const char *xa_state_names[]={
@@ -411,7 +402,7 @@ inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
{
Rpl_filter *rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
return rpl_filter->is_on() && tables && !thd->spcont &&
- !rpl_filter->tables_ok(thd->db, tables);
+ !rpl_filter->tables_ok(thd->db.str, tables);
}
#endif
@@ -420,7 +411,7 @@ static bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables)
{
for (TABLE_LIST *table= tables; table; table= table->next_global)
{
- DBUG_ASSERT(table->db && table->table_name);
+ DBUG_ASSERT(table->db.str && table->table_name.str);
if (table->updating && !thd->find_tmp_table_share(table))
return 1;
}
@@ -448,14 +439,17 @@ bool stmt_causes_implicit_commit(THD *thd, uint mask)
switch (lex->sql_command) {
case SQLCOM_DROP_TABLE:
+ case SQLCOM_DROP_SEQUENCE:
skip= (lex->tmp_table() ||
(thd->variables.option_bits & OPTION_GTID_BEGIN));
break;
case SQLCOM_ALTER_TABLE:
+ case SQLCOM_ALTER_SEQUENCE:
/* If ALTER TABLE of non-temporary table, do implicit commit */
skip= (lex->tmp_table());
break;
case SQLCOM_CREATE_TABLE:
+ case SQLCOM_CREATE_SEQUENCE:
/*
If CREATE TABLE of non-temporary table and the table is not part
if a BEGIN GTID ... COMMIT group, do a implicit commit.
@@ -544,24 +538,36 @@ void init_update_queries(void)
*/
sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS |
- CF_CAN_GENERATE_ROW_EVENTS;
+ CF_CAN_GENERATE_ROW_EVENTS |
+ CF_SCHEMA_CHANGE;
+ sql_command_flags[SQLCOM_CREATE_SEQUENCE]= (CF_CHANGES_DATA |
+ CF_REEXECUTION_FRAGILE |
+ CF_AUTO_COMMIT_TRANS |
+ CF_SCHEMA_CHANGE);
sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS |
- CF_REPORT_PROGRESS | CF_ADMIN_COMMAND;
+ CF_ADMIN_COMMAND | CF_REPORT_PROGRESS;
sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS |
CF_INSERTS_DATA | CF_ADMIN_COMMAND;
+ sql_command_flags[SQLCOM_ALTER_SEQUENCE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
+ CF_AUTO_COMMIT_TRANS | CF_SCHEMA_CHANGE |
+ CF_ADMIN_COMMAND;
sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_SCHEMA_CHANGE;
+ sql_command_flags[SQLCOM_DROP_SEQUENCE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_SCHEMA_CHANGE;
sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS | CF_REPORT_PROGRESS |
CF_INSERTS_DATA;
- sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_DB_CHANGE;
+ sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_DB_CHANGE;
+ sql_command_flags[SQLCOM_CREATE_PACKAGE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_DROP_PACKAGE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_CREATE_PACKAGE_BODY]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_DROP_PACKAGE_BODY]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_ALTER_DB_UPGRADE]= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_ALTER_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_RENAME_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS |
- CF_ADMIN_COMMAND;
+ sql_command_flags[SQLCOM_ALTER_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_DB_CHANGE;
+ sql_command_flags[SQLCOM_RENAME_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_ADMIN_COMMAND;
sql_command_flags[SQLCOM_DROP_INDEX]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS |
CF_REPORT_PROGRESS | CF_ADMIN_COMMAND;
sql_command_flags[SQLCOM_CREATE_VIEW]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
@@ -603,7 +609,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
- CF_CAN_BE_EXPLAINED;;
+ CF_CAN_BE_EXPLAINED;
sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
@@ -635,6 +641,8 @@ void init_update_queries(void)
CF_OPTIMIZER_TRACE; // (1)
sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SHOW_STATUS_PACKAGE]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
+ sql_command_flags[SQLCOM_SHOW_STATUS_PACKAGE_BODY]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_SHOW_DATABASES]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_SHOW_TRIGGERS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
@@ -669,10 +677,13 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_SHOW_SLAVE_STAT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_CREATE_PACKAGE]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_CREATE_PACKAGE_BODY]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
sql_command_flags[SQLCOM_SHOW_PROC_CODE]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_FUNC_CODE]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_PACKAGE_BODY_CODE]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_PROFILES]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_PROFILE]= CF_STATUS_COMMAND;
@@ -728,6 +739,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_TRUNCATE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
/* We don't want to replicate DROP for temp tables in row format */
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
+ sql_command_flags[SQLCOM_DROP_SEQUENCE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
/* We don't want to replicate CREATE/DROP INDEX for temp tables in row format */
sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
sql_command_flags[SQLCOM_DROP_INDEX]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
@@ -809,7 +821,9 @@ void init_update_queries(void)
have to be closed before temporary tables are pre-opened.
*/
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_HA_CLOSE;
+ sql_command_flags[SQLCOM_CREATE_SEQUENCE]|= CF_HA_CLOSE;
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_HA_CLOSE;
+ sql_command_flags[SQLCOM_DROP_SEQUENCE]|= CF_HA_CLOSE;
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_HA_CLOSE;
sql_command_flags[SQLCOM_TRUNCATE]|= CF_HA_CLOSE;
sql_command_flags[SQLCOM_REPAIR]|= CF_HA_CLOSE;
@@ -827,13 +841,19 @@ void init_update_queries(void)
even temporary table DDL should be disallowed.
*/
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_DISALLOW_IN_RO_TRANS;
+ sql_command_flags[SQLCOM_CREATE_SEQUENCE]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_DISALLOW_IN_RO_TRANS;
+ sql_command_flags[SQLCOM_DROP_SEQUENCE]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_RENAME_TABLE]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_DROP_INDEX]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_CREATE_DB]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_DROP_DB]|= CF_DISALLOW_IN_RO_TRANS;
+ sql_command_flags[SQLCOM_CREATE_PACKAGE]|= CF_DISALLOW_IN_RO_TRANS;
+ sql_command_flags[SQLCOM_DROP_PACKAGE]|= CF_DISALLOW_IN_RO_TRANS;
+ sql_command_flags[SQLCOM_CREATE_PACKAGE_BODY]|= CF_DISALLOW_IN_RO_TRANS;
+ sql_command_flags[SQLCOM_DROP_PACKAGE_BODY]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_ALTER_DB_UPGRADE]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_ALTER_DB]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_CREATE_VIEW]|= CF_DISALLOW_IN_RO_TRANS;
@@ -928,7 +948,7 @@ void execute_init_command(THD *thd, LEX_STRING *init_command,
save_vio= thd->net.vio;
thd->net.vio= 0;
thd->clear_error(1);
- dispatch_command(COM_QUERY, thd, buf, len, FALSE, FALSE);
+ dispatch_command(COM_QUERY, thd, buf, (uint)len, FALSE, FALSE);
thd->client_capabilities= save_client_capabilities;
thd->net.vio= save_vio;
@@ -941,8 +961,8 @@ void execute_init_command(THD *thd, LEX_STRING *init_command,
static char *fgets_fn(char *buffer, size_t size, fgets_input_t input, int *error)
{
MYSQL_FILE *in= static_cast<MYSQL_FILE*> (input);
- char *line= mysql_file_fgets(buffer, size, in);
- if (error)
+ char *line= mysql_file_fgets(buffer, (int)size, in);
+ if (unlikely(error))
*error= (line == NULL) ? ferror(in->m_file) : 0;
return line;
}
@@ -1020,7 +1040,7 @@ static void handle_bootstrap_impl(THD *thd)
}
query= (char *) thd->memdup_w_gap(buffer, length + 1,
- thd->db_length + 1 +
+ thd->db.length + 1 +
QUERY_CACHE_DB_LENGTH_SIZE +
QUERY_CACHE_FLAGS_SIZE);
size_t db_len= 0;
@@ -1056,7 +1076,7 @@ static void handle_bootstrap_impl(THD *thd)
#endif
delete_explain_query(thd->lex);
- if (bootstrap_error)
+ if (unlikely(bootstrap_error))
break;
thd->reset_kill_query(); /* Ensure that killed_errmsg is released */
@@ -1166,15 +1186,10 @@ static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables)
for (const TABLE_LIST *table= tables; table; table= table->next_global)
{
TABLE_CATEGORY c;
- LEX_STRING db, tn;
- lex_string_set(&db, table->db);
- lex_string_set(&tn, table->table_name);
+ LEX_CSTRING db= table->db, tn= table->table_name;
c= get_table_category(&db, &tn);
- if (c != TABLE_CATEGORY_INFORMATION &&
- c != TABLE_CATEGORY_PERFORMANCE)
- {
+ if (c != TABLE_CATEGORY_INFORMATION && c != TABLE_CATEGORY_PERFORMANCE)
return false;
- }
}
return true;
}
@@ -1231,8 +1246,8 @@ bool do_command(THD *thd)
the client, the connection is closed or "net_wait_timeout"
number of seconds has passed.
*/
- if(!thd->skip_wait_timeout)
- my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
+ if (!thd->skip_wait_timeout)
+ my_net_set_read_timeout(net, thd->get_net_wait_timeout());
/* Errors and diagnostics are cleared once here before query */
thd->clear_error(1);
@@ -1283,7 +1298,7 @@ bool do_command(THD *thd)
}
#endif /* WITH_WSREP */
- if (packet_length == packet_error)
+ if (unlikely(packet_length == packet_error))
{
DBUG_PRINT("info",("Got error %d reading command from socket %s",
net->error,
@@ -1295,7 +1310,8 @@ bool do_command(THD *thd)
mysql_mutex_lock(&thd->LOCK_thd_data);
if (thd->wsrep_conflict_state == MUST_ABORT)
{
- DBUG_PRINT("wsrep",("aborted for wsrep rollback: %lu", thd->real_id));
+ DBUG_PRINT("wsrep",("aborted for wsrep rollback: %lu",
+ (ulong) thd->real_id));
wsrep_client_rollback(thd);
}
mysql_mutex_unlock(&thd->LOCK_thd_data);
@@ -1431,7 +1447,7 @@ out:
This is a helper function to mysql_execute_command.
- @note SQLCOM_MULTI_UPDATE is an exception and delt with elsewhere.
+ @note SQLCOM_MULTI_UPDATE is an exception and dealt with elsewhere.
@see mysql_execute_command
@returns Status code
@@ -1448,9 +1464,12 @@ static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables)
LEX *lex= thd->lex;
- if (thd->security_ctx->master_access & SUPER_ACL)
+ /* Super user is allowed to do changes */
+ if (((ulong)(thd->security_ctx->master_access & SUPER_ACL) ==
+ (ulong)SUPER_ACL))
DBUG_RETURN(FALSE);
+ /* Check if command doesn't update anything */
if (!(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA))
DBUG_RETURN(FALSE);
@@ -1458,11 +1477,6 @@ static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables)
if (lex->sql_command == SQLCOM_UPDATE_MULTI)
DBUG_RETURN(FALSE);
- if (lex->sql_command == SQLCOM_CREATE_DB ||
- lex->sql_command == SQLCOM_ALTER_DB ||
- lex->sql_command == SQLCOM_DROP_DB)
- DBUG_RETURN(TRUE);
-
/*
a table-to-be-created is not in the temp table list yet,
so CREATE TABLE needs a special treatment
@@ -1477,8 +1491,15 @@ static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables)
if (lex->sql_command == SQLCOM_DROP_TABLE && lex->tmp_table())
DBUG_RETURN(FALSE);
- /* Now, check thd->temporary_tables list */
- DBUG_RETURN(some_non_temp_table_to_be_updated(thd, all_tables));
+ /* Check if we created, dropped, or renamed a database */
+ if ((sql_command_flags[lex->sql_command] & CF_DB_CHANGE))
+ DBUG_RETURN(TRUE);
+
+ if (some_non_temp_table_to_be_updated(thd, all_tables))
+ DBUG_RETURN(TRUE);
+
+ /* Assuming that only temporary tables are modified. */
+ DBUG_RETURN(FALSE);
}
@@ -1493,7 +1514,7 @@ static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables)
@retval # - Number of commands in the batch
*/
-uint maria_multi_check(THD *thd, char *packet, uint packet_length)
+uint maria_multi_check(THD *thd, char *packet, size_t packet_length)
{
uint counter= 0;
DBUG_ENTER("maria_multi_check");
@@ -1560,9 +1581,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
"<?>")));
bool drop_more_results= 0;
- if (!is_com_multi)
- inc_thread_running();
-
/* keep it withing 1 byte */
compile_time_assert(COM_END == 255);
@@ -1610,12 +1628,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
DBUG_EXECUTE_IF("crash_dispatch_command_before",
{ DBUG_PRINT("crash_dispatch_command_before", ("now"));
- DBUG_ABORT(); });
+ DBUG_SUICIDE(); });
/* Performance Schema Interface instrumentation, begin */
thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi,
com_statement_info[command].
m_key);
+ /*
+ We should always call reset_for_next_command() before a query.
+ mysql_parse() will do this for queries. Ensure it's also done
+ for other commands.
+ */
+ if (command != COM_QUERY)
+ thd->reset_for_next_command();
thd->set_command(command);
thd->enable_slow_log= true;
@@ -1665,14 +1690,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
switch (command) {
case COM_INIT_DB:
{
- LEX_STRING tmp;
+ LEX_CSTRING tmp;
status_var_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB]);
- if (thd->copy_with_error(system_charset_info, &tmp,
- thd->charset(), packet, packet_length))
+ if (unlikely(thd->copy_with_error(system_charset_info, (LEX_STRING*) &tmp,
+ thd->charset(), packet, packet_length)))
break;
if (!mysql_change_db(thd, &tmp, FALSE))
{
- general_log_write(thd, command, thd->db, thd->db_length);
+ general_log_write(thd, command, thd->db.str, thd->db.length);
my_ok(thd);
}
break;
@@ -1708,8 +1733,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* acl_authenticate() takes the data from net->read_pos */
net->read_pos= (uchar*)packet;
- uint save_db_length= thd->db_length;
- char *save_db= thd->db;
+ LEX_CSTRING save_db= thd->db;
USER_CONN *save_user_connect= thd->user_connect;
Security_context save_security_ctx= *thd->security_ctx;
CHARSET_INFO *save_character_set_client=
@@ -1740,12 +1764,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (auth_rc)
{
/* Free user if allocated by acl_authenticate */
- my_free(thd->security_ctx->user);
+ my_free(const_cast<char*>(thd->security_ctx->user));
*thd->security_ctx= save_security_ctx;
if (thd->user_connect)
decrease_user_connections(thd->user_connect);
thd->user_connect= save_user_connect;
- thd->reset_db(save_db, save_db_length);
+ thd->reset_db(&save_db);
thd->update_charset(save_character_set_client, save_collation_connection,
save_character_set_results);
thd->failed_com_change_user++;
@@ -1758,8 +1782,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (save_user_connect)
decrease_user_connections(save_user_connect);
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
- my_free(save_db);
- my_free(save_security_ctx.user);
+ my_free((char*) save_db.str);
+ my_free(const_cast<char*>(save_security_ctx.user));
}
break;
}
@@ -1804,10 +1828,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->m_digest= & thd->m_digest_state;
thd->m_digest->reset(thd->m_token_array, max_digest_length);
- if (alloc_query(thd, packet, packet_length))
+ if (unlikely(alloc_query(thd, packet, packet_length)))
break; // fatal error is set
MYSQL_QUERY_START(thd->query(), thd->thread_id,
- (char *) (thd->db ? thd->db : ""),
+ thd->get_db(),
&thd->security_ctx->priv_user[0],
(char *) thd->security_ctx->host_or_ip);
char *packet_end= thd->query() + thd->query_length();
@@ -1820,7 +1844,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->query_length());
Parser_state parser_state;
- if (parser_state.init(thd, thd->query(), thd->query_length()))
+ if (unlikely(parser_state.init(thd, thd->query(), thd->query_length())))
break;
if (WSREP_ON)
@@ -1885,7 +1909,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* DTRACE begin */
MYSQL_QUERY_START(beginning_of_next_stmt, thd->thread_id,
- (char *) (thd->db ? thd->db : ""),
+ thd->get_db(),
&thd->security_ctx->priv_user[0],
(char *) thd->security_ctx->host_or_ip);
@@ -1894,7 +1918,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
com_statement_info[command].m_key,
- thd->db, thd->db_length,
+ thd->db.str, thd->db.length,
thd->charset());
THD_STAGE_INFO(thd, stage_init);
MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, beginning_of_next_stmt,
@@ -1902,6 +1926,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->set_query_and_id(beginning_of_next_stmt, length,
thd->charset(), next_query_id());
+
/*
Count each statement from the client.
*/
@@ -1911,7 +1936,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->set_time(); /* Reset the query start time. */
parser_state.reset(beginning_of_next_stmt, length);
- /* TODO: set thd->lex->sql_command to SQLCOM_END here */
if (WSREP_ON)
wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state,
@@ -1936,7 +1960,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* Locked closure of all tables */
TABLE_LIST table_list;
LEX_STRING table_name;
- LEX_STRING db;
+ LEX_CSTRING db;
/*
SHOW statements should not add the used tables to the list of tables
used in a transaction.
@@ -1944,7 +1968,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS]);
- if (thd->copy_db_to(&db.str, &db.length))
+ if (thd->copy_db_to(&db))
break;
/*
We have name + wildcard in packet, separated by endzero
@@ -1969,7 +1993,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
packet= arg_end + 1;
- thd->reset_for_next_command(0); // Don't clear errors
// thd->reset_for_next_command reset state => restore it
if (is_next_command)
{
@@ -1983,10 +2006,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (lower_case_table_names)
{
table_name.length= my_casedn_str(files_charset_info, table_name.str);
- db.length= my_casedn_str(files_charset_info, db.str);
+ db.length= my_casedn_str(files_charset_info, (char*) db.str);
}
- table_list.init_one_table(db.str, db.length, table_name.str,
- table_name.length, table_name.str, TL_READ);
+ table_list.init_one_table(&db, (LEX_CSTRING*) &table_name, 0, TL_READ);
/*
Init TABLE_LIST members necessary when the undelrying
table is view.
@@ -1997,9 +2019,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
&table_list.next_local);
thd->lex->add_to_query_tables(&table_list);
- if (is_infoschema_db(table_list.db, table_list.db_length))
+ if (is_infoschema_db(&table_list.db))
{
- ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, table_list.alias);
+ ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, &table_list.alias);
if (schema_table)
table_list.schema_table= schema_table;
}
@@ -2008,7 +2030,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (!(fields= (char *) thd->memdup(packet, query_length + 1)))
break;
thd->set_query(fields, query_length);
- general_log_print(thd, command, "%s %s", table_list.table_name, fields);
+ general_log_print(thd, command, "%s %s", table_list.table_name.str,
+ fields);
if (thd->open_temporary_tables(&table_list))
break;
@@ -2129,7 +2152,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
else
#endif
{
- thd->lex->relay_log_connection_name= empty_lex_str;
+ thd->lex->relay_log_connection_name= empty_clex_str;
if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, &not_used))
break;
}
@@ -2173,7 +2196,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
STATUS_VAR *current_global_status_var; // Big; Don't allocate on stack
ulong uptime;
- uint length __attribute__((unused));
ulonglong queries_per_second1000;
char buff[250];
uint buff_len= sizeof(buff);
@@ -2188,8 +2210,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
queries_per_second1000= 0;
else
queries_per_second1000= thd->query_id * 1000 / uptime;
-
- length= my_snprintf(buff, buff_len - 1,
+#ifndef EMBEDDED_LIBRARY
+ size_t length=
+#endif
+ my_snprintf(buff, buff_len - 1,
"Uptime: %lu Threads: %d Questions: %lu "
"Slow queries: %lu Opens: %lu Flush tables: %lld "
"Open tables: %u Queries per second avg: %u.%03u",
@@ -2316,7 +2340,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
if (dispatch_command(subcommand, thd, packet + (1 + length_length),
- subpacket_length - (1 + length_length), TRUE,
+ (uint)(subpacket_length - (1 + length_length)), TRUE,
(current_com != counter)))
{
DBUG_ASSERT(thd->is_error());
@@ -2325,7 +2349,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
DBUG_ASSERT(subpacket_length <= packet_length);
packet+= subpacket_length;
- packet_length-= subpacket_length;
+ packet_length-= (uint)subpacket_length;
}
com_multi_end:
@@ -2380,7 +2404,7 @@ com_multi_end:
(thd->open_tables == NULL ||
(thd->locked_tables_mode == LTM_LOCK_TABLES)));
- thd_proc_info(thd, "updating status");
+ thd_proc_info(thd, "Updating status");
/* Finalize server status flags after executing a command. */
thd->update_server_status();
if (command != COM_MULTI)
@@ -2392,7 +2416,7 @@ com_multi_end:
if (drop_more_results)
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
- if (!thd->is_error() && !thd->killed_errno())
+ if (likely(!thd->is_error() && !thd->killed_errno()))
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0);
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_STATUS,
@@ -2416,10 +2440,8 @@ com_multi_end:
thd->m_digest= NULL;
if (!is_com_multi)
- {
- dec_thread_running();
thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory
- }
+
thd->reset_kill_query(); /* Ensure that killed_errmsg is released */
/*
LEX::m_sql_cmd can point to Sql_cmd allocated on thd->mem_root.
@@ -2449,11 +2471,18 @@ com_multi_end:
DBUG_RETURN(error);
}
+static bool slow_filter_masked(THD *thd, ulonglong mask)
+{
+ return thd->variables.log_slow_filter && !(thd->variables.log_slow_filter & mask);
+}
/*
+ Log query to slow queries, if it passes filtering
+
@note
This function must call delete_explain_query().
*/
+
void log_slow_statement(THD *thd)
{
DBUG_ENTER("log_slow_statement");
@@ -2465,7 +2494,6 @@ void log_slow_statement(THD *thd)
*/
if (unlikely(thd->in_sub_stmt))
goto end; // Don't set time for sub stmt
-
/*
Skip both long_query_count increment and logging if the current
statement forces slow log suppression (e.g. an SP statement).
@@ -2484,21 +2512,27 @@ void log_slow_statement(THD *thd)
thd->server_status|= SERVER_QUERY_WAS_SLOW;
});
- if (((thd->server_status & SERVER_QUERY_WAS_SLOW) ||
- ((thd->server_status &
- (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
- opt_log_queries_not_using_indexes &&
- !(thd->query_plan_flags & QPLAN_STATUS))) &&
+ if ((thd->server_status &
+ (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
+ !(thd->query_plan_flags & QPLAN_STATUS) &&
+ !slow_filter_masked(thd, QPLAN_NOT_USING_INDEX))
+ {
+ thd->query_plan_flags|= QPLAN_NOT_USING_INDEX;
+ /* We are always logging no index queries if enabled in filter */
+ thd->server_status|= SERVER_QUERY_WAS_SLOW;
+ }
+
+ if ((thd->server_status & SERVER_QUERY_WAS_SLOW) &&
thd->get_examined_row_count() >= thd->variables.min_examined_row_limit)
{
thd->status_var.long_query_count++;
/*
- until opt_log_slow_admin_statements is removed, it
+ until log_slow_disabled_statements=admin is removed, it
duplicates slow_log_filter=admin
*/
if ((thd->query_plan_flags & QPLAN_ADMIN) &&
- !opt_log_slow_admin_statements)
+ (thd->variables.log_slow_disabled_statements & LOG_SLOW_DISABLE_ADMIN))
goto end;
if (!global_system_variables.sql_log_slow || !thd->variables.sql_log_slow)
@@ -2516,8 +2550,7 @@ void log_slow_statement(THD *thd)
Follow the slow log filter configuration:
skip logging if the current statement matches the filter.
*/
- if (thd->variables.log_slow_filter &&
- !(thd->variables.log_slow_filter & thd->query_plan_flags))
+ if (slow_filter_masked(thd, thd->query_plan_flags))
goto end;
THD_STAGE_INFO(thd, stage_logging_slow_query);
@@ -2575,6 +2608,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
case SCH_TABLE_NAMES:
case SCH_TABLES:
+ case SCH_CHECK_CONSTRAINTS:
case SCH_VIEWS:
case SCH_TRIGGERS:
case SCH_EVENTS:
@@ -2584,21 +2618,23 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
DBUG_RETURN(1);
#else
{
- LEX_STRING db;
- size_t dummy;
- if (lex->select_lex.db == NULL &&
- lex->copy_db_to(&lex->select_lex.db, &dummy))
+ if (lex->select_lex.db.str == NULL &&
+ lex->copy_db_to(&lex->select_lex.db))
{
DBUG_RETURN(1);
}
schema_select_lex= new (thd->mem_root) SELECT_LEX();
- db.str= schema_select_lex->db= lex->select_lex.db;
schema_select_lex->table_list.first= NULL;
- db.length= strlen(db.str);
-
- if (check_db_name(&db))
+ if (lower_case_table_names == 1)
+ lex->select_lex.db.str= thd->strdup(lex->select_lex.db.str);
+ schema_select_lex->db= lex->select_lex.db;
+ /*
+ check_db_name() may change db.str if lower_case_table_names == 1,
+ but that's ok as the db is allocted above in this case.
+ */
+ if (check_db_name((LEX_STRING*) &lex->select_lex.db))
{
- my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->select_lex.db.str);
DBUG_RETURN(1);
}
break;
@@ -2661,7 +2697,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
TRUE error; In this case thd->fatal_error is set
*/
-bool alloc_query(THD *thd, const char *packet, uint packet_length)
+bool alloc_query(THD *thd, const char *packet, size_t packet_length)
{
char *query;
/* Remove garbage at start and end of query */
@@ -2689,7 +2725,7 @@ bool alloc_query(THD *thd, const char *packet, uint packet_length)
*/
if (! (query= (char*) thd->memdup_w_gap(packet,
packet_length,
- 1 + thd->db_length +
+ 1 + thd->db.length +
QUERY_CACHE_DB_LENGTH_SIZE +
QUERY_CACHE_FLAGS_SIZE)))
return TRUE;
@@ -2699,7 +2735,7 @@ bool alloc_query(THD *thd, const char *packet, uint packet_length)
also store this length, in case current database is changed during
execution. We might need to reallocate the 'query' buffer
*/
- int2store(query + packet_length + 1, thd->db_length);
+ int2store(query + packet_length + 1, thd->db.length);
thd->set_query(query, packet_length);
@@ -2757,7 +2793,7 @@ bool sp_process_definer(THD *thd)
DBUG_RETURN(TRUE);
if (thd->slave_thread && lex->sphead)
- lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
+ lex->sphead->set_suid(SP_IS_NOT_SUID);
}
else
{
@@ -2917,12 +2953,13 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
{
/* bits that should be cleared in thd->server_status */
uint bits_to_be_cleared= 0;
+ ulonglong affected_rows;
if (sp->m_flags & sp_head::MULTI_RESULTS)
{
if (!(thd->client_capabilities & CLIENT_MULTI_RESULTS))
{
/* The client does not support multiple result sets being sent back */
- my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
+ my_error(ER_SP_BADSELECT, MYF(0), ErrConvDQName(sp).ptr());
return 1;
}
}
@@ -2962,11 +2999,249 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
return 1; // Substatement should already have sent error
}
- my_ok(thd, (thd->get_row_count_func() < 0) ? 0 : thd->get_row_count_func());
+ affected_rows= thd->affected_rows; // Affected rows for all sub statements
+ thd->affected_rows= 0; // Reset total, as my_ok() adds to it
+ my_ok(thd, affected_rows);
return 0;
}
+static int mysql_create_routine(THD *thd, LEX *lex)
+{
+ DBUG_ASSERT(lex->sphead != 0);
+ DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */
+ /*
+ Verify that the database name is allowed, optionally
+ lowercase it.
+ */
+ if (check_db_name((LEX_STRING*) &lex->sphead->m_db))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str);
+ return true;
+ }
+
+ if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str,
+ NULL, NULL, 0, 0))
+ return true;
+
+ /* Checking the drop permissions if CREATE OR REPLACE is used */
+ if (lex->create_info.or_replace())
+ {
+ if (check_routine_access(thd, ALTER_PROC_ACL, &lex->sphead->m_db,
+ &lex->sphead->m_name,
+ Sp_handler::handler(lex->sql_command), 0))
+ return true;
+ }
+
+ const LEX_CSTRING *name= lex->sphead->name();
+#ifdef HAVE_DLOPEN
+ if (lex->sphead->m_handler->type() == TYPE_ENUM_FUNCTION)
+ {
+ udf_func *udf = find_udf(name->str, name->length);
+
+ if (udf)
+ {
+ my_error(ER_UDF_EXISTS, MYF(0), name->str);
+ return true;
+ }
+ }
+#endif
+
+ if (sp_process_definer(thd))
+ return true;
+
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ if (!lex->sphead->m_handler->sp_create_routine(thd, lex->sphead))
+ {
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /* only add privileges if really neccessary */
+
+ Security_context security_context;
+ bool restore_backup_context= false;
+ Security_context *backup= NULL;
+ LEX_USER *definer= thd->lex->definer;
+ /*
+ We're going to issue an implicit GRANT statement so we close all
+ open tables. We have to keep metadata locks as this ensures that
+ this statement is atomic against concurent FLUSH TABLES WITH READ
+ LOCK. Deadlocks which can arise due to fact that this implicit
+ statement takes metadata locks should be detected by a deadlock
+ detector in MDL subsystem and reported as errors.
+
+ No need to commit/rollback statement transaction, it's not started.
+
+ TODO: Long-term we should either ensure that implicit GRANT statement
+ is written into binary log as a separate statement or make both
+ creation of routine and implicit GRANT parts of one fully atomic
+ statement.
+ */
+ DBUG_ASSERT(thd->transaction.stmt.is_empty());
+ close_thread_tables(thd);
+ /*
+ Check if the definer exists on slave,
+ then use definer privilege to insert routine privileges to mysql.procs_priv.
+
+ For current user of SQL thread has GLOBAL_ACL privilege,
+ which doesn't any check routine privileges,
+ so no routine privilege record will insert into mysql.procs_priv.
+ */
+ if (thd->slave_thread && is_acl_user(definer->host.str, definer->user.str))
+ {
+ security_context.change_security_context(thd,
+ &thd->lex->definer->user,
+ &thd->lex->definer->host,
+ &thd->lex->sphead->m_db,
+ &backup);
+ restore_backup_context= true;
+ }
+
+ if (sp_automatic_privileges && !opt_noacl &&
+ check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
+ &lex->sphead->m_db, name,
+ Sp_handler::handler(lex->sql_command), 1))
+ {
+ if (sp_grant_privileges(thd, lex->sphead->m_db.str, name->str,
+ Sp_handler::handler(lex->sql_command)))
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_PROC_AUTO_GRANT_FAIL, ER_THD(thd, ER_PROC_AUTO_GRANT_FAIL));
+ thd->clear_error();
+ }
+
+ /*
+ Restore current user with GLOBAL_ACL privilege of SQL thread
+ */
+ if (restore_backup_context)
+ {
+ DBUG_ASSERT(thd->slave_thread == 1);
+ thd->security_ctx->restore_security_context(thd, backup);
+ }
+
+#endif
+ return false;
+ }
+WSREP_ERROR_LABEL:
+ return true;
+}
+
+
+/**
+ Prepare for CREATE DATABASE, ALTER DATABASE, DROP DATABASE.
+
+ @param thd - current THD
+ @param want_access - access needed
+ @param dbname - the database name
+
+ @retval false - Ok to proceed with CREATE/ALTER/DROP
+ @retval true - not OK to proceed (error, or filtered)
+
+ Note, on slave this function returns true if the database
+ is in the ignore filter. The caller must distinguish this case
+ from other cases: bad database error, no access error.
+ This can be done by testing thd->is_error().
+*/
+static bool prepare_db_action(THD *thd, ulong want_access, LEX_CSTRING *dbname)
+{
+ if (check_db_name((LEX_STRING*)dbname))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), dbname->str);
+ return true;
+ }
+ /*
+ If in a slave thread :
+ - CREATE DATABASE DB was certainly not preceded by USE DB.
+ - ALTER DATABASE DB may not be preceded by USE DB.
+ - DROP DATABASE DB may not be preceded by USE DB.
+ For that reason, db_ok() in sql/slave.cc did not check the
+ do_db/ignore_db. And as this query involves no tables, tables_ok()
+ was not called. So we have to check rules again here.
+ */
+#ifdef HAVE_REPLICATION
+ if (thd->slave_thread)
+ {
+ Rpl_filter *rpl_filter;
+ rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
+ if (!rpl_filter->db_ok(dbname->str) ||
+ !rpl_filter->db_ok_with_wild_table(dbname->str))
+ {
+ my_message(ER_SLAVE_IGNORED_TABLE,
+ ER_THD(thd, ER_SLAVE_IGNORED_TABLE), MYF(0));
+ return true;
+ }
+ }
+#endif
+ return check_access(thd, want_access, dbname->str, NULL, NULL, 1, 0);
+}
+
+
+bool Sql_cmd_call::execute(THD *thd)
+{
+ TABLE_LIST *all_tables= thd->lex->query_tables;
+ sp_head *sp;
+ /*
+ This will cache all SP and SF and open and lock all tables
+ required for execution.
+ */
+ if (check_table_access(thd, SELECT_ACL, all_tables, FALSE,
+ UINT_MAX, FALSE) ||
+ open_and_lock_tables(thd, all_tables, TRUE, 0))
+ return true;
+
+ /*
+ By this moment all needed SPs should be in cache so no need to look
+ into DB.
+ */
+ if (!(sp= m_handler->sp_find_routine(thd, m_name, true)))
+ {
+ /*
+ If the routine is not found, let's still check EXECUTE_ACL to decide
+ whether to return "Access denied" or "Routine does not exist".
+ */
+ if (check_routine_access(thd, EXECUTE_ACL, &m_name->m_db,
+ &m_name->m_name,
+ &sp_handler_procedure,
+ false))
+ return true;
+ /*
+ sp_find_routine can have issued an ER_SP_RECURSION_LIMIT error.
+ Send message ER_SP_DOES_NOT_EXIST only if procedure is not found in
+ cache.
+ */
+ if (!sp_cache_lookup(&thd->sp_proc_cache, m_name))
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
+ ErrConvDQName(m_name).ptr());
+ return true;
+ }
+ else
+ {
+ if (sp->check_execute_access(thd))
+ return true;
+ /*
+ Check that the stored procedure doesn't contain Dynamic SQL
+ and doesn't return result sets: such stored procedures can't
+ be called from a function or trigger.
+ */
+ if (thd->in_sub_stmt)
+ {
+ const char *where= (thd->in_sub_stmt & SUB_STMT_TRIGGER ?
+ "trigger" : "function");
+ if (sp->is_not_allowed_in_function(where))
+ return true;
+ }
+
+ if (do_execute_sp(thd, sp))
+ return true;
+
+ /*
+ Disable slow log for the above call(), if calls are disabled.
+ Instead we will log the executed statements to the slow log.
+ */
+ if (thd->variables.log_slow_disabled_statements & LOG_SLOW_DISABLE_CALL)
+ thd->enable_slow_log= 0;
+ }
+ return false;
+}
+
+
/**
Execute command saved in thd and lex->sql_command.
@@ -3039,6 +3314,12 @@ mysql_execute_command(THD *thd)
table_list.first);
/*
+ Remember last commmand executed, so that we can use it in functions called by
+ dispatch_command()
+ */
+ thd->last_sql_command= lex->sql_command;
+
+ /*
Reset warning count for each query that uses tables
A better approach would be to reset this for any commands
that is not a SHOW command or a select that only access local
@@ -3139,7 +3420,8 @@ mysql_execute_command(THD *thd)
*/
if (!(lex->sql_command == SQLCOM_UPDATE_MULTI) &&
!(lex->sql_command == SQLCOM_SET_OPTION) &&
- !(lex->sql_command == SQLCOM_DROP_TABLE &&
+ !((lex->sql_command == SQLCOM_DROP_TABLE ||
+ lex->sql_command == SQLCOM_DROP_SEQUENCE) &&
lex->tmp_table() && lex->if_exists()) &&
all_tables_not_ok(thd, all_tables))
{
@@ -3296,6 +3578,7 @@ mysql_execute_command(THD *thd)
case GET_NO_ARG:
case GET_DISABLED:
DBUG_ASSERT(0);
+ /* fall through */
case 0:
case GET_FLAGSET:
case GET_ENUM:
@@ -3474,8 +3757,7 @@ mysql_execute_command(THD *thd)
Item **it= lex->value_list.head_ref();
if (!(*it)->basic_const_item() ||
- (!(*it)->fixed && (*it)->fix_fields(lex->thd, it)) ||
- (*it)->check_cols(1))
+ (*it)->fix_fields_if_needed_for_scalar(lex->thd, it))
{
my_message(ER_SET_CONSTANTS_ONLY, ER_THD(thd, ER_SET_CONSTANTS_ONLY),
MYF(0));
@@ -3485,6 +3767,8 @@ mysql_execute_command(THD *thd)
/* fall through */
case SQLCOM_SHOW_STATUS_PROC:
case SQLCOM_SHOW_STATUS_FUNC:
+ case SQLCOM_SHOW_STATUS_PACKAGE:
+ case SQLCOM_SHOW_STATUS_PACKAGE_BODY:
case SQLCOM_SHOW_DATABASES:
case SQLCOM_SHOW_TABLES:
case SQLCOM_SHOW_TRIGGERS:
@@ -3586,8 +3870,7 @@ mysql_execute_command(THD *thd)
goto error;
/* PURGE MASTER LOGS BEFORE 'data' */
it= (Item *)lex->value_list.head();
- if ((!it->fixed && it->fix_fields(lex->thd, &it)) ||
- it->check_cols(1))
+ if (it->fix_fields_if_needed_for_scalar(lex->thd, &it))
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
goto error;
@@ -3649,7 +3932,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_ASSIGN_TO_KEYCACHE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_access(thd, INDEX_ACL, first_table->db,
+ if (check_access(thd, INDEX_ACL, first_table->db.str,
&first_table->grant.privilege,
&first_table->grant.m_internal,
0, 0))
@@ -3660,7 +3943,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_PRELOAD_KEYS:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_access(thd, INDEX_ACL, first_table->db,
+ if (check_access(thd, INDEX_ACL, first_table->db.str,
&first_table->grant.privilege,
&first_table->grant.m_internal,
0, 0))
@@ -3697,7 +3980,7 @@ mysql_execute_command(THD *thd)
{
/* New replication created */
mi= new Master_info(&lex_mi->connection_name, relay_log_recovery);
- if (!mi || mi->error())
+ if (unlikely(!mi || mi->error()))
{
delete mi;
res= 1;
@@ -3794,20 +4077,20 @@ mysql_execute_command(THD *thd)
HA_CREATE_INFO create_info;
Alter_info alter_info(lex->alter_info, thd->mem_root);
- if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
+ if (unlikely(thd->is_fatal_error)) /* out of memory creating alter_info */
goto error;
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_one_table_access(thd, INDEX_ACL, all_tables))
goto error; /* purecov: inspected */
- WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL)
+ WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL);
bzero((char*) &create_info, sizeof(create_info));
create_info.db_type= 0;
create_info.row_type= ROW_TYPE_NOT_USED;
create_info.default_table_charset= thd->variables.collation_database;
- res= mysql_alter_table(thd, first_table->db, first_table->table_name,
+ res= mysql_alter_table(thd, &first_table->db, &first_table->table_name,
&create_info, first_table, &alter_info,
0, (ORDER*) 0, 0);
break;
@@ -3825,8 +4108,8 @@ mysql_execute_command(THD *thd)
We don't need to ensure that only one user is using master_info
as start_slave is protected against simultaneous usage
*/
- if ((mi= get_master_info(&lex_mi->connection_name,
- Sql_condition::WARN_LEVEL_ERROR)))
+ if (unlikely((mi= get_master_info(&lex_mi->connection_name,
+ Sql_condition::WARN_LEVEL_ERROR))))
{
if (load_error)
{
@@ -3919,7 +4202,7 @@ mysql_execute_command(THD *thd)
if (check_rename_table(thd, first_table, all_tables))
goto error;
- WSREP_TO_ISOLATION_BEGIN(0, 0, first_table)
+ WSREP_TO_ISOLATION_BEGIN(0, 0, first_table);
if (mysql_rename_tables(thd, first_table, 0))
goto error;
@@ -3961,8 +4244,8 @@ mysql_execute_command(THD *thd)
*/
DBUG_PRINT("debug", ("lex->only_view: %d, table: %s.%s",
- lex->only_view,
- first_table->db, first_table->table_name));
+ lex->table_type == TABLE_TYPE_VIEW,
+ first_table->db.str, first_table->table_name.str));
res= mysqld_show_create(thd, first_table);
break;
#endif
@@ -4010,8 +4293,7 @@ mysql_execute_command(THD *thd)
select_lex->order_list.elements,
select_lex->order_list.first,
unit->select_limit_cnt,
- lex->duplicates, lex->ignore,
- &found, &updated);
+ lex->ignore, &found, &updated);
MYSQL_UPDATE_DONE(res, found, updated);
/* mysql_update return 2 if we need to switch to multi-update */
if (up_result != 2)
@@ -4031,6 +4313,7 @@ mysql_execute_command(THD *thd)
else
res= 0;
+ unit->set_limit(select_lex);
/*
We can not use mysql_explain_union() because of parameters of
mysql_select in mysql_multi_update so just set the option if needed
@@ -4214,7 +4497,7 @@ mysql_execute_command(THD *thd)
if (WSREP(thd) && thd->wsrep_consistency_check == CONSISTENCY_CHECK_DECLARED)
{
thd->wsrep_consistency_check = CONSISTENCY_CHECK_RUNNING;
- WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL);
+ WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL);
}
#endif /* WITH_WSREP */
@@ -4343,7 +4626,7 @@ mysql_execute_command(THD *thd)
unit->set_limit(select_lex);
MYSQL_DELETE_START(thd->query());
- Protocol *save_protocol;
+ Protocol * UNINIT_VAR(save_protocol);
bool replaced_protocol= false;
if (!select_lex->item_list.is_empty())
@@ -4412,17 +4695,17 @@ mysql_execute_command(THD *thd)
break;
MYSQL_MULTI_DELETE_START(thd->query());
- if ((res= mysql_multi_delete_prepare(thd)))
+ if (unlikely(res= mysql_multi_delete_prepare(thd)))
{
MYSQL_MULTI_DELETE_DONE(1, 0);
goto error;
}
- if (!thd->is_fatal_error)
+ if (likely(!thd->is_fatal_error))
{
result= new (thd->mem_root) multi_delete(thd, aux_tables,
lex->table_count);
- if (result)
+ if (unlikely(result))
{
res= mysql_select(thd,
select_lex->get_table_list(),
@@ -4435,7 +4718,7 @@ mysql_execute_command(THD *thd)
SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
OPTION_SETUP_TABLES_DONE) & ~OPTION_BUFFER_RESULT,
result, unit, select_lex);
- res|= thd->is_error();
+ res|= (int)(thd->is_error());
MYSQL_MULTI_DELETE_DONE(res, result->num_deleted());
if (res)
@@ -4455,6 +4738,7 @@ mysql_execute_command(THD *thd)
}
break;
}
+ case SQLCOM_DROP_SEQUENCE:
case SQLCOM_DROP_TABLE:
{
int result;
@@ -4472,7 +4756,7 @@ mysql_execute_command(THD *thd)
}
else
{
- status_var_decrement(thd->status_var.com_stat[SQLCOM_DROP_TABLE]);
+ status_var_decrement(thd->status_var.com_stat[lex->sql_command]);
status_var_increment(thd->status_var.com_drop_tmp_table);
/* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
@@ -4503,10 +4787,13 @@ mysql_execute_command(THD *thd)
}
/* DDL and binlog write order are protected by metadata locks. */
- res= mysql_rm_table(thd, first_table, lex->if_exists(), lex->tmp_table());
+ res= mysql_rm_table(thd, first_table, lex->if_exists(), lex->tmp_table(),
+ lex->table_type == TABLE_TYPE_SEQUENCE);
- /* when dropping temporary tables if @@session_track_state_change is ON then
- send the boolean tracker in the OK packet */
+ /*
+ When dropping temporary tables if @@session_track_state_change is ON
+ then send the boolean tracker in the OK packet
+ */
if(!res && (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
{
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
@@ -4547,9 +4834,7 @@ mysql_execute_command(THD *thd)
#endif
case SQLCOM_CHANGE_DB:
{
- LEX_STRING db_str= { (char *) select_lex->db, strlen(select_lex->db) };
-
- if (!mysql_change_db(thd, &db_str, FALSE))
+ if (!mysql_change_db(thd, &select_lex->db, FALSE))
my_ok(thd);
break;
@@ -4588,9 +4873,9 @@ mysql_execute_command(THD *thd)
if ((check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)
|| open_and_lock_tables(thd, all_tables, TRUE, 0)))
goto error;
- if (!(res= sql_set_variables(thd, lex_var_list, true)))
+ if (likely(!(res= sql_set_variables(thd, lex_var_list, true))))
{
- if (!thd->is_error())
+ if (likely(!thd->is_error()))
my_ok(thd);
}
else
@@ -4671,74 +4956,26 @@ mysql_execute_command(THD *thd)
break;
case SQLCOM_CREATE_DB:
{
- if (check_db_name(&lex->name))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
- break;
- }
- /*
- If in a slave thread :
- CREATE DATABASE DB was certainly not preceded by USE DB.
- For that reason, db_ok() in sql/slave.cc did not check the
- do_db/ignore_db. And as this query involves no tables, tables_ok()
- above was not called. So we have to check rules again here.
- */
-#ifdef HAVE_REPLICATION
- if (thd->slave_thread)
- {
- rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
- if (!rpl_filter->db_ok(lex->name.str) ||
- !rpl_filter->db_ok_with_wild_table(lex->name.str))
- {
- my_message(ER_SLAVE_IGNORED_TABLE, ER_THD(thd, ER_SLAVE_IGNORED_TABLE), MYF(0));
- break;
- }
- }
-#endif
- if (check_access(thd, lex->create_info.or_replace() ?
+ if (prepare_db_action(thd, lex->create_info.or_replace() ?
(CREATE_ACL | DROP_ACL) : CREATE_ACL,
- lex->name.str, NULL, NULL, 1, 0))
+ &lex->name))
break;
- WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL)
- res= mysql_create_db(thd, lex->name.str,
+ WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL);
+ res= mysql_create_db(thd, &lex->name,
lex->create_info, &lex->create_info);
break;
}
case SQLCOM_DROP_DB:
{
- if (check_db_name(&lex->name))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
+ if (prepare_db_action(thd, DROP_ACL, &lex->name))
break;
- }
- /*
- If in a slave thread :
- DROP DATABASE DB may not be preceded by USE DB.
- For that reason, maybe db_ok() in sql/slave.cc did not check the
- do_db/ignore_db. And as this query involves no tables, tables_ok()
- above was not called. So we have to check rules again here.
- */
-#ifdef HAVE_REPLICATION
- if (thd->slave_thread)
- {
- rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
- if (!rpl_filter->db_ok(lex->name.str) ||
- !rpl_filter->db_ok_with_wild_table(lex->name.str))
- {
- my_message(ER_SLAVE_IGNORED_TABLE, ER_THD(thd, ER_SLAVE_IGNORED_TABLE), MYF(0));
- break;
- }
- }
-#endif
- if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0))
- break;
- WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL)
- res= mysql_rm_db(thd, lex->name.str, lex->if_exists());
+ WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL);
+ res= mysql_rm_db(thd, &lex->name, lex->if_exists());
break;
}
case SQLCOM_ALTER_DB_UPGRADE:
{
- LEX_STRING *db= & lex->name;
+ LEX_CSTRING *db= &lex->name;
#ifdef HAVE_REPLICATION
if (thd->slave_thread)
{
@@ -4752,7 +4989,7 @@ mysql_execute_command(THD *thd)
}
}
#endif
- if (check_db_name(db))
+ if (check_db_name((LEX_STRING*) db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
break;
@@ -4764,7 +5001,7 @@ mysql_execute_command(THD *thd)
res= 1;
break;
}
- WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL);
res= mysql_upgrade_db(thd, db);
if (!res)
my_ok(thd);
@@ -4772,51 +5009,27 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_ALTER_DB:
{
- LEX_STRING *db= &lex->name;
- if (check_db_name(db))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
- break;
- }
- /*
- If in a slave thread :
- ALTER DATABASE DB may not be preceded by USE DB.
- For that reason, maybe db_ok() in sql/slave.cc did not check the
- do_db/ignore_db. And as this query involves no tables, tables_ok()
- above was not called. So we have to check rules again here.
- */
-#ifdef HAVE_REPLICATION
- if (thd->slave_thread)
- {
- rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
- if (!rpl_filter->db_ok(db->str) ||
- !rpl_filter->db_ok_with_wild_table(db->str))
- {
- my_message(ER_SLAVE_IGNORED_TABLE, ER_THD(thd, ER_SLAVE_IGNORED_TABLE), MYF(0));
- break;
- }
- }
-#endif
- if (check_access(thd, ALTER_ACL, db->str, NULL, NULL, 1, 0))
+ LEX_CSTRING *db= &lex->name;
+ if (prepare_db_action(thd, ALTER_ACL, db))
break;
- WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL)
- res= mysql_alter_db(thd, db->str, &lex->create_info);
+ WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL);
+ res= mysql_alter_db(thd, db, &lex->create_info);
break;
}
case SQLCOM_SHOW_CREATE_DB:
{
char db_name_buff[NAME_LEN+1];
- LEX_STRING db_name;
+ LEX_CSTRING db_name;
DBUG_EXECUTE_IF("4x_server_emul",
my_error(ER_UNKNOWN_ERROR, MYF(0)); goto error;);
db_name.str= db_name_buff;
db_name.length= lex->name.length;
- strmov(db_name.str, lex->name.str);
+ strmov(db_name_buff, lex->name.str);
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
- if (check_db_name(&db_name))
+ if (check_db_name((LEX_STRING*) &db_name))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
break;
@@ -4869,12 +5082,12 @@ mysql_execute_command(THD *thd)
break;
case SQLCOM_SHOW_CREATE_EVENT:
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
- res= Events::show_create_event(thd, lex->spname->m_db,
- lex->spname->m_name);
+ res= Events::show_create_event(thd, &lex->spname->m_db,
+ &lex->spname->m_name);
break;
case SQLCOM_DROP_EVENT:
if (!(res= Events::drop_event(thd,
- lex->spname->m_db, lex->spname->m_name,
+ &lex->spname->m_db, &lex->spname->m_name,
lex->if_exists())))
my_ok(thd);
break;
@@ -4889,7 +5102,7 @@ mysql_execute_command(THD *thd)
"mysql", NULL, NULL, 1, 0))
break;
#ifdef HAVE_DLOPEN
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (!(res = mysql_create_function(thd, &lex->udf)))
my_ok(thd);
#else
@@ -4907,7 +5120,7 @@ mysql_execute_command(THD *thd)
"mysql", NULL, NULL, 1, 1) &&
check_global_access(thd,CREATE_USER_ACL))
break;
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
if (!(res= mysql_create_user(thd, lex->users_list,
lex->sql_command == SQLCOM_CREATE_ROLE)))
@@ -4921,7 +5134,7 @@ mysql_execute_command(THD *thd)
check_global_access(thd,CREATE_USER_ACL))
break;
/* Conditionally writes to binlog */
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (!(res= mysql_drop_user(thd, lex->users_list,
lex->sql_command == SQLCOM_DROP_ROLE)))
my_ok(thd);
@@ -4934,7 +5147,7 @@ mysql_execute_command(THD *thd)
check_global_access(thd,CREATE_USER_ACL))
break;
/* Conditionally writes to binlog */
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (lex->sql_command == SQLCOM_ALTER_USER)
res= mysql_alter_user(thd, lex->users_list);
else
@@ -4950,7 +5163,7 @@ mysql_execute_command(THD *thd)
break;
/* Conditionally writes to binlog */
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (!(res = mysql_revoke_all(thd, lex->users_list)))
my_ok(thd);
break;
@@ -4960,7 +5173,7 @@ mysql_execute_command(THD *thd)
{
if (lex->type != TYPE_ENUM_PROXY &&
check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
- first_table ? first_table->db : select_lex->db,
+ first_table ? first_table->db.str : select_lex->db.str,
first_table ? &first_table->grant.privilege : NULL,
first_table ? &first_table->grant.m_internal : NULL,
first_table ? 0 : 1, 0))
@@ -5000,19 +5213,18 @@ mysql_execute_command(THD *thd)
}
if (first_table)
{
- if (lex->type == TYPE_ENUM_PROCEDURE ||
- lex->type == TYPE_ENUM_FUNCTION)
+ const Sp_handler *sph= Sp_handler::handler((stored_procedure_type)
+ lex->type);
+ if (sph)
{
uint grants= lex->all_privileges
? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL)
: lex->grant;
- if (check_grant_routine(thd, grants | GRANT_ACL, all_tables,
- lex->type == TYPE_ENUM_PROCEDURE, 0))
+ if (check_grant_routine(thd, grants | GRANT_ACL, all_tables, sph, 0))
goto error;
/* Conditionally writes to binlog */
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
- res= mysql_routine_grant(thd, all_tables,
- lex->type == TYPE_ENUM_PROCEDURE,
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
+ res= mysql_routine_grant(thd, all_tables, sph,
lex->users_list, grants,
lex->sql_command == SQLCOM_REVOKE, TRUE);
if (!res)
@@ -5024,7 +5236,7 @@ mysql_execute_command(THD *thd)
all_tables, FALSE, UINT_MAX, FALSE))
goto error;
/* Conditionally writes to binlog */
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
res= mysql_table_grant(thd, all_tables, lex->users_list,
lex->columns, lex->grant,
lex->sql_command == SQLCOM_REVOKE);
@@ -5040,9 +5252,9 @@ mysql_execute_command(THD *thd)
}
else
{
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
- res= mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
+ res= mysql_grant(thd, select_lex->db.str, lex->users_list, lex->grant,
lex->sql_command == SQLCOM_REVOKE,
lex->type == TYPE_ENUM_PROXY);
}
@@ -5066,7 +5278,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_REVOKE_ROLE:
case SQLCOM_GRANT_ROLE:
{
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (!(res= mysql_grant_role(thd, lex->users_list,
lex->sql_command != SQLCOM_GRANT_ROLE)))
my_ok(thd);
@@ -5124,7 +5336,7 @@ mysql_execute_command(THD *thd)
REFRESH_STATUS |
REFRESH_USER_RESOURCES))
{
- WSREP_TO_ISOLATION_BEGIN_WRTCHK(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN_WRTCHK(WSREP_MYSQL_DB, NULL, NULL);
}
#endif /* WITH_WSREP*/
@@ -5158,11 +5370,11 @@ mysql_execute_command(THD *thd)
*/
if (first_table)
{
- WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
+ WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
}
else
{
- WSREP_TO_ISOLATION_BEGIN_WRTCHK(WSREP_MYSQL_DB, NULL, NULL);
+ WSREP_TO_ISOLATION_BEGIN_WRTCHK(WSREP_MYSQL_DB, NULL, NULL);
}
}
#endif /* WITH_WSREP */
@@ -5210,7 +5422,7 @@ mysql_execute_command(THD *thd)
if (lex->kill_type == KILL_TYPE_ID || lex->kill_type == KILL_TYPE_QUERY)
{
Item *it= (Item *)lex->value_list.head();
- if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1))
+ if (it->fix_fields_if_needed_for_scalar(lex->thd, &it))
{
my_message(ER_SET_CONSTANTS_ONLY, ER_THD(thd, ER_SET_CONSTANTS_ONLY),
MYF(0));
@@ -5408,173 +5620,14 @@ mysql_execute_command(THD *thd)
break;
case SQLCOM_CREATE_PROCEDURE:
case SQLCOM_CREATE_SPFUNCTION:
+ case SQLCOM_CREATE_PACKAGE:
+ case SQLCOM_CREATE_PACKAGE_BODY:
{
- uint namelen;
- char *name;
-
- DBUG_ASSERT(lex->sphead != 0);
- DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */
- /*
- Verify that the database name is allowed, optionally
- lowercase it.
- */
- if (check_db_name(&lex->sphead->m_db))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str);
- goto error;
- }
-
- if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str,
- NULL, NULL, 0, 0))
- goto error;
-
- /* Checking the drop permissions if CREATE OR REPLACE is used */
- if (lex->create_info.or_replace())
- {
- if (check_routine_access(thd, ALTER_PROC_ACL, lex->spname->m_db.str,
- lex->spname->m_name.str,
- lex->sql_command == SQLCOM_CREATE_PROCEDURE, 0))
- goto error;
- }
-
- name= lex->sphead->name(&namelen);
-#ifdef HAVE_DLOPEN
- if (lex->sphead->m_type == TYPE_ENUM_FUNCTION)
- {
- udf_func *udf = find_udf(name, namelen);
-
- if (udf)
- {
- my_error(ER_UDF_EXISTS, MYF(0), name);
- goto error;
- }
- }
-#endif
-
- if (sp_process_definer(thd))
- goto error;
-
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
- if (!sp_create_routine(thd, lex->sphead->m_type, lex->sphead))
- {
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* only add privileges if really neccessary */
-
- Security_context security_context;
- bool restore_backup_context= false;
- Security_context *backup= NULL;
- LEX_USER *definer= thd->lex->definer;
- /*
- We're going to issue an implicit GRANT statement so we close all
- open tables. We have to keep metadata locks as this ensures that
- this statement is atomic against concurent FLUSH TABLES WITH READ
- LOCK. Deadlocks which can arise due to fact that this implicit
- statement takes metadata locks should be detected by a deadlock
- detector in MDL subsystem and reported as errors.
-
- No need to commit/rollback statement transaction, it's not started.
-
- TODO: Long-term we should either ensure that implicit GRANT statement
- is written into binary log as a separate statement or make both
- creation of routine and implicit GRANT parts of one fully atomic
- statement.
- */
- DBUG_ASSERT(thd->transaction.stmt.is_empty());
- close_thread_tables(thd);
- /*
- Check if the definer exists on slave,
- then use definer privilege to insert routine privileges to mysql.procs_priv.
-
- For current user of SQL thread has GLOBAL_ACL privilege,
- which doesn't any check routine privileges,
- so no routine privilege record will insert into mysql.procs_priv.
- */
- if (thd->slave_thread && is_acl_user(definer->host.str, definer->user.str))
- {
- security_context.change_security_context(thd,
- &thd->lex->definer->user,
- &thd->lex->definer->host,
- &thd->lex->sphead->m_db,
- &backup);
- restore_backup_context= true;
- }
-
- if (sp_automatic_privileges && !opt_noacl &&
- check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
- lex->sphead->m_db.str, name,
- lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
- {
- if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
- lex->sql_command == SQLCOM_CREATE_PROCEDURE))
- push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_PROC_AUTO_GRANT_FAIL, ER_THD(thd, ER_PROC_AUTO_GRANT_FAIL));
- thd->clear_error();
- }
-
- /*
- Restore current user with GLOBAL_ACL privilege of SQL thread
- */
- if (restore_backup_context)
- {
- DBUG_ASSERT(thd->slave_thread == 1);
- thd->security_ctx->restore_security_context(thd, backup);
- }
-
-#endif
- }
- else
+ if (mysql_create_routine(thd, lex))
goto error;
my_ok(thd);
break; /* break super switch */
} /* end case group bracket */
- case SQLCOM_CALL:
- {
- sp_head *sp;
- /*
- This will cache all SP and SF and open and lock all tables
- required for execution.
- */
- if (check_table_access(thd, SELECT_ACL, all_tables, FALSE,
- UINT_MAX, FALSE) ||
- open_and_lock_tables(thd, all_tables, TRUE, 0))
- goto error;
-
- if (check_routine_access(thd, EXECUTE_ACL, lex->spname->m_db.str,
- lex->spname->m_name.str, TRUE, FALSE))
- goto error;
-
- /*
- By this moment all needed SPs should be in cache so no need to look
- into DB.
- */
- if (!(sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
- &thd->sp_proc_cache, TRUE)))
- {
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
- lex->spname->m_qname.str);
- goto error;
- }
- else
- {
- /*
- Check that the stored procedure doesn't contain Dynamic SQL
- and doesn't return result sets: such stored procedures can't
- be called from a function or trigger.
- */
- if (thd->in_sub_stmt)
- {
- const char *where= (thd->in_sub_stmt & SUB_STMT_TRIGGER ?
- "trigger" : "function");
- if (sp->is_not_allowed_in_function(where))
- goto error;
- }
-
- if (do_execute_sp(thd, sp))
- goto error;
- }
- break;
- }
-
case SQLCOM_COMPOUND:
DBUG_ASSERT(all_tables == 0);
DBUG_ASSERT(thd->in_sub_stmt == 0);
@@ -5587,13 +5640,9 @@ mysql_execute_command(THD *thd)
case SQLCOM_ALTER_FUNCTION:
{
int sp_result;
- enum stored_procedure_type type;
- type= (lex->sql_command == SQLCOM_ALTER_PROCEDURE ?
- TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
-
- if (check_routine_access(thd, ALTER_PROC_ACL, lex->spname->m_db.str,
- lex->spname->m_name.str,
- lex->sql_command == SQLCOM_ALTER_PROCEDURE, 0))
+ const Sp_handler *sph= Sp_handler::handler(lex->sql_command);
+ if (check_routine_access(thd, ALTER_PROC_ACL, &lex->spname->m_db,
+ &lex->spname->m_name, sph, 0))
goto error;
/*
@@ -5603,7 +5652,7 @@ mysql_execute_command(THD *thd)
already puts on CREATE FUNCTION.
*/
/* Conditionally writes to binlog */
- sp_result= sp_update_routine(thd, type, lex->spname, &lex->sp_chistics);
+ sp_result= sph->sp_update_routine(thd, lex->spname, &lex->sp_chistics);
switch (sp_result)
{
case SP_OK:
@@ -5611,17 +5660,19 @@ mysql_execute_command(THD *thd)
break;
case SP_KEY_NOT_FOUND:
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ sph->type_str(), ErrConvDQName(lex->spname).ptr());
goto error;
default:
my_error(ER_SP_CANT_ALTER, MYF(0),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ sph->type_str(), ErrConvDQName(lex->spname).ptr());
goto error;
}
break;
}
case SQLCOM_DROP_PROCEDURE:
case SQLCOM_DROP_FUNCTION:
+ case SQLCOM_DROP_PACKAGE:
+ case SQLCOM_DROP_PACKAGE_BODY:
{
#ifdef HAVE_DLOPEN
if (lex->sql_command == SQLCOM_DROP_FUNCTION &&
@@ -5665,19 +5716,15 @@ mysql_execute_command(THD *thd)
#endif
int sp_result;
- enum stored_procedure_type type;
- type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ?
- TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
- char *db= lex->spname->m_db.str;
- char *name= lex->spname->m_name.str;
-
- if (check_routine_access(thd, ALTER_PROC_ACL, db, name,
- lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
+ const Sp_handler *sph= Sp_handler::handler(lex->sql_command);
+
+ if (check_routine_access(thd, ALTER_PROC_ACL, &lex->spname->m_db, &lex->spname->m_name,
+ Sp_handler::handler(lex->sql_command), 0))
goto error;
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
- sp_result= sp_drop_routine(thd, type, lex->spname);
+ sp_result= sph->sp_drop_routine(thd, lex->spname);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
@@ -5700,8 +5747,8 @@ mysql_execute_command(THD *thd)
if (sp_result != SP_KEY_NOT_FOUND &&
sp_automatic_privileges && !opt_noacl &&
- sp_revoke_privileges(thd, db, name,
- lex->sql_command == SQLCOM_DROP_PROCEDURE))
+ sp_revoke_privileges(thd, lex->spname->m_db.str, lex->spname->m_name.str,
+ Sp_handler::handler(lex->sql_command)))
{
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_PROC_AUTO_REVOKE_FAIL,
@@ -5722,51 +5769,52 @@ mysql_execute_command(THD *thd)
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SP_DOES_NOT_EXIST, ER_THD(thd, ER_SP_DOES_NOT_EXIST),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ sph->type_str(),
+ ErrConvDQName(lex->spname).ptr());
if (!res)
my_ok(thd);
break;
}
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ sph->type_str(), ErrConvDQName(lex->spname).ptr());
goto error;
default:
my_error(ER_SP_DROP_FAILED, MYF(0),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ sph->type_str(), ErrConvDQName(lex->spname).ptr());
goto error;
}
break;
}
case SQLCOM_SHOW_CREATE_PROC:
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
- if (sp_show_create_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname))
- goto error;
- break;
- }
case SQLCOM_SHOW_CREATE_FUNC:
+ case SQLCOM_SHOW_CREATE_PACKAGE:
+ case SQLCOM_SHOW_CREATE_PACKAGE_BODY:
{
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
- if (sp_show_create_routine(thd, TYPE_ENUM_FUNCTION, lex->spname))
- goto error;
+ const Sp_handler *sph= Sp_handler::handler(lex->sql_command);
+ if (sph->sp_show_create_routine(thd, lex->spname))
+ goto error;
break;
}
case SQLCOM_SHOW_PROC_CODE:
case SQLCOM_SHOW_FUNC_CODE:
+ case SQLCOM_SHOW_PACKAGE_BODY_CODE:
{
#ifndef DBUG_OFF
+ Database_qualified_name pkgname(&null_clex_str, &null_clex_str);
sp_head *sp;
- stored_procedure_type type= (lex->sql_command == SQLCOM_SHOW_PROC_CODE ?
- TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
-
+ const Sp_handler *sph= Sp_handler::handler(lex->sql_command);
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
- if (sp_cache_routine(thd, type, lex->spname, FALSE, &sp))
+ if (sph->sp_resolve_package_routine(thd, thd->lex->sphead,
+ lex->spname, &sph, &pkgname))
+ return true;
+ if (sph->sp_cache_routine(thd, lex->spname, false, &sp))
goto error;
if (!sp || sp->show_routine_code(thd))
{
/* We don't distinguish between errors for now */
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
- SP_COM_STRING(lex), lex->spname->m_name.str);
+ sph->type_str(), lex->spname->m_name.str);
goto error;
}
break;
@@ -5791,9 +5839,9 @@ mysql_execute_command(THD *thd)
{
/*
Note: SQLCOM_CREATE_VIEW also handles 'ALTER VIEW' commands
- as specified through the thd->lex->create_view_mode flag.
+ as specified through the thd->lex->create_view->mode flag.
*/
- res= mysql_create_view(thd, first_table, thd->lex->create_view_mode);
+ res= mysql_create_view(thd, first_table, thd->lex->create_view->mode);
break;
}
case SQLCOM_DROP_VIEW:
@@ -5801,7 +5849,7 @@ mysql_execute_command(THD *thd)
if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE))
goto error;
/* Conditionally writes to binlog. */
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
break;
}
@@ -5904,7 +5952,7 @@ mysql_execute_command(THD *thd)
if (check_global_access(thd, SUPER_ACL))
break;
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
res= create_server(thd, &lex->server_options);
break;
@@ -5917,9 +5965,9 @@ mysql_execute_command(THD *thd)
if (check_global_access(thd, SUPER_ACL))
break;
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
- if ((error= alter_server(thd, &lex->server_options)))
+ if (unlikely((error= alter_server(thd, &lex->server_options))))
{
DBUG_PRINT("info", ("problem altering server <%s>",
lex->server_options.server_name.str));
@@ -5937,7 +5985,7 @@ mysql_execute_command(THD *thd)
if (check_global_access(thd, SUPER_ACL))
break;
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if ((err_code= drop_server(thd, &lex->server_options)))
{
@@ -5962,12 +6010,15 @@ mysql_execute_command(THD *thd)
case SQLCOM_REPAIR:
case SQLCOM_TRUNCATE:
case SQLCOM_CREATE_TABLE:
+ case SQLCOM_CREATE_SEQUENCE:
case SQLCOM_ALTER_TABLE:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
/* fall through */
+ case SQLCOM_ALTER_SEQUENCE:
case SQLCOM_SIGNAL:
case SQLCOM_RESIGNAL:
case SQLCOM_GET_DIAGNOSTICS:
+ case SQLCOM_CALL:
DBUG_ASSERT(lex->m_sql_cmd != NULL);
res= lex->m_sql_cmd->execute(thd);
break;
@@ -6014,8 +6065,12 @@ finish:
}
thd->reset_kill_query();
}
- if (thd->is_error() || (thd->variables.option_bits & OPTION_MASTER_SQL_ERROR))
+ if (unlikely(thd->is_error()) ||
+ (thd->variables.option_bits & OPTION_MASTER_SQL_ERROR))
+ {
+ THD_STAGE_INFO(thd, stage_rollback);
trans_rollback_stmt(thd);
+ }
#ifdef WITH_WSREP
else if (thd->spcont &&
(thd->wsrep_conflict_state == MUST_ABORT ||
@@ -6038,6 +6093,7 @@ finish:
else
{
/* If commit fails, we should be able to reset the OK status. */
+ THD_STAGE_INFO(thd, stage_commit);
thd->get_stmt_da()->set_overwrite_status(true);
trans_commit_stmt(thd);
thd->get_stmt_da()->set_overwrite_status(false);
@@ -6047,12 +6103,13 @@ finish:
#endif
}
- /* Free tables */
+ /* Free tables. Set stage 'closing tables' */
close_thread_tables(thd);
#ifdef WITH_WSREP
thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK;
#endif /* WITH_WSREP */
+
#ifndef DBUG_OFF
if (lex->sql_command != SQLCOM_SET_OPTION && ! thd->in_sub_stmt)
DEBUG_SYNC(thd, "execute_command_after_close_tables");
@@ -6070,6 +6127,7 @@ finish:
one of storage engines (e.g. due to deadlock). Rollback transaction in
all storage engines including binary log.
*/
+ THD_STAGE_INFO(thd, stage_rollback_implicit);
trans_rollback_implicit(thd);
thd->mdl_context.release_transactional_locks();
}
@@ -6079,6 +6137,7 @@ finish:
DBUG_ASSERT(! thd->in_sub_stmt);
if (!(thd->variables.option_bits & OPTION_GTID_BEGIN))
{
+ THD_STAGE_INFO(thd, stage_commit_implicit);
/* 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. */
@@ -6106,6 +6165,8 @@ finish:
thd->mdl_context.release_statement_locks();
}
+ THD_STAGE_INFO(thd, stage_starting_cleanup);
+
TRANSACT_TRACKER(add_trx_state_from_thd(thd));
WSREP_TO_ISOLATION_END;
@@ -6153,7 +6214,7 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
to prepend EXPLAIN to any query and receive output for it,
even if the query itself redirects the output.
*/
- if (!(result= new (thd->mem_root) select_send(thd)))
+ if (unlikely(!(result= new (thd->mem_root) select_send(thd))))
return 1; /* purecov: inspected */
thd->send_explain_fields(result, lex->describe, lex->analyze_stmt);
@@ -6164,7 +6225,7 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
res= mysql_explain_union(thd, &lex->unit, result);
/* Print EXPLAIN only if we don't have an error */
- if (!res)
+ if (likely(!res))
{
/*
Do like the original select_describe did: remove OFFSET from the
@@ -6335,11 +6396,11 @@ static bool check_rename_table(THD *thd, TABLE_LIST *first_table,
TABLE_LIST *table;
for (table= first_table; table; table= table->next_local->next_local)
{
- if (check_access(thd, ALTER_ACL | DROP_ACL, table->db,
+ if (check_access(thd, ALTER_ACL | DROP_ACL, table->db.str,
&table->grant.privilege,
&table->grant.m_internal,
0, 0) ||
- check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db,
+ check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db.str,
&table->next_local->grant.privilege,
&table->next_local->grant.m_internal,
0, 0))
@@ -6432,13 +6493,15 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
dummy= 0;
}
- THD_STAGE_INFO(thd, stage_checking_permissions);
- if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
+ /* check access may be called twice in a row. Don't change to same stage */
+ if (thd->proc_info != stage_checking_permissions.m_name)
+ THD_STAGE_INFO(thd, stage_checking_permissions);
+ if (unlikely((!db || !db[0]) && !thd->db.str && !dont_check_global_grants))
{
DBUG_RETURN(FALSE); // CTE reference or an error later
}
- if ((db != NULL) && (db != any_db))
+ if (likely((db != NULL) && (db != any_db)))
{
/*
Check if this is reserved database, like information schema or
@@ -6485,7 +6548,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
*/
if (!(sctx->master_access & SELECT_ACL))
{
- if (db && (!thd->db || db_is_pattern || strcmp(db, thd->db)))
+ if (db && (!thd->db.str || db_is_pattern || strcmp(db, thd->db.str)))
{
db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
db_is_pattern);
@@ -6508,8 +6571,8 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
*save_priv|= sctx->master_access;
DBUG_RETURN(FALSE);
}
- if (((want_access & ~sctx->master_access) & ~DB_ACLS) ||
- (! db && dont_check_global_grants))
+ if (unlikely(((want_access & ~sctx->master_access) & ~DB_ACLS) ||
+ (! db && dont_check_global_grants)))
{ // We can never grant this
DBUG_PRINT("error",("No possible access"));
if (!no_errors)
@@ -6525,7 +6588,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
DBUG_RETURN(TRUE); /* purecov: tested */
}
- if (db == any_db)
+ if (unlikely(db == any_db))
{
/*
Access granted; Allow select on *any* db.
@@ -6534,7 +6597,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
DBUG_RETURN(FALSE);
}
- if (db && (!thd->db || db_is_pattern || strcmp(db,thd->db)))
+ if (db && (!thd->db.str || db_is_pattern || strcmp(db, thd->db.str)))
{
db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
db_is_pattern);
@@ -6589,8 +6652,8 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
status_var_increment(thd->status_var.access_denied_errors);
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user, sctx->priv_host,
- (db ? db : (thd->db ?
- thd->db :
+ (db ? db : (thd->db.str ?
+ thd->db.str :
"unknown")));
}
DBUG_RETURN(TRUE);
@@ -6628,7 +6691,7 @@ bool check_single_table_access(THD *thd, ulong privilege,
!all_tables->schema_table)
db_name= all_tables->view_db.str;
else
- db_name= all_tables->db;
+ db_name= all_tables->db.str;
if (check_access(thd, privilege, db_name,
&all_tables->grant.privilege,
@@ -6717,7 +6780,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
case SCH_TRIGGERS:
case SCH_EVENTS:
{
- const char *dst_db_name= table->schema_select_lex->db;
+ const char *dst_db_name= table->schema_select_lex->db.str;
DBUG_ASSERT(dst_db_name);
@@ -6752,7 +6815,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
if (thd->open_temporary_tables(dst_table))
return TRUE;
- if (check_access(thd, SELECT_ACL, dst_table->db,
+ if (check_access(thd, SELECT_ACL, dst_table->db.str,
&dst_table->grant.privilege,
&dst_table->grant.m_internal,
FALSE, FALSE))
@@ -6862,6 +6925,15 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
thd->security_ctx= sctx;
+ if (table_ref->sequence)
+ {
+ /* We want to have either SELECT or INSERT rights to sequences depending
+ on how they are accessed
+ */
+ want_access= ((table_ref->lock_type == TL_WRITE_ALLOW_WRITE) ?
+ INSERT_ACL : SELECT_ACL);
+ }
+
if (check_access(thd, want_access, table_ref->get_db_name(),
&table_ref->grant.privilege,
&table_ref->grant.m_internal,
@@ -6879,14 +6951,15 @@ deny:
bool
-check_routine_access(THD *thd, ulong want_access,char *db, char *name,
- bool is_proc, bool no_errors)
+check_routine_access(THD *thd, ulong want_access, const LEX_CSTRING *db,
+ const LEX_CSTRING *name,
+ const Sp_handler *sph, bool no_errors)
{
TABLE_LIST tables[1];
bzero((char *)tables, sizeof(TABLE_LIST));
- tables->db= db;
- tables->table_name= tables->alias= name;
+ tables->db= *db;
+ tables->table_name= tables->alias= *name;
/*
The following test is just a shortcut for check_access() (to avoid
@@ -6903,13 +6976,13 @@ check_routine_access(THD *thd, ulong want_access,char *db, char *name,
DBUG_ASSERT((want_access & CREATE_PROC_ACL) == 0);
if ((thd->security_ctx->master_access & want_access) == want_access)
tables->grant.privilege= want_access;
- else if (check_access(thd, want_access, db,
+ else if (check_access(thd, want_access, db->str,
&tables->grant.privilege,
&tables->grant.m_internal,
0, no_errors))
return TRUE;
- return check_grant_routine(thd, want_access, tables, is_proc, no_errors);
+ return check_grant_routine(thd, want_access, tables, sph, no_errors);
}
@@ -6927,7 +7000,7 @@ check_routine_access(THD *thd, ulong want_access,char *db, char *name,
*/
bool check_some_routine_access(THD *thd, const char *db, const char *name,
- bool is_proc)
+ const Sp_handler *sph)
{
ulong save_priv;
/*
@@ -6944,7 +7017,7 @@ bool check_some_routine_access(THD *thd, const char *db, const char *name,
if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, NULL, 0, 1) ||
(save_priv & SHOW_PROC_ACLS))
return FALSE;
- return check_routine_level_acl(thd, db, name, is_proc);
+ return check_routine_level_acl(thd, db, name, sph);
}
@@ -6970,7 +7043,7 @@ bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table)
{
if (access & want_access)
{
- if (!check_access(thd, access, table->db,
+ if (!check_access(thd, access, table->db.str,
&table->grant.privilege,
&table->grant.m_internal,
0, 1) &&
@@ -7009,7 +7082,7 @@ bool check_global_access(THD *thd, ulong want_access, bool no_errors)
char command[128];
if ((thd->security_ctx->master_access & want_access))
return 0;
- if (!no_errors)
+ if (unlikely(!no_errors))
{
get_privilege_desc(command, sizeof(command), want_access);
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command);
@@ -7052,8 +7125,8 @@ bool check_fk_parent_table_access(THD *thd,
TABLE_LIST parent_table;
bool is_qualified_table_name;
Foreign_key *fk_key= (Foreign_key *)key;
- LEX_STRING db_name;
- LEX_STRING table_name= { fk_key->ref_table.str,
+ LEX_CSTRING db_name;
+ LEX_CSTRING table_name= { fk_key->ref_table.str,
fk_key->ref_table.length };
const ulong privileges= (SELECT_ACL | INSERT_ACL | UPDATE_ACL |
DELETE_ACL | REFERENCES_ACL);
@@ -7069,12 +7142,13 @@ bool check_fk_parent_table_access(THD *thd,
if (fk_key->ref_db.str)
{
is_qualified_table_name= true;
- db_name.str= (char *) thd->memdup(fk_key->ref_db.str,
- fk_key->ref_db.length+1);
+ if (!(db_name.str= (char *) thd->memdup(fk_key->ref_db.str,
+ fk_key->ref_db.length+1)))
+ return true;
db_name.length= fk_key->ref_db.length;
// Check if database name is valid or not.
- if (fk_key->ref_db.str && check_db_name(&db_name))
+ if (check_db_name((LEX_STRING*) &db_name))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
return true;
@@ -7082,13 +7156,16 @@ bool check_fk_parent_table_access(THD *thd,
}
else
{
- if (!thd->db)
+ if (!thd->db.str)
{
- db_name.str= (char *) thd->memdup(create_db, strlen(create_db)+1);
+ DBUG_ASSERT(create_db);
db_name.length= strlen(create_db);
+ if (!(db_name.str= (char *) thd->memdup(create_db,
+ db_name.length+1)))
+ return true;
is_qualified_table_name= true;
- if(create_db && check_db_name(&db_name))
+ if (check_db_name((LEX_STRING*) &db_name))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
return true;
@@ -7096,7 +7173,7 @@ bool check_fk_parent_table_access(THD *thd,
}
else
{
- if (thd->lex->copy_db_to(&db_name.str, &db_name.length))
+ if (thd->lex->copy_db_to(&db_name))
return true;
else
is_qualified_table_name= false;
@@ -7106,15 +7183,14 @@ bool check_fk_parent_table_access(THD *thd,
// if lower_case_table_names is set then convert tablename to lower case.
if (lower_case_table_names)
{
- table_name.str= (char *) thd->memdup(fk_key->ref_table.str,
- fk_key->ref_table.length+1);
- table_name.length= my_casedn_str(files_charset_info, table_name.str);
- db_name.length = my_casedn_str(files_charset_info, db_name.str);
+ char *name;
+ table_name.str= name= (char *) thd->memdup(fk_key->ref_table.str,
+ fk_key->ref_table.length+1);
+ table_name.length= my_casedn_str(files_charset_info, name);
+ db_name.length= my_casedn_str(files_charset_info, (char*) db_name.str);
}
- parent_table.init_one_table(db_name.str, db_name.length,
- table_name.str, table_name.length,
- table_name.str, TL_IGNORE);
+ parent_table.init_one_table(&db_name, &table_name, 0, TL_IGNORE);
/*
Check if user has any of the "privileges" at table level on
@@ -7199,16 +7275,16 @@ bool check_stack_overrun(THD *thd, long margin,
#define MY_YACC_INIT 1000 // Start with big alloc
#define MY_YACC_MAX 32000 // Because of 'short'
-bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
+bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, size_t *yystacksize)
{
Yacc_state *state= & current_thd->m_parser_state->m_yacc;
- ulong old_info=0;
+ size_t old_info=0;
DBUG_ASSERT(state);
- if ((uint) *yystacksize >= MY_YACC_MAX)
+ if ( *yystacksize >= MY_YACC_MAX)
return 1;
if (!state->yacc_yyvs)
old_info= *yystacksize;
- *yystacksize= set_zone((*yystacksize)*2,MY_YACC_INIT,MY_YACC_MAX);
+ *yystacksize= set_zone((int)(*yystacksize)*2,MY_YACC_INIT,MY_YACC_MAX);
if (!(state->yacc_yyvs= (uchar*)
my_realloc(state->yacc_yyvs,
*yystacksize*sizeof(**yyvs),
@@ -7249,17 +7325,16 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
void THD::reset_for_next_command(bool do_clear_error)
{
- THD *thd= this;
DBUG_ENTER("THD::reset_for_next_command");
- DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */
- DBUG_ASSERT(! thd->in_sub_stmt);
+ DBUG_ASSERT(!spcont); /* not for substatements of routines */
+ DBUG_ASSERT(!in_sub_stmt);
- if (do_clear_error)
+ if (likely(do_clear_error))
clear_error(1);
- thd->free_list= 0;
+ free_list= 0;
/*
- We also assign thd->stmt_lex in lex_start(), but during bootstrap this
+ We also assign stmt_lex in lex_start(), but during bootstrap this
code is executed first.
*/
DBUG_ASSERT(lex == &main_lex);
@@ -7269,8 +7344,8 @@ void THD::reset_for_next_command(bool do_clear_error)
Those two lines below are theoretically unneeded as
THD::cleanup_after_query() should take care of this already.
*/
- thd->auto_inc_intervals_in_cur_stmt_for_binlog.empty();
- thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
+ auto_inc_intervals_in_cur_stmt_for_binlog.empty();
+ stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
#ifdef WITH_WSREP
/*
@@ -7281,58 +7356,56 @@ void THD::reset_for_next_command(bool do_clear_error)
use autoinc values passed in binlog events, not the values forced by
the cluster.
*/
- if (WSREP(thd) && thd->wsrep_exec_mode == LOCAL_STATE &&
- !thd->slave_thread && wsrep_auto_increment_control)
+ if (WSREP(this) && wsrep_exec_mode == LOCAL_STATE &&
+ !slave_thread && wsrep_auto_increment_control)
{
- thd->variables.auto_increment_offset=
+ variables.auto_increment_offset=
global_system_variables.auto_increment_offset;
- thd->variables.auto_increment_increment=
+ variables.auto_increment_increment=
global_system_variables.auto_increment_increment;
}
#endif /* WITH_WSREP */
- 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;
+ query_start_sec_part_used= 0;
+ is_fatal_error= time_zone_used= 0;
+ log_current_statement= 0;
/*
Clear the status flag that are expected to be cleared at the
beginning of each SQL statement.
*/
- thd->server_status&= ~SERVER_STATUS_CLEAR_SET;
+ server_status&= ~SERVER_STATUS_CLEAR_SET;
/*
If in autocommit mode and not in a transaction, reset
OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
in ha_rollback_trans() about some tables couldn't be rolled back.
*/
- if (!thd->in_multi_stmt_transaction_mode())
+ if (!in_multi_stmt_transaction_mode())
{
- thd->variables.option_bits&= ~OPTION_KEEP_LOG;
- thd->transaction.all.reset();
+ variables.option_bits&= ~OPTION_KEEP_LOG;
+ transaction.all.reset();
}
- DBUG_ASSERT(thd->security_ctx== &thd->main_security_ctx);
- thd->thread_specific_used= FALSE;
+ DBUG_ASSERT(security_ctx== &main_security_ctx);
+ thread_specific_used= FALSE;
if (opt_bin_log)
- reset_dynamic(&thd->user_var_events);
- DBUG_ASSERT(thd->user_var_events_alloc == &thd->main_mem_root);
+ reset_dynamic(&user_var_events);
+ DBUG_ASSERT(user_var_events_alloc == &main_mem_root);
+ enable_slow_log= true;
+ get_stmt_da()->reset_for_next_command();
+ rand_used= 0;
+ m_sent_row_count= m_examined_row_count= 0;
+ accessed_rows_and_keys= 0;
- 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;
+ reset_slow_query_state();
- thd->query_plan_flags= QPLAN_INIT;
- thd->query_plan_fsort_passes= 0;
-
- thd->reset_current_stmt_binlog_format_row();
- thd->binlog_unsafe_warning_flags= 0;
+ reset_current_stmt_binlog_format_row();
+ binlog_unsafe_warning_flags= 0;
- thd->save_prep_leaf_list= false;
+ save_prep_leaf_list= false;
DBUG_PRINT("debug",
("is_current_stmt_binlog_format_row(): %d",
- thd->is_current_stmt_binlog_format_row()));
+ is_current_stmt_binlog_format_row()));
DBUG_VOID_RETURN;
}
@@ -7373,18 +7446,21 @@ mysql_init_select(LEX *lex)
*/
bool
-mysql_new_select(LEX *lex, bool move_down)
+mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
{
- SELECT_LEX *select_lex;
THD *thd= lex->thd;
+ bool new_select= select_lex == NULL;
DBUG_ENTER("mysql_new_select");
- if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
- DBUG_RETURN(1);
- select_lex->select_number= ++thd->lex->stmt_lex->current_select_number;
- select_lex->parent_lex= lex; /* Used in init_query. */
- select_lex->init_query();
- select_lex->init_select();
+ if (new_select)
+ {
+ if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
+ DBUG_RETURN(1);
+ select_lex->select_number= ++thd->lex->stmt_lex->current_select_number;
+ select_lex->parent_lex= lex; /* Used in init_query. */
+ select_lex->init_query();
+ select_lex->init_select();
+ }
lex->nest_level++;
if (lex->nest_level > (int) MAX_SELECT_NESTING)
{
@@ -7396,13 +7472,11 @@ mysql_new_select(LEX *lex, bool move_down)
if (move_down)
{
SELECT_LEX_UNIT *unit;
- lex->subqueries= TRUE;
/* first select_lex of subselect or derived table */
if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT()))
DBUG_RETURN(1);
unit->init_query();
- unit->init_select();
unit->thd= thd;
unit->include_down(lex->current_select);
unit->link_next= 0;
@@ -7455,7 +7529,8 @@ mysql_new_select(LEX *lex, bool move_down)
unit->first_select()->context.outer_context;
}
- select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
+ if (new_select)
+ select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
lex->current_select= select_lex;
/*
in subquery is SELECT query and we allow resolution of names in SELECT
@@ -7475,28 +7550,23 @@ mysql_new_select(LEX *lex, bool move_down)
@param var_name Variable name
*/
-void create_select_for_variable(const char *var_name)
+void create_select_for_variable(THD *thd, LEX_CSTRING *var_name)
{
- THD *thd;
LEX *lex;
- LEX_STRING tmp;
Item *var;
char buff[MAX_SYS_VAR_LENGTH*2+4+8], *end;
DBUG_ENTER("create_select_for_variable");
- thd= current_thd;
lex= thd->lex;
mysql_init_select(lex);
lex->sql_command= SQLCOM_SELECT;
- tmp.str= (char*) var_name;
- tmp.length=strlen(var_name);
/*
We set the name of Item to @@session.var_name because that then is used
as the column name in the output.
*/
- if ((var= get_system_var(thd, OPT_SESSION, tmp, null_lex_str)))
+ if ((var= get_system_var(thd, OPT_SESSION, var_name, &null_clex_str)))
{
- end= strxmov(buff, "@@session.", var_name, NullS);
+ end= strxmov(buff, "@@session.", var_name->str, NullS);
var->set_name(thd, buff, (uint)(end-buff), system_charset_info);
add_item_to_list(thd, var);
}
@@ -7711,7 +7781,7 @@ void mysql_parse(THD *thd, char *rawbuf, uint length,
bool err= parse_sql(thd, parser_state, NULL, true);
- if (!err)
+ if (likely(!err))
{
thd->m_statement_psi=
MYSQL_REFINE_STATEMENT(thd->m_statement_psi,
@@ -7726,7 +7796,7 @@ void mysql_parse(THD *thd, char *rawbuf, uint length,
else
#endif
{
- if (! thd->is_error())
+ if (likely(! thd->is_error()))
{
const char *found_semicolon= parser_state->m_lip.found_semicolon;
/*
@@ -7751,7 +7821,7 @@ void mysql_parse(THD *thd, char *rawbuf, uint length,
lex->set_trg_event_type_for_tables();
MYSQL_QUERY_EXEC_START(thd->query(),
thd->thread_id,
- (char *) (thd->db ? thd->db : ""),
+ thd->get_db(),
&thd->security_ctx->priv_user[0],
(char *) thd->security_ctx->host_or_ip,
0);
@@ -7776,6 +7846,8 @@ void mysql_parse(THD *thd, char *rawbuf, uint length,
THD_STAGE_INFO(thd, stage_freeing_items);
sp_cache_enforce_limit(thd->sp_proc_cache, stored_program_cache_size);
sp_cache_enforce_limit(thd->sp_func_cache, stored_program_cache_size);
+ sp_cache_enforce_limit(thd->sp_package_spec_cache, stored_program_cache_size);
+ sp_cache_enforce_limit(thd->sp_package_body_cache, stored_program_cache_size);
thd->end_statement();
thd->cleanup_after_query();
DBUG_ASSERT(thd->Item_change_list::is_empty());
@@ -7818,7 +7890,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *rawbuf, uint length)
DBUG_ENTER("mysql_test_parse_for_slave");
Parser_state parser_state;
- if (!(error= parser_state.init(thd, rawbuf, length)))
+ if (likely(!(error= parser_state.init(thd, rawbuf, length))))
{
lex_start(thd);
thd->reset_for_next_command();
@@ -7840,7 +7912,7 @@ add_proc_to_list(THD* thd, Item *item)
ORDER *order;
Item **item_ptr;
- if (!(order = (ORDER *) thd->alloc(sizeof(ORDER)+sizeof(Item*))))
+ if (unlikely(!(order = (ORDER *) thd->alloc(sizeof(ORDER)+sizeof(Item*)))))
return 1;
item_ptr = (Item**) (order+1);
*item_ptr= item;
@@ -7858,7 +7930,7 @@ bool add_to_list(THD *thd, SQL_I_List<ORDER> &list, Item *item,bool asc)
{
ORDER *order;
DBUG_ENTER("add_to_list");
- if (!(order = (ORDER *) thd->alloc(sizeof(ORDER))))
+ if (unlikely(!(order = (ORDER *) thd->alloc(sizeof(ORDER)))))
DBUG_RETURN(1);
order->item_ptr= item;
order->item= &order->item_ptr;
@@ -7893,7 +7965,7 @@ bool add_to_list(THD *thd, SQL_I_List<ORDER> &list, Item *item,bool asc)
TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
Table_ident *table,
- LEX_STRING *alias,
+ LEX_CSTRING *alias,
ulong table_options,
thr_lock_type lock_type,
enum_mdl_type mdl_type,
@@ -7903,47 +7975,48 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
{
TABLE_LIST *ptr;
TABLE_LIST *UNINIT_VAR(previous_table_ref); /* The table preceding the current one. */
- char *alias_str;
+ LEX_CSTRING alias_str;
LEX *lex= thd->lex;
DBUG_ENTER("add_table_to_list");
- if (!table)
+ if (unlikely(!table))
DBUG_RETURN(0); // End of memory
- alias_str= alias ? alias->str : table->table.str;
+ alias_str= alias ? *alias : table->table;
+ DBUG_ASSERT(alias_str.str);
if (!MY_TEST(table_options & TL_OPTION_ALIAS) &&
- check_table_name(table->table.str, table->table.length, FALSE))
+ unlikely(check_table_name(table->table.str, table->table.length, FALSE)))
{
my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
DBUG_RETURN(0);
}
- if (table->is_derived_table() == FALSE && table->db.str &&
- check_db_name(&table->db))
+ if (unlikely(table->is_derived_table() == FALSE && table->db.str &&
+ check_db_name((LEX_STRING*) &table->db)))
{
my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
DBUG_RETURN(0);
}
- if (!alias) /* Alias is case sensitive */
+ if (!alias) /* Alias is case sensitive */
{
- if (table->sel)
+ if (unlikely(table->sel))
{
my_message(ER_DERIVED_MUST_HAVE_ALIAS,
ER_THD(thd, ER_DERIVED_MUST_HAVE_ALIAS), MYF(0));
DBUG_RETURN(0);
}
- if (!(alias_str= (char*) thd->memdup(alias_str,table->table.length+1)))
+ /* alias_str points to table->table; Let's make a copy */
+ if (unlikely(!(alias_str.str= (char*) thd->memdup(alias_str.str, alias_str.length+1))))
DBUG_RETURN(0);
}
- if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
+ if (unlikely(!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))))
DBUG_RETURN(0); /* purecov: inspected */
if (table->db.str)
{
ptr->is_fqtn= TRUE;
- ptr->db= table->db.str;
- ptr->db_length= table->db.length;
+ ptr->db= table->db;
}
- else if (lex->copy_db_to(&ptr->db, &ptr->db_length))
+ else if (lex->copy_db_to(&ptr->db))
DBUG_RETURN(0);
else
ptr->is_fqtn= FALSE;
@@ -7953,20 +8026,21 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
if (lower_case_table_names)
{
if (table->table.length)
- table->table.length= my_casedn_str(files_charset_info, table->table.str);
- if (ptr->db_length && ptr->db != any_db)
- ptr->db_length= my_casedn_str(files_charset_info, ptr->db);
+ table->table.length= my_casedn_str(files_charset_info,
+ (char*) table->table.str);
+ if (ptr->db.length && ptr->db.str != any_db)
+ ptr->db.length= my_casedn_str(files_charset_info, (char*) ptr->db.str);
}
- ptr->table_name=table->table.str;
- ptr->table_name_length=table->table.length;
+ ptr->table_name= table->table;
ptr->lock_type= lock_type;
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= MY_TEST(table_options & TL_OPTION_FORCE_INDEX);
ptr->ignore_leaves= MY_TEST(table_options & TL_OPTION_IGNORE_LEAVES);
+ ptr->sequence= MY_TEST(table_options & TL_OPTION_SEQUENCE);
ptr->derived= table->sel;
- if (!ptr->derived && is_infoschema_db(ptr->db, ptr->db_length))
+ if (!ptr->derived && is_infoschema_db(&ptr->db))
{
if (ptr->updating &&
/* Special cases which are processed by commands itself */
@@ -7980,7 +8054,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
DBUG_RETURN(0);
}
ST_SCHEMA_TABLE *schema_table;
- schema_table= find_schema_table(thd, ptr->table_name);
+ schema_table= find_schema_table(thd, &ptr->table_name);
ptr->schema_table_name= ptr->table_name;
ptr->schema_table= schema_table;
}
@@ -7992,8 +8066,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
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 */
- if (lock_type != TL_IGNORE)
+ /* check that used name is unique. Sequences are ignored */
+ if (lock_type != TL_IGNORE && !ptr->sequence)
{
TABLE_LIST *first_table= table_list.first;
if (lex->sql_command == SQLCOM_CREATE_VIEW)
@@ -8002,16 +8076,17 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
tables ;
tables=tables->next_local)
{
- if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
- !strcmp(ptr->db, tables->db))
+ if (unlikely(!my_strcasecmp(table_alias_charset, alias_str.str,
+ tables->alias.str) &&
+ !cmp(&ptr->db, &tables->db) && ! tables->sequence))
{
- my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str); /* purecov: tested */
+ my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str.str); /* purecov: tested */
DBUG_RETURN(0); /* purecov: tested */
}
}
}
/* Store the table reference preceding the current one. */
- if (table_list.elements > 0)
+ if (table_list.elements > 0 && likely(!ptr->sequence))
{
/*
table_list.next points to the last inserted TABLE_LIST->next_local'
@@ -8036,8 +8111,11 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
Notice that as a side effect here we set the next_local field of the
previous table reference to 'ptr'. Here we also add one element to the
list 'table_list'.
+ We don't store sequences into the local list to hide them from INSERT
+ and SELECT.
*/
- table_list.link_in_list(ptr, &ptr->next_local);
+ if (likely(!ptr->sequence))
+ 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;
@@ -8046,9 +8124,10 @@ 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 (ptr->db && !(table_options & TL_OPTION_ALIAS))
+ if (ptr->db.str && !(table_options & TL_OPTION_ALIAS))
{
- ptr->mdl_request.init(MDL_key::TABLE, ptr->db, ptr->table_name, mdl_type,
+ ptr->mdl_request.init(MDL_key::TABLE, ptr->db.str, ptr->table_name.str,
+ mdl_type,
MDL_TRANSACTION);
}
DBUG_RETURN(ptr);
@@ -8080,16 +8159,18 @@ bool st_select_lex::init_nested_join(THD *thd)
NESTED_JOIN *nested_join;
DBUG_ENTER("init_nested_join");
- if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
- sizeof(NESTED_JOIN))))
+ if (unlikely(!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
+ sizeof(NESTED_JOIN)))))
DBUG_RETURN(1);
nested_join= ptr->nested_join=
((NESTED_JOIN*) ((uchar*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST))));
- join_list->push_front(ptr, thd->mem_root);
+ if (unlikely(join_list->push_front(ptr, thd->mem_root)))
+ DBUG_RETURN(1);
ptr->embedding= embedding;
ptr->join_list= join_list;
- ptr->alias= (char*) "(nested_join)";
+ ptr->alias.str="(nested_join)";
+ ptr->alias.length= sizeof("(nested_join)")-1;
embedding= ptr;
join_list= &nested_join->join_list;
join_list->empty();
@@ -8169,16 +8250,16 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
{
DBUG_RETURN(head);
}
-
- if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
- sizeof(NESTED_JOIN))))
+ if (unlikely(!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
+ sizeof(NESTED_JOIN)))))
DBUG_RETURN(0);
nested_join= ptr->nested_join=
((NESTED_JOIN*) ((uchar*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST))));
ptr->embedding= embedding;
ptr->join_list= join_list;
- ptr->alias= (char*) "(nest_last_join)";
+ ptr->alias.str= "(nest_last_join)";
+ ptr->alias.length= sizeof("(nest_last_join)")-1;
embedded_list= &nested_join->join_list;
embedded_list->empty();
nested_join->nest_type= JOIN_OP_NEST;
@@ -8186,7 +8267,7 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
for (uint i=0; i < 2; i++)
{
TABLE_LIST *table= join_list->pop();
- if (!table)
+ if (unlikely(!table))
DBUG_RETURN(NULL);
table->join_list= embedded_list;
table->embedding= ptr;
@@ -8460,7 +8541,8 @@ bool st_select_lex::add_cross_joined_table(TABLE_LIST *left_op,
cj_nest->on_expr= tbl->on_expr;
cj_nest->embedding= tbl->embedding;
cj_nest->join_list= jl;
- cj_nest->alias= (char*) "(nest_last_join)";
+ cj_nest->alias.str= "(nest_last_join)";
+ cj_nest->alias.length= sizeof("(nest_last_join)");
li.replace(cj_nest);
/*
@@ -8563,8 +8645,8 @@ void st_select_lex::prepare_add_window_spec(THD *thd)
}
bool st_select_lex::add_window_def(THD *thd,
- LEX_STRING *win_name,
- LEX_STRING *win_ref,
+ LEX_CSTRING *win_name,
+ LEX_CSTRING *win_ref,
SQL_I_List<ORDER> win_partition_list,
SQL_I_List<ORDER> win_order_list,
Window_frame *win_frame)
@@ -8586,7 +8668,7 @@ bool st_select_lex::add_window_def(THD *thd,
}
bool st_select_lex::add_window_spec(THD *thd,
- LEX_STRING *win_ref,
+ LEX_CSTRING *win_ref,
SQL_I_List<ORDER> win_partition_list,
SQL_I_List<ORDER> win_order_list,
Window_frame *win_frame)
@@ -8686,7 +8768,7 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
fake_select_lex->nest_level_base= first_select()->nest_level_base;
fake_select_lex->nest_level=first_select()->nest_level;
- if (!is_union())
+ if (!is_unit_op())
{
/*
This works only for
@@ -8836,13 +8918,13 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields,
/**
- Find a thread by id and return it, locking it LOCK_thd_data
+ Find a thread by id and return it, locking it LOCK_thd_kill
@param id Identifier of the thread we're looking for
@param query_id If true, search by query_id instead of thread_id
@return NULL - not found
- pointer - thread found, and its LOCK_thd_data is locked.
+ pointer - thread found, and its LOCK_thd_kill is locked.
*/
THD *find_thread_by_id(longlong id, bool query_id)
@@ -8856,7 +8938,7 @@ THD *find_thread_by_id(longlong id, bool query_id)
continue;
if (id == (query_id ? tmp->query_id : (longlong) tmp->thread_id))
{
- mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
+ mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete
break;
}
}
@@ -8912,13 +8994,13 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
thd->security_ctx->user_matches(tmp->security_ctx)) &&
!wsrep_thd_is_BF(tmp, false))
{
- tmp->awake(kill_signal);
+ tmp->awake_no_mutex(kill_signal);
error=0;
}
else
error= (type == KILL_TYPE_QUERY ? ER_KILL_QUERY_DENIED_ERROR :
ER_KILL_DENIED_ERROR);
- mysql_mutex_unlock(&tmp->LOCK_thd_data);
+ mysql_mutex_unlock(&tmp->LOCK_thd_kill);
}
DBUG_PRINT("exit", ("%d", error));
DBUG_RETURN(error);
@@ -8948,7 +9030,7 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user,
*rows= 0;
- if (thd->is_fatal_error) // If we run out of memory
+ if (unlikely(thd->is_fatal_error)) // If we run out of memory
DBUG_RETURN(ER_OUT_OF_RESOURCES);
DBUG_PRINT("enter", ("user: %s signal: %u", user->user.str,
@@ -8976,7 +9058,7 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user,
DBUG_RETURN(ER_KILL_DENIED_ERROR);
}
if (!threads_to_kill.push_back(tmp, thd->mem_root))
- mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
+ mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete
}
}
mysql_mutex_unlock(&LOCK_thread_count);
@@ -8987,17 +9069,17 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user,
THD *ptr= it2++;
do
{
- ptr->awake(kill_signal);
+ ptr->awake_no_mutex(kill_signal);
/*
Careful here: The list nodes are allocated on the memroots of the
THDs to be awakened.
But those THDs may be terminated and deleted as soon as we release
- LOCK_thd_data, which will make the list nodes invalid.
+ LOCK_thd_kill, which will make the list nodes invalid.
Since the operation "it++" dereferences the "next" pointer of the
- previous list node, we need to do this while holding LOCK_thd_data.
+ previous list node, we need to do this while holding LOCK_thd_kill.
*/
next_ptr= it2++;
- mysql_mutex_unlock(&ptr->LOCK_thd_data);
+ mysql_mutex_unlock(&ptr->LOCK_thd_kill);
(*rows)++;
} while ((ptr= next_ptr));
}
@@ -9018,7 +9100,7 @@ static
void sql_kill(THD *thd, longlong id, killed_state state, killed_type type)
{
uint error;
- if (!(error= kill_one_thread(thd, id, state, type)))
+ if (likely(!(error= kill_one_thread(thd, id, state, type))))
{
if (!thd->killed)
my_ok(thd);
@@ -9035,7 +9117,7 @@ void sql_kill_user(THD *thd, LEX_USER *user, killed_state state)
{
uint error;
ha_rows rows;
- if (!(error= kill_threads_for_user(thd, user, state, &rows)))
+ if (likely(!(error= kill_threads_for_user(thd, user, state, &rows))))
my_ok(thd, rows);
else
{
@@ -9051,14 +9133,14 @@ void sql_kill_user(THD *thd, LEX_USER *user, killed_state state)
/** If pointer is not a null pointer, append filename to it. */
bool append_file_to_dir(THD *thd, const char **filename_ptr,
- const char *table_name)
+ const LEX_CSTRING *table_name)
{
char buff[FN_REFLEN],*ptr, *end;
if (!*filename_ptr)
return 0; // nothing to do
/* Check that the filename is not too long and it's a hard path */
- if (strlen(*filename_ptr)+strlen(table_name) >= FN_REFLEN-1 ||
+ if (strlen(*filename_ptr)+table_name->length >= FN_REFLEN-1 ||
!test_if_hard_path(*filename_ptr))
{
my_error(ER_WRONG_TABLE_NAME, MYF(0), *filename_ptr);
@@ -9067,36 +9149,11 @@ bool append_file_to_dir(THD *thd, const char **filename_ptr,
/* Fix is using unix filename format on dos */
strmov(buff,*filename_ptr);
end=convert_dirname(buff, *filename_ptr, NullS);
- if (!(ptr= (char*) thd->alloc((size_t) (end-buff) + strlen(table_name)+1)))
+ if (unlikely(!(ptr= (char*) thd->alloc((size_t) (end-buff) +
+ table_name->length + 1))))
return 1; // End of memory
*filename_ptr=ptr;
- strxmov(ptr,buff,table_name,NullS);
- return 0;
-}
-
-
-/**
- Check if the select is a simple select (not an union).
-
- @retval
- 0 ok
- @retval
- 1 error ; In this case the error messege is sent to the client
-*/
-
-bool check_simple_select()
-{
- THD *thd= current_thd;
- LEX *lex= thd->lex;
- if (lex->current_select != &lex->select_lex)
- {
- char command[80];
- Lex_input_stream *lip= & thd->m_parser_state->m_lip;
- strmake(command, lip->yylval->symbol.str,
- MY_MIN(lip->yylval->symbol.length, sizeof(command)-1));
- my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command);
- return 1;
- }
+ strxmov(ptr,buff,table_name->str,NullS);
return 0;
}
@@ -9185,7 +9242,6 @@ Item * all_any_subquery_creator(THD *thd, Item *left_expr,
bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
{
- const char *msg= 0;
TABLE_LIST *table;
LEX *lex= thd->lex;
SELECT_LEX *select_lex= &lex->select_lex;
@@ -9206,12 +9262,12 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
continue;
if (table->derived)
table->grant.privilege= SELECT_ACL;
- else if ((check_access(thd, UPDATE_ACL, table->db,
+ else if ((check_access(thd, UPDATE_ACL, table->db.str,
&table->grant.privilege,
&table->grant.m_internal,
0, 1) ||
check_grant(thd, UPDATE_ACL, table, FALSE, 1, TRUE)) &&
- (check_access(thd, SELECT_ACL, table->db,
+ (check_access(thd, SELECT_ACL, table->db.str,
&table->grant.privilege,
&table->grant.m_internal,
0, 0) ||
@@ -9231,7 +9287,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
{
if (!table->table_in_first_from_clause)
{
- if (check_access(thd, SELECT_ACL, table->db,
+ if (check_access(thd, SELECT_ACL, table->db.str,
&table->grant.privilege,
&table->grant.m_internal,
0, 0) ||
@@ -9241,15 +9297,6 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
}
}
- if (select_lex->order_list.elements)
- msg= "ORDER BY";
- else if (select_lex->select_limit)
- msg= "LIMIT";
- if (msg)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "UPDATE", msg);
- DBUG_RETURN(TRUE);
- }
DBUG_RETURN(FALSE);
}
@@ -9338,25 +9385,25 @@ static TABLE_LIST *multi_delete_table_match(LEX *lex, TABLE_LIST *tbl,
for (TABLE_LIST *elem= tables; elem; elem= elem->next_local)
{
- int cmp;
+ int res;
if (tbl->is_fqtn && elem->is_alias)
continue; /* no match */
if (tbl->is_fqtn && elem->is_fqtn)
- cmp= my_strcasecmp(table_alias_charset, tbl->table_name, elem->table_name) ||
- strcmp(tbl->db, elem->db);
+ res= (my_strcasecmp(table_alias_charset, tbl->table_name.str, elem->table_name.str) ||
+ cmp(&tbl->db, &elem->db));
else if (elem->is_alias)
- cmp= my_strcasecmp(table_alias_charset, tbl->alias, elem->alias);
+ res= my_strcasecmp(table_alias_charset, tbl->alias.str, elem->alias.str);
else
- cmp= my_strcasecmp(table_alias_charset, tbl->table_name, elem->table_name) ||
- strcmp(tbl->db, elem->db);
+ res= (my_strcasecmp(table_alias_charset, tbl->table_name.str, elem->table_name.str) ||
+ cmp(&tbl->db, &elem->db));
- if (cmp)
+ if (res)
continue;
if (match)
{
- my_error(ER_NONUNIQ_TABLE, MYF(0), elem->alias);
+ my_error(ER_NONUNIQ_TABLE, MYF(0), elem->alias.str);
DBUG_RETURN(NULL);
}
@@ -9364,7 +9411,7 @@ static TABLE_LIST *multi_delete_table_match(LEX *lex, TABLE_LIST *tbl,
}
if (!match)
- my_error(ER_UNKNOWN_TABLE, MYF(0), tbl->table_name, "MULTI DELETE");
+ my_error(ER_UNKNOWN_TABLE, MYF(0), tbl->table_name.str, "MULTI DELETE");
DBUG_RETURN(match);
}
@@ -9399,10 +9446,7 @@ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
if (!walk)
DBUG_RETURN(TRUE);
if (!walk->derived)
- {
target_tbl->table_name= walk->table_name;
- target_tbl->table_name_length= walk->table_name_length;
- }
walk->updating= target_tbl->updating;
walk->lock_type= target_tbl->lock_type;
/* We can assume that tables to be deleted from are locked for write. */
@@ -9453,10 +9497,18 @@ bool update_precheck(THD *thd, TABLE_LIST *tables)
bool delete_precheck(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("delete_precheck");
- if (check_one_table_access(thd, DELETE_ACL, tables))
- DBUG_RETURN(TRUE);
- /* Set privilege for the WHERE clause */
- tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
+ if (tables->vers_conditions.is_set())
+ {
+ if (check_one_table_access(thd, DELETE_HISTORY_ACL, tables))
+ DBUG_RETURN(TRUE);
+ }
+ else
+ {
+ if (check_one_table_access(thd, DELETE_ACL, tables))
+ DBUG_RETURN(TRUE);
+ /* Set privilege for the WHERE clause */
+ tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
+ }
DBUG_RETURN(FALSE);
}
@@ -9560,7 +9612,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
if (lex->create_info.or_replace() && !lex->tmp_table())
want_priv|= DROP_ACL;
- if (check_access(thd, want_priv, create_table->db,
+ if (check_access(thd, want_priv, create_table->db.str,
&create_table->grant.privilege,
&create_table->grant.m_internal,
0, 0))
@@ -9626,7 +9678,8 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
goto err;
}
- if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info, create_table->db))
+ if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info,
+ create_table->db.str))
goto err;
error= FALSE;
@@ -9713,7 +9766,7 @@ void get_default_definer(THD *thd, LEX_USER *definer, bool role)
if (role)
{
definer->user.str= const_cast<char*>(sctx->priv_role);
- definer->host= empty_lex_str;
+ definer->host= empty_clex_str;
}
else
{
@@ -9742,7 +9795,7 @@ LEX_USER *create_default_definer(THD *thd, bool role)
{
LEX_USER *definer;
- if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
+ if (unlikely(! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))))
return 0;
thd->get_definer(definer, role);
@@ -9770,13 +9823,14 @@ LEX_USER *create_default_definer(THD *thd, bool role)
- On error, return 0.
*/
-LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
+LEX_USER *create_definer(THD *thd, LEX_CSTRING *user_name,
+ LEX_CSTRING *host_name)
{
LEX_USER *definer;
/* Create and initialize. */
- if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
+ if (unlikely(!(definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))))
return 0;
definer->user= *user_name;
@@ -9804,8 +9858,8 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
The function is not used in existing code but can be useful later?
*/
-bool check_string_byte_length(LEX_STRING *str, uint err_msg,
- uint max_byte_length)
+bool check_string_byte_length(const LEX_CSTRING *str, uint err_msg,
+ size_t max_byte_length)
{
if (str->length <= max_byte_length)
return FALSE;
@@ -9834,12 +9888,13 @@ bool check_string_byte_length(LEX_STRING *str, uint err_msg,
*/
-bool check_string_char_length(LEX_STRING *str, uint err_msg,
- uint max_char_length, CHARSET_INFO *cs,
+bool check_string_char_length(const LEX_CSTRING *str, uint err_msg,
+ size_t max_char_length, CHARSET_INFO *cs,
bool no_error)
{
Well_formed_prefix prefix(cs, str->str, str->length, max_char_length);
- if (!prefix.well_formed_error_pos() && str->length == prefix.length())
+ if (likely(!prefix.well_formed_error_pos() &&
+ str->length == prefix.length()))
return FALSE;
if (!no_error)
@@ -9853,7 +9908,7 @@ bool check_string_char_length(LEX_STRING *str, uint err_msg,
}
-bool check_ident_length(LEX_STRING *ident)
+bool check_ident_length(const LEX_CSTRING *ident)
{
if (check_string_char_length(ident, 0, NAME_CHAR_LEN, system_charset_info, 1))
{
@@ -9879,7 +9934,7 @@ extern "C" {
int path_starts_from_data_home_dir(const char *path)
{
- int dir_len= strlen(path);
+ size_t dir_len= strlen(path);
DBUG_ENTER("path_starts_from_data_home_dir");
if (mysql_unpacked_real_data_home_len<= dir_len)
@@ -9963,7 +10018,7 @@ int error_if_data_home_dir(const char *path, const char *what)
has invalid symbols
*/
-bool check_host_name(LEX_STRING *str)
+bool check_host_name(LEX_CSTRING *str)
{
const char *name= str->str;
const char *end= str->str + str->length;
@@ -9986,6 +10041,7 @@ bool check_host_name(LEX_STRING *str)
extern int MYSQLparse(THD *thd); // from sql_yacc.cc
+extern int ORAparse(THD *thd); // from sql_yacc_ora.cc
/**
@@ -10029,8 +10085,7 @@ bool parse_sql(THD *thd, Parser_state *parser_state,
/* Start Digest */
parser_state->m_digest_psi= MYSQL_DIGEST_START(thd->m_statement_psi);
- if (parser_state->m_input.m_compute_digest ||
- (parser_state->m_digest_psi != NULL))
+ if (parser_state->m_digest_psi != NULL)
{
/*
If either:
@@ -10045,7 +10100,10 @@ bool parse_sql(THD *thd, Parser_state *parser_state,
/* Parse the query. */
- bool mysql_parse_status= MYSQLparse(thd) != 0;
+ bool mysql_parse_status=
+ ((thd->variables.sql_mode & MODE_ORACLE) ?
+ ORAparse(thd) :
+ MYSQLparse(thd)) != 0;
/*
Check that if MYSQLparse() failed either thd->is_error() is set, or an