Skip to content

Commit 3d649c6

Browse files
kevgsvuvova
authored andcommitted
MDEV-15408 Confusing error message upon ER_VERS_FIELD_WRONG_TYPE while omitting UNSIGNED in BIGINT
Improve diagnostics. Try to guess what type user tried to type.
1 parent 3d56adb commit 3d649c6

File tree

4 files changed

+103
-66
lines changed

4 files changed

+103
-66
lines changed

mysql-test/suite/versioning/r/create.result

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ Sys_start bigint as row start invisible,
157157
Sys_end bigint unsigned as row end invisible,
158158
period for system_time (Sys_start, Sys_end)
159159
) with system versioning engine innodb;
160-
ERROR HY000: `Sys_start` must be of type TIMESTAMP(6) for system-versioned table `t1`
160+
ERROR HY000: `Sys_start` must be of type BIGINT(20) UNSIGNED for system-versioned table `t1`
161161
create or replace table t1 (
162162
x14 int unsigned,
163163
Sys_start bigint unsigned as row start invisible,
@@ -495,5 +495,19 @@ Table Create Table
495495
t1 CREATE TABLE `t1` (
496496
`i` int(11) DEFAULT NULL
497497
) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
498+
create or replace table t1 (
499+
a int,
500+
row_start bigint as row start,
501+
row_end bigint as row end,
502+
period for system_time (row_start, row_end)
503+
) engine=innodb with system versioning;
504+
ERROR HY000: `row_start` must be of type BIGINT(20) UNSIGNED for system-versioned table `t1`
505+
create or replace table t1 (
506+
a int,
507+
row_start bigint as row start,
508+
row_end bigint as row end,
509+
period for system_time (row_start, row_end)
510+
) engine=myisam with system versioning;
511+
ERROR HY000: `row_start` must be of type TIMESTAMP(6) for system-versioned table `t1`
498512
drop database test;
499513
create database test;

mysql-test/suite/versioning/t/create.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,5 +371,21 @@ create or replace table t1 (i int) with system versioning as select 1 as i;
371371
--replace_result $default_engine DEFAULT_ENGINE
372372
show create table t1;
373373

374+
--error ER_VERS_FIELD_WRONG_TYPE
375+
create or replace table t1 (
376+
a int,
377+
row_start bigint as row start,
378+
row_end bigint as row end,
379+
period for system_time (row_start, row_end)
380+
) engine=innodb with system versioning;
381+
382+
--error ER_VERS_FIELD_WRONG_TYPE
383+
create or replace table t1 (
384+
a int,
385+
row_start bigint as row start,
386+
row_end bigint as row end,
387+
period for system_time (row_start, row_end)
388+
) engine=myisam with system versioning;
389+
374390
drop database test;
375391
create database test;

sql/handler.cc

Lines changed: 71 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -7211,8 +7211,9 @@ bool Table_scope_and_contents_source_st::vers_check_system_fields(
72117211
{
72127212
if (!(options & HA_VERSIONED_TABLE))
72137213
return false;
7214-
return vers_info.check_sys_fields(create_table.table_name, create_table.db,
7215-
alter_info);
7214+
return vers_info.check_sys_fields(
7215+
create_table.table_name, create_table.db, alter_info,
7216+
ha_check_storage_engine_flag(db_type, HTON_NATIVE_SYS_VERSIONING));
72167217
}
72177218

72187219

@@ -7321,7 +7322,11 @@ bool Vers_parse_info::fix_alter_info(THD *thd, Alter_info *alter_info,
73217322

73227323
if (alter_info->flags & ALTER_ADD_SYSTEM_VERSIONING)
73237324
{
7324-
if (check_sys_fields(table_name, share->db, alter_info))
7325+
const bool can_native=
7326+
ha_check_storage_engine_flag(create_info->db_type,
7327+
HTON_NATIVE_SYS_VERSIONING) ||
7328+
create_info->db_type->db_type == DB_TYPE_PARTITION_DB;
7329+
if (check_sys_fields(table_name, share->db, alter_info, can_native))
73257330
return true;
73267331
}
73277332

@@ -7426,78 +7431,83 @@ bool Vers_parse_info::check_conditions(const Lex_table_name &table_name,
74267431
return false;
74277432
}
74287433

7434+
static bool is_versioning_timestamp(const Create_field *f)
7435+
{
7436+
return (f->type_handler() == &type_handler_datetime2 ||
7437+
f->type_handler() == &type_handler_timestamp2) &&
7438+
f->length == MAX_DATETIME_FULL_WIDTH;
7439+
}
7440+
7441+
static bool is_some_bigint(const Create_field *f)
7442+
{
7443+
return f->type_handler() == &type_handler_longlong ||
7444+
f->type_handler() == &type_handler_vers_trx_id;
7445+
}
7446+
7447+
static bool is_versioning_bigint(const Create_field *f)
7448+
{
7449+
return is_some_bigint(f) && f->flags & UNSIGNED_FLAG &&
7450+
f->length == MY_INT64_NUM_DECIMAL_DIGITS - 1;
7451+
}
7452+
7453+
static bool require_timestamp(const Create_field *f, Lex_table_name table_name)
7454+
{
7455+
my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str, "TIMESTAMP(6)",
7456+
table_name.str);
7457+
return true;
7458+
}
7459+
static bool require_bigint(const Create_field *f, Lex_table_name table_name)
7460+
{
7461+
my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str,
7462+
"BIGINT(20) UNSIGNED", table_name.str);
7463+
return true;
7464+
}
7465+
74297466
bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name,
74307467
const Lex_table_name &db,
7431-
Alter_info *alter_info)
7468+
Alter_info *alter_info, bool can_native)
74327469
{
74337470
if (check_conditions(table_name, db))
74347471
return true;
74357472

7473+
const Create_field *row_start= NULL;
7474+
const Create_field *row_end= NULL;
7475+
74367476
List_iterator<Create_field> it(alter_info->create_list);
7437-
uint found_flag= 0;
74387477
while (Create_field *f= it++)
74397478
{
7440-
vers_sys_type_t f_check_unit= VERS_UNDEFINED;
7441-
uint sys_flag= f->flags & VERS_SYSTEM_FIELD;
7479+
if (!row_start && f->flags & VERS_SYS_START_FLAG)
7480+
row_start= f;
7481+
else if (!row_end && f->flags & VERS_SYS_END_FLAG)
7482+
row_end= f;
7483+
}
74427484

7443-
if (!sys_flag)
7444-
continue;
7485+
const bool expect_timestamp=
7486+
!can_native || !is_some_bigint(row_start) || !is_some_bigint(row_end);
74457487

7446-
if (sys_flag & found_flag)
7447-
{
7448-
my_error(ER_VERS_DUPLICATE_ROW_START_END, MYF(0),
7449-
found_flag & VERS_SYS_START_FLAG ? "START" : "END",
7450-
f->field_name.str);
7451-
return true;
7452-
}
7488+
if (expect_timestamp)
7489+
{
7490+
if (!is_versioning_timestamp(row_start))
7491+
return require_timestamp(row_start, table_name);
74537492

7454-
sys_flag|= found_flag;
7493+
if (!is_versioning_timestamp(row_end))
7494+
return require_timestamp(row_end, table_name);
7495+
}
7496+
else
7497+
{
7498+
if (!is_versioning_bigint(row_start))
7499+
return require_bigint(row_start, table_name);
74557500

7456-
if ((f->type_handler() == &type_handler_datetime2 ||
7457-
f->type_handler() == &type_handler_timestamp2) &&
7458-
f->length == MAX_DATETIME_FULL_WIDTH)
7459-
{
7460-
f_check_unit= VERS_TIMESTAMP;
7461-
}
7462-
else if (f->type_handler() == &type_handler_longlong
7463-
&& (f->flags & UNSIGNED_FLAG)
7464-
&& f->length == (MY_INT64_NUM_DECIMAL_DIGITS - 1))
7465-
{
7466-
f_check_unit= VERS_TRX_ID;
7467-
}
7468-
else
7469-
{
7470-
if (!check_unit)
7471-
check_unit= VERS_TIMESTAMP;
7472-
goto error;
7473-
}
7501+
if (!is_versioning_bigint(row_end))
7502+
return require_bigint(row_end, table_name);
7503+
}
74747504

7475-
if (f_check_unit)
7476-
{
7477-
if (check_unit)
7478-
{
7479-
if (check_unit == f_check_unit)
7480-
{
7481-
if (check_unit == VERS_TRX_ID && !TR_table::use_transaction_registry)
7482-
{
7483-
my_error(ER_VERS_TRT_IS_DISABLED, MYF(0));
7484-
return true;
7485-
}
7486-
return false;
7487-
}
7488-
error:
7489-
my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str,
7490-
check_unit == VERS_TIMESTAMP ?
7491-
"TIMESTAMP(6)" :
7492-
"BIGINT(20) UNSIGNED",
7493-
table_name.str);
7494-
return true;
7495-
}
7496-
check_unit= f_check_unit;
7497-
}
7505+
if (is_versioning_bigint(row_start) && is_versioning_bigint(row_end) &&
7506+
!TR_table::use_transaction_registry)
7507+
{
7508+
my_error(ER_VERS_TRT_IS_DISABLED, MYF(0));
7509+
return true;
74987510
}
74997511

