Commit 84675ed9 authored by Yuchen Pei's avatar Yuchen Pei

MDEV-28152 Create sequence truncating out-of-bound max/minvalue

This is item 2 of MDEV-28152. When creating a sequence with a huge
minvalue / maxvalue, truncate it to the nearest valid value for the
type, i.e. LONGLONG_MAX - 1 for values >= LONGLONG_MAX and
LONGLONG_MIN + 1 for values <= LONGLONG_MIN
parent ce4a289f
...@@ -143,6 +143,66 @@ t1 CREATE SEQUENCE `t1` start with 10 minvalue -10 maxvalue 11 increment by 10 c ...@@ -143,6 +143,66 @@ t1 CREATE SEQUENCE `t1` start with 10 minvalue -10 maxvalue 11 increment by 10 c
select * from t1; select * from t1;
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
10 -10 11 10 10 10 1 0 10 -10 11 10 10 10 1 0
create or replace sequence t1 minvalue -999999999999999999999;
Warnings:
Note 1292 Truncated incorrect INTEGER value: 'MINVALUE'
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with -9223372036854775807 minvalue -9223372036854775807 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
create or replace sequence t1 minvalue -9223372036854775808;
Warnings:
Note 1292 Truncated incorrect INTEGER value: 'MINVALUE'
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with -9223372036854775807 minvalue -9223372036854775807 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
create or replace sequence t1 minvalue -9223372036854775807;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with -9223372036854775807 minvalue -9223372036854775807 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
create or replace sequence t1 minvalue 9223372036854775805;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 9223372036854775805 minvalue 9223372036854775805 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
create or replace sequence t1 minvalue 9223372036854775806;
ERROR HY000: Sequence 'test.t1' has out of range value for options
create or replace sequence t1 minvalue 9223372036854775807;
ERROR HY000: Sequence 'test.t1' has out of range value for options
create or replace sequence t1 minvalue 9223372036854775808;
ERROR HY000: Sequence 'test.t1' has out of range value for options
create or replace sequence t1 minvalue 9999999999999999999999;
ERROR HY000: Sequence 'test.t1' has out of range value for options
create or replace sequence t1 maxvalue -999999999999999999999 increment by -1;
ERROR HY000: Sequence 'test.t1' has out of range value for options
create or replace sequence t1 maxvalue -9223372036854775808 increment by -1;
ERROR HY000: Sequence 'test.t1' has out of range value for options
create or replace sequence t1 maxvalue -9223372036854775807 increment by -1;
ERROR HY000: Sequence 'test.t1' has out of range value for options
create or replace sequence t1 maxvalue -9223372036854775806 increment by -1;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with -9223372036854775806 minvalue -9223372036854775807 maxvalue -9223372036854775806 increment by -1 cache 1000 nocycle ENGINE=MyISAM
create or replace sequence t1 maxvalue 9223372036854775806;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
create or replace sequence t1 maxvalue 9223372036854775807;
Warnings:
Note 1292 Truncated incorrect INTEGER value: 'MAXVALUE'
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
create or replace sequence t1 maxvalue 9223372036854775808;
Warnings:
Note 1292 Truncated incorrect INTEGER value: 'MAXVALUE'
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
create or replace sequence t1 maxvalue 9999999999999999999999;
Warnings:
Note 1292 Truncated incorrect INTEGER value: 'MAXVALUE'
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
create or replace sequence t1 start with 10 NO MAXVALUE NO MINVALUE; create or replace sequence t1 start with 10 NO MAXVALUE NO MINVALUE;
create or replace sequence t1 start with 10 maxvalue 10; create or replace sequence t1 start with 10 maxvalue 10;
create or replace sequence t1 start with 10 minvalue 10; create or replace sequence t1 start with 10 minvalue 10;
...@@ -182,15 +242,11 @@ create or replace sequence t1 start with 10 min_value=1 NO MINVALUE; ...@@ -182,15 +242,11 @@ create or replace sequence t1 start with 10 min_value=1 NO MINVALUE;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NO MINVALUE' at line 1 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NO MINVALUE' at line 1
create or replace sequence t1 start with 10 min_value=1 NO MINVALUE; create or replace sequence t1 start with 10 min_value=1 NO MINVALUE;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NO MINVALUE' at line 1 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NO MINVALUE' at line 1
create sequence t1 start with 10 maxvalue=9223372036854775807;
ERROR HY000: Sequence 'test.t1' has out of range value for options
create sequence t1 start with 10 minvalue=-9223372036854775808;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '9223372036854775808' at line 1
create sequence t1 RESTART WITH 10; create sequence t1 RESTART WITH 10;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'RESTART' at line 1 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'RESTART' at line 1
create or replace sequence t1 start with 10 NO MINVALUE minvalue=1; create or replace sequence t1 start with 10 NO MINVALUE minvalue=1;
drop sequence t1; ERROR HY000: Option 'MINVALUE' used twice in statement
create sequence t1; create or replace sequence t1;
show fields from t1; show fields from t1;
Field Type Null Key Default Extra Field Type Null Key Default Extra
next_not_cached_value bigint(21) NO NULL next_not_cached_value bigint(21) NO NULL
......
...@@ -71,6 +71,41 @@ create or replace sequence t1 start with 10 minvalue=-10 maxvalue=11 cache=10 cy ...@@ -71,6 +71,41 @@ create or replace sequence t1 start with 10 minvalue=-10 maxvalue=11 cache=10 cy
show create sequence t1; show create sequence t1;
select * from t1; select * from t1;
# Truncating out-of-bound numbers for minvalue and maxvalue
create or replace sequence t1 minvalue -999999999999999999999;
show create sequence t1;
create or replace sequence t1 minvalue -9223372036854775808;
show create sequence t1;
create or replace sequence t1 minvalue -9223372036854775807;
show create sequence t1;
create or replace sequence t1 minvalue 9223372036854775805;
show create sequence t1;
--error ER_SEQUENCE_INVALID_DATA
create or replace sequence t1 minvalue 9223372036854775806;
--error ER_SEQUENCE_INVALID_DATA
create or replace sequence t1 minvalue 9223372036854775807;
--error ER_SEQUENCE_INVALID_DATA
create or replace sequence t1 minvalue 9223372036854775808;
--error ER_SEQUENCE_INVALID_DATA
create or replace sequence t1 minvalue 9999999999999999999999;
--error ER_SEQUENCE_INVALID_DATA
create or replace sequence t1 maxvalue -999999999999999999999 increment by -1;
--error ER_SEQUENCE_INVALID_DATA
create or replace sequence t1 maxvalue -9223372036854775808 increment by -1;
--error ER_SEQUENCE_INVALID_DATA
create or replace sequence t1 maxvalue -9223372036854775807 increment by -1;
create or replace sequence t1 maxvalue -9223372036854775806 increment by -1;
show create sequence t1;
create or replace sequence t1 maxvalue 9223372036854775806;
show create sequence t1;
create or replace sequence t1 maxvalue 9223372036854775807;
show create sequence t1;
create or replace sequence t1 maxvalue 9223372036854775808;
show create sequence t1;
create or replace sequence t1 maxvalue 9999999999999999999999;
show create sequence t1;
# NO MINVALUE, NO MAXVALUE # NO MINVALUE, NO MAXVALUE
create or replace sequence t1 start with 10 NO MAXVALUE NO MINVALUE; create or replace sequence t1 start with 10 NO MAXVALUE NO MINVALUE;
...@@ -114,21 +149,15 @@ create or replace sequence t1 maxvalue=13, increment= -1; ...@@ -114,21 +149,15 @@ create or replace sequence t1 maxvalue=13, increment= -1;
create or replace sequence t1 start with 10 min_value=1 NO MINVALUE; create or replace sequence t1 start with 10 min_value=1 NO MINVALUE;
--error ER_PARSE_ERROR --error ER_PARSE_ERROR
create or replace sequence t1 start with 10 min_value=1 NO MINVALUE; create or replace sequence t1 start with 10 min_value=1 NO MINVALUE;
--error ER_SEQUENCE_INVALID_DATA
create sequence t1 start with 10 maxvalue=9223372036854775807;
--error ER_PARSE_ERROR
create sequence t1 start with 10 minvalue=-9223372036854775808;
--error ER_PARSE_ERROR --error ER_PARSE_ERROR
create sequence t1 RESTART WITH 10; create sequence t1 RESTART WITH 10;
--error ER_DUP_ARGUMENT
# This should probably give an error
create or replace sequence t1 start with 10 NO MINVALUE minvalue=1; create or replace sequence t1 start with 10 NO MINVALUE minvalue=1;
drop sequence t1;
# #
# Test with LIST COLUMNS as first command # Test with LIST COLUMNS as first command
# #
create sequence t1; create or replace sequence t1;
show fields from t1; show fields from t1;
flush tables; flush tables;
show fields from t1; show fields from t1;
......
...@@ -227,7 +227,7 @@ int ha_sequence::write_row(const uchar *buf) ...@@ -227,7 +227,7 @@ int ha_sequence::write_row(const uchar *buf)
int error= 0; int error= 0;
/* This is called from alter table */ /* This is called from alter table */
tmp_seq.read_fields(table); tmp_seq.read_fields(table);
if (tmp_seq.check_and_adjust(0)) if (tmp_seq.check_and_adjust(thd, 0))
DBUG_RETURN(HA_ERR_SEQUENCE_INVALID_DATA); DBUG_RETURN(HA_ERR_SEQUENCE_INVALID_DATA);
sequence->copy(&tmp_seq); sequence->copy(&tmp_seq);
if (likely(!(error= file->write_row(buf)))) if (likely(!(error= file->write_row(buf))))
...@@ -258,7 +258,7 @@ int ha_sequence::write_row(const uchar *buf) ...@@ -258,7 +258,7 @@ int ha_sequence::write_row(const uchar *buf)
DBUG_RETURN(ER_LOCK_WAIT_TIMEOUT); DBUG_RETURN(ER_LOCK_WAIT_TIMEOUT);
tmp_seq.read_fields(table); tmp_seq.read_fields(table);
if (tmp_seq.check_and_adjust(0)) if (tmp_seq.check_and_adjust(thd, 0))
DBUG_RETURN(HA_ERR_SEQUENCE_INVALID_DATA); DBUG_RETURN(HA_ERR_SEQUENCE_INVALID_DATA);
/* /*
......
...@@ -82,7 +82,7 @@ static Field_definition sequence_structure[]= ...@@ -82,7 +82,7 @@ static Field_definition sequence_structure[]=
true invalid true invalid
*/ */
bool sequence_definition::check_and_adjust(bool set_reserved_until) bool sequence_definition::check_and_adjust(THD *thd, bool set_reserved_until)
{ {
longlong max_increment; longlong max_increment;
DBUG_ENTER("sequence_definition::check"); DBUG_ENTER("sequence_definition::check");
...@@ -104,6 +104,22 @@ bool sequence_definition::check_and_adjust(bool set_reserved_until) ...@@ -104,6 +104,22 @@ bool sequence_definition::check_and_adjust(bool set_reserved_until)
if (!(used_fields & seq_field_used_max_value)) if (!(used_fields & seq_field_used_max_value))
max_value= real_increment < 0 ? -1 : LONGLONG_MAX-1; max_value= real_increment < 0 ? -1 : LONGLONG_MAX-1;
if (max_value == LONGLONG_MAX)
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_TRUNCATED_WRONG_VALUE,
ER_THD(thd, ER_TRUNCATED_WRONG_VALUE),
"INTEGER", "MAXVALUE");
max_value= LONGLONG_MAX - 1;
}
if (min_value == LONGLONG_MIN)
{
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_NOTE, ER_TRUNCATED_WRONG_VALUE,
ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), "INTEGER", "MINVALUE");
min_value= LONGLONG_MIN + 1;
}
if (!(used_fields & seq_field_used_start)) if (!(used_fields & seq_field_used_start))
{ {
/* Use min_value or max_value for start depending on real_increment */ /* Use min_value or max_value for start depending on real_increment */
...@@ -993,7 +1009,7 @@ bool Sql_cmd_alter_sequence::execute(THD *thd) ...@@ -993,7 +1009,7 @@ bool Sql_cmd_alter_sequence::execute(THD *thd)
/* Let check_and_adjust think all fields are used */ /* Let check_and_adjust think all fields are used */
new_seq->used_fields= ~0; new_seq->used_fields= ~0;
if (new_seq->check_and_adjust(0)) if (new_seq->check_and_adjust(thd, 0))
{ {
my_error(ER_SEQUENCE_INVALID_DATA, MYF(0), my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
first_table->db.str, first_table->db.str,
......
...@@ -53,7 +53,7 @@ class sequence_definition :public Sql_alloc ...@@ -53,7 +53,7 @@ class sequence_definition :public Sql_alloc
bool cycle; bool cycle;
uint used_fields; // Which fields where used in CREATE uint used_fields; // Which fields where used in CREATE
bool check_and_adjust(bool set_reserved_until); bool check_and_adjust(THD *thd, bool set_reserved_until);
void store_fields(TABLE *table); void store_fields(TABLE *table);
void read_fields(TABLE *table); void read_fields(TABLE *table);
int write_initial_sequence(TABLE *table); int write_initial_sequence(TABLE *table);
......
...@@ -198,6 +198,7 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)() ...@@ -198,6 +198,7 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
int num; int num;
ulong ulong_num; ulong ulong_num;
ulonglong ulonglong_number; ulonglong ulonglong_number;
ulonglong minus_ulonglong_number;
longlong longlong_number; longlong longlong_number;
uint sp_instr_addr; uint sp_instr_addr;
...@@ -345,9 +346,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); ...@@ -345,9 +346,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
*/ */
%ifdef MARIADB %ifdef MARIADB
%expect 82 %expect 84
%else %else
%expect 83 %expect 85
%endif %endif
/* /*
...@@ -1465,6 +1466,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); ...@@ -1465,6 +1466,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <ulonglong_number> %type <ulonglong_number>
ulonglong_num real_ulonglong_num ulonglong_num real_ulonglong_num
%type <minus_ulonglong_number>
minus_ulonglong_num
%type <longlong_number> %type <longlong_number>
longlong_num longlong_num
...@@ -2419,7 +2423,7 @@ create: ...@@ -2419,7 +2423,7 @@ create:
{ {
LEX *lex= thd->lex; 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), my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
lex->first_select_lex()->table_list.first->db.str, lex->first_select_lex()->table_list.first->db.str,
...@@ -2605,9 +2609,42 @@ sequence_defs: ...@@ -2605,9 +2609,42 @@ sequence_defs:
; ;
sequence_def: sequence_def:
MINVALUE_SYM opt_equal longlong_num MINVALUE_SYM opt_equal ulonglong_num
{ {
Lex->create_info.seq_create_info->min_value= $3; if (unlikely(Lex->create_info.seq_create_info->used_fields &
seq_field_used_min_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MINVALUE"));
if ($3 > (ulonglong) LONGLONG_MAX)
Lex->create_info.seq_create_info->min_value= LONGLONG_MAX;
else
Lex->create_info.seq_create_info->min_value= (longlong) $3;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
}
| MINVALUE_SYM opt_equal minus_ulonglong_num
{
if (unlikely(Lex->create_info.seq_create_info->used_fields &
seq_field_used_min_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MINVALUE"));
if ($3 > (ulonglong) LONGLONG_MAX)
Lex->create_info.seq_create_info->min_value= LONGLONG_MIN;
else
Lex->create_info.seq_create_info->min_value= - (longlong) $3;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
}
| MINVALUE_SYM opt_equal DECIMAL_NUM
{
if (unlikely(Lex->create_info.seq_create_info->used_fields &
seq_field_used_min_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MINVALUE"));
Lex->create_info.seq_create_info->min_value= LONGLONG_MAX;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
}
| MINVALUE_SYM opt_equal '-' DECIMAL_NUM
{
if (unlikely(Lex->create_info.seq_create_info->used_fields &
seq_field_used_min_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MINVALUE"));
Lex->create_info.seq_create_info->min_value= LONGLONG_MIN;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value; Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
} }
| NO_SYM MINVALUE_SYM | NO_SYM MINVALUE_SYM
...@@ -2622,12 +2659,42 @@ sequence_def: ...@@ -2622,12 +2659,42 @@ sequence_def:
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MINVALUE")); my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MINVALUE"));
Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value; Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
} }
| MAXVALUE_SYM opt_equal longlong_num | MAXVALUE_SYM opt_equal ulonglong_num
{
if (unlikely(Lex->create_info.seq_create_info->used_fields &
seq_field_used_max_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MAXVALUE"));
if ($3 > (ulonglong) LONGLONG_MAX)
Lex->create_info.seq_create_info->max_value= LONGLONG_MAX;
else
Lex->create_info.seq_create_info->max_value= (longlong) $3;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
}
| MAXVALUE_SYM opt_equal minus_ulonglong_num
{ {
if (unlikely(Lex->create_info.seq_create_info->used_fields & if (unlikely(Lex->create_info.seq_create_info->used_fields &
seq_field_used_max_value)) seq_field_used_max_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MAXVALUE")); my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MAXVALUE"));
Lex->create_info.seq_create_info->max_value= $3; if ($3 > (ulonglong) LONGLONG_MAX)
Lex->create_info.seq_create_info->max_value= LONGLONG_MIN;
else
Lex->create_info.seq_create_info->max_value= - (longlong) $3;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
}
| MAXVALUE_SYM opt_equal DECIMAL_NUM
{
if (unlikely(Lex->create_info.seq_create_info->used_fields &
seq_field_used_max_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MAXVALUE"));
Lex->create_info.seq_create_info->max_value= LONGLONG_MAX;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
}
| MAXVALUE_SYM opt_equal '-' DECIMAL_NUM
{
if (unlikely(Lex->create_info.seq_create_info->used_fields &
seq_field_used_max_value))
my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MAXVALUE"));
Lex->create_info.seq_create_info->max_value= LONGLONG_MIN;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value; Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
} }
| NO_SYM MAXVALUE_SYM | NO_SYM MAXVALUE_SYM
...@@ -12575,6 +12642,12 @@ ulonglong_num: ...@@ -12575,6 +12642,12 @@ ulonglong_num:
| opt_plus FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); } | opt_plus FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
; ;
minus_ulonglong_num:
'-' NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
| '-' ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
| '-' LONG_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
;
real_ulonglong_num: real_ulonglong_num:
NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); } NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
| ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); } | ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment