summaryrefslogtreecommitdiff
path: root/sql/sql_yacc.yy
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r--sql/sql_yacc.yy2674
1 files changed, 1903 insertions, 771 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 3b42fe1e74a..16916fb919d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -23,8 +23,9 @@
*/
%{
-#define YYLIP (& thd->m_parser_state->m_lip)
-#define YYPS (& thd->m_parser_state->m_yacc)
+#define YYLIP (& thd->m_parser_state->m_lip)
+#define YYPS (& thd->m_parser_state->m_yacc)
+#define YYCSCL (thd->variables.character_set_client)
#define MYSQL_YACC
#define YYINITDEPTH 100
@@ -32,8 +33,8 @@
#define Lex (thd->lex)
#define Select Lex->current_select
+#include <my_global.h>
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_parse.h" /* comp_*_creator */
#include "sql_table.h" /* primary_key_name */
#include "sql_partition.h" /* mem_alloc_error, partition_info, HASH_PARTITION */
@@ -47,17 +48,21 @@
#include "sp_pcontext.h"
#include "sp_rcontext.h"
#include "sp.h"
-#include "sql_alter.h" // Alter_table*_statement
-#include "sql_truncate.h" // Truncate_statement
-#include "sql_admin.h" // Analyze/Check..._table_stmt
-#include "sql_partition_admin.h" // Alter_table_*_partition_stmt
+#include "sql_alter.h" // Sql_cmd_alter_table*
+#include "sql_truncate.h" // Sql_cmd_truncate_table
+#include "sql_admin.h" // Sql_cmd_analyze/Check..._table
+#include "sql_partition_admin.h" // Sql_cmd_alter_table_*_part.
+#include "sql_handler.h" // Sql_cmd_handler_*
#include "sql_signal.h"
+#include "sql_get_diagnostics.h" // Sql_cmd_get_diagnostics
#include "event_parse_data.h"
#include "create_options.h"
#include <myisam.h>
#include <myisammrg.h>
#include "keycaches.h"
#include "set_var.h"
+#include "rpl_mi.h"
+#include "lex_token.h"
/* this is to get the bison compilation windows warnings out */
#ifdef _MSC_VER
@@ -272,7 +277,7 @@ void case_stmt_action_case(LEX *lex)
(Instruction 12 in the example)
*/
- lex->spcont->push_label((char *)"", lex->sphead->instructions());
+ lex->spcont->push_label(current_thd, empty_lex_str, lex->sphead->instructions());
}
/**
@@ -340,8 +345,8 @@ int case_stmt_action_when(LEX *lex, Item *when, bool simple)
(jump_if_not from instruction 2 to 5, 5 to 8 ... in the example)
*/
- return !test(i) ||
- sp->push_backpatch(i, ctx->push_label((char *)"", 0)) ||
+ return !MY_TEST(i) ||
+ sp->push_backpatch(i, ctx->push_label(current_thd, empty_lex_str, 0)) ||
sp->add_cont_backpatch(i) ||
sp->add_instr(i);
}
@@ -358,7 +363,7 @@ int case_stmt_action_then(LEX *lex)
sp_pcontext *ctx= lex->spcont;
uint ip= sp->instructions();
sp_instr_jump *i = new sp_instr_jump(ip, ctx);
- if (!test(i) || sp->add_instr(i))
+ if (!MY_TEST(i) || sp->add_instr(i))
return 1;
/*
@@ -464,7 +469,7 @@ set_system_variable(THD *thd, struct sys_var_with_base *tmp,
*/
static bool
-set_local_variable(THD *thd, sp_variable_t *spv, Item *val)
+set_local_variable(THD *thd, sp_variable *spv, Item *val)
{
Item *it;
LEX *lex= thd->lex;
@@ -472,8 +477,8 @@ set_local_variable(THD *thd, sp_variable_t *spv, Item *val)
if (val)
it= val;
- else if (spv->dflt)
- it= spv->dflt;
+ else if (spv->default_value)
+ it= spv->default_value;
else
{
it= new (thd->mem_root) Item_null();
@@ -539,6 +544,57 @@ set_trigger_new_row(THD *thd, LEX_STRING *name, Item *val)
/**
+ Create an object to represent a SP variable in the Item-hierarchy.
+
+ @param thd The current thread.
+ @param name The SP variable name.
+ @param spvar The SP variable (optional).
+ @param start_in_q Start position of the SP variable name in the query.
+ @param end_in_q End position of the SP variable name in the query.
+
+ @remark If spvar is not specified, the name is used to search for the
+ variable in the parse-time context. If the variable does not
+ exist, a error is set and NULL is returned to the caller.
+
+ @return An Item_splocal object representing the SP variable, or NULL on error.
+*/
+static Item_splocal*
+create_item_for_sp_var(THD *thd, LEX_STRING name, sp_variable *spvar,
+ const char *start_in_q, const char *end_in_q)
+{
+ Item_splocal *item;
+ LEX *lex= thd->lex;
+ uint pos_in_q, len_in_q;
+ sp_pcontext *spc = lex->spcont;
+
+ /* If necessary, look for the variable. */
+ if (spc && !spvar)
+ spvar= spc->find_variable(name, false);
+
+ if (!spvar)
+ {
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), name.str);
+ return NULL;
+ }
+
+ DBUG_ASSERT(spc && spvar);
+
+ /* Position and length of the SP variable name in the query. */
+ pos_in_q= start_in_q - lex->sphead->m_tmp_query;
+ len_in_q= end_in_q - start_in_q;
+
+ item= new (thd->mem_root)
+ Item_splocal(name, spvar->offset, spvar->type, pos_in_q, len_in_q);
+
+#ifndef DBUG_OFF
+ if (item)
+ item->m_sp= lex->sphead;
+#endif
+
+ return item;
+}
+
+/**
Helper to resolve the SQL:2003 Syntax exception 1) in <in predicate>.
See SQL:2003, Part 2, section 8.4 <in predicate>, Note 184, page 383.
This function returns the proper item for the SQL expression
@@ -703,10 +759,10 @@ static bool add_create_index_prepare (LEX *lex, Table_ident *table)
if (!lex->current_select->add_table_to_list(lex->thd, table, NULL,
TL_OPTION_UPDATING,
TL_READ_NO_INSERT,
- MDL_SHARED_NO_WRITE))
+ MDL_SHARED_UPGRADABLE))
return TRUE;
lex->alter_info.reset();
- lex->alter_info.flags= ALTER_ADD_INDEX;
+ lex->alter_info.flags= Alter_info::ALTER_ADD_INDEX;
lex->col_list.empty();
lex->change= NullS;
lex->option_list= NULL;
@@ -719,7 +775,7 @@ static bool add_create_index (LEX *lex, Key::Keytype type,
{
Key *key;
key= new Key(type, name, info ? info : &lex->key_create_info, generated,
- lex->col_list, lex->option_list);
+ lex->col_list, lex->option_list, lex->check_exists);
if (key == NULL)
return TRUE;
@@ -728,6 +784,115 @@ static bool add_create_index (LEX *lex, Key::Keytype type,
return FALSE;
}
+
+/**
+ Create a separate LEX for each assignment if in SP.
+
+ If we are in SP we want have own LEX for each assignment.
+ This is mostly because it is hard for several sp_instr_set
+ and sp_instr_set_trigger instructions share one LEX.
+ (Well, it is theoretically possible but adds some extra
+ overhead on preparation for execution stage and IMO less
+ robust).
+
+ QQ: May be we should simply prohibit group assignments in SP?
+
+ @see sp_create_assignment_instr
+
+ @param thd Thread context
+ @param no_lookahead True if the parser has no lookahead
+*/
+
+static void sp_create_assignment_lex(THD *thd, bool no_lookahead)
+{
+ LEX *lex= thd->lex;
+
+ if (lex->sphead)
+ {
+ Lex_input_stream *lip= &thd->m_parser_state->m_lip;
+ LEX *old_lex= lex;
+ lex->sphead->reset_lex(thd);
+ lex= thd->lex;
+
+ /* Set new LEX as if we at start of set rule. */
+ lex->sql_command= SQLCOM_SET_OPTION;
+ mysql_init_select(lex);
+ lex->var_list.empty();
+ lex->autocommit= 0;
+ /* get_ptr() is only correct with no lookahead. */
+ DBUG_ASSERT(no_lookahead);
+ lex->sphead->m_tmp_query= lip->get_ptr();
+ /* Inherit from outer lex. */
+ lex->option_type= old_lex->option_type;
+ }
+}
+
+
+/**
+ Create a SP instruction for a SET assignment.
+
+ @see sp_create_assignment_lex
+
+ @param thd Thread context
+ @param no_lookahead True if the parser has no lookahead
+
+ @return false if success, true otherwise.
+*/
+
+static bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
+{
+ LEX *lex= thd->lex;
+
+ if (lex->sphead)
+ {
+ sp_head *sp= lex->sphead;
+
+ if (!lex->var_list.is_empty())
+ {
+ /*
+ We have assignment to user or system variable or
+ option setting, so we should construct sp_instr_stmt
+ for it.
+ */
+ LEX_STRING qbuff;
+ sp_instr_stmt *i;
+ Lex_input_stream *lip= &thd->m_parser_state->m_lip;
+
+ if (!(i= new sp_instr_stmt(sp->instructions(), lex->spcont,
+ lex)))
+ return true;
+
+ /*
+ Extract the query statement from the tokenizer. The
+ end is either lip->ptr, if there was no lookahead,
+ lip->tok_end otherwise.
+ */
+ if (no_lookahead)
+ qbuff.length= lip->get_ptr() - sp->m_tmp_query;
+ else
+ qbuff.length= lip->get_tok_end() - sp->m_tmp_query;
+
+ if (!(qbuff.str= (char*) alloc_root(thd->mem_root,
+ qbuff.length + 5)))
+ return true;
+
+ strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query,
+ qbuff.length);
+ qbuff.length+= 4;
+ i->m_query= qbuff;
+ if (sp->add_instr(i))
+ return true;
+ }
+ enum_var_type inner_option_type= lex->option_type;
+ if (lex->sphead->restore_lex(thd))
+ return true;
+ /* Copy option_type to outer lex in case it has changed. */
+ thd->lex->option_type= inner_option_type;
+ }
+ return false;
+}
+
+
%}
%union {
int num;
@@ -766,7 +931,7 @@ static bool add_create_index (LEX *lex, Key::Keytype type,
timestamp_type date_time_type;
st_select_lex *select_lex;
chooser_compare_func_creator boolfunc2creator;
- struct sp_cond_type *spcondtype;
+ class sp_condition_value *spcondvalue;
struct { int vars, conds, hndlrs, curs; } spblock;
sp_name *spname;
LEX *lex;
@@ -777,6 +942,14 @@ static bool add_create_index (LEX *lex, Key::Keytype type,
enum Foreign_key::fk_option m_fk_option;
enum enum_yes_no_unknown m_yes_no_unk;
Diag_condition_item_name diag_condition_item_name;
+ Diagnostics_information::Which_area diag_area;
+ Diagnostics_information *diag_info;
+ Statement_information_item *stmt_info_item;
+ Statement_information_item::Name stmt_info_item_name;
+ List<Statement_information_item> *stmt_info_list;
+ Condition_information_item *cond_info_item;
+ Condition_information_item::Name cond_info_item_name;
+ List<Condition_information_item> *cond_info_list;
DYNCALL_CREATE_DEF *dyncol_def;
List<DYNCALL_CREATE_DEF> *dyncol_def_list;
bool is_not_empty;
@@ -790,10 +963,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
- Currently there are 175 shift/reduce conflicts.
+ Currently there are 163 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
-%expect 175
+%expect 163
/*
Comments for TOKENS.
@@ -807,7 +980,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
MYSQL-FUNC : MySQL extention, function
INTERNAL : Not a real token, lex optimization
OPERATOR : SQL operator
- FUTURE-USE : Reserved for futur use
+ FUTURE-USE : Reserved for future use
This makes the code grep-able, and helps maintenance.
*/
@@ -816,6 +989,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ACCESSIBLE_SYM
%token ACTION /* SQL-2003-N */
%token ADD /* SQL-2003-R */
+%token ADMIN_SYM /* SQL-2003-N */
%token ADDDATE_SYM /* MYSQL-FUNC */
%token AFTER_SYM /* SQL-2003-N */
%token AGAINST
@@ -836,6 +1010,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token AUTHORS_SYM
%token AUTOEXTEND_SIZE_SYM
%token AUTO_INC
+%token AUTO_SYM
%token AVG_ROW_LENGTH
%token AVG_SYM /* SQL-2003-N */
%token BACKUP_SYM
@@ -884,11 +1059,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token COLLATION_SYM /* SQL-2003-N */
%token COLUMNS
%token COLUMN_ADD_SYM
+%token COLUMN_CHECK_SYM
%token COLUMN_CREATE_SYM
%token COLUMN_DELETE_SYM
-%token COLUMN_EXISTS_SYM
%token COLUMN_GET_SYM
-%token COLUMN_LIST_SYM
%token COLUMN_SYM /* SQL-2003-R */
%token COLUMN_NAME_SYM /* SQL-2003-N */
%token COMMENT_SYM
@@ -916,7 +1090,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CROSS /* SQL-2003-R */
%token CUBE_SYM /* SQL-2003-R */
%token CURDATE /* MYSQL-FUNC */
+%token CURRENT_SYM /* SQL-2003-R */
%token CURRENT_USER /* SQL-2003-R */
+%token CURRENT_ROLE /* SQL-2003-R */
+%token CURRENT_POS_SYM
%token CURSOR_SYM /* SQL-2003-R */
%token CURSOR_NAME_SYM /* SQL-2003-N */
%token CURTIME /* MYSQL-FUNC */
@@ -946,6 +1123,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token DESCRIBE /* SQL-2003-R */
%token DES_KEY_FILE
%token DETERMINISTIC_SYM /* SQL-2003-R */
+%token DIAGNOSTICS_SYM /* SQL-2003-N */
%token DIRECTORY_SYM
%token DISABLE_SYM
%token DISCARD
@@ -979,11 +1157,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token EVENTS_SYM
%token EVENT_SYM
%token EVERY_SYM /* SQL-2003-N */
+%token EXCHANGE_SYM
%token EXAMINED_SYM
%token EXECUTE_SYM /* SQL-2003-R */
%token EXISTS /* SQL-2003-R */
%token EXIT_SYM
%token EXPANSION_SYM
+%token EXPORT_SYM
%token EXTENDED_SYM
%token EXTENT_SIZE_SYM
%token EXTRACT_SYM /* SQL-2003-N */
@@ -1011,6 +1191,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token GEOMETRYCOLLECTION
%token GEOMETRY_SYM
%token GET_FORMAT /* MYSQL-FUNC */
+%token GET_SYM /* SQL-2003-R */
%token GLOBAL_SYM /* SQL-2003-R */
%token GRANT /* SQL-2003-R */
%token GRANTS
@@ -1031,6 +1212,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token HOUR_MINUTE_SYM
%token HOUR_SECOND_SYM
%token HOUR_SYM /* SQL-2003-R */
+%token ID_SYM /* MYSQL */
%token IDENT
%token IDENTIFIED_SYM
%token IDENT_QUOTED
@@ -1097,6 +1279,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token LOW_PRIORITY
%token LT /* OPERATOR */
%token MASTER_CONNECT_RETRY_SYM
+%token MASTER_GTID_POS_SYM
%token MASTER_HOST_SYM
%token MASTER_LOG_FILE_SYM
%token MASTER_LOG_POS_SYM
@@ -1107,11 +1290,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token MASTER_SSL_CA_SYM
%token MASTER_SSL_CERT_SYM
%token MASTER_SSL_CIPHER_SYM
+%token MASTER_SSL_CRL_SYM
+%token MASTER_SSL_CRLPATH_SYM
%token MASTER_SSL_KEY_SYM
%token MASTER_SSL_SYM
%token MASTER_SSL_VERIFY_SERVER_CERT_SYM
%token MASTER_SYM
%token MASTER_USER_SYM
+%token MASTER_USE_GTID_SYM
%token MASTER_HEARTBEAT_PERIOD_SYM
%token MATCH /* SQL-2003-R */
%token MAX_CONNECTIONS_PER_HOUR
@@ -1168,13 +1354,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NO_WRITE_TO_BINLOG
%token NULL_SYM /* SQL-2003-R */
%token NUM
+%token NUMBER_SYM /* SQL-2003-N */
%token NUMERIC_SYM /* SQL-2003-R */
%token NVARCHAR_SYM
%token OFFSET_SYM
%token OLD_PASSWORD
%token ON /* SQL-2003-R */
-%token ONE_SHOT_SYM
%token ONE_SYM
+%token ONLY_SYM /* SQL-2003-R */
%token ONLINE_SYM
%token OPEN_SYM /* SQL-2003-R */
%token OPTIMIZE
@@ -1196,9 +1383,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token PARSER_SYM
%token PARSE_VCOL_EXPR_SYM
%token PARTIAL /* SQL-2003-N */
-%token PARTITIONING_SYM
-%token PARTITIONS_SYM
%token PARTITION_SYM /* SQL-2003-R */
+%token PARTITIONS_SYM
+%token PARTITIONING_SYM
%token PASSWORD
%token PERSISTENT_SYM
%token PHASE_SYM
@@ -1259,16 +1446,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token RESTORE_SYM
%token RESTRICT
%token RESUME_SYM
+%token RETURNED_SQLSTATE_SYM /* SQL-2003-N */
+%token RETURNING_SYM
%token RETURNS_SYM /* SQL-2003-R */
%token RETURN_SYM /* SQL-2003-R */
+%token REVERSE_SYM
%token REVOKE /* SQL-2003-R */
%token RIGHT /* SQL-2003-R */
+%token ROLE_SYM
%token ROLLBACK_SYM /* SQL-2003-R */
%token ROLLUP_SYM /* SQL-2003-R */
%token ROUTINE_SYM /* SQL-2003-N */
%token ROWS_SYM /* SQL-2003-R */
%token ROW_FORMAT_SYM
%token ROW_SYM /* SQL-2003-R */
+%token ROW_COUNT_SYM /* SQL-2003-N */
%token RTREE_SYM
%token SAVEPOINT_SYM /* SQL-2003-R */
%token SCHEDULE_SYM
@@ -1295,6 +1487,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token SIGNED_SYM
%token SIMPLE_SYM /* SQL-2003-N */
%token SLAVE
+%token SLAVES
+%token SLAVE_POS_SYM
%token SLOW
%token SMALLINT /* SQL-2003-R */
%token SNAPSHOT_SYM
@@ -1320,6 +1514,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token STARTING
%token STARTS_SYM
%token START_SYM /* SQL-2003-R */
+%token STATS_AUTO_RECALC_SYM
+%token STATS_PERSISTENT_SYM
+%token STATS_SAMPLE_PAGES_SYM
%token STATUS_SYM
%token STDDEV_SAMP_SYM /* SQL-2003-N */
%token STD_SYM
@@ -1412,6 +1609,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token WAIT_SYM
%token WARNINGS
%token WEEK_SYM
+%token WEIGHT_STRING_SYM
%token WHEN_SYM /* SQL-2003-R */
%token WHERE /* SQL-2003-R */
%token WHILE_SYM
@@ -1453,41 +1651,48 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <lex_str>
IDENT IDENT_QUOTED TEXT_STRING DECIMAL_NUM FLOAT_NUM NUM LONG_NUM
- HEX_NUM HEX_STRING hex_num_or_string
+ HEX_NUM HEX_STRING
LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
NCHAR_STRING opt_component key_cache_name
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
- opt_constraint constraint opt_ident
+ opt_constraint constraint opt_ident opt_if_not_exists_ident
%type <lex_str_ptr>
opt_table_alias
%type <table>
table_ident table_ident_nodb references xid
- table_ident_opt_wild
+ table_ident_opt_wild create_like
%type <simple_string>
remember_name remember_end opt_db text_or_password
%type <string>
- text_string opt_gconcat_separator
+ text_string hex_or_bin_String opt_gconcat_separator
%type <lex_type> field_def
%type <num>
type type_with_opt_collate int_type real_type order_dir lock_option
- udf_type if_exists opt_local opt_table_options table_options
- table_option opt_if_not_exists opt_no_write_to_binlog
+ udf_type opt_if_exists opt_local opt_table_options table_options
+ table_option opt_if_not_exists create_or_replace opt_no_write_to_binlog
opt_temporary all_or_any opt_distinct
opt_ignore_leaves fulltext_options spatial_type union_option
- start_transaction_opts
- union_opt select_derived_init option_type2
+ union_opt select_derived_init transaction_access_mode_types
opt_natural_language_mode opt_query_expansion
opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
optional_flush_tables_arguments opt_dyncol_type dyncol_type
opt_time_precision kill_type kill_option int_num
+ opt_default_time_precision
+
+/*
+ Bit field of MYSQL_START_TRANS_OPT_* flags.
+*/
+%type <num> opt_start_transaction_option_list
+%type <num> start_transaction_option_list
+%type <num> start_transaction_option
%type <m_yes_no_unk>
opt_chain opt_release
@@ -1497,6 +1702,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <ulong_num>
ulong_num real_ulong_num merge_insert_types
+ ws_nweights
+ ws_level_flag_desc ws_level_flag_reverse ws_level_flags
+ opt_ws_levels ws_level_list ws_level_list_item ws_level_number
+ ws_level_range ws_level_list_or_range
%type <ulonglong_number>
ulonglong_num real_ulonglong_num size_number
@@ -1507,7 +1716,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
replace_lock_option opt_low_priority insert_lock_option load_data_lock
%type <item>
- literal text_literal insert_ident order_ident
+ literal text_literal insert_ident order_ident temporal_literal
simple_ident expr opt_expr opt_else sum_expr in_sum_expr
variable variable_aux bool_pri
predicate bit_expr
@@ -1524,6 +1733,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
function_call_generic
function_call_conflict kill_expr
signal_allowed_expr
+ simple_target_specification
+ condition_number
%type <item_num>
NUM_literal
@@ -1542,7 +1753,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
btree_or_rtree
%type <string_list>
- using_list
+ using_list opt_use_partition use_partition
%type <key_part>
key_part
@@ -1570,7 +1781,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <symbol> keyword keyword_sp
-%type <lex_user> user grant_user
+%type <lex_user> user grant_user grant_role user_or_role current_role
+ admin_option_for_role user_maybe_role
%type <charset>
opt_collate
@@ -1601,7 +1813,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
show describe load alter optimize keycache preload flush
reset purge begin commit rollback savepoint release
slave master_def master_defs master_file_def slave_until_opts
- repair analyze check start checksum
+ repair analyze opt_with_admin opt_with_admin_option
+ analyze_table_list analyze_table_elem_spec
+ opt_persistent_stat_clause persistent_stat_spec
+ persistent_column_stat_spec persistent_index_stat_spec
+ table_column_list table_index_list table_index_name
+ check start checksum
field_list field_list_item field_spec kill column_def key_def
keycache_list keycache_list_or_parts assign_to_keycache
assign_to_keycache_parts
@@ -1616,14 +1833,15 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
ref_list opt_match_clause opt_on_update_delete use
opt_delete_options opt_delete_option varchar nchar nvarchar
opt_outer table_list table_name table_alias_ref_list table_alias_ref
- opt_option opt_place
+ opt_place
opt_attribute opt_attribute_list attribute column_list column_list_id
opt_column_list grant_privileges grant_ident grant_list grant_option
- object_privilege object_privilege_list user_list rename_list
- clear_privileges flush_options flush_option
- opt_with_read_lock flush_options_list
+ object_privilege object_privilege_list user_list user_and_role_list
+ rename_list
+ clear_privileges flush_options flush_option table_or_tables
+ opt_flush_lock flush_lock flush_options_list
equal optional_braces
- opt_mi_check_type opt_to mi_check_types normal_join
+ opt_mi_check_type opt_to mi_check_types
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
single_multi table_wild_list table_wild_one opt_wild
@@ -1631,12 +1849,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
precision subselect_start opt_and charset
subselect_end select_var_list select_var_list_init help
field_length opt_field_length
- opt_extended_describe
+ opt_extended_describe shutdown
prepare prepare_src execute deallocate
statement sp_suid
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
- view_replace_or_algorithm view_replace
view_algorithm view_or_trigger_or_sp_or_event
definer_tail no_definer_tail
view_suid view_tail view_list_opt view_list view_select
@@ -1649,9 +1866,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
key_using_alg
part_column_list
server_def server_options_list server_option
- definer_opt no_definer definer
+ definer_opt no_definer definer get_diagnostics
parse_vcol_expr vcol_opt_specifier vcol_opt_attribute
vcol_opt_attribute_list vcol_attribute
+ explainable_command
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
@@ -1665,17 +1883,26 @@ END_OF_INPUT
%type <NONE> case_stmt_specification simple_case_stmt searched_case_stmt
%type <num> sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list
-%type <spcondtype> sp_cond sp_hcond sqlstate signal_value opt_signal_value
+%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
%type <spblock> sp_decls sp_decl
%type <lex> sp_cursor_stmt
%type <spname> sp_name
%type <index_hint> index_hint_type
-%type <num> index_hint_clause
+%type <num> index_hint_clause normal_join inner_join
%type <filetype> data_or_xml
%type <NONE> signal_stmt resignal_stmt
%type <diag_condition_item_name> signal_condition_information_item_name
+%type <diag_area> which_area;
+%type <diag_info> diagnostics_information;
+%type <stmt_info_item> statement_information_item;
+%type <stmt_info_item_name> statement_information_item_name;
+%type <stmt_info_list> statement_information;
+%type <cond_info_item> condition_information_item;
+%type <cond_info_item_name> condition_information_item_name;
+%type <cond_info_list> condition_information;
+
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM
@@ -1683,8 +1910,11 @@ END_OF_INPUT
%type <is_not_empty> opt_union_order_or_limit
+%type <NONE> ROLE_SYM
+
%%
+
/*
Indentation of grammar rules:
@@ -1778,6 +2008,7 @@ statement:
| drop
| execute
| flush
+ | get_diagnostics
| grant
| handler
| help
@@ -1807,6 +2038,7 @@ statement:
| set
| signal_stmt
| show
+ | shutdown
| slave
| start
| truncate
@@ -1908,7 +2140,7 @@ help:
/* change master */
change:
- CHANGE MASTER_SYM TO_SYM
+ CHANGE MASTER_SYM optional_connection_name TO_SYM
{
Lex->sql_command = SQLCOM_CHANGE_MASTER;
}
@@ -1972,6 +2204,14 @@ master_def:
Lex->mi.ssl_verify_server_cert= $3 ?
LEX_MASTER_INFO::LEX_MI_ENABLE : LEX_MASTER_INFO::LEX_MI_DISABLE;
}
+ | MASTER_SSL_CRL_SYM EQ TEXT_STRING_sys
+ {
+ Lex->mi.ssl_crl= $3.str;
+ }
+ | MASTER_SSL_CRLPATH_SYM EQ TEXT_STRING_sys
+ {
+ Lex->mi.ssl_crlpath= $3.str;
+ }
| MASTER_HEARTBEAT_PERIOD_SYM EQ NUM_literal
{
@@ -1987,7 +2227,7 @@ master_def:
}
if (Lex->mi.heartbeat_period > slave_net_timeout)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX,
ER(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX));
}
@@ -1995,7 +2235,7 @@ master_def:
{
if (Lex->mi.heartbeat_period != 0.0)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN,
ER(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN));
Lex->mi.heartbeat_period= 0.0;
@@ -2043,7 +2283,7 @@ master_file_def:
from 0" (4 in fact), unspecified means "don't change the position
(keep the preceding value)").
*/
- Lex->mi.pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.pos);
+ Lex->mi.pos= MY_MAX(BIN_LOG_HEADER_SIZE, Lex->mi.pos);
}
| RELAY_LOG_FILE_SYM EQ TEXT_STRING_sys
{
@@ -2053,38 +2293,93 @@ master_file_def:
{
Lex->mi.relay_log_pos = $3;
/* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */
- Lex->mi.relay_log_pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.relay_log_pos);
+ Lex->mi.relay_log_pos= MY_MAX(BIN_LOG_HEADER_SIZE, Lex->mi.relay_log_pos);
+ }
+ | MASTER_USE_GTID_SYM EQ CURRENT_POS_SYM
+ {
+ if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
+ {
+ my_error(ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid");
+ MYSQL_YYABORT;
+ }
+ Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_CURRENT_POS;
}
;
+ | MASTER_USE_GTID_SYM EQ SLAVE_POS_SYM
+ {
+ if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
+ {
+ my_error(ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid");
+ MYSQL_YYABORT;
+ }
+ Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_SLAVE_POS;
+ }
+ ;
+ | MASTER_USE_GTID_SYM EQ NO_SYM
+ {
+ if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
+ {
+ my_error(ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid");
+ MYSQL_YYABORT;
+ }
+ Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_NO;
+ }
+ ;
+
+optional_connection_name:
+ /* empty */
+ {
+ LEX *lex= thd->lex;
+ lex->mi.connection_name= thd->variables.default_master_connection;
+ }
+ | connection_name;
+ ;
+
+connection_name:
+ TEXT_STRING_sys
+ {
+ Lex->mi.connection_name= $1;
+#ifdef HAVE_REPLICATION
+ if (check_master_connection_name(&$1))
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "MASTER_CONNECTION_NAME");
+ MYSQL_YYABORT;
+ }
+#endif
+ }
/* create a table */
create:
- CREATE opt_table_options TABLE_SYM opt_if_not_exists table_ident
+ create_or_replace opt_table_options TABLE_SYM opt_if_not_exists table_ident
{
LEX *lex= thd->lex;
lex->sql_command= SQLCOM_CREATE_TABLE;
+ if ($1 && $4)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "OR REPLACE", "IF NOT EXISTS");
+ MYSQL_YYABORT;
+ }
if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
TL_OPTION_UPDATING,
TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
- /*
- For CREATE TABLE, an non-existing table is not an error.
- Instruct open_tables() to just take an MDL lock if the
- table does not exist.
- */
- lex->query_tables->open_strategy= TABLE_LIST::OPEN_IF_EXISTS;
lex->alter_info.reset();
lex->col_list.empty();
lex->change=NullS;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
- lex->create_info.options=$2 | $4;
+ /*
+ For CREATE TABLE we should not open the table even if it exists.
+ If the table exists, we should either not create it or replace it
+ */
+ lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
+ lex->create_info.options= ($1 | $2 | $4);
lex->create_info.default_table_charset= NULL;
lex->name.str= 0;
lex->name.length= 0;
lex->create_last_non_select_table= lex->last_table();
}
- create2
+ create_body
{
LEX *lex= thd->lex;
lex->current_select= &lex->select_lex;
@@ -2092,7 +2387,7 @@ create:
!lex->create_info.db_type)
{
lex->create_info.db_type= ha_default_handlerton(thd);
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_USING_OTHER_HANDLER,
ER(ER_WARN_USING_OTHER_HANDLER),
hton_name(lex->create_info.db_type)->str,
@@ -2100,38 +2395,41 @@ create:
}
create_table_set_open_action_and_adjust_tables(lex);
}
- | CREATE opt_unique INDEX_SYM ident key_alg ON table_ident
+ | CREATE opt_unique INDEX_SYM opt_if_not_exists ident key_alg ON table_ident
{
- if (add_create_index_prepare(Lex, $7))
+ if (add_create_index_prepare(Lex, $8))
MYSQL_YYABORT;
}
'(' key_list ')' normal_key_options
{
- if (add_create_index(Lex, $2, $4))
+ if (add_create_index(Lex, $2, $5))
MYSQL_YYABORT;
}
- | CREATE fulltext INDEX_SYM ident init_key_options ON
+ opt_index_lock_algorithm { }
+ | CREATE fulltext INDEX_SYM opt_if_not_exists ident init_key_options ON
table_ident
{
- if (add_create_index_prepare(Lex, $7))
+ if (add_create_index_prepare(Lex, $8))
MYSQL_YYABORT;
}
'(' key_list ')' fulltext_key_options
{
- if (add_create_index(Lex, $2, $4))
+ if (add_create_index(Lex, $2, $5))
MYSQL_YYABORT;
}
- | CREATE spatial INDEX_SYM ident init_key_options ON
+ opt_index_lock_algorithm { }
+ | CREATE spatial INDEX_SYM opt_if_not_exists ident init_key_options ON
table_ident
{
- if (add_create_index_prepare(Lex, $7))
+ if (add_create_index_prepare(Lex, $8))
MYSQL_YYABORT;
}
'(' key_list ')' spatial_key_options
{
- if (add_create_index(Lex, $2, $4))
+ if (add_create_index(Lex, $2, $5))
MYSQL_YYABORT;
}
+ opt_index_lock_algorithm { }
| CREATE DATABASE opt_if_not_exists ident
{
Lex->create_info.default_table_charset= NULL;
@@ -2144,18 +2442,30 @@ create:
lex->name= $4;
lex->create_info.options=$3;
}
- | CREATE
+ | create_or_replace
{
- Lex->create_view_mode= VIEW_CREATE_NEW;
+ Lex->create_view_mode= ($1 == 0 ? VIEW_CREATE_NEW :
+ VIEW_CREATE_OR_REPLACE);
Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED;
Lex->create_view_suid= TRUE;
}
view_or_trigger_or_sp_or_event
- {}
+ {
+ if ($1 && Lex->sql_command != SQLCOM_CREATE_VIEW)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "OR REPLACE",
+ "TRIGGERS / SP / EVENT");
+ MYSQL_YYABORT;
+ }
+ }
| CREATE USER clear_privileges grant_list
{
Lex->sql_command = SQLCOM_CREATE_USER;
}
+ | CREATE ROLE_SYM clear_privileges role_list opt_with_admin
+ {
+ Lex->sql_command = SQLCOM_CREATE_ROLE;
+ }
| CREATE LOGFILE_SYM GROUP_SYM logfile_group_info
{
Lex->alter_tablespace_info->ts_cmd_type= CREATE_LOGFILE_GROUP;
@@ -2576,14 +2886,16 @@ sp_fdparam:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_variable(&$1, TRUE))
+ if (spc->find_variable($1, TRUE))
{
my_error(ER_SP_DUP_PARAM, MYF(0), $1.str);
MYSQL_YYABORT;
}
- sp_variable_t *spvar= spc->push_variable(&$1,
- (enum enum_field_types)$3,
- sp_param_in);
+
+ sp_variable *spvar= spc->add_variable(thd,
+ $1,
+ (enum enum_field_types) $3,
+ sp_variable::MODE_IN);
if (lex->sphead->fill_field_definition(thd, lex,
(enum enum_field_types) $3,
@@ -2613,14 +2925,15 @@ sp_pdparam:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_variable(&$3, TRUE))
+ if (spc->find_variable($3, TRUE))
{
my_error(ER_SP_DUP_PARAM, MYF(0), $3.str);
MYSQL_YYABORT;
}
- sp_variable_t *spvar= spc->push_variable(&$3,
- (enum enum_field_types)$4,
- (sp_param_mode_t)$1);
+ sp_variable *spvar= spc->add_variable(thd,
+ $3,
+ (enum enum_field_types) $4,
+ (sp_variable::enum_mode) $1);
if (lex->sphead->fill_field_definition(thd, lex,
(enum enum_field_types) $4,
@@ -2634,10 +2947,10 @@ sp_pdparam:
;
sp_opt_inout:
- /* Empty */ { $$= sp_param_in; }
- | IN_SYM { $$= sp_param_in; }
- | OUT_SYM { $$= sp_param_out; }
- | INOUT_SYM { $$= sp_param_inout; }
+ /* Empty */ { $$= sp_variable::MODE_IN; }
+ | IN_SYM { $$= sp_variable::MODE_IN; }
+ | OUT_SYM { $$= sp_variable::MODE_OUT; }
+ | INOUT_SYM { $$= sp_variable::MODE_INOUT; }
;
sp_proc_stmts:
@@ -2708,13 +3021,13 @@ sp_decl:
for (uint i = num_vars-$2 ; i < num_vars ; i++)
{
uint var_idx= pctx->var_context2runtime(i);
- sp_variable_t *spvar= pctx->find_variable(var_idx);
+ sp_variable *spvar= pctx->find_variable(var_idx);
if (!spvar)
MYSQL_YYABORT;
spvar->type= var_type;
- spvar->dflt= dflt_value_item;
+ spvar->default_value= dflt_value_item;
if (lex->sphead->fill_field_definition(thd, lex, var_type,
&spvar->field_def))
@@ -2750,12 +3063,12 @@ sp_decl:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_cond(&$2, TRUE))
+ if (spc->find_condition($2, TRUE))
{
my_error(ER_SP_DUP_COND, MYF(0), $2.str);
MYSQL_YYABORT;
}
- if(thd->lex->spcont->push_cond(&$2, $5))
+ if(spc->add_condition(thd, $2, $5))
MYSQL_YYABORT;
$$.vars= $$.hndlrs= $$.curs= 0;
$$.conds= 1;
@@ -2765,21 +3078,25 @@ sp_decl:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
- lex->spcont= lex->spcont->push_context(LABEL_HANDLER_SCOPE);
+ sp_handler *h= lex->spcont->add_handler(thd,
+ (sp_handler::enum_type) $2);
+
+ lex->spcont= lex->spcont->push_context(thd,
+ sp_pcontext::HANDLER_SCOPE);
sp_pcontext *ctx= lex->spcont;
sp_instr_hpush_jump *i=
- new sp_instr_hpush_jump(sp->instructions(), ctx, $2,
- ctx->current_var_count());
+ new sp_instr_hpush_jump(sp->instructions(), ctx, h);
+
if (i == NULL || sp->add_instr(i))
MYSQL_YYABORT;
/* For continue handlers, mark end of handler scope. */
- if ($2 == SP_HANDLER_CONTINUE &&
+ if ($2 == sp_handler::CONTINUE &&
sp->push_backpatch(i, ctx->last_label()))
MYSQL_YYABORT;
- if (sp->push_backpatch(i, ctx->push_label(empty_c_string, 0)))
+ if (sp->push_backpatch(i, ctx->push_label(thd, empty_lex_str, 0)))
MYSQL_YYABORT;
}
sp_hcond_list sp_proc_stmt
@@ -2787,20 +3104,19 @@ sp_decl:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
- sp_label_t *hlab= lex->spcont->pop_label(); /* After this hdlr */
+ sp_label *hlab= lex->spcont->pop_label(); /* After this hdlr */
sp_instr_hreturn *i;
- if ($2 == SP_HANDLER_CONTINUE)
+ if ($2 == sp_handler::CONTINUE)
{
- i= new sp_instr_hreturn(sp->instructions(), ctx,
- ctx->current_var_count());
+ i= new sp_instr_hreturn(sp->instructions(), ctx);
if (i == NULL ||
sp->add_instr(i))
MYSQL_YYABORT;
}
else
{ /* EXIT or UNDO handler, just jump to the end of the block */
- i= new sp_instr_hreturn(sp->instructions(), ctx, 0);
+ i= new sp_instr_hreturn(sp->instructions(), ctx);
if (i == NULL ||
sp->add_instr(i) ||
sp->push_backpatch(i, lex->spcont->last_label())) /* Block end */
@@ -2811,8 +3127,7 @@ sp_decl:
lex->spcont= ctx->pop_context();
$$.vars= $$.conds= $$.curs= 0;
- $$.hndlrs= $6;
- lex->spcont->add_handlers($6);
+ $$.hndlrs= 1;
}
| DECLARE_SYM ident CURSOR_SYM FOR_SYM sp_cursor_stmt
{
@@ -2822,7 +3137,7 @@ sp_decl:
uint offp;
sp_instr_cpush *i;
- if (ctx->find_cursor(&$2, &offp, TRUE))
+ if (ctx->find_cursor($2, &offp, TRUE))
{
my_error(ER_SP_DUP_CURS, MYF(0), $2.str);
delete $5;
@@ -2832,7 +3147,7 @@ sp_decl:
ctx->current_cursor_count());
if (i == NULL ||
sp->add_instr(i) ||
- ctx->push_cursor(&$2))
+ ctx->add_cursor($2))
MYSQL_YYABORT;
$$.vars= $$.conds= $$.hndlrs= 0;
$$.curs= 1;
@@ -2863,9 +3178,9 @@ sp_cursor_stmt:
;
sp_handler_type:
- EXIT_SYM { $$= SP_HANDLER_EXIT; }
- | CONTINUE_SYM { $$= SP_HANDLER_CONTINUE; }
- /*| UNDO_SYM { QQ No yet } */
+ EXIT_SYM { $$= sp_handler::EXIT; }
+ | CONTINUE_SYM { $$= sp_handler::CONTINUE; }
+ /*| UNDO_SYM { QQ No yet } */
;
sp_hcond_list:
@@ -2882,7 +3197,7 @@ sp_hcond_element:
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont->parent_context();
- if (ctx->find_handler($1))
+ if (ctx->check_duplicate_handler($1))
{
my_message(ER_SP_DUP_HANDLER, ER(ER_SP_DUP_HANDLER), MYF(0));
MYSQL_YYABORT;
@@ -2893,7 +3208,6 @@ sp_hcond_element:
(sp_instr_hpush_jump *)sp->last_instruction();
i->add_condition($1);
- ctx->push_handler($1);
}
}
;
@@ -2906,11 +3220,9 @@ sp_cond:
my_error(ER_WRONG_VALUE, MYF(0), "CONDITION", "0");
MYSQL_YYABORT;
}
- $$= (sp_cond_type_t *) thd->alloc(sizeof(sp_cond_type_t));
+ $$= new (thd->mem_root) sp_condition_value($1);
if ($$ == NULL)
MYSQL_YYABORT;
- $$->type= sp_cond_type_t::number;
- $$->mysqlerr= $1;
}
| sqlstate
;
@@ -2918,17 +3230,22 @@ sp_cond:
sqlstate:
SQLSTATE_SYM opt_value TEXT_STRING_literal
{ /* SQLSTATE */
- if (!sp_cond_check(&$3))
+
+ /*
+ An error is triggered:
+ - if the specified string is not a valid SQLSTATE,
+ - or if it represents the completion condition -- it is not
+ allowed to SIGNAL, or declare a handler for the completion
+ condition.
+ */
+ if (!is_sqlstate_valid(&$3) || is_sqlstate_completion($3.str))
{
my_error(ER_SP_BAD_SQLSTATE, MYF(0), $3.str);
MYSQL_YYABORT;
}
- $$= (sp_cond_type_t *) thd->alloc(sizeof(sp_cond_type_t));
+ $$= new (thd->mem_root) sp_condition_value($3.str);
if ($$ == NULL)
MYSQL_YYABORT;
- $$->type= sp_cond_type_t::state;
- memcpy($$->sqlstate, $3.str, SQLSTATE_LENGTH);
- $$->sqlstate[SQLSTATE_LENGTH]= '\0';
}
;
@@ -2944,7 +3261,7 @@ sp_hcond:
}
| ident /* CONDITION name */
{
- $$= Lex->spcont->find_cond(&$1);
+ $$= Lex->spcont->find_condition($1, false);
if ($$ == NULL)
{
my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
@@ -2953,24 +3270,21 @@ sp_hcond:
}
| SQLWARNING_SYM /* SQLSTATEs 01??? */
{
- $$= (sp_cond_type_t *) thd->alloc(sizeof(sp_cond_type_t));
+ $$= new (thd->mem_root) sp_condition_value(sp_condition_value::WARNING);
if ($$ == NULL)
MYSQL_YYABORT;
- $$->type= sp_cond_type_t::warning;
}
| not FOUND_SYM /* SQLSTATEs 02??? */
{
- $$= (sp_cond_type_t *) thd->alloc(sizeof(sp_cond_type_t));
+ $$= new (thd->mem_root) sp_condition_value(sp_condition_value::NOT_FOUND);
if ($$ == NULL)
MYSQL_YYABORT;
- $$->type= sp_cond_type_t::notfound;
}
| SQLEXCEPTION_SYM /* All other SQLSTATEs */
{
- $$= (sp_cond_type_t *) thd->alloc(sizeof(sp_cond_type_t));
+ $$= new (thd->mem_root) sp_condition_value(sp_condition_value::EXCEPTION);
if ($$ == NULL)
MYSQL_YYABORT;
- $$->type= sp_cond_type_t::exception;
}
;
@@ -2981,9 +3295,9 @@ signal_stmt:
Yacc_state *state= & thd->m_parser_state->m_yacc;
lex->sql_command= SQLCOM_SIGNAL;
- lex->m_stmt= new (thd->mem_root) Signal_statement(lex, $2,
- state->m_set_signal_info);
- if (lex->m_stmt == NULL)
+ lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_signal($2, state->m_set_signal_info);
+ if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
;
@@ -2992,20 +3306,20 @@ signal_value:
ident
{
LEX *lex= Lex;
- sp_cond_type_t *cond;
+ sp_condition_value *cond;
if (lex->spcont == NULL)
{
/* SIGNAL foo cannot be used outside of stored programs */
my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
MYSQL_YYABORT;
}
- cond= lex->spcont->find_cond(&$1);
+ cond= lex->spcont->find_condition($1, false);
if (cond == NULL)
{
my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
MYSQL_YYABORT;
}
- if (cond->type != sp_cond_type_t::state)
+ if (cond->type != sp_condition_value::SQLSTATE)
{
my_error(ER_SIGNAL_BAD_CONDITION_TYPE, MYF(0));
MYSQL_YYABORT;
@@ -3119,13 +3433,160 @@ resignal_stmt:
Yacc_state *state= & thd->m_parser_state->m_yacc;
lex->sql_command= SQLCOM_RESIGNAL;
- lex->m_stmt= new (thd->mem_root) Resignal_statement(lex, $2,
- state->m_set_signal_info);
- if (lex->m_stmt == NULL)
+ lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_resignal($2,
+ state->m_set_signal_info);
+ if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
;
+get_diagnostics:
+ GET_SYM which_area DIAGNOSTICS_SYM diagnostics_information
+ {
+ Diagnostics_information *info= $4;
+
+ info->set_which_da($2);
+
+ Lex->sql_command= SQLCOM_GET_DIAGNOSTICS;
+ Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_get_diagnostics(info);
+
+ if (Lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+which_area:
+ /* If <which area> is not specified, then CURRENT is implicit. */
+ { $$= Diagnostics_information::CURRENT_AREA; }
+ | CURRENT_SYM
+ { $$= Diagnostics_information::CURRENT_AREA; }
+ ;
+
+diagnostics_information:
+ statement_information
+ {
+ $$= new (thd->mem_root) Statement_information($1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | CONDITION_SYM condition_number condition_information
+ {
+ $$= new (thd->mem_root) Condition_information($2, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+statement_information:
+ statement_information_item
+ {
+ $$= new (thd->mem_root) List<Statement_information_item>;
+ if ($$ == NULL || $$->push_back($1))
+ MYSQL_YYABORT;
+ }
+ | statement_information ',' statement_information_item
+ {
+ if ($1->push_back($3))
+ MYSQL_YYABORT;
+ $$= $1;
+ }
+ ;
+
+statement_information_item:
+ simple_target_specification EQ statement_information_item_name
+ {
+ $$= new (thd->mem_root) Statement_information_item($3, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+
+simple_target_specification:
+ ident
+ {
+ Lex_input_stream *lip= &thd->m_parser_state->m_lip;
+ $$= create_item_for_sp_var(thd, $1, NULL,
+ lip->get_tok_start(), lip->get_ptr());
+
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | '@' ident_or_text
+ {
+ $$= new (thd->mem_root) Item_func_get_user_var($2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+statement_information_item_name:
+ NUMBER_SYM
+ { $$= Statement_information_item::NUMBER; }
+ | ROW_COUNT_SYM
+ { $$= Statement_information_item::ROW_COUNT; }
+ ;
+
+/*
+ Only a limited subset of <expr> are allowed in GET DIAGNOSTICS
+ <condition number>, same subset as for SIGNAL/RESIGNAL.
+*/
+condition_number:
+ signal_allowed_expr
+ { $$= $1; }
+ ;
+
+condition_information:
+ condition_information_item
+ {
+ $$= new (thd->mem_root) List<Condition_information_item>;
+ if ($$ == NULL || $$->push_back($1))
+ MYSQL_YYABORT;
+ }
+ | condition_information ',' condition_information_item
+ {
+ if ($1->push_back($3))
+ MYSQL_YYABORT;
+ $$= $1;
+ }
+ ;
+
+condition_information_item:
+ simple_target_specification EQ condition_information_item_name
+ {
+ $$= new (thd->mem_root) Condition_information_item($3, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+
+condition_information_item_name:
+ CLASS_ORIGIN_SYM
+ { $$= Condition_information_item::CLASS_ORIGIN; }
+ | SUBCLASS_ORIGIN_SYM
+ { $$= Condition_information_item::SUBCLASS_ORIGIN; }
+ | CONSTRAINT_CATALOG_SYM
+ { $$= Condition_information_item::CONSTRAINT_CATALOG; }
+ | CONSTRAINT_SCHEMA_SYM
+ { $$= Condition_information_item::CONSTRAINT_SCHEMA; }
+ | CONSTRAINT_NAME_SYM
+ { $$= Condition_information_item::CONSTRAINT_NAME; }
+ | CATALOG_NAME_SYM
+ { $$= Condition_information_item::CATALOG_NAME; }
+ | SCHEMA_NAME_SYM
+ { $$= Condition_information_item::SCHEMA_NAME; }
+ | TABLE_NAME_SYM
+ { $$= Condition_information_item::TABLE_NAME; }
+ | COLUMN_NAME_SYM
+ { $$= Condition_information_item::COLUMN_NAME; }
+ | CURSOR_NAME_SYM
+ { $$= Condition_information_item::CURSOR_NAME; }
+ | MESSAGE_TEXT_SYM
+ { $$= Condition_information_item::MESSAGE_TEXT; }
+ | MYSQL_ERRNO_SYM
+ { $$= Condition_information_item::MYSQL_ERRNO; }
+ | RETURNED_SQLSTATE_SYM
+ { $$= Condition_information_item::RETURNED_SQLSTATE; }
+ ;
+
sp_decl_idents:
ident
{
@@ -3134,12 +3595,15 @@ sp_decl_idents:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_variable(&$1, TRUE))
+ if (spc->find_variable($1, TRUE))
{
my_error(ER_SP_DUP_VAR, MYF(0), $1.str);
MYSQL_YYABORT;
}
- spc->push_variable(&$1, (enum_field_types)0, sp_param_in);
+ spc->add_variable(thd,
+ $1,
+ MYSQL_TYPE_DECIMAL,
+ sp_variable::MODE_IN);
$$= 1;
}
| sp_decl_idents ',' ident
@@ -3149,12 +3613,15 @@ sp_decl_idents:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_variable(&$3, TRUE))
+ if (spc->find_variable($3, TRUE))
{
my_error(ER_SP_DUP_VAR, MYF(0), $3.str);
MYSQL_YYABORT;
}
- spc->push_variable(&$3, (enum_field_types)0, sp_param_in);
+ spc->add_variable(thd,
+ $3,
+ MYSQL_TYPE_DECIMAL,
+ sp_variable::MODE_IN);
$$= $1 + 1;
}
;
@@ -3229,7 +3696,7 @@ sp_proc_stmt_statement:
if (yychar == YYEMPTY)
i->m_query.length= lip->get_ptr() - sp->m_tmp_query;
else
- i->m_query.length= lip->get_tok_end() - sp->m_tmp_query;
+ i->m_query.length= lip->get_tok_start() - sp->m_tmp_query;;
if (!(i->m_query.str= strmake_root(thd->mem_root,
sp->m_tmp_query,
i->m_query.length)) ||
@@ -3274,7 +3741,8 @@ sp_proc_stmt_unlabeled:
{ /* Unlabeled controls get a secret label. */
LEX *lex= Lex;
- lex->spcont->push_label((char *)"", lex->sphead->instructions());
+ lex->spcont->push_label(thd, empty_lex_str,
+ lex->sphead->instructions());
}
sp_unlabeled_control
{
@@ -3290,7 +3758,7 @@ sp_proc_stmt_leave:
LEX *lex= Lex;
sp_head *sp = lex->sphead;
sp_pcontext *ctx= lex->spcont;
- sp_label_t *lab= ctx->find_label($2.str);
+ sp_label *lab= ctx->find_label($2);
if (! lab)
{
@@ -3310,7 +3778,7 @@ sp_proc_stmt_leave:
there are no hpop/cpop at the jump destination,
so we should include the block context here for cleanup.
*/
- bool exclusive= (lab->type == SP_LAB_BEGIN);
+ bool exclusive= (lab->type == sp_label::BEGIN);
n= ctx->diff_handlers(lab->ctx, exclusive);
if (n)
@@ -3343,9 +3811,9 @@ sp_proc_stmt_iterate:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
- sp_label_t *lab= ctx->find_label($2.str);
+ sp_label *lab= ctx->find_label($2);
- if (! lab || lab->type != SP_LAB_ITER)
+ if (! lab || lab->type != sp_label::ITERATION)
{
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str);
MYSQL_YYABORT;
@@ -3388,7 +3856,7 @@ sp_proc_stmt_open:
uint offset;
sp_instr_copen *i;
- if (! lex->spcont->find_cursor(&$2, &offset))
+ if (! lex->spcont->find_cursor($2, &offset, false))
{
my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
MYSQL_YYABORT;
@@ -3408,7 +3876,7 @@ sp_proc_stmt_fetch:
uint offset;
sp_instr_cfetch *i;
- if (! lex->spcont->find_cursor(&$3, &offset))
+ if (! lex->spcont->find_cursor($3, &offset, false))
{
my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $3.str);
MYSQL_YYABORT;
@@ -3430,7 +3898,7 @@ sp_proc_stmt_close:
uint offset;
sp_instr_cclose *i;
- if (! lex->spcont->find_cursor(&$2, &offset))
+ if (! lex->spcont->find_cursor($2, &offset, false))
{
my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
MYSQL_YYABORT;
@@ -3454,9 +3922,9 @@ sp_fetch_list:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *spc= lex->spcont;
- sp_variable_t *spv;
+ sp_variable *spv;
- if (!spc || !(spv = spc->find_variable(&$1)))
+ if (!spc || !(spv = spc->find_variable($1, false)))
{
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
MYSQL_YYABORT;
@@ -3474,9 +3942,9 @@ sp_fetch_list:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *spc= lex->spcont;
- sp_variable_t *spv;
+ sp_variable *spv;
- if (!spc || !(spv = spc->find_variable(&$3)))
+ if (!spc || !(spv = spc->find_variable($3, false)))
{
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $3.str);
MYSQL_YYABORT;
@@ -3502,7 +3970,7 @@ sp_if:
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx,
$2, lex);
if (i == NULL ||
- sp->push_backpatch(i, ctx->push_label((char *)"", 0)) ||
+ sp->push_backpatch(i, ctx->push_label(thd, empty_lex_str, 0)) ||
sp->add_cont_backpatch(i) ||
sp->add_instr(i))
MYSQL_YYABORT;
@@ -3519,7 +3987,7 @@ sp_if:
sp->add_instr(i))
MYSQL_YYABORT;
sp->backpatch(ctx->pop_label());
- sp->push_backpatch(i, ctx->push_label((char *)"", 0));
+ sp->push_backpatch(i, ctx->push_label(thd, empty_lex_str, 0));
}
sp_elseifs
{
@@ -3661,7 +4129,7 @@ sp_labeled_control:
{
LEX *lex= Lex;
sp_pcontext *ctx= lex->spcont;
- sp_label_t *lab= ctx->find_label($1.str);
+ sp_label *lab= ctx->find_label($1);
if (lab)
{
@@ -3670,19 +4138,18 @@ sp_labeled_control:
}
else
{
- lab= lex->spcont->push_label($1.str,
- lex->sphead->instructions());
- lab->type= SP_LAB_ITER;
+ lab= lex->spcont->push_label(thd, $1, lex->sphead->instructions());
+ lab->type= sp_label::ITERATION;
}
}
sp_unlabeled_control sp_opt_label
{
LEX *lex= Lex;
- sp_label_t *lab= lex->spcont->pop_label();
+ sp_label *lab= lex->spcont->pop_label();
if ($5.str)
{
- if (my_strcasecmp(system_charset_info, $5.str, lab->name) != 0)
+ if (my_strcasecmp(system_charset_info, $5.str, lab->name.str) != 0)
{
my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str);
MYSQL_YYABORT;
@@ -3702,7 +4169,7 @@ sp_labeled_block:
{
LEX *lex= Lex;
sp_pcontext *ctx= lex->spcont;
- sp_label_t *lab= ctx->find_label($1.str);
+ sp_label *lab= ctx->find_label($1);
if (lab)
{
@@ -3710,18 +4177,17 @@ sp_labeled_block:
MYSQL_YYABORT;
}
- lab= lex->spcont->push_label($1.str,
- lex->sphead->instructions());
- lab->type= SP_LAB_BEGIN;
+ lab= lex->spcont->push_label(thd, $1, lex->sphead->instructions());
+ lab->type= sp_label::BEGIN;
}
sp_block_content sp_opt_label
{
LEX *lex= Lex;
- sp_label_t *lab= lex->spcont->pop_label();
+ sp_label *lab= lex->spcont->pop_label();
if ($5.str)
{
- if (my_strcasecmp(system_charset_info, $5.str, lab->name) != 0)
+ if (my_strcasecmp(system_charset_info, $5.str, lab->name.str) != 0)
{
my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str);
MYSQL_YYABORT;
@@ -3734,8 +4200,8 @@ sp_unlabeled_block:
{ /* Unlabeled blocks get a secret label. */
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
- sp_label_t *lab= lex->spcont->push_label((char *)"", ip);
- lab->type= SP_LAB_BEGIN;
+ sp_label *lab= lex->spcont->push_label(thd, empty_lex_str, ip);
+ lab->type= sp_label::BEGIN;
}
sp_block_content
{
@@ -3750,7 +4216,8 @@ sp_block_content:
together. No [[NOT] ATOMIC] yet, and we need to figure out how
make it coexist with the existing BEGIN COMMIT/ROLLBACK. */
LEX *lex= Lex;
- lex->spcont= lex->spcont->push_context(LABEL_DEFAULT_SCOPE);
+ lex->spcont= lex->spcont->push_context(thd,
+ sp_pcontext::REGULAR_SCOPE);
}
sp_decls
sp_proc_stmts
@@ -3786,7 +4253,7 @@ sp_unlabeled_control:
{
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
- sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
+ sp_label *lab= lex->spcont->last_label(); /* Jumping back */
sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
if (i == NULL ||
lex->sphead->add_instr(i))
@@ -3814,7 +4281,7 @@ sp_unlabeled_control:
{
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
- sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
+ sp_label *lab= lex->spcont->last_label(); /* Jumping back */
sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
if (i == NULL ||
lex->sphead->add_instr(i))
@@ -3827,7 +4294,7 @@ sp_unlabeled_control:
{
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
- sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
+ sp_label *lab= lex->spcont->last_label(); /* Jumping back */
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
$5, lab->ip,
lex);
@@ -4250,34 +4717,23 @@ size_number:
End tablespace part
*/
-create2:
- '(' create2a {}
- | opt_create_table_options
- opt_create_partitioning
- create3 {}
- | LIKE table_ident
- {
- TABLE_LIST *src_table;
- LEX *lex= thd->lex;
-
- lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE;
- src_table= lex->select_lex.add_table_to_list(thd, $2, NULL, 0,
- TL_READ,
- MDL_SHARED_READ);
- if (! src_table)
- MYSQL_YYABORT;
- /* CREATE TABLE ... LIKE is not allowed for views. */
- src_table->required_type= FRMTYPE_TABLE;
- }
- | '(' LIKE table_ident ')'
+create_body:
+ '(' create_field_list ')'
+ { Lex->create_info.option_list= NULL; }
+ opt_create_table_options opt_create_partitioning opt_create_select {}
+ | opt_create_table_options opt_create_partitioning opt_create_select {}
+ /*
+ the following rule is redundant, but there's a shift/reduce
+ conflict that prevents the rule above from parsing a syntax like
+ CREATE TABLE t1 (SELECT 1);
+ */
+ | '(' create_select ')' { Select->set_braces(1);} union_opt {}
+ | create_like
{
- TABLE_LIST *src_table;
- LEX *lex= thd->lex;
- lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE;
- src_table= lex->select_lex.add_table_to_list(thd, $3, NULL, 0,
- TL_READ,
- MDL_SHARED_READ);
+ Lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE;
+ TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(thd,
+ $1, NULL, 0, TL_READ, MDL_SHARED_READ);
if (! src_table)
MYSQL_YYABORT;
/* CREATE TABLE ... LIKE is not allowed for views. */
@@ -4285,21 +4741,12 @@ create2:
}
;
-create2a:
- create_field_list ')'
- {
- Lex->create_info.option_list= NULL;
- }
- opt_create_table_options
- opt_create_partitioning
- create3 {}
- | opt_create_partitioning
- create_select ')'
- { Select->set_braces(1);}
- union_opt {}
+create_like:
+ LIKE table_ident { $$= $2; }
+ | '(' LIKE table_ident ')' { $$= $3; }
;
-create3:
+opt_create_select:
/* empty */ {}
| opt_duplicate opt_as create_select
{ Select->set_braces(0);}
@@ -4363,7 +4810,7 @@ partitioning:
}
if (lex->sql_command == SQLCOM_ALTER_TABLE)
{
- lex->alter_info.flags|= ALTER_PARTITION;
+ lex->alter_info.flags|= Alter_info::ALTER_PARTITION;
}
}
partition
@@ -5078,9 +5525,28 @@ table_option:
;
opt_if_not_exists:
- /* empty */ { $$= 0; }
- | IF not EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; }
- ;
+ /* empty */
+ {
+ Lex->check_exists= FALSE;
+ $$= 0;
+ }
+ | IF not EXISTS
+ {
+ Lex->check_exists= TRUE;
+ $$=HA_LEX_CREATE_IF_NOT_EXISTS;
+ }
+ ;
+
+create_or_replace:
+ CREATE /* empty */
+ {
+ $$= 0;
+ }
+ | CREATE OR_SYM REPLACE
+ {
+ $$= HA_LEX_CREATE_REPLACE;
+ }
+ ;
opt_create_table_options:
/* empty */
@@ -5155,6 +5621,70 @@ create_table_option:
~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;
}
+ | STATS_AUTO_RECALC_SYM opt_equal ulong_num
+ {
+ switch($3) {
+ case 0:
+ Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_OFF;
+ break;
+ case 1:
+ Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_ON;
+ break;
+ default:
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ MYSQL_YYABORT;
+ }
+ Lex->create_info.used_fields|= HA_CREATE_USED_STATS_AUTO_RECALC;
+ }
+ | STATS_AUTO_RECALC_SYM opt_equal DEFAULT
+ {
+ Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_DEFAULT;
+ Lex->create_info.used_fields|= HA_CREATE_USED_STATS_AUTO_RECALC;
+ }
+ | STATS_PERSISTENT_SYM opt_equal ulong_num
+ {
+ switch($3) {
+ case 0:
+ Lex->create_info.table_options|= HA_OPTION_NO_STATS_PERSISTENT;
+ break;
+ case 1:
+ Lex->create_info.table_options|= HA_OPTION_STATS_PERSISTENT;
+ break;
+ default:
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ MYSQL_YYABORT;
+ }
+ Lex->create_info.used_fields|= HA_CREATE_USED_STATS_PERSISTENT;
+ }
+ | STATS_PERSISTENT_SYM opt_equal DEFAULT
+ {
+ Lex->create_info.table_options&=
+ ~(HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT);
+ Lex->create_info.used_fields|= HA_CREATE_USED_STATS_PERSISTENT;
+ }
+ | STATS_SAMPLE_PAGES_SYM opt_equal ulong_num
+ {
+ /* From user point of view STATS_SAMPLE_PAGES can be specified as
+ STATS_SAMPLE_PAGES=N (where 0<N<=65535, it does not make sense to
+ scan 0 pages) or STATS_SAMPLE_PAGES=default. Internally we record
+ =default as 0. See create_frm() in sql/table.cc, we use only two
+ bytes for stats_sample_pages and this is why we do not allow
+ larger values. 65535 pages, 16kb each means to sample 1GB, which
+ is impractical. If at some point this needs to be extended, then
+ we can store the higher bits from stats_sample_pages in .frm too. */
+ if ($3 == 0 || $3 > 0xffff)
+ {
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ MYSQL_YYABORT;
+ }
+ Lex->create_info.stats_sample_pages=$3;
+ Lex->create_info.used_fields|= HA_CREATE_USED_STATS_SAMPLE_PAGES;
+ }
+ | STATS_SAMPLE_PAGES_SYM opt_equal DEFAULT
+ {
+ Lex->create_info.stats_sample_pages=0;
+ Lex->create_info.used_fields|= HA_CREATE_USED_STATS_SAMPLE_PAGES;
+ }
| CHECKSUM_SYM opt_equal ulong_num
{
Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM;
@@ -5274,18 +5804,8 @@ create_table_option:
default_charset:
opt_default charset opt_equal charset_name_or_default
{
- HA_CREATE_INFO *cinfo= &Lex->create_info;
- if ((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
- cinfo->default_table_charset && $4 &&
- !my_charset_same(cinfo->default_table_charset,$4))
- {
- my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
- "CHARACTER SET ", cinfo->default_table_charset->csname,
- "CHARACTER SET ", $4->csname);
+ if (Lex->create_info.add_table_option_default_charset($4))
MYSQL_YYABORT;
- }
- Lex->create_info.default_table_charset= $4;
- Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
}
;
@@ -5312,7 +5832,7 @@ storage_engines:
plugin_ref plugin= ha_resolve_by_name(thd, &$1);
if (plugin)
- $$= plugin_data(plugin, handlerton*);
+ $$= plugin_hton(plugin);
else
{
if (thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION)
@@ -5321,7 +5841,7 @@ storage_engines:
MYSQL_YYABORT;
}
$$= 0;
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_UNKNOWN_STORAGE_ENGINE,
ER(ER_UNKNOWN_STORAGE_ENGINE),
$1.str);
@@ -5334,7 +5854,7 @@ known_storage_engines:
{
plugin_ref plugin;
if ((plugin= ha_resolve_by_name(thd, &$1)))
- $$= plugin_data(plugin, handlerton*);
+ $$= plugin_hton(plugin);
else
{
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
@@ -5398,14 +5918,14 @@ column_def:
;
key_def:
- normal_key_type opt_ident key_alg '(' key_list ')'
+ normal_key_type opt_if_not_exists_ident key_alg '(' key_list ')'
{ Lex->option_list= NULL; }
normal_key_options
{
if (add_create_index (Lex, $1, $2))
MYSQL_YYABORT;
}
- | fulltext opt_key_or_index opt_ident init_key_options
+ | fulltext opt_key_or_index opt_if_not_exists_ident init_key_options
'(' key_list ')'
{ Lex->option_list= NULL; }
fulltext_key_options
@@ -5413,7 +5933,7 @@ key_def:
if (add_create_index (Lex, $1, $3))
MYSQL_YYABORT;
}
- | spatial opt_key_or_index opt_ident init_key_options
+ | spatial opt_key_or_index opt_if_not_exists_ident init_key_options
'(' key_list ')'
{ Lex->option_list= NULL; }
spatial_key_options
@@ -5421,7 +5941,7 @@ key_def:
if (add_create_index (Lex, $1, $3))
MYSQL_YYABORT;
}
- | opt_constraint constraint_key_type opt_ident key_alg
+ | opt_constraint constraint_key_type opt_if_not_exists_ident key_alg
'(' key_list ')'
{ Lex->option_list= NULL; }
normal_key_options
@@ -5429,15 +5949,17 @@ key_def:
if (add_create_index (Lex, $2, $3.str ? $3 : $1))
MYSQL_YYABORT;
}
- | opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
+ | opt_constraint FOREIGN KEY_SYM opt_if_not_exists_ident '(' key_list ')' references
{
LEX *lex=Lex;
Key *key= new Foreign_key($4.str ? $4 : $1, lex->col_list,
- $8,
+ $8->db,
+ $8->table,
lex->ref_list,
lex->fk_delete_opt,
lex->fk_update_opt,
- lex->fk_match_option);
+ lex->fk_match_option,
+ lex->check_exists);
if (key == NULL)
MYSQL_YYABORT;
lex->alter_info.key_list.push_back(key);
@@ -5446,7 +5968,7 @@ key_def:
&default_key_create_info, 1))
MYSQL_YYABORT;
/* Only used for ALTER TABLE. Ignored otherwise. */
- lex->alter_info.flags|= ALTER_FOREIGN_KEY;
+ lex->alter_info.flags|= Alter_info::ADD_FOREIGN_KEY;
}
| opt_constraint check_constraint
{
@@ -5546,13 +6068,13 @@ vcol_attribute:
{
LEX *lex=Lex;
lex->type|= UNIQUE_FLAG;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
| UNIQUE_SYM KEY_SYM
{
LEX *lex=Lex;
lex->type|= UNIQUE_KEY_FLAG;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
| COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
;
@@ -5667,7 +6189,7 @@ type:
{
char buff[sizeof("YEAR()") + MY_INT64_NUM_DECIMAL_DIGITS + 1];
my_snprintf(buff, sizeof(buff), "YEAR(%lu)", length);
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_WARN_DEPRECATED_SYNTAX,
ER(ER_WARN_DEPRECATED_SYNTAX),
buff, "YEAR(4)");
@@ -5887,9 +6409,9 @@ attribute:
NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; }
| not NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
| DEFAULT now_or_signed_literal { Lex->default_value=$2; }
- | ON UPDATE_SYM NOW_SYM optional_braces
+ | ON UPDATE_SYM NOW_SYM opt_default_time_precision
{
- Item *item= new (thd->mem_root) Item_func_now_local(6);
+ Item *item= new (thd->mem_root) Item_func_now_local($4);
if (item == NULL)
MYSQL_YYABORT;
Lex->on_update_value= item;
@@ -5899,25 +6421,25 @@ attribute:
{
LEX *lex=Lex;
lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
| opt_primary KEY_SYM
{
LEX *lex=Lex;
lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
| UNIQUE_SYM
{
LEX *lex=Lex;
lex->type|= UNIQUE_FLAG;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
| UNIQUE_SYM KEY_SYM
{
LEX *lex=Lex;
lex->type|= UNIQUE_KEY_FLAG;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
| COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
| COLLATE_SYM collation_name
@@ -5981,9 +6503,9 @@ type_with_opt_collate:
now_or_signed_literal:
- NOW_SYM optional_braces
+ NOW_SYM opt_default_time_precision
{
- $$= new (thd->mem_root) Item_func_now_local(6);
+ $$= new (thd->mem_root) Item_func_now_local($2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -5991,11 +6513,6 @@ now_or_signed_literal:
{ $$=$1; }
;
-hex_num_or_string:
- HEX_NUM {}
- | HEX_STRING {}
- ;
-
charset:
CHAR_SYM SET {}
| CHARSET {}
@@ -6044,11 +6561,8 @@ old_or_new_charset_name_or_default:
collation_name:
ident_or_text
{
- if (!($$=get_charset_by_name($1.str,MYF(0))))
- {
- my_error(ER_UNKNOWN_COLLATION, MYF(0), $1.str);
+ if (!($$= mysqld_collation_get_by_name($1.str)))
MYSQL_YYABORT;
- }
}
;
@@ -6092,19 +6606,13 @@ unicode:
}
| UNICODE_SYM BINARY
{
- if (!(Lex->charset=get_charset_by_name("ucs2_bin", MYF(0))))
- {
- my_error(ER_UNKNOWN_COLLATION, MYF(0), "ucs2_bin");
+ if (!(Lex->charset= mysqld_collation_get_by_name("ucs2_bin")))
MYSQL_YYABORT;
- }
}
| BINARY UNICODE_SYM
{
- if (!(Lex->charset=get_charset_by_name("ucs2_bin", MYF(0))))
- {
- my_error(ER_UNKNOWN_COLLATION, MYF(0), "ucs2_bin");
+ if (!(Lex->charset= mysqld_collation_get_by_name("ucs2_bin")))
MYSQL_YYABORT;
- }
}
;
@@ -6131,6 +6639,73 @@ opt_bin_mod:
| BINARY { Lex->type|= BINCMP_FLAG; }
;
+ws_nweights:
+ '(' real_ulong_num
+ {
+ if ($2 == 0)
+ {
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ MYSQL_YYABORT;
+ }
+ }
+ ')'
+ { $$= $2; }
+ ;
+
+ws_level_flag_desc:
+ ASC { $$= 0; }
+ | DESC { $$= 1 << MY_STRXFRM_DESC_SHIFT; }
+ ;
+
+ws_level_flag_reverse:
+ REVERSE_SYM { $$= 1 << MY_STRXFRM_REVERSE_SHIFT; } ;
+
+ws_level_flags:
+ /* empty */ { $$= 0; }
+ | ws_level_flag_desc { $$= $1; }
+ | ws_level_flag_desc ws_level_flag_reverse { $$= $1 | $2; }
+ | ws_level_flag_reverse { $$= $1 ; }
+ ;
+
+ws_level_number:
+ real_ulong_num
+ {
+ $$= $1 < 1 ? 1 : ($1 > MY_STRXFRM_NLEVELS ? MY_STRXFRM_NLEVELS : $1);
+ $$--;
+ }
+ ;
+
+ws_level_list_item:
+ ws_level_number ws_level_flags
+ {
+ $$= (1 | $2) << $1;
+ }
+ ;
+
+ws_level_list:
+ ws_level_list_item { $$= $1; }
+ | ws_level_list ',' ws_level_list_item { $$|= $3; }
+ ;
+
+ws_level_range:
+ ws_level_number '-' ws_level_number
+ {
+ uint start= $1;
+ uint end= $3;
+ for ($$= 0; start <= end; start++)
+ $$|= (1 << start);
+ }
+ ;
+
+ws_level_list_or_range:
+ ws_level_list { $$= $1; }
+ | ws_level_range { $$= $1; }
+ ;
+
+opt_ws_levels:
+ /* empty*/ { $$= 0; }
+ | LEVEL_SYM ws_level_list_or_range { $$= $2; }
+ ;
opt_primary:
/* empty */
@@ -6414,6 +6989,18 @@ opt_ident:
| field_ident { $$= $1; }
;
+opt_if_not_exists_ident:
+ opt_if_not_exists opt_ident
+ {
+ LEX *lex= Lex;
+ if (lex->check_exists && lex->sql_command != SQLCOM_ALTER_TABLE)
+ {
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ MYSQL_YYABORT;
+ }
+ $$= $2;
+ };
+
opt_component:
/* empty */ { $$= null_lex_str; }
| '.' ident { $$= $2; }
@@ -6428,39 +7015,41 @@ string_list:
*/
alter:
- ALTER alter_options TABLE_SYM table_ident
+ ALTER
+ {
+ Lex->name.str= 0;
+ Lex->name.length= 0;
+ Lex->only_view= FALSE;
+ Lex->sql_command= SQLCOM_ALTER_TABLE;
+ Lex->duplicates= DUP_ERROR;
+ Lex->col_list.empty();
+ Lex->select_lex.init_order();
+ bzero(&Lex->create_info, sizeof(Lex->create_info));
+ Lex->create_info.db_type= 0;
+ Lex->create_info.default_table_charset= NULL;
+ Lex->create_info.row_type= ROW_TYPE_NOT_USED;
+ Lex->alter_info.reset();
+ Lex->no_write_to_binlog= 0;
+ Lex->create_info.storage_media= HA_SM_DEFAULT;
+ DBUG_ASSERT(!Lex->m_sql_cmd);
+ }
+ alter_options TABLE_SYM table_ident
{
- LEX *lex= thd->lex;
- lex->name.str= 0;
- lex->name.length= 0;
- lex->sql_command= SQLCOM_ALTER_TABLE;
- lex->duplicates= DUP_ERROR;
- if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
+ if (!Lex->select_lex.add_table_to_list(thd, $5, NULL,
TL_OPTION_UPDATING,
TL_READ_NO_INSERT,
- MDL_SHARED_NO_WRITE))
+ MDL_SHARED_UPGRADABLE))
MYSQL_YYABORT;
- lex->col_list.empty();
- lex->select_lex.init_order();
- lex->select_lex.db= (lex->select_lex.table_list.first)->db;
- bzero((char*) &lex->create_info,sizeof(lex->create_info));
- lex->create_info.db_type= 0;
- lex->create_info.default_table_charset= NULL;
- lex->create_info.row_type= ROW_TYPE_NOT_USED;
- lex->alter_info.reset();
- lex->no_write_to_binlog= 0;
- lex->create_info.storage_media= HA_SM_DEFAULT;
- lex->create_last_non_select_table= lex->last_table();
- DBUG_ASSERT(!lex->m_stmt);
+ Lex->select_lex.db= (Lex->select_lex.table_list.first)->db;
+ Lex->create_last_non_select_table= Lex->last_table();
}
alter_commands
{
- LEX *lex= thd->lex;
- if (!lex->m_stmt)
+ if (!Lex->m_sql_cmd)
{
/* Create a generic ALTER TABLE statment. */
- lex->m_stmt= new (thd->mem_root) Alter_table_statement(lex);
- if (lex->m_stmt == NULL)
+ Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table();
+ if (Lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
}
@@ -6657,8 +7246,22 @@ ident_or_empty:
alter_commands:
/* empty */
- | DISCARD TABLESPACE { Lex->alter_info.tablespace_op= DISCARD_TABLESPACE; }
- | IMPORT TABLESPACE { Lex->alter_info.tablespace_op= IMPORT_TABLESPACE; }
+ | DISCARD TABLESPACE
+ {
+ Lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_discard_import_tablespace(
+ Sql_cmd_discard_import_tablespace::DISCARD_TABLESPACE);
+ if (Lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ | IMPORT TABLESPACE
+ {
+ Lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_discard_import_tablespace(
+ Sql_cmd_discard_import_tablespace::IMPORT_TABLESPACE);
+ if (Lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
| alter_list
opt_partitioning
| alter_list
@@ -6670,19 +7273,18 @@ alter_commands:
From here we insert a number of commands to manage the partitions of a
partitioned table such as adding partitions, dropping partitions,
reorganising partitions in various manners. In future releases the list
- will be longer and also include moving partitions to a
- new table and so forth.
+ will be longer.
*/
| add_partition_rule
- | DROP PARTITION_SYM alt_part_name_list
+ | DROP PARTITION_SYM opt_if_exists alt_part_name_list
{
- Lex->alter_info.flags|= ALTER_DROP_PARTITION;
+ Lex->alter_info.flags|= Alter_info::ALTER_DROP_PARTITION;
}
| REBUILD_SYM PARTITION_SYM opt_no_write_to_binlog
all_or_alt_part_name_list
{
LEX *lex= Lex;
- lex->alter_info.flags|= ALTER_REBUILD_PARTITION;
+ lex->alter_info.flags|= Alter_info::ALTER_REBUILD_PARTITION;
lex->no_write_to_binlog= $3;
}
| OPTIMIZE PARTITION_SYM opt_no_write_to_binlog
@@ -6691,10 +7293,10 @@ alter_commands:
LEX *lex= thd->lex;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
- DBUG_ASSERT(!lex->m_stmt);
- lex->m_stmt= new (thd->mem_root)
- Alter_table_optimize_partition_statement(lex);
- if (lex->m_stmt == NULL)
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_alter_table_optimize_partition();
+ if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
opt_no_write_to_binlog
@@ -6704,20 +7306,20 @@ alter_commands:
LEX *lex= thd->lex;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
- DBUG_ASSERT(!lex->m_stmt);
- lex->m_stmt= new (thd->mem_root)
- Alter_table_analyze_partition_statement(lex);
- if (lex->m_stmt == NULL)
- MYSQL_YYABORT;
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_alter_table_analyze_partition();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
}
| CHECK_SYM PARTITION_SYM all_or_alt_part_name_list
{
LEX *lex= thd->lex;
lex->check_opt.init();
- DBUG_ASSERT(!lex->m_stmt);
- lex->m_stmt= new (thd->mem_root)
- Alter_table_check_partition_statement(lex);
- if (lex->m_stmt == NULL)
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_alter_table_check_partition();
+ if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
opt_mi_check_type
@@ -6727,17 +7329,17 @@ alter_commands:
LEX *lex= thd->lex;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
- DBUG_ASSERT(!lex->m_stmt);
- lex->m_stmt= new (thd->mem_root)
- Alter_table_repair_partition_statement(lex);
- if (lex->m_stmt == NULL)
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_alter_table_repair_partition();
+ if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
opt_mi_repair_type
| COALESCE PARTITION_SYM opt_no_write_to_binlog real_ulong_num
{
LEX *lex= Lex;
- lex->alter_info.flags|= ALTER_COALESCE_PARTITION;
+ lex->alter_info.flags|= Alter_info::ALTER_COALESCE_PARTITION;
lex->no_write_to_binlog= $3;
lex->alter_info.num_parts= $4;
}
@@ -6745,32 +7347,56 @@ alter_commands:
{
LEX *lex= thd->lex;
lex->check_opt.init();
- DBUG_ASSERT(!lex->m_stmt);
- lex->m_stmt= new (thd->mem_root)
- Alter_table_truncate_partition_statement(lex);
- if (lex->m_stmt == NULL)
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_alter_table_truncate_partition();
+ if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
| reorg_partition_rule
+ | EXCHANGE_SYM PARTITION_SYM alt_part_name_item
+ WITH TABLE_SYM table_ident have_partitioning
+ {
+ LEX *lex= thd->lex;
+ size_t dummy;
+ lex->select_lex.db=$6->db.str;
+ if (lex->select_lex.db == NULL &&
+ lex->copy_db_to(&lex->select_lex.db, &dummy))
+ {
+ MYSQL_YYABORT;
+ }
+ lex->name= $6->table;
+ lex->alter_info.flags|= Alter_info::ALTER_EXCHANGE_PARTITION;
+ if (!lex->select_lex.add_table_to_list(thd, $6, NULL,
+ TL_OPTION_UPDATING,
+ TL_READ_NO_INSERT,
+ MDL_SHARED_NO_WRITE))
+ MYSQL_YYABORT;
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_alter_table_exchange_partition();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
;
remove_partitioning:
REMOVE_SYM PARTITIONING_SYM
{
- Lex->alter_info.flags|= ALTER_REMOVE_PARTITIONING;
+ Lex->alter_info.flags|= Alter_info::ALTER_REMOVE_PARTITIONING;
}
;
all_or_alt_part_name_list:
ALL
{
- Lex->alter_info.flags|= ALTER_ALL_PARTITION;
+ Lex->alter_info.flags|= Alter_info::ALTER_ALL_PARTITION;
}
| alt_part_name_list
;
add_partition_rule:
- ADD PARTITION_SYM opt_no_write_to_binlog
+ ADD PARTITION_SYM opt_if_not_exists opt_no_write_to_binlog
{
LEX *lex= Lex;
lex->part_info= new partition_info();
@@ -6779,8 +7405,8 @@ add_partition_rule:
mem_alloc_error(sizeof(partition_info));
MYSQL_YYABORT;
}
- lex->alter_info.flags|= ALTER_ADD_PARTITION;
- lex->no_write_to_binlog= $3;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_PARTITION;
+ lex->no_write_to_binlog= $4;
}
add_part_extra
{}
@@ -6817,11 +7443,11 @@ reorg_partition_rule:
reorg_parts_rule:
/* empty */
{
- Lex->alter_info.flags|= ALTER_TABLE_REORG;
+ Lex->alter_info.flags|= Alter_info::ALTER_TABLE_REORG;
}
| alt_part_name_list
{
- Lex->alter_info.flags|= ALTER_REORGANIZE_PARTITION;
+ Lex->alter_info.flags|= Alter_info::ALTER_REORGANIZE_PARTITION;
}
INTO '(' part_def_list ')'
{
@@ -6856,11 +7482,11 @@ alter_list:
;
add_column:
- ADD opt_column
+ ADD opt_column opt_if_not_exists
{
LEX *lex=Lex;
lex->change=0;
- lex->alter_info.flags|= ALTER_ADD_COLUMN;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN;
}
;
@@ -6872,43 +7498,44 @@ alter_list_item:
| ADD key_def
{
Lex->create_last_non_select_table= Lex->last_table();
- Lex->alter_info.flags|= ALTER_ADD_INDEX;
+ Lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
| add_column '(' create_field_list ')'
{
- Lex->alter_info.flags|= ALTER_ADD_COLUMN | ALTER_ADD_INDEX;
+ Lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN |
+ Alter_info::ALTER_ADD_INDEX;
}
- | CHANGE opt_column field_ident
+ | CHANGE opt_column opt_if_exists field_ident
{
LEX *lex=Lex;
- lex->change= $3.str;
- lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+ lex->change= $4.str;
+ lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
lex->option_list= NULL;
}
field_spec opt_place
{
Lex->create_last_non_select_table= Lex->last_table();
}
- | MODIFY_SYM opt_column field_ident
+ | MODIFY_SYM opt_column opt_if_exists field_ident
{
LEX *lex=Lex;
lex->length=lex->dec=0; lex->type=0;
lex->default_value= lex->on_update_value= 0;
lex->comment=null_lex_str;
lex->charset= NULL;
- lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+ lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
lex->vcol_info= 0;
lex->option_list= NULL;
}
field_def
{
LEX *lex=Lex;
- if (add_field_to_list(lex->thd,&$3,
- $5.type,
- $5.length, $5.dec, lex->type,
+ if (add_field_to_list(lex->thd,&$4,
+ $6.type,
+ $6.length, $6.dec, lex->type,
lex->default_value, lex->on_update_value,
&lex->comment,
- $3.str, &lex->interval_list, $5.charset,
+ $4.str, &lex->interval_list, $6.charset,
lex->uint_geom_type,
lex->vcol_info, lex->option_list))
MYSQL_YYABORT;
@@ -6917,48 +7544,54 @@ alter_list_item:
{
Lex->create_last_non_select_table= Lex->last_table();
}
- | DROP opt_column field_ident opt_restrict
+ | DROP opt_column opt_if_exists field_ident opt_restrict
{
LEX *lex=Lex;
- Alter_drop *ad= new Alter_drop(Alter_drop::COLUMN, $3.str);
+ Alter_drop *ad= new Alter_drop(Alter_drop::COLUMN, $4.str, $3);
if (ad == NULL)
MYSQL_YYABORT;
lex->alter_info.drop_list.push_back(ad);
- lex->alter_info.flags|= ALTER_DROP_COLUMN;
+ lex->alter_info.flags|= Alter_info::ALTER_DROP_COLUMN;
}
- | DROP FOREIGN KEY_SYM opt_ident
+ | DROP FOREIGN KEY_SYM opt_if_exists field_ident
{
- Lex->alter_info.flags|= ALTER_DROP_INDEX | ALTER_FOREIGN_KEY;
+ LEX *lex=Lex;
+ Alter_drop *ad= new Alter_drop(Alter_drop::FOREIGN_KEY, $5.str, $4);
+ if (ad == NULL)
+ MYSQL_YYABORT;
+ lex->alter_info.drop_list.push_back(ad);
+ lex->alter_info.flags|= Alter_info::DROP_FOREIGN_KEY;
}
| DROP PRIMARY_SYM KEY_SYM
{
LEX *lex=Lex;
- Alter_drop *ad= new Alter_drop(Alter_drop::KEY, primary_key_name);
+ Alter_drop *ad= new Alter_drop(Alter_drop::KEY, primary_key_name,
+ FALSE);
if (ad == NULL)
MYSQL_YYABORT;
lex->alter_info.drop_list.push_back(ad);
- lex->alter_info.flags|= ALTER_DROP_INDEX;
+ lex->alter_info.flags|= Alter_info::ALTER_DROP_INDEX;
}
- | DROP key_or_index field_ident
+ | DROP key_or_index opt_if_exists field_ident
{
LEX *lex=Lex;
- Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $3.str);
+ Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $4.str, $3);
if (ad == NULL)
MYSQL_YYABORT;
lex->alter_info.drop_list.push_back(ad);
- lex->alter_info.flags|= ALTER_DROP_INDEX;
+ lex->alter_info.flags|= Alter_info::ALTER_DROP_INDEX;
}
| DISABLE_SYM KEYS
{
LEX *lex=Lex;
- lex->alter_info.keys_onoff= DISABLE;
- lex->alter_info.flags|= ALTER_KEYS_ONOFF;
+ lex->alter_info.keys_onoff= Alter_info::DISABLE;
+ lex->alter_info.flags|= Alter_info::ALTER_KEYS_ONOFF;
}
| ENABLE_SYM KEYS
{
LEX *lex=Lex;
- lex->alter_info.keys_onoff= ENABLE;
- lex->alter_info.flags|= ALTER_KEYS_ONOFF;
+ lex->alter_info.keys_onoff= Alter_info::ENABLE;
+ lex->alter_info.flags|= Alter_info::ALTER_KEYS_ONOFF;
}
| ALTER opt_column field_ident SET DEFAULT signed_literal
{
@@ -6967,7 +7600,7 @@ alter_list_item:
if (ac == NULL)
MYSQL_YYABORT;
lex->alter_info.alter_list.push_back(ac);
- lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT;
+ lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN_DEFAULT;
}
| ALTER opt_column field_ident DROP DEFAULT
{
@@ -6976,7 +7609,7 @@ alter_list_item:
if (ac == NULL)
MYSQL_YYABORT;
lex->alter_info.alter_list.push_back(ac);
- lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT;
+ lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN_DEFAULT;
}
| RENAME opt_to table_ident
{
@@ -6995,7 +7628,7 @@ alter_list_item:
MYSQL_YYABORT;
}
lex->name= $3->table;
- lex->alter_info.flags|= ALTER_RENAME;
+ lex->alter_info.flags|= Alter_info::ALTER_RENAME;
}
| CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate
{
@@ -7011,16 +7644,14 @@ alter_list_item:
MYSQL_YYABORT;
}
LEX *lex= Lex;
- lex->create_info.table_charset=
- lex->create_info.default_table_charset= $5;
- lex->create_info.used_fields|= (HA_CREATE_USED_CHARSET |
- HA_CREATE_USED_DEFAULT_CHARSET);
- lex->alter_info.flags|= ALTER_CONVERT;
+ if (lex->create_info.add_alter_list_item_convert_to_charset($5))
+ MYSQL_YYABORT;
+ lex->alter_info.flags|= Alter_info::ALTER_CONVERT;
}
| create_table_options_space_separated
{
LEX *lex=Lex;
- lex->alter_info.flags|= ALTER_OPTIONS;
+ lex->alter_info.flags|= Alter_info::ALTER_OPTIONS;
if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
!lex->create_info.db_type)
{
@@ -7029,12 +7660,53 @@ alter_list_item:
}
| FORCE_SYM
{
- Lex->alter_info.flags|= ALTER_RECREATE;
+ Lex->alter_info.flags|= Alter_info::ALTER_RECREATE;
}
| alter_order_clause
{
LEX *lex=Lex;
- lex->alter_info.flags|= ALTER_ORDER;
+ lex->alter_info.flags|= Alter_info::ALTER_ORDER;
+ }
+ | alter_algorithm_option
+ | alter_lock_option
+ ;
+
+opt_index_lock_algorithm:
+ /* empty */
+ | alter_lock_option
+ | alter_algorithm_option
+ | alter_lock_option alter_algorithm_option
+ | alter_algorithm_option alter_lock_option
+
+alter_algorithm_option:
+ ALGORITHM_SYM opt_equal DEFAULT
+ {
+ Lex->alter_info.requested_algorithm=
+ Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT;
+ }
+ | ALGORITHM_SYM opt_equal ident
+ {
+ if (Lex->alter_info.set_requested_algorithm(&$3))
+ {
+ my_error(ER_UNKNOWN_ALTER_ALGORITHM, MYF(0), $3.str);
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+alter_lock_option:
+ LOCK_SYM opt_equal DEFAULT
+ {
+ Lex->alter_info.requested_lock=
+ Alter_info::ALTER_TABLE_LOCK_DEFAULT;
+ }
+ | LOCK_SYM opt_equal ident
+ {
+ if (Lex->alter_info.set_requested_lock(&$3))
+ {
+ my_error(ER_UNKNOWN_ALTER_LOCK, MYF(0), $3.str);
+ MYSQL_YYABORT;
+ }
}
;
@@ -7049,7 +7721,7 @@ opt_ignore:
;
alter_options:
- { Lex->ignore= Lex->online= 0;} alter_options_part2
+ { Lex->ignore= 0;} alter_options_part2
;
alter_options_part2:
@@ -7064,7 +7736,11 @@ alter_option_list:
alter_option:
IGNORE_SYM { Lex->ignore= 1;}
- | ONLINE_SYM { Lex->online= 1;}
+ | ONLINE_SYM
+ {
+ Lex->alter_info.requested_lock=
+ Alter_info::ALTER_TABLE_LOCK_NONE;
+ }
opt_restrict:
@@ -7075,8 +7751,16 @@ opt_restrict:
opt_place:
/* empty */ {}
- | AFTER_SYM ident { store_position_for_column($2.str); }
- | FIRST_SYM { store_position_for_column(first_keyword); }
+ | AFTER_SYM ident
+ {
+ store_position_for_column($2.str);
+ Lex->alter_info.flags |= Alter_info::ALTER_COLUMN_ORDER;
+ }
+ | FIRST_SYM
+ {
+ store_position_for_column(first_keyword);
+ Lex->alter_info.flags |= Alter_info::ALTER_COLUMN_ORDER;
+ }
;
opt_to:
@@ -7086,12 +7770,8 @@ opt_to:
| AS {}
;
-/*
- SLAVE START and SLAVE STOP are deprecated. We keep them for compatibility.
-*/
-
slave:
- START_SYM SLAVE slave_thread_opts
+ START_SYM SLAVE optional_connection_name slave_thread_opts
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_SLAVE_START;
@@ -7100,44 +7780,80 @@ slave:
}
slave_until
{}
- | STOP_SYM SLAVE slave_thread_opts
+ | START_SYM ALL SLAVES slave_thread_opts
{
LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_STOP;
+ lex->sql_command = SQLCOM_SLAVE_ALL_START;
lex->type = 0;
- /* If you change this code don't forget to update SLAVE STOP too */
}
- | SLAVE START_SYM slave_thread_opts
+ {}
+ | STOP_SYM SLAVE optional_connection_name slave_thread_opts
{
LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_START;
+ lex->sql_command = SQLCOM_SLAVE_STOP;
lex->type = 0;
+ /* If you change this code don't forget to update SLAVE STOP too */
}
- slave_until
- {}
- | SLAVE STOP_SYM slave_thread_opts
+ | STOP_SYM ALL SLAVES slave_thread_opts
{
LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_STOP;
+ lex->sql_command = SQLCOM_SLAVE_ALL_STOP;
lex->type = 0;
+ /* If you change this code don't forget to update SLAVE STOP too */
}
;
start:
- START_SYM TRANSACTION_SYM start_transaction_opts
+ START_SYM TRANSACTION_SYM opt_start_transaction_option_list
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_BEGIN;
+ /* READ ONLY and READ WRITE are mutually exclusive. */
+ if (($3 & MYSQL_START_TRANS_OPT_READ_WRITE) &&
+ ($3 & MYSQL_START_TRANS_OPT_READ_ONLY))
+ {
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ MYSQL_YYABORT;
+ }
lex->start_transaction_opt= $3;
}
;
-start_transaction_opts:
- /*empty*/ { $$ = 0; }
- | WITH CONSISTENT_SYM SNAPSHOT_SYM
+opt_start_transaction_option_list:
+ /* empty */
+ {
+ $$= 0;
+ }
+ | start_transaction_option_list
+ {
+ $$= $1;
+ }
+ ;
+
+start_transaction_option_list:
+ start_transaction_option
+ {
+ $$= $1;
+ }
+ | start_transaction_option_list ',' start_transaction_option
+ {
+ $$= $1 | $3;
+ }
+ ;
+
+start_transaction_option:
+ WITH CONSISTENT_SYM SNAPSHOT_SYM
{
$$= MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT;
}
+ | READ_SYM ONLY_SYM
+ {
+ $$= MYSQL_START_TRANS_OPT_READ_ONLY;
+ }
+ | READ_SYM WRITE_SYM
+ {
+ $$= MYSQL_START_TRANS_OPT_READ_WRITE;
+ }
;
slave_thread_opts:
@@ -7172,6 +7888,10 @@ slave_until:
MYSQL_YYABORT;
}
}
+ | UNTIL_SYM MASTER_GTID_POS_SYM EQ TEXT_STRING_sys
+ {
+ Lex->mi.gtid_pos_str = $4;
+ }
;
slave_until_opts:
@@ -7216,9 +7936,9 @@ repair:
repair_table_or_view
{
LEX* lex= thd->lex;
- DBUG_ASSERT(!lex->m_stmt);
- lex->m_stmt= new (thd->mem_root) Repair_table_statement(lex);
- if (lex->m_stmt == NULL)
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_repair_table();
+ if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
;
@@ -7255,16 +7975,103 @@ analyze:
/* Will be overriden during execution. */
YYPS->m_lock_type= TL_UNLOCK;
}
- table_list
+ analyze_table_list
{
LEX* lex= thd->lex;
- DBUG_ASSERT(!lex->m_stmt);
- lex->m_stmt= new (thd->mem_root) Analyze_table_statement(lex);
- if (lex->m_stmt == NULL)
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_analyze_table();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+analyze_table_list:
+ analyze_table_elem_spec
+ | analyze_table_list ',' analyze_table_elem_spec
+ ;
+
+analyze_table_elem_spec:
+ table_name opt_persistent_stat_clause
+ ;
+
+opt_persistent_stat_clause:
+ /* empty */
+ {}
+ | PERSISTENT_SYM FOR_SYM persistent_stat_spec
+ {
+ thd->lex->with_persistent_for_clause= TRUE;
+ }
+ ;
+
+persistent_stat_spec:
+ ALL
+ {}
+ | COLUMNS persistent_column_stat_spec INDEXES persistent_index_stat_spec
+ {}
+
+persistent_column_stat_spec:
+ ALL {}
+ | '('
+ {
+ LEX* lex= thd->lex;
+ lex->column_list= new List<LEX_STRING>;
+ if (lex->column_list == NULL)
+ MYSQL_YYABORT;
+ }
+ table_column_list
+ ')'
+ ;
+
+persistent_index_stat_spec:
+ ALL {}
+ | '('
+ {
+ LEX* lex= thd->lex;
+ lex->index_list= new List<LEX_STRING>;
+ if (lex->index_list == NULL)
MYSQL_YYABORT;
}
+ table_index_list
+ ')'
+ ;
+
+table_column_list:
+ /* empty */
+ {}
+ | ident
+ {
+ Lex->column_list->push_back((LEX_STRING*)
+ sql_memdup(&$1, sizeof(LEX_STRING)));
+ }
+ | table_column_list ',' ident
+ {
+ Lex->column_list->push_back((LEX_STRING*)
+ sql_memdup(&$3, sizeof(LEX_STRING)));
+ }
+ ;
+
+table_index_list:
+ /* empty */
+ {}
+ | table_index_name
+ | table_index_list ',' table_index_name
;
+table_index_name:
+ ident
+ {
+ Lex->index_list->push_back(
+ (LEX_STRING*) sql_memdup(&$1, sizeof(LEX_STRING)));
+ }
+ |
+ PRIMARY_SYM
+ {
+ LEX_STRING str= {(char*) "PRIMARY", 7};
+ Lex->index_list->push_back(
+ (LEX_STRING*) sql_memdup(&str, sizeof(LEX_STRING)));
+ }
+ ;
+
binlog_base64_event:
BINLOG_SYM TEXT_STRING_sys
{
@@ -7296,9 +8103,9 @@ check: CHECK_SYM
my_error(ER_SP_BADSTATEMENT, MYF(0), "CHECK");
MYSQL_YYABORT;
}
- DBUG_ASSERT(!lex->m_stmt);
- lex->m_stmt= new (thd->mem_root) Check_table_statement(lex);
- if (lex->m_stmt == NULL)
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table();
+ if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
;
@@ -7341,9 +8148,9 @@ optimize:
table_list
{
LEX* lex= thd->lex;
- DBUG_ASSERT(!lex->m_stmt);
- lex->m_stmt= new (thd->mem_root) Optimize_table_statement(lex);
- if (lex->m_stmt == NULL)
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_optimize_table();
+ if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
;
@@ -7490,7 +8297,7 @@ preload_keys_parts:
adm_partition:
PARTITION_SYM have_partitioning
{
- Lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
+ Lex->alter_info.flags|= Alter_info::ALTER_ADMIN_PARTITION;
}
'(' all_or_alt_part_name_list ')'
;
@@ -7771,6 +8578,12 @@ select_alias:
| TEXT_STRING_sys { $$=$1; }
;
+opt_default_time_precision:
+ /* empty */ { $$= NOT_FIXED_DEC; }
+ | '(' ')' { $$= NOT_FIXED_DEC; }
+ | '(' real_ulong_num ')' { $$= $2; };
+ ;
+
opt_time_precision:
/* empty */ { $$= 0; }
| '(' ')' { $$= 0; }
@@ -8289,7 +9102,7 @@ dyncall_create_element:
alloc_root(thd->mem_root, sizeof(DYNCALL_CREATE_DEF));
if ($$ == NULL)
MYSQL_YYABORT;
- $$->num= $1;
+ $$->key= $1;
$$->value= $3;
$$->type= (DYNAMIC_COLUMN_TYPE)$4;
$$->cs= lex->charset;
@@ -8396,7 +9209,29 @@ simple_expr:
MYSQL_YYABORT;
}
| '{' ident expr '}'
- { $$= $3; }
+ {
+ $$= NULL;
+ /*
+ If "expr" is reasonably short pure ASCII string literal,
+ try to parse known ODBC style date, time or timestamp literals,
+ e.g:
+ SELECT {d'2001-01-01'};
+ SELECT {t'10:20:30'};
+ SELECT {ts'2001-01-01 10:20:30'};
+ */
+ if ($3->type() == Item::STRING_ITEM)
+ {
+ Item_string *item= (Item_string *) $3;
+ enum_field_types type= item->odbc_temporal_literal_type(&$2);
+ if (type != MYSQL_TYPE_STRING)
+ {
+ $$= create_temporal_literal(thd, item->val_str(NULL),
+ type, false);
+ }
+ }
+ if ($$ == NULL)
+ $$= $3;
+ }
| MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
{
$2->push_front($5);
@@ -8497,6 +9332,14 @@ function_call_keyword:
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
Lex->safe_to_cache_query= 0;
}
+ | CURRENT_ROLE optional_braces
+ {
+ $$= new (thd->mem_root) Item_func_current_role(Lex->current_context());
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
+ Lex->safe_to_cache_query= 0;
+ }
| DATE_SYM '(' expr ')'
{
$$= new (thd->mem_root) Item_date_typecast($3);
@@ -8840,16 +9683,9 @@ function_call_nonkeyword:
MYSQL_YYABORT;
}
|
- COLUMN_EXISTS_SYM '(' expr ',' expr ')'
- {
- $$= new (thd->mem_root) Item_func_dyncol_exists($3, $5);
- if ($$ == NULL)
- MYSQL_YYABORT;
- }
- |
- COLUMN_LIST_SYM '(' expr ')'
+ COLUMN_CHECK_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_dyncol_list($3);
+ $$= new (thd->mem_root) Item_func_dyncol_check($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8968,6 +9804,20 @@ function_call_conflict:
if ($$ == NULL)
MYSQL_YYABORT;
}
+ | REVERSE_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_reverse($3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | ROW_COUNT_SYM '(' ')'
+ {
+ $$= new (thd->mem_root) Item_func_row_count();
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
+ Lex->safe_to_cache_query= 0;
+ }
| TRUNCATE_SYM '(' expr ',' expr ')'
{
$$= new (thd->mem_root) Item_func_round($3,$5,1);
@@ -8991,6 +9841,36 @@ function_call_conflict:
if ($$ == NULL)
MYSQL_YYABORT;
}
+ | WEIGHT_STRING_SYM '(' expr opt_ws_levels ')'
+ {
+ $$= new (thd->mem_root) Item_func_weight_string($3, 0, 0, $4);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | WEIGHT_STRING_SYM '(' expr AS CHAR_SYM ws_nweights opt_ws_levels ')'
+ {
+ $$= new (thd->mem_root)
+ Item_func_weight_string($3, 0, $6,
+ $7 | MY_STRXFRM_PAD_WITH_SPACE);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | WEIGHT_STRING_SYM '(' expr AS BINARY ws_nweights ')'
+ {
+ Item *item= new (thd->mem_root) Item_char_typecast($3, $6, &my_charset_bin);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ $$= new (thd->mem_root)
+ Item_func_weight_string(item, 0, $6, MY_STRXFRM_PAD_WITH_SPACE);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | WEIGHT_STRING_SYM '(' expr ',' ulong_num ',' ulong_num ',' ulong_num ')'
+ {
+ $$= new (thd->mem_root) Item_func_weight_string($3, $5, $7, $9);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
| geometry_function
{
#ifdef HAVE_SPATIAL
@@ -9653,9 +10533,7 @@ join_table:
left-associative joins.
*/
table_ref normal_join table_ref %prec TABLE_REF_PRIORITY
- { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); }
- | table_ref STRAIGHT_JOIN table_factor
- { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=1; }
+ { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=$2; }
| table_ref normal_join table_ref
ON
{
@@ -9667,22 +10545,7 @@ join_table:
}
expr
{
- add_join_on($3,$6);
- Lex->pop_context();
- Select->parsing_place= NO_MATTER;
- }
- | table_ref STRAIGHT_JOIN table_factor
- ON
- {
- MYSQL_YYABORT_UNLESS($1 && $3);
- /* Change the current name resolution context to a local context. */
- if (push_new_name_resolution_context(thd, $1, $3))
- MYSQL_YYABORT;
- Select->parsing_place= IN_ON;
- }
- expr
- {
- $3->straight=1;
+ $3->straight=$2;
add_join_on($3,$6);
Lex->pop_context();
Select->parsing_place= NO_MATTER;
@@ -9693,10 +10556,15 @@ join_table:
MYSQL_YYABORT_UNLESS($1 && $3);
}
'(' using_list ')'
- { add_join_natural($1,$3,$7,Select); $$=$3; }
- | table_ref NATURAL JOIN_SYM table_factor
+ {
+ $3->straight=$2;
+ add_join_natural($1,$3,$7,Select);
+ $$=$3;
+ }
+ | table_ref NATURAL inner_join table_factor
{
MYSQL_YYABORT_UNLESS($1 && ($$=$4));
+ $4->straight=$3;
add_join_natural($1,$4,NULL,Select);
}
@@ -9776,12 +10644,34 @@ join_table:
}
;
+
+inner_join: /* $$ set if using STRAIGHT_JOIN, false otherwise */
+ JOIN_SYM { $$ = 0; }
+ | INNER_SYM JOIN_SYM { $$ = 0; }
+ | STRAIGHT_JOIN { $$ = 1; }
+ ;
+
normal_join:
- JOIN_SYM {}
- | INNER_SYM JOIN_SYM {}
- | CROSS JOIN_SYM {}
+ inner_join { $$ = $1; }
+ | CROSS JOIN_SYM { $$ = 0; }
;
+/*
+ table PARTITION (list of partitions), reusing using_list instead of creating
+ a new rule for partition_list.
+*/
+opt_use_partition:
+ /* empty */ { $$= 0;}
+ | use_partition
+ ;
+
+use_partition:
+ PARTITION_SYM '(' using_list ')' have_partitioning
+ {
+ $$= $3;
+ }
+ ;
+
/*
This is a flattening of the rules <table factor> and <table primary>
in the SQL:2003 standard, since we don't have <sample clause>
@@ -9795,13 +10685,14 @@ table_factor:
SELECT_LEX *sel= Select;
sel->table_join_options= 0;
}
- table_ident opt_table_alias opt_key_definition
+ table_ident opt_use_partition opt_table_alias opt_key_definition
{
- if (!($$= Select->add_table_to_list(thd, $2, $3,
+ if (!($$= Select->add_table_to_list(thd, $2, $4,
Select->get_table_join_options(),
YYPS->m_lock_type,
YYPS->m_mdl_type,
- Select->pop_index_hints())))
+ Select->pop_index_hints(),
+ $3)))
MYSQL_YYABORT;
Select->add_joined_table($$);
}
@@ -9871,7 +10762,7 @@ table_factor:
if (ti == NULL)
MYSQL_YYABORT;
if (!($$= sel->add_table_to_list(lex->thd,
- new Table_ident(unit), $5, 0,
+ ti, $5, 0,
TL_READ, MDL_SHARED_READ)))
MYSQL_YYABORT;
@@ -10263,8 +11154,8 @@ opt_escape:
{
Lex->escape_used= FALSE;
$$= ((thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) ?
- new (thd->mem_root) Item_string("", 0, &my_charset_latin1) :
- new (thd->mem_root) Item_string("\\", 1, &my_charset_latin1));
+ new (thd->mem_root) Item_string_ascii("", 0) :
+ new (thd->mem_root) Item_string_ascii("\\", 1));
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -10427,7 +11318,10 @@ opt_limit_clause:
limit_clause:
LIMIT limit_options
{
- Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
+ SELECT_LEX *sel= Select;
+ if (!sel->select_limit->basic_const_item() ||
+ sel->select_limit->val_int() > 0)
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
}
| LIMIT limit_options ROWS_SYM EXAMINED_SYM limit_rows_option
{
@@ -10469,9 +11363,9 @@ limit_option:
Item_splocal *splocal;
LEX *lex= thd->lex;
Lex_input_stream *lip= & thd->m_parser_state->m_lip;
- sp_variable_t *spv;
+ sp_variable *spv;
sp_pcontext *spc = lex->spcont;
- if (spc && (spv = spc->find_variable(&$1)))
+ if (spc && (spv = spc->find_variable($1, false)))
{
splocal= new (thd->mem_root)
Item_splocal($1, spv->offset, spv->type,
@@ -10701,9 +11595,9 @@ select_var_ident:
| ident_or_text
{
LEX *lex=Lex;
- sp_variable_t *t;
+ sp_variable *t;
- if (!lex->spcont || !(t=lex->spcont->find_variable(&$1)))
+ if (!lex->spcont || !(t=lex->spcont->find_variable($1, false)))
{
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
MYSQL_YYABORT;
@@ -10793,41 +11687,41 @@ do:
*/
drop:
- DROP opt_temporary table_or_tables if_exists
+ DROP opt_temporary table_or_tables opt_if_exists
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_DROP_TABLE;
lex->drop_temporary= $2;
- lex->drop_if_exists= $4;
+ lex->check_exists= $4;
YYPS->m_lock_type= TL_UNLOCK;
YYPS->m_mdl_type= MDL_EXCLUSIVE;
}
table_list opt_restrict
{}
- | DROP INDEX_SYM ident ON table_ident {}
+ | DROP INDEX_SYM opt_if_exists ident ON table_ident {}
{
LEX *lex=Lex;
- Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $3.str);
+ Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $4.str, $3);
if (ad == NULL)
MYSQL_YYABORT;
lex->sql_command= SQLCOM_DROP_INDEX;
lex->alter_info.reset();
- lex->alter_info.flags= ALTER_DROP_INDEX;
+ lex->alter_info.flags= Alter_info::ALTER_DROP_INDEX;
lex->alter_info.drop_list.push_back(ad);
- if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
+ if (!lex->current_select->add_table_to_list(lex->thd, $6, NULL,
TL_OPTION_UPDATING,
TL_READ_NO_INSERT,
- MDL_SHARED_NO_WRITE))
+ MDL_SHARED_UPGRADABLE))
MYSQL_YYABORT;
}
- | DROP DATABASE if_exists ident
+ | DROP DATABASE opt_if_exists ident
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_DROP_DB;
- lex->drop_if_exists=$3;
+ lex->check_exists=$3;
lex->name= $4;
}
- | DROP FUNCTION_SYM if_exists ident '.' ident
+ | DROP FUNCTION_SYM opt_if_exists ident '.' ident
{
LEX *lex= thd->lex;
sp_name *spname;
@@ -10842,14 +11736,14 @@ drop:
MYSQL_YYABORT;
}
lex->sql_command = SQLCOM_DROP_FUNCTION;
- lex->drop_if_exists= $3;
+ lex->check_exists= $3;
spname= new sp_name($4, $6, true);
if (spname == NULL)
MYSQL_YYABORT;
spname->init_qname(thd);
lex->spname= spname;
}
- | DROP FUNCTION_SYM if_exists ident
+ | DROP FUNCTION_SYM opt_if_exists ident
{
LEX *lex= thd->lex;
LEX_STRING db= {0, 0};
@@ -10862,14 +11756,14 @@ drop:
if (thd->db && lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
lex->sql_command = SQLCOM_DROP_FUNCTION;
- lex->drop_if_exists= $3;
+ lex->check_exists= $3;
spname= new sp_name(db, $4, false);
if (spname == NULL)
MYSQL_YYABORT;
spname->init_qname(thd);
lex->spname= spname;
}
- | DROP PROCEDURE_SYM if_exists sp_name
+ | DROP PROCEDURE_SYM opt_if_exists sp_name
{
LEX *lex=Lex;
if (lex->sphead)
@@ -10878,34 +11772,38 @@ drop:
MYSQL_YYABORT;
}
lex->sql_command = SQLCOM_DROP_PROCEDURE;
- lex->drop_if_exists= $3;
+ lex->check_exists= $3;
lex->spname= $4;
}
| DROP USER clear_privileges user_list
{
Lex->sql_command = SQLCOM_DROP_USER;
}
- | DROP VIEW_SYM if_exists
+ | DROP ROLE_SYM clear_privileges role_list
+ {
+ Lex->sql_command = SQLCOM_DROP_ROLE;
+ }
+ | DROP VIEW_SYM opt_if_exists
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_DROP_VIEW;
- lex->drop_if_exists= $3;
+ lex->check_exists= $3;
YYPS->m_lock_type= TL_UNLOCK;
YYPS->m_mdl_type= MDL_EXCLUSIVE;
}
table_list opt_restrict
{}
- | DROP EVENT_SYM if_exists sp_name
+ | DROP EVENT_SYM opt_if_exists sp_name
{
- Lex->drop_if_exists= $3;
+ Lex->check_exists= $3;
Lex->spname= $4;
Lex->sql_command = SQLCOM_DROP_EVENT;
}
- | DROP TRIGGER_SYM if_exists sp_name
+ | DROP TRIGGER_SYM opt_if_exists sp_name
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_DROP_TRIGGER;
- lex->drop_if_exists= $3;
+ lex->check_exists= $3;
lex->spname= $4;
}
| DROP TABLESPACE tablespace_name opt_ts_engine opt_ts_wait
@@ -10918,10 +11816,10 @@ drop:
LEX *lex= Lex;
lex->alter_tablespace_info->ts_cmd_type= DROP_LOGFILE_GROUP;
}
- | DROP SERVER_SYM if_exists ident_or_text
+ | DROP SERVER_SYM opt_if_exists ident_or_text
{
Lex->sql_command = SQLCOM_DROP_SERVER;
- Lex->drop_if_exists= $3;
+ Lex->check_exists= $3;
Lex->server_options.server_name= $4.str;
Lex->server_options.server_name_length= $4.length;
}
@@ -10943,6 +11841,19 @@ table_name:
}
;
+table_name_with_opt_use_partition:
+ table_ident opt_use_partition
+ {
+ if (!Select->add_table_to_list(thd, $1, NULL,
+ TL_OPTION_UPDATING,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type,
+ NULL,
+ $2))
+ MYSQL_YYABORT;
+ }
+ ;
+
table_alias_ref_list:
table_alias_ref
| table_alias_ref_list ',' table_alias_ref
@@ -10959,9 +11870,17 @@ table_alias_ref:
}
;
-if_exists:
- /* empty */ { $$= 0; }
- | IF EXISTS { $$= 1; }
+opt_if_exists:
+ /* empty */
+ {
+ Lex->check_exists= FALSE;
+ $$= 0;
+ }
+ | IF EXISTS
+ {
+ Lex->check_exists= TRUE;
+ $$= 1;
+ }
;
opt_temporary:
@@ -11047,7 +11966,7 @@ insert2:
;
insert_table:
- table_name
+ table_name_with_opt_use_partition
{
LEX *lex=Lex;
lex->field_list.empty();
@@ -11247,17 +12166,20 @@ delete:
;
single_multi:
- FROM table_ident
+ FROM table_ident opt_use_partition
{
if (!Select->add_table_to_list(thd, $2, NULL, TL_OPTION_UPDATING,
YYPS->m_lock_type,
- YYPS->m_mdl_type))
+ YYPS->m_mdl_type,
+ NULL,
+ $3))
MYSQL_YYABORT;
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
}
where_clause opt_order_clause
delete_limit_clause {}
+ opt_select_expressions {}
| table_wild_list
{
mysql_init_multi_delete(Lex);
@@ -11282,6 +12204,11 @@ single_multi:
}
;
+opt_select_expressions:
+ /* empty */
+ | RETURNING_SYM select_item_list
+ ;
+
table_wild_list:
table_wild_one
| table_wild_list ',' table_wild_one
@@ -11347,9 +12274,9 @@ truncate:
table_name
{
LEX* lex= thd->lex;
- DBUG_ASSERT(!lex->m_stmt);
- lex->m_stmt= new (thd->mem_root) Truncate_statement(lex);
- if (lex->m_stmt == NULL)
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_truncate_table();
+ if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
;
@@ -11424,6 +12351,7 @@ show:
{
LEX *lex=Lex;
lex->wild=0;
+ lex->ident=null_lex_str;
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
@@ -11489,6 +12417,19 @@ show_param:
if (prepare_schema_table(thd, lex, 0, SCH_PLUGINS))
MYSQL_YYABORT;
}
+ | PLUGINS_SYM SONAME_SYM TEXT_STRING_sys
+ {
+ Lex->ident= $3;
+ Lex->sql_command= SQLCOM_SHOW_PLUGINS;
+ if (prepare_schema_table(thd, Lex, 0, SCH_ALL_PLUGINS))
+ MYSQL_YYABORT;
+ }
+ | PLUGINS_SYM SONAME_SYM wild_and_where
+ {
+ Lex->sql_command= SQLCOM_SHOW_PLUGINS;
+ if (prepare_schema_table(thd, Lex, 0, SCH_ALL_PLUGINS))
+ MYSQL_YYABORT;
+ }
| ENGINE_SYM known_storage_engines show_engine_param
{ Lex->create_info.db_type= $2; }
| ENGINE_SYM ALL show_engine_param
@@ -11515,7 +12456,7 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
} opt_limit_clause_init
- | RELAYLOG_SYM EVENTS_SYM binlog_in binlog_from
+ | RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in binlog_from
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_RELAYLOG_EVENTS;
@@ -11540,19 +12481,11 @@ show_param:
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_AUTHORS;
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT,
- ER(ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT),
- "SHOW AUTHORS");
}
| CONTRIBUTORS_SYM
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_CONTRIBUTORS;
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT,
- ER(ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT),
- "SHOW CONTRIBUTORS");
}
| PRIVILEGES
{
@@ -11610,20 +12543,16 @@ show_param:
}
| GRANTS
{
- LEX *lex=Lex;
- lex->sql_command= SQLCOM_SHOW_GRANTS;
- LEX_USER *curr_user;
- if (!(curr_user= (LEX_USER*) lex->thd->alloc(sizeof(st_lex_user))))
+ Lex->sql_command= SQLCOM_SHOW_GRANTS;
+ if (!(Lex->grant_user= (LEX_USER*)thd->alloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
- bzero(curr_user, sizeof(st_lex_user));
- lex->grant_user= curr_user;
+ Lex->grant_user->user= current_user_and_current_role;
}
- | GRANTS FOR_SYM user
+ | GRANTS FOR_SYM user_or_role
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_GRANTS;
lex->grant_user=$3;
- lex->grant_user->password=null_lex_str;
}
| CREATE DATABASE opt_if_not_exists ident
{
@@ -11651,9 +12580,22 @@ show_param:
{
Lex->sql_command = SQLCOM_SHOW_MASTER_STAT;
}
+ | ALL SLAVES STATUS_SYM
+ {
+ Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
+ Lex->verbose= 1;
+ }
| SLAVE STATUS_SYM
{
+ LEX *lex= thd->lex;
+ lex->mi.connection_name= thd->variables.default_master_connection;
+ lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
+ lex->verbose= 0;
+ }
+ | SLAVE connection_name STATUS_SYM
+ {
Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
+ Lex->verbose= 0;
}
| CLIENT_STATS_SYM
{
@@ -11732,6 +12674,13 @@ show_param:
Lex->spname= $3;
Lex->sql_command = SQLCOM_SHOW_CREATE_EVENT;
}
+ | describe_command FOR_SYM expr
+ {
+ Lex->sql_command= SQLCOM_SHOW_EXPLAIN;
+ if (prepare_schema_table(thd, Lex, 0, SCH_EXPLAIN))
+ MYSQL_YYABORT;
+ add_value_to_list(thd, $3);
+ }
;
show_engine_param:
@@ -11814,13 +12763,21 @@ describe:
}
| describe_command opt_extended_describe
{ Lex->describe|= DESCRIBE_NORMAL; }
- select
+ explainable_command
{
LEX *lex=Lex;
lex->select_lex.options|= SELECT_DESCRIBE;
}
;
+explainable_command:
+ select
+ | insert
+ | replace
+ | update
+ | delete
+ ;
+
describe_command:
DESC
| DESCRIBE
@@ -11871,24 +12828,36 @@ flush_options:
YYPS->m_lock_type= TL_READ_NO_INSERT;
YYPS->m_mdl_type= MDL_SHARED_HIGH_PRIO;
}
- opt_table_list {}
- opt_with_read_lock {}
+ opt_table_list opt_flush_lock
| flush_options_list
;
-opt_with_read_lock:
+opt_flush_lock:
/* empty */ {}
- | WITH READ_SYM LOCK_SYM optional_flush_tables_arguments
+ | flush_lock
+ {
+ TABLE_LIST *tables= Lex->query_tables;
+ for (; tables; tables= tables->next_global)
{
- TABLE_LIST *tables= Lex->query_tables;
- Lex->type|= REFRESH_READ_LOCK | $4;
- for (; tables; tables= tables->next_global)
- {
- tables->mdl_request.set_type(MDL_SHARED_NO_WRITE);
- tables->required_type= FRMTYPE_TABLE; /* Don't try to flush views. */
- tables->open_type= OT_BASE_ONLY; /* Ignore temporary tables. */
- }
+ tables->mdl_request.set_type(MDL_SHARED_NO_WRITE);
+ tables->required_type= FRMTYPE_TABLE; /* Don't try to flush views. */
+ tables->open_type= OT_BASE_ONLY; /* Ignore temporary tables. */
}
+ }
+ ;
+
+flush_lock:
+ WITH READ_SYM LOCK_SYM optional_flush_tables_arguments
+ { Lex->type|= REFRESH_READ_LOCK | $4; }
+ | FOR_SYM
+ {
+ if (Lex->query_tables == NULL) // Table list can't be empty
+ {
+ my_parse_error(ER(ER_NO_TABLES_USED));
+ MYSQL_YYABORT;
+ }
+ Lex->type|= REFRESH_FOR_EXPORT;
+ } EXPORT_SYM {}
;
flush_options_list:
@@ -11908,8 +12877,17 @@ flush_option:
{ Lex->type|= REFRESH_SLOW_LOG; }
| BINARY LOGS_SYM
{ Lex->type|= REFRESH_BINARY_LOG; }
- | RELAY LOGS_SYM
- { Lex->type|= REFRESH_RELAY_LOG; }
+ | RELAY LOGS_SYM optional_connection_name
+ {
+ LEX *lex= Lex;
+ if (lex->type & REFRESH_RELAY_LOG)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "FLUSH", "RELAY LOGS");
+ MYSQL_YYABORT;
+ }
+ lex->type|= REFRESH_RELAY_LOG;
+ lex->relay_log_connection_name= lex->mi.connection_name;
+ }
| QUERY_SYM CACHE_SYM
{ Lex->type|= REFRESH_QUERY_CACHE_FREE; }
| HOSTS_SYM
@@ -11917,13 +12895,23 @@ flush_option:
| PRIVILEGES
{ Lex->type|= REFRESH_GRANT; }
| LOGS_SYM
- { Lex->type|= REFRESH_LOG; }
+ {
+ Lex->type|= REFRESH_LOG;
+ Lex->relay_log_connection_name.str= (char*) "";
+ Lex->relay_log_connection_name.length= 0;
+ }
| STATUS_SYM
{ Lex->type|= REFRESH_STATUS; }
- | SLAVE
+ | SLAVE optional_connection_name
{
- Lex->type|= REFRESH_SLAVE;
- Lex->reset_slave_info.all= false;
+ LEX *lex= Lex;
+ if (lex->type & REFRESH_SLAVE)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "FLUSH","SLAVE");
+ MYSQL_YYABORT;
+ }
+ lex->type|= REFRESH_SLAVE;
+ lex->reset_slave_info.all= false;
}
| CLIENT_STATS_SYM
{ Lex->type|= REFRESH_CLIENT_STATS; }
@@ -11967,6 +12955,7 @@ reset_options:
reset_option:
SLAVE { Lex->type|= REFRESH_SLAVE; }
+ optional_connection_name
slave_reset_options { }
| MASTER_SYM { Lex->type|= REFRESH_MASTER; }
| QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE;}
@@ -12015,6 +13004,7 @@ kill:
lex->value_list.empty();
lex->users_list.empty();
lex->sql_command= SQLCOM_KILL;
+ lex->kill_type= KILL_TYPE_ID;
}
kill_type kill_option kill_expr
{
@@ -12031,13 +13021,17 @@ kill_option:
/* empty */ { $$= (int) KILL_CONNECTION; }
| CONNECTION_SYM { $$= (int) KILL_CONNECTION; }
| QUERY_SYM { $$= (int) KILL_QUERY; }
+ | QUERY_SYM ID_SYM
+ {
+ $$= (int) KILL_QUERY;
+ Lex->kill_type= KILL_TYPE_QUERY;
+ }
;
kill_expr:
expr
{
Lex->value_list.push_front($$);
- Lex->kill_type= KILL_TYPE_ID;
}
| USER user
{
@@ -12046,6 +13040,11 @@ kill_expr:
}
;
+
+shutdown:
+ SHUTDOWN { Lex->sql_command= SQLCOM_SHUTDOWN; }
+ ;
+
/* change database */
use:
@@ -12081,18 +13080,18 @@ load:
if (!(lex->exchange= new sql_exchange($7.str, 0, $2)))
MYSQL_YYABORT;
}
- opt_duplicate INTO TABLE_SYM table_ident
+ opt_duplicate INTO TABLE_SYM table_ident opt_use_partition
{
LEX *lex=Lex;
if (!Select->add_table_to_list(thd, $12, NULL, TL_OPTION_UPDATING,
- $4, MDL_SHARED_WRITE))
+ $4, MDL_SHARED_WRITE, NULL, $13))
MYSQL_YYABORT;
lex->field_list.empty();
lex->update_list.empty();
lex->value_list.empty();
}
opt_load_data_charset
- { Lex->exchange->cs= $14; }
+ { Lex->exchange->cs= $15; }
opt_xml_rows_identified_by
opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
opt_load_data_set_spec
@@ -12290,14 +13289,10 @@ text_literal:
}
| UNDERSCORE_CHARSET TEXT_STRING
{
- Item_string *str= new (thd->mem_root) Item_string($2.str,
+ $$= new (thd->mem_root) Item_string_with_introducer($2.str,
$2.length, $1);
- if (str == NULL)
+ if ($$ == NULL)
MYSQL_YYABORT;
- str->set_repertoire_from_value();
- str->set_cs_specified(TRUE);
-
- $$= str;
}
| text_literal TEXT_STRING_literal
{
@@ -12326,7 +13321,12 @@ text_string:
if ($$ == NULL)
MYSQL_YYABORT;
}
- | HEX_NUM
+ | hex_or_bin_String { $$= $1; }
+ ;
+
+
+hex_or_bin_String:
+ HEX_NUM
{
Item *tmp= new (thd->mem_root) Item_hex_hybrid($1.str, $1.length);
if (tmp == NULL)
@@ -12393,8 +13393,16 @@ signed_literal:
literal:
text_literal { $$ = $1; }
| NUM_literal { $$ = $1; }
+ | temporal_literal { $$= $1; }
| NULL_SYM
{
+ /*
+ For the digest computation, in this context only,
+ NULL is considered a literal, hence reduced to '?'
+ REDUCE:
+ TOK_GENERIC_VALUE := NULL_SYM
+ */
+ YYLIP->reduce_digest_token(TOK_GENERIC_VALUE, NULL_SYM);
$$ = new (thd->mem_root) Item_null();
if ($$ == NULL)
MYSQL_YYABORT;
@@ -12430,66 +13438,20 @@ literal:
if ($$ == NULL)
MYSQL_YYABORT;
}
- | UNDERSCORE_CHARSET hex_num_or_string
- {
- Item *tmp= new (thd->mem_root) Item_hex_string($2.str, $2.length);
- if (tmp == NULL)
- MYSQL_YYABORT;
- /*
- it is OK only emulate fix_fieds, because we need only
- value of constant
- */
- tmp->quick_fix_field();
- String *str= tmp->val_str((String*) 0);
-
- Item_string *item_str;
- item_str= new (thd->mem_root)
- Item_string(NULL, /* name will be set in select_item */
- str ? str->ptr() : "",
- str ? str->length() : 0,
- $1);
- if (!item_str ||
- !item_str->check_well_formed_result(&item_str->str_value, TRUE))
- {
- MYSQL_YYABORT;
- }
-
- item_str->set_repertoire_from_value();
- item_str->set_cs_specified(TRUE);
-
- $$= item_str;
- }
- | UNDERSCORE_CHARSET BIN_NUM
+ | UNDERSCORE_CHARSET hex_or_bin_String
{
- Item *tmp= new (thd->mem_root) Item_bin_string($2.str, $2.length);
- if (tmp == NULL)
- MYSQL_YYABORT;
+ Item_string_with_introducer *item_str;
/*
- it is OK only emulate fix_fieds, because we need only
- value of constant
+ Pass NULL as name. Name will be set in the "select_item" rule and
+ will include the introducer and the original hex/bin notation.
*/
- tmp->quick_fix_field();
- String *str= tmp->val_str((String*) 0);
-
- Item_string *item_str;
item_str= new (thd->mem_root)
- Item_string(NULL, /* name will be set in select_item */
- str ? str->ptr() : "",
- str ? str->length() : 0,
- $1);
- if (!item_str ||
- !item_str->check_well_formed_result(&item_str->str_value, TRUE))
- {
+ Item_string_with_introducer(NULL, $2->ptr(), $2->length(), $1);
+ if (!item_str || !item_str->check_well_formed_result(true))
MYSQL_YYABORT;
- }
-
- item_str->set_cs_specified(TRUE);
$$= item_str;
}
- | DATE_SYM text_literal { $$ = $2; }
- | TIME_SYM text_literal { $$ = $2; }
- | TIMESTAMP text_literal { $$ = $2; }
;
NUM_literal:
@@ -12538,6 +13500,31 @@ NUM_literal:
}
;
+
+temporal_literal:
+ DATE_SYM TEXT_STRING
+ {
+ if (!($$= create_temporal_literal(thd, $2.str, $2.length, YYCSCL,
+ MYSQL_TYPE_DATE, true)))
+ MYSQL_YYABORT;
+ }
+ | TIME_SYM TEXT_STRING
+ {
+ if (!($$= create_temporal_literal(thd, $2.str, $2.length, YYCSCL,
+ MYSQL_TYPE_TIME, true)))
+ MYSQL_YYABORT;
+ }
+ | TIMESTAMP TEXT_STRING
+ {
+ if (!($$= create_temporal_literal(thd, $2.str, $2.length, YYCSCL,
+ MYSQL_TYPE_DATETIME, true)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+
+
/**********************************************************************
** Creating different items.
**********************************************************************/
@@ -12580,9 +13567,9 @@ simple_ident:
{
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
- sp_variable_t *spv;
+ sp_variable *spv;
sp_pcontext *spc = lex->spcont;
- if (spc && (spv = spc->find_variable(&$1)))
+ if (spc && (spv = spc->find_variable($1, false)))
{
/* We're compiling a stored procedure and found a variable */
if (! lex->parsing_options.allows_variable)
@@ -12956,14 +13943,13 @@ ident_or_text:
| LEX_HOSTNAME { $$=$1;}
;
-user:
+user_maybe_role:
ident_or_text
{
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
$$->user = $1;
- $$->host.str= (char *) "%";
- $$->host.length= 1;
+ $$->host= null_lex_str; // User or Role, see get_current_user()
$$->password= null_lex_str;
$$->plugin= empty_lex_str;
$$->auth= empty_lex_str;
@@ -12987,26 +13973,44 @@ user:
system_charset_info, 0) ||
check_host_name(&$$->host))
MYSQL_YYABORT;
- /*
- Convert hostname part of username to lowercase.
- It's OK to use in-place lowercase as long as
- the character set is utf8.
- */
- my_casedn_str(system_charset_info, $$->host.str);
+ if ($$->host.str[0])
+ {
+ /*
+ Convert hostname part of username to lowercase.
+ It's OK to use in-place lowercase as long as
+ the character set is utf8.
+ */
+ my_casedn_str(system_charset_info, $$->host.str);
+ }
+ else
+ {
+ /*
+ fix historical undocumented convention that empty host is the
+ same as '%'
+ */
+ $$->host= host_not_specified;
+ }
}
| CURRENT_USER optional_braces
{
- if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ if (!($$=(LEX_USER*)thd->calloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
- /*
- empty LEX_USER means current_user and
- will be handled in the get_current_user() function
- later
- */
- bzero($$, sizeof(LEX_USER));
+ $$->user= current_user;
+ $$->plugin= empty_lex_str;
+ $$->auth= empty_lex_str;
}
;
+user_or_role: user_maybe_role | current_role;
+
+user: user_maybe_role
+ {
+ if ($1->user.str != current_user.str && $1->host.str == 0)
+ $1->host= host_not_specified;
+ $$= $1;
+ }
+ ;
+
/* Keyword that we allow for identifiers (except SP labels) */
keyword:
keyword_sp {}
@@ -13020,11 +14024,10 @@ keyword:
| CHECKPOINT_SYM {}
| CLOSE_SYM {}
| COLUMN_ADD_SYM {}
+ | COLUMN_CHECK_SYM {}
| COLUMN_CREATE_SYM {}
| COLUMN_DELETE_SYM {}
- | COLUMN_EXISTS_SYM {}
| COLUMN_GET_SYM {}
- | COLUMN_LIST_SYM {}
| COMMENT_SYM {}
| COMMIT_SYM {}
| CONTAINS_SYM {}
@@ -13034,6 +14037,7 @@ keyword:
| EXAMINED_SYM {}
| EXECUTE_SYM {}
| FLUSH_SYM {}
+ | GET_SYM {}
| HANDLER_SYM {}
| HELP_SYM {}
| HOST_SYM {}
@@ -13045,7 +14049,6 @@ keyword:
| OPTIONS_SYM {}
| OWNER_SYM {}
| PARSER_SYM {}
- | PARTITION_SYM {}
| PORT_SYM {}
| PREPARE_SYM {}
| REMOVE_SYM {}
@@ -13056,9 +14059,11 @@ keyword:
| SAVEPOINT_SYM {}
| SECURITY_SYM {}
| SERVER_SYM {}
+ | SHUTDOWN {}
| SIGNED_SYM {}
| SOCKET_SYM {}
| SLAVE {}
+ | SLAVES {}
| SONAME_SYM {}
| START_SYM {}
| STOP_SYM {}
@@ -13079,6 +14084,7 @@ keyword:
keyword_sp:
ACTION {}
| ADDDATE_SYM {}
+ | ADMIN_SYM {}
| AFTER_SYM {}
| AGAINST {}
| AGGREGATE_SYM {}
@@ -13089,6 +14095,7 @@ keyword_sp:
| AUTHORS_SYM {}
| AUTO_INC {}
| AUTOEXTEND_SIZE_SYM {}
+ | AUTO_SYM {}
| AVG_ROW_LENGTH {}
| AVG_SYM {}
| BINLOG_SYM {}
@@ -13122,8 +14129,14 @@ keyword_sp:
| CONSTRAINT_NAME_SYM {}
| CONTEXT_SYM {}
| CONTRIBUTORS_SYM {}
+ | CURRENT_POS_SYM {}
| CPU_SYM {}
| CUBE_SYM {}
+ /*
+ Although a reserved keyword in SQL:2003 (and :2008),
+ not reserved in MySQL per WL#2111 specification.
+ */
+ | CURRENT_SYM {}
| CURSOR_NAME_SYM {}
| DATA_SYM {}
| DATAFILE_SYM {}
@@ -13133,6 +14146,7 @@ keyword_sp:
| DEFINER_SYM {}
| DELAY_KEY_WRITE_SYM {}
| DES_KEY_FILE {}
+ | DIAGNOSTICS_SYM {}
| DIRECTORY_SYM {}
| DISABLE_SYM {}
| DISCARD {}
@@ -13150,7 +14164,9 @@ keyword_sp:
| EVENT_SYM {}
| EVENTS_SYM {}
| EVERY_SYM {}
+ | EXCHANGE_SYM {}
| EXPANSION_SYM {}
+ | EXPORT_SYM {}
| EXTENDED_SYM {}
| EXTENT_SIZE_SYM {}
| FAULTS_SYM {}
@@ -13172,6 +14188,7 @@ keyword_sp:
| HARD_SYM {}
| HOSTS_SYM {}
| HOUR_SYM {}
+ | ID_SYM {}
| IDENTIFIED_SYM {}
| IGNORE_SERVER_IDS_SYM {}
| INDEX_STATS_SYM {}
@@ -13199,11 +14216,13 @@ keyword_sp:
| MAX_ROWS {}
| MASTER_SYM {}
| MASTER_HEARTBEAT_PERIOD_SYM {}
+ | MASTER_GTID_POS_SYM {}
| MASTER_HOST_SYM {}
| MASTER_PORT_SYM {}
| MASTER_LOG_FILE_SYM {}
| MASTER_LOG_POS_SYM {}
| MASTER_USER_SYM {}
+ | MASTER_USE_GTID_SYM {}
| MASTER_PASSWORD_SYM {}
| MASTER_SERVER_ID_SYM {}
| MASTER_CONNECT_RETRY_SYM {}
@@ -13212,6 +14231,8 @@ keyword_sp:
| MASTER_SSL_CAPATH_SYM {}
| MASTER_SSL_CERT_SYM {}
| MASTER_SSL_CIPHER_SYM {}
+ | MASTER_SSL_CRL_SYM {}
+ | MASTER_SSL_CRLPATH_SYM {}
| MASTER_SSL_KEY_SYM {}
| MAX_CONNECTIONS_PER_HOUR {}
| MAX_QUERIES_PER_HOUR {}
@@ -13245,12 +14266,13 @@ keyword_sp:
| NO_WAIT_SYM {}
| NODEGROUP_SYM {}
| NONE_SYM {}
+ | NUMBER_SYM {}
| NVARCHAR_SYM {}
| OFFSET_SYM {}
| OLD_PASSWORD {}
- | ONE_SHOT_SYM {}
| ONE_SYM {}
| ONLINE_SYM {}
+ | ONLY_SYM {}
| PACK_KEYS_SYM {}
| PAGE_SYM {}
| PARTIAL {}
@@ -13291,10 +14313,14 @@ keyword_sp:
| REPLICATION {}
| RESOURCES {}
| RESUME_SYM {}
+ | RETURNED_SQLSTATE_SYM {}
| RETURNS_SYM {}
+ | REVERSE_SYM {}
+ | ROLE_SYM {}
| ROLLUP_SYM {}
| ROUTINE_SYM {}
| ROWS_SYM {}
+ | ROW_COUNT_SYM {}
| ROW_FORMAT_SYM {}
| ROW_SYM {}
| RTREE_SYM {}
@@ -13306,7 +14332,7 @@ keyword_sp:
| SESSION_SYM {}
| SIMPLE_SYM {}
| SHARE_SYM {}
- | SHUTDOWN {}
+ | SLAVE_POS_SYM {}
| SLOW {}
| SNAPSHOT_SYM {}
| SOFT_SYM {}
@@ -13365,6 +14391,7 @@ keyword_sp:
| WARNINGS {}
| WAIT_SYM {}
| WEEK_SYM {}
+ | WEIGHT_STRING_SYM {}
| WORK_SYM {}
| X509_SYM {}
| XML_SYM {}
@@ -13372,125 +14399,112 @@ keyword_sp:
| VIA_SYM {}
;
-/* Option functions */
+/*
+ SQLCOM_SET_OPTION statement.
+
+ Note that to avoid shift/reduce conflicts, we have separate rules for the
+ first option listed in the statement.
+*/
set:
- SET opt_option
+ SET
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SET_OPTION;
mysql_init_select(lex);
lex->option_type=OPT_SESSION;
lex->var_list.empty();
- lex->one_shot_set= 0;
lex->autocommit= 0;
+ sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
- option_value_list
+ start_option_value_list
{}
;
-opt_option:
- /* empty */ {}
- | OPTION {}
- ;
-option_value_list:
- option_type_value
- | option_value_list ',' option_type_value
- ;
-
-option_type_value:
+// Start of option value list
+start_option_value_list:
+ option_value_no_option_type
{
- LEX *lex= thd->lex;
- Lex_input_stream *lip= YYLIP;
-
- if (lex->sphead)
- {
- /*
- If we are in SP we want have own LEX for each assignment.
- This is mostly because it is hard for several sp_instr_set
- and sp_instr_set_trigger instructions share one LEX.
- (Well, it is theoretically possible but adds some extra
- overhead on preparation for execution stage and IMO less
- robust).
-
- QQ: May be we should simply prohibit group assignments in SP?
- */
- lex->sphead->reset_lex(thd);
- lex= thd->lex;
-
- /* Set new LEX as if we at start of set rule. */
- lex->sql_command= SQLCOM_SET_OPTION;
- mysql_init_select(lex);
- lex->option_type=OPT_SESSION;
- lex->var_list.empty();
- lex->one_shot_set= 0;
- lex->autocommit= 0;
- lex->sphead->m_tmp_query= lip->get_tok_start();
- }
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
}
- ext_option_value
+ option_value_list_continued
+ | TRANSACTION_SYM
{
- LEX *lex= thd->lex;
- Lex_input_stream *lip= YYLIP;
-
- if (lex->sphead)
- {
- sp_head *sp= lex->sphead;
+ Lex->option_type= OPT_DEFAULT;
+ }
+ transaction_characteristics
+ {
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ | option_type
+ {
+ Lex->option_type= $1;
+ }
+ start_option_value_list_following_option_type
+ ;
- if (!lex->var_list.is_empty())
- {
- /*
- We have assignment to user or system variable or
- option setting, so we should construct sp_instr_stmt
- for it.
- */
- LEX_STRING qbuff;
- sp_instr_stmt *i;
- if (!(i= new sp_instr_stmt(sp->instructions(), lex->spcont,
- lex)))
- MYSQL_YYABORT;
+// Start of option value list, option_type was given
+start_option_value_list_following_option_type:
+ option_value_following_option_type
+ {
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ option_value_list_continued
+ | TRANSACTION_SYM transaction_characteristics
+ {
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ ;
- /*
- Extract the query statement from the tokenizer. The
- end is either lip->ptr, if there was no lookahead,
- lip->tok_end otherwise.
- */
- if (yychar == YYEMPTY)
- qbuff.length= lip->get_ptr() - sp->m_tmp_query;
- else
- qbuff.length= lip->get_tok_end() - sp->m_tmp_query;
+// Remainder of the option value list after first option value.
+option_value_list_continued:
+ /* empty */
+ | ',' option_value_list
+ ;
- if (!(qbuff.str= (char*) alloc_root(thd->mem_root,
- qbuff.length + 5)))
- MYSQL_YYABORT;
+// Repeating list of option values after first option value.
+option_value_list:
+ {
+ sp_create_assignment_lex(thd, yychar == YYEMPTY);
+ }
+ option_value
+ {
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ | option_value_list ','
+ {
+ sp_create_assignment_lex(thd, yychar == YYEMPTY);
+ }
+ option_value
+ {
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ ;
- strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query,
- qbuff.length);
- qbuff.length+= 4;
- i->m_query= qbuff;
- if (sp->add_instr(i))
- MYSQL_YYABORT;
- }
- if (lex->sphead->restore_lex(thd))
- MYSQL_YYABORT;
- }
+// Wrapper around option values following the first option value in the stmt.
+option_value:
+ option_type
+ {
+ Lex->option_type= $1;
}
+ option_value_following_option_type
+ | option_value_no_option_type
;
option_type:
- option_type2 {}
- | GLOBAL_SYM { $$=OPT_GLOBAL; }
+ GLOBAL_SYM { $$=OPT_GLOBAL; }
| LOCAL_SYM { $$=OPT_SESSION; }
| SESSION_SYM { $$=OPT_SESSION; }
;
-option_type2:
- /* empty */ { $$= OPT_DEFAULT; }
- | ONE_SHOT_SYM { Lex->one_shot_set= 1; $$= OPT_SESSION; }
- ;
-
opt_var_type:
/* empty */ { $$=OPT_SESSION; }
| GLOBAL_SYM { $$=OPT_GLOBAL; }
@@ -13505,72 +14519,59 @@ opt_var_ident_type:
| SESSION_SYM '.' { $$=OPT_SESSION; }
;
-ext_option_value:
- sys_option_value
- | option_type2 option_value
+// Option values with preceding option_type.
+option_value_following_option_type:
+ internal_variable_name equal set_expr_or_default
+ {
+ LEX *lex= Lex;
+
+ if ($1.var && $1.var != trg_new_row_fake_var)
+ {
+ /* It is a system variable. */
+ if (set_system_variable(thd, &$1, lex->option_type, $3))
+ MYSQL_YYABORT;
+ }
+ else
+ {
+ /*
+ Not in trigger assigning value to new row,
+ and option_type preceding local variable is illegal.
+ */
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ MYSQL_YYABORT;
+ }
+ }
;
-sys_option_value:
- option_type internal_variable_name equal set_expr_or_default
+// Option values without preceding option_type.
+option_value_no_option_type:
+ internal_variable_name equal set_expr_or_default
{
LEX *lex= Lex;
- LEX_STRING *name= &$2.base_name;
- if ($2.var == trg_new_row_fake_var)
+ if ($1.var == trg_new_row_fake_var)
{
/* We are in trigger and assigning value to field of new row */
- if ($1)
- {
- my_parse_error(ER(ER_SYNTAX_ERROR));
- MYSQL_YYABORT;
- }
- if (set_trigger_new_row(thd, name, $4))
+ if (set_trigger_new_row(thd, &$1.base_name, $3))
MYSQL_YYABORT;
}
- else if ($2.var)
+ else if ($1.var)
{
- if ($1)
- lex->option_type= $1;
-
/* It is a system variable. */
- if (set_system_variable(thd, &$2, lex->option_type, $4))
+ if (set_system_variable(thd, &$1, lex->option_type, $3))
MYSQL_YYABORT;
}
else
{
sp_pcontext *spc= lex->spcont;
- sp_variable_t *spv= spc->find_variable(name);
-
- if ($1)
- {
- my_parse_error(ER(ER_SYNTAX_ERROR));
- MYSQL_YYABORT;
- }
+ sp_variable *spv= spc->find_variable($1.base_name, false);
/* It is a local variable. */
- if (set_local_variable(thd, spv, $4))
+ if (set_local_variable(thd, spv, $3))
MYSQL_YYABORT;
}
}
- | option_type TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types
- {
- LEX *lex=Lex;
- lex->option_type= $1;
- Item *item= new (thd->mem_root) Item_int((int32) $5);
- if (item == NULL)
- MYSQL_YYABORT;
- set_var *var= new set_var(lex->option_type,
- find_sys_var(thd, "tx_isolation"),
- &null_lex_str,
- item);
- if (var == NULL)
- MYSQL_YYABORT;
- lex->var_list.push_back(var);
- }
- ;
-
-option_value:
- '@' ident_or_text equal expr
+ | '@' ident_or_text equal expr
{
Item_func_set_user_var *item;
item= new (thd->mem_root) Item_func_set_user_var($2, $4);
@@ -13614,7 +14615,7 @@ option_value:
names.str= (char *)"names";
names.length= 5;
- if (spc && spc->find_variable(&names))
+ if (spc && spc->find_variable(names, false))
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str);
else
my_parse_error(ER(ER_SYNTAX_ERROR));
@@ -13640,6 +14641,12 @@ option_value:
MYSQL_YYABORT;
lex->var_list.push_back(var);
}
+ | ROLE_SYM ident_or_text
+ {
+ LEX *lex = Lex;
+ set_var_role *var= new set_var_role($2);
+ lex->var_list.push_back(var);
+ }
| PASSWORD equal text_or_password
{
LEX *lex= thd->lex;
@@ -13649,15 +14656,14 @@ option_value:
pw.str= (char *)"password";
pw.length= 8;
- if (spc && spc->find_variable(&pw))
+ if (spc && spc->find_variable(pw, false))
{
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
MYSQL_YYABORT;
}
- if (!(user=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
+ if (!(user=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
- user->host=null_lex_str;
- user->user.str=thd->security_ctx->user;
+ user->user= current_user;
set_var_password *var= new set_var_password(user, $3);
if (var == NULL)
MYSQL_YYABORT;
@@ -13682,10 +14688,10 @@ internal_variable_name:
ident
{
sp_pcontext *spc= thd->lex->spcont;
- sp_variable_t *spv;
+ sp_variable *spv;
/* Best effort lookup for system variable. */
- if (!spc || !(spv = spc->find_variable(&$1)))
+ if (!spc || !(spv = spc->find_variable($1, false)))
{
struct sys_var_with_base tmp= {NULL, $1};
@@ -13761,6 +14767,52 @@ internal_variable_name:
}
;
+transaction_characteristics:
+ transaction_access_mode
+ | isolation_level
+ | transaction_access_mode ',' isolation_level
+ | isolation_level ',' transaction_access_mode
+ ;
+
+transaction_access_mode:
+ transaction_access_mode_types
+ {
+ LEX *lex=Lex;
+ Item *item= new (thd->mem_root) Item_int((int32) $1);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ set_var *var= new set_var(lex->option_type,
+ find_sys_var(thd, "tx_read_only"),
+ &null_lex_str,
+ item);
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var);
+ }
+ ;
+
+isolation_level:
+ ISOLATION LEVEL_SYM isolation_types
+ {
+ LEX *lex=Lex;
+ Item *item= new (thd->mem_root) Item_int((int32) $3);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ set_var *var= new set_var(lex->option_type,
+ find_sys_var(thd, "tx_isolation"),
+ &null_lex_str,
+ item);
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var);
+ }
+ ;
+
+transaction_access_mode_types:
+ READ_SYM ONLY_SYM { $$= true; }
+ | READ_SYM WRITE_SYM { $$= false; }
+ ;
+
isolation_types:
READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
| READ_SYM COMMITTED_SYM { $$= ISO_READ_COMMITTED; }
@@ -13781,33 +14833,32 @@ text_or_password:
}
| OLD_PASSWORD '(' TEXT_STRING ')'
{
- $$= $3.length ? Item_func_old_password::alloc(thd, $3.str,
- $3.length) :
+ $$= $3.length ? Item_func_old_password::
+ alloc(thd, $3.str, $3.length) :
$3.str;
if ($$ == NULL)
MYSQL_YYABORT;
}
;
-
set_expr_or_default:
expr { $$=$1; }
| DEFAULT { $$=0; }
| ON
{
- $$=new (thd->mem_root) Item_string("ON", 2, system_charset_info);
+ $$=new (thd->mem_root) Item_string_sys("ON", 2);
if ($$ == NULL)
MYSQL_YYABORT;
}
| ALL
{
- $$=new (thd->mem_root) Item_string("ALL", 3, system_charset_info);
+ $$=new (thd->mem_root) Item_string_sys("ALL", 3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| BINARY
{
- $$=new (thd->mem_root) Item_string("binary", 6, system_charset_info);
+ $$=new (thd->mem_root) Item_string_sys("binary", 6);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -13989,13 +15040,13 @@ revoke:
;
revoke_command:
- grant_privileges ON opt_table grant_ident FROM user_list
+ grant_privileges ON opt_table grant_ident FROM user_and_role_list
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_REVOKE;
lex->type= 0;
}
- | grant_privileges ON FUNCTION_SYM grant_ident FROM user_list
+ | grant_privileges ON FUNCTION_SYM grant_ident FROM user_and_role_list
{
LEX *lex= Lex;
if (lex->columns.elements)
@@ -14006,7 +15057,7 @@ revoke_command:
lex->sql_command= SQLCOM_REVOKE;
lex->type= TYPE_ENUM_FUNCTION;
}
- | grant_privileges ON PROCEDURE_SYM grant_ident FROM user_list
+ | grant_privileges ON PROCEDURE_SYM grant_ident FROM user_and_role_list
{
LEX *lex= Lex;
if (lex->columns.elements)
@@ -14017,7 +15068,7 @@ revoke_command:
lex->sql_command= SQLCOM_REVOKE;
lex->type= TYPE_ENUM_PROCEDURE;
}
- | ALL opt_privileges ',' GRANT OPTION FROM user_list
+ | ALL opt_privileges ',' GRANT OPTION FROM user_and_role_list
{
Lex->sql_command = SQLCOM_REVOKE_ALL;
}
@@ -14027,9 +15078,22 @@ revoke_command:
lex->users_list.push_front ($3);
lex->sql_command= SQLCOM_REVOKE;
lex->type= TYPE_ENUM_PROXY;
- }
+ }
+ | admin_option_for_role FROM user_and_role_list
+ {
+ Lex->sql_command= SQLCOM_REVOKE_ROLE;
+ if (Lex->users_list.push_front($1))
+ MYSQL_YYABORT;
+ }
;
+admin_option_for_role:
+ ADMIN_SYM OPTION FOR_SYM grant_role
+ { Lex->with_admin_option= true; $$= $4; }
+ | grant_role
+ { Lex->with_admin_option= false; $$= $1; }
+ ;
+
grant:
GRANT clear_privileges grant_command
{}
@@ -14073,7 +15137,74 @@ grant_command:
lex->users_list.push_front ($3);
lex->sql_command= SQLCOM_GRANT;
lex->type= TYPE_ENUM_PROXY;
- }
+ }
+ | grant_role TO_SYM grant_list opt_with_admin_option
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_GRANT_ROLE;
+ /* The first role is the one that is granted */
+ if (Lex->users_list.push_front($1))
+ MYSQL_YYABORT;
+ }
+
+ ;
+
+opt_with_admin:
+ /* nothing */ { Lex->definer = 0; }
+ | WITH ADMIN_SYM user_or_role { Lex->definer = $3; }
+
+opt_with_admin_option:
+ /* nothing */ { Lex->with_admin_option= false; }
+ | WITH ADMIN_SYM OPTION { Lex->with_admin_option= true; }
+
+role_list:
+ grant_role
+ {
+ if (Lex->users_list.push_back($1))
+ MYSQL_YYABORT;
+ }
+ | role_list ',' grant_role
+ {
+ if (Lex->users_list.push_back($3))
+ MYSQL_YYABORT;
+ }
+ ;
+
+current_role:
+ CURRENT_ROLE optional_braces
+ {
+ if (!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))
+ MYSQL_YYABORT;
+ $$->user= current_role;
+ $$->plugin= empty_lex_str;
+ $$->auth= empty_lex_str;
+ }
+ ;
+
+grant_role:
+ ident_or_text
+ {
+ CHARSET_INFO *cs= system_charset_info;
+ /* trim end spaces (as they'll be lost in mysql.user anyway) */
+ $1.length= cs->cset->lengthsp(cs, $1.str, $1.length);
+ if ($1.length == 0)
+ {
+ my_error(ER_INVALID_ROLE, MYF(0), "");
+ MYSQL_YYABORT;
+ }
+ if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ MYSQL_YYABORT;
+ $$->user = $1;
+ $$->host= empty_lex_str;
+ $$->password= null_lex_str;
+ $$->plugin= empty_lex_str;
+ $$->auth= empty_lex_str;
+
+ if (check_string_char_length(&$$->user, ER(ER_USERNAME),
+ username_char_length, cs, 0))
+ MYSQL_YYABORT;
+ }
+ | current_role
;
opt_table:
@@ -14263,6 +15394,19 @@ grant_list:
}
;
+user_and_role_list:
+ user_or_role
+ {
+ if (Lex->users_list.push_back($1))
+ MYSQL_YYABORT;
+ }
+ | user_and_role_list ',' user_or_role
+ {
+ if (Lex->users_list.push_back($3))
+ MYSQL_YYABORT;
+ }
+ ;
+
via_or_with: VIA_SYM | WITH ;
using_or_as: USING | AS ;
@@ -14270,9 +15414,11 @@ grant_user:
user IDENTIFIED_SYM BY TEXT_STRING
{
$$=$1; $1->password=$4;
+ if (Lex->sql_command == SQLCOM_REVOKE)
+ MYSQL_YYABORT;
if ($4.length)
{
- if (thd->variables.old_passwords)
+ if (thd->variables.old_passwords == 1)
{
char *buff=
(char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
@@ -14311,7 +15457,7 @@ grant_user:
$1->plugin= $4;
$1->auth= $6;
}
- | user
+ | user_or_role
{ $$= $1; $1->password= null_lex_str; }
;
@@ -14703,7 +15849,7 @@ view_or_trigger_or_sp_or_event:
{}
| no_definer no_definer_tail
{}
- | view_replace_or_algorithm definer_opt view_tail
+ | view_algorithm definer_opt view_tail
{}
;
@@ -14750,9 +15896,9 @@ no_definer:
;
definer:
- DEFINER_SYM EQ user
+ DEFINER_SYM EQ user_or_role
{
- thd->lex->definer= get_current_user(thd, $3);
+ thd->lex->definer= $3;
}
;
@@ -14762,20 +15908,6 @@ definer:
**************************************************************************/
-view_replace_or_algorithm:
- view_replace
- {}
- | view_replace view_algorithm
- {}
- | view_algorithm
- {}
- ;
-
-view_replace:
- OR_SYM REPLACE
- { Lex->create_view_mode= VIEW_CREATE_OR_REPLACE; }
- ;
-
view_algorithm:
ALGORITHM_SYM EQ UNDEFINED_SYM
{ Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED; }
@@ -15115,7 +16247,7 @@ sf_tail:
If a collision exists, it should not be silenced but fixed.
*/
push_warning_printf(thd,
- MYSQL_ERROR::WARN_LEVEL_NOTE,
+ Sql_condition::WARN_LEVEL_NOTE,
ER_NATIVE_FCT_NAME_COLLISION,
ER(ER_NATIVE_FCT_NAME_COLLISION),
sp->m_name.str);