7500-
my_error(ER_MISSING, MYF(0), table_name.str, found_flag & VERS_SYS_START_FLAG ?
7501-
"ROW END" : found_flag ? "ROW START" : "ROW START/END");
7502-
return true;
7512+
return false;
75037513
}

sql/handler.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,7 +1924,6 @@ extern const LEX_CSTRING null_clex_str;
19241924
struct Vers_parse_info
19251925
{
19261926
Vers_parse_info() :
1927-
check_unit(VERS_UNDEFINED),
19281927
versioned_fields(false),
19291928
unversioned_fields(false)
19301929
{}
@@ -1933,7 +1932,6 @@ struct Vers_parse_info
19331932
{
19341933
system_time= start_end_t(null_clex_str, null_clex_str);
19351934
as_row= start_end_t(null_clex_str, null_clex_str);
1936-
check_unit= VERS_UNDEFINED;
19371935
versioned_fields= false;
19381936
unversioned_fields= false;
19391937
}
@@ -1951,7 +1949,6 @@ struct Vers_parse_info
19511949

19521950
start_end_t system_time;
19531951
start_end_t as_row;
1954-
vers_sys_type_t check_unit;
19551952

19561953
void set_system_time(Lex_ident start, Lex_ident end)
19571954
{
@@ -1993,7 +1990,7 @@ struct Vers_parse_info
19931990
TABLE_LIST &src_table, TABLE_LIST &table);
19941991
bool check_sys_fields(const Lex_table_name &table_name,
19951992
const Lex_table_name &db,
1996-
Alter_info *alter_info);
1993+
Alter_info *alter_info, bool can_native);
19971994

19981995
/**
19991996
At least one field was specified 'WITH/WITHOUT SYSTEM VERSIONING'.

0 commit comments

Comments
 (0)