summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorEugene Kosov <claprix@yandex.ru>2019-05-10 16:21:22 +0300
committerSergei Golubchik <serg@mariadb.org>2019-05-17 13:53:22 +0200
commit3d649c6e37de47336860bee6d23804d62a0746cb (patch)
treeab4eafed33f5f88832bd4f9b72e5baba5989b756 /sql
parent3d56adbfac394b2b3ffd22a89fe7c2978ed9a505 (diff)
downloadmariadb-git-3d649c6e37de47336860bee6d23804d62a0746cb.tar.gz
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.
Diffstat (limited to 'sql')
-rw-r--r--sql/handler.cc132
-rw-r--r--sql/handler.h5
2 files changed, 72 insertions, 65 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index 3e1cbc117a9..957e1ba0e19 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -7211,8 +7211,9 @@ bool Table_scope_and_contents_source_st::vers_check_system_fields(
{
if (!(options & HA_VERSIONED_TABLE))
return false;
- return vers_info.check_sys_fields(create_table.table_name, create_table.db,
- alter_info);
+ return vers_info.check_sys_fields(
+ create_table.table_name, create_table.db, alter_info,
+ ha_check_storage_engine_flag(db_type, HTON_NATIVE_SYS_VERSIONING));
}
@@ -7321,7 +7322,11 @@ bool Vers_parse_info::fix_alter_info(THD *thd, Alter_info *alter_info,
if (alter_info->flags & ALTER_ADD_SYSTEM_VERSIONING)
{
- if (check_sys_fields(table_name, share->db, alter_info))
+ const bool can_native=
+ ha_check_storage_engine_flag(create_info->db_type,
+ HTON_NATIVE_SYS_VERSIONING) ||
+ create_info->db_type->db_type == DB_TYPE_PARTITION_DB;
+ if (check_sys_fields(table_name, share->db, alter_info, can_native))
return true;
}
@@ -7426,78 +7431,83 @@ bool Vers_parse_info::check_conditions(const Lex_table_name &table_name,
return false;
}
+static bool is_versioning_timestamp(const Create_field *f)
+{
+ return (f->type_handler() == &type_handler_datetime2 ||
+ f->type_handler() == &type_handler_timestamp2) &&
+ f->length == MAX_DATETIME_FULL_WIDTH;
+}
+
+static bool is_some_bigint(const Create_field *f)
+{
+ return f->type_handler() == &type_handler_longlong ||
+ f->type_handler() == &type_handler_vers_trx_id;
+}
+
+static bool is_versioning_bigint(const Create_field *f)
+{
+ return is_some_bigint(f) && f->flags & UNSIGNED_FLAG &&
+ f->length == MY_INT64_NUM_DECIMAL_DIGITS - 1;
+}
+
+static bool require_timestamp(const Create_field *f, Lex_table_name table_name)
+{
+ my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str, "TIMESTAMP(6)",
+ table_name.str);
+ return true;
+}
+static bool require_bigint(const Create_field *f, Lex_table_name table_name)
+{
+ my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str,
+ "BIGINT(20) UNSIGNED", table_name.str);
+ return true;
+}
+
bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name,
const Lex_table_name &db,
- Alter_info *alter_info)
+ Alter_info *alter_info, bool can_native)
{
if (check_conditions(table_name, db))
return true;
+ const Create_field *row_start= NULL;
+ const Create_field *row_end= NULL;
+
List_iterator<Create_field> it(alter_info->create_list);
- uint found_flag= 0;
while (Create_field *f= it++)
{
- vers_sys_type_t f_check_unit= VERS_UNDEFINED;
- uint sys_flag= f->flags & VERS_SYSTEM_FIELD;
+ if (!row_start && f->flags & VERS_SYS_START_FLAG)
+ row_start= f;
+ else if (!row_end && f->flags & VERS_SYS_END_FLAG)
+ row_end= f;
+ }
- if (!sys_flag)
- continue;
+ const bool expect_timestamp=
+ !can_native || !is_some_bigint(row_start) || !is_some_bigint(row_end);
- if (sys_flag & found_flag)
- {
- my_error(ER_VERS_DUPLICATE_ROW_START_END, MYF(0),
- found_flag & VERS_SYS_START_FLAG ? "START" : "END",
- f->field_name.str);
- return true;
- }
+ if (expect_timestamp)
+ {
+ if (!is_versioning_timestamp(row_start))
+ return require_timestamp(row_start, table_name);
- sys_flag|= found_flag;
+ if (!is_versioning_timestamp(row_end))
+ return require_timestamp(row_end, table_name);
+ }
+ else
+ {
+ if (!is_versioning_bigint(row_start))
+ return require_bigint(row_start, table_name);
- if ((f->type_handler() == &type_handler_datetime2 ||
- f->type_handler() == &type_handler_timestamp2) &&
- f->length == MAX_DATETIME_FULL_WIDTH)
- {
- f_check_unit= VERS_TIMESTAMP;
- }
- else if (f->type_handler() == &type_handler_longlong
- && (f->flags & UNSIGNED_FLAG)
- && f->length == (MY_INT64_NUM_DECIMAL_DIGITS - 1))
- {
- f_check_unit= VERS_TRX_ID;
- }
- else
- {
- if (!check_unit)
- check_unit= VERS_TIMESTAMP;
- goto error;
- }
+ if (!is_versioning_bigint(row_end))
+ return require_bigint(row_end, table_name);
+ }
- if (f_check_unit)
- {
- if (check_unit)
- {
- if (check_unit == f_check_unit)
- {
- if (check_unit == VERS_TRX_ID && !TR_table::use_transaction_registry)
- {
- my_error(ER_VERS_TRT_IS_DISABLED, MYF(0));
- return true;
- }
- return false;
- }
- error:
- my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str,
- check_unit == VERS_TIMESTAMP ?
- "TIMESTAMP(6)" :
- "BIGINT(20) UNSIGNED",
- table_name.str);
- return true;
- }
- check_unit= f_check_unit;
- }
+ if (is_versioning_bigint(row_start) && is_versioning_bigint(row_end) &&
+ !TR_table::use_transaction_registry)
+ {
+ my_error(ER_VERS_TRT_IS_DISABLED, MYF(0));
+ return true;
}
- my_error(ER_MISSING, MYF(0), table_name.str, found_flag & VERS_SYS_START_FLAG ?
- "ROW END" : found_flag ? "ROW START" : "ROW START/END");
- return true;
+ return false;
}
diff --git a/sql/handler.h b/sql/handler.h
index 1c336e7e35f..2209bd4071c 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1924,7 +1924,6 @@ extern const LEX_CSTRING null_clex_str;
struct Vers_parse_info
{
Vers_parse_info() :
- check_unit(VERS_UNDEFINED),
versioned_fields(false),
unversioned_fields(false)
{}
@@ -1933,7 +1932,6 @@ struct Vers_parse_info
{
system_time= start_end_t(null_clex_str, null_clex_str);
as_row= start_end_t(null_clex_str, null_clex_str);
- check_unit= VERS_UNDEFINED;
versioned_fields= false;
unversioned_fields= false;
}
@@ -1951,7 +1949,6 @@ struct Vers_parse_info
start_end_t system_time;
start_end_t as_row;
- vers_sys_type_t check_unit;
void set_system_time(Lex_ident start, Lex_ident end)
{
@@ -1993,7 +1990,7 @@ public:
TABLE_LIST &src_table, TABLE_LIST &table);
bool check_sys_fields(const Lex_table_name &table_name,
const Lex_table_name &db,
- Alter_info *alter_info);
+ Alter_info *alter_info, bool can_native);
/**
At least one field was specified 'WITH/WITHOUT SYSTEM VERSIONING'.