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.yy296
1 files changed, 228 insertions, 68 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f0ed46646ae..ae81c026b26 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -200,6 +200,11 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
ulonglong ulonglong_number;
longlong longlong_number;
uint sp_instr_addr;
+ /*
+ Longlong_hybrid does not have a default constructor, hence the
+ default value below.
+ */
+ Longlong_hybrid longlong_hybrid_number= Longlong_hybrid(0, false);
/* structs */
LEX_CSTRING lex_str;
@@ -1466,7 +1471,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
ulonglong_num real_ulonglong_num
%type <longlong_number>
- longlong_num
+ sequence_value_num
+
+%type <longlong_hybrid_number>
+ sequence_value_hybrid_num sequence_truncated_value_hybrid_num
%type <choice> choice
@@ -2419,7 +2427,8 @@ create:
{
LEX *lex= thd->lex;
- if (unlikely(lex->create_info.seq_create_info->check_and_adjust(1)))
+ if (unlikely(lex->create_info.seq_create_info->
+ check_and_adjust(thd, 1)))
{
my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
lex->first_select_lex()->table_list.first->db.str,
@@ -2429,12 +2438,13 @@ create:
}
/* No fields specified, generate them */
- if (unlikely(prepare_sequence_fields(thd,
- &lex->alter_info.create_list)))
+ if (unlikely(
+ lex->create_info.seq_create_info->prepare_sequence_fields(
+ &lex->alter_info.create_list, false)))
MYSQL_YYABORT;
/* CREATE SEQUENCE always creates a sequence */
- Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
+ Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
Lex->create_info.sequence= 1;
create_table_set_open_action_and_adjust_tables(lex);
@@ -2605,90 +2615,113 @@ sequence_defs:
;
sequence_def:
- MINVALUE_SYM opt_equal longlong_num
- {
- Lex->create_info.seq_create_info->min_value= $3;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
+ AS int_type field_options
+ {
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_as))
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "AS"));
+ if ($3 & ZEROFILL_FLAG)
+ my_yyabort_error((ER_BAD_OPTION_VALUE, MYF(0), "ZEROFILL",
+ "AS"));
+ seq->value_type = $2->field_type();
+ seq->is_unsigned= $3 & UNSIGNED_FLAG ? true : false;
+ seq->used_fields|= seq_field_used_as;
+ }
+ | MINVALUE_SYM opt_equal sequence_truncated_value_hybrid_num
+ {
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_min_value))
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MINVALUE"));
+ seq->min_value_from_parser= $3;
+ seq->used_fields|=
+ seq_field_used_min_value;
+ seq->used_fields|=
+ seq_field_specified_min_value;
}
| NO_SYM MINVALUE_SYM
{
- if (unlikely(Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_min_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MINVALUE"));
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
+ seq->used_fields|= seq_field_used_min_value;
}
| NOMINVALUE_SYM
{
- if (unlikely(Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_min_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MINVALUE"));
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
+ seq->used_fields|= seq_field_used_min_value;
}
- | MAXVALUE_SYM opt_equal longlong_num
+ | MAXVALUE_SYM opt_equal sequence_truncated_value_hybrid_num
{
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_max_value))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_max_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MAXVALUE"));
- Lex->create_info.seq_create_info->max_value= $3;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
+ seq->max_value_from_parser= $3;
+ seq->used_fields|= seq_field_used_max_value;
+ seq->used_fields|= seq_field_specified_max_value;
}
| NO_SYM MAXVALUE_SYM
{
- if (unlikely(Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_max_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MAXVALUE"));
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
+ seq->used_fields|= seq_field_used_max_value;
}
| NOMAXVALUE_SYM
{
- if (unlikely(Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_max_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MAXVALUE"));
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
+ seq->used_fields|= seq_field_used_max_value;
}
- | START_SYM opt_with longlong_num
+ | START_SYM opt_with sequence_value_hybrid_num
{
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_start))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_start))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "START"));
- Lex->create_info.seq_create_info->start= $3;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_start;
+ seq->start_from_parser= $3;
+ seq->used_fields|= seq_field_used_start;
}
- | INCREMENT_SYM opt_by longlong_num
+ | INCREMENT_SYM opt_by sequence_value_num
{
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_increment))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_increment))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "INCREMENT"));
- Lex->create_info.seq_create_info->increment= $3;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_increment;
+ seq->increment= $3;
+ seq->used_fields|= seq_field_used_increment;
}
- | CACHE_SYM opt_equal longlong_num
+ | CACHE_SYM opt_equal sequence_value_num
{
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_cache))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_cache))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CACHE"));
- Lex->create_info.seq_create_info->cache= $3;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_cache;
+ seq->cache= $3;
+ seq->used_fields|= seq_field_used_cache;
}
| NOCACHE_SYM
{
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_cache))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_cache))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CACHE"));
- Lex->create_info.seq_create_info->cache= 0;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_cache;
+ seq->cache= 0;
+ seq->used_fields|= seq_field_used_cache;
}
| CYCLE_SYM
{
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_cycle))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_cycle))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CYCLE"));
- Lex->create_info.seq_create_info->cycle= 1;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_cycle;
+ seq->cycle= 1;
+ seq->used_fields|= seq_field_used_cycle;
}
| NOCYCLE_SYM
{
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_cycle))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_cycle))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CYCLE"));
- Lex->create_info.seq_create_info->cycle= 0;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_cycle;
+ seq->cycle= 0;
+ seq->used_fields|= seq_field_used_cycle;
}
| RESTART_SYM
{
@@ -2697,23 +2730,24 @@ sequence_def:
thd->parse_error(ER_SYNTAX_ERROR, "RESTART");
MYSQL_YYABORT;
}
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_restart))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_restart))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "RESTART"));
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_restart;
+ seq->used_fields|= seq_field_used_restart;
}
- | RESTART_SYM opt_with longlong_num
+ | RESTART_SYM opt_with sequence_value_hybrid_num
{
if (unlikely(Lex->sql_command != SQLCOM_ALTER_SEQUENCE))
{
thd->parse_error(ER_SYNTAX_ERROR, "RESTART");
MYSQL_YYABORT;
}
- if (unlikely(Lex->create_info.seq_create_info->used_fields &
- seq_field_used_restart))
+ sequence_definition *seq= Lex->create_info.seq_create_info;
+ if (unlikely(seq->used_fields & seq_field_used_restart))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "RESTART"));
- Lex->create_info.seq_create_info->restart= $3;
- Lex->create_info.seq_create_info->used_fields|= seq_field_used_restart | seq_field_used_restart_value;
+ seq->restart_from_parser= $3;
+ seq->used_fields|=
+ seq_field_used_restart | seq_field_used_restart_value;
}
;
@@ -7119,6 +7153,13 @@ alter:
{
/* Create a generic ALTER SEQUENCE statment. */
Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_sequence($3);
+ if ((Lex->create_info.seq_create_info->used_fields &
+ seq_field_used_as) &&
+ (Lex->create_info.seq_create_info->used_fields -
+ seq_field_used_as))
+ my_yyabort_error((ER_NOT_SUPPORTED_YET, MYF(0),
+ "ALTER SEQUENCE with both AS <type> and "
+ "something else."));
if (unlikely(Lex->m_sql_cmd == NULL))
MYSQL_YYABORT;
} stmt_end {}
@@ -9728,19 +9769,23 @@ column_default_non_parenthesized_expr:
if (unlikely(!($$= Lex->create_item_func_lastval(thd, $3))))
MYSQL_YYABORT;
}
- | SETVAL_SYM '(' table_ident ',' longlong_num ')'
+ | SETVAL_SYM '(' table_ident ',' sequence_value_hybrid_num ')'
{
- if (unlikely(!($$= Lex->create_item_func_setval(thd, $3, $5, 0, 1))))
+ if (unlikely(!($$= Lex->create_item_func_setval(thd, $3, $5, 0,
+ 1))))
MYSQL_YYABORT;
}
- | SETVAL_SYM '(' table_ident ',' longlong_num ',' bool ')'
+ | SETVAL_SYM '(' table_ident ',' sequence_value_hybrid_num ',' bool ')'
{
- if (unlikely(!($$= Lex->create_item_func_setval(thd, $3, $5, 0, $7))))
+ if (unlikely(!($$= Lex->create_item_func_setval(thd, $3, $5, 0,
+ $7))))
MYSQL_YYABORT;
}
- | SETVAL_SYM '(' table_ident ',' longlong_num ',' bool ',' ulonglong_num ')'
+ | SETVAL_SYM '(' table_ident ',' sequence_value_hybrid_num ',' bool ','
+ ulonglong_num ')'
{
- if (unlikely(!($$= Lex->create_item_func_setval(thd, $3, $5, $9, $7))))
+ if (unlikely(!($$= Lex->create_item_func_setval(thd, $3, $5, $9,
+ $7))))
MYSQL_YYABORT;
}
;
@@ -12560,11 +12605,126 @@ real_ulong_num:
| dec_num_error { MYSQL_YYABORT; }
;
-longlong_num:
- opt_plus NUM { int error; $$= (longlong) my_strtoll10($2.str, (char**) 0, &error); }
- | LONG_NUM { int error; $$= (longlong) my_strtoll10($1.str, (char**) 0, &error); }
- | '-' NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); }
- | '-' LONG_NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); }
+/*
+ For simple sequence metadata values that are signed and do not need
+ truncation
+*/
+sequence_value_num:
+ opt_plus NUM
+ {
+ int error;
+ $$= (longlong) my_strtoll10($2.str, (char**) 0, &error);
+ }
+ | opt_plus LONG_NUM
+ {
+ int error;
+ $$= (longlong) my_strtoll10($2.str, (char**) 0, &error);
+ }
+ | '-' NUM
+ {
+ int error;
+ $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error);
+ }
+ | '-' LONG_NUM
+ {
+ int error;
+ $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error);
+ }
+ | '-' ULONGLONG_NUM
+ {
+ int error;
+ const ulonglong abs= my_strtoll10($2.str, (char**) 0, &error);
+ if (abs == 1 + (ulonglong) LONGLONG_MAX)
+ $$= LONGLONG_MIN;
+ else
+ thd->parse_error(ER_DATA_OUT_OF_RANGE);
+ }
+ ;
+
+/*
+ For sequence metadata values that may be unsigned but do not need
+ truncation (start, restart)
+*/
+sequence_value_hybrid_num:
+ opt_plus NUM
+ {
+ int error;
+ $$= Longlong_hybrid(my_strtoll10($2.str, (char**) 0, &error),
+ false);
+ }
+ | opt_plus LONG_NUM
+ {
+ int error;
+ $$= Longlong_hybrid(my_strtoll10($2.str, (char**) 0, &error),
+ false);
+ }
+ | opt_plus ULONGLONG_NUM
+ {
+ int error;
+ $$= Longlong_hybrid(my_strtoll10($2.str, (char**) 0, &error),
+ true);
+ }
+ | '-' NUM
+ {
+ int error;
+ $$= Longlong_hybrid(- my_strtoll10($2.str, (char**) 0, &error),
+ false);
+ }
+ | '-' LONG_NUM
+ {
+ int error;
+ $$= Longlong_hybrid(- my_strtoll10($2.str, (char**) 0, &error),
+ false);
+ }
+ | '-' ULONGLONG_NUM
+ {
+ int error;
+ const ulonglong abs= my_strtoll10($2.str, (char**) 0, &error);
+ if (abs == 1 + (ulonglong) LONGLONG_MAX)
+ $$= Longlong_hybrid(LONGLONG_MIN, false);
+ else
+ thd->parse_error(ER_DATA_OUT_OF_RANGE);
+ }
+ ;
+
+/*
+ For sequence metadata values that may be unsigned and need
+ truncation (maxvalue, minvalue)
+*/
+sequence_truncated_value_hybrid_num:
+ opt_plus NUM
+ {
+ int error;
+ $$= Longlong_hybrid(my_strtoll10($2.str, (char**) 0, &error),
+ false);
+ }
+ | opt_plus LONG_NUM
+ {
+ int error;
+ $$= Longlong_hybrid(my_strtoll10($2.str, (char**) 0, &error),
+ false);
+ }
+ | opt_plus ULONGLONG_NUM
+ {
+ int error;
+ $$= Longlong_hybrid(my_strtoll10($2.str, (char**) 0, &error),
+ true);
+ }
+ | opt_plus DECIMAL_NUM { $$= Longlong_hybrid(ULONGLONG_MAX, true); }
+ | '-' NUM
+ {
+ int error;
+ $$= Longlong_hybrid(- my_strtoll10($2.str, (char**) 0, &error),
+ false);
+ }
+ | '-' LONG_NUM
+ {
+ int error;
+ $$= Longlong_hybrid(- my_strtoll10($2.str, (char**) 0, &error),
+ false);
+ }
+ | '-' ULONGLONG_NUM { $$= Longlong_hybrid(LONGLONG_MIN, false); }
+ | '-' DECIMAL_NUM { $$= Longlong_hybrid(LONGLONG_MIN, false); }
;
ulonglong_num: