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.cc661
1 files changed, 350 insertions, 311 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index ac742d79681..f9be9019489 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -101,6 +101,7 @@
#include "set_var.h"
#include "log_slow.h"
#include "sql_bootstrap.h"
+#include "sql_sequence.h"
#include "my_json_writer.h"
@@ -448,14 +449,17 @@ static 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.
@@ -542,19 +546,27 @@ 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;
sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS |
CF_INSERTS_DATA;
+ sql_command_flags[SQLCOM_ALTER_SEQUENCE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
+ CF_AUTO_COMMIT_TRANS | CF_SCHEMA_CHANGE;
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_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;
@@ -721,6 +733,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;
/* One can change replication mode with SET */
sql_command_flags[SQLCOM_SET_OPTION]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
@@ -763,6 +776,7 @@ void init_update_queries(void)
*/
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_PREOPEN_TMP_TABLES;
+ sql_command_flags[SQLCOM_DROP_SEQUENCE]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_TRUNCATE]|= CF_PREOPEN_TMP_TABLES;
@@ -795,7 +809,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;
@@ -813,8 +829,10 @@ 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;
@@ -1407,7 +1425,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
@@ -1425,13 +1443,12 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
LEX *lex= thd->lex;
- const my_bool user_is_super=
- ((ulong)(thd->security_ctx->master_access & SUPER_ACL) ==
- (ulong)SUPER_ACL);
-
- if (user_is_super)
+ /* 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);
@@ -1439,29 +1456,17 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
if (lex->sql_command == SQLCOM_UPDATE_MULTI)
DBUG_RETURN(FALSE);
- const my_bool create_temp_tables=
- (lex->sql_command == SQLCOM_CREATE_TABLE) && lex->tmp_table();
-
- const my_bool drop_temp_tables=
- (lex->sql_command == SQLCOM_DROP_TABLE) && lex->tmp_table();
-
- const my_bool update_real_tables=
- some_non_temp_table_to_be_updated(thd, all_tables) &&
- !(create_temp_tables || drop_temp_tables);
-
-
- const my_bool create_or_drop_databases=
- (lex->sql_command == SQLCOM_CREATE_DB) ||
- (lex->sql_command == SQLCOM_DROP_DB);
+ /* Check if we created or dropped temporary tables */
+ if ((sql_command_flags[lex->sql_command] & CF_SCHEMA_CHANGE) &&
+ lex->tmp_table())
+ DBUG_RETURN(FALSE);
- if (update_real_tables || create_or_drop_databases)
- {
- /*
- An attempt was made to modify one or more non-temporary tables.
- */
- DBUG_RETURN(TRUE);
- }
+ /* Check if we created or dropped databases */
+ 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);
@@ -1574,7 +1579,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (thd->wsrep_conflict_state == ABORTED &&
command != COM_STMT_CLOSE && command != COM_QUIT)
{
- my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction");
+ my_message(ER_LOCK_DEADLOCK, "wsrep aborted transaction", MYF(0));
WSREP_DEBUG("Deadlock error for: %s", thd->query());
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
thd->killed = NOT_KILLED;
@@ -1654,9 +1659,9 @@ 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,
+ if (thd->copy_with_error(system_charset_info, (LEX_STRING*) &tmp,
thd->charset(), packet, packet_length))
break;
if (!mysql_change_db(thd, &tmp, FALSE))
@@ -1726,7 +1731,7 @@ 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);
@@ -1745,7 +1750,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
decrease_user_connections(save_user_connect);
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
my_free(save_db);
- my_free(save_security_ctx.user);
+ my_free(const_cast<char*>(save_security_ctx.user));
}
break;
}
@@ -1922,7 +1927,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.
@@ -1969,7 +1974,7 @@ 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);
@@ -2110,7 +2115,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;
}
@@ -2291,7 +2296,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (server_command_flags[subcommand] & CF_NO_COM_MULTI)
{
- my_error(ER_BAD_COMMAND_IN_MULTI, MYF(0), command_name[subcommand]);
+ my_error(ER_BAD_COMMAND_IN_MULTI, MYF(0),
+ command_name[subcommand].str);
goto com_multi_end;
}
@@ -2533,10 +2539,16 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
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;
+ if (lower_case_table_names == 1)
+ lex->select_lex.db= thd->strdup(lex->select_lex.db);
+ 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.
+ */
+ db.str= (char*) lex->select_lex.db;
db.length= strlen(db.str);
-
if (check_db_name(&db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
@@ -2698,7 +2710,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
{
@@ -2863,7 +2875,7 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
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;
}
/*
@@ -2902,6 +2914,174 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
}
+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.str,
+ lex->sphead->m_name.str,
+ lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
+ return true;
+ }
+
+ const LEX_CSTRING *name= lex->sphead->name();
+#ifdef HAVE_DLOPEN
+ if (lex->sphead->m_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 (!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->str,
+ lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
+ {
+ if (sp_grant_privileges(thd, lex->sphead->m_db.str, name->str,
+ 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
+ return false;
+ }
+#ifdef WITH_WSREP
+error: /* Used by WSREP_TO_ISOLATION_BEGIN */
+#endif
+ 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);
+}
+
/**
Execute command saved in thd and lex->sql_command.
@@ -3078,7 +3258,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))
{
@@ -3704,6 +3885,7 @@ mysql_execute_command(THD *thd)
res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_MUTEX);
break;
}
+ case SQLCOM_CREATE_SEQUENCE:
case SQLCOM_CREATE_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
@@ -3961,6 +4143,7 @@ mysql_execute_command(THD *thd)
/* Regular CREATE TABLE */
res= mysql_create_table(thd, create_table, &create_info, &alter_info);
}
+
if (!res)
{
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
@@ -4169,9 +4352,9 @@ end_with_restore_list:
*/
DBUG_PRINT("debug", ("lex->only_view: %d, table: %s.%s",
- lex->only_view,
+ lex->table_type == TABLE_TYPE_VIEW,
first_table->db, first_table->table_name));
- if (lex->only_view)
+ if (lex->table_type == TABLE_TYPE_VIEW)
{
if (check_table_access(thd, SELECT_ACL, first_table, FALSE, 1, FALSE))
{
@@ -4185,7 +4368,6 @@ end_with_restore_list:
/* Ignore temporary tables if this is "SHOW CREATE VIEW" */
first_table->open_type= OT_BASE_ONLY;
-
}
else
{
@@ -4694,6 +4876,7 @@ end_with_restore_list:
}
break;
}
+ case SQLCOM_DROP_SEQUENCE:
case SQLCOM_DROP_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
@@ -4704,7 +4887,7 @@ end_with_restore_list:
}
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 */
@@ -4734,10 +4917,13 @@ end_with_restore_list:
lex->create_info.set(DDL_options_st::OPT_IF_EXISTS);
/* 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);
@@ -4778,7 +4964,7 @@ end_with_restore_list:
#endif
case SQLCOM_CHANGE_DB:
{
- LEX_STRING db_str= { (char *) select_lex->db, strlen(select_lex->db) };
+ LEX_CSTRING db_str= { (char *) select_lex->db, strlen(select_lex->db) };
if (!mysql_change_db(thd, &db_str, FALSE))
my_ok(thd);
@@ -4901,33 +5087,9 @@ end_with_restore_list:
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,
@@ -4936,31 +5098,7 @@ end_with_restore_list:
}
case SQLCOM_DROP_DB:
{
- if (check_db_name(&lex->name))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
- 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))
+ if (prepare_db_action(thd, DROP_ACL, &lex->name))
break;
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL)
res= mysql_rm_db(thd, lex->name.str, lex->if_exists());
@@ -4968,7 +5106,7 @@ end_with_restore_list:
}
case SQLCOM_ALTER_DB_UPGRADE:
{
- LEX_STRING *db= & lex->name;
+ LEX_CSTRING *db= &lex->name;
#ifdef HAVE_REPLICATION
if (thd->slave_thread)
{
@@ -4982,7 +5120,7 @@ end_with_restore_list:
}
}
#endif
- if (check_db_name(db))
+ if (check_db_name((LEX_STRING*) db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
break;
@@ -5002,32 +5140,8 @@ end_with_restore_list:
}
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);
@@ -5036,19 +5150,19 @@ end_with_restore_list:
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);
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error;
#endif /* WITH_WSREP */
- 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;
@@ -5104,13 +5218,13 @@ end_with_restore_list:
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error;
#endif /* WITH_WSREP */
- 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:
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
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;
@@ -5636,120 +5750,7 @@ end_with_restore_list:
case SQLCOM_CREATE_PROCEDURE:
case SQLCOM_CREATE_SPFUNCTION:
{
- 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_DROP_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 */
@@ -5777,9 +5778,15 @@ end_with_restore_list:
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;
+ /*
+ 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, lex->spname))
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
+ ErrConvDQName(lex->spname).ptr());
+ goto error;
}
else
{
@@ -5838,11 +5845,11 @@ end_with_restore_list:
break;
case SP_KEY_NOT_FOUND:
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ SP_COM_STRING(lex), ErrConvDQName(lex->spname).ptr());
goto error;
default:
my_error(ER_SP_CANT_ALTER, MYF(0),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ SP_COM_STRING(lex), ErrConvDQName(lex->spname).ptr());
goto error;
}
break;
@@ -5895,8 +5902,8 @@ end_with_restore_list:
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;
+ const char *db= lex->spname->m_db.str;
+ const char *name= lex->spname->m_name.str;
if (check_routine_access(thd, ALTER_PROC_ACL, db, name,
lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
@@ -5949,17 +5956,18 @@ end_with_restore_list:
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);
+ SP_COM_STRING(lex),
+ 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);
+ SP_COM_STRING(lex), ErrConvDQName(lex->spname).ptr());
goto error;
default:
my_error(ER_SP_DROP_FAILED, MYF(0),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ SP_COM_STRING(lex), ErrConvDQName(lex->spname).ptr());
goto error;
}
break;
@@ -6026,10 +6034,10 @@ end_with_restore_list:
{
/*
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.
*/
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
- 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:
@@ -6202,9 +6210,11 @@ end_with_restore_list:
case SQLCOM_REPAIR:
case SQLCOM_TRUNCATE:
case SQLCOM_ALTER_TABLE:
- thd->query_plan_flags|= QPLAN_ADMIN;
DBUG_ASSERT(first_table == all_tables && first_table != 0);
/* fall through */
+ case SQLCOM_ALTER_SEQUENCE:
+ thd->query_plan_flags|= QPLAN_ADMIN;
+ /* fall through */
case SQLCOM_SIGNAL:
case SQLCOM_RESIGNAL:
case SQLCOM_GET_DIAGNOSTICS:
@@ -7023,6 +7033,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,
@@ -7040,7 +7059,8 @@ deny:
bool
-check_routine_access(THD *thd, ulong want_access,char *db, char *name,
+check_routine_access(THD *thd, ulong want_access, const char *db,
+ const char *name,
bool is_proc, bool no_errors)
{
TABLE_LIST tables[1];
@@ -7213,8 +7233,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);
@@ -7230,12 +7250,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;
@@ -7245,11 +7266,14 @@ bool check_fk_parent_table_access(THD *thd,
{
if (!thd->db)
{
- 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;
@@ -7267,10 +7291,11 @@ 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,
@@ -7525,18 +7550,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->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->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)
{
@@ -7607,7 +7635,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
@@ -7631,7 +7660,7 @@ void create_select_for_variable(const char *var_name)
{
THD *thd;
LEX *lex;
- LEX_STRING tmp;
+ LEX_CSTRING tmp;
Item *var;
char buff[MAX_SYS_VAR_LENGTH*2+4+8], *end;
DBUG_ENTER("create_select_for_variable");
@@ -7640,13 +7669,13 @@ void create_select_for_variable(const char *var_name)
lex= thd->lex;
mysql_init_select(lex);
lex->sql_command= SQLCOM_SELECT;
- tmp.str= (char*) var_name;
+ tmp.str= 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, tmp, null_clex_str)))
{
end= strxmov(buff, "@@session.", var_name, NullS);
var->set_name(thd, buff, end-buff, system_charset_info);
@@ -7739,7 +7768,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
(longlong) thd->thread_id, is_autocommit,
thd->wsrep_retry_counter,
thd->variables.wsrep_retry_autocommit, thd->query());
- my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction");
+ my_message(ER_LOCK_DEADLOCK, "wsrep aborted transaction", MYF(0));
thd->killed= NOT_KILLED;
thd->wsrep_conflict_state= NO_CONFLICT;
if (thd->wsrep_conflict_state != REPLAYING)
@@ -8013,7 +8042,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,
@@ -8023,7 +8052,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
{
register TABLE_LIST *ptr;
TABLE_LIST *UNINIT_VAR(previous_table_ref); /* The table preceding the current one. */
- char *alias_str;
+ const char *alias_str;
LEX *lex= thd->lex;
DBUG_ENTER("add_table_to_list");
@@ -8038,7 +8067,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
}
if (table->is_derived_table() == FALSE && table->db.str &&
- check_db_name(&table->db))
+ check_db_name((LEX_STRING*) &table->db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
DBUG_RETURN(0);
@@ -8073,9 +8102,10 @@ 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);
+ table->table.length= my_casedn_str(files_charset_info,
+ (char*) table->table.str);
if (ptr->db_length && ptr->db != any_db)
- ptr->db_length= my_casedn_str(files_charset_info, ptr->db);
+ ptr->db_length= my_casedn_str(files_charset_info, (char*) ptr->db);
}
ptr->table_name=table->table.str;
@@ -8085,6 +8115,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
/* 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))
{
@@ -8125,8 +8156,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)
@@ -8136,7 +8167,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
tables=tables->next_local)
{
if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
- !strcmp(ptr->db, tables->db))
+ !strcmp(ptr->db, tables->db) && ! tables->sequence)
{
my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str); /* purecov: tested */
DBUG_RETURN(0); /* purecov: tested */
@@ -8144,7 +8175,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
}
}
/* Store the table reference preceding the current one. */
- if (table_list.elements > 0)
+ if (table_list.elements > 0 && !ptr->sequence)
{
/*
table_list.next points to the last inserted TABLE_LIST->next_local'
@@ -8169,8 +8200,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 (!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;
@@ -8414,8 +8448,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)
@@ -8437,7 +8471,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)
@@ -8538,7 +8572,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
@@ -9566,7 +9600,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
{
@@ -9623,7 +9657,8 @@ 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;
@@ -9657,7 +9692,7 @@ 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,
+bool check_string_byte_length(LEX_CSTRING *str, uint err_msg,
uint max_byte_length)
{
if (str->length <= max_byte_length)
@@ -9687,7 +9722,7 @@ bool check_string_byte_length(LEX_STRING *str, uint err_msg,
*/
-bool check_string_char_length(LEX_STRING *str, uint err_msg,
+bool check_string_char_length(LEX_CSTRING *str, uint err_msg,
uint max_char_length, CHARSET_INFO *cs,
bool no_error)
{
@@ -9706,7 +9741,7 @@ bool check_string_char_length(LEX_STRING *str, uint err_msg,
}
-bool check_ident_length(LEX_STRING *ident)
+bool check_ident_length(LEX_CSTRING *ident)
{
if (check_string_char_length(ident, 0, NAME_CHAR_LEN, system_charset_info, 1))
{
@@ -9816,7 +9851,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;
@@ -9839,6 +9874,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
/**
@@ -9898,7 +9934,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