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.yy6780
1 files changed, 3886 insertions, 2894 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index ba0041cf477..5111f0690ab 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, MariaDB
+ Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -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,32 +33,35 @@
#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 */
#include "sql_acl.h" /* *_ACL */
-#include "password.h" /* my_make_scrambled_password_323, my_make_scrambled_password */
#include "sql_class.h" /* Key_part_spec, enum_filetype, Diag_condition_item_name */
#include "slave.h"
#include "lex_symbol.h"
#include "item_create.h"
#include "sp_head.h"
-#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_show.h"
+#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
@@ -88,35 +92,15 @@ int yylex(void *yylval, void *yythd);
YYABORT; \
} while (0)
-#define MYSQL_YYABORT_UNLESS(A) \
- if (!(A)) \
- { \
- my_parse_error(ER(ER_SYNTAX_ERROR));\
- MYSQL_YYABORT; \
+#define MYSQL_YYABORT_UNLESS(A) \
+ if (!(A)) \
+ { \
+ my_parse_error(thd, ER_SYNTAX_ERROR); \
+ MYSQL_YYABORT; \
}
-/*
- Work around for broken code generated by bison 1.875.
-
- The code generated by bison 1.875a and later, bison 2.1 and bison 2.2 is ok.
- With bison 1.875 however, the generated code contains:
-<pre>
- yyerrlab1:
- #if defined (__GNUC_MINOR__) && 2093 <= (__GNUC__ * 1000 + __GNUC_MINOR__)
- __attribute__ ((__unused__))
- #endif
-</pre>
- This usage of __attribute__ is illegal, so we remove it.
- See the following references for details:
- http://lists.gnu.org/archive/html/bug-bison/2004-02/msg00014.html
- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14273
-*/
-
-#if defined (__GNUC_MINOR__) && 2093 <= (__GNUC__ * 1000 + __GNUC_MINOR__)
-#undef __attribute__
-#define __attribute__(X)
-#endif
-
+#define my_yyabort_error(A) \
+ do { my_error A; MYSQL_YYABORT; } while(0)
#ifndef DBUG_OFF
#define YYDEBUG 1
@@ -135,21 +119,34 @@ int yylex(void *yylval, void *yythd);
parser.
*/
-void my_parse_error(const char *s)
+static void my_parse_error_intern(THD *thd, const char *err_text,
+ const char *yytext)
{
- THD *thd= current_thd;
- Lex_input_stream *lip= & thd->m_parser_state->m_lip;
-
- const char *yytext= lip->get_tok_start();
+ Lex_input_stream *lip= &thd->m_parser_state->m_lip;
if (!yytext)
- yytext= "";
-
+ {
+ if (!(yytext= lip->get_tok_start()))
+ yytext= "";
+ }
/* Push an error into the error stack */
- ErrConvString err(yytext, strlen(yytext), thd->variables.character_set_client);
- my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s,
- err.ptr(), lip->yylineno);
+ ErrConvString err(yytext, strlen(yytext),
+ thd->variables.character_set_client);
+ my_printf_error(ER_PARSE_ERROR, ER_THD(thd, ER_PARSE_ERROR), MYF(0),
+ err_text, err.ptr(), lip->yylineno);
+}
+
+
+static void my_parse_error(THD *thd, uint err_number, const char *yytext=0)
+{
+ return my_parse_error_intern(thd, ER_THD(thd, err_number), yytext);
+}
+
+void LEX::parse_error()
+{
+ my_parse_error(thd, ER_SYNTAX_ERROR);
}
+
/**
@brief Bison callback to report a syntax/OOM error
@@ -181,8 +178,8 @@ void MYSQLerror(THD *thd, const char *s)
/* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
- s= ER(ER_SYNTAX_ERROR);
- my_parse_error(s);
+ s= ER_THD(thd, ER_SYNTAX_ERROR);
+ my_parse_error_intern(thd, s, 0);
}
@@ -220,59 +217,67 @@ static bool is_native_function(THD *thd, const LEX_STRING *name)
}
-/**
- Helper action for a case statement (entering the CASE).
- This helper is used for both 'simple' and 'searched' cases.
- This helper, with the other case_stmt_action_..., is executed when
- the following SQL code is parsed:
-<pre>
-CREATE PROCEDURE proc_19194_simple(i int)
-BEGIN
- DECLARE str CHAR(10);
-
- CASE i
- WHEN 1 THEN SET str="1";
- WHEN 2 THEN SET str="2";
- WHEN 3 THEN SET str="3";
- ELSE SET str="unknown";
- END CASE;
-
- SELECT str;
-END
-</pre>
- The actions are used to generate the following code:
-<pre>
-SHOW PROCEDURE CODE proc_19194_simple;
-Pos Instruction
-0 set str@1 NULL
-1 set_case_expr (12) 0 i@0
-2 jump_if_not 5(12) (case_expr@0 = 1)
-3 set str@1 _latin1'1'
-4 jump 12
-5 jump_if_not 8(12) (case_expr@0 = 2)
-6 set str@1 _latin1'2'
-7 jump 12
-8 jump_if_not 11(12) (case_expr@0 = 3)
-9 set str@1 _latin1'3'
-10 jump 12
-11 set str@1 _latin1'unknown'
-12 stmt 0 "SELECT str"
-</pre>
+static sp_head *make_sp_head(THD *thd, sp_name *name,
+ enum stored_procedure_type type)
+{
+ LEX *lex= thd->lex;
+ sp_head *sp;
- @param lex the parser lex context
-*/
+ /* Order is important here: new - reset - init */
+ if ((sp= new sp_head()))
+ {
+ sp->reset_thd_mem_root(thd);
+ sp->init(lex);
+ sp->m_type= type;
+ if (name)
+ sp->init_sp_name(thd, name);
+ sp->m_chistics= &lex->sp_chistics;
+ lex->sphead= sp;
+ }
+ bzero(&lex->sp_chistics, sizeof(lex->sp_chistics));
+ return sp;
+}
-void case_stmt_action_case(LEX *lex)
+static bool maybe_start_compound_statement(THD *thd)
{
- lex->sphead->new_cont_backpatch(NULL);
+ if (!thd->lex->sphead)
+ {
+ if (!make_sp_head(thd, NULL, TYPE_ENUM_PROCEDURE))
+ return 1;
- /*
- BACKPATCH: Creating target label for the jump to
- "case_stmt_action_end_case"
- (Instruction 12 in the example)
- */
+ Lex->sp_chistics.suid= SP_IS_NOT_SUID;
+ Lex->sphead->set_body_start(thd, YYLIP->get_cpp_ptr());
+ }
+ return 0;
+}
- lex->spcont->push_label((char *)"", lex->sphead->instructions());
+static bool push_sp_label(THD *thd, LEX_STRING label)
+{
+ sp_pcontext *ctx= thd->lex->spcont;
+ sp_label *lab= ctx->find_label(label);
+
+ if (lab)
+ {
+ my_error(ER_SP_LABEL_REDEFINE, MYF(0), label.str);
+ return 1;
+ }
+ else
+ {
+ lab= thd->lex->spcont->push_label(thd, label,
+ thd->lex->sphead->instructions());
+ lab->type= sp_label::ITERATION;
+ }
+ return 0;
+}
+
+static bool push_sp_empty_label(THD *thd)
+{
+ if (maybe_start_compound_statement(thd))
+ return 1;
+ /* Unlabeled controls get an empty label. */
+ thd->lex->spcont->push_label(thd, empty_lex_str,
+ thd->lex->sphead->instructions());
+ return 0;
}
/**
@@ -293,8 +298,9 @@ int case_stmt_action_expr(LEX *lex, Item* expr)
if (parsing_ctx->push_case_expr_id(case_expr_id))
return 1;
- i= new sp_instr_set_case_expr(sp->instructions(),
- parsing_ctx, case_expr_id, expr, lex);
+ i= new (lex->thd->mem_root)
+ sp_instr_set_case_expr(sp->instructions(), parsing_ctx, case_expr_id, expr,
+ lex);
sp->add_cont_backpatch(i);
return sp->add_instr(i);
@@ -316,10 +322,12 @@ int case_stmt_action_when(LEX *lex, Item *when, bool simple)
sp_instr_jump_if_not *i;
Item_case_expr *var;
Item *expr;
+ THD *thd= lex->thd;
if (simple)
{
- var= new Item_case_expr(ctx->get_current_case_expr_id());
+ var= new (thd->mem_root)
+ Item_case_expr(thd, ctx->get_current_case_expr_id());
#ifndef DBUG_OFF
if (var)
@@ -328,11 +336,11 @@ int case_stmt_action_when(LEX *lex, Item *when, bool simple)
}
#endif
- expr= new Item_func_eq(var, when);
- i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
+ expr= new (thd->mem_root) Item_func_eq(thd, var, when);
+ i= new (thd->mem_root) sp_instr_jump_if_not(ip, ctx, expr, lex);
}
else
- i= new sp_instr_jump_if_not(ip, ctx, when, lex);
+ i= new (thd->mem_root) sp_instr_jump_if_not(ip, ctx, when, lex);
/*
BACKPATCH: Registering forward jump from
@@ -340,8 +348,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(thd, empty_lex_str, 0)) ||
sp->add_cont_backpatch(i) ||
sp->add_instr(i);
}
@@ -357,8 +365,8 @@ int case_stmt_action_then(LEX *lex)
sp_head *sp= lex->sphead;
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))
+ sp_instr_jump *i= new (lex->thd->mem_root) sp_instr_jump(ip, ctx);
+ if (!MY_TEST(i) || sp->add_instr(i))
return 1;
/*
@@ -371,44 +379,19 @@ int case_stmt_action_then(LEX *lex)
/*
BACKPATCH: Registering forward jump from
- "case_stmt_action_then" to "case_stmt_action_end_case"
+ "case_stmt_action_then" to after END CASE
(jump from instruction 4 to 12, 7 to 12 ... in the example)
*/
return sp->push_backpatch(i, ctx->last_label());
}
-/**
- Helper action for an end case.
- This helper is used for both 'simple' and 'searched' cases.
- @param lex the parser lex context
- @param simple true for simple cases, false for searched cases
-*/
-
-void case_stmt_action_end_case(LEX *lex, bool simple)
-{
- /*
- BACKPATCH: Resolving forward jump from
- "case_stmt_action_then" to "case_stmt_action_end_case"
- (jump from instruction 4 to 12, 7 to 12 ... in the example)
- */
- lex->sphead->backpatch(lex->spcont->pop_label());
-
- if (simple)
- lex->spcont->pop_case_expr_id();
-
- lex->sphead->do_cont_backpatch();
-}
-
-
static bool
find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp)
{
tmp->var= find_sys_var(thd, tmp->base_name.str, tmp->base_name.length);
- if (tmp->var == NULL)
- my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), tmp->base_name.str);
- else
+ if (tmp->var != NULL)
tmp->base_name= null_lex_str;
return thd->is_error();
@@ -445,10 +428,11 @@ set_system_variable(THD *thd, struct sys_var_with_base *tmp,
return TRUE;
}
- if (! (var= new set_var(var_type, tmp->var, &tmp->base_name, val)))
+ if (! (var= new (thd->mem_root)
+ set_var(thd, var_type, tmp->var, &tmp->base_name, val)))
return TRUE;
- return lex->var_list.push_back(var);
+ return lex->var_list.push_back(var, thd->mem_root);
}
@@ -464,7 +448,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,17 +456,18 @@ 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();
+ it= new (thd->mem_root) Item_null(thd);
if (it == NULL)
return TRUE;
}
- sp_set= new sp_instr_set(lex->sphead->instructions(), lex->spcont,
- spv->offset, it, spv->type, lex, TRUE);
+ sp_set= new (thd->mem_root)
+ sp_instr_set(lex->sphead->instructions(), lex->spcont,
+ spv->offset, it, spv->type, lex, TRUE);
return (sp_set == NULL || lex->sphead->add_instr(sp_set));
}
@@ -508,22 +493,24 @@ set_trigger_new_row(THD *thd, LEX_STRING *name, Item *val)
/* QQ: Shouldn't this be field's default value ? */
if (! val)
- val= new Item_null();
+ val= new (thd->mem_root) Item_null(thd);
DBUG_ASSERT(lex->trg_chistics.action_time == TRG_ACTION_BEFORE &&
(lex->trg_chistics.event == TRG_EVENT_INSERT ||
lex->trg_chistics.event == TRG_EVENT_UPDATE));
trg_fld= new (thd->mem_root)
- Item_trigger_field(lex->current_context(),
+ Item_trigger_field(thd, lex->current_context(),
Item_trigger_field::NEW_ROW,
name->str, UPDATE_ACL, FALSE);
if (trg_fld == NULL)
return TRUE;
- sp_fld= new sp_instr_set_trigger_field(lex->sphead->instructions(),
- lex->spcont, trg_fld, val, lex);
+ sp_fld= new (thd->mem_root)
+ sp_instr_set_trigger_field(lex->sphead->instructions(),
+ lex->spcont, trg_fld, val,
+ lex);
if (sp_fld == NULL)
return TRUE;
@@ -539,6 +526,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(thd, 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
@@ -596,7 +634,7 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
Item_in_subselect(left, subselect)
*/
subselect= expr3->invalidate_and_restore_select_lex();
- result= new (thd->mem_root) Item_in_subselect(left, subselect);
+ result= new (thd->mem_root) Item_in_subselect(thd, left, subselect);
if (! equal)
result = negate_expression(thd, result);
@@ -606,9 +644,9 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
}
if (equal)
- result= new (thd->mem_root) Item_func_eq(left, expr);
+ result= new (thd->mem_root) Item_func_eq(thd, left, expr);
else
- result= new (thd->mem_root) Item_func_ne(left, expr);
+ result= new (thd->mem_root) Item_func_ne(thd, left, expr);
DBUG_RETURN(result);
}
@@ -622,11 +660,11 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
@param lex The parser state.
- @param is_union_distinct True if the union preceding the new select statement
- uses UNION DISTINCT.
+ @param is_union_distinct True if the union preceding the new select
+ statement uses UNION DISTINCT.
@param is_top_level This should be @c TRUE if the newly created SELECT_LEX
- is a non-nested statement.
+ is a non-nested statement.
@return <code>false</code> if successful, <code>true</code> if an error was
reported. In the latter case parsing should stop.
@@ -643,9 +681,20 @@ bool add_select_to_union_list(LEX *lex, bool is_union_distinct,
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
return TRUE;
}
+ if (lex->current_select->order_list.first && !lex->current_select->braces)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
+ return TRUE;
+ }
+
+ if (lex->current_select->explicit_limit && !lex->current_select->braces)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "UNION", "LIMIT");
+ return TRUE;
+ }
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(lex->thd, ER_SYNTAX_ERROR);
return TRUE;
}
/* This counter shouldn't be incremented for UNION parts */
@@ -670,17 +719,20 @@ bool add_select_to_union_list(LEX *lex, bool is_union_distinct,
bool setup_select_in_parentheses(LEX *lex)
{
SELECT_LEX * sel= lex->current_select;
+ /*
if (sel->set_braces(1))
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(lex->thd, ER_SYNTAX_ERROR);
return TRUE;
}
+ */
+ DBUG_ASSERT(sel->braces);
if (sel->linkage == UNION_TYPE &&
!sel->master_unit()->first_select()->braces &&
sel->master_unit()->first_select()->linkage ==
UNION_TYPE)
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(lex->thd, ER_SYNTAX_ERROR);
return TRUE;
}
if (sel->linkage == UNION_TYPE &&
@@ -690,110 +742,294 @@ bool setup_select_in_parentheses(LEX *lex)
my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY");
return TRUE;
}
- /* select in braces, can't contain global parameters */
- if (sel->master_unit()->fake_select_lex)
- sel->master_unit()->global_parameters=
- sel->master_unit()->fake_select_lex;
return FALSE;
}
-static bool add_create_index_prepare (LEX *lex, Table_ident *table)
+static bool add_create_index_prepare(LEX *lex, Table_ident *table)
{
lex->sql_command= SQLCOM_CREATE_INDEX;
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->col_list.empty();
- lex->change= NullS;
+ lex->alter_info.flags= Alter_info::ALTER_ADD_INDEX;
lex->option_list= NULL;
return FALSE;
}
-static bool add_create_index (LEX *lex, Key::Keytype type,
- const LEX_STRING &name,
- KEY_CREATE_INFO *info= NULL, bool generated= 0)
+
+/**
+ 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. */
+ if (no_lookahead)
+ lex->sphead->m_tmp_query= lip->get_ptr();
+ else
+ lex->sphead->m_tmp_query= lip->get_tok_end();
+ /* 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 (thd->mem_root)
+ 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;
+}
+
+
+static void add_key_to_list(LEX *lex, LEX_STRING *field_name,
+ enum Key::Keytype type, bool check_exists)
{
Key *key;
- key= new Key(type, name, info ? info : &lex->key_create_info, generated,
- lex->col_list, lex->option_list);
- if (key == NULL)
- return TRUE;
+ MEM_ROOT *mem_root= lex->thd->mem_root;
+ key= new (mem_root)
+ Key(type, null_lex_str, HA_KEY_ALG_UNDEF, false,
+ DDL_options(check_exists ?
+ DDL_options::OPT_IF_NOT_EXISTS :
+ DDL_options::OPT_NONE));
+ key->columns.push_back(new (mem_root) Key_part_spec(*field_name, 0),
+ mem_root);
+ lex->alter_info.key_list.push_back(key, mem_root);
+}
- lex->alter_info.key_list.push_back(key);
- lex->col_list.empty();
- return FALSE;
+void LEX::init_last_field(Create_field *field, const char *field_name,
+ CHARSET_INFO *cs)
+{
+ last_field= field;
+
+ field->field_name= field_name;
+
+ /* reset LEX fields that are used in Create_field::set_and_check() */
+ length= 0;
+ dec= 0;
+ charset= cs;
+}
+
+void LEX::set_last_field_type(enum enum_field_types field_type)
+{
+ last_field->sql_type= field_type;
+ last_field->create_if_not_exists= check_exists;
+ last_field->charset= charset;
+
+ if (length)
+ {
+ int err;
+ last_field->length= my_strtoll10(length, NULL, &err);
+ if (err)
+ last_field->length= ~0ULL; // safety
+ }
+ else
+ last_field->length= 0;
+
+ last_field->decimals= dec ? (uint)atoi(dec) : 0;
+}
+
+bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin)
+{
+ /*
+ if charset is NULL - we're parsing a field declaration.
+ we cannot call find_bin_collation for a field here, because actual
+ field charset is determined in get_sql_field_charset() much later.
+ so we only set a flag.
+ */
+ if (!charset)
+ {
+ charset= cs;
+ last_field->flags|= bin ? BINCMP_FLAG : 0;
+ return false;
+ }
+
+ charset= bin ? find_bin_collation(cs ? cs : charset)
+ : cs ? cs : charset;
+ return charset == NULL;
}
+#define bincmp_collation(X,Y) \
+ do \
+ { \
+ if (Lex->set_bincmp(X,Y)) \
+ MYSQL_YYABORT; \
+ } while(0)
+
%}
%union {
int num;
ulong ulong_num;
ulonglong ulonglong_number;
longlong longlong_number;
+
+ /* structs */
LEX_STRING lex_str;
- LEX_STRING *lex_str_ptr;
LEX_SYMBOL symbol;
- LEX_TYPE lex_type;
- Table_ident *table;
- char *simple_string;
+ struct sys_var_with_base variable;
+ struct { int vars, conds, hndlrs, curs; } spblock;
+
+ /* pointers */
+ CHARSET_INFO *charset;
+ Condition_information_item *cond_info_item;
+ DYNCALL_CREATE_DEF *dyncol_def;
+ Diagnostics_information *diag_info;
Item *item;
Item_num *item_num;
+ Item_param *item_param;
+ Key_part_spec *key_part;
+ LEX *lex;
+ LEX_STRING *lex_str_ptr;
+ LEX_USER *lex_user;
+ List<Condition_information_item> *cond_info_list;
+ List<DYNCALL_CREATE_DEF> *dyncol_def_list;
List<Item> *item_list;
+ List<Statement_information_item> *stmt_info_list;
List<String> *string_list;
+ Statement_information_item *stmt_info_item;
String *string;
- Key_part_spec *key_part;
TABLE_LIST *table_list;
- udf_func *udf;
- LEX_USER *lex_user;
- struct sys_var_with_base variable;
- enum enum_var_type var_type;
- Key::Keytype key_type;
- enum ha_key_alg key_alg;
+ Table_ident *table;
+ char *simple_string;
+ chooser_compare_func_creator boolfunc2creator;
+ class my_var *myvar;
+ class sp_condition_value *spcondvalue;
+ class sp_head *sphead;
+ class sp_label *splabel;
+ class sp_name *spname;
+ class sp_variable *spvar;
handlerton *db_type;
- enum row_type row_type;
- enum ha_rkey_function ha_rkey_mode;
- enum enum_tx_isolation tx_isolation;
- enum Cast_target cast_type;
- enum Item_udftype udf_type;
- enum ha_choice choice;
- CHARSET_INFO *charset;
- thr_lock_type lock_type;
- interval_type interval, interval_time_st;
- timestamp_type date_time_type;
st_select_lex *select_lex;
- chooser_compare_func_creator boolfunc2creator;
- struct sp_cond_type *spcondtype;
- struct { int vars, conds, hndlrs, curs; } spblock;
- sp_name *spname;
- LEX *lex;
- sp_head *sphead;
struct p_elem_val *p_elem_value;
- enum index_hint_type index_hint;
+ udf_func *udf;
+
+ /* enums */
+ enum Cast_target cast_type;
+ enum Condition_information_item::Name cond_info_item_name;
+ enum enum_diag_condition_item_name diag_condition_item_name;
+ enum Diagnostics_information::Which_area diag_area;
+ enum Field::geometry_type geom_type;
+ enum enum_fk_option m_fk_option;
+ enum Item_udftype udf_type;
+ enum Key::Keytype key_type;
+ enum Statement_information_item::Name stmt_info_item_name;
+ enum enum_field_types field_type;
enum enum_filetype filetype;
- enum Foreign_key::fk_option m_fk_option;
+ enum enum_tx_isolation tx_isolation;
+ enum enum_var_type var_type;
enum enum_yes_no_unknown m_yes_no_unk;
- Diag_condition_item_name diag_condition_item_name;
- DYNCALL_CREATE_DEF *dyncol_def;
- List<DYNCALL_CREATE_DEF> *dyncol_def_list;
- bool is_not_empty;
+ enum ha_choice choice;
+ enum ha_key_alg key_alg;
+ enum ha_rkey_function ha_rkey_mode;
+ enum index_hint_type index_hint;
+ enum interval_type interval, interval_time_st;
+ enum row_type row_type;
+ enum sp_variable::enum_mode spvar_mode;
+ enum thr_lock_type lock_type;
+ enum enum_mysql_timestamp_type date_time_type;
+ DDL_options_st object_ddl_options;
}
%{
bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%}
-%pure_parser /* We have threads */
+%pure-parser /* We have threads */
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
- Currently there are 175 shift/reduce conflicts.
+ Currently there are 160 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
-%expect 175
+%expect 162
/*
Comments for TOKENS.
@@ -807,15 +1043,16 @@ 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.
*/
-
+
%token ABORT_SYM /* INTERNAL (used in lex) */
%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
@@ -833,9 +1070,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ASCII_SYM /* MYSQL-FUNC */
%token ASENSITIVE_SYM /* FUTURE-USE */
%token AT_SYM /* SQL-2003-R */
+%token ATOMIC_SYM /* SQL-2003-R */
%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
@@ -876,7 +1115,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CIPHER_SYM
%token CLASS_ORIGIN_SYM /* SQL-2003-N */
%token CLIENT_SYM
-%token CLIENT_STATS_SYM
%token CLOSE_SYM /* SQL-2003-R */
%token COALESCE /* SQL-2003-N */
%token CODE_SYM
@@ -884,11 +1122,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 +1153,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 */
@@ -942,10 +1182,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token DELAYED_SYM
%token DELAY_KEY_WRITE_SYM
%token DELETE_SYM /* SQL-2003-R */
+%token DELETE_DOMAIN_ID_SYM
%token DESC /* SQL-2003-N */
%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
@@ -953,6 +1195,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token DISTINCT /* SQL-2003-R */
%token DIV_SYM
%token DOUBLE_SYM /* SQL-2003-R */
+%token DO_DOMAIN_IDS_SYM
%token DO_SYM
%token DROP /* SQL-2003-R */
%token DUAL_SYM
@@ -978,11 +1221,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 */
@@ -999,6 +1244,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token FORCE_SYM
%token FOREIGN /* SQL-2003-R */
%token FOR_SYM /* SQL-2003-R */
+%token FORMAT_SYM
%token FOUND_SYM /* SQL-2003-R */
%token FROM
%token FULL /* SQL-2003-R */
@@ -1010,6 +1256,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
@@ -1029,16 +1276,17 @@ 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
-%token IF
+%token IF_SYM
+%token IGNORE_DOMAIN_IDS_SYM
%token IGNORE_SYM
%token IGNORE_SERVER_IDS_SYM
%token IMPORT
%token INDEXES
%token INDEX_SYM
-%token INDEX_STATS_SYM
%token INFILE
%token INITIAL_SIZE_SYM
%token INNER_SYM /* SQL-2003-R */
@@ -1094,6 +1342,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token LOOP_SYM
%token LOW_PRIORITY
%token MASTER_CONNECT_RETRY_SYM
+%token MASTER_GTID_POS_SYM
%token MASTER_HOST_SYM
%token MASTER_LOG_FILE_SYM
%token MASTER_LOG_POS_SYM
@@ -1104,11 +1353,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
@@ -1117,6 +1369,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token MAX_SIZE_SYM
%token MAX_SYM /* SQL-2003-N */
%token MAX_UPDATES_PER_HOUR
+%token MAX_STATEMENT_TIME_SYM
%token MAX_USER_CONNECTIONS_SYM
%token MAX_VALUE_SYM /* SQL-2003-N */
%token MEDIUMBLOB
@@ -1150,7 +1403,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NATURAL /* SQL-2003-R */
%token NCHAR_STRING
%token NCHAR_SYM /* SQL-2003-R */
-%token NDBCLUSTER_SYM
%token NE /* OPERATOR */
%token NEG
%token NEW_SYM /* SQL-2003-R */
@@ -1165,13 +1417,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 OLD_PASSWORD_SYM
%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
@@ -1193,10 +1446,10 @@ 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 PASSWORD
+%token PARTITIONS_SYM
+%token PARTITIONING_SYM
+%token PASSWORD_SYM
%token PERSISTENT_SYM
%token PHASE_SYM
%token PLUGINS_SYM
@@ -1256,16 +1509,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
@@ -1292,6 +1550,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
@@ -1313,10 +1573,15 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token SQL_SMALL_RESULT
%token SQL_SYM /* SQL-2003-R */
%token SQL_THREAD
+%token REF_SYSTEM_ID_SYM
%token SSL_SYM
%token STARTING
%token STARTS_SYM
%token START_SYM /* SQL-2003-R */
+%token STATEMENT_SYM
+%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
@@ -1339,7 +1604,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token TABLES
%token TABLESPACE
%token TABLE_REF_PRIORITY
-%token TABLE_STATS_SYM
%token TABLE_SYM /* SQL-2003-R */
%token TABLE_CHECKSUM_SYM
%token TABLE_NAME_SYM /* SQL-2003-N */
@@ -1387,8 +1651,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token UPDATE_SYM /* SQL-2003-R */
%token UPGRADE_SYM
%token USAGE /* SQL-2003-N */
-%token USER /* SQL-2003-R */
-%token USER_STATS_SYM
+%token USER_SYM /* SQL-2003-R */
%token USE_FRM
%token USE_SYM
%token USING /* SQL-2003-R */
@@ -1409,6 +1672,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
@@ -1450,7 +1714,7 @@ 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
@@ -1462,29 +1726,47 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%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
+ remember_name remember_end opt_db remember_tok_start
+ wild_and_where
%type <string>
- text_string opt_gconcat_separator
+ text_string hex_or_bin_String opt_gconcat_separator
-%type <lex_type> field_def
+%type <field_type> type_with_opt_collate int_type real_type field_type
+
+%type <geom_type> spatial_type
%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
+ order_dir lock_option
+ udf_type opt_local 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
+ opt_ignore_leaves fulltext_options union_option
+ opt_not opt_union_order_or_limit
+ 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
+ case_stmt_body opt_bin_mod
+ opt_if_exists_table_element opt_if_not_exists_table_element
+ opt_into opt_procedure_clause
+
+%type <object_ddl_options>
+ create_or_replace
+ opt_if_not_exists
+ opt_if_exists
+
+/*
+ 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
@@ -1494,6 +1776,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
@@ -1504,13 +1790,13 @@ 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
table_wild simple_expr udf_expr
expr_or_default set_expr_or_default
- param_marker geometry_function
+ geometry_function
signed_literal now_or_signed_literal opt_escape
sp_opt_default
simple_ident_nospvar simple_ident_q
@@ -1521,6 +1807,10 @@ 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_param> param_marker
%type <item_num>
NUM_literal
@@ -1533,13 +1823,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
option_type opt_var_type opt_var_ident_type
%type <key_type>
- normal_key_type opt_unique constraint_key_type fulltext spatial
+ opt_unique constraint_key_type fulltext spatial
%type <key_alg>
- btree_or_rtree
+ btree_or_rtree opt_key_algorithm_clause opt_USING_key_algorithm
%type <string_list>
- using_list
+ using_list opt_use_partition use_partition
%type <key_part>
key_part
@@ -1567,11 +1857,13 @@ 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
charset_name
+ charset_or_alias
charset_name_or_default
old_or_new_charset_name
old_or_new_charset_name_or_default
@@ -1592,13 +1884,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <dyncol_def_list> dyncall_create_list
+%type <myvar> select_outvar
+
%type <NONE>
+ analyze_stmt_command
query verb_clause create change select do drop insert replace insert2
- insert_values update delete truncate rename
+ insert_values update delete truncate rename compound_statement
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
@@ -1606,21 +1906,22 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
select_item_list select_item values_list no_braces
opt_limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
- handler
+ field_def handler opt_generated_always
opt_precision opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list field_options field_option
- field_opt_list opt_binary ascii unicode table_lock_list table_lock
+ field_opt_list opt_binary table_lock_list table_lock
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
+ object_privilege object_privilege_list user_list user_and_role_list
+ rename_list table_or_tables
clear_privileges flush_options flush_option
- opt_with_read_lock flush_options_list
+ 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
@@ -1628,60 +1929,77 @@ 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
+ opt_format_json
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
- view_check_option trigger_tail sp_tail sf_tail udf_tail event_tail
+ view_check_option trigger_tail sp_tail sf_tail event_tail
+ udf_tail udf_tail2
install uninstall partition_entry binlog_base64_event
- init_key_options normal_key_options normal_key_opts all_key_opt
+ normal_key_options normal_key_opts all_key_opt
spatial_key_options fulltext_key_options normal_key_opt
fulltext_key_opt spatial_key_opt fulltext_key_opts spatial_key_opts
keep_gcc_happy
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
+ opt_delete_gtid_domain
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
%type <NONE> sp_proc_stmt_statement sp_proc_stmt_return
+%type <NONE> sp_proc_stmt_compound_ok
%type <NONE> sp_proc_stmt_if
-%type <NONE> sp_labeled_control sp_proc_stmt_unlabeled
-%type <NONE> sp_labeled_block sp_unlabeled_block
+%type <NONE> sp_labeled_control sp_unlabeled_control
+%type <NONE> sp_labeled_block sp_unlabeled_block sp_unlabeled_block_not_atomic
%type <NONE> sp_proc_stmt_leave
%type <NONE> sp_proc_stmt_iterate
%type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close
-%type <NONE> case_stmt_specification simple_case_stmt searched_case_stmt
+%type <NONE> case_stmt_specification
+%type <NONE> loop_body while_body repeat_body
-%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 <num> sp_decl_idents sp_handler_type sp_hcond_list
+%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 <splabel> sp_block_content
+%type <spvar> sp_param_name_and_type
+%type <spvar_mode> sp_opt_inout
%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
THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM DELETE_SYM
-
-%type <is_not_empty> opt_union_order_or_limit
+ ROLE_SYM
%%
+
/*
Indentation of grammar rules:
@@ -1708,10 +2026,8 @@ query:
{
if (!thd->bootstrap &&
(!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
- {
- my_message(ER_EMPTY_QUERY, ER(ER_EMPTY_QUERY), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_EMPTY_QUERY, MYF(0)));
+
thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
YYLIP->found_semicolon= NULL;
}
@@ -1755,12 +2071,14 @@ opt_end_of_input:
verb_clause:
statement
| begin
+ | compound_statement
;
-/* Verb clauses, except begin */
+/* Verb clauses, except begin and compound_statement */
statement:
alter
| analyze
+ | analyze_stmt_command
| binlog_base64_event
| call
| change
@@ -1775,6 +2093,7 @@ statement:
| drop
| execute
| flush
+ | get_diagnostics
| grant
| handler
| help
@@ -1804,6 +2123,7 @@ statement:
| set
| signal_stmt
| show
+ | shutdown
| slave
| start
| truncate
@@ -1877,8 +2197,9 @@ execute_var_ident:
'@' ident_or_text
{
LEX *lex=Lex;
- LEX_STRING *lexstr= (LEX_STRING*)sql_memdup(&$2, sizeof(LEX_STRING));
- if (!lexstr || lex->prepared_stmt_params.push_back(lexstr))
+ LEX_STRING *lexstr= (LEX_STRING*)thd->memdup(&$2, sizeof(LEX_STRING));
+ if (!lexstr || lex->prepared_stmt_params.push_back(lexstr,
+ thd->mem_root))
MYSQL_YYABORT;
}
;
@@ -1889,10 +2210,7 @@ help:
HELP_SYM
{
if (Lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "HELP");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HELP"));
}
ident_or_text
{
@@ -1905,7 +2223,7 @@ help:
/* change master */
change:
- CHANGE MASTER_SYM TO_SYM
+ CHANGE MASTER_SYM optional_connection_name TO_SYM
{
Lex->sql_command = SQLCOM_CHANGE_MASTER;
}
@@ -1969,32 +2287,36 @@ 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 '=' TEXT_STRING_sys
+ {
+ Lex->mi.ssl_crl= $3.str;
+ }
+ | MASTER_SSL_CRLPATH_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.ssl_crlpath= $3.str;
+ }
| MASTER_HEARTBEAT_PERIOD_SYM '=' NUM_literal
{
Lex->mi.heartbeat_period= (float) $3->val_real();
if (Lex->mi.heartbeat_period > SLAVE_MAX_HEARTBEAT_PERIOD ||
Lex->mi.heartbeat_period < 0.0)
- {
- const char format[]= "%d";
- char buf[4*sizeof(SLAVE_MAX_HEARTBEAT_PERIOD) + sizeof(format)];
- sprintf(buf, format, SLAVE_MAX_HEARTBEAT_PERIOD);
- my_error(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE, MYF(0), buf);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE, MYF(0),
+ SLAVE_MAX_HEARTBEAT_PERIOD));
+
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));
+ ER_THD(thd, ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX));
}
if (Lex->mi.heartbeat_period < 0.001)
{
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));
+ ER_THD(thd, ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN));
Lex->mi.heartbeat_period= 0.0;
}
Lex->mi.heartbeat_opt= LEX_MASTER_INFO::LEX_MI_DISABLE;
@@ -2005,6 +2327,14 @@ master_def:
{
Lex->mi.repl_ignore_server_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
}
+ | DO_DOMAIN_IDS_SYM '=' '(' do_domain_id_list ')'
+ {
+ Lex->mi.repl_do_domain_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
+ }
+ | IGNORE_DOMAIN_IDS_SYM '=' '(' ignore_domain_id_list ')'
+ {
+ Lex->mi.repl_ignore_domain_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
+ }
|
master_file_def
;
@@ -2020,6 +2350,33 @@ ignore_server_id:
{
insert_dynamic(&Lex->mi.repl_ignore_server_ids, (uchar*) &($1));
}
+ ;
+
+do_domain_id_list:
+ /* Empty */
+ | do_domain_id
+ | do_domain_id_list ',' do_domain_id
+ ;
+
+do_domain_id:
+ ulong_num
+ {
+ insert_dynamic(&Lex->mi.repl_do_domain_ids, (uchar*) &($1));
+ }
+ ;
+
+ignore_domain_id_list:
+ /* Empty */
+ | ignore_domain_id
+ | ignore_domain_id_list ',' ignore_domain_id
+ ;
+
+ignore_domain_id:
+ ulong_num
+ {
+ insert_dynamic(&Lex->mi.repl_ignore_domain_ids, (uchar*) &($1));
+ }
+ ;
master_file_def:
MASTER_LOG_FILE_SYM '=' TEXT_STRING_sys
@@ -2028,7 +2385,6 @@ master_file_def:
}
| MASTER_LOG_POS_SYM '=' ulonglong_num
{
- Lex->mi.pos = $3;
/*
If the user specified a value < BIN_LOG_HEADER_SIZE, adjust it
instead of causing subsequent errors.
@@ -2040,7 +2396,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, $3);
}
| RELAY_LOG_FILE_SYM '=' TEXT_STRING_sys
{
@@ -2050,86 +2406,119 @@ 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 '=' CURRENT_POS_SYM
+ {
+ if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
+ Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_CURRENT_POS;
}
+ | MASTER_USE_GTID_SYM '=' SLAVE_POS_SYM
+ {
+ if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
+ Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_SLAVE_POS;
+ }
+ | MASTER_USE_GTID_SYM '=' NO_SYM
+ {
+ if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
+ Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_NO;
+ }
+ ;
+
+optional_connection_name:
+ /* empty */
+ {
+ LEX *lex= thd->lex;
+ lex->mi.connection_name= null_lex_str;
+ }
+ | connection_name
;
+connection_name:
+ TEXT_STRING_sys
+ {
+ Lex->mi.connection_name= $1;
+#ifdef HAVE_REPLICATION
+ if (check_master_connection_name(&$1))
+ my_yyabort_error((ER_WRONG_ARGUMENTS, MYF(0), "MASTER_CONNECTION_NAME"));
+#endif
+ }
+ ;
+
/* create a table */
create:
- CREATE opt_table_options TABLE_SYM opt_if_not_exists table_ident
+ create_or_replace opt_temporary TABLE_SYM opt_if_not_exists table_ident
{
LEX *lex= thd->lex;
- lex->sql_command= SQLCOM_CREATE_TABLE;
+ lex->create_info.init();
+ if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 | $4))
+ MYSQL_YYABORT;
if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
TL_OPTION_UPDATING,
TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
+ lex->alter_info.reset();
/*
- 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.
+ 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_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;
+ lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
lex->create_info.default_table_charset= NULL;
- lex->name.str= 0;
- lex->name.length= 0;
+ lex->name= null_lex_str;
lex->create_last_non_select_table= lex->last_table();
}
- create2
+ create_body
{
LEX *lex= thd->lex;
lex->current_select= &lex->select_lex;
if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
!lex->create_info.db_type)
{
- lex->create_info.db_type= ha_default_handlerton(thd);
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ lex->create_info.use_default_db_type(thd);
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_USING_OTHER_HANDLER,
- ER(ER_WARN_USING_OTHER_HANDLER),
+ ER_THD(thd, ER_WARN_USING_OTHER_HANDLER),
hton_name(lex->create_info.db_type)->str,
$5->table.str);
}
create_table_set_open_action_and_adjust_tables(lex);
}
- | CREATE opt_unique INDEX_SYM ident key_alg ON table_ident
+ | create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident
+ opt_key_algorithm_clause
+ 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 (Lex->add_create_index($2, $5, $6, $1 | $4))
MYSQL_YYABORT;
}
- | CREATE fulltext INDEX_SYM ident init_key_options ON
- table_ident
+ '(' key_list ')' normal_key_options
+ opt_index_lock_algorithm { }
+ | create_or_replace fulltext INDEX_SYM opt_if_not_exists ident
+ ON table_ident
{
if (add_create_index_prepare(Lex, $7))
MYSQL_YYABORT;
- }
- '(' key_list ')' fulltext_key_options
- {
- if (add_create_index(Lex, $2, $4))
+ if (Lex->add_create_index($2, $5, HA_KEY_ALG_UNDEF, $1 | $4))
MYSQL_YYABORT;
}
- | CREATE spatial INDEX_SYM ident init_key_options ON
- table_ident
+ '(' key_list ')' fulltext_key_options
+ opt_index_lock_algorithm { }
+ | create_or_replace spatial INDEX_SYM opt_if_not_exists ident
+ ON table_ident
{
if (add_create_index_prepare(Lex, $7))
MYSQL_YYABORT;
- }
- '(' key_list ')' spatial_key_options
- {
- if (add_create_index(Lex, $2, $4))
+ if (Lex->add_create_index($2, $5, HA_KEY_ALG_UNDEF, $1 | $4))
MYSQL_YYABORT;
}
- | CREATE DATABASE opt_if_not_exists ident
+ '(' key_list ')' spatial_key_options
+ opt_index_lock_algorithm { }
+ | create_or_replace DATABASE opt_if_not_exists ident
{
Lex->create_info.default_table_charset= NULL;
Lex->create_info.used_fields= 0;
@@ -2137,21 +2526,29 @@ create:
opt_create_database_options
{
LEX *lex=Lex;
- lex->sql_command=SQLCOM_CREATE_DB;
+ if (lex->set_command_with_check(SQLCOM_CREATE_DB, 0, $1 | $3))
+ MYSQL_YYABORT;
lex->name= $4;
- lex->create_info.options=$3;
}
- | CREATE
+ | create_or_replace
{
- Lex->create_view_mode= VIEW_CREATE_NEW;
+ Lex->create_info.set($1);
+ Lex->create_view_mode= ($1.or_replace() ? VIEW_CREATE_OR_REPLACE :
+ VIEW_CREATE_NEW);
Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED;
Lex->create_view_suid= TRUE;
}
- view_or_trigger_or_sp_or_event
- {}
- | CREATE USER clear_privileges grant_list
+ view_or_trigger_or_sp_or_event { }
+ | create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list
{
- Lex->sql_command = SQLCOM_CREATE_USER;
+ if (Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3))
+ MYSQL_YYABORT;
+ }
+ | create_or_replace ROLE_SYM opt_if_not_exists
+ clear_privileges role_list opt_with_admin
+ {
+ if (Lex->set_command_with_check(SQLCOM_CREATE_ROLE, $1 | $3))
+ MYSQL_YYABORT;
}
| CREATE LOGFILE_SYM GROUP_SYM logfile_group_info
{
@@ -2161,23 +2558,21 @@ create:
{
Lex->alter_tablespace_info->ts_cmd_type= CREATE_TABLESPACE;
}
- | CREATE server_def
- {
- Lex->sql_command= SQLCOM_CREATE_SERVER;
- }
+ | create_or_replace { Lex->set_command(SQLCOM_CREATE_SERVER, $1); }
+ server_def
+ { }
;
server_def:
- SERVER_SYM
- ident_or_text
- FOREIGN DATA_SYM WRAPPER_SYM
- ident_or_text
- OPTIONS_SYM '(' server_options_list ')'
+ SERVER_SYM opt_if_not_exists ident_or_text
{
- Lex->server_options.server_name= $2.str;
- Lex->server_options.server_name_length= $2.length;
- Lex->server_options.scheme= $6.str;
+ if (Lex->add_create_options_with_check($2))
+ MYSQL_YYABORT;
+ Lex->server_options.reset($3);
}
+ FOREIGN DATA_SYM WRAPPER_SYM ident_or_text
+ OPTIONS_SYM '(' server_options_list ')'
+ { Lex->server_options.scheme= $8; }
;
server_options_list:
@@ -2186,29 +2581,35 @@ server_options_list:
;
server_option:
- USER TEXT_STRING_sys
+ USER_SYM TEXT_STRING_sys
{
- Lex->server_options.username= $2.str;
+ MYSQL_YYABORT_UNLESS(Lex->server_options.username.str == 0);
+ Lex->server_options.username= $2;
}
| HOST_SYM TEXT_STRING_sys
{
- Lex->server_options.host= $2.str;
+ MYSQL_YYABORT_UNLESS(Lex->server_options.host.str == 0);
+ Lex->server_options.host= $2;
}
| DATABASE TEXT_STRING_sys
{
- Lex->server_options.db= $2.str;
+ MYSQL_YYABORT_UNLESS(Lex->server_options.db.str == 0);
+ Lex->server_options.db= $2;
}
| OWNER_SYM TEXT_STRING_sys
{
- Lex->server_options.owner= $2.str;
+ MYSQL_YYABORT_UNLESS(Lex->server_options.owner.str == 0);
+ Lex->server_options.owner= $2;
}
- | PASSWORD TEXT_STRING_sys
+ | PASSWORD_SYM TEXT_STRING_sys
{
- Lex->server_options.password= $2.str;
+ MYSQL_YYABORT_UNLESS(Lex->server_options.password.str == 0);
+ Lex->server_options.password= $2;
}
| SOCKET_SYM TEXT_STRING_sys
{
- Lex->server_options.socket= $2.str;
+ MYSQL_YYABORT_UNLESS(Lex->server_options.socket.str == 0);
+ Lex->server_options.socket= $2;
}
| PORT_SYM ulong_num
{
@@ -2222,7 +2623,8 @@ event_tail:
LEX *lex=Lex;
lex->stmt_definition_begin= $1;
- lex->create_info.options= $3;
+ if (lex->add_create_options_with_check($3))
+ MYSQL_YYABORT;
if (!(lex->event_parse_data= Event_parse_data::new_instance(thd)))
MYSQL_YYABORT;
lex->event_parse_data->identifier= $4;
@@ -2285,7 +2687,7 @@ opt_ev_status:
ev_starts:
/* empty */
{
- Item *item= new (thd->mem_root) Item_func_now_local(0);
+ Item *item= new (thd->mem_root) Item_func_now_local(thd, 0);
if (item == NULL)
MYSQL_YYABORT;
Lex->event_parse_data->item_starts= item;
@@ -2310,16 +2712,11 @@ opt_ev_on_completion:
;
ev_on_completion:
- ON COMPLETION_SYM PRESERVE_SYM
+ ON COMPLETION_SYM opt_not PRESERVE_SYM
{
- Lex->event_parse_data->on_completion=
- Event_parse_data::ON_COMPLETION_PRESERVE;
- $$= 1;
- }
- | ON COMPLETION_SYM NOT_SYM PRESERVE_SYM
- {
- Lex->event_parse_data->on_completion=
- Event_parse_data::ON_COMPLETION_DROP;
+ Lex->event_parse_data->on_completion= $3
+ ? Event_parse_data::ON_COMPLETION_DROP
+ : Event_parse_data::ON_COMPLETION_PRESERVE;
$$= 1;
}
;
@@ -2356,26 +2753,15 @@ ev_sql_stmt:
- CREATE PROCEDURE ... BEGIN DROP EVENT ... END|
*/
if (lex->sphead)
- {
- my_error(ER_EVENT_RECURSION_FORBIDDEN, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_EVENT_RECURSION_FORBIDDEN, MYF(0)));
- if (!(lex->sphead= new sp_head()))
+ if (!make_sp_head(thd, lex->event_parse_data->identifier, TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT;
- lex->sphead->reset_thd_mem_root(thd);
- lex->sphead->init(lex);
- lex->sphead->init_sp_name(thd, lex->event_parse_data->identifier);
-
- lex->sphead->m_type= TYPE_ENUM_PROCEDURE;
-
- bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
- lex->sphead->m_chistics= &lex->sp_chistics;
-
+ lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
lex->sphead->set_body_start(thd, lip->get_cpp_ptr());
}
- ev_sql_stmt_inner
+ sp_proc_stmt
{
LEX *lex= thd->lex;
@@ -2383,28 +2769,10 @@ ev_sql_stmt:
lex->sphead->set_stmt_end(thd);
lex->sphead->restore_thd_mem_root(thd);
- lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
-
lex->event_parse_data->body_changed= TRUE;
}
;
-ev_sql_stmt_inner:
- sp_proc_stmt_statement
- | sp_proc_stmt_return
- | sp_proc_stmt_if
- | case_stmt_specification
- | sp_labeled_block
- | sp_unlabeled_block
- | sp_labeled_control
- | sp_proc_stmt_unlabeled
- | sp_proc_stmt_leave
- | sp_proc_stmt_iterate
- | sp_proc_stmt_open
- | sp_proc_stmt_fetch
- | sp_proc_stmt_close
- ;
-
clear_privileges:
/* Nothing */
{
@@ -2424,15 +2792,10 @@ sp_name:
ident '.' ident
{
if (!$1.str || check_db_name(&$1))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
if (check_routine_name(&$3))
- {
MYSQL_YYABORT;
- }
- $$= new sp_name($1, $3, true);
+ $$= new (thd->mem_root) sp_name($1, $3, true);
if ($$ == NULL)
MYSQL_YYABORT;
$$->init_qname(thd);
@@ -2447,7 +2810,7 @@ sp_name:
}
if (lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
- $$= new sp_name(db, $1, false);
+ $$= new (thd->mem_root) sp_name(db, $1, false);
if ($$ == NULL)
MYSQL_YYABORT;
$$->init_qname(thd);
@@ -2485,8 +2848,7 @@ sp_chistic:
/* Create characteristics */
sp_c_chistic:
sp_chistic { }
- | DETERMINISTIC_SYM { Lex->sp_chistics.detistic= TRUE; }
- | not DETERMINISTIC_SYM { Lex->sp_chistics.detistic= FALSE; }
+ | opt_not DETERMINISTIC_SYM { Lex->sp_chistics.detistic= ! $1; }
;
sp_suid:
@@ -2527,11 +2889,11 @@ opt_sp_cparams:
sp_cparams:
sp_cparams ',' expr
{
- Lex->value_list.push_back($3);
+ Lex->value_list.push_back($3, thd->mem_root);
}
| expr
{
- Lex->value_list.push_back($1);
+ Lex->value_list.push_back($1, thd->mem_root);
}
;
@@ -2542,54 +2904,40 @@ sp_fdparam_list:
;
sp_fdparams:
- sp_fdparams ',' sp_fdparam
- | sp_fdparam
+ sp_fdparams ',' sp_param_name_and_type
+ | sp_param_name_and_type
;
-sp_init_param:
- /* Empty */
+sp_param_name_and_type:
+ ident
{
LEX *lex= Lex;
+ sp_pcontext *spc= lex->spcont;
- lex->length= 0;
- lex->dec= 0;
- lex->type= 0;
-
- lex->default_value= 0;
- lex->on_update_value= 0;
+ if (spc->find_variable($1, TRUE))
+ my_yyabort_error((ER_SP_DUP_PARAM, MYF(0), $1.str));
- lex->comment= null_lex_str;
- lex->charset= NULL;
+ sp_variable *spvar= spc->add_variable(thd, $1);
- lex->interval_list.empty();
- lex->uint_geom_type= 0;
- lex->vcol_info= 0;
+ lex->init_last_field(&spvar->field_def, $1.str,
+ thd->variables.collation_database);
+ $<spvar>$= spvar;
}
- ;
-
-sp_fdparam:
- ident sp_init_param type_with_opt_collate
+ type_with_opt_collate
{
LEX *lex= Lex;
- sp_pcontext *spc= lex->spcont;
-
- 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= $<spvar>2;
- if (lex->sphead->fill_field_definition(thd, lex,
- (enum enum_field_types) $3,
- &spvar->field_def))
+ spvar->type= $3;
+ if (lex->sphead->fill_field_definition(thd, lex, $3,
+ lex->last_field))
{
MYSQL_YYABORT;
}
spvar->field_def.field_name= spvar->name.str;
spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
+
+ $$= spvar;
}
;
@@ -2605,36 +2953,14 @@ sp_pdparams:
;
sp_pdparam:
- sp_opt_inout sp_init_param ident type_with_opt_collate
- {
- LEX *lex= Lex;
- sp_pcontext *spc= lex->spcont;
-
- 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);
-
- if (lex->sphead->fill_field_definition(thd, lex,
- (enum enum_field_types) $4,
- &spvar->field_def))
- {
- MYSQL_YYABORT;
- }
- spvar->field_def.field_name= spvar->name.str;
- spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
- }
+ sp_opt_inout sp_param_name_and_type { $2->mode=$1; }
;
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:
@@ -2659,17 +2985,9 @@ sp_decls:
shift/reduce conflicts with the wrong result. (And we get
better error handling this way.) */
if (($2.vars || $2.conds) && ($1.curs || $1.hndlrs))
- { /* Variable or condition following cursor or handler */
- my_message(ER_SP_VARCOND_AFTER_CURSHNDLR,
- ER(ER_SP_VARCOND_AFTER_CURSHNDLR), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_VARCOND_AFTER_CURSHNDLR, MYF(0)));
if ($2.curs && $1.hndlrs)
- { /* Cursor following handler */
- my_message(ER_SP_CURSOR_AFTER_HANDLER,
- ER(ER_SP_CURSOR_AFTER_HANDLER), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_CURSOR_AFTER_HANDLER, MYF(0)));
$$.vars= $1.vars + $2.vars;
$$.conds= $1.conds + $2.conds;
$$.hndlrs= $1.hndlrs + $2.hndlrs;
@@ -2681,9 +2999,17 @@ sp_decl:
DECLARE_SYM sp_decl_idents
{
LEX *lex= Lex;
+ sp_pcontext *pctx= lex->spcont;
+
+ // get the last variable:
+ uint num_vars= pctx->context_var_count();
+ uint var_idx= pctx->var_context2runtime(num_vars - 1);
+ sp_variable *spvar= pctx->find_variable(var_idx);
lex->sphead->reset_lex(thd);
- lex->spcont->declare_var_boundary($2);
+ pctx->declare_var_boundary($2);
+ thd->lex->init_last_field(&spvar->field_def, spvar->name.str,
+ thd->variables.collation_database);
}
type_with_opt_collate
sp_opt_default
@@ -2691,12 +3017,12 @@ sp_decl:
LEX *lex= Lex;
sp_pcontext *pctx= lex->spcont;
uint num_vars= pctx->context_var_count();
- enum enum_field_types var_type= (enum enum_field_types) $4;
+ enum enum_field_types var_type= $4;
Item *dflt_value_item= $5;
if (!dflt_value_item)
{
- dflt_value_item= new (thd->mem_root) Item_null();
+ dflt_value_item= new (thd->mem_root) Item_null(thd);
if (dflt_value_item == NULL)
MYSQL_YYABORT;
/* QQ Set to the var_type with null_value? */
@@ -2705,13 +3031,18 @@ 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);
+ bool last= i == num_vars - 1;
if (!spvar)
MYSQL_YYABORT;
+ if (!last)
+ spvar->field_def= *lex->last_field;
+
spvar->type= var_type;
- spvar->dflt= dflt_value_item;
+ spvar->default_value= dflt_value_item;
+ spvar->field_def.field_name= spvar->name.str;
if (lex->sphead->fill_field_definition(thd, lex, var_type,
&spvar->field_def))
@@ -2719,20 +3050,15 @@ sp_decl:
MYSQL_YYABORT;
}
- spvar->field_def.field_name= spvar->name.str;
spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
/* The last instruction is responsible for freeing LEX. */
- sp_instr_set *is= new sp_instr_set(lex->sphead->instructions(),
- pctx,
- var_idx,
- dflt_value_item,
- var_type,
- lex,
- (i == num_vars - 1));
- if (is == NULL ||
- lex->sphead->add_instr(is))
+ sp_instr_set *is= new (thd->mem_root)
+ sp_instr_set(lex->sphead->instructions(),
+ pctx, var_idx, dflt_value_item,
+ var_type, lex, last);
+ if (is == NULL || lex->sphead->add_instr(is))
MYSQL_YYABORT;
}
@@ -2747,12 +3073,9 @@ sp_decl:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_cond(&$2, TRUE))
- {
- my_error(ER_SP_DUP_COND, MYF(0), $2.str);
- MYSQL_YYABORT;
- }
- if(thd->lex->spcont->push_cond(&$2, $5))
+ if (spc->find_condition($2, TRUE))
+ my_yyabort_error((ER_SP_DUP_COND, MYF(0), $2.str));
+ if(spc->add_condition(thd, $2, $5))
MYSQL_YYABORT;
$$.vars= $$.hndlrs= $$.curs= 0;
$$.conds= 1;
@@ -2762,21 +3085,26 @@ 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 (thd->mem_root) 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
@@ -2784,20 +3112,21 @@ 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 (thd->mem_root)
+ 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 (thd->mem_root)
+ sp_instr_hreturn(sp->instructions(), ctx);
if (i == NULL ||
sp->add_instr(i) ||
sp->push_backpatch(i, lex->spcont->last_label())) /* Block end */
@@ -2808,8 +3137,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
{
@@ -2819,17 +3147,13 @@ sp_decl:
uint offp;
sp_instr_cpush *i;
- if (ctx->find_cursor(&$2, &offp, TRUE))
- {
- my_error(ER_SP_DUP_CURS, MYF(0), $2.str);
- delete $5;
- MYSQL_YYABORT;
- }
- i= new sp_instr_cpush(sp->instructions(), ctx, $5,
- ctx->current_cursor_count());
- if (i == NULL ||
- sp->add_instr(i) ||
- ctx->push_cursor(&$2))
+ if (ctx->find_cursor($2, &offp, TRUE))
+ my_yyabort_error((ER_SP_DUP_CURS, MYF(0), $2.str));
+
+ i= new (thd->mem_root)
+ sp_instr_cpush(sp->instructions(), ctx, $5,
+ ctx->current_cursor_count());
+ if (i == NULL || sp->add_instr(i) || ctx->add_cursor($2))
MYSQL_YYABORT;
$$.vars= $$.conds= $$.hndlrs= 0;
$$.curs= 1;
@@ -2847,11 +3171,7 @@ sp_cursor_stmt:
DBUG_ASSERT(lex->sql_command == SQLCOM_SELECT);
if (lex->result)
- {
- my_message(ER_SP_BAD_CURSOR_SELECT, ER(ER_SP_BAD_CURSOR_SELECT),
- MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BAD_CURSOR_SELECT, MYF(0)));
lex->sp_lex_in_use= TRUE;
$$= lex;
if (lex->sphead->restore_lex(thd))
@@ -2860,9 +3180,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:
@@ -2879,19 +3199,11 @@ sp_hcond_element:
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont->parent_context();
- if (ctx->find_handler($1))
- {
- my_message(ER_SP_DUP_HANDLER, ER(ER_SP_DUP_HANDLER), MYF(0));
- MYSQL_YYABORT;
- }
- else
- {
- sp_instr_hpush_jump *i=
- (sp_instr_hpush_jump *)sp->last_instruction();
+ if (ctx->check_duplicate_handler($1))
+ my_yyabort_error((ER_SP_DUP_HANDLER, MYF(0)));
- i->add_condition($1);
- ctx->push_handler($1);
- }
+ sp_instr_hpush_jump *i= (sp_instr_hpush_jump *)sp->last_instruction();
+ i->add_condition($1);
}
;
@@ -2899,15 +3211,10 @@ sp_cond:
ulong_num
{ /* mysql errno */
if ($1 == 0)
- {
- my_error(ER_WRONG_VALUE, MYF(0), "CONDITION", "0");
- MYSQL_YYABORT;
- }
- $$= (sp_cond_type_t *) thd->alloc(sizeof(sp_cond_type_t));
+ my_yyabort_error((ER_WRONG_VALUE, MYF(0), "CONDITION", "0"));
+ $$= new (thd->mem_root) sp_condition_value($1);
if ($$ == NULL)
MYSQL_YYABORT;
- $$->type= sp_cond_type_t::number;
- $$->mysqlerr= $1;
}
| sqlstate
;
@@ -2915,17 +3222,19 @@ sp_cond:
sqlstate:
SQLSTATE_SYM opt_value TEXT_STRING_literal
{ /* SQLSTATE */
- if (!sp_cond_check(&$3))
- {
- my_error(ER_SP_BAD_SQLSTATE, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
- $$= (sp_cond_type_t *) thd->alloc(sizeof(sp_cond_type_t));
+
+ /*
+ 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_yyabort_error((ER_SP_BAD_SQLSTATE, MYF(0), $3.str));
+ $$= 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';
}
;
@@ -2941,33 +3250,27 @@ 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);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
}
| 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;
}
;
@@ -2978,9 +3281,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;
}
;
@@ -2989,24 +3292,16 @@ signal_value:
ident
{
LEX *lex= Lex;
- sp_cond_type_t *cond;
+ sp_condition_value *cond;
+
+ /* SIGNAL foo cannot be used outside of stored programs */
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);
+ my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
+ 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)
- {
- my_error(ER_SIGNAL_BAD_CONDITION_TYPE, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
+ if (cond->type != sp_condition_value::SQLSTATE)
+ my_yyabort_error((ER_SIGNAL_BAD_CONDITION_TYPE, MYF(0)));
$$= cond;
}
| sqlstate
@@ -3044,11 +3339,8 @@ signal_information_item_list:
info= &thd->m_parser_state->m_yacc.m_set_signal_info;
int index= (int) $3;
if (info->m_item[index] != NULL)
- {
- my_error(ER_DUP_SIGNAL_SET, MYF(0),
- Diag_condition_item_names[index].str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_SIGNAL_SET, MYF(0),
+ Diag_condition_item_names[index].str));
info->m_item[index]= $5;
}
;
@@ -3071,7 +3363,7 @@ signal_allowed_expr:
SIGNAL/RESIGNAL ...
SET <signal condition item name> = @foo := expr
*/
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
}
@@ -3116,13 +3408,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, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ | statement_information ',' statement_information_item
+ {
+ if ($1->push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ $$= $1;
+ }
+ ;
+
+statement_information_item:
+ simple_target_specification '=' 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(thd, $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, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ | condition_information ',' condition_information_item
+ {
+ if ($1->push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ $$= $1;
+ }
+ ;
+
+condition_information_item:
+ simple_target_specification '=' 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
{
@@ -3131,12 +3570,9 @@ sp_decl_idents:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- 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);
+ if (spc->find_variable($1, TRUE))
+ my_yyabort_error((ER_SP_DUP_VAR, MYF(0), $1.str));
+ spc->add_variable(thd, $1);
$$= 1;
}
| sp_decl_idents ',' ident
@@ -3146,12 +3582,9 @@ sp_decl_idents:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- 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);
+ if (spc->find_variable($3, TRUE))
+ my_yyabort_error((ER_SP_DUP_VAR, MYF(0), $3.str));
+ spc->add_variable(thd, $3);
$$= $1 + 1;
}
;
@@ -3164,23 +3597,32 @@ sp_opt_default:
sp_proc_stmt:
sp_proc_stmt_statement
| sp_proc_stmt_return
- | sp_proc_stmt_if
- | case_stmt_specification
| sp_labeled_block
| sp_unlabeled_block
| sp_labeled_control
- | sp_proc_stmt_unlabeled
| sp_proc_stmt_leave
| sp_proc_stmt_iterate
| sp_proc_stmt_open
| sp_proc_stmt_fetch
| sp_proc_stmt_close
+ | sp_proc_stmt_compound_ok
+ ;
+
+sp_proc_stmt_compound_ok:
+ sp_proc_stmt_if
+ | case_stmt_specification
+ | sp_unlabeled_block_not_atomic
+ | sp_unlabeled_control
;
sp_proc_stmt_if:
- IF
- { Lex->sphead->new_cont_backpatch(NULL); }
- sp_if END IF
+ IF_SYM
+ {
+ if (maybe_start_compound_statement(thd))
+ MYSQL_YYABORT;
+ Lex->sphead->new_cont_backpatch(NULL);
+ }
+ sp_if END IF_SYM
{ Lex->sphead->do_cont_backpatch(); }
;
@@ -3199,11 +3641,9 @@ sp_proc_stmt_statement:
sp_head *sp= lex->sphead;
sp->m_flags|= sp_get_flags_for_command(lex);
+ /* "USE db" doesn't work in a procedure */
if (lex->sql_command == SQLCOM_CHANGE_DB)
- { /* "USE db" doesn't work in a procedure */
- my_error(ER_SP_BADSTATEMENT, MYF(0), "USE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "USE"));
/*
Don't add an instruction for SET statements, since all
instructions for them were already added during processing
@@ -3213,8 +3653,8 @@ sp_proc_stmt_statement:
lex->var_list.is_empty());
if (lex->sql_command != SQLCOM_SET_OPTION)
{
- sp_instr_stmt *i=new sp_instr_stmt(sp->instructions(),
- lex->spcont, lex);
+ sp_instr_stmt *i=new (thd->mem_root)
+ sp_instr_stmt(sp->instructions(), lex->spcont, lex);
if (i == NULL)
MYSQL_YYABORT;
@@ -3226,7 +3666,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)) ||
@@ -3247,90 +3687,69 @@ sp_proc_stmt_return:
sp_head *sp= lex->sphead;
if (sp->m_type != TYPE_ENUM_FUNCTION)
- {
- my_message(ER_SP_BADRETURN, ER(ER_SP_BADRETURN), MYF(0));
+ my_yyabort_error((ER_SP_BADRETURN, MYF(0)));
+
+ sp_instr_freturn *i;
+
+ i= new (thd->mem_root)
+ sp_instr_freturn(sp->instructions(), lex->spcont, $3,
+ sp->m_return_field_def.sql_type, lex);
+ if (i == NULL || sp->add_instr(i))
MYSQL_YYABORT;
- }
- else
- {
- sp_instr_freturn *i;
+ sp->m_flags|= sp_head::HAS_RETURN;
- i= new sp_instr_freturn(sp->instructions(), lex->spcont, $3,
- sp->m_return_field_def.sql_type, lex);
- if (i == NULL ||
- sp->add_instr(i))
- MYSQL_YYABORT;
- sp->m_flags|= sp_head::HAS_RETURN;
- }
if (sp->restore_lex(thd))
MYSQL_YYABORT;
}
;
-sp_proc_stmt_unlabeled:
- { /* Unlabeled controls get a secret label. */
- LEX *lex= Lex;
-
- lex->spcont->push_label((char *)"", lex->sphead->instructions());
- }
- sp_unlabeled_control
- {
- LEX *lex= Lex;
-
- lex->sphead->backpatch(lex->spcont->pop_label());
- }
- ;
-
sp_proc_stmt_leave:
LEAVE_SYM label_ident
{
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)
+ my_yyabort_error((ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str));
+
+ sp_instr_jump *i;
+ uint ip= sp->instructions();
+ uint n;
+ /*
+ When jumping to a BEGIN-END block end, the target jump
+ points to the block hpop/cpop cleanup instructions,
+ so we should exclude the block context here.
+ When jumping to something else (i.e., SP_LAB_ITER),
+ there are no hpop/cpop at the jump destination,
+ so we should include the block context here for cleanup.
+ */
+ bool exclusive= (lab->type == sp_label::BEGIN);
+
+ n= ctx->diff_handlers(lab->ctx, exclusive);
+ if (n)
{
- my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str);
- MYSQL_YYABORT;
+ sp_instr_hpop *hpop= new (thd->mem_root)
+ sp_instr_hpop(ip++, ctx, n);
+ if (hpop == NULL)
+ MYSQL_YYABORT;
+ sp->add_instr(hpop);
}
- else
+ n= ctx->diff_cursors(lab->ctx, exclusive);
+ if (n)
{
- sp_instr_jump *i;
- uint ip= sp->instructions();
- uint n;
- /*
- When jumping to a BEGIN-END block end, the target jump
- points to the block hpop/cpop cleanup instructions,
- so we should exclude the block context here.
- When jumping to something else (i.e., SP_LAB_ITER),
- 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);
-
- n= ctx->diff_handlers(lab->ctx, exclusive);
- if (n)
- {
- sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n);
- if (hpop == NULL)
- MYSQL_YYABORT;
- sp->add_instr(hpop);
- }
- n= ctx->diff_cursors(lab->ctx, exclusive);
- if (n)
- {
- sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n);
- if (cpop == NULL)
- MYSQL_YYABORT;
- sp->add_instr(cpop);
- }
- i= new sp_instr_jump(ip, ctx);
- if (i == NULL)
+ sp_instr_cpop *cpop= new (thd->mem_root)
+ sp_instr_cpop(ip++, ctx, n);
+ if (cpop == NULL)
MYSQL_YYABORT;
- sp->push_backpatch(i, lab); /* Jumping forward */
- sp->add_instr(i);
+ sp->add_instr(cpop);
}
+ i= new (thd->mem_root) sp_instr_jump(ip, ctx);
+ if (i == NULL)
+ MYSQL_YYABORT;
+ sp->push_backpatch(i, lab); /* Jumping forward */
+ sp->add_instr(i);
}
;
@@ -3340,40 +3759,38 @@ 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_label::ITERATION)
+ my_yyabort_error((ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str));
+
+ sp_instr_jump *i;
+ uint ip= sp->instructions();
+ uint n;
- if (! lab || lab->type != SP_LAB_ITER)
+ n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */
+ if (n)
{
- my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str);
- MYSQL_YYABORT;
+ sp_instr_hpop *hpop= new (thd->mem_root)
+ sp_instr_hpop(ip++, ctx, n);
+ if (hpop == NULL ||
+ sp->add_instr(hpop))
+ MYSQL_YYABORT;
}
- else
+ n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */
+ if (n)
{
- sp_instr_jump *i;
- uint ip= sp->instructions();
- uint n;
-
- n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */
- if (n)
- {
- sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n);
- if (hpop == NULL ||
- sp->add_instr(hpop))
- MYSQL_YYABORT;
- }
- n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */
- if (n)
- {
- sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n);
- if (cpop == NULL ||
- sp->add_instr(cpop))
- MYSQL_YYABORT;
- }
- i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
- if (i == NULL ||
- sp->add_instr(i))
+ sp_instr_cpop *cpop= new (thd->mem_root)
+ sp_instr_cpop(ip++, ctx, n);
+ if (cpop == NULL ||
+ sp->add_instr(cpop))
MYSQL_YYABORT;
}
+ i= new (thd->mem_root)
+ sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
+ if (i == NULL ||
+ sp->add_instr(i))
+ MYSQL_YYABORT;
}
;
@@ -3385,12 +3802,10 @@ sp_proc_stmt_open:
uint offset;
sp_instr_copen *i;
- if (! lex->spcont->find_cursor(&$2, &offset))
- {
- my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
- MYSQL_YYABORT;
- }
- i= new sp_instr_copen(sp->instructions(), lex->spcont, offset);
+ if (! lex->spcont->find_cursor($2, &offset, false))
+ my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $2.str));
+ i= new (thd->mem_root)
+ sp_instr_copen(sp->instructions(), lex->spcont, offset);
if (i == NULL ||
sp->add_instr(i))
MYSQL_YYABORT;
@@ -3405,12 +3820,10 @@ sp_proc_stmt_fetch:
uint offset;
sp_instr_cfetch *i;
- if (! lex->spcont->find_cursor(&$3, &offset))
- {
- my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
- i= new sp_instr_cfetch(sp->instructions(), lex->spcont, offset);
+ if (! lex->spcont->find_cursor($3, &offset, false))
+ my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $3.str));
+ i= new (thd->mem_root)
+ sp_instr_cfetch(sp->instructions(), lex->spcont, offset);
if (i == NULL ||
sp->add_instr(i))
MYSQL_YYABORT;
@@ -3427,12 +3840,10 @@ sp_proc_stmt_close:
uint offset;
sp_instr_cclose *i;
- if (! lex->spcont->find_cursor(&$2, &offset))
- {
- my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
- MYSQL_YYABORT;
- }
- i= new sp_instr_cclose(sp->instructions(), lex->spcont, offset);
+ if (! lex->spcont->find_cursor($2, &offset, false))
+ my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $2.str));
+ i= new (thd->mem_root)
+ sp_instr_cclose(sp->instructions(), lex->spcont, offset);
if (i == NULL ||
sp->add_instr(i))
MYSQL_YYABORT;
@@ -3451,40 +3862,28 @@ 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)))
- {
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
- else
- {
- /* An SP local variable */
- sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ if (!spc || !(spv = spc->find_variable($1, false)))
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
- i->add_to_varlist(spv);
- }
+ /* An SP local variable */
+ sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ i->add_to_varlist(spv);
}
| sp_fetch_list ',' ident
{
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)))
- {
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
- else
- {
- /* An SP local variable */
- sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ if (!spc || !(spv = spc->find_variable($3, false)))
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $3.str));
- i->add_to_varlist(spv);
- }
+ /* An SP local variable */
+ sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ i->add_to_varlist(spv);
}
;
@@ -3496,10 +3895,10 @@ sp_if:
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
uint ip= sp->instructions();
- sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx,
- $2, lex);
+ sp_instr_jump_if_not *i= new (thd->mem_root)
+ 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;
@@ -3511,12 +3910,12 @@ sp_if:
sp_head *sp= Lex->sphead;
sp_pcontext *ctx= Lex->spcont;
uint ip= sp->instructions();
- sp_instr_jump *i = new sp_instr_jump(ip, ctx);
+ sp_instr_jump *i= new (thd->mem_root) sp_instr_jump(ip, ctx);
if (i == NULL ||
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
{
@@ -3533,51 +3932,89 @@ sp_elseifs:
;
case_stmt_specification:
- simple_case_stmt
- | searched_case_stmt
- ;
-
-simple_case_stmt:
CASE_SYM
{
- LEX *lex= Lex;
- case_stmt_action_case(lex);
- lex->sphead->reset_lex(thd); /* For expr $3 */
- }
- expr
- {
- LEX *lex= Lex;
- if (case_stmt_action_expr(lex, $3))
- MYSQL_YYABORT;
+ if (maybe_start_compound_statement(thd))
+ MYSQL_YYABORT;
+
+ /**
+ An example of the CASE statement in use is
+ <pre>
+ CREATE PROCEDURE proc_19194_simple(i int)
+ BEGIN
+ DECLARE str CHAR(10);
+
+ CASE i
+ WHEN 1 THEN SET str="1";
+ WHEN 2 THEN SET str="2";
+ WHEN 3 THEN SET str="3";
+ ELSE SET str="unknown";
+ END CASE;
+
+ SELECT str;
+ END
+ </pre>
+ The actions are used to generate the following code:
+ <pre>
+ SHOW PROCEDURE CODE proc_19194_simple;
+ Pos Instruction
+ 0 set str@1 NULL
+ 1 set_case_expr (12) 0 i@0
+ 2 jump_if_not 5(12) (case_expr@0 = 1)
+ 3 set str@1 _latin1'1'
+ 4 jump 12
+ 5 jump_if_not 8(12) (case_expr@0 = 2)
+ 6 set str@1 _latin1'2'
+ 7 jump 12
+ 8 jump_if_not 11(12) (case_expr@0 = 3)
+ 9 set str@1 _latin1'3'
+ 10 jump 12
+ 11 set str@1 _latin1'unknown'
+ 12 stmt 0 "SELECT str"
+ </pre>
+ */
- /* For expr $3 */
- if (lex->sphead->restore_lex(thd))
- MYSQL_YYABORT;
+ Lex->sphead->new_cont_backpatch(NULL);
+
+ /*
+ BACKPATCH: Creating target label for the jump to after END CASE
+ (instruction 12 in the example)
+ */
+ Lex->spcont->push_label(thd, empty_lex_str, Lex->sphead->instructions());
}
- simple_when_clause_list
+ case_stmt_body
else_clause_opt
END
CASE_SYM
{
- LEX *lex= Lex;
- case_stmt_action_end_case(lex, true);
+ /*
+ BACKPATCH: Resolving forward jump from
+ "case_stmt_action_then" to after END CASE
+ (jump from instruction 4 to 12, 7 to 12 ... in the example)
+ */
+ Lex->sphead->backpatch(Lex->spcont->pop_label());
+
+ if ($3)
+ Lex->spcont->pop_case_expr_id();
+
+ Lex->sphead->do_cont_backpatch();
}
;
-searched_case_stmt:
- CASE_SYM
- {
- LEX *lex= Lex;
- case_stmt_action_case(lex);
- }
- searched_when_clause_list
- else_clause_opt
- END
- CASE_SYM
+case_stmt_body:
+ { Lex->sphead->reset_lex(thd); /* For expr $2 */ }
+ expr
{
- LEX *lex= Lex;
- case_stmt_action_end_case(lex, false);
+ if (case_stmt_action_expr(Lex, $2))
+ MYSQL_YYABORT;
+
+ if (Lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
}
+ simple_when_clause_list
+ { $$= 1; }
+ | searched_when_clause_list
+ { $$= 0; }
;
simple_when_clause_list:
@@ -3644,8 +4081,8 @@ else_clause_opt:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
uint ip= sp->instructions();
- sp_instr_error *i= new sp_instr_error(ip, lex->spcont,
- ER_SP_CASE_NOT_FOUND);
+ sp_instr_error *i= new (thd->mem_root)
+ sp_instr_error(ip, lex->spcont, ER_SP_CASE_NOT_FOUND);
if (i == NULL ||
sp->add_instr(i))
MYSQL_YYABORT;
@@ -3653,101 +4090,60 @@ else_clause_opt:
| ELSE sp_proc_stmts1
;
-sp_labeled_control:
- label_ident ':'
- {
- LEX *lex= Lex;
- sp_pcontext *ctx= lex->spcont;
- sp_label_t *lab= ctx->find_label($1.str);
-
- if (lab)
- {
- my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
- else
- {
- lab= lex->spcont->push_label($1.str,
- lex->sphead->instructions());
- lab->type= SP_LAB_ITER;
- }
- }
- sp_unlabeled_control sp_opt_label
- {
- LEX *lex= Lex;
- sp_label_t *lab= lex->spcont->pop_label();
-
- if ($5.str)
- {
- if (my_strcasecmp(system_charset_info, $5.str, lab->name) != 0)
- {
- my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str);
- MYSQL_YYABORT;
- }
- }
- lex->sphead->backpatch(lab);
- }
- ;
-
sp_opt_label:
/* Empty */ { $$= null_lex_str; }
| label_ident { $$= $1; }
;
sp_labeled_block:
- label_ident ':'
+ label_ident ':' BEGIN_SYM
{
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)
- {
- my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
-
- lab= lex->spcont->push_label($1.str,
- lex->sphead->instructions());
- lab->type= SP_LAB_BEGIN;
+ my_yyabort_error((ER_SP_LABEL_REDEFINE, MYF(0), $1.str));
+ lex->name= $1;
}
sp_block_content sp_opt_label
{
- LEX *lex= Lex;
- sp_label_t *lab= lex->spcont->pop_label();
-
- if ($5.str)
+ if ($6.str)
{
- if (my_strcasecmp(system_charset_info, $5.str, lab->name) != 0)
- {
- my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str);
- MYSQL_YYABORT;
- }
+ if (my_strcasecmp(system_charset_info, $6.str, $5->name.str) != 0)
+ my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $6.str));
}
}
;
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;
+ BEGIN_SYM
+ {
+ Lex->name= empty_lex_str; // Unlabeled blocks get an empty label
}
sp_block_content
+ { }
+ ;
+
+sp_unlabeled_block_not_atomic:
+ BEGIN_SYM not ATOMIC_SYM /* TODO: BEGIN ATOMIC (not -> opt_not) */
{
- LEX *lex= Lex;
- lex->spcont->pop_label();
+ if (maybe_start_compound_statement(thd))
+ MYSQL_YYABORT;
+ Lex->name= empty_lex_str; // Unlabeled blocks get an empty label
}
+ sp_block_content
+ { }
;
sp_block_content:
- BEGIN_SYM
- { /* QQ This is just a dummy for grouping declarations and statements
- 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);
+ sp_label *lab= lex->spcont->push_label(thd, lex->name,
+ lex->sphead->instructions());
+ lab->type= sp_label::BEGIN;
+ lex->spcont= lex->spcont->push_context(thd,
+ sp_pcontext::REGULAR_SCOPE);
}
sp_decls
sp_proc_stmts
@@ -3759,45 +4155,49 @@ sp_block_content:
sp_instr *i;
sp->backpatch(ctx->last_label()); /* We always have a label */
- if ($3.hndlrs)
+ if ($2.hndlrs)
{
- i= new sp_instr_hpop(sp->instructions(), ctx, $3.hndlrs);
+ i= new (thd->mem_root)
+ sp_instr_hpop(sp->instructions(), ctx, $2.hndlrs);
if (i == NULL ||
sp->add_instr(i))
MYSQL_YYABORT;
}
- if ($3.curs)
+ if ($2.curs)
{
- i= new sp_instr_cpop(sp->instructions(), ctx, $3.curs);
+ i= new (thd->mem_root)
+ sp_instr_cpop(sp->instructions(), ctx, $2.curs);
if (i == NULL ||
sp->add_instr(i))
MYSQL_YYABORT;
}
lex->spcont= ctx->pop_context();
+ $$ = lex->spcont->pop_label();
}
;
-sp_unlabeled_control:
- LOOP_SYM
+loop_body:
sp_proc_stmts1 END LOOP_SYM
{
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
- sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
+ sp_label *lab= lex->spcont->last_label(); /* Jumping back */
+ sp_instr_jump *i= new (thd->mem_root)
+ sp_instr_jump(ip, lex->spcont, lab->ip);
if (i == NULL ||
lex->sphead->add_instr(i))
MYSQL_YYABORT;
}
- | WHILE_SYM
- { Lex->sphead->reset_lex(thd); }
+ ;
+
+while_body:
expr DO_SYM
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
uint ip= sp->instructions();
- sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
- $3, lex);
+ sp_instr_jump_if_not *i= new (thd->mem_root)
+ sp_instr_jump_if_not(ip, lex->spcont, $1, lex);
if (i == NULL ||
/* Jumping forward */
sp->push_backpatch(i, lex->spcont->last_label()) ||
@@ -3811,23 +4211,26 @@ sp_unlabeled_control:
{
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
- sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
+ sp_label *lab= lex->spcont->last_label(); /* Jumping back */
+ sp_instr_jump *i= new (thd->mem_root)
+ sp_instr_jump(ip, lex->spcont, lab->ip);
if (i == NULL ||
lex->sphead->add_instr(i))
MYSQL_YYABORT;
lex->sphead->do_cont_backpatch();
}
- | REPEAT_SYM sp_proc_stmts1 UNTIL_SYM
+ ;
+
+repeat_body:
+ sp_proc_stmts1 UNTIL_SYM
{ Lex->sphead->reset_lex(thd); }
expr END REPEAT_SYM
{
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
- sp_label_t *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);
+ sp_label *lab= lex->spcont->last_label(); /* Jumping back */
+ sp_instr_jump_if_not *i= new (thd->mem_root)
+ sp_instr_jump_if_not(ip, lex->spcont, $4, lab->ip, lex);
if (i == NULL ||
lex->sphead->add_instr(i))
MYSQL_YYABORT;
@@ -3838,6 +4241,81 @@ sp_unlabeled_control:
}
;
+pop_sp_label:
+ sp_opt_label
+ {
+ sp_label *lab;
+ Lex->sphead->backpatch(lab= Lex->spcont->pop_label());
+ if ($1.str)
+ {
+ if (my_strcasecmp(system_charset_info, $1.str,
+ lab->name.str) != 0)
+ my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $1.str));
+ }
+ }
+ ;
+
+pop_sp_empty_label:
+ {
+ sp_label *lab;
+ Lex->sphead->backpatch(lab= Lex->spcont->pop_label());
+ DBUG_ASSERT(lab->name.length == 0);
+ }
+ ;
+
+sp_labeled_control:
+ label_ident ':' LOOP_SYM
+ {
+ if (push_sp_label(thd, $1))
+ MYSQL_YYABORT;
+ }
+ loop_body pop_sp_label
+ { }
+ | label_ident ':' WHILE_SYM
+ {
+ if (push_sp_label(thd, $1))
+ MYSQL_YYABORT;
+ Lex->sphead->reset_lex(thd);
+ }
+ while_body pop_sp_label
+ { }
+ | label_ident ':' REPEAT_SYM
+ {
+ if (push_sp_label(thd, $1))
+ MYSQL_YYABORT;
+ }
+ repeat_body pop_sp_label
+ { }
+ ;
+
+sp_unlabeled_control:
+ LOOP_SYM
+ {
+ if (push_sp_empty_label(thd))
+ MYSQL_YYABORT;
+ }
+ loop_body
+ pop_sp_empty_label
+ { }
+ | WHILE_SYM
+ {
+ if (push_sp_empty_label(thd))
+ MYSQL_YYABORT;
+ Lex->sphead->reset_lex(thd);
+ }
+ while_body
+ pop_sp_empty_label
+ { }
+ | REPEAT_SYM
+ {
+ if (push_sp_empty_label(thd))
+ MYSQL_YYABORT;
+ }
+ repeat_body
+ pop_sp_empty_label
+ { }
+ ;
+
trg_action_time:
BEFORE_SYM
{ Lex->trg_chistics.action_time= TRG_ACTION_BEFORE; }
@@ -4046,7 +4524,8 @@ tablespace_name:
ident
{
LEX *lex= Lex;
- lex->alter_tablespace_info= new st_alter_tablespace();
+ lex->alter_tablespace_info= (new (thd->mem_root)
+ st_alter_tablespace());
if (lex->alter_tablespace_info == NULL)
MYSQL_YYABORT;
lex->alter_tablespace_info->tablespace_name= $1.str;
@@ -4058,7 +4537,8 @@ logfile_group_name:
ident
{
LEX *lex= Lex;
- lex->alter_tablespace_info= new st_alter_tablespace();
+ lex->alter_tablespace_info= (new (thd->mem_root)
+ st_alter_tablespace());
if (lex->alter_tablespace_info == NULL)
MYSQL_YYABORT;
lex->alter_tablespace_info->logfile_group_name= $1.str;
@@ -4137,10 +4617,7 @@ opt_ts_nodegroup:
{
LEX *lex= Lex;
if (lex->alter_tablespace_info->nodegroup_id != UNDEF_NODEGROUP)
- {
- my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NODEGROUP");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NODEGROUP"));
lex->alter_tablespace_info->nodegroup_id= $3;
}
;
@@ -4150,10 +4627,7 @@ opt_ts_comment:
{
LEX *lex= Lex;
if (lex->alter_tablespace_info->ts_comment != NULL)
- {
- my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"COMMENT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"COMMENT"));
lex->alter_tablespace_info->ts_comment= $3.str;
}
;
@@ -4163,11 +4637,8 @@ opt_ts_engine:
{
LEX *lex= Lex;
if (lex->alter_tablespace_info->storage_engine != NULL)
- {
- my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),
- "STORAGE ENGINE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE, MYF(0),
+ "STORAGE ENGINE"));
lex->alter_tablespace_info->storage_engine= $4;
}
;
@@ -4187,10 +4658,7 @@ ts_wait:
{
LEX *lex= Lex;
if (!(lex->alter_tablespace_info->wait_until_completed))
- {
- my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NO_WAIT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NO_WAIT"));
lex->alter_tablespace_info->wait_until_completed= FALSE;
}
;
@@ -4218,23 +4686,14 @@ size_number:
case 'k':
case 'K': text_shift_number+=10; break;
default:
- {
- my_error(ER_WRONG_SIZE_NUMBER, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_SIZE_NUMBER, MYF(0)));
}
if (prefix_number >> 31)
- {
- my_error(ER_SIZE_OVERFLOW_ERROR, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SIZE_OVERFLOW_ERROR, MYF(0)));
number= prefix_number << text_shift_number;
}
else
- {
- my_error(ER_WRONG_SIZE_NUMBER, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_SIZE_NUMBER, MYF(0)));
$$= number;
}
;
@@ -4243,34 +4702,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.add(DDL_options_st::OPT_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. */
@@ -4278,21 +4726,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);}
@@ -4348,7 +4787,7 @@ partitioning:
PARTITION_SYM have_partitioning
{
LEX *lex= Lex;
- lex->part_info= new partition_info();
+ lex->part_info= new (thd->mem_root) partition_info();
if (!lex->part_info)
{
mem_alloc_error(sizeof(partition_info));
@@ -4356,7 +4795,7 @@ partitioning:
}
if (lex->sql_command == SQLCOM_ALTER_TABLE)
{
- lex->alter_info.flags|= ALTER_PARTITION;
+ lex->alter_info.flags|= Alter_info::ALTER_PARTITION;
}
}
partition
@@ -4368,15 +4807,11 @@ have_partitioning:
#ifdef WITH_PARTITION_STORAGE_ENGINE
LEX_STRING partition_name={C_STRING_WITH_LEN("partition")};
if (!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN))
- {
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
- "--skip-partition");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_OPTION_PREVENTS_STATEMENT, MYF(0),
+ "--skip-partition"));
#else
- my_error(ER_FEATURE_DISABLED, MYF(0), "partitioning",
- "--with-plugin-partition");
- MYSQL_YYABORT;
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), "partitioning",
+ "--with-plugin-partition"));
#endif
}
;
@@ -4387,7 +4822,7 @@ partition_entry:
LEX *lex= Lex;
if (!lex->part_info)
{
- my_parse_error(ER(ER_PARTITION_ENTRY_ERROR));
+ my_parse_error(thd, ER_PARTITION_ENTRY_ERROR);
MYSQL_YYABORT;
}
/*
@@ -4442,7 +4877,7 @@ opt_key_algo:
Lex->part_info->key_algorithm= partition_info::KEY_ALGORITHM_55;
break;
default:
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
}
@@ -4463,17 +4898,14 @@ part_field_item:
{
partition_info *part_info= Lex->part_info;
part_info->num_columns++;
- if (part_info->part_field_list.push_back($1.str))
+ if (part_info->part_field_list.push_back($1.str, thd->mem_root))
{
mem_alloc_error(1);
MYSQL_YYABORT;
}
if (part_info->num_columns > MAX_REF_PARTS)
- {
- my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
- "list of partition fields");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
+ "list of partition fields"));
}
;
@@ -4514,10 +4946,7 @@ opt_num_parts:
uint num_parts= $2;
partition_info *part_info= Lex->part_info;
if (num_parts == 0)
- {
- my_error(ER_NO_PARTS_ERROR, MYF(0), "partitions");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_NO_PARTS_ERROR, MYF(0), "partitions"));
part_info->num_parts= num_parts;
part_info->use_default_num_partitions= FALSE;
@@ -4548,17 +4977,14 @@ sub_part_field_item:
ident
{
partition_info *part_info= Lex->part_info;
- if (part_info->subpart_field_list.push_back($1.str))
+ if (part_info->subpart_field_list.push_back($1.str, thd->mem_root))
{
mem_alloc_error(1);
MYSQL_YYABORT;
}
if (part_info->subpart_field_list.elements > MAX_REF_PARTS)
- {
- my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
- "list of subpartition fields");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
+ "list of subpartition fields"));
}
;
@@ -4571,7 +4997,7 @@ part_func_expr:
lex->safe_to_cache_query= 1;
if (not_corr_func)
{
- my_parse_error(ER(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR));
+ my_parse_error(thd, ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR);
MYSQL_YYABORT;
}
$$=$1;
@@ -4585,10 +5011,7 @@ opt_num_subparts:
uint num_parts= $2;
LEX *lex= Lex;
if (num_parts == 0)
- {
- my_error(ER_NO_PARTS_ERROR, MYF(0), "subpartitions");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_NO_PARTS_ERROR, MYF(0), "subpartitions"));
lex->part_info->num_subparts= num_parts;
lex->part_info->use_default_num_subpartitions= FALSE;
}
@@ -4599,17 +5022,11 @@ part_defs:
{
partition_info *part_info= Lex->part_info;
if (part_info->part_type == RANGE_PARTITION)
- {
- my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
- "RANGE");
- MYSQL_YYABORT;
- }
- else if (part_info->part_type == LIST_PARTITION)
- {
- my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
- "LIST");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
+ "RANGE"));
+ if (part_info->part_type == LIST_PARTITION)
+ my_yyabort_error((ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
+ "LIST"));
}
| '(' part_def_list ')'
{
@@ -4620,7 +5037,7 @@ part_defs:
if (part_info->num_parts !=
count_curr_parts)
{
- my_parse_error(ER(ER_PARTITION_WRONG_NO_PART_ERROR));
+ my_parse_error(thd, ER_PARTITION_WRONG_NO_PART_ERROR);
MYSQL_YYABORT;
}
}
@@ -4641,9 +5058,10 @@ part_definition:
PARTITION_SYM
{
partition_info *part_info= Lex->part_info;
- partition_element *p_elem= new partition_element();
+ partition_element *p_elem= new (thd->mem_root) partition_element();
- if (!p_elem || part_info->partitions.push_back(p_elem))
+ if (!p_elem ||
+ part_info->partitions.push_back(p_elem, thd->mem_root))
{
mem_alloc_error(sizeof(partition_element));
MYSQL_YYABORT;
@@ -4692,11 +5110,8 @@ opt_part_values:
if (! lex->is_partition_management())
{
if (part_info->part_type != RANGE_PARTITION)
- {
- my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN"));
}
else
part_info->part_type= RANGE_PARTITION;
@@ -4709,11 +5124,8 @@ opt_part_values:
if (! lex->is_partition_management())
{
if (part_info->part_type != LIST_PARTITION)
- {
- my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "LIST", "IN");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "LIST", "IN"));
}
else
part_info->part_type= LIST_PARTITION;
@@ -4730,16 +5142,16 @@ part_func_max:
part_info->num_columns != 1U)
{
part_info->print_debug("Kilroy II", NULL);
- my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
+ my_parse_error(thd, ER_PARTITION_COLUMN_LIST_ERROR);
MYSQL_YYABORT;
}
else
part_info->num_columns= 1U;
- if (part_info->init_column_part())
+ if (part_info->init_column_part(thd))
{
MYSQL_YYABORT;
}
- if (part_info->add_max_value())
+ if (part_info->add_max_value(thd))
{
MYSQL_YYABORT;
}
@@ -4761,7 +5173,7 @@ part_values_in:
part_info->num_columns > MAX_REF_PARTS)
{
part_info->print_debug("Kilroy III", NULL);
- my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
+ my_parse_error(thd, ER_PARTITION_COLUMN_LIST_ERROR);
MYSQL_YYABORT;
}
/*
@@ -4771,7 +5183,7 @@ part_values_in:
we ADD or REORGANIZE partitions. Also can only happen
for LIST partitions.
*/
- if (part_info->reorganize_into_single_field_col_val())
+ if (part_info->reorganize_into_single_field_col_val(thd))
{
MYSQL_YYABORT;
}
@@ -4782,7 +5194,7 @@ part_values_in:
partition_info *part_info= Lex->part_info;
if (part_info->num_columns < 2U)
{
- my_parse_error(ER(ER_ROW_SINGLE_PARTITION_FIELD_ERROR));
+ my_parse_error(thd, ER_ROW_SINGLE_PARTITION_FIELD_ERROR);
MYSQL_YYABORT;
}
}
@@ -4801,7 +5213,7 @@ part_value_item:
/* Initialisation code needed for each list of value expressions */
if (!(part_info->part_type == LIST_PARTITION &&
part_info->num_columns == 1U) &&
- part_info->init_column_part())
+ part_info->init_column_part(thd))
{
MYSQL_YYABORT;
}
@@ -4823,7 +5235,7 @@ part_value_item:
error.
*/
part_info->print_debug("Kilroy I", NULL);
- my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
+ my_parse_error(thd, ER_PARTITION_COLUMN_LIST_ERROR);
MYSQL_YYABORT;
}
part_info->curr_list_object= 0;
@@ -4841,10 +5253,10 @@ part_value_expr_item:
partition_info *part_info= Lex->part_info;
if (part_info->part_type == LIST_PARTITION)
{
- my_parse_error(ER(ER_MAXVALUE_IN_VALUES_IN));
+ my_parse_error(thd, ER_MAXVALUE_IN_VALUES_IN);
MYSQL_YYABORT;
}
- if (part_info->add_max_value())
+ if (part_info->add_max_value(thd))
{
MYSQL_YYABORT;
}
@@ -4857,7 +5269,7 @@ part_value_expr_item:
if (!lex->safe_to_cache_query)
{
- my_parse_error(ER(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR));
+ my_parse_error(thd, ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR);
MYSQL_YYABORT;
}
if (part_info->add_column_list_value(thd, part_expr))
@@ -4879,7 +5291,7 @@ opt_sub_partition:
We come here when we have defined subpartitions on the first
partition but not on all the subsequent partitions.
*/
- my_parse_error(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR));
+ my_parse_error(thd, ER_PARTITION_WRONG_NO_SUBPART_ERROR);
MYSQL_YYABORT;
}
}
@@ -4891,7 +5303,7 @@ opt_sub_partition:
if (part_info->num_subparts !=
part_info->count_curr_subparts)
{
- my_parse_error(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR));
+ my_parse_error(thd, ER_PARTITION_WRONG_NO_SUBPART_ERROR);
MYSQL_YYABORT;
}
}
@@ -4899,7 +5311,7 @@ opt_sub_partition:
{
if (part_info->partitions.elements > 1)
{
- my_parse_error(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR));
+ my_parse_error(thd, ER_PARTITION_WRONG_NO_SUBPART_ERROR);
MYSQL_YYABORT;
}
part_info->num_subparts= part_info->count_curr_subparts;
@@ -4918,7 +5330,8 @@ sub_part_definition:
{
partition_info *part_info= Lex->part_info;
partition_element *curr_part= part_info->current_partition;
- partition_element *sub_p_elem= new partition_element(curr_part);
+ partition_element *sub_p_elem= new (thd->mem_root)
+ partition_element(curr_part);
if (part_info->use_default_subpartitions &&
part_info->partitions.elements >= 2)
{
@@ -4933,11 +5346,11 @@ sub_part_definition:
the second partition (the current partition processed
have already been put into the partitions list.
*/
- my_parse_error(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR));
+ my_parse_error(thd, ER_PARTITION_WRONG_NO_SUBPART_ERROR);
MYSQL_YYABORT;
}
if (!sub_p_elem ||
- curr_part->subpartitions.push_back(sub_p_elem))
+ curr_part->subpartitions.push_back(sub_p_elem, thd->mem_root))
{
mem_alloc_error(sizeof(partition_element));
MYSQL_YYABORT;
@@ -5022,7 +5435,7 @@ create_select:
{
Select->parsing_place= NO_MATTER;
}
- opt_select_from
+ table_expression
{
/*
The following work only with the local list, the global list
@@ -5052,24 +5465,38 @@ create_database_option:
| default_charset {}
;
-opt_table_options:
- /* empty */ { $$= 0; }
- | table_options { $$= $1;}
- ;
-
-table_options:
- table_option { $$=$1; }
- | table_option table_options { $$= $1 | $2; }
- ;
-
-table_option:
- TEMPORARY { $$=HA_LEX_CREATE_TMP_TABLE; }
- ;
+opt_if_not_exists_table_element:
+ /* empty */
+ {
+ Lex->check_exists= FALSE;
+ }
+ | IF_SYM not EXISTS
+ {
+ Lex->check_exists= TRUE;
+ }
+ ;
opt_if_not_exists:
- /* empty */ { $$= 0; }
- | IF not EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; }
- ;
+ /* empty */
+ {
+ $$.init();
+ }
+ | IF_SYM not EXISTS
+ {
+ $$.set(DDL_options_st::OPT_IF_NOT_EXISTS);
+ }
+ ;
+
+create_or_replace:
+ CREATE /* empty */
+ {
+ $$.init();
+ }
+ | CREATE OR_SYM REPLACE
+ {
+ $$.set(DDL_options_st::OPT_OR_REPLACE);
+ }
+ ;
opt_create_table_options:
/* empty */
@@ -5108,7 +5535,7 @@ create_table_option:
Lex->create_info.avg_row_length=$3;
Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;
}
- | PASSWORD opt_equal TEXT_STRING_sys
+ | PASSWORD_SYM opt_equal TEXT_STRING_sys
{
Lex->create_info.password=$3.str;
Lex->create_info.used_fields|= HA_CREATE_USED_PASSWORD;
@@ -5133,7 +5560,7 @@ create_table_option:
Lex->create_info.table_options|= HA_OPTION_PACK_KEYS;
break;
default:
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;
@@ -5144,6 +5571,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(thd, 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(thd, 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(thd, 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;
@@ -5180,7 +5671,7 @@ create_table_option:
from the global list.
*/
LEX *lex=Lex;
- lex->create_info.merge_list= lex->select_lex.table_list;
+ lex->create_info.merge_list= lex->select_lex.table_list.first;
lex->select_lex.table_list= lex->save_list;
/*
When excluding union list from the global list we assume that
@@ -5189,7 +5680,7 @@ create_table_option:
*/
TABLE_LIST *last_non_sel_table= lex->create_last_non_select_table;
DBUG_ASSERT(last_non_sel_table->next_global ==
- lex->create_info.merge_list.first);
+ lex->create_info.merge_list);
last_non_sel_table->next_global= 0;
Lex->query_tables_last= &last_non_sel_table->next_global;
@@ -5236,12 +5727,16 @@ create_table_option:
}
| IDENT_sys equal TEXT_STRING_sys
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, true, &Lex->create_info.option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, false, &Lex->create_info.option_list,
&Lex->option_list_last);
@@ -5263,18 +5758,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;
}
;
@@ -5298,21 +5783,19 @@ default_collation:
storage_engines:
ident_or_text
{
- plugin_ref plugin= ha_resolve_by_name(thd, &$1);
+ plugin_ref plugin= ha_resolve_by_name(thd, &$1,
+ thd->lex->create_info.tmp_table());
if (plugin)
- $$= plugin_data(plugin, handlerton*);
+ $$= plugin_hton(plugin);
else
{
if (thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION)
- {
- my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
$$= 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),
+ ER_THD(thd, ER_UNKNOWN_STORAGE_ENGINE),
$1.str);
}
}
@@ -5322,13 +5805,10 @@ known_storage_engines:
ident_or_text
{
plugin_ref plugin;
- if ((plugin= ha_resolve_by_name(thd, &$1)))
- $$= plugin_data(plugin, handlerton*);
+ if ((plugin= ha_resolve_by_name(thd, &$1, false)))
+ $$= plugin_hton(plugin);
else
- {
- my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
}
;
@@ -5348,11 +5828,6 @@ merge_insert_types:
| LAST_SYM { $$= MERGE_INSERT_TO_LAST; }
;
-opt_select_from:
- opt_limit_clause {}
- | select_from select_lock_type
- ;
-
udf_type:
STRING_SYM {$$ = (int) STRING_RESULT; }
| REAL {$$ = (int) REAL_RESULT; }
@@ -5381,66 +5856,90 @@ field_list_item:
column_def:
field_spec opt_check_constraint
| field_spec references
- {
- Lex->col_list.empty(); /* Alloced by sql_alloc */
- }
;
key_def:
- normal_key_type opt_ident key_alg '(' key_list ')'
- { Lex->option_list= NULL; }
- normal_key_options
+ key_or_index opt_if_not_exists opt_ident opt_USING_key_algorithm
+ {
+ Lex->option_list= NULL;
+ if (Lex->add_key(Key::MULTIPLE, $3, $4, $2))
+ MYSQL_YYABORT;
+ }
+ '(' key_list ')' normal_key_options { }
+ | key_or_index opt_if_not_exists ident TYPE_SYM btree_or_rtree
+ {
+ Lex->option_list= NULL;
+ if (Lex->add_key(Key::MULTIPLE, $3, $5, $2))
+ MYSQL_YYABORT;
+ }
+ '(' key_list ')' normal_key_options { }
+ | fulltext opt_key_or_index opt_if_not_exists opt_ident
{
- if (add_create_index (Lex, $1, $2))
+ Lex->option_list= NULL;
+ if (Lex->add_key($1, $4, HA_KEY_ALG_UNDEF, $3))
MYSQL_YYABORT;
}
- | fulltext opt_key_or_index opt_ident init_key_options
- '(' key_list ')'
- { Lex->option_list= NULL; }
- fulltext_key_options
+ '(' key_list ')' fulltext_key_options { }
+ | spatial opt_key_or_index opt_if_not_exists opt_ident
{
- if (add_create_index (Lex, $1, $3))
+ Lex->option_list= NULL;
+ if (Lex->add_key($1, $4, HA_KEY_ALG_UNDEF, $3))
MYSQL_YYABORT;
}
- | spatial opt_key_or_index opt_ident init_key_options
- '(' key_list ')'
- { Lex->option_list= NULL; }
- spatial_key_options
+ '(' key_list ')' spatial_key_options { }
+ | opt_constraint constraint_key_type
+ opt_if_not_exists opt_ident
+ opt_USING_key_algorithm
{
- if (add_create_index (Lex, $1, $3))
+ Lex->option_list= NULL;
+ if (Lex->add_key($2, $4.str ? $4 : $1, $5, $3))
MYSQL_YYABORT;
}
- | opt_constraint constraint_key_type opt_ident key_alg
- '(' key_list ')'
- { Lex->option_list= NULL; }
- normal_key_options
+ '(' key_list ')' normal_key_options { }
+ | opt_constraint constraint_key_type opt_if_not_exists ident
+ TYPE_SYM btree_or_rtree
{
- if (add_create_index (Lex, $2, $3.str ? $3 : $1))
+ Lex->option_list= NULL;
+ if (Lex->add_key($2, $4.str ? $4 : $1, $6, $3))
MYSQL_YYABORT;
}
- | opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
+ '(' key_list ')' normal_key_options { }
+ | opt_constraint FOREIGN KEY_SYM opt_if_not_exists opt_ident
+ {
+ if (Lex->check_add_key($4) ||
+ !(Lex->last_key= (new (thd->mem_root)
+ Key(Key::MULTIPLE, $1.str ? $1 : $5,
+ HA_KEY_ALG_UNDEF, true, $4))))
+ MYSQL_YYABORT;
+ Lex->option_list= NULL;
+ }
+ '(' key_list ')' references
{
LEX *lex=Lex;
- Key *key= new Foreign_key($4.str ? $4 : $1, lex->col_list,
- $8,
- lex->ref_list,
- lex->fk_delete_opt,
- lex->fk_update_opt,
- lex->fk_match_option);
+ Key *key= (new (thd->mem_root)
+ Foreign_key($5.str ? $5 : $1,
+ lex->last_key->columns,
+ $10->db,
+ $10->table,
+ lex->ref_list,
+ lex->fk_delete_opt,
+ lex->fk_update_opt,
+ lex->fk_match_option,
+ $4));
if (key == NULL)
MYSQL_YYABORT;
- lex->alter_info.key_list.push_back(key);
+ /*
+ handle_if_exists_options() expectes the two keys in this order:
+ the Foreign_key, followed by its auto-generated Key.
+ */
+ lex->alter_info.key_list.push_back(key, thd->mem_root);
+ lex->alter_info.key_list.push_back(Lex->last_key, thd->mem_root);
lex->option_list= NULL;
- if (add_create_index (lex, Key::MULTIPLE, $1.str ? $1 : $4,
- &default_key_create_info, 1))
- MYSQL_YYABORT;
+
/* Only used for ALTER TABLE. Ignored otherwise. */
- lex->alter_info.flags|= ALTER_FOREIGN_KEY;
- }
- | opt_constraint check_constraint
- {
- Lex->col_list.empty(); /* Alloced by sql_alloc */
+ lex->alter_info.flags|= Alter_info::ADD_FOREIGN_KEY;
}
+ | opt_constraint check_constraint { }
;
opt_check_constraint:
@@ -5465,58 +5964,59 @@ field_spec:
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->vcol_info= 0;
- lex->option_list= NULL;
+ Create_field *f= new (thd->mem_root) Create_field();
+
+ if (check_string_char_length(&$1, 0, NAME_CHAR_LEN,
+ system_charset_info, 1))
+ my_yyabort_error((ER_TOO_LONG_IDENT, MYF(0), $1.str));
+
+ if (!f)
+ MYSQL_YYABORT;
+
+ lex->init_last_field(f, $1.str, NULL);
}
+ field_type { Lex->set_last_field_type($3); }
field_def
{
LEX *lex=Lex;
- if (add_field_to_list(lex->thd, &$1, $3.type,
- $3.length, $3.dec, lex->type,
- lex->default_value, lex->on_update_value,
- &lex->comment,
- lex->change, &lex->interval_list, $3.charset,
- lex->uint_geom_type,
- lex->vcol_info, lex->option_list))
+ Create_field *f= lex->last_field;
+
+ if (f->check(thd))
MYSQL_YYABORT;
+
+ lex->alter_info.create_list.push_back(f, thd->mem_root);
+
+ if (f->flags & PRI_KEY_FLAG)
+ add_key_to_list(lex, &$1, Key::PRIMARY, Lex->check_exists);
+ else if (f->flags & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
+ add_key_to_list(lex, &$1, Key::UNIQUE, Lex->check_exists);
}
;
field_def:
- type opt_attribute
- { $$.set($1, Lex->length, Lex->dec, Lex->charset); }
- | type opt_generated_always AS
- { $<lex_type>$.set($1, Lex->length, Lex->dec, Lex->charset); }
- '(' virtual_column_func ')' vcol_opt_specifier vcol_opt_attribute
- {
- $$= $<lex_type>4;
- Lex->vcol_info->set_field_type($$.type);
- $$.type= (enum enum_field_types)MYSQL_TYPE_VIRTUAL;
- }
+ opt_attribute
+ | opt_generated_always AS
+ '(' virtual_column_func ')'
+ vcol_opt_specifier vcol_opt_attribute
;
opt_generated_always:
- /* empty */
+ /* empty */ {}
| GENERATED_SYM ALWAYS_SYM {}
;
vcol_opt_specifier:
/* empty */
{
- Lex->vcol_info->set_stored_in_db_flag(FALSE);
+ Lex->last_field->vcol_info->set_stored_in_db_flag(FALSE);
}
| VIRTUAL_SYM
{
- Lex->vcol_info->set_stored_in_db_flag(FALSE);
+ Lex->last_field->vcol_info->set_stored_in_db_flag(FALSE);
}
| PERSISTENT_SYM
{
- Lex->vcol_info->set_stored_in_db_flag(TRUE);
+ Lex->last_field->vcol_info->set_stored_in_db_flag(TRUE);
}
;
@@ -5534,16 +6034,16 @@ vcol_attribute:
UNIQUE_SYM
{
LEX *lex=Lex;
- lex->type|= UNIQUE_FLAG;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
+ lex->last_field->flags|= UNIQUE_FLAG;
+ 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->last_field->flags|= UNIQUE_FLAG;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
- | COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
+ | COMMENT_SYM TEXT_STRING_sys { Lex->last_field->comment= $2; }
;
parse_vcol_expr:
@@ -5555,33 +6055,45 @@ parse_vcol_expr:
Prevent the end user from invoking this command.
*/
if (!Lex->parse_vcol_expr)
- {
- my_message(ER_SYNTAX_ERROR, ER(ER_SYNTAX_ERROR), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SYNTAX_ERROR, MYF(0)));
}
;
virtual_column_func:
remember_name expr remember_end
{
- Lex->vcol_info= new Virtual_column_info();
- if (!Lex->vcol_info)
+ Virtual_column_info *v= new (thd->mem_root) Virtual_column_info();
+ if (!v)
{
mem_alloc_error(sizeof(Virtual_column_info));
MYSQL_YYABORT;
}
uint expr_len= (uint)($3 - $1) - 1;
- Lex->vcol_info->expr_str.str= (char* ) sql_memdup($1 + 1, expr_len);
- Lex->vcol_info->expr_str.length= expr_len;
- Lex->vcol_info->expr_item= $2;
+ v->expr_str.str= (char* ) thd->memdup($1 + 1, expr_len);
+ v->expr_str.length= expr_len;
+ v->expr_item= $2;
+ Lex->last_field->vcol_info= v;
}
;
-type:
+field_type:
int_type opt_field_length field_options { $$=$1; }
| real_type opt_precision field_options { $$=$1; }
- | FLOAT_SYM float_options field_options { $$=MYSQL_TYPE_FLOAT; }
+ | FLOAT_SYM float_options field_options
+ {
+ $$=MYSQL_TYPE_FLOAT;
+ if (Lex->length && !Lex->dec)
+ {
+ int err;
+ ulonglong tmp_length= my_strtoll10(Lex->length, NULL, &err);
+ if (err || tmp_length > PRECISION_FOR_DOUBLE)
+ my_yyabort_error((ER_WRONG_FIELD_SPEC, MYF(0),
+ Lex->last_field->field_name));
+ if (tmp_length > PRECISION_FOR_FLOAT)
+ $$= MYSQL_TYPE_DOUBLE;
+ Lex->length= 0;
+ }
+ }
| BIT_SYM
{
Lex->length= (char*) "1";
@@ -5613,13 +6125,13 @@ type:
| nchar field_length opt_bin_mod
{
$$=MYSQL_TYPE_STRING;
- Lex->charset=national_charset_info;
+ bincmp_collation(national_charset_info, $3);
}
| nchar opt_bin_mod
{
Lex->length= (char*) "1";
$$=MYSQL_TYPE_STRING;
- Lex->charset=national_charset_info;
+ bincmp_collation(national_charset_info, $2);
}
| BINARY field_length
{
@@ -5639,7 +6151,7 @@ type:
| nvarchar field_length opt_bin_mod
{
$$= MYSQL_TYPE_VARCHAR;
- Lex->charset=national_charset_info;
+ bincmp_collation(national_charset_info, $3);
}
| VARBINARY field_length
{
@@ -5656,9 +6168,9 @@ 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),
+ ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX),
buff, "YEAR(4)");
}
}
@@ -5667,22 +6179,28 @@ type:
| DATE_SYM
{ $$=MYSQL_TYPE_DATE; }
| TIME_SYM opt_field_length
- { $$=MYSQL_TYPE_TIME; }
+ { $$= opt_mysql56_temporal_format ?
+ MYSQL_TYPE_TIME2 : MYSQL_TYPE_TIME; }
| TIMESTAMP opt_field_length
{
if (thd->variables.sql_mode & MODE_MAXDB)
- $$=MYSQL_TYPE_DATETIME;
+ $$= opt_mysql56_temporal_format ?
+ MYSQL_TYPE_DATETIME2 : MYSQL_TYPE_DATETIME;
else
{
/*
Unlike other types TIMESTAMP fields are NOT NULL by default.
+ Unless --explicit-defaults-for-timestamp is given.
*/
- Lex->type|= NOT_NULL_FLAG;
- $$=MYSQL_TYPE_TIMESTAMP;
+ if (!opt_explicit_defaults_for_timestamp)
+ Lex->last_field->flags|= NOT_NULL_FLAG;
+ $$= opt_mysql56_temporal_format ? MYSQL_TYPE_TIMESTAMP2
+ : MYSQL_TYPE_TIMESTAMP;
}
}
| DATETIME opt_field_length
- { $$=MYSQL_TYPE_DATETIME; }
+ { $$= opt_mysql56_temporal_format ?
+ MYSQL_TYPE_DATETIME2 : MYSQL_TYPE_DATETIME; }
| TINYBLOB
{
Lex->charset=&my_charset_bin;
@@ -5693,16 +6211,15 @@ type:
Lex->charset=&my_charset_bin;
$$=MYSQL_TYPE_BLOB;
}
- | spatial_type
+ | spatial_type float_options srid_option
{
#ifdef HAVE_SPATIAL
Lex->charset=&my_charset_bin;
- Lex->uint_geom_type= (uint)$1;
+ Lex->last_field->geom_type= $1;
$$=MYSQL_TYPE_GEOMETRY;
#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
- MYSQL_YYABORT;
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
+ sym_group_geom.needed_define));
#endif
}
| MEDIUMBLOB
@@ -5736,20 +6253,16 @@ type:
{ $$=MYSQL_TYPE_NEWDECIMAL;}
| FIXED_SYM float_options field_options
{ $$=MYSQL_TYPE_NEWDECIMAL;}
- | ENUM
- {Lex->interval_list.empty();}
- '(' string_list ')' opt_binary
+ | ENUM '(' string_list ')' opt_binary
{ $$=MYSQL_TYPE_ENUM; }
- | SET
- { Lex->interval_list.empty();}
- '(' string_list ')' opt_binary
+ | SET '(' string_list ')' opt_binary
{ $$=MYSQL_TYPE_SET; }
| LONG_SYM opt_binary
{ $$=MYSQL_TYPE_MEDIUM_BLOB; }
| SERIAL_SYM
{
$$=MYSQL_TYPE_LONGLONG;
- Lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNSIGNED_FLAG |
+ Lex->last_field->flags|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNSIGNED_FLAG |
UNIQUE_FLAG);
}
;
@@ -5812,6 +6325,16 @@ real_type:
{ $$=MYSQL_TYPE_DOUBLE; }
;
+srid_option:
+ /* empty */
+ { Lex->last_field->srid= 0; }
+ |
+ REF_SYSTEM_ID_SYM '=' NUM
+ {
+ Lex->last_field->srid=atoi($3.str);
+ }
+ ;
+
float_options:
/* empty */
{ Lex->dec=Lex->length= (char*)0; }
@@ -5842,8 +6365,8 @@ field_opt_list:
field_option:
SIGNED_SYM {}
- | UNSIGNED { Lex->type|= UNSIGNED_FLAG;}
- | ZEROFILL { Lex->type|= UNSIGNED_FLAG | ZEROFILL_FLAG; }
+ | UNSIGNED { Lex->last_field->flags|= UNSIGNED_FLAG;}
+ | ZEROFILL { Lex->last_field->flags|= UNSIGNED_FLAG | ZEROFILL_FLAG; }
;
field_length:
@@ -5873,106 +6396,98 @@ opt_attribute_list:
;
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
+ NULL_SYM { Lex->last_field->flags&= ~ NOT_NULL_FLAG; }
+ | not NULL_SYM { Lex->last_field->flags|= NOT_NULL_FLAG; }
+ | DEFAULT now_or_signed_literal { Lex->last_field->def= $2; }
+ | 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(thd, $4);
if (item == NULL)
MYSQL_YYABORT;
- Lex->on_update_value= item;
+ Lex->last_field->on_update= item;
}
- | AUTO_INC { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
+ | AUTO_INC { Lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
| SERIAL_SYM DEFAULT VALUE_SYM
{
LEX *lex=Lex;
- lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG;
- lex->alter_info.flags|= ALTER_ADD_INDEX;
+ lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG;
+ 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->last_field->flags|= PRI_KEY_FLAG | NOT_NULL_FLAG;
+ 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->last_field->flags|= UNIQUE_FLAG;
+ 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->last_field->flags|= UNIQUE_KEY_FLAG;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
- | COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
+ | COMMENT_SYM TEXT_STRING_sys { Lex->last_field->comment= $2; }
| COLLATE_SYM collation_name
{
if (Lex->charset && !my_charset_same(Lex->charset,$2))
- {
- my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- $2->name,Lex->charset->csname);
- MYSQL_YYABORT;
- }
- else
- {
- Lex->charset=$2;
- }
+ my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $2->name,Lex->charset->csname));
+ Lex->last_field->charset= $2;
}
| IDENT_sys equal TEXT_STRING_sys
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
- engine_option_value($1, $3, true, &Lex->option_list,
+ engine_option_value($1, $3, true, &Lex->last_field->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
- engine_option_value($1, $3, false, &Lex->option_list,
+ engine_option_value($1, $3, false, &Lex->last_field->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal real_ulonglong_num
{
new (thd->mem_root)
- engine_option_value($1, $3, &Lex->option_list,
+ engine_option_value($1, $3, &Lex->last_field->option_list,
&Lex->option_list_last, thd->mem_root);
}
| IDENT_sys equal DEFAULT
{
new (thd->mem_root)
- engine_option_value($1, &Lex->option_list, &Lex->option_list_last);
+ engine_option_value($1, &Lex->last_field->option_list, &Lex->option_list_last);
}
;
type_with_opt_collate:
- type opt_collate
+ field_type opt_collate
{
$$= $1;
- if (Lex->charset) /* Lex->charset is scanned in "type" */
+ if ($2)
{
if (!(Lex->charset= merge_charset_and_collation(Lex->charset, $2)))
MYSQL_YYABORT;
}
- else if ($2)
- {
- my_error(ER_NOT_SUPPORTED_YET, MYF(0),
- "COLLATE with no CHARACTER SET "
- "in SP parameters, RETURNS, DECLARE");
- MYSQL_YYABORT;
- }
+ Lex->set_last_field_type($1);
}
;
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(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -5980,11 +6495,6 @@ now_or_signed_literal:
{ $$=$1; }
;
-hex_num_or_string:
- HEX_NUM {}
- | HEX_STRING {}
- ;
-
charset:
CHAR_SYM SET {}
| CHARSET {}
@@ -5994,10 +6504,7 @@ charset_name:
ident_or_text
{
if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))))
- {
- my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str));
}
| BINARY { $$= &my_charset_bin; }
;
@@ -6017,10 +6524,7 @@ old_or_new_charset_name:
{
if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))) &&
!($$=get_old_charset_by_name($1.str)))
- {
- my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str));
}
| BINARY { $$= &my_charset_bin; }
;
@@ -6033,11 +6537,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;
- }
}
;
@@ -6056,70 +6557,96 @@ opt_default:
| DEFAULT {}
;
-
-ascii:
- ASCII_SYM { Lex->charset= &my_charset_latin1; }
- | BINARY ASCII_SYM
- {
- Lex->charset= &my_charset_latin1_bin;
- }
- | ASCII_SYM BINARY
+charset_or_alias:
+ charset charset_name { $$= $2; }
+ | ASCII_SYM { $$= &my_charset_latin1; }
+ | UNICODE_SYM
{
- Lex->charset= &my_charset_latin1_bin;
+ if (!($$= get_charset_by_csname("ucs2", MY_CS_PRIMARY,MYF(0))))
+ my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2"));
}
;
-unicode:
- UNICODE_SYM
- {
- if (!(Lex->charset=get_charset_by_csname("ucs2",
- MY_CS_PRIMARY,MYF(0))))
- {
- my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2");
- MYSQL_YYABORT;
- }
- }
- | UNICODE_SYM BINARY
- {
- if (!(Lex->charset=get_charset_by_name("ucs2_bin", MYF(0))))
- {
- my_error(ER_UNKNOWN_COLLATION, MYF(0), "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");
- MYSQL_YYABORT;
- }
- }
+opt_binary:
+ /* empty */ { bincmp_collation(NULL, false); }
+ | BYTE_SYM { bincmp_collation(&my_charset_bin, false); }
+ | charset_or_alias opt_bin_mod { bincmp_collation($1, $2); }
+ | BINARY { bincmp_collation(NULL, true); }
+ | BINARY charset_or_alias { bincmp_collation($2, true); }
;
-opt_binary:
- /* empty */ { Lex->charset=NULL; }
- | ascii
- | unicode
- | BYTE_SYM { Lex->charset=&my_charset_bin; }
- | charset charset_name opt_bin_mod { Lex->charset=$2; }
- | BINARY
- {
- Lex->charset= NULL;
- Lex->type|= BINCMP_FLAG;
- }
- | BINARY charset charset_name
+opt_bin_mod:
+ /* empty */ { $$= false; }
+ | BINARY { $$= true; }
+ ;
+
+ws_nweights:
+ '(' real_ulong_num
+ {
+ if ($2 == 0)
{
- Lex->charset= $3;
- Lex->type|= BINCMP_FLAG;
+ my_parse_error(thd, ER_SYNTAX_ERROR);
+ MYSQL_YYABORT;
}
+ }
+ ')'
+ { $$= $2; }
;
-opt_bin_mod:
- /* empty */ { }
- | BINARY { Lex->type|= BINCMP_FLAG; }
+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 */
@@ -6146,19 +6673,19 @@ opt_ref_list:
ref_list:
ref_list ',' ident
{
- Key_part_spec *key= new Key_part_spec($3, 0);
+ Key_part_spec *key= new (thd->mem_root) Key_part_spec($3, 0);
if (key == NULL)
MYSQL_YYABORT;
- Lex->ref_list.push_back(key);
+ Lex->ref_list.push_back(key, thd->mem_root);
}
| ident
{
- Key_part_spec *key= new Key_part_spec($1, 0);
+ Key_part_spec *key= new (thd->mem_root) Key_part_spec($1, 0);
if (key == NULL)
MYSQL_YYABORT;
LEX *lex= Lex;
lex->ref_list.empty();
- lex->ref_list.push_back(key);
+ lex->ref_list.push_back(key, thd->mem_root);
}
;
@@ -6177,19 +6704,19 @@ opt_on_update_delete:
/* empty */
{
LEX *lex= Lex;
- lex->fk_update_opt= Foreign_key::FK_OPTION_UNDEF;
- lex->fk_delete_opt= Foreign_key::FK_OPTION_UNDEF;
+ lex->fk_update_opt= FK_OPTION_UNDEF;
+ lex->fk_delete_opt= FK_OPTION_UNDEF;
}
| ON UPDATE_SYM delete_option
{
LEX *lex= Lex;
lex->fk_update_opt= $3;
- lex->fk_delete_opt= Foreign_key::FK_OPTION_UNDEF;
+ lex->fk_delete_opt= FK_OPTION_UNDEF;
}
| ON DELETE_SYM delete_option
{
LEX *lex= Lex;
- lex->fk_update_opt= Foreign_key::FK_OPTION_UNDEF;
+ lex->fk_update_opt= FK_OPTION_UNDEF;
lex->fk_delete_opt= $3;
}
| ON UPDATE_SYM delete_option
@@ -6209,15 +6736,11 @@ opt_on_update_delete:
;
delete_option:
- RESTRICT { $$= Foreign_key::FK_OPTION_RESTRICT; }
- | CASCADE { $$= Foreign_key::FK_OPTION_CASCADE; }
- | SET NULL_SYM { $$= Foreign_key::FK_OPTION_SET_NULL; }
- | NO_SYM ACTION { $$= Foreign_key::FK_OPTION_NO_ACTION; }
- | SET DEFAULT { $$= Foreign_key::FK_OPTION_DEFAULT; }
- ;
-
-normal_key_type:
- key_or_index { $$= Key::MULTIPLE; }
+ RESTRICT { $$= FK_OPTION_RESTRICT; }
+ | CASCADE { $$= FK_OPTION_CASCADE; }
+ | SET NULL_SYM { $$= FK_OPTION_SET_NULL; }
+ | NO_SYM ACTION { $$= FK_OPTION_NO_ACTION; }
+ | SET DEFAULT { $$= FK_OPTION_SET_DEFAULT; }
;
constraint_key_type:
@@ -6256,43 +6779,25 @@ spatial:
#ifdef HAVE_SPATIAL
$$= Key::SPATIAL;
#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
- MYSQL_YYABORT;
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
+ sym_group_geom.needed_define));
#endif
}
;
-init_key_options:
- {
- Lex->key_create_info= default_key_create_info;
- }
- ;
-
-/*
- For now, key_alg initializies lex->key_create_info.
- In the future, when all key options are after key definition,
- we can remove key_alg and move init_key_options to key_options
-*/
-
-key_alg:
- init_key_options
- | init_key_options key_using_alg
- ;
-
normal_key_options:
/* empty */ {}
- | normal_key_opts
+ | normal_key_opts { Lex->last_key->option_list= Lex->option_list; }
;
fulltext_key_options:
/* empty */ {}
- | fulltext_key_opts
+ | fulltext_key_opts { Lex->last_key->option_list= Lex->option_list; }
;
spatial_key_options:
/* empty */ {}
- | spatial_key_opts
+ | spatial_key_opts { Lex->last_key->option_list= Lex->option_list; }
;
normal_key_opts:
@@ -6310,23 +6815,40 @@ fulltext_key_opts:
| fulltext_key_opts fulltext_key_opt
;
+opt_USING_key_algorithm:
+ /* Empty*/ { $$= HA_KEY_ALG_UNDEF; }
+ | USING btree_or_rtree { $$= $2; }
+
+/* TYPE is a valid identifier, so it's handled differently than USING */
+opt_key_algorithm_clause:
+ /* Empty*/ { $$= HA_KEY_ALG_UNDEF; }
+ | USING btree_or_rtree { $$= $2; }
+ | TYPE_SYM btree_or_rtree { $$= $2; }
+
key_using_alg:
- USING btree_or_rtree { Lex->key_create_info.algorithm= $2; }
- | TYPE_SYM btree_or_rtree { Lex->key_create_info.algorithm= $2; }
+ USING btree_or_rtree
+ { Lex->last_key->key_create_info.algorithm= $2; }
+ | TYPE_SYM btree_or_rtree
+ { Lex->last_key->key_create_info.algorithm= $2; }
;
all_key_opt:
KEY_BLOCK_SIZE opt_equal ulong_num
- { Lex->key_create_info.block_size= $3; }
- | COMMENT_SYM TEXT_STRING_sys { Lex->key_create_info.comment= $2; }
+ { Lex->last_key->key_create_info.block_size= $3; }
+ | COMMENT_SYM TEXT_STRING_sys
+ { Lex->last_key->key_create_info.comment= $2; }
| IDENT_sys equal TEXT_STRING_sys
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, true, &Lex->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, false, &Lex->option_list,
&Lex->option_list_last);
@@ -6358,12 +6880,9 @@ fulltext_key_opt:
| WITH PARSER_SYM IDENT_sys
{
if (plugin_is_ready(&$3, MYSQL_FTPARSER_PLUGIN))
- Lex->key_create_info.parser_name= $3;
+ Lex->last_key->key_create_info.parser_name= $3;
else
- {
- my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str));
}
;
@@ -6374,14 +6893,20 @@ btree_or_rtree:
;
key_list:
- key_list ',' key_part order_dir { Lex->col_list.push_back($3); }
- | key_part order_dir { Lex->col_list.push_back($1); }
+ key_list ',' key_part order_dir
+ {
+ Lex->last_key->columns.push_back($3, thd->mem_root);
+ }
+ | key_part order_dir
+ {
+ Lex->last_key->columns.push_back($1, thd->mem_root);
+ }
;
key_part:
ident
{
- $$= new Key_part_spec($1, 0);
+ $$= new (thd->mem_root) Key_part_spec($1, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -6389,10 +6914,8 @@ key_part:
{
int key_part_len= atoi($3.str);
if (!key_part_len)
- {
- my_error(ER_KEY_PART_0, MYF(0), $1.str);
- }
- $$= new Key_part_spec($1, (uint) key_part_len);
+ my_yyabort_error((ER_KEY_PART_0, MYF(0), $1.str));
+ $$= new (thd->mem_root) Key_part_spec($1, (uint) key_part_len);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -6409,47 +6932,47 @@ opt_component:
;
string_list:
- text_string { Lex->interval_list.push_back($1); }
- | string_list ',' text_string { Lex->interval_list.push_back($3); };
+ text_string
+ { Lex->last_field->interval_list.push_back($1, thd->mem_root); }
+ | string_list ',' text_string
+ { Lex->last_field->interval_list.push_back($3, thd->mem_root); };
/*
** Alter table
*/
alter:
- ALTER alter_options TABLE_SYM table_ident
+ ALTER
+ {
+ Lex->name= null_lex_str;
+ Lex->only_view= FALSE;
+ Lex->sql_command= SQLCOM_ALTER_TABLE;
+ Lex->duplicates= DUP_ERROR;
+ Lex->select_lex.init_order();
+ Lex->create_info.init();
+ 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;
}
}
@@ -6471,10 +6994,7 @@ alter:
{
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "DATABASE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "DATABASE"));
lex->sql_command= SQLCOM_ALTER_DB_UPGRADE;
lex->name= $3;
}
@@ -6483,10 +7003,7 @@ alter:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_a_chistics
@@ -6501,10 +7018,7 @@ alter:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_a_chistics
@@ -6519,10 +7033,7 @@ alter:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW"));
lex->create_view_mode= VIEW_ALTER;
}
view_tail
@@ -6537,16 +7048,13 @@ alter:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW"));
lex->create_view_algorithm= VIEW_ALGORITHM_INHERIT;
lex->create_view_mode= VIEW_ALTER;
}
view_tail
{}
- | ALTER definer_opt EVENT_SYM sp_name
+ | ALTER definer_opt remember_name EVENT_SYM sp_name
{
/*
It is safe to use Lex->spname because
@@ -6558,9 +7066,10 @@ alter:
if (!(Lex->event_parse_data= Event_parse_data::new_instance(thd)))
MYSQL_YYABORT;
- Lex->event_parse_data->identifier= $4;
+ Lex->event_parse_data->identifier= $5;
Lex->sql_command= SQLCOM_ALTER_EVENT;
+ Lex->stmt_definition_begin= $3;
}
ev_alter_on_schedule_completion
opt_ev_rename_to
@@ -6568,9 +7077,9 @@ alter:
opt_ev_comment
opt_ev_sql_stmt
{
- if (!($6 || $7 || $8 || $9 || $10))
+ if (!($7 || $8 || $9 || $10 || $11))
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
/*
@@ -6578,6 +7087,7 @@ alter:
can overwrite it
*/
Lex->sql_command= SQLCOM_ALTER_EVENT;
+ Lex->stmt_definition_end= (char*)YYLIP->get_cpp_ptr();
}
| ALTER TABLESPACE alter_tablespace_info
{
@@ -6599,13 +7109,12 @@ alter:
LEX *lex= Lex;
lex->alter_tablespace_info->ts_cmd_type= ALTER_ACCESS_MODE_TABLESPACE;
}
- | ALTER SERVER_SYM ident_or_text OPTIONS_SYM '(' server_options_list ')'
+ | ALTER SERVER_SYM ident_or_text
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_ALTER_SERVER;
- lex->server_options.server_name= $3.str;
- lex->server_options.server_name_length= $3.length;
- }
+ lex->server_options.reset($3);
+ } OPTIONS_SYM '(' server_options_list ')' { }
;
ev_alter_on_schedule_completion:
@@ -6634,14 +7143,28 @@ opt_ev_sql_stmt:
;
ident_or_empty:
- /* empty */ { $$.str= 0; $$.length= 0; }
+ /* empty */ { $$= null_lex_str; }
| ident { $$= $1; }
;
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
@@ -6653,19 +7176,20 @@ 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;
+ DBUG_ASSERT(!Lex->if_exists());
+ Lex->create_info.add($3);
}
| 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
@@ -6674,10 +7198,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
@@ -6687,20 +7211,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
@@ -6710,17 +7234,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;
}
@@ -6728,42 +7252,69 @@ 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();
+ lex->part_info= new (thd->mem_root) partition_info();
if (!lex->part_info)
{
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;
+ DBUG_ASSERT(!Lex->create_info.if_not_exists());
+ lex->create_info.set($3);
+ lex->no_write_to_binlog= $4;
}
add_part_extra
{}
@@ -6786,7 +7337,7 @@ reorg_partition_rule:
REORGANIZE_SYM PARTITION_SYM opt_no_write_to_binlog
{
LEX *lex= Lex;
- lex->part_info= new partition_info();
+ lex->part_info= new (thd->mem_root) partition_info();
if (!lex->part_info)
{
mem_alloc_error(sizeof(partition_info));
@@ -6800,11 +7351,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 ')'
{
@@ -6821,7 +7372,8 @@ alt_part_name_list:
alt_part_name_item:
ident
{
- if (Lex->alter_info.partition_names.push_back($1.str))
+ if (Lex->alter_info.partition_names.push_back($1.str,
+ thd->mem_root))
{
mem_alloc_error(1);
MYSQL_YYABORT;
@@ -6839,11 +7391,10 @@ alter_list:
;
add_column:
- ADD opt_column
+ ADD opt_column opt_if_not_exists_table_element
{
LEX *lex=Lex;
- lex->change=0;
- lex->alter_info.flags|= ALTER_ADD_COLUMN;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN;
}
;
@@ -6855,111 +7406,98 @@ 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;
- }
- | CHANGE opt_column field_ident
- {
- LEX *lex=Lex;
- lex->change= $3.str;
- lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
- lex->option_list= NULL;
+ Lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN |
+ Alter_info::ALTER_ADD_INDEX;
}
+ | CHANGE opt_column opt_if_exists_table_element field_ident
field_spec opt_place
{
+ Lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
Lex->create_last_non_select_table= Lex->last_table();
+ Lex->last_field->change= $4.str;
}
- | MODIFY_SYM opt_column field_ident
+ | MODIFY_SYM opt_column opt_if_exists_table_element
+ field_spec opt_place
{
- 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->vcol_info= 0;
- lex->option_list= NULL;
+ Lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
+ Lex->create_last_non_select_table= Lex->last_table();
+ Lex->last_field->change= Lex->last_field->field_name;
}
- field_def
+ | DROP opt_column opt_if_exists_table_element field_ident opt_restrict
{
LEX *lex=Lex;
- if (add_field_to_list(lex->thd,&$3,
- $5.type,
- $5.length, $5.dec, lex->type,
- lex->default_value, lex->on_update_value,
- &lex->comment,
- $3.str, &lex->interval_list, $5.charset,
- lex->uint_geom_type,
- lex->vcol_info, lex->option_list))
+ Alter_drop *ad= (new (thd->mem_root)
+ Alter_drop(Alter_drop::COLUMN, $4.str, $3));
+ if (ad == NULL)
MYSQL_YYABORT;
+ lex->alter_info.drop_list.push_back(ad, thd->mem_root);
+ lex->alter_info.flags|= Alter_info::ALTER_DROP_COLUMN;
}
- opt_place
- {
- Lex->create_last_non_select_table= Lex->last_table();
- }
- | DROP opt_column field_ident opt_restrict
+ | DROP FOREIGN KEY_SYM opt_if_exists_table_element field_ident
{
LEX *lex=Lex;
- Alter_drop *ad= new Alter_drop(Alter_drop::COLUMN, $3.str);
+ Alter_drop *ad= (new (thd->mem_root)
+ 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_DROP_COLUMN;
- }
- | DROP FOREIGN KEY_SYM opt_ident
- {
- Lex->alter_info.flags|= ALTER_DROP_INDEX | ALTER_FOREIGN_KEY;
+ lex->alter_info.drop_list.push_back(ad, thd->mem_root);
+ 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 (thd->mem_root)
+ 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.drop_list.push_back(ad, thd->mem_root);
+ lex->alter_info.flags|= Alter_info::ALTER_DROP_INDEX;
}
- | DROP key_or_index field_ident
+ | DROP key_or_index opt_if_exists_table_element field_ident
{
LEX *lex=Lex;
- Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $3.str);
+ Alter_drop *ad= (new (thd->mem_root)
+ 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.drop_list.push_back(ad, thd->mem_root);
+ 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
{
LEX *lex=Lex;
- Alter_column *ac= new Alter_column($3.str,$6);
+ Alter_column *ac= new (thd->mem_root) Alter_column($3.str,$6);
if (ac == NULL)
MYSQL_YYABORT;
- lex->alter_info.alter_list.push_back(ac);
- lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT;
+ lex->alter_info.alter_list.push_back(ac, thd->mem_root);
+ lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN_DEFAULT;
}
| ALTER opt_column field_ident DROP DEFAULT
{
LEX *lex=Lex;
- Alter_column *ac= new Alter_column($3.str, (Item*) 0);
+ Alter_column *ac= (new (thd->mem_root)
+ Alter_column($3.str, (Item*) 0));
if (ac == NULL)
MYSQL_YYABORT;
- lex->alter_info.alter_list.push_back(ac);
- lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT;
+ lex->alter_info.alter_list.push_back(ac, thd->mem_root);
+ lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN_DEFAULT;
}
| RENAME opt_to table_ident
{
@@ -6973,12 +7511,9 @@ alter_list_item:
}
if (check_table_name($3->table.str,$3->table.length, FALSE) ||
($3->db.str && check_db_name(&$3->db)))
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $3->table.str));
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
{
@@ -6988,22 +7523,16 @@ alter_list_item:
}
$5= $5 ? $5 : $4;
if (!my_charset_same($4,$5))
- {
- my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- $5->name, $4->csname);
+ my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $5->name, $4->csname));
+ if (Lex->create_info.add_alter_list_item_convert_to_charset($5))
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;
+ Lex->alter_info.flags|= Alter_info::ALTER_OPTIONS;
}
| 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)
{
@@ -7012,12 +7541,47 @@ 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_yyabort_error((ER_UNKNOWN_ALTER_ALGORITHM, MYF(0), $3.str));
+ }
+ ;
+
+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_yyabort_error((ER_UNKNOWN_ALTER_LOCK, MYF(0), $3.str));
}
;
@@ -7032,7 +7596,7 @@ opt_ignore:
;
alter_options:
- { Lex->ignore= Lex->online= 0;} alter_options_part2
+ { Lex->ignore= 0;} alter_options_part2
;
alter_options_part2:
@@ -7047,7 +7611,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:
@@ -7058,8 +7626,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:
@@ -7069,12 +7645,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;
@@ -7083,44 +7655,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(thd, 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:
@@ -7149,11 +7757,11 @@ slave_until:
(lex->mi.relay_log_name || lex->mi.relay_log_pos)) ||
!((lex->mi.log_file_name && lex->mi.pos) ||
(lex->mi.relay_log_name && lex->mi.relay_log_pos)))
- {
- my_message(ER_BAD_SLAVE_UNTIL_COND,
- ER(ER_BAD_SLAVE_UNTIL_COND), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_BAD_SLAVE_UNTIL_COND, MYF(0)));
+ }
+ | UNTIL_SYM MASTER_GTID_POS_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.gtid_pos_str = $4;
}
;
@@ -7199,9 +7807,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;
}
;
@@ -7238,23 +7846,121 @@ 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 (thd->mem_root) 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 (thd->mem_root) 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*)
+ thd->memdup(&$1, sizeof(LEX_STRING)), thd->mem_root);
+ }
+ | table_column_list ',' ident
+ {
+ Lex->column_list->push_back((LEX_STRING*)
+ thd->memdup(&$3, sizeof(LEX_STRING)), thd->mem_root);
+ }
+ ;
+
+table_index_list:
+ /* empty */
+ {}
+ | table_index_name
+ | table_index_list ',' table_index_name
;
+table_index_name:
+ ident
+ {
+ Lex->index_list->push_back((LEX_STRING*)
+ thd->memdup(&$1, sizeof(LEX_STRING)),
+ thd->mem_root);
+ }
+ |
+ PRIMARY_SYM
+ {
+ LEX_STRING str= {(char*) "PRIMARY", 7};
+ Lex->index_list->push_back((LEX_STRING*)
+ thd->memdup(&str, sizeof(LEX_STRING)),
+ thd->mem_root);
+ }
+ ;
+
binlog_base64_event:
BINLOG_SYM TEXT_STRING_sys
{
Lex->sql_command = SQLCOM_BINLOG_BASE64_EVENT;
Lex->comment= $2;
+ Lex->ident.str= NULL;
+ Lex->ident.length= 0;
}
- ;
+ |
+ BINLOG_SYM '@' ident_or_text ',' '@' ident_or_text
+ {
+ Lex->sql_command = SQLCOM_BINLOG_BASE64_EVENT;
+ Lex->comment= $3;
+ Lex->ident= $6;
+ }
+ ;
check_view_or_table:
table_or_tables table_list opt_mi_check_type
@@ -7275,13 +7981,10 @@ check: CHECK_SYM
{
LEX* lex= thd->lex;
if (lex->sphead)
- {
- 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)
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "CHECK"));
+ 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;
}
;
@@ -7324,9 +8027,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;
}
;
@@ -7344,7 +8047,7 @@ rename:
}
table_to_table_list
{}
- | RENAME USER clear_privileges rename_list
+ | RENAME USER_SYM clear_privileges rename_list
{
Lex->sql_command = SQLCOM_RENAME_USER;
}
@@ -7353,12 +8056,14 @@ rename:
rename_list:
user TO_SYM user
{
- if (Lex->users_list.push_back($1) || Lex->users_list.push_back($3))
+ if (Lex->users_list.push_back($1, thd->mem_root) ||
+ Lex->users_list.push_back($3, thd->mem_root))
MYSQL_YYABORT;
}
| rename_list ',' user TO_SYM user
{
- if (Lex->users_list.push_back($3) || Lex->users_list.push_back($5))
+ if (Lex->users_list.push_back($3, thd->mem_root) ||
+ Lex->users_list.push_back($5, thd->mem_root))
MYSQL_YYABORT;
}
;
@@ -7373,9 +8078,9 @@ table_to_table:
{
LEX *lex=Lex;
SELECT_LEX *sl= lex->current_select;
- if (!sl->add_table_to_list(lex->thd, $1,NULL,TL_OPTION_UPDATING,
+ if (!sl->add_table_to_list(thd, $1,NULL,TL_OPTION_UPDATING,
TL_IGNORE, MDL_EXCLUSIVE) ||
- !sl->add_table_to_list(lex->thd, $3,NULL,TL_OPTION_UPDATING,
+ !sl->add_table_to_list(thd, $3,NULL,TL_OPTION_UPDATING,
TL_IGNORE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
}
@@ -7473,7 +8178,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 ')'
;
@@ -7518,6 +8223,13 @@ select_init:
;
select_paren:
+ {
+ /*
+ In order to correctly parse UNION's global ORDER BY we need to
+ set braces before parsing the clause.
+ */
+ Lex->current_select->set_braces(true);
+ }
SELECT_SYM select_part2
{
if (setup_select_in_parentheses(Lex))
@@ -7528,7 +8240,11 @@ select_paren:
/* The equivalent of select_paren for nested queries. */
select_paren_derived:
+ {
+ Lex->current_select->set_braces(true);
+ }
SELECT_SYM select_part2_derived
+ table_expression
{
if (setup_select_in_parentheses(Lex))
MYSQL_YYABORT;
@@ -7540,23 +8256,44 @@ select_init2:
select_part2
{
LEX *lex= Lex;
- SELECT_LEX * sel= lex->current_select;
- if (lex->current_select->set_braces(0))
- {
- my_parse_error(ER(ER_SYNTAX_ERROR));
- MYSQL_YYABORT;
- }
- if (sel->linkage == UNION_TYPE &&
- sel->master_unit()->first_select()->braces)
- {
- my_parse_error(ER(ER_SYNTAX_ERROR));
- MYSQL_YYABORT;
- }
+ /* Parentheses carry no meaning here */
+ lex->current_select->set_braces(false);
}
union_clause
;
+/*
+ Theoretically we can merge all 3 right hand sides of the select_part2
+ rule into one, however such a transformation adds one shift/reduce
+ conflict more.
+*/
select_part2:
+ select_options_and_item_list
+ opt_order_clause
+ opt_limit_clause
+ opt_select_lock_type
+ | select_options_and_item_list into opt_select_lock_type
+ | select_options_and_item_list
+ opt_into
+ from_clause
+ opt_where_clause
+ opt_group_clause
+ opt_having_clause
+ opt_order_clause
+ opt_limit_clause
+ opt_procedure_clause
+ opt_into
+ opt_select_lock_type
+ {
+ if ($2 && $10) /* double "INTO" clause */
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "INTO", "INTO"));
+
+ if ($9 && ($2 || $10)) /* "INTO" with "PROCEDURE ANALYSE" */
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "PROCEDURE", "INTO"));
+ }
+ ;
+
+select_options_and_item_list:
{
LEX *lex= Lex;
SELECT_LEX *sel= lex->current_select;
@@ -7568,26 +8305,36 @@ select_part2:
{
Select->parsing_place= NO_MATTER;
}
- select_into select_lock_type
;
-select_into:
- opt_order_clause opt_limit_clause {}
- | into
- | select_from
- | into select_from
- | select_from into
+table_expression:
+ opt_from_clause
+ opt_where_clause
+ opt_group_clause
+ opt_having_clause
+ opt_order_clause
+ opt_limit_clause
+ opt_procedure_clause
+ opt_select_lock_type
+ ;
+
+from_clause:
+ FROM table_reference_list
+ ;
+
+opt_from_clause:
+ /* empty */
+ | from_clause
;
-select_from:
- FROM join_table_list where_clause group_clause having_clause
- opt_order_clause opt_limit_clause procedure_clause
+table_reference_list:
+ join_table_list
{
Select->context.table_list=
Select->context.first_name_resolution_table=
Select->table_list.first;
}
- | FROM DUAL_SYM where_clause opt_limit_clause
+ | DUAL_SYM
/* oracle compatibility: oracle always requires FROM clause,
and DUAL is system table without fields.
Is "SELECT 1 FROM DUAL" any better than "SELECT 1" ?
@@ -7599,10 +8346,7 @@ select_options:
| select_option_list
{
if (Select->options & SELECT_DISTINCT && Select->options & SELECT_ALL)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT"));
}
;
@@ -7620,26 +8364,15 @@ select_option:
SQL_CACHE wasn't specified, and only once per query.
*/
if (Lex->current_select != &Lex->select_lex)
- {
- my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE");
- MYSQL_YYABORT;
- }
- else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE");
- MYSQL_YYABORT;
- }
- else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE");
- MYSQL_YYABORT;
- }
- else
- {
- Lex->safe_to_cache_query=0;
- Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
- Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
- }
+ my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"));
+
+ Lex->safe_to_cache_query=0;
+ Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
+ Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
}
| SQL_CACHE_SYM
{
@@ -7648,40 +8381,31 @@ select_option:
SQL_NO_CACHE wasn't specified, and only once per query.
*/
if (Lex->current_select != &Lex->select_lex)
- {
- my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE");
- MYSQL_YYABORT;
- }
- else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE");
- MYSQL_YYABORT;
- }
- else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE");
- MYSQL_YYABORT;
- }
- else
- {
- Lex->safe_to_cache_query=1;
- Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
- Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
- }
+ my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"));
+
+ Lex->safe_to_cache_query=1;
+ Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
+ Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
}
;
-select_lock_type:
+opt_select_lock_type:
/* empty */
| FOR_SYM UPDATE_SYM
{
LEX *lex=Lex;
+ lex->current_select->lock_type= TL_WRITE;
lex->current_select->set_lock_for_tables(TL_WRITE);
lex->safe_to_cache_query=0;
}
| LOCK_SYM IN_SYM SHARE_SYM MODE_SYM
{
LEX *lex=Lex;
+ lex->current_select->lock_type= TL_READ_WITH_SHARED_LOCKS;
lex->current_select->
set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
lex->safe_to_cache_query=0;
@@ -7694,7 +8418,7 @@ select_item_list:
| '*'
{
Item *item= new (thd->mem_root)
- Item_field(&thd->lex->current_select->context,
+ Item_field(thd, &thd->lex->current_select->context,
NULL, NULL, "*");
if (item == NULL)
MYSQL_YYABORT;
@@ -7720,10 +8444,7 @@ select_item:
{
if (Lex->sql_command == SQLCOM_CREATE_VIEW &&
check_column_name($4.str))
- {
- my_error(ER_WRONG_COLUMN_NAME, MYF(0), $4.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), $4.str));
$2->is_autogenerated_name= FALSE;
$2->set_name($4.str, $4.length, system_charset_info);
}
@@ -7734,6 +8455,12 @@ select_item:
}
;
+remember_tok_start:
+ {
+ $$= (char*) YYLIP->get_tok_start();
+ }
+ ;
+
remember_name:
{
$$= (char*) YYLIP->get_cpp_tok_start();
@@ -7754,6 +8481,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; }
@@ -7797,7 +8530,7 @@ expr:
/*
(X1 OR X2) OR Y ==> OR (X1, X2, Y)
*/
- item1->add($3);
+ item1->add($3, thd->mem_root);
$$ = $1;
}
}
@@ -7807,13 +8540,13 @@ expr:
/*
X OR (Y1 OR Y2) ==> OR (X, Y1, Y2)
*/
- item3->add_at_head($1);
+ item3->add_at_head($1, thd->mem_root);
$$ = $3;
}
else
{
/* X OR Y */
- $$ = new (thd->mem_root) Item_cond_or($1, $3);
+ $$= new (thd->mem_root) Item_cond_or(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -7821,7 +8554,7 @@ expr:
| expr XOR expr %prec XOR
{
/* XOR is a proprietary extension */
- $$ = new (thd->mem_root) Item_func_xor($1, $3);
+ $$= new (thd->mem_root) Item_func_xor(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -7847,7 +8580,7 @@ expr:
/*
(X1 AND X2) AND Y ==> AND (X1, X2, Y)
*/
- item1->add($3);
+ item1->add($3, thd->mem_root);
$$ = $1;
}
}
@@ -7857,13 +8590,13 @@ expr:
/*
X AND (Y1 AND Y2) ==> AND (X, Y1, Y2)
*/
- item3->add_at_head($1);
+ item3->add_at_head($1, thd->mem_root);
$$ = $3;
}
else
{
/* X AND Y */
- $$ = new (thd->mem_root) Item_cond_and($1, $3);
+ $$= new (thd->mem_root) Item_cond_and(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -7876,37 +8609,37 @@ expr:
}
| bool_pri IS TRUE_SYM %prec IS
{
- $$= new (thd->mem_root) Item_func_istrue($1);
+ $$= new (thd->mem_root) Item_func_istrue(thd, $1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS not TRUE_SYM %prec IS
{
- $$= new (thd->mem_root) Item_func_isnottrue($1);
+ $$= new (thd->mem_root) Item_func_isnottrue(thd, $1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS FALSE_SYM %prec IS
{
- $$= new (thd->mem_root) Item_func_isfalse($1);
+ $$= new (thd->mem_root) Item_func_isfalse(thd, $1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS not FALSE_SYM %prec IS
{
- $$= new (thd->mem_root) Item_func_isnotfalse($1);
+ $$= new (thd->mem_root) Item_func_isnotfalse(thd, $1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS UNKNOWN_SYM %prec IS
{
- $$= new (thd->mem_root) Item_func_isnull($1);
+ $$= new (thd->mem_root) Item_func_isnull(thd, $1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS not UNKNOWN_SYM %prec IS
{
- $$= new (thd->mem_root) Item_func_isnotnull($1);
+ $$= new (thd->mem_root) Item_func_isnotnull(thd, $1);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -7916,31 +8649,31 @@ expr:
bool_pri:
bool_pri IS NULL_SYM %prec IS
{
- $$= new (thd->mem_root) Item_func_isnull($1);
+ $$= new (thd->mem_root) Item_func_isnull(thd, $1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS not NULL_SYM %prec IS
{
- $$= new (thd->mem_root) Item_func_isnotnull($1);
+ $$= new (thd->mem_root) Item_func_isnotnull(thd, $1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri EQUAL_SYM predicate %prec EQUAL_SYM
{
- $$= new (thd->mem_root) Item_func_equal($1,$3);
+ $$= new (thd->mem_root) Item_func_equal(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri comp_op predicate %prec '='
{
- $$= (*$2)(0)->create($1,$3);
+ $$= (*$2)(0)->create(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri comp_op all_or_any '(' subselect ')' %prec '='
{
- $$= all_any_subquery_creator($1, $2, $3, $5);
+ $$= all_any_subquery_creator(thd, $1, $2, $3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -7950,13 +8683,13 @@ bool_pri:
predicate:
bit_expr IN_SYM '(' subselect ')'
{
- $$= new (thd->mem_root) Item_in_subselect($1, $4);
+ $$= new (thd->mem_root) Item_in_subselect(thd, $1, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr not IN_SYM '(' subselect ')'
{
- Item *item= new (thd->mem_root) Item_in_subselect($1, $5);
+ Item *item= new (thd->mem_root) Item_in_subselect(thd, $1, $5);
if (item == NULL)
MYSQL_YYABORT;
$$= negate_expression(thd, item);
@@ -7971,9 +8704,9 @@ predicate:
}
| bit_expr IN_SYM '(' expr ',' expr_list ')'
{
- $6->push_front($4);
- $6->push_front($1);
- $$= new (thd->mem_root) Item_func_in(*$6);
+ $6->push_front($4, thd->mem_root);
+ $6->push_front($1, thd->mem_root);
+ $$= new (thd->mem_root) Item_func_in(thd, *$6);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -7985,9 +8718,9 @@ predicate:
}
| bit_expr not IN_SYM '(' expr ',' expr_list ')'
{
- $7->push_front($5);
- $7->push_front($1);
- Item_func_in *item = new (thd->mem_root) Item_func_in(*$7);
+ $7->push_front($5, thd->mem_root);
+ $7->push_front($1, thd->mem_root);
+ Item_func_in *item= new (thd->mem_root) Item_func_in(thd, *$7);
if (item == NULL)
MYSQL_YYABORT;
item->negate();
@@ -7995,14 +8728,14 @@ predicate:
}
| bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
{
- $$= new (thd->mem_root) Item_func_between($1,$3,$5);
+ $$= new (thd->mem_root) Item_func_between(thd, $1, $3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
{
Item_func_between *item;
- item= new (thd->mem_root) Item_func_between($1,$4,$6);
+ item= new (thd->mem_root) Item_func_between(thd, $1, $4, $6);
if (item == NULL)
MYSQL_YYABORT;
item->negate();
@@ -8010,39 +8743,40 @@ predicate:
}
| bit_expr SOUNDS_SYM LIKE bit_expr
{
- Item *item1= new (thd->mem_root) Item_func_soundex($1);
- Item *item4= new (thd->mem_root) Item_func_soundex($4);
+ Item *item1= new (thd->mem_root) Item_func_soundex(thd, $1);
+ Item *item4= new (thd->mem_root) Item_func_soundex(thd, $4);
if ((item1 == NULL) || (item4 == NULL))
MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_func_eq(item1, item4);
+ $$= new (thd->mem_root) Item_func_eq(thd, item1, item4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr LIKE simple_expr opt_escape
{
- $$= new (thd->mem_root) Item_func_like($1,$3,$4,Lex->escape_used);
+ $$= new (thd->mem_root) Item_func_like(thd, $1, $3, $4,
+ Lex->escape_used);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr not LIKE simple_expr opt_escape
{
- Item *item= new (thd->mem_root) Item_func_like($1,$4,$5,
+ Item *item= new (thd->mem_root) Item_func_like(thd, $1, $4, $5,
Lex->escape_used);
if (item == NULL)
MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_func_not(item);
+ $$= new (thd->mem_root) Item_func_not(thd, item);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr REGEXP bit_expr
{
- $$= new (thd->mem_root) Item_func_regex($1,$3);
+ $$= new (thd->mem_root) Item_func_regex(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr not REGEXP bit_expr
{
- Item *item= new (thd->mem_root) Item_func_regex($1,$4);
+ Item *item= new (thd->mem_root) Item_func_regex(thd, $1, $4);
if (item == NULL)
MYSQL_YYABORT;
$$= negate_expression(thd, item);
@@ -8055,85 +8789,85 @@ predicate:
bit_expr:
bit_expr '|' bit_expr %prec '|'
{
- $$= new (thd->mem_root) Item_func_bit_or($1,$3);
+ $$= new (thd->mem_root) Item_func_bit_or(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '&' bit_expr %prec '&'
{
- $$= new (thd->mem_root) Item_func_bit_and($1,$3);
+ $$= new (thd->mem_root) Item_func_bit_and(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr SHIFT_LEFT bit_expr %prec SHIFT_LEFT
{
- $$= new (thd->mem_root) Item_func_shift_left($1,$3);
+ $$= new (thd->mem_root) Item_func_shift_left(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr SHIFT_RIGHT bit_expr %prec SHIFT_RIGHT
{
- $$= new (thd->mem_root) Item_func_shift_right($1,$3);
+ $$= new (thd->mem_root) Item_func_shift_right(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '+' bit_expr %prec '+'
{
- $$= new (thd->mem_root) Item_func_plus($1,$3);
+ $$= new (thd->mem_root) Item_func_plus(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '-' bit_expr %prec '-'
{
- $$= new (thd->mem_root) Item_func_minus($1,$3);
+ $$= new (thd->mem_root) Item_func_minus(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '+' INTERVAL_SYM expr interval %prec '+'
{
- $$= new (thd->mem_root) Item_date_add_interval($1,$4,$5,0);
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $1, $4, $5, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '-' INTERVAL_SYM expr interval %prec '-'
{
- $$= new (thd->mem_root) Item_date_add_interval($1,$4,$5,1);
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $1, $4, $5, 1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '*' bit_expr %prec '*'
{
- $$= new (thd->mem_root) Item_func_mul($1,$3);
+ $$= new (thd->mem_root) Item_func_mul(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '/' bit_expr %prec '/'
{
- $$= new (thd->mem_root) Item_func_div($1,$3);
+ $$= new (thd->mem_root) Item_func_div(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '%' bit_expr %prec '%'
{
- $$= new (thd->mem_root) Item_func_mod($1,$3);
+ $$= new (thd->mem_root) Item_func_mod(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr DIV_SYM bit_expr %prec DIV_SYM
{
- $$= new (thd->mem_root) Item_func_int_div($1,$3);
+ $$= new (thd->mem_root) Item_func_int_div(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr MOD_SYM bit_expr %prec MOD_SYM
{
- $$= new (thd->mem_root) Item_func_mod($1,$3);
+ $$= new (thd->mem_root) Item_func_mod(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '^' bit_expr
{
- $$= new (thd->mem_root) Item_func_bit_xor($1,$3);
+ $$= new (thd->mem_root) Item_func_bit_xor(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8226,7 +8960,9 @@ dyncol_type:
$$= DYN_COL_DECIMAL;
Lex->charset= NULL;
}
- | char opt_binary
+ | char
+ { Lex->charset= thd->variables.collation_connection; }
+ opt_binary
{
LEX *lex= Lex;
$$= DYN_COL_STRING;
@@ -8272,7 +9008,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;
@@ -8292,11 +9028,11 @@ dyncall_create_list:
$$= new (thd->mem_root) List<DYNCALL_CREATE_DEF>;
if ($$ == NULL)
MYSQL_YYABORT;
- $$->push_back($1);
+ $$->push_back($1, thd->mem_root);
}
| dyncall_create_list ',' dyncall_create_element
{
- $1->push_back($3);
+ $1->push_back($3, thd->mem_root);
$$= $1;
}
;
@@ -8309,22 +9045,22 @@ simple_expr:
| function_call_conflict
| simple_expr COLLATE_SYM ident_or_text %prec NEG
{
- Item *i1= new (thd->mem_root) Item_string($3.str,
+ Item *i1= new (thd->mem_root) Item_string(thd, $3.str,
$3.length,
thd->charset());
if (i1 == NULL)
MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_func_set_collation($1, i1);
+ $$= new (thd->mem_root) Item_func_set_collation(thd, $1, i1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| literal
- | param_marker
+ | param_marker { $$= $1; }
| variable
| sum_expr
| simple_expr OR_OR_SYM simple_expr
{
- $$= new (thd->mem_root) Item_func_concat($1, $3);
+ $$= new (thd->mem_root) Item_func_concat(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8334,13 +9070,13 @@ simple_expr:
}
| '-' simple_expr %prec NEG
{
- $$= new (thd->mem_root) Item_func_neg($2);
+ $$= new (thd->mem_root) Item_func_neg(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
| '~' simple_expr %prec NEG
{
- $$= new (thd->mem_root) Item_func_bit_neg($2);
+ $$= new (thd->mem_root) Item_func_bit_neg(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8352,7 +9088,7 @@ simple_expr:
}
| '(' subselect ')'
{
- $$= new (thd->mem_root) Item_singlerow_subselect($2);
+ $$= new (thd->mem_root) Item_singlerow_subselect(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8360,33 +9096,56 @@ simple_expr:
{ $$= $2; }
| '(' expr ',' expr_list ')'
{
- $4->push_front($2);
- $$= new (thd->mem_root) Item_row(*$4);
+ $4->push_front($2, thd->mem_root);
+ $$= new (thd->mem_root) Item_row(thd, *$4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| ROW_SYM '(' expr ',' expr_list ')'
{
- $5->push_front($3);
- $$= new (thd->mem_root) Item_row(*$5);
+ $5->push_front($3, thd->mem_root);
+ $$= new (thd->mem_root) Item_row(thd, *$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| EXISTS '(' subselect ')'
{
- $$= new (thd->mem_root) Item_exists_subselect($3);
+ $$= new (thd->mem_root) Item_exists_subselect(thd, $3);
if ($$ == NULL)
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);
- Item_func_match *i1= new (thd->mem_root) Item_func_match(*$2, $6);
+ $2->push_front($5, thd->mem_root);
+ Item_func_match *i1= new (thd->mem_root) Item_func_match(thd, *$2,
+ $6);
if (i1 == NULL)
MYSQL_YYABORT;
- Select->add_ftfunc_to_list(i1);
+ Select->add_ftfunc_to_list(thd, i1);
$$= i1;
}
| BINARY simple_expr %prec NEG
@@ -8406,7 +9165,7 @@ simple_expr:
}
| CASE_SYM opt_expr when_list opt_else END
{
- $$= new (thd->mem_root) Item_func_case(* $3, $2, $4 );
+ $$= new (thd->mem_root) Item_func_case(thd, *$3, $2, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8419,27 +9178,23 @@ simple_expr:
}
| CONVERT_SYM '(' expr USING charset_name ')'
{
- $$= new (thd->mem_root) Item_func_conv_charset($3,$5);
+ $$= new (thd->mem_root) Item_func_conv_charset(thd, $3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| DEFAULT '(' simple_ident ')'
{
- if ($3->is_splocal())
- {
- Item_splocal *il= static_cast<Item_splocal *>($3);
-
- my_error(ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str);
- MYSQL_YYABORT;
- }
- $$= new (thd->mem_root) Item_default_value(Lex->current_context(),
+ Item_splocal *il= $3->get_item_splocal();
+ if (il)
+ my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str));
+ $$= new (thd->mem_root) Item_default_value(thd, Lex->current_context(),
$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| VALUES '(' simple_ident_nospvar ')'
{
- $$= new (thd->mem_root) Item_insert_value(Lex->current_context(),
+ $$= new (thd->mem_root) Item_insert_value(thd, Lex->current_context(),
$3);
if ($$ == NULL)
MYSQL_YYABORT;
@@ -8447,7 +9202,7 @@ simple_expr:
| INTERVAL_SYM expr interval '+' expr %prec INTERVAL_SYM
/* we cannot put interval before - */
{
- $$= new (thd->mem_root) Item_date_add_interval($5,$2,$3,0);
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $5, $2, $3, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8462,19 +9217,29 @@ simple_expr:
function_call_keyword:
CHAR_SYM '(' expr_list ')'
{
- $$= new (thd->mem_root) Item_func_char(*$3);
+ $$= new (thd->mem_root) Item_func_char(thd, *$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CHAR_SYM '(' expr_list USING charset_name ')'
{
- $$= new (thd->mem_root) Item_func_char(*$3, $5);
+ $$= new (thd->mem_root) Item_func_char(thd, *$3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CURRENT_USER optional_braces
{
- $$= new (thd->mem_root) Item_func_current_user(Lex->current_context());
+ $$= new (thd->mem_root) Item_func_current_user(thd,
+ Lex->current_context());
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ 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(thd,
+ Lex->current_context());
if ($$ == NULL)
MYSQL_YYABORT;
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
@@ -8482,25 +9247,25 @@ function_call_keyword:
}
| DATE_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_date_typecast($3);
+ $$= new (thd->mem_root) Item_date_typecast(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| DAY_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_dayofmonth($3);
+ $$= new (thd->mem_root) Item_func_dayofmonth(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| HOUR_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_hour($3);
+ $$= new (thd->mem_root) Item_func_hour(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| INSERT '(' expr ',' expr ',' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_insert($3,$5,$7,$9);
+ $$= new (thd->mem_root) Item_func_insert(thd, $3, $5, $7, $9);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8509,125 +9274,127 @@ function_call_keyword:
List<Item> *list= new (thd->mem_root) List<Item>;
if (list == NULL)
MYSQL_YYABORT;
- list->push_front($5);
- list->push_front($3);
- Item_row *item= new (thd->mem_root) Item_row(*list);
+ list->push_front($5, thd->mem_root);
+ list->push_front($3, thd->mem_root);
+ Item_row *item= new (thd->mem_root) Item_row(thd, *list);
if (item == NULL)
MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_func_interval(item);
+ $$= new (thd->mem_root) Item_func_interval(thd, item);
if ($$ == NULL)
MYSQL_YYABORT;
}
| INTERVAL_SYM '(' expr ',' expr ',' expr_list ')' %prec INTERVAL_SYM
{
- $7->push_front($5);
- $7->push_front($3);
- Item_row *item= new (thd->mem_root) Item_row(*$7);
+ $7->push_front($5, thd->mem_root);
+ $7->push_front($3, thd->mem_root);
+ Item_row *item= new (thd->mem_root) Item_row(thd, *$7);
if (item == NULL)
MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_func_interval(item);
+ $$= new (thd->mem_root) Item_func_interval(thd, item);
if ($$ == NULL)
MYSQL_YYABORT;
}
| LEFT '(' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_left($3,$5);
+ $$= new (thd->mem_root) Item_func_left(thd, $3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MINUTE_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_minute($3);
+ $$= new (thd->mem_root) Item_func_minute(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MONTH_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_month($3);
+ $$= new (thd->mem_root) Item_func_month(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| RIGHT '(' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_right($3,$5);
+ $$= new (thd->mem_root) Item_func_right(thd, $3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SECOND_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_second($3);
+ $$= new (thd->mem_root) Item_func_second(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TIME_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_time_typecast($3, AUTO_SEC_PART_DIGITS);
+ $$= new (thd->mem_root) Item_time_typecast(thd, $3,
+ AUTO_SEC_PART_DIGITS);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TIMESTAMP '(' expr ')'
{
- $$= new (thd->mem_root) Item_datetime_typecast($3, AUTO_SEC_PART_DIGITS);
+ $$= new (thd->mem_root) Item_datetime_typecast(thd, $3,
+ AUTO_SEC_PART_DIGITS);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TIMESTAMP '(' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_add_time($3, $5, 1, 0);
+ $$= new (thd->mem_root) Item_func_add_time(thd, $3, $5, 1, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_trim($3);
+ $$= new (thd->mem_root) Item_func_trim(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' LEADING expr FROM expr ')'
{
- $$= new (thd->mem_root) Item_func_ltrim($6,$4);
+ $$= new (thd->mem_root) Item_func_ltrim(thd, $6, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' TRAILING expr FROM expr ')'
{
- $$= new (thd->mem_root) Item_func_rtrim($6,$4);
+ $$= new (thd->mem_root) Item_func_rtrim(thd, $6, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' BOTH expr FROM expr ')'
{
- $$= new (thd->mem_root) Item_func_trim($6,$4);
+ $$= new (thd->mem_root) Item_func_trim(thd, $6, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' LEADING FROM expr ')'
{
- $$= new (thd->mem_root) Item_func_ltrim($5);
+ $$= new (thd->mem_root) Item_func_ltrim(thd, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' TRAILING FROM expr ')'
{
- $$= new (thd->mem_root) Item_func_rtrim($5);
+ $$= new (thd->mem_root) Item_func_rtrim(thd, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' BOTH FROM expr ')'
{
- $$= new (thd->mem_root) Item_func_trim($5);
+ $$= new (thd->mem_root) Item_func_trim(thd, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' expr FROM expr ')'
{
- $$= new (thd->mem_root) Item_func_trim($5,$3);
+ $$= new (thd->mem_root) Item_func_trim(thd, $5, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
- | USER '(' ')'
+ | USER_SYM '(' ')'
{
- $$= new (thd->mem_root) Item_func_user();
+ $$= new (thd->mem_root) Item_func_user(thd);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
@@ -8635,7 +9402,7 @@ function_call_keyword:
}
| YEAR_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_year($3);
+ $$= new (thd->mem_root) Item_func_year(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8656,27 +9423,27 @@ function_call_keyword:
function_call_nonkeyword:
ADDDATE_SYM '(' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_date_add_interval($3, $5,
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $5,
INTERVAL_DAY, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
{
- $$= new (thd->mem_root) Item_date_add_interval($3, $6, $7, 0);
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CURDATE optional_braces
{
- $$= new (thd->mem_root) Item_func_curdate_local();
+ $$= new (thd->mem_root) Item_func_curdate_local(thd);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
| CURTIME opt_time_precision
{
- $$= new (thd->mem_root) Item_func_curtime_local($2);
+ $$= new (thd->mem_root) Item_func_curtime_local(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
@@ -8684,76 +9451,76 @@ function_call_nonkeyword:
| DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
%prec INTERVAL_SYM
{
- $$= new (thd->mem_root) Item_date_add_interval($3,$6,$7,0);
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| DATE_SUB_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
%prec INTERVAL_SYM
{
- $$= new (thd->mem_root) Item_date_add_interval($3,$6,$7,1);
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| EXTRACT_SYM '(' interval FROM expr ')'
{
- $$=new (thd->mem_root) Item_extract( $3, $5);
+ $$=new (thd->mem_root) Item_extract(thd, $3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| GET_FORMAT '(' date_time_type ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_get_format($3, $5);
+ $$= new (thd->mem_root) Item_func_get_format(thd, $3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| NOW_SYM opt_time_precision
{
- $$= new (thd->mem_root) Item_func_now_local($2);
+ $$= new (thd->mem_root) Item_func_now_local(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
| POSITION_SYM '(' bit_expr IN_SYM expr ')'
{
- $$ = new (thd->mem_root) Item_func_locate($5,$3);
+ $$= new (thd->mem_root) Item_func_locate(thd, $5, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUBDATE_SYM '(' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_date_add_interval($3, $5,
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $5,
INTERVAL_DAY, 1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
{
- $$= new (thd->mem_root) Item_date_add_interval($3, $6, $7, 1);
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUBSTRING '(' expr ',' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_substr($3,$5,$7);
+ $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUBSTRING '(' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_substr($3,$5);
+ $$= new (thd->mem_root) Item_func_substr(thd, $3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUBSTRING '(' expr FROM expr FOR_SYM expr ')'
{
- $$= new (thd->mem_root) Item_func_substr($3,$5,$7);
+ $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUBSTRING '(' expr FROM expr ')'
{
- $$= new (thd->mem_root) Item_func_substr($3,$5);
+ $$= new (thd->mem_root) Item_func_substr(thd, $3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8768,42 +9535,42 @@ function_call_nonkeyword:
*/
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
if (global_system_variables.sysdate_is_now == 0)
- $$= new (thd->mem_root) Item_func_sysdate_local($2);
+ $$= new (thd->mem_root) Item_func_sysdate_local(thd, $2);
else
- $$= new (thd->mem_root) Item_func_now_local($2);
+ $$= new (thd->mem_root) Item_func_now_local(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
| TIMESTAMP_ADD '(' interval_time_stamp ',' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_date_add_interval($7,$5,$3,0);
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $7, $5, $3, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TIMESTAMP_DIFF '(' interval_time_stamp ',' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_timestamp_diff($5,$7,$3);
+ $$= new (thd->mem_root) Item_func_timestamp_diff(thd, $5, $7, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| UTC_DATE_SYM optional_braces
{
- $$= new (thd->mem_root) Item_func_curdate_utc();
+ $$= new (thd->mem_root) Item_func_curdate_utc(thd);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
| UTC_TIME_SYM opt_time_precision
{
- $$= new (thd->mem_root) Item_func_curtime_utc($2);
+ $$= new (thd->mem_root) Item_func_curtime_utc(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
| UTC_TIMESTAMP_SYM opt_time_precision
{
- $$= new (thd->mem_root) Item_func_now_utc($2);
+ $$= new (thd->mem_root) Item_func_now_utc(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
@@ -8823,16 +9590,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(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8863,114 +9623,174 @@ function_call_nonkeyword:
function_call_conflict:
ASCII_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_ascii($3);
+ $$= new (thd->mem_root) Item_func_ascii(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CHARSET '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_charset($3);
+ $$= new (thd->mem_root) Item_func_charset(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| COALESCE '(' expr_list ')'
{
- $$= new (thd->mem_root) Item_func_coalesce(* $3);
+ $$= new (thd->mem_root) Item_func_coalesce(thd, *$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| COLLATION_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_collation($3);
+ $$= new (thd->mem_root) Item_func_collation(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| DATABASE '(' ')'
{
- $$= new (thd->mem_root) Item_func_database();
+ $$= new (thd->mem_root) Item_func_database(thd);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
- | IF '(' expr ',' expr ',' expr ')'
+ | IF_SYM '(' expr ',' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_if($3,$5,$7);
+ $$= new (thd->mem_root) Item_func_if(thd, $3, $5, $7);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | FORMAT_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_format(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | FORMAT_SYM '(' expr ',' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_format(thd, $3, $5, $7);
if ($$ == NULL)
MYSQL_YYABORT;
}
| LAST_VALUE '(' expr_list ')'
{
- $$= new (thd->mem_root) Item_func_last_value(* $3);
+ $$= new (thd->mem_root) Item_func_last_value(thd, *$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MICROSECOND_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_microsecond($3);
+ $$= new (thd->mem_root) Item_func_microsecond(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MOD_SYM '(' expr ',' expr ')'
{
- $$ = new (thd->mem_root) Item_func_mod($3, $5);
+ $$= new (thd->mem_root) Item_func_mod(thd, $3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
- | OLD_PASSWORD '(' expr ')'
+ | OLD_PASSWORD_SYM '(' expr ')'
{
- $$= new (thd->mem_root) Item_func_old_password($3);
+ $$= new (thd->mem_root)
+ Item_func_password(thd, $3, Item_func_password::OLD);
if ($$ == NULL)
MYSQL_YYABORT;
}
- | PASSWORD '(' expr ')'
+ | PASSWORD_SYM '(' expr ')'
{
Item* i1;
- if (thd->variables.old_passwords)
- i1= new (thd->mem_root) Item_func_old_password($3);
- else
- i1= new (thd->mem_root) Item_func_password($3);
+ i1= new (thd->mem_root) Item_func_password(thd, $3);
if (i1 == NULL)
MYSQL_YYABORT;
$$= i1;
}
| QUARTER_SYM '(' expr ')'
{
- $$ = new (thd->mem_root) Item_func_quarter($3);
+ $$= new (thd->mem_root) Item_func_quarter(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| REPEAT_SYM '(' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_repeat($3,$5);
+ $$= new (thd->mem_root) Item_func_repeat(thd, $3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| REPLACE '(' expr ',' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_replace($3,$5,$7);
+ $$= new (thd->mem_root) Item_func_replace(thd, $3, $5, $7);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | REVERSE_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_reverse(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | ROW_COUNT_SYM '(' ')'
+ {
+ $$= new (thd->mem_root) Item_func_row_count(thd);
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);
+ $$= new (thd->mem_root) Item_func_round(thd, $3, $5, 1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| WEEK_SYM '(' expr ')'
{
- Item *i1= new (thd->mem_root) Item_int((char*) "0",
- thd->variables.default_week_format,
- 1);
- if (i1 == NULL)
+ Item *i1;
+ LEX_STRING name= {C_STRING_WITH_LEN("default_week_format")};
+ if (!(i1= get_system_var(thd, OPT_SESSION,
+ name, null_lex_str)))
MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_func_week($3, i1);
+ i1->set_name((const char *)
+ STRING_WITH_LEN("@@default_week_format"),
+ system_charset_info);
+ $$= new (thd->mem_root) Item_func_week(thd, $3, i1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| WEEK_SYM '(' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_week($3,$5);
+ $$= new (thd->mem_root) Item_func_week(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | WEIGHT_STRING_SYM '(' expr opt_ws_levels ')'
+ {
+ $$= new (thd->mem_root) Item_func_weight_string(thd, $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(thd, $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(thd, $3, $6,
+ &my_charset_bin);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ $$= new (thd->mem_root)
+ Item_func_weight_string(thd, 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(thd, $3, $5, $7,
+ $9);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8982,9 +9802,8 @@ function_call_conflict:
if ($$ == NULL)
MYSQL_YYABORT;
#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
- MYSQL_YYABORT;
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
+ sym_group_geom.needed_define));
#endif
}
;
@@ -8993,52 +9812,52 @@ geometry_function:
CONTAINS_SYM '(' expr ',' expr ')'
{
$$= GEOM_NEW(thd,
- Item_func_spatial_rel($3, $5,
- Item_func::SP_CONTAINS_FUNC));
+ Item_func_spatial_precise_rel(thd, $3, $5,
+ Item_func::SP_CONTAINS_FUNC));
}
| GEOMETRYCOLLECTION '(' expr_list ')'
{
$$= GEOM_NEW(thd,
- Item_func_spatial_collection(* $3,
+ Item_func_spatial_collection(thd, *$3,
Geometry::wkb_geometrycollection,
Geometry::wkb_point));
}
| LINESTRING '(' expr_list ')'
{
$$= GEOM_NEW(thd,
- Item_func_spatial_collection(* $3,
+ Item_func_spatial_collection(thd, *$3,
Geometry::wkb_linestring,
Geometry::wkb_point));
}
| MULTILINESTRING '(' expr_list ')'
{
$$= GEOM_NEW(thd,
- Item_func_spatial_collection(* $3,
+ Item_func_spatial_collection(thd, *$3,
Geometry::wkb_multilinestring,
Geometry::wkb_linestring));
}
| MULTIPOINT '(' expr_list ')'
{
$$= GEOM_NEW(thd,
- Item_func_spatial_collection(* $3,
+ Item_func_spatial_collection(thd, *$3,
Geometry::wkb_multipoint,
Geometry::wkb_point));
}
| MULTIPOLYGON '(' expr_list ')'
{
$$= GEOM_NEW(thd,
- Item_func_spatial_collection(* $3,
+ Item_func_spatial_collection(thd, *$3,
Geometry::wkb_multipolygon,
Geometry::wkb_polygon));
}
| POINT_SYM '(' expr ',' expr ')'
{
- $$= GEOM_NEW(thd, Item_func_point($3,$5));
+ $$= GEOM_NEW(thd, Item_func_point(thd, $3, $5));
}
| POLYGON '(' expr_list ')'
{
$$= GEOM_NEW(thd,
- Item_func_spatial_collection(* $3,
+ Item_func_spatial_collection(thd, *$3,
Geometry::wkb_polygon,
Geometry::wkb_linestring));
}
@@ -9065,7 +9884,7 @@ function_call_generic:
{
if (lex->current_select->inc_in_sum_expr())
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
}
@@ -9146,10 +9965,7 @@ function_call_generic:
*/
if (!$1.str || check_db_name(&$1))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
if (check_routine_name(&$3))
{
MYSQL_YYABORT;
@@ -9194,11 +10010,11 @@ udf_expr_list:
$$= new (thd->mem_root) List<Item>;
if ($$ == NULL)
MYSQL_YYABORT;
- $$->push_back($1);
+ $$->push_back($1, thd->mem_root);
}
| udf_expr_list ',' udf_expr
{
- $1->push_back($3);
+ $1->push_back($3, thd->mem_root);
$$= $1;
}
;
@@ -9233,46 +10049,46 @@ udf_expr:
sum_expr:
AVG_SYM '(' in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_avg($3, FALSE);
+ $$= new (thd->mem_root) Item_sum_avg(thd, $3, FALSE);
if ($$ == NULL)
MYSQL_YYABORT;
}
| AVG_SYM '(' DISTINCT in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_avg($4, TRUE);
+ $$= new (thd->mem_root) Item_sum_avg(thd, $4, TRUE);
if ($$ == NULL)
MYSQL_YYABORT;
}
| BIT_AND '(' in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_and($3);
+ $$= new (thd->mem_root) Item_sum_and(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| BIT_OR '(' in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_or($3);
+ $$= new (thd->mem_root) Item_sum_or(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| BIT_XOR '(' in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_xor($3);
+ $$= new (thd->mem_root) Item_sum_xor(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| COUNT_SYM '(' opt_all '*' ')'
{
- Item *item= new (thd->mem_root) Item_int((int32) 0L,1);
+ Item *item= new (thd->mem_root) Item_int(thd, (int32) 0L, 1);
if (item == NULL)
MYSQL_YYABORT;
- $$= new (thd->mem_root) Item_sum_count(item);
+ $$= new (thd->mem_root) Item_sum_count(thd, item);
if ($$ == NULL)
MYSQL_YYABORT;
}
| COUNT_SYM '(' in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_count($3);
+ $$= new (thd->mem_root) Item_sum_count(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9282,13 +10098,13 @@ sum_expr:
{ Select->in_sum_expr--; }
')'
{
- $$= new (thd->mem_root) Item_sum_count(* $5);
+ $$= new (thd->mem_root) Item_sum_count(thd, *$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MIN_SYM '(' in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_min($3);
+ $$= new (thd->mem_root) Item_sum_min(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9299,55 +10115,55 @@ sum_expr:
*/
| MIN_SYM '(' DISTINCT in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_min($4);
+ $$= new (thd->mem_root) Item_sum_min(thd, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MAX_SYM '(' in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_max($3);
+ $$= new (thd->mem_root) Item_sum_max(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MAX_SYM '(' DISTINCT in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_max($4);
+ $$= new (thd->mem_root) Item_sum_max(thd, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| STD_SYM '(' in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_std($3, 0);
+ $$= new (thd->mem_root) Item_sum_std(thd, $3, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| VARIANCE_SYM '(' in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_variance($3, 0);
+ $$= new (thd->mem_root) Item_sum_variance(thd, $3, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| STDDEV_SAMP_SYM '(' in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_std($3, 1);
+ $$= new (thd->mem_root) Item_sum_std(thd, $3, 1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| VAR_SAMP_SYM '(' in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_variance($3, 1);
+ $$= new (thd->mem_root) Item_sum_variance(thd, $3, 1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUM_SYM '(' in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_sum($3, FALSE);
+ $$= new (thd->mem_root) Item_sum_sum(thd, $3, FALSE);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUM_SYM '(' DISTINCT in_sum_expr ')'
{
- $$= new (thd->mem_root) Item_sum_sum($4, TRUE);
+ $$= new (thd->mem_root) Item_sum_sum(thd, $4, TRUE);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9360,7 +10176,7 @@ sum_expr:
SELECT_LEX *sel= Select;
sel->in_sum_expr--;
$$= new (thd->mem_root)
- Item_func_group_concat(Lex->current_context(), $3, $5,
+ Item_func_group_concat(thd, Lex->current_context(), $3, $5,
sel->gorder_list, $7);
if ($$ == NULL)
MYSQL_YYABORT;
@@ -9373,10 +10189,7 @@ variable:
'@'
{
if (! Lex->parsing_options.allows_variable)
- {
- my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
}
variable_aux
{
@@ -9388,16 +10201,16 @@ variable_aux:
ident_or_text SET_VAR expr
{
Item_func_set_user_var *item;
- $$= item= new (thd->mem_root) Item_func_set_user_var($1, $3);
+ $$= item= new (thd->mem_root) Item_func_set_user_var(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
LEX *lex= Lex;
lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- lex->set_var_list.push_back(item);
+ lex->set_var_list.push_back(item, thd->mem_root);
}
| ident_or_text
{
- $$= new (thd->mem_root) Item_func_get_user_var($1);
+ $$= new (thd->mem_root) Item_func_get_user_var(thd, $1);
if ($$ == NULL)
MYSQL_YYABORT;
LEX *lex= Lex;
@@ -9408,7 +10221,7 @@ variable_aux:
/* disallow "SELECT @@global.global.variable" */
if ($3.str && $4.str && check_reserved_words(&$3))
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
if (!($$= get_system_var(thd, $2, $3, $4)))
@@ -9443,9 +10256,8 @@ opt_gorder_clause:
sel->olap != UNSPECIFIED_OLAP_TYPE &&
(sel->linkage != UNION_TYPE || sel->braces))
{
- my_error(ER_WRONG_USAGE, MYF(0),
- "CUBE/ROLLUP", "ORDER BY");
- MYSQL_YYABORT;
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0),
+ "CUBE/ROLLUP", "ORDER BY"));
}
}
gorder_list;
@@ -9464,7 +10276,7 @@ in_sum_expr:
LEX *lex= Lex;
if (lex->current_select->inc_in_sum_expr())
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
}
@@ -9478,7 +10290,9 @@ in_sum_expr:
cast_type:
BINARY opt_field_length
{ $$=ITEM_CAST_CHAR; Lex->charset= &my_charset_bin; Lex->dec= 0; }
- | CHAR_SYM opt_field_length opt_binary
+ | CHAR_SYM opt_field_length
+ { Lex->charset= thd->variables.collation_connection; }
+ opt_binary
{ $$=ITEM_CAST_CHAR; Lex->dec= 0; }
| NCHAR_SYM opt_field_length
{ $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; Lex->dec=0; }
@@ -9524,11 +10338,11 @@ expr_list:
$$= new (thd->mem_root) List<Item>;
if ($$ == NULL)
MYSQL_YYABORT;
- $$->push_back($1);
+ $$->push_back($1, thd->mem_root);
}
| expr_list ',' expr
{
- $1->push_back($3);
+ $1->push_back($3, thd->mem_root);
$$= $1;
}
;
@@ -9544,11 +10358,11 @@ ident_list:
$$= new (thd->mem_root) List<Item>;
if ($$ == NULL)
MYSQL_YYABORT;
- $$->push_back($1);
+ $$->push_back($1, thd->mem_root);
}
| ident_list ',' simple_ident
{
- $1->push_back($3);
+ $1->push_back($3, thd->mem_root);
$$= $1;
}
;
@@ -9566,16 +10380,16 @@ opt_else:
when_list:
WHEN_SYM expr THEN_SYM expr
{
- $$= new List<Item>;
+ $$= new (thd->mem_root) List<Item>;
if ($$ == NULL)
MYSQL_YYABORT;
- $$->push_back($2);
- $$->push_back($4);
+ $$->push_back($2, thd->mem_root);
+ $$->push_back($4, thd->mem_root);
}
| when_list WHEN_SYM expr THEN_SYM expr
{
- $1->push_back($3);
- $1->push_back($5);
+ $1->push_back($3, thd->mem_root);
+ $1->push_back($5, thd->mem_root);
$$= $1;
}
;
@@ -9587,9 +10401,9 @@ table_ref:
| join_table
{
LEX *lex= Lex;
- if (!($$= lex->current_select->nest_last_join(lex->thd)))
+ if (!($$= lex->current_select->nest_last_join(thd)))
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
}
@@ -9636,9 +10450,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
{
@@ -9650,23 +10462,8 @@ 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;
- add_join_on($3,$6);
+ $3->straight=$2;
+ add_join_on(thd, $3, $6);
Lex->pop_context();
Select->parsing_place= NO_MATTER;
}
@@ -9676,10 +10473,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);
}
@@ -9695,7 +10497,7 @@ join_table:
}
expr
{
- add_join_on($5,$8);
+ add_join_on(thd, $5, $8);
Lex->pop_context();
$5->outer_join|=JOIN_TYPE_LEFT;
$$=$5;
@@ -9734,7 +10536,7 @@ join_table:
LEX *lex= Lex;
if (!($$= lex->current_select->convert_right_join()))
MYSQL_YYABORT;
- add_join_on($$, $8);
+ add_join_on(thd, $$, $8);
Lex->pop_context();
Select->parsing_place= NO_MATTER;
}
@@ -9759,12 +10561,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>
@@ -9778,13 +10602,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($$);
}
@@ -9796,15 +10621,11 @@ table_factor:
{
if (sel->set_braces(1))
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
- /* select in braces, can't contain global parameters */
- if (sel->master_unit()->fake_select_lex)
- sel->master_unit()->global_parameters=
- sel->master_unit()->fake_select_lex;
}
- if ($2->init_nested_join(lex->thd))
+ if ($2->init_nested_join(thd))
MYSQL_YYABORT;
$$= 0;
/* incomplete derived tables return NULL, we must be
@@ -9850,11 +10671,11 @@ table_factor:
SELECT_LEX *sel= lex->current_select;
SELECT_LEX_UNIT *unit= sel->master_unit();
lex->current_select= sel= unit->outer_select();
- Table_ident *ti= new Table_ident(unit);
+ Table_ident *ti= new (thd->mem_root) Table_ident(unit);
if (ti == NULL)
MYSQL_YYABORT;
- if (!($$= sel->add_table_to_list(lex->thd,
- new Table_ident(unit), $5, 0,
+ if (!($$= sel->add_table_to_list(thd,
+ ti, $5, 0,
TL_READ, MDL_SHARED_READ)))
MYSQL_YYABORT;
@@ -9872,7 +10693,7 @@ table_factor:
Tables with or without joins within parentheses cannot
have aliases, and we ruled out derived tables above.
*/
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
else
@@ -9917,7 +10738,7 @@ select_derived_union:
{
if ($1 && $2)
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
}
@@ -9935,12 +10756,10 @@ select_derived_union:
last select in the union.
*/
Lex->pop_context();
- }
- opt_union_order_or_limit
- {
+
if ($1 != NULL)
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
}
@@ -9951,16 +10770,9 @@ select_init2_derived:
select_part2_derived
{
LEX *lex= Lex;
- SELECT_LEX * sel= lex->current_select;
if (lex->current_select->set_braces(0))
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
- MYSQL_YYABORT;
- }
- if (sel->linkage == UNION_TYPE &&
- sel->master_unit()->first_select()->braces)
- {
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
}
@@ -9979,28 +10791,25 @@ select_part2_derived:
{
Select->parsing_place= NO_MATTER;
}
- opt_select_from select_lock_type
;
/* handle contents of parentheses in join expression */
select_derived:
get_select_lex
{
- LEX *lex= Lex;
- if ($1->init_nested_join(lex->thd))
+ if ($1->init_nested_join(thd))
MYSQL_YYABORT;
}
derived_table_list
{
- LEX *lex= Lex;
/* for normal joins, $3 != NULL and end_nested_join() != NULL,
for derived tables, both must equal NULL */
- if (!($$= $1->end_nested_join(lex->thd)) && $3)
+ if (!($$= $1->end_nested_join(thd)) && $3)
MYSQL_YYABORT;
if (!$3 && $$)
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
}
@@ -10013,7 +10822,7 @@ select_derived2:
if (!lex->expr_allows_subselect ||
lex->sql_command == (int)SQLCOM_PURGE)
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
@@ -10027,7 +10836,7 @@ select_derived2:
{
Select->parsing_place= NO_MATTER;
}
- opt_select_from
+ table_expression
;
get_select_lex:
@@ -10040,17 +10849,14 @@ select_derived_init:
LEX *lex= Lex;
if (! lex->parsing_options.allows_derived)
- {
- my_error(ER_VIEW_SELECT_DERIVED, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_DERIVED, MYF(0)));
SELECT_LEX *sel= lex->current_select;
TABLE_LIST *embedding;
- if (!sel->embedding || sel->end_nested_join(lex->thd))
+ if (!sel->embedding || sel->end_nested_join(thd))
{
/* we are not in parentheses */
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
embedding= Select->embedding;
@@ -10128,14 +10934,14 @@ key_usage_list:
using_list:
ident
{
- if (!($$= new List<String>))
+ if (!($$= new (thd->mem_root) List<String>))
MYSQL_YYABORT;
String *s= new (thd->mem_root) String((const char *) $1.str,
$1.length,
system_charset_info);
if (s == NULL)
MYSQL_YYABORT;
- $$->push_back(s);
+ $$->push_back(s, thd->mem_root);
}
| using_list ',' ident
{
@@ -10144,7 +10950,7 @@ using_list:
system_charset_info);
if (s == NULL)
MYSQL_YYABORT;
- $1->push_back(s);
+ $1->push_back(s, thd->mem_root);
$$= $1;
}
;
@@ -10193,7 +10999,7 @@ opt_table_alias:
/* empty */ { $$=0; }
| table_alias ident
{
- $$= (LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING));
+ $$= (LEX_STRING*) thd->memdup(&$2,sizeof(LEX_STRING));
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -10204,7 +11010,7 @@ opt_all:
| ALL
;
-where_clause:
+opt_where_clause:
/* empty */ { Select->where= 0; }
| WHERE
{
@@ -10213,14 +11019,14 @@ where_clause:
expr
{
SELECT_LEX *select= Select;
- select->where= normalize_cond($3);
+ select->where= normalize_cond(thd, $3);
select->parsing_place= NO_MATTER;
if ($3)
$3->top_level_item();
}
;
-having_clause:
+opt_having_clause:
/* empty */
| HAVING
{
@@ -10229,7 +11035,7 @@ having_clause:
expr
{
SELECT_LEX *sel= Select;
- sel->having= normalize_cond($3);
+ sel->having= normalize_cond(thd, $3);
sel->parsing_place= NO_MATTER;
if ($3)
$3->top_level_item();
@@ -10246,8 +11052,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(thd, "", 0) :
+ new (thd->mem_root) Item_string_ascii(thd, "\\", 1));
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -10257,7 +11063,7 @@ opt_escape:
group by statement in select
*/
-group_clause:
+opt_group_clause:
/* empty */
| GROUP_SYM BY group_list olap_opt
;
@@ -10282,14 +11088,11 @@ olap_opt:
*/
LEX *lex=Lex;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "WITH CUBE",
- "global union parameters");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH CUBE",
+ "global union parameters"));
lex->current_select->olap= CUBE_TYPE;
- my_error(ER_NOT_SUPPORTED_YET, MYF(0), "CUBE");
- MYSQL_YYABORT;
+
+ my_yyabort_error((ER_NOT_SUPPORTED_YET, MYF(0), "CUBE"));
}
| WITH_ROLLUP_SYM
{
@@ -10302,11 +11105,8 @@ olap_opt:
*/
LEX *lex= Lex;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
- "global union parameters");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
+ "global union parameters"));
lex->current_select->olap= ROLLUP_TYPE;
}
;
@@ -10356,7 +11156,8 @@ order_clause:
"CUBE/ROLLUP", "ORDER BY");
MYSQL_YYABORT;
}
- if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
+ if (lex->sql_command != SQLCOM_ALTER_TABLE &&
+ !unit->fake_select_lex)
{
/*
A query of the of the form (SELECT ...) ORDER BY order_list is
@@ -10370,12 +11171,26 @@ order_clause:
if (!unit->is_union() &&
(first_sl->order_list.elements ||
first_sl->select_limit) &&
- unit->add_fake_select_lex(lex->thd))
+ unit->add_fake_select_lex(thd))
MYSQL_YYABORT;
}
+ if (sel->master_unit()->is_union() && !sel->braces)
+ {
+ /*
+ At this point we don't know yet whether this is the last
+ select in union or not, but we move ORDER BY to
+ fake_select_lex anyway. If there would be one more select
+ in union mysql_new_select will correctly throw error.
+ */
+ DBUG_ASSERT(sel->master_unit()->fake_select_lex);
+ lex->current_select= sel->master_unit()->fake_select_lex;
+ }
}
order_list
- ;
+ {
+
+ }
+ ;
order_list:
order_list ',' order_ident order_dir
@@ -10390,33 +11205,38 @@ order_dir:
| DESC { $$ =0; }
;
-opt_limit_clause_init:
- /* empty */
- {
- LEX *lex= Lex;
- SELECT_LEX *sel= lex->current_select;
- sel->offset_limit= 0;
- sel->select_limit= 0;
- lex->limit_rows_examined= 0;
- }
- | limit_clause {}
- ;
-
opt_limit_clause:
/* empty */ {}
| limit_clause {}
;
+limit_clause_init:
+ LIMIT
+ {
+ SELECT_LEX *sel= Select;
+ if (sel->master_unit()->is_union() && !sel->braces)
+ {
+ /* Move LIMIT that belongs to UNION to fake_select_lex */
+ Lex->current_select= sel->master_unit()->fake_select_lex;
+ DBUG_ASSERT(Select);
+ }
+ }
+ ;
+
limit_clause:
- LIMIT limit_options
+ limit_clause_init 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
+ | limit_clause_init limit_options
+ ROWS_SYM EXAMINED_SYM limit_rows_option
{
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
}
- | LIMIT ROWS_SYM EXAMINED_SYM limit_rows_option
+ | limit_clause_init ROWS_SYM EXAMINED_SYM limit_rows_option
{
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
}
@@ -10452,12 +11272,12 @@ 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,
+ Item_splocal(thd, $1, spv->offset, spv->type,
lip->get_tok_start() - lex->sphead->m_tmp_query,
lip->get_ptr() - lip->get_tok_start());
if (splocal == NULL)
@@ -10468,37 +11288,31 @@ limit_option:
lex->safe_to_cache_query=0;
}
else
- {
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
if (splocal->type() != Item::INT_ITEM)
- {
- my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0)));
splocal->limit_clause_param= TRUE;
$$= splocal;
}
| param_marker
{
- ((Item_param *) $1)->limit_clause_param= TRUE;
+ $1->limit_clause_param= TRUE;
}
| ULONGLONG_NUM
{
- $$= new (thd->mem_root) Item_uint($1.str, $1.length);
+ $$= new (thd->mem_root) Item_uint(thd, $1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
| LONG_NUM
{
- $$= new (thd->mem_root) Item_uint($1.str, $1.length);
+ $$= new (thd->mem_root) Item_uint(thd, $1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
| NUM
{
- $$= new (thd->mem_root) Item_uint($1.str, $1.length);
+ $$= new (thd->mem_root) Item_uint(thd, $1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -10524,8 +11338,8 @@ delete_limit_clause:
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
sel->explicit_limit= 1;
}
- | LIMIT ROWS_SYM EXAMINED_SYM { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; }
- | LIMIT limit_option ROWS_SYM EXAMINED_SYM { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; }
+ | LIMIT ROWS_SYM EXAMINED_SYM { my_parse_error(thd, ER_SYNTAX_ERROR); MYSQL_YYABORT; }
+ | LIMIT limit_option ROWS_SYM EXAMINED_SYM { my_parse_error(thd, ER_SYNTAX_ERROR); MYSQL_YYABORT; }
;
int_num:
@@ -10569,7 +11383,7 @@ real_ulonglong_num:
dec_num_error:
dec_num
- { my_parse_error(ER(ER_ONLY_INTEGERS_ALLOWED)); }
+ { my_parse_error(thd, ER_ONLY_INTEGERS_ALLOWED); }
;
dec_num:
@@ -10582,32 +11396,26 @@ choice:
| DEFAULT { $$= HA_CHOICE_UNDEF; }
;
-procedure_clause:
- /* empty */
+opt_procedure_clause:
+ /* empty */ { $$= false; }
| PROCEDURE_SYM ident /* Procedure name */
{
LEX *lex=Lex;
if (! lex->parsing_options.allows_select_procedure)
- {
- my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "PROCEDURE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_CLAUSE, MYF(0), "PROCEDURE"));
if (&lex->select_lex != lex->current_select)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery"));
lex->proc_list.elements=0;
lex->proc_list.first=0;
lex->proc_list.next= &lex->proc_list.first;
Item_field *item= new (thd->mem_root)
- Item_field(&lex->current_select->context,
+ Item_field(thd, &lex->current_select->context,
NULL, NULL, $2.str);
if (item == NULL)
MYSQL_YYABORT;
- if (add_proc_to_list(lex->thd, item))
+ if (add_proc_to_list(thd, item))
MYSQL_YYABORT;
Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -10623,6 +11431,7 @@ procedure_clause:
{
/* Subqueries are allowed from now.*/
Lex->expr_allows_subselect= true;
+ $$= true;
}
;
@@ -10649,7 +11458,8 @@ procedure_item:
select_var_list_init:
{
LEX *lex=Lex;
- if (!lex->describe && (!(lex->result= new select_dumpvar())))
+ if (!lex->describe &&
+ (!(lex->result= new (thd->mem_root) select_dumpvar(thd))))
MYSQL_YYABORT;
}
select_var_list
@@ -10661,16 +11471,13 @@ select_var_list:
| select_var_ident {}
;
-select_var_ident:
- '@' ident_or_text
+select_var_ident: select_outvar
{
- LEX *lex=Lex;
- if (lex->result)
+ if (Lex->result)
{
- my_var *var= new my_var($2,0,0,(enum_field_types)0);
- if (var == NULL)
+ if ($1 == NULL)
MYSQL_YYABORT;
- ((select_dumpvar *)lex->result)->var_list.push_back(var);
+ ((select_dumpvar *)Lex->result)->var_list.push_back($1, thd->mem_root);
}
else
{
@@ -10678,48 +11485,39 @@ select_var_ident:
The parser won't create select_result instance only
if it's an EXPLAIN.
*/
- DBUG_ASSERT(lex->describe);
+ DBUG_ASSERT(Lex->describe);
}
}
+ ;
+
+select_outvar:
+ '@' ident_or_text
+ {
+ $$ = Lex->result ? new (thd->mem_root) my_var_user($2) : NULL;
+ }
| ident_or_text
{
- LEX *lex=Lex;
- sp_variable_t *t;
+ sp_variable *t;
- if (!lex->spcont || !(t=lex->spcont->find_variable(&$1)))
- {
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
- if (lex->result)
- {
- my_var *var= new my_var($1,1,t->offset,t->type);
- if (var == NULL)
- MYSQL_YYABORT;
- ((select_dumpvar *)lex->result)->var_list.push_back(var);
-#ifndef DBUG_OFF
- var->sp= lex->sphead;
-#endif
- }
- else
- {
- /*
- The parser won't create select_result instance only
- if it's an EXPLAIN.
- */
- DBUG_ASSERT(lex->describe);
- }
+ if (!Lex->spcont || !(t= Lex->spcont->find_variable($1, false)))
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
+ $$ = Lex->result ? (new (thd->mem_root)
+ my_var_sp($1, t->offset, t->type,
+ Lex->sphead)) :
+ NULL;
}
;
+opt_into:
+ /* empty */ { $$= false; }
+ | into { $$= true; }
+ ;
+
into:
INTO
{
if (! Lex->parsing_options.allows_select_into)
- {
- my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "INTO");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_CLAUSE, MYF(0), "INTO"));
}
into_destination
;
@@ -10729,8 +11527,10 @@ into_destination:
{
LEX *lex= Lex;
lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- if (!(lex->exchange= new sql_exchange($2.str, 0)) ||
- !(lex->result= new select_export(lex->exchange)))
+ if (!(lex->exchange=
+ new (thd->mem_root) sql_exchange($2.str, 0)) ||
+ !(lex->result=
+ new (thd->mem_root) select_export(thd, lex->exchange)))
MYSQL_YYABORT;
}
opt_load_data_charset
@@ -10742,9 +11542,10 @@ into_destination:
if (!lex->describe)
{
lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- if (!(lex->exchange= new sql_exchange($2.str,1)))
+ if (!(lex->exchange= new (thd->mem_root) sql_exchange($2.str,1)))
MYSQL_YYABORT;
- if (!(lex->result= new select_dump(lex->exchange)))
+ if (!(lex->result=
+ new (thd->mem_root) select_dump(thd, lex->exchange)))
MYSQL_YYABORT;
}
}
@@ -10776,119 +11577,103 @@ 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->set_command(SQLCOM_DROP_TABLE, $2, $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_table_element ident ON table_ident {}
{
LEX *lex=Lex;
- Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $3.str);
+ Alter_drop *ad= (new (thd->mem_root)
+ 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.drop_list.push_back(ad);
- if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
+ lex->alter_info.flags= Alter_info::ALTER_DROP_INDEX;
+ lex->alter_info.drop_list.push_back(ad, thd->mem_root);
+ if (!lex->current_select->add_table_to_list(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->set_command(SQLCOM_DROP_DB, $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;
if ($4.str && check_db_name(&$4))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), $4.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $4.str));
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
- MYSQL_YYABORT;
- }
- lex->sql_command = SQLCOM_DROP_FUNCTION;
- lex->drop_if_exists= $3;
- spname= new sp_name($4, $6, true);
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
+ lex->set_command(SQLCOM_DROP_FUNCTION, $3);
+ spname= new (thd->mem_root) 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};
sp_name *spname;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
if (thd->db && lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
- lex->sql_command = SQLCOM_DROP_FUNCTION;
- lex->drop_if_exists= $3;
- spname= new sp_name(db, $4, false);
+ lex->set_command(SQLCOM_DROP_FUNCTION, $3);
+ spname= new (thd->mem_root) 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)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
- MYSQL_YYABORT;
- }
- lex->sql_command = SQLCOM_DROP_PROCEDURE;
- lex->drop_if_exists= $3;
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
+ lex->set_command(SQLCOM_DROP_PROCEDURE, $3);
lex->spname= $4;
}
- | DROP USER clear_privileges user_list
+ | DROP USER_SYM opt_if_exists clear_privileges user_list
+ {
+ Lex->set_command(SQLCOM_DROP_USER, $3);
+ }
+ | DROP ROLE_SYM opt_if_exists clear_privileges role_list
{
- Lex->sql_command = SQLCOM_DROP_USER;
+ Lex->set_command(SQLCOM_DROP_ROLE, $3);
}
- | DROP VIEW_SYM if_exists
+ | DROP VIEW_SYM opt_if_exists
{
LEX *lex= Lex;
- lex->sql_command= SQLCOM_DROP_VIEW;
- lex->drop_if_exists= $3;
+ lex->set_command(SQLCOM_DROP_VIEW, $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->spname= $4;
- Lex->sql_command = SQLCOM_DROP_EVENT;
+ Lex->set_command(SQLCOM_DROP_EVENT, $3);
}
- | 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->set_command(SQLCOM_DROP_TRIGGER, $3);
lex->spname= $4;
}
| DROP TABLESPACE tablespace_name opt_ts_engine opt_ts_wait
@@ -10901,12 +11686,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->server_options.server_name= $4.str;
- Lex->server_options.server_name_length= $4.length;
+ Lex->set_command(SQLCOM_DROP_SERVER, $3);
+ Lex->server_options.reset($4);
}
;
@@ -10926,6 +11709,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
@@ -10942,14 +11738,33 @@ table_alias_ref:
}
;
-if_exists:
- /* empty */ { $$= 0; }
- | IF EXISTS { $$= 1; }
+opt_if_exists_table_element:
+ /* empty */
+ {
+ Lex->check_exists= FALSE;
+ $$= 0;
+ }
+ | IF_SYM EXISTS
+ {
+ Lex->check_exists= TRUE;
+ $$= 1;
+ }
+ ;
+
+opt_if_exists:
+ /* empty */
+ {
+ $$.set(DDL_options_st::OPT_NONE);
+ }
+ | IF_SYM EXISTS
+ {
+ $$.set(DDL_options_st::OPT_IF_EXISTS);
+ }
;
opt_temporary:
/* empty */ { $$= 0; }
- | TEMPORARY { $$= 1; }
+ | TEMPORARY { $$= HA_LEX_CREATE_TMP_TABLE; }
;
/*
** Insert : add new data to table
@@ -11030,7 +11845,7 @@ insert2:
;
insert_table:
- table_name
+ table_name_with_opt_use_partition
{
LEX *lex=Lex;
lex->field_list.empty();
@@ -11045,16 +11860,17 @@ insert_field_spec:
| SET
{
LEX *lex=Lex;
- if (!(lex->insert_list = new List_item) ||
- lex->many_values.push_back(lex->insert_list))
+ if (!(lex->insert_list= new (thd->mem_root) List_item) ||
+ lex->many_values.push_back(lex->insert_list, thd->mem_root))
MYSQL_YYABORT;
}
ident_eq_list
;
fields:
- fields ',' insert_ident { Lex->field_list.push_back($3); }
- | insert_ident { Lex->field_list.push_back($1); }
+ fields ',' insert_ident
+ { Lex->field_list.push_back($3, thd->mem_root); }
+ | insert_ident { Lex->field_list.push_back($1, thd->mem_root); }
;
insert_values:
@@ -11082,8 +11898,8 @@ ident_eq_value:
simple_ident_nospvar equal expr_or_default
{
LEX *lex=Lex;
- if (lex->field_list.push_back($1) ||
- lex->insert_list->push_back($3))
+ if (lex->field_list.push_back($1, thd->mem_root) ||
+ lex->insert_list->push_back($3, thd->mem_root))
MYSQL_YYABORT;
}
;
@@ -11101,13 +11917,13 @@ opt_equal:
no_braces:
'('
{
- if (!(Lex->insert_list = new List_item))
+ if (!(Lex->insert_list= new (thd->mem_root) List_item))
MYSQL_YYABORT;
}
opt_values ')'
{
LEX *lex=Lex;
- if (lex->many_values.push_back(lex->insert_list))
+ if (lex->many_values.push_back(lex->insert_list, thd->mem_root))
MYSQL_YYABORT;
}
;
@@ -11120,12 +11936,12 @@ opt_values:
values:
values ',' expr_or_default
{
- if (Lex->insert_list->push_back($3))
+ if (Lex->insert_list->push_back($3, thd->mem_root))
MYSQL_YYABORT;
}
| expr_or_default
{
- if (Lex->insert_list->push_back($1))
+ if (Lex->insert_list->push_back($1, thd->mem_root))
MYSQL_YYABORT;
}
;
@@ -11134,7 +11950,7 @@ expr_or_default:
expr { $$= $1;}
| DEFAULT
{
- $$= new (thd->mem_root) Item_default_value(Lex->current_context());
+ $$= new (thd->mem_root) Item_default_value(thd, Lex->current_context());
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -11176,7 +11992,7 @@ update:
*/
Select->set_lock_for_tables($3);
}
- where_clause opt_order_clause delete_limit_clause {}
+ opt_where_clause opt_order_clause delete_limit_clause {}
;
update_list:
@@ -11201,8 +12017,8 @@ insert_update_elem:
simple_ident_nospvar equal expr_or_default
{
LEX *lex= Lex;
- if (lex->update_list.push_back($1) ||
- lex->value_list.push_back($3))
+ if (lex->update_list.push_back($1, thd->mem_root) ||
+ lex->value_list.push_back($3, thd->mem_root))
MYSQL_YYABORT;
}
;
@@ -11230,24 +12046,27 @@ 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
+ opt_where_clause opt_order_clause
delete_limit_clause {}
+ opt_select_expressions {}
| table_wild_list
{
mysql_init_multi_delete(Lex);
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
}
- FROM join_table_list where_clause
+ FROM join_table_list opt_where_clause
{
if (multi_delete_set_locks_and_link_aux_tables(Lex))
MYSQL_YYABORT;
@@ -11258,13 +12077,18 @@ single_multi:
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
}
- USING join_table_list where_clause
+ USING join_table_list opt_where_clause
{
if (multi_delete_set_locks_and_link_aux_tables(Lex))
MYSQL_YYABORT;
}
;
+opt_select_expressions:
+ /* empty */
+ | RETURNING_SYM select_item_list
+ ;
+
table_wild_list:
table_wild_one
| table_wild_list ',' table_wild_one
@@ -11273,7 +12097,7 @@ table_wild_list:
table_wild_one:
ident opt_wild
{
- Table_ident *ti= new Table_ident($1);
+ Table_ident *ti= new (thd->mem_root) Table_ident($1);
if (ti == NULL)
MYSQL_YYABORT;
if (!Select->add_table_to_list(thd,
@@ -11286,7 +12110,7 @@ table_wild_one:
}
| ident '.' ident opt_wild
{
- Table_ident *ti= new Table_ident(thd, $1, $3, 0);
+ Table_ident *ti= new (thd->mem_root) Table_ident(thd, $1, $3, 0);
if (ti == NULL)
MYSQL_YYABORT;
if (!Select->add_table_to_list(thd,
@@ -11330,9 +12154,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;
}
;
@@ -11407,9 +12231,10 @@ 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));
+ lex->create_info.init();
}
show_param
{
@@ -11472,6 +12297,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
@@ -11497,13 +12335,14 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
- } opt_limit_clause_init
- | RELAYLOG_SYM EVENTS_SYM binlog_in binlog_from
+ }
+ opt_limit_clause
+ | RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in binlog_from
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_RELAYLOG_EVENTS;
- } opt_limit_clause_init
- | keys_or_index from_or_in table_ident opt_db where_clause
+ } opt_limit_clause
+ | keys_or_index from_or_in table_ident opt_db opt_where_clause
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_KEYS;
@@ -11523,19 +12362,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
{
@@ -11546,25 +12377,25 @@ show_param:
{ (void) create_select_for_variable("warning_count"); }
| COUNT_SYM '(' '*' ')' ERRORS
{ (void) create_select_for_variable("error_count"); }
- | WARNINGS opt_limit_clause_init
+ | WARNINGS opt_limit_clause
{ Lex->sql_command = SQLCOM_SHOW_WARNS;}
- | ERRORS opt_limit_clause_init
+ | ERRORS opt_limit_clause
{ Lex->sql_command = SQLCOM_SHOW_ERRORS;}
| PROFILES_SYM
{ Lex->sql_command = SQLCOM_SHOW_PROFILES; }
- | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause_init
+ | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_PROFILE;
if (prepare_schema_table(thd, lex, NULL, SCH_PROFILES) != 0)
- YYABORT;
+ MYSQL_YYABORT;
}
| opt_var_type STATUS_SYM wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_STATUS;
lex->option_type= $1;
- if (prepare_schema_table(thd, lex, 0, SCH_STATUS))
+ if (prepare_schema_table(thd, lex, 0, SCH_SESSION_STATUS))
MYSQL_YYABORT;
}
| opt_full PROCESSLIST_SYM
@@ -11574,7 +12405,7 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_VARIABLES;
lex->option_type= $1;
- if (prepare_schema_table(thd, lex, 0, SCH_VARIABLES))
+ if (prepare_schema_table(thd, lex, 0, SCH_SESSION_VARIABLES))
MYSQL_YYABORT;
}
| charset wild_and_where
@@ -11593,25 +12424,20 @@ 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 clear_privileges
{
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
{
- Lex->sql_command=SQLCOM_SHOW_CREATE_DB;
- Lex->create_info.options=$3;
+ Lex->set_command(SQLCOM_SHOW_CREATE_DB, $3);
Lex->name= $4;
}
| CREATE TABLE_SYM table_ident
@@ -11634,37 +12460,22 @@ show_param:
{
Lex->sql_command = SQLCOM_SHOW_MASTER_STAT;
}
- | SLAVE STATUS_SYM
+ | ALL SLAVES STATUS_SYM
{
Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
+ Lex->verbose= 1;
}
- | CLIENT_STATS_SYM
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_CLIENT_STATS;
- if (prepare_schema_table(thd, lex, 0, SCH_CLIENT_STATS))
- MYSQL_YYABORT;
- }
- | USER_STATS_SYM
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_USER_STATS;
- if (prepare_schema_table(thd, lex, 0, SCH_USER_STATS))
- MYSQL_YYABORT;
- }
- | TABLE_STATS_SYM
+ | SLAVE STATUS_SYM
{
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_TABLE_STATS;
- if (prepare_schema_table(thd, lex, 0, SCH_TABLE_STATS))
- MYSQL_YYABORT;
+ LEX *lex= thd->lex;
+ lex->mi.connection_name= null_lex_str;
+ lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
+ lex->verbose= 0;
}
- | INDEX_STATS_SYM
+ | SLAVE connection_name STATUS_SYM
{
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_INDEX_STATS;
- if (prepare_schema_table(thd, lex, 0, SCH_INDEX_STATS))
- MYSQL_YYABORT;
+ Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
+ Lex->verbose= 0;
}
| CREATE PROCEDURE_SYM sp_name
{
@@ -11715,6 +12526,32 @@ 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);
+ }
+ | IDENT_sys remember_tok_start wild_and_where
+ {
+ LEX *lex= Lex;
+ bool in_plugin;
+ lex->sql_command= SQLCOM_SHOW_GENERIC;
+ ST_SCHEMA_TABLE *table= find_schema_table(thd, $1.str, &in_plugin);
+ if (!table || !table->old_format || !in_plugin)
+ {
+ my_parse_error(thd, ER_SYNTAX_ERROR, $2);
+ MYSQL_YYABORT;
+ }
+ if (lex->wild && table->idx_field1 < 0)
+ {
+ my_parse_error(thd, ER_SYNTAX_ERROR, $3);
+ MYSQL_YYABORT;
+ }
+ if (make_schema_select(thd, Lex->current_select, table))
+ MYSQL_YYABORT;
+ }
;
show_engine_param:
@@ -11762,19 +12599,21 @@ binlog_from:
;
wild_and_where:
- /* empty */
- | LIKE TEXT_STRING_sys
+ /* empty */ { $$= 0; }
+ | LIKE remember_tok_start TEXT_STRING_sys
{
- Lex->wild= new (thd->mem_root) String($2.str, $2.length,
+ Lex->wild= new (thd->mem_root) String($3.str, $3.length,
system_charset_info);
if (Lex->wild == NULL)
MYSQL_YYABORT;
+ $$= $2;
}
- | WHERE expr
+ | WHERE remember_tok_start expr
{
- Select->where= normalize_cond($2);
- if ($2)
- $2->top_level_item();
+ Select->where= normalize_cond(thd, $3);
+ if ($3)
+ $3->top_level_item();
+ $$= $2;
}
;
@@ -11797,22 +12636,50 @@ 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
;
+analyze_stmt_command:
+ ANALYZE_SYM opt_format_json explainable_command
+ {
+ Lex->analyze_stmt= true;
+ }
+ ;
+
opt_extended_describe:
- /* empty */ {}
- | EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; }
+ EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; }
| PARTITIONS_SYM { Lex->describe|= DESCRIBE_PARTITIONS; }
+ | opt_format_json {}
+ ;
+
+opt_format_json:
+ /* empty */ {}
+ | FORMAT_SYM '=' ident_or_text
+ {
+ if (!my_strcasecmp(system_charset_info, $3.str, "JSON"))
+ Lex->explain_json= true;
+ else if (!my_strcasecmp(system_charset_info, $3.str, "TRADITIONAL"))
+ DBUG_ASSERT(Lex->explain_json==false);
+ else
+ my_yyabort_error((ER_UNKNOWN_EXPLAIN_FORMAT, MYF(0), $3.str));
+ }
;
opt_describe_column:
@@ -11854,24 +12721,37 @@ 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(thd, ER_NO_TABLES_USED);
+ MYSQL_YYABORT;
+ }
+ Lex->type|= REFRESH_FOR_EXPORT;
+ } EXPORT_SYM {}
;
flush_options_list:
@@ -11889,10 +12769,16 @@ flush_option:
{ Lex->type|= REFRESH_GENERAL_LOG; }
| SLOW LOGS_SYM
{ Lex->type|= REFRESH_SLOW_LOG; }
- | BINARY LOGS_SYM
+ | BINARY LOGS_SYM opt_delete_gtid_domain
{ 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_yyabort_error((ER_WRONG_USAGE, MYF(0), "FLUSH", "RELAY LOGS"));
+ 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
@@ -11900,28 +12786,39 @@ flush_option:
| PRIVILEGES
{ Lex->type|= REFRESH_GRANT; }
| LOGS_SYM
- { Lex->type|= REFRESH_LOG; }
+ {
+ Lex->type|= REFRESH_LOG;
+ Lex->relay_log_connection_name= empty_lex_str;
+ }
| STATUS_SYM
{ Lex->type|= REFRESH_STATUS; }
- | SLAVE
+ | SLAVE optional_connection_name
{
- Lex->type|= REFRESH_SLAVE;
- Lex->reset_slave_info.all= false;
- }
- | CLIENT_STATS_SYM
- { Lex->type|= REFRESH_CLIENT_STATS; }
- | USER_STATS_SYM
- { Lex->type|= REFRESH_USER_STATS; }
- | TABLE_STATS_SYM
- { Lex->type|= REFRESH_TABLE_STATS; }
- | INDEX_STATS_SYM
- { Lex->type|= REFRESH_INDEX_STATS; }
+ LEX *lex= Lex;
+ if (lex->type & REFRESH_SLAVE)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "FLUSH","SLAVE"));
+ lex->type|= REFRESH_SLAVE;
+ lex->reset_slave_info.all= false;
+ }
| MASTER_SYM
{ Lex->type|= REFRESH_MASTER; }
| DES_KEY_FILE
{ Lex->type|= REFRESH_DES_KEY_FILE; }
| RESOURCES
{ Lex->type|= REFRESH_USER_RESOURCES; }
+ | IDENT_sys remember_tok_start
+ {
+ Lex->type|= REFRESH_GENERIC;
+ ST_SCHEMA_TABLE *table= find_schema_table(thd, $1.str);
+ if (!table || !table->reset_table)
+ {
+ my_parse_error(thd, ER_SYNTAX_ERROR, $2);
+ MYSQL_YYABORT;
+ }
+ Lex->view_list.push_back((LEX_STRING*)
+ thd->memdup(&$1, sizeof(LEX_STRING)),
+ thd->mem_root);
+ }
;
opt_table_list:
@@ -11929,6 +12826,33 @@ opt_table_list:
| table_list {}
;
+opt_delete_gtid_domain:
+ /* empty */ {}
+ | DELETE_DOMAIN_ID_SYM '=' '(' delete_domain_id_list ')'
+ {}
+ ;
+delete_domain_id_list:
+ /* Empty */
+ | delete_domain_id
+ | delete_domain_id_list ',' delete_domain_id
+ ;
+
+delete_domain_id:
+ ulonglong_num
+ {
+ uint32 value= (uint32) $1;
+ if ($1 > UINT_MAX32)
+ {
+ my_printf_error(ER_BINLOG_CANT_DELETE_GTID_DOMAIN,
+ "The value of gtid domain being deleted ('%llu') "
+ "exceeds its maximum size "
+ "of 32 bit unsigned integer", MYF(0), $1);
+ MYSQL_YYABORT;
+ }
+ insert_dynamic(&Lex->delete_gtid_domain, (uchar*) &value);
+ }
+ ;
+
optional_flush_tables_arguments:
/* empty */ {$$= 0;}
| AND_SYM DISABLE_SYM CHECKPOINT_SYM {$$= REFRESH_CHECKPOINT; }
@@ -11950,8 +12874,14 @@ reset_options:
reset_option:
SLAVE { Lex->type|= REFRESH_SLAVE; }
+ optional_connection_name
slave_reset_options { }
- | MASTER_SYM { Lex->type|= REFRESH_MASTER; }
+ | MASTER_SYM
+ {
+ Lex->type|= REFRESH_MASTER;
+ Lex->next_binlog_file_number= 0;
+ }
+ master_reset_options
| QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE;}
;
@@ -11960,6 +12890,14 @@ slave_reset_options:
| ALL { Lex->reset_slave_info.all= true; }
;
+master_reset_options:
+ /* empty */ {}
+ | TO_SYM ulong_num
+ {
+ Lex->next_binlog_file_number = $2;
+ }
+ ;
+
purge:
PURGE
{
@@ -11984,7 +12922,7 @@ purge_option:
{
LEX *lex= Lex;
lex->value_list.empty();
- lex->value_list.push_front($2);
+ lex->value_list.push_front($2, thd->mem_root);
lex->sql_command= SQLCOM_PURGE_BEFORE;
}
;
@@ -11998,6 +12936,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
{
@@ -12014,21 +12953,30 @@ 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;
+ Lex->value_list.push_front($$, thd->mem_root);
}
- | USER user
+ | USER_SYM user
{
- Lex->users_list.push_back($2);
+ Lex->users_list.push_back($2, thd->mem_root);
Lex->kill_type= KILL_TYPE_USER;
}
;
+
+shutdown:
+ SHUTDOWN { Lex->sql_command= SQLCOM_SHUTDOWN; }
+ ;
+
/* change database */
use:
@@ -12046,6 +12994,7 @@ load:
LOAD data_or_xml
{
LEX *lex= thd->lex;
+ mysql_init_select(lex);
if (lex->sphead)
{
@@ -12061,14 +13010,14 @@ load:
lex->local_file= $5;
lex->duplicates= DUP_ERROR;
lex->ignore= 0;
- if (!(lex->exchange= new sql_exchange($7.str, 0, $2)))
+ if (!(lex->exchange= new (thd->mem_root) 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();
@@ -12076,7 +13025,7 @@ load:
lex->many_values.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
@@ -12185,8 +13134,7 @@ opt_ignore_lines:
;
lines_or_rows:
- LINES { }
-
+ LINES { }
| ROWS_SYM { }
;
@@ -12198,16 +13146,16 @@ opt_field_or_var_spec:
fields_or_vars:
fields_or_vars ',' field_or_var
- { Lex->field_list.push_back($3); }
+ { Lex->field_list.push_back($3, thd->mem_root); }
| field_or_var
- { Lex->field_list.push_back($1); }
+ { Lex->field_list.push_back($1, thd->mem_root); }
;
field_or_var:
simple_ident_nospvar {$$= $1;}
| '@' ident_or_text
{
- $$= new (thd->mem_root) Item_user_var_as_out_param($2);
+ $$= new (thd->mem_root) Item_user_var_as_out_param(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -12227,8 +13175,8 @@ load_data_set_elem:
simple_ident_nospvar equal remember_name expr_or_default remember_end
{
LEX *lex= Lex;
- if (lex->update_list.push_back($1) ||
- lex->value_list.push_back($4))
+ if (lex->update_list.push_back($1, thd->mem_root) ||
+ lex->value_list.push_back($4, thd->mem_root))
MYSQL_YYABORT;
$4->set_name_no_truncate($3, (uint) ($5 - $3), thd->charset());
}
@@ -12254,7 +13202,8 @@ text_literal:
if (thd->convert_string(&tmp, cs_con, $1.str, $1.length, cs_cli))
MYSQL_YYABORT;
}
- $$= new (thd->mem_root) Item_string(tmp.str, tmp.length, cs_con,
+ $$= new (thd->mem_root) Item_string(thd, tmp.str, tmp.length,
+ cs_con,
DERIVATION_COERCIBLE,
repertoire);
if ($$ == NULL)
@@ -12265,7 +13214,7 @@ text_literal:
uint repertoire= Lex->text_string_is_7bit ?
MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30;
DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info));
- $$= new (thd->mem_root) Item_string($1.str, $1.length,
+ $$= new (thd->mem_root) Item_string(thd, $1.str, $1.length,
national_charset_info,
DERIVATION_COERCIBLE,
repertoire);
@@ -12274,14 +13223,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(thd, $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
{
@@ -12310,9 +13255,15 @@ 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);
+ Item *tmp= new (thd->mem_root) Item_hex_hybrid(thd, $1.str,
+ $1.length);
if (tmp == NULL)
MYSQL_YYABORT;
/*
@@ -12324,7 +13275,8 @@ text_string:
}
| HEX_STRING
{
- Item *tmp= new (thd->mem_root) Item_hex_string($1.str, $1.length);
+ Item *tmp= new (thd->mem_root) Item_hex_string(thd, $1.str,
+ $1.length);
if (tmp == NULL)
MYSQL_YYABORT;
tmp->quick_fix_field();
@@ -12332,7 +13284,8 @@ text_string:
}
| BIN_NUM
{
- Item *tmp= new (thd->mem_root) Item_bin_string($1.str, $1.length);
+ Item *tmp= new (thd->mem_root) Item_bin_string(thd, $1.str,
+ $1.length);
if (tmp == NULL)
MYSQL_YYABORT;
/*
@@ -12351,16 +13304,13 @@ param_marker:
Lex_input_stream *lip= YYLIP;
Item_param *item;
if (! lex->parsing_options.allows_variable)
- {
- my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
- MYSQL_YYABORT;
- }
- item= new (thd->mem_root) Item_param((uint) (lip->get_tok_start() - thd->query()));
- if (!($$= item) || lex->param_list.push_back(item))
- {
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
+ const char *query_start= lex->sphead ? lex->sphead->m_tmp_query
+ : thd->query();
+ item= new (thd->mem_root) Item_param(thd, lip->get_tok_start() -
+ query_start);
+ if (!($$= item) || lex->param_list.push_back(item, thd->mem_root))
+ my_yyabort_error((ER_OUT_OF_RESOURCES, MYF(0)));
}
;
@@ -12370,110 +13320,73 @@ signed_literal:
| '-' NUM_literal
{
$2->max_length++;
- $$= $2->neg();
+ $$= $2->neg(thd);
}
;
literal:
text_literal { $$ = $1; }
| NUM_literal { $$ = $1; }
+ | temporal_literal { $$= $1; }
| NULL_SYM
{
- $$ = new (thd->mem_root) Item_null();
+ /*
+ 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(thd);
if ($$ == NULL)
MYSQL_YYABORT;
YYLIP->next_state= MY_LEX_OPERATOR_OR_IDENT;
}
| FALSE_SYM
{
- $$= new (thd->mem_root) Item_int((char*) "FALSE",0,1);
+ $$= new (thd->mem_root) Item_int(thd, (char*) "FALSE",0,1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRUE_SYM
{
- $$= new (thd->mem_root) Item_int((char*) "TRUE",1,1);
+ $$= new (thd->mem_root) Item_int(thd, (char*) "TRUE",1,1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| HEX_NUM
{
- $$ = new (thd->mem_root) Item_hex_hybrid($1.str, $1.length);
+ $$= new (thd->mem_root) Item_hex_hybrid(thd, $1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
| HEX_STRING
{
- $$ = new (thd->mem_root) Item_hex_string($1.str, $1.length);
+ $$= new (thd->mem_root) Item_hex_string(thd, $1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
| BIN_NUM
{
- $$= new (thd->mem_root) Item_bin_string($1.str, $1.length);
+ $$= new (thd->mem_root) Item_bin_string(thd, $1.str, $1.length);
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(thd, 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:
@@ -12481,7 +13394,7 @@ NUM_literal:
{
int error;
$$= new (thd->mem_root)
- Item_int($1.str,
+ Item_int(thd, $1.str,
(longlong) my_strtoll10($1.str, NULL, &error),
$1.length);
if ($$ == NULL)
@@ -12491,7 +13404,7 @@ NUM_literal:
{
int error;
$$= new (thd->mem_root)
- Item_int($1.str,
+ Item_int(thd, $1.str,
(longlong) my_strtoll10($1.str, NULL, &error),
$1.length);
if ($$ == NULL)
@@ -12499,13 +13412,13 @@ NUM_literal:
}
| ULONGLONG_NUM
{
- $$= new (thd->mem_root) Item_uint($1.str, $1.length);
+ $$= new (thd->mem_root) Item_uint(thd, $1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
| DECIMAL_NUM
{
- $$= new (thd->mem_root) Item_decimal($1.str, $1.length,
+ $$= new (thd->mem_root) Item_decimal(thd, $1.str, $1.length,
thd->charset());
if (($$ == NULL) || (thd->is_error()))
{
@@ -12514,7 +13427,7 @@ NUM_literal:
}
| FLOAT_NUM
{
- $$= new (thd->mem_root) Item_float($1.str, $1.length);
+ $$= new (thd->mem_root) Item_float(thd, $1.str, $1.length);
if (($$ == NULL) || (thd->is_error()))
{
MYSQL_YYABORT;
@@ -12522,6 +13435,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.
**********************************************************************/
@@ -12535,7 +13473,7 @@ table_wild:
ident '.' '*'
{
SELECT_LEX *sel= Select;
- $$= new (thd->mem_root) Item_field(Lex->current_context(),
+ $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
NullS, $1.str, "*");
if ($$ == NULL)
MYSQL_YYABORT;
@@ -12546,7 +13484,7 @@ table_wild:
SELECT_LEX *sel= Select;
const char* schema= thd->client_capabilities & CLIENT_NO_SCHEMA ?
NullS : $1.str;
- $$= new (thd->mem_root) Item_field(Lex->current_context(),
+ $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
schema,
$3.str,"*");
if ($$ == NULL)
@@ -12564,20 +13502,17 @@ 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)
- {
- my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
Item_splocal *splocal;
splocal= new (thd->mem_root)
- Item_splocal($1, spv->offset, spv->type,
+ Item_splocal(thd, $1, spv->offset, spv->type,
lip->get_tok_start_prev() - lex->sphead->m_tmp_query,
lip->get_tok_end() - lip->get_tok_start_prev());
if (splocal == NULL)
@@ -12594,12 +13529,12 @@ simple_ident:
if ((sel->parsing_place != IN_HAVING) ||
(sel->get_in_sum_expr() > 0))
{
- $$= new (thd->mem_root) Item_field(Lex->current_context(),
+ $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
NullS, NullS, $1.str);
}
else
{
- $$= new (thd->mem_root) Item_ref(Lex->current_context(),
+ $$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
NullS, NullS, $1.str);
}
if ($$ == NULL)
@@ -12616,12 +13551,12 @@ simple_ident_nospvar:
if ((sel->parsing_place != IN_HAVING) ||
(sel->get_in_sum_expr() > 0))
{
- $$= new (thd->mem_root) Item_field(Lex->current_context(),
+ $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
NullS, NullS, $1.str);
}
else
{
- $$= new (thd->mem_root) Item_ref(Lex->current_context(),
+ $$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
NullS, NullS, $1.str);
}
if ($$ == NULL)
@@ -12649,31 +13584,25 @@ simple_ident_q:
if (lex->trg_chistics.event == TRG_EVENT_INSERT &&
!new_row)
- {
- my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT"));
if (lex->trg_chistics.event == TRG_EVENT_DELETE &&
new_row)
- {
- my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE"));
DBUG_ASSERT(!new_row ||
(lex->trg_chistics.event == TRG_EVENT_INSERT ||
lex->trg_chistics.event == TRG_EVENT_UPDATE));
- const bool read_only=
+ const bool tmp_read_only=
!(new_row && lex->trg_chistics.action_time == TRG_ACTION_BEFORE);
trg_fld= new (thd->mem_root)
- Item_trigger_field(Lex->current_context(),
+ Item_trigger_field(thd, Lex->current_context(),
new_row ?
Item_trigger_field::NEW_ROW:
Item_trigger_field::OLD_ROW,
$3.str,
SELECT_ACL,
- read_only);
+ tmp_read_only);
if (trg_fld == NULL)
MYSQL_YYABORT;
@@ -12697,12 +13626,12 @@ simple_ident_q:
if ((sel->parsing_place != IN_HAVING) ||
(sel->get_in_sum_expr() > 0))
{
- $$= new (thd->mem_root) Item_field(Lex->current_context(),
+ $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
NullS, $1.str, $3.str);
}
else
{
- $$= new (thd->mem_root) Item_ref(Lex->current_context(),
+ $$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
NullS, $1.str, $3.str);
}
if ($$ == NULL)
@@ -12721,13 +13650,13 @@ simple_ident_q:
if ((sel->parsing_place != IN_HAVING) ||
(sel->get_in_sum_expr() > 0))
{
- $$= new (thd->mem_root) Item_field(Lex->current_context(),
+ $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
NullS, $2.str, $4.str);
}
else
{
- $$= new (thd->mem_root) Item_ref(Lex->current_context(),
+ $$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
NullS, $2.str, $4.str);
}
if ($$ == NULL)
@@ -12747,13 +13676,13 @@ simple_ident_q:
if ((sel->parsing_place != IN_HAVING) ||
(sel->get_in_sum_expr() > 0))
{
- $$= new (thd->mem_root) Item_field(Lex->current_context(),
+ $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
schema,
$3.str, $5.str);
}
else
{
- $$= new (thd->mem_root) Item_ref(Lex->current_context(),
+ $$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
schema,
$3.str, $5.str);
}
@@ -12768,26 +13697,17 @@ field_ident:
{
TABLE_LIST *table= Select->table_list.first;
if (my_strcasecmp(table_alias_charset, $1.str, table->db))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
if (my_strcasecmp(table_alias_charset, $3.str,
table->table_name))
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $3.str));
$$=$5;
}
| ident '.' ident
{
TABLE_LIST *table= Select->table_list.first;
if (my_strcasecmp(table_alias_charset, $1.str, table->alias))
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $1.str));
$$=$3;
}
| '.' ident { $$=$2;} /* For Delphi */
@@ -12796,20 +13716,20 @@ field_ident:
table_ident:
ident
{
- $$= new Table_ident($1);
+ $$= new (thd->mem_root) Table_ident($1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| ident '.' ident
{
- $$= new Table_ident(thd, $1,$3,0);
+ $$= new (thd->mem_root) Table_ident(thd, $1, $3, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| '.' ident
{
/* For Delphi */
- $$= new Table_ident($2);
+ $$= new (thd->mem_root) Table_ident($2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -12818,13 +13738,13 @@ table_ident:
table_ident_opt_wild:
ident opt_wild
{
- $$= new Table_ident($1);
+ $$= new (thd->mem_root) Table_ident($1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| ident '.' ident opt_wild
{
- $$= new Table_ident(thd, $1,$3,0);
+ $$= new (thd->mem_root) Table_ident(thd, $1, $3, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -12834,7 +13754,7 @@ table_ident_nodb:
ident
{
LEX_STRING db={(char*) any_db,3};
- $$= new Table_ident(thd, db,$1,0);
+ $$= new (thd->mem_root) Table_ident(thd, db, $1, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -12862,8 +13782,8 @@ IDENT_sys:
}
else
{
- if (thd->convert_string(&$$, system_charset_info,
- $1.str, $1.length, thd->charset()))
+ if (thd->convert_with_error(system_charset_info, &$$,
+ thd->charset(), $1.str, $1.length))
MYSQL_YYABORT;
}
}
@@ -12940,19 +13860,16 @@ 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;
- $$->password= null_lex_str;
- $$->plugin= empty_lex_str;
- $$->auth= empty_lex_str;
+ $$->host= null_lex_str; // User or Role, see get_current_user()
+ $$->reset_auth();
- if (check_string_char_length(&$$->user, ER(ER_USERNAME),
+ if (check_string_char_length(&$$->user, ER_USERNAME,
username_char_length,
system_charset_info, 0))
MYSQL_YYABORT;
@@ -12962,35 +13879,51 @@ user:
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
$$->user = $1; $$->host=$3;
- $$->password= null_lex_str;
- $$->plugin= empty_lex_str;
- $$->auth= empty_lex_str;
+ $$->reset_auth();
- if (check_string_char_length(&$$->user, ER(ER_USERNAME),
+ if (check_string_char_length(&$$->user, ER_USERNAME,
username_char_length,
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 {}
@@ -13004,11 +13937,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 {}
@@ -13018,6 +13950,8 @@ keyword:
| EXAMINED_SYM {}
| EXECUTE_SYM {}
| FLUSH_SYM {}
+ | FORMAT_SYM {}
+ | GET_SYM {}
| HANDLER_SYM {}
| HELP_SYM {}
| HOST_SYM {}
@@ -13029,7 +13963,6 @@ keyword:
| OPTIONS_SYM {}
| OWNER_SYM {}
| PARSER_SYM {}
- | PARTITION_SYM {}
| PORT_SYM {}
| PREPARE_SYM {}
| REMOVE_SYM {}
@@ -13040,9 +13973,11 @@ keyword:
| SAVEPOINT_SYM {}
| SECURITY_SYM {}
| SERVER_SYM {}
+ | SHUTDOWN {}
| SIGNED_SYM {}
| SOCKET_SYM {}
| SLAVE {}
+ | SLAVES {}
| SONAME_SYM {}
| START_SYM {}
| STOP_SYM {}
@@ -13063,6 +13998,7 @@ keyword:
keyword_sp:
ACTION {}
| ADDDATE_SYM {}
+ | ADMIN_SYM {}
| AFTER_SYM {}
| AGAINST {}
| AGGREGATE_SYM {}
@@ -13070,9 +14006,11 @@ keyword_sp:
| ALWAYS_SYM {}
| ANY_SYM {}
| AT_SYM {}
+ | ATOMIC_SYM {}
| AUTHORS_SYM {}
| AUTO_INC {}
| AUTOEXTEND_SIZE_SYM {}
+ | AUTO_SYM {}
| AVG_ROW_LENGTH {}
| AVG_SYM {}
| BINLOG_SYM {}
@@ -13086,7 +14024,6 @@ keyword_sp:
| CHAIN_SYM {}
| CHANGED {}
| CIPHER_SYM {}
- | CLIENT_STATS_SYM {}
| CLIENT_SYM {}
| CLASS_ORIGIN_SYM {}
| COALESCE {}
@@ -13106,8 +14043,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 {}
@@ -13117,6 +14060,7 @@ keyword_sp:
| DEFINER_SYM {}
| DELAY_KEY_WRITE_SYM {}
| DES_KEY_FILE {}
+ | DIAGNOSTICS_SYM {}
| DIRECTORY_SYM {}
| DISABLE_SYM {}
| DISCARD {}
@@ -13134,7 +14078,9 @@ keyword_sp:
| EVENT_SYM {}
| EVENTS_SYM {}
| EVERY_SYM {}
+ | EXCHANGE_SYM {}
| EXPANSION_SYM {}
+ | EXPORT_SYM {}
| EXTENDED_SYM {}
| EXTENT_SIZE_SYM {}
| FAULTS_SYM {}
@@ -13156,9 +14102,9 @@ keyword_sp:
| HARD_SYM {}
| HOSTS_SYM {}
| HOUR_SYM {}
+ | ID_SYM {}
| IDENTIFIED_SYM {}
| IGNORE_SERVER_IDS_SYM {}
- | INDEX_STATS_SYM {}
| INVOKER_SYM {}
| IMPORT {}
| INDEXES {}
@@ -13183,11 +14129,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 {}
@@ -13196,10 +14144,13 @@ 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 {}
| MAX_SIZE_SYM {}
+ | MAX_STATEMENT_TIME_SYM {}
| MAX_UPDATES_PER_HOUR {}
| MAX_USER_CONNECTIONS_SYM {}
| MEDIUM_SYM {}
@@ -13223,24 +14174,24 @@ keyword_sp:
| NAMES_SYM {}
| NATIONAL_SYM {}
| NCHAR_SYM {}
- | NDBCLUSTER_SYM {}
| NEXT_SYM {}
| NEW_SYM {}
| NO_WAIT_SYM {}
| NODEGROUP_SYM {}
| NONE_SYM {}
+ | NUMBER_SYM {}
| NVARCHAR_SYM {}
| OFFSET_SYM {}
- | OLD_PASSWORD {}
- | ONE_SHOT_SYM {}
+ | OLD_PASSWORD_SYM {}
| ONE_SYM {}
| ONLINE_SYM {}
+ | ONLY_SYM {}
| PACK_KEYS_SYM {}
| PAGE_SYM {}
| PARTIAL {}
| PARTITIONING_SYM {}
| PARTITIONS_SYM {}
- | PASSWORD {}
+ | PASSWORD_SYM {}
| PERSISTENT_SYM {}
| PHASE_SYM {}
| PLUGIN_SYM {}
@@ -13275,10 +14226,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 {}
@@ -13290,7 +14245,7 @@ keyword_sp:
| SESSION_SYM {}
| SIMPLE_SYM {}
| SHARE_SYM {}
- | SHUTDOWN {}
+ | SLAVE_POS_SYM {}
| SLOW {}
| SNAPSHOT_SYM {}
| SOFT_SYM {}
@@ -13301,6 +14256,7 @@ keyword_sp:
| SQL_NO_CACHE_SYM {}
| SQL_THREAD {}
| STARTS_SYM {}
+ | STATEMENT_SYM {}
| STATUS_SYM {}
| STORAGE_SYM {}
| STRING_SYM {}
@@ -13314,7 +14270,6 @@ keyword_sp:
| SWAPS_SYM {}
| SWITCHES_SYM {}
| TABLE_NAME_SYM {}
- | TABLE_STATS_SYM {}
| TABLES {}
| TABLE_CHECKSUM_SYM {}
| TABLESPACE {}
@@ -13339,8 +14294,7 @@ keyword_sp:
| UNDOFILE_SYM {}
| UNKNOWN_SYM {}
| UNTIL_SYM {}
- | USER {}
- | USER_STATS_SYM {}
+ | USER_SYM {}
| USE_FRM {}
| VARIABLES {}
| VIEW_SYM {}
@@ -13349,6 +14303,7 @@ keyword_sp:
| WARNINGS {}
| WAIT_SYM {}
| WEEK_SYM {}
+ | WEIGHT_STRING_SYM {}
| WORK_SYM {}
| X509_SYM {}
| XML_SYM {}
@@ -13356,125 +14311,138 @@ 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
{}
+ | SET STATEMENT_SYM
+ {
+ LEX *lex= Lex;
+ mysql_init_select(lex);
+ lex->option_type= OPT_SESSION;
+ lex->sql_command= SQLCOM_SET_OPTION;
+ lex->autocommit= 0;
+ }
+ set_stmt_option_value_following_option_type_list
+ {
+ LEX *lex= Lex;
+ if (lex->table_or_sp_used())
+ my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT"));
+ lex->stmt_var_list= lex->var_list;
+ lex->var_list.empty();
+ }
+ FOR_SYM verb_clause
+ {}
;
-opt_option:
- /* empty */ {}
- | OPTION {}
- ;
-
-option_value_list:
- option_type_value
- | option_value_list ',' option_type_value
- ;
+set_stmt_option_value_following_option_type_list:
+ /*
+ Only system variables can be used here. If this condition is changed
+ please check careful code under lex->option_type == OPT_STATEMENT
+ condition on wrong type casts.
+ */
+ option_value_following_option_type
+ | set_stmt_option_value_following_option_type_list ',' option_value_following_option_type
-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 (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ option_value_list_continued
+ | TRANSACTION_SYM
+ {
+ 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->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();
- }
+// 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;
}
- ext_option_value
+ option_value_list_continued
+ | TRANSACTION_SYM transaction_characteristics
{
- LEX *lex= thd->lex;
- Lex_input_stream *lip= YYLIP;
-
- if (lex->sphead)
- {
- sp_head *sp= lex->sphead;
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ ;
- 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;
+// Remainder of the option value list after first option value.
+option_value_list_continued:
+ /* empty */
+ | ',' option_value_list
+ ;
- if (!(i= new sp_instr_stmt(sp->instructions(), lex->spcont,
- lex)))
- 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;
+ }
+ ;
- /*
- 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;
-
- if (!(qbuff.str= (char*) alloc_root(thd->mem_root,
- qbuff.length + 5)))
- 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; }
@@ -13489,81 +14457,68 @@ 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(thd, 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);
+ item= new (thd->mem_root) Item_func_set_user_var(thd, $2, $4);
if (item == NULL)
MYSQL_YYABORT;
- set_var_user *var= new set_var_user(item);
+ set_var_user *var= new (thd->mem_root) set_var_user(item);
if (var == NULL)
MYSQL_YYABORT;
- Lex->var_list.push_back(var);
+ Lex->var_list.push_back(var, thd->mem_root);
}
| '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default
{
@@ -13588,12 +14543,13 @@ option_value:
CHARSET_INFO *cs2;
cs2= $2 ? $2: global_system_variables.character_set_client;
set_var_collation_client *var;
- var= new set_var_collation_client(cs2,
- thd->variables.collation_database,
- cs2);
+ var= (new (thd->mem_root)
+ set_var_collation_client(cs2,
+ thd->variables.collation_database,
+ cs2));
if (var == NULL)
MYSQL_YYABORT;
- lex->var_list.push_back(var);
+ lex->var_list.push_back(var, thd->mem_root);
}
| NAMES_SYM equal expr
{
@@ -13603,10 +14559,10 @@ 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));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
@@ -13624,57 +14580,71 @@ option_value:
MYSQL_YYABORT;
}
set_var_collation_client *var;
- var= new set_var_collation_client(cs3, cs3, cs3);
+ var= new (thd->mem_root) set_var_collation_client(cs3, cs3, cs3);
if (var == NULL)
MYSQL_YYABORT;
- lex->var_list.push_back(var);
+ lex->var_list.push_back(var, thd->mem_root);
}
- | PASSWORD equal text_or_password
+ | DEFAULT ROLE_SYM grant_role
{
- LEX *lex= thd->lex;
+ LEX *lex = Lex;
LEX_USER *user;
- sp_pcontext *spc= lex->spcont;
- LEX_STRING pw;
-
- pw.str= (char *)"password";
- pw.length= 8;
- if (spc && spc->find_variable(&pw))
- {
- my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
+ if (!(user=(LEX_USER *) thd->calloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
- }
- if (!(user=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
+ user->user= current_user;
+ set_var_default_role *var= (new (thd->mem_root)
+ set_var_default_role(user,
+ $3->user));
+ if (var == NULL)
MYSQL_YYABORT;
- user->host=null_lex_str;
- user->user.str=thd->security_ctx->user;
- set_var_password *var= new set_var_password(user, $3);
+ lex->var_list.push_back(var, thd->mem_root);
+ thd->lex->autocommit= TRUE;
+ if (lex->sphead)
+ lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
+ }
+ | DEFAULT ROLE_SYM grant_role FOR_SYM user
+ {
+ LEX *lex = Lex;
+ set_var_default_role *var= (new (thd->mem_root)
+ set_var_default_role($5, $3->user));
if (var == NULL)
MYSQL_YYABORT;
- thd->lex->var_list.push_back(var);
+ lex->var_list.push_back(var, thd->mem_root);
thd->lex->autocommit= TRUE;
if (lex->sphead)
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
}
- | PASSWORD FOR_SYM user equal text_or_password
+ | ROLE_SYM ident_or_text
+ {
+ LEX *lex = Lex;
+ set_var_role *var= new (thd->mem_root) set_var_role($2);
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var, thd->mem_root);
+ }
+ | PASSWORD_SYM opt_for_user text_or_password
{
- set_var_password *var= new set_var_password($3,$5);
+ LEX *lex = Lex;
+ set_var_password *var= (new (thd->mem_root)
+ set_var_password(lex->definer));
if (var == NULL)
MYSQL_YYABORT;
- Lex->var_list.push_back(var);
- Lex->autocommit= TRUE;
- if (Lex->sphead)
- Lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
+ lex->var_list.push_back(var, thd->mem_root);
+ lex->autocommit= TRUE;
+ if (lex->sphead)
+ lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
}
;
+
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};
@@ -13699,7 +14669,7 @@ internal_variable_name:
LEX *lex= Lex;
if (check_reserved_words(&$1))
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_TRIGGER &&
@@ -13707,10 +14677,7 @@ internal_variable_name:
!my_strcasecmp(system_charset_info, $1.str, "OLD")))
{
if ($1.str[0]=='O' || $1.str[0]=='o')
- {
- my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", "");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", ""));
if (lex->trg_chistics.event == TRG_EVENT_DELETE)
{
my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0),
@@ -13718,10 +14685,7 @@ internal_variable_name:
MYSQL_YYABORT;
}
if (lex->trg_chistics.action_time == TRG_ACTION_AFTER)
- {
- my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after ");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after "));
/* This special combination will denote field of NEW row */
$$.var= trg_new_row_fake_var;
$$.base_name= $3;
@@ -13750,6 +14714,54 @@ 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(thd, (int32) $1);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ set_var *var= (new (thd->mem_root)
+ set_var(thd, 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, thd->mem_root);
+ }
+ ;
+
+isolation_level:
+ ISOLATION LEVEL_SYM isolation_types
+ {
+ LEX *lex=Lex;
+ Item *item= new (thd->mem_root) Item_int(thd, (int32) $3);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ set_var *var= (new (thd->mem_root)
+ set_var(thd, lex->option_type,
+ find_sys_var(thd, "tx_isolation"),
+ &null_lex_str,
+ item));
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var, thd->mem_root);
+ }
+ ;
+
+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; }
@@ -13757,46 +14769,54 @@ isolation_types:
| SERIALIZABLE_SYM { $$= ISO_SERIALIZABLE; }
;
-text_or_password:
- TEXT_STRING { $$=$1.str;}
- | PASSWORD '(' TEXT_STRING ')'
+opt_for_user:
+ equal
{
- $$= $3.length ? thd->variables.old_passwords ?
- Item_func_old_password::alloc(thd, $3.str, $3.length) :
- Item_func_password::alloc(thd, $3.str, $3.length) :
- $3.str;
- if ($$ == NULL)
+ LEX *lex= thd->lex;
+ sp_pcontext *spc= lex->spcont;
+ LEX_STRING pw= { C_STRING_WITH_LEN("password") };
+
+ if (spc && spc->find_variable(pw, false))
+ my_yyabort_error((ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str));
+ if (!(lex->definer= (LEX_USER*) thd->calloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
+ lex->definer->user= current_user;
+ lex->definer->plugin= empty_lex_str;
+ lex->definer->auth= empty_lex_str;
}
- | OLD_PASSWORD '(' TEXT_STRING ')'
+ | FOR_SYM user equal { Lex->definer= $2; }
+ ;
+
+text_or_password:
+ TEXT_STRING { Lex->definer->pwhash= $1;}
+ | PASSWORD_SYM '(' TEXT_STRING ')' { Lex->definer->pwtext= $3; }
+ | OLD_PASSWORD_SYM '(' TEXT_STRING ')'
{
- $$= $3.length ? Item_func_old_password::alloc(thd, $3.str,
- $3.length) :
- $3.str;
- if ($$ == NULL)
- MYSQL_YYABORT;
+ Lex->definer->pwtext= $3;
+ Lex->definer->pwhash.str= Item_func_password::alloc(thd,
+ $3.str, $3.length, Item_func_password::OLD);
+ Lex->definer->pwhash.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
}
;
-
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(thd, "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(thd, "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(thd, "binary", 6);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -13810,10 +14830,7 @@ lock:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "LOCK");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "LOCK"));
lex->sql_command= SQLCOM_LOCK_TABLES;
}
table_lock_list
@@ -13863,10 +14880,7 @@ unlock:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "UNLOCK");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "UNLOCK"));
lex->sql_command= SQLCOM_UNLOCK_TABLES;
}
table_or_tables
@@ -13882,47 +14896,38 @@ handler:
{
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->sql_command = SQLCOM_HA_OPEN;
- if (!lex->current_select->add_table_to_list(lex->thd, $2, $4, 0))
+ if (!lex->current_select->add_table_to_list(thd, $2, $4, 0))
MYSQL_YYABORT;
}
| HANDLER_SYM table_ident_nodb CLOSE_SYM
{
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->sql_command = SQLCOM_HA_CLOSE;
- if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
+ if (!lex->current_select->add_table_to_list(thd, $2, 0, 0))
MYSQL_YYABORT;
}
| HANDLER_SYM table_ident_nodb READ_SYM
{
LEX *lex=Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->expr_allows_subselect= FALSE;
lex->sql_command = SQLCOM_HA_READ;
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
- Item *one= new (thd->mem_root) Item_int((int32) 1);
+ Item *one= new (thd->mem_root) Item_int(thd, (int32) 1);
if (one == NULL)
MYSQL_YYABORT;
lex->current_select->select_limit= one;
lex->current_select->offset_limit= 0;
lex->limit_rows_examined= 0;
- if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
+ if (!lex->current_select->add_table_to_list(thd, $2, 0, 0))
MYSQL_YYABORT;
}
- handler_read_or_scan where_clause opt_limit_clause
+ handler_read_or_scan opt_where_clause opt_limit_clause
{
Lex->expr_allows_subselect= TRUE;
/* Stored functions are not supported for HANDLER READ. */
@@ -13955,7 +14960,7 @@ handler_rkey_function:
LEX *lex=Lex;
lex->ha_read_mode = RKEY;
lex->ha_rkey_mode=$1;
- if (!(lex->insert_list = new List_item))
+ if (!(lex->insert_list= new (thd->mem_root) List_item))
MYSQL_YYABORT;
}
'(' values ')'
@@ -13978,35 +14983,35 @@ 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)
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
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)
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
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;
}
@@ -14016,9 +15021,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, thd->mem_root))
+ 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
{}
@@ -14038,7 +15056,7 @@ grant_command:
LEX *lex= Lex;
if (lex->columns.elements)
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
lex->sql_command= SQLCOM_GRANT;
@@ -14050,7 +15068,7 @@ grant_command:
LEX *lex= Lex;
if (lex->columns.elements)
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
lex->sql_command= SQLCOM_GRANT;
@@ -14062,7 +15080,70 @@ 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, thd->mem_root))
+ 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, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ | role_list ',' grant_role
+ {
+ if (Lex->users_list.push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+current_role:
+ CURRENT_ROLE optional_braces
+ {
+ if (!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))
+ MYSQL_YYABORT;
+ $$->user= current_role;
+ $$->reset_auth();
+ }
+ ;
+
+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);
+ $1.str[$1.length] = '\0';
+ if ($1.length == 0)
+ my_yyabort_error((ER_INVALID_ROLE, MYF(0), ""));
+ if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ MYSQL_YYABORT;
+ $$->user = $1;
+ $$->host= empty_lex_str;
+ $$->reset_auth();
+
+ if (check_string_char_length(&$$->user, ER_USERNAME,
+ username_char_length,
+ cs, 0))
+ MYSQL_YYABORT;
+ }
+ | current_role
;
opt_table:
@@ -14124,7 +15205,7 @@ object_privilege:
| SHOW VIEW_SYM { Lex->grant |= SHOW_VIEW_ACL; }
| CREATE ROUTINE_SYM { Lex->grant |= CREATE_PROC_ACL; }
| ALTER ROUTINE_SYM { Lex->grant |= ALTER_PROC_ACL; }
- | CREATE USER { Lex->grant |= CREATE_USER_ACL; }
+ | CREATE USER_SYM { Lex->grant |= CREATE_USER_ACL; }
| EVENT_SYM { Lex->grant |= EVENT_ACL;}
| TRIGGER_SYM { Lex->grant |= TRIGGER_ACL; }
| CREATE TABLESPACE { Lex->grant |= CREATE_TABLESPACE_ACL; }
@@ -14145,30 +15226,21 @@ require_list_element:
{
LEX *lex=Lex;
if (lex->x509_subject)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "SUBJECT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SUBJECT"));
lex->x509_subject=$2.str;
}
| ISSUER_SYM TEXT_STRING
{
LEX *lex=Lex;
if (lex->x509_issuer)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "ISSUER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "ISSUER"));
lex->x509_issuer=$2.str;
}
| CIPHER_SYM TEXT_STRING
{
LEX *lex=Lex;
if (lex->ssl_cipher)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "CIPHER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CIPHER"));
lex->ssl_cipher=$2.str;
}
;
@@ -14183,11 +15255,7 @@ grant_ident:
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
- {
- my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
- ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
}
| ident '.' '*'
{
@@ -14196,11 +15264,7 @@ grant_ident:
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
- {
- my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
- ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
}
| '*' '.' '*'
{
@@ -14209,16 +15273,12 @@ grant_ident:
if (lex->grant == GLOBAL_ACLS)
lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
- {
- my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
- ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
}
| table_ident
{
LEX *lex=Lex;
- if (!lex->current_select->add_table_to_list(lex->thd, $1,NULL,
+ if (!lex->current_select->add_table_to_list(thd, $1,NULL,
TL_OPTION_UPDATING))
MYSQL_YYABORT;
if (lex->grant == GLOBAL_ACLS)
@@ -14229,12 +15289,12 @@ grant_ident:
user_list:
user
{
- if (Lex->users_list.push_back($1))
+ if (Lex->users_list.push_back($1, thd->mem_root))
MYSQL_YYABORT;
}
| user_list ',' user
{
- if (Lex->users_list.push_back($3))
+ if (Lex->users_list.push_back($3, thd->mem_root))
MYSQL_YYABORT;
}
;
@@ -14242,12 +15302,25 @@ user_list:
grant_list:
grant_user
{
- if (Lex->users_list.push_back($1))
+ if (Lex->users_list.push_back($1, thd->mem_root))
MYSQL_YYABORT;
}
| grant_list ',' grant_user
{
- if (Lex->users_list.push_back($3))
+ if (Lex->users_list.push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+user_and_role_list:
+ user_or_role
+ {
+ if (Lex->users_list.push_back($1, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ | user_and_role_list ',' user_or_role
+ {
+ if (Lex->users_list.push_back($3, thd->mem_root))
MYSQL_YYABORT;
}
;
@@ -14258,35 +15331,15 @@ using_or_as: USING | AS ;
grant_user:
user IDENTIFIED_SYM BY TEXT_STRING
{
- $$=$1; $1->password=$4;
- if ($4.length)
- {
- if (thd->variables.old_passwords)
- {
- char *buff=
- (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
- if (buff == NULL)
- MYSQL_YYABORT;
- my_make_scrambled_password_323(buff, $4.str, $4.length);
- $1->password.str= buff;
- $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
- }
- else
- {
- char *buff=
- (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
- if (buff == NULL)
- MYSQL_YYABORT;
- my_make_scrambled_password(buff, $4.str, $4.length);
- $1->password.str= buff;
- $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
- }
- }
+ $$= $1;
+ $1->pwtext= $4;
+ if (Lex->sql_command == SQLCOM_REVOKE)
+ MYSQL_YYABORT;
}
- | user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
+ | user IDENTIFIED_SYM BY PASSWORD_SYM TEXT_STRING
{
$$= $1;
- $1->password= $5;
+ $1->pwhash= $5;
}
| user IDENTIFIED_SYM via_or_with ident_or_text
{
@@ -14300,8 +15353,8 @@ grant_user:
$1->plugin= $4;
$1->auth= $6;
}
- | user
- { $$= $1; $1->password= null_lex_str; }
+ | user_or_role
+ { $$= $1; }
;
opt_column_list:
@@ -14321,7 +15374,7 @@ column_list:
column_list_id:
ident
{
- String *new_str = new (thd->mem_root) String((const char*) $1.str,$1.length,system_charset_info);
+ String *new_str= new (thd->mem_root) String((const char*) $1.str,$1.length,system_charset_info);
if (new_str == NULL)
MYSQL_YYABORT;
List_iterator <LEX_COLUMN> iter(Lex->columns);
@@ -14338,10 +15391,11 @@ column_list_id:
point->rights |= lex->which_columns;
else
{
- LEX_COLUMN *col= new LEX_COLUMN (*new_str,lex->which_columns);
+ LEX_COLUMN *col= (new (thd->mem_root)
+ LEX_COLUMN(*new_str,lex->which_columns));
if (col == NULL)
MYSQL_YYABORT;
- lex->columns.push_back(col);
+ lex->columns.push_back(col, thd->mem_root);
}
}
;
@@ -14407,6 +15461,12 @@ grant_option:
lex->mqh.user_conn= $2;
lex->mqh.specified_limits|= USER_RESOURCES::USER_CONNECTIONS;
}
+ | MAX_STATEMENT_TIME_SYM NUM_literal
+ {
+ LEX *lex=Lex;
+ lex->mqh.max_statement_time= $2->val_real();
+ lex->mqh.specified_limits|= USER_RESOURCES::MAX_STATEMENT_TIME;
+ }
;
begin:
@@ -14417,6 +15477,20 @@ begin:
lex->start_transaction_opt= 0;
}
opt_work {}
+ ;
+
+compound_statement:
+ sp_proc_stmt_compound_ok
+ {
+ Lex->sql_command= SQLCOM_COMPOUND;
+ Lex->sphead->set_stmt_end(thd);
+ Lex->sphead->restore_thd_mem_root(thd);
+ }
+ ;
+
+opt_not:
+ /* nothing */ { $$= 0; }
+ | not { $$= 1; }
;
opt_work:
@@ -14519,14 +15593,13 @@ union_list:
;
union_opt:
- /* Empty */ { $$= 0; }
+ opt_union_order_or_limit
| union_list { $$= 1; }
- | union_order_or_limit { $$= 1; }
;
opt_union_order_or_limit:
- /* Empty */{ $$= false; }
- | union_order_or_limit { $$= true; }
+ /* Empty */ { $$= 0; }
+ | union_order_or_limit { $$= 1; }
;
union_order_or_limit:
@@ -14538,7 +15611,6 @@ union_order_or_limit:
SELECT_LEX *fake= unit->fake_select_lex;
if (fake)
{
- unit->global_parameters= fake;
fake->no_table_names_allowed= 1;
lex->current_select= fake;
}
@@ -14552,7 +15624,7 @@ union_order_or_limit:
;
order_or_limit:
- order_clause opt_limit_clause_init
+ order_clause opt_limit_clause
| limit_clause
;
@@ -14564,17 +15636,19 @@ union_option:
query_specification:
SELECT_SYM select_init2_derived
- {
+ table_expression
+ {
$$= Lex->current_select->master_unit()->first_select();
}
| '(' select_paren_derived ')'
+ opt_union_order_or_limit
{
$$= Lex->current_select->master_unit()->first_select();
}
;
query_expression_body:
- query_specification opt_union_order_or_limit
+ query_specification
| query_expression_body
UNION_SYM union_option
{
@@ -14582,7 +15656,6 @@ query_expression_body:
MYSQL_YYABORT;
}
query_specification
- opt_union_order_or_limit
{
Lex->pop_context();
$$= $1;
@@ -14603,7 +15676,7 @@ subselect_start:
if (!lex->expr_allows_subselect ||
lex->sql_command == (int)SQLCOM_PURGE)
{
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
}
/*
@@ -14694,7 +15767,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
{}
;
@@ -14741,9 +15814,12 @@ no_definer:
;
definer:
- DEFINER_SYM '=' user
+ DEFINER_SYM '=' user_or_role
{
- thd->lex->definer= get_current_user(thd, $3);
+ Lex->definer= $3;
+ Lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
+ Lex->ssl_cipher= Lex->x509_subject= Lex->x509_issuer= 0;
+ bzero(&(Lex->mqh), sizeof(Lex->mqh));
}
;
@@ -14753,20 +15829,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 '=' UNDEFINED_SYM
{ Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED; }
@@ -14786,12 +15848,14 @@ view_suid:
;
view_tail:
- view_suid VIEW_SYM table_ident
+ view_suid VIEW_SYM opt_if_not_exists table_ident
{
LEX *lex= thd->lex;
+ if (lex->add_create_options_with_check($3))
+ MYSQL_YYABORT;
lex->sql_command= SQLCOM_CREATE_VIEW;
/* first table in list is target VIEW name */
- if (!lex->select_lex.add_table_to_list(thd, $3, NULL,
+ if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
TL_OPTION_UPDATING,
TL_IGNORE,
MDL_EXCLUSIVE))
@@ -14809,15 +15873,17 @@ view_list_opt:
view_list:
ident
- {
- Lex->view_list.push_back((LEX_STRING*)
- sql_memdup(&$1, sizeof(LEX_STRING)));
- }
+ {
+ Lex->view_list.push_back((LEX_STRING*)
+ thd->memdup(&$1, sizeof(LEX_STRING)),
+ thd->mem_root);
+ }
| view_list ',' ident
- {
- Lex->view_list.push_back((LEX_STRING*)
- sql_memdup(&$3, sizeof(LEX_STRING)));
- }
+ {
+ Lex->view_list.push_back((LEX_STRING*)
+ thd->memdup(&$3, sizeof(LEX_STRING)),
+ thd->mem_root);
+ }
;
view_select:
@@ -14869,52 +15935,46 @@ view_check_option:
trigger_tail:
TRIGGER_SYM
remember_name
+ opt_if_not_exists
+ {
+ if (Lex->add_create_options_with_check($3))
+ MYSQL_YYABORT;
+ }
sp_name
trg_action_time
trg_event
ON
- remember_name /* $7 */
- { /* $8 */
+ remember_name /* $9 */
+ { /* $10 */
Lex->raw_trg_on_table_name_begin= YYLIP->get_tok_start();
}
- table_ident /* $9 */
+ table_ident /* $11 */
FOR_SYM
- remember_name /* $11 */
- { /* $12 */
+ remember_name /* $13 */
+ { /* $14 */
Lex->raw_trg_on_table_name_end= YYLIP->get_tok_start();
}
EACH_SYM
ROW_SYM
- { /* $15 */
+ { /* $17 */
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
- sp_head *sp;
if (lex->sphead)
- {
- my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"));
- if (!(sp= new sp_head()))
- MYSQL_YYABORT;
- sp->reset_thd_mem_root(thd);
- sp->init(lex);
- sp->m_type= TYPE_ENUM_TRIGGER;
- sp->init_sp_name(thd, $3);
lex->stmt_definition_begin= $2;
- lex->ident.str= $7;
- lex->ident.length= $11 - $7;
+ lex->ident.str= $9;
+ lex->ident.length= $13 - $9;
+ lex->spname= $5;
- lex->sphead= sp;
- lex->spname= $3;
+ if (!make_sp_head(thd, $5, TYPE_ENUM_TRIGGER))
+ MYSQL_YYABORT;
- bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
- lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->set_body_start(thd, lip->get_cpp_ptr());
}
- sp_proc_stmt /* $16 */
- { /* $17 */
+ sp_proc_stmt /* $18 */
+ { /* $19 */
LEX *lex= Lex;
sp_head *sp= lex->sphead;
@@ -14930,7 +15990,7 @@ trigger_tail:
sp_proc_stmt alternatives are not saving/restoring LEX, so
lex->query_tables can be wiped out.
*/
- if (!lex->select_lex.add_table_to_list(thd, $9,
+ if (!lex->select_lex.add_table_to_list(thd, $11,
(LEX_STRING*) 0,
TL_OPTION_UPDATING,
TL_READ_NO_INSERT,
@@ -14946,71 +16006,45 @@ trigger_tail:
**************************************************************************/
udf_tail:
- AGGREGATE_SYM remember_name FUNCTION_SYM ident
+ AGGREGATE_SYM udf_tail2 { thd->lex->udf.type= UDFTYPE_AGGREGATE; }
+ | udf_tail2 { thd->lex->udf.type= UDFTYPE_FUNCTION; }
+ ;
+
+udf_tail2:
+ FUNCTION_SYM opt_if_not_exists ident
RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
{
LEX *lex= thd->lex;
- if (is_native_function(thd, & $4))
- {
- my_error(ER_NATIVE_FCT_NAME_COLLISION, MYF(0),
- $4.str);
+ if (lex->add_create_options_with_check($2))
MYSQL_YYABORT;
- }
- lex->sql_command = SQLCOM_CREATE_FUNCTION;
- lex->udf.type= UDFTYPE_AGGREGATE;
- lex->stmt_definition_begin= $2;
- lex->udf.name = $4;
- lex->udf.returns=(Item_result) $6;
- lex->udf.dl=$8.str;
- }
- | remember_name FUNCTION_SYM ident
- RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
- {
- LEX *lex= thd->lex;
if (is_native_function(thd, & $3))
- {
- my_error(ER_NATIVE_FCT_NAME_COLLISION, MYF(0),
- $3.str);
- MYSQL_YYABORT;
- }
- lex->sql_command = SQLCOM_CREATE_FUNCTION;
- lex->udf.type= UDFTYPE_FUNCTION;
- lex->stmt_definition_begin= $1;
- lex->udf.name = $3;
- lex->udf.returns=(Item_result) $5;
- lex->udf.dl=$7.str;
+ my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $3.str));
+ lex->sql_command= SQLCOM_CREATE_FUNCTION;
+ lex->udf.name= $3;
+ lex->udf.returns= (Item_result) $5;
+ lex->udf.dl= $7.str;
}
;
sf_tail:
- remember_name /* $1 */
- FUNCTION_SYM /* $2 */
+ FUNCTION_SYM /* $1 */
+ opt_if_not_exists /* $2 */
sp_name /* $3 */
'(' /* $4 */
{ /* $5 */
- LEX *lex= thd->lex;
+ LEX *lex= Lex;
Lex_input_stream *lip= YYLIP;
- sp_head *sp;
const char* tmp_param_begin;
- lex->stmt_definition_begin= $1;
+ if (lex->add_create_options_with_check($2))
+ MYSQL_YYABORT;
lex->spname= $3;
if (lex->sphead)
- {
- my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION");
- MYSQL_YYABORT;
- }
- /* Order is important here: new - reset - init */
- sp= new sp_head();
- if (sp == NULL)
- MYSQL_YYABORT;
- sp->reset_thd_mem_root(thd);
- sp->init(lex);
- sp->init_sp_name(thd, lex->spname);
+ my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION"));
- sp->m_type= TYPE_ENUM_FUNCTION;
- lex->sphead= sp;
+ if (!make_sp_head(thd, $3, TYPE_ENUM_FUNCTION))
+ MYSQL_YYABORT;
tmp_param_begin= lip->get_cpp_tok_start();
tmp_param_begin++;
@@ -15024,41 +16058,20 @@ sf_tail:
RETURNS_SYM /* $9 */
{ /* $10 */
LEX *lex= Lex;
- lex->charset= NULL;
- lex->length= lex->dec= NULL;
- lex->interval_list.empty();
- lex->type= 0;
- lex->vcol_info= 0;
+ lex->init_last_field(&lex->sphead->m_return_field_def, NULL,
+ thd->variables.collation_database);
}
type_with_opt_collate /* $11 */
{ /* $12 */
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- /*
- This was disabled in 5.1.12. See bug #20701
- When collation support in SP is implemented, then this test
- should be removed.
- */
- if (($11 == MYSQL_TYPE_STRING || $11 == MYSQL_TYPE_VARCHAR)
- && (lex->type & BINCMP_FLAG))
- {
- my_error(ER_NOT_SUPPORTED_YET, MYF(0), "return value collation");
+ if (Lex->sphead->fill_field_definition(thd, Lex, $11,
+ Lex->last_field))
MYSQL_YYABORT;
- }
-
- if (sp->fill_field_definition(thd, lex,
- (enum enum_field_types) $11,
- &sp->m_return_field_def))
- MYSQL_YYABORT;
-
- bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_c_chistics /* $13 */
{ /* $14 */
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
- lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
}
sp_proc_stmt /* $15 */
@@ -15072,10 +16085,7 @@ sf_tail:
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->set_stmt_end(thd);
if (!(sp->m_flags & sp_head::HAS_RETURN))
- {
- my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NORETURN, MYF(0), sp->m_qname.str));
if (is_native_function(thd, & sp->m_name))
{
/*
@@ -15094,9 +16104,9 @@ sf_tail:
- The user deploys 5.{N+1}. At this point, 'select foo()'
means something different, and the user code is most likely
broken (it's only safe if the code is 'select db.foo()').
- With a warning printed when the SF is loaded (which has to occur
- before the call), the warning will provide a hint explaining
- the root cause of a later failure of 'select foo()'.
+ With a warning printed when the SF is loaded (which has to
+ occur before the call), the warning will provide a hint
+ explaining the root cause of a later failure of 'select foo()'.
With no warning printed, the user code will fail with no
apparent reason.
Printing a warning each time db_load_routine is executed for
@@ -15106,9 +16116,9 @@ 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),
+ ER_THD(thd, ER_NATIVE_FCT_NAME_COLLISION),
sp->m_name.str);
}
sp->restore_thd_mem_root(thd);
@@ -15116,29 +16126,17 @@ sf_tail:
;
sp_tail:
- PROCEDURE_SYM remember_name sp_name
+ PROCEDURE_SYM opt_if_not_exists sp_name
{
- LEX *lex= Lex;
- sp_head *sp;
-
- if (lex->sphead)
- {
- my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE");
+ if (Lex->add_create_options_with_check($2))
MYSQL_YYABORT;
- }
- lex->stmt_definition_begin= $2;
+ if (Lex->sphead)
+ my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE"));
- /* Order is important here: new - reset - init */
- sp= new sp_head();
- if (sp == NULL)
+ if (!make_sp_head(thd, $3, TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT;
- sp->reset_thd_mem_root(thd);
- sp->init(lex);
- sp->m_type= TYPE_ENUM_PROCEDURE;
- sp->init_sp_name(thd, $3);
-
- lex->sphead= sp;
+ Lex->spname= $3;
}
'('
{
@@ -15151,17 +16149,11 @@ sp_tail:
sp_pdparam_list
')'
{
- LEX *lex= thd->lex;
-
- lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
- bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
+ Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
}
sp_c_chistics
{
- LEX *lex= thd->lex;
-
- lex->sphead->m_chistics= &lex->sp_chistics;
- lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
+ Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
}
sp_proc_stmt
{