From 19da9a51ae174785806c87bcc8fa47406af9ed96 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 28 May 2020 22:22:20 +0300 Subject: [PATCH] MDEV-16937 Strict SQL with system versioned tables causes issues Respect system fields in NO_ZERO_DATE mode. This is the subject for refactoring in MDEV-19597 --- .../federated/federatedx_versioning.result | 4 ++-- .../suite/federated/federatedx_versioning.test | 2 +- mysql-test/suite/versioning/common.inc | 4 ++++ .../suite/versioning/engines.combinations | 5 +++++ mysql-test/suite/versioning/r/select.result | 6 +++--- .../suite/versioning/r/select2,trx_id.rdiff | 4 ++-- mysql-test/suite/versioning/r/select2.result | 10 +++++----- mysql-test/suite/versioning/r/sysvars.result | 4 ++-- mysql-test/suite/versioning/r/view.result | 2 +- mysql-test/suite/versioning/t/select.test | 10 +++++----- mysql-test/suite/versioning/t/select2.test | 10 +++++----- mysql-test/suite/versioning/t/sysvars.test | 4 ++-- mysql-test/suite/versioning/t/view.test | 2 +- sql/field.cc | 7 +++++++ sql/sql_table.cc | 1 + sql/table.cc | 2 +- sql/unireg.cc | 2 ++ storage/federatedx/ha_federatedx.cc | 17 +++++++++++++++++ 18 files changed, 66 insertions(+), 30 deletions(-) diff --git a/mysql-test/suite/federated/federatedx_versioning.result b/mysql-test/suite/federated/federatedx_versioning.result index c708b5f79329b..d9e8a421989dc 100644 --- a/mysql-test/suite/federated/federatedx_versioning.result +++ b/mysql-test/suite/federated/federatedx_versioning.result @@ -9,8 +9,8 @@ show create table tf; Table Create Table tf CREATE TABLE `tf` ( `x` int(11) DEFAULT NULL, - `row_start` SYS_TYPE NOT NULL INVISIBLE DEFAULT 0, - `row_end` SYS_TYPE NOT NULL INVISIBLE DEFAULT 0 + `row_start` SYS_TYPE INVISIBLE DEFAULT '1971-01-01 00:00:00.000000', + `row_end` SYS_TYPE INVISIBLE DEFAULT '1971-01-01 00:00:00.000000' ) ENGINE=FEDERATED DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:MASTER_MYPORT/test/t1' # INSERT insert into t1 values (1); diff --git a/mysql-test/suite/federated/federatedx_versioning.test b/mysql-test/suite/federated/federatedx_versioning.test index 40d0bc5018a9a..44999522a4d78 100644 --- a/mysql-test/suite/federated/federatedx_versioning.test +++ b/mysql-test/suite/federated/federatedx_versioning.test @@ -12,7 +12,7 @@ eval create or replace table t1 ( with system versioning; --replace_result $MASTER_MYPORT MASTER_MYPORT eval create or replace table tf engine=FEDERATED connection='mysql://root@127.0.0.1:$MASTER_MYPORT/test/t1'; ---replace_result $MASTER_MYPORT MASTER_MYPORT $sys_datatype_expl SYS_TYPE "'0000-00-00 00:00:00.000000'" 0 +--replace_result $MASTER_MYPORT MASTER_MYPORT $sys_datatype_expl SYS_TYPE 19710101000000 "'1971-01-01 00:00:00.000000'" " NOT NULL" "" show create table tf; --echo # INSERT insert into t1 values (1); diff --git a/mysql-test/suite/versioning/common.inc b/mysql-test/suite/versioning/common.inc index 355b571e5a044..efb081a02e40d 100644 --- a/mysql-test/suite/versioning/common.inc +++ b/mysql-test/suite/versioning/common.inc @@ -50,6 +50,10 @@ if ($MTR_COMBINATION_MYISAM) { --let $MTR_COMBINATION_TIMESTAMP= 1 } +if ($MTR_COMBINATION_TRADITIONAL) +{ + --let $MTR_COMBINATION_TIMESTAMP= 1 +} if ($MTR_COMBINATION_HEAP) { --let $MTR_COMBINATION_TIMESTAMP= 1 diff --git a/mysql-test/suite/versioning/engines.combinations b/mysql-test/suite/versioning/engines.combinations index 26b5bab23f176..57e2af6cd06bc 100644 --- a/mysql-test/suite/versioning/engines.combinations +++ b/mysql-test/suite/versioning/engines.combinations @@ -7,5 +7,10 @@ default-storage-engine=innodb [myisam] default-storage-engine=myisam +[traditional] +default-storage-engine=myisam +sql-mode=traditional + [heap] default-storage-engine=memory + diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result index 74df243cf7c48..23c6e2d74af8f 100644 --- a/mysql-test/suite/versioning/r/select.result +++ b/mysql-test/suite/versioning/r/select.result @@ -43,7 +43,7 @@ ASOF_x y 7 107 8 108 9 109 -select x as FROMTO_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1; +select x as FROMTO_x, y from t1 for system_time from timestamp '1970-01-01 00:00:00' to timestamp @t1; FROMTO_x y 0 100 1 101 @@ -55,7 +55,7 @@ FROMTO_x y 7 107 8 108 9 109 -select x as BETWAND_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between timestamp '1970-01-01 00:00:00' and timestamp @t1; BETWAND_x y 0 100 1 101 @@ -247,7 +247,7 @@ a b select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; a b 1 2 -select * from (select * from t1 cross join t2 for system_time as of timestamp ('0-0-0')) as tmp; +select * from (select * from t1 cross join t2 for system_time as of timestamp ('1970-01-01 00:00:00')) as tmp; a b create or replace table t1(a1 int) with system versioning; create or replace table t2(a2 int) with system versioning; diff --git a/mysql-test/suite/versioning/r/select2,trx_id.rdiff b/mysql-test/suite/versioning/r/select2,trx_id.rdiff index a657b94c031a6..d4b35c455686c 100644 --- a/mysql-test/suite/versioning/r/select2,trx_id.rdiff +++ b/mysql-test/suite/versioning/r/select2,trx_id.rdiff @@ -22,7 +22,7 @@ 7 107 8 108 9 109 --select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1; +-select x as FROMTO2_x, y from t1 for system_time from '1970-01-01 00:00' to @t1; +select x as FROMTO2_x, y from t1 for system_time from @x0 to @x1; FROMTO2_x y 0 100 @@ -31,7 +31,7 @@ 7 107 8 108 9 109 --select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; +-select x as BETWAND2_x, y from t1 for system_time between timestamp '1970-01-01 00:00' and timestamp @t1; +select x as BETWAND2_x, y from t1 for system_time between transaction @x0 and transaction @x1; BETWAND2_x y 0 100 diff --git a/mysql-test/suite/versioning/r/select2.result b/mysql-test/suite/versioning/r/select2.result index 7b20d68343bee..90607335fc1c4 100644 --- a/mysql-test/suite/versioning/r/select2.result +++ b/mysql-test/suite/versioning/r/select2.result @@ -44,7 +44,7 @@ ASOF_x y 7 107 8 108 9 109 -select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1; +select x as FROMTO_x, y from t1 for system_time from '1970-01-01 00:00' to timestamp @t1; FROMTO_x y 0 100 1 101 @@ -56,7 +56,7 @@ FROMTO_x y 7 107 8 108 9 109 -select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between '1970-01-01 00:00' and timestamp @t1; BETWAND_x y 0 100 1 101 @@ -94,7 +94,7 @@ ASOF2_x y 7 107 8 108 9 109 -select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1; +select x as FROMTO2_x, y from t1 for system_time from '1970-01-01 00:00' to @t1; FROMTO2_x y 0 100 1 101 @@ -106,7 +106,7 @@ FROMTO2_x y 7 107 8 108 9 109 -select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; +select x as BETWAND2_x, y from t1 for system_time between timestamp '1970-01-01 00:00' and timestamp @t1; BETWAND2_x y 0 100 1 101 @@ -270,7 +270,7 @@ a b select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; a b 1 2 -select * from (select * from t1 cross join t2 for system_time as of timestamp ('0-0-0')) as tmp; +select * from (select * from t1 cross join t2 for system_time as of timestamp ('1970-01-01 00:00')) as tmp; a b create or replace table t1(a1 int) with system versioning; create or replace table t2(a2 int) with system versioning; diff --git a/mysql-test/suite/versioning/r/sysvars.result b/mysql-test/suite/versioning/r/sysvars.result index 899eda91a812d..9cb4911b32115 100644 --- a/mysql-test/suite/versioning/r/sysvars.result +++ b/mysql-test/suite/versioning/r/sysvars.result @@ -134,11 +134,11 @@ select * from t for system_time all; a 2 1 -select * from t for system_time from '0-0-0' to current_timestamp(6); +select * from t for system_time from '1970-01-01 00:00' to current_timestamp(6); a 2 1 -select * from t for system_time between '0-0-0' and current_timestamp(6); +select * from t for system_time between '1970-01-01 00:00' and current_timestamp(6); a 2 1 diff --git a/mysql-test/suite/versioning/r/view.result b/mysql-test/suite/versioning/r/view.result index 3b3fe580af496..e9e7489979017 100644 --- a/mysql-test/suite/versioning/r/view.result +++ b/mysql-test/suite/versioning/r/view.result @@ -79,7 +79,7 @@ create or replace view vt12 as select * from t1 cross join t2; select * from vt12; a b 1 2 -create or replace view vt12 as select * from t1 for system_time as of timestamp ('0-0-0') cross join t2; +create or replace view vt12 as select * from t1 for system_time as of timestamp ('1970-01-01 00:00') cross join t2; select * from vt12; a b # VIEW improvements [tempesta-tech/mariadb#183] diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test index 16c2f34ab35cc..c70f2714fff9b 100644 --- a/mysql-test/suite/versioning/t/select.test +++ b/mysql-test/suite/versioning/t/select.test @@ -48,8 +48,8 @@ if ($MTR_COMBINATION_TRX_ID) select x, y from t1; select x as ASOF_x, y from t1 for system_time as of timestamp @t0; -select x as FROMTO_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1; -select x as BETWAND_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; +select x as FROMTO_x, y from t1 for system_time from timestamp '1970-01-01 00:00:00' to timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between timestamp '1970-01-01 00:00:00' and timestamp @t1; select x as ALL_x, y from t1 for system_time all; --disable_query_log @@ -62,8 +62,8 @@ if ($MTR_COMBINATION_TRX_ID) if ($MTR_COMBINATION_TIMESTAMP) { select x as ASOF2_x, y from t1 for system_time as of @t0; - select x as FROMTO2_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1; - select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; + select x as FROMTO2_x, y from t1 for system_time from timestamp '1970-01-01 00:00:00' to timestamp @t1; + select x as BETWAND2_x, y from t1 for system_time between timestamp '1970-01-01 00:00:00' and timestamp @t1; } --enable_query_log @@ -161,7 +161,7 @@ insert into t1 values (1); insert into t2 values (2); select * from (select * from t1 cross join t2) as tmp; select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; -select * from (select * from t1 cross join t2 for system_time as of timestamp ('0-0-0')) as tmp; +select * from (select * from t1 cross join t2 for system_time as of timestamp ('1970-01-01 00:00:00')) as tmp; create or replace table t1(a1 int) with system versioning; create or replace table t2(a2 int) with system versioning; diff --git a/mysql-test/suite/versioning/t/select2.test b/mysql-test/suite/versioning/t/select2.test index fa5d52c5143a2..7ede218cabff2 100644 --- a/mysql-test/suite/versioning/t/select2.test +++ b/mysql-test/suite/versioning/t/select2.test @@ -36,8 +36,8 @@ if($MTR_COMBINATION_TRX_ID) { select x, y from t1; select x as ASOF_x, y from t1 for system_time as of timestamp @t0; -select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1; -select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1; +select x as FROMTO_x, y from t1 for system_time from '1970-01-01 00:00' to timestamp @t1; +select x as BETWAND_x, y from t1 for system_time between '1970-01-01 00:00' and timestamp @t1; select x as ALL_x, y from t1 for system_time all; if($MTR_COMBINATION_TRX_ID) { @@ -47,8 +47,8 @@ if($MTR_COMBINATION_TRX_ID) { } if(!$MTR_COMBINATION_TRX_ID) { select x as ASOF2_x, y from t1 for system_time as of @t0; - select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1; - select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1; + select x as FROMTO2_x, y from t1 for system_time from '1970-01-01 00:00' to @t1; + select x as BETWAND2_x, y from t1 for system_time between timestamp '1970-01-01 00:00' and timestamp @t1; } drop table t1; @@ -166,7 +166,7 @@ insert into t1 values (1); insert into t2 values (2); select * from (select * from t1 cross join t2) as tmp; select * from (select * from (select * from t1 cross join t2) as tmp1) as tmp2; -select * from (select * from t1 cross join t2 for system_time as of timestamp ('0-0-0')) as tmp; +select * from (select * from t1 cross join t2 for system_time as of timestamp ('1970-01-01 00:00')) as tmp; create or replace table t1(a1 int) with system versioning; create or replace table t2(a2 int) with system versioning; diff --git a/mysql-test/suite/versioning/t/sysvars.test b/mysql-test/suite/versioning/t/sysvars.test index 8c8311d66fcfa..1999ddd13fcf9 100644 --- a/mysql-test/suite/versioning/t/sysvars.test +++ b/mysql-test/suite/versioning/t/sysvars.test @@ -97,8 +97,8 @@ select * from t for system_time all; select * from t; select * from t for system_time as of timestamp current_timestamp(6); select * from t for system_time all; -select * from t for system_time from '0-0-0' to current_timestamp(6); -select * from t for system_time between '0-0-0' and current_timestamp(6); +select * from t for system_time from '1970-01-01 00:00' to current_timestamp(6); +select * from t for system_time between '1970-01-01 00:00' and current_timestamp(6); show status like "Feature_system_versioning"; diff --git a/mysql-test/suite/versioning/t/view.test b/mysql-test/suite/versioning/t/view.test index 288f1eb6e21a2..37676a7fb5074 100644 --- a/mysql-test/suite/versioning/t/view.test +++ b/mysql-test/suite/versioning/t/view.test @@ -65,7 +65,7 @@ insert into t1 values (1); insert into t2 values (2); create or replace view vt12 as select * from t1 cross join t2; select * from vt12; -create or replace view vt12 as select * from t1 for system_time as of timestamp ('0-0-0') cross join t2; +create or replace view vt12 as select * from t1 for system_time as of timestamp ('1970-01-01 00:00') cross join t2; select * from vt12; --echo # VIEW improvements [tempesta-tech/mariadb#183] diff --git a/sql/field.cc b/sql/field.cc index a9cf4589a1695..519a00677ec99 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -11456,6 +11456,13 @@ bool Field::save_in_field_default_value(bool view_error_processing) { THD *thd= table->in_use; + /* + TODO: MDEV-19597 Refactor TABLE::vers_update_fields() via stored virtual columns + This condition will go away as well as other conditions with vers_sys_field(). + */ + if (vers_sys_field()) + return false; + if (unlikely(flags & NO_DEFAULT_VALUE_FLAG && real_type() != MYSQL_TYPE_ENUM)) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 30b728adf6944..c6b22650d5c18 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4195,6 +4195,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (thd->variables.sql_mode & MODE_NO_ZERO_DATE && !sql_field->default_value && !sql_field->vcol_info && + !sql_field->vers_sys_field() && sql_field->is_timestamp_type() && !opt_explicit_defaults_for_timestamp && (sql_field->flags & NOT_NULL_FLAG) && diff --git a/sql/table.cc b/sql/table.cc index c91e9d84a599b..7d09985094c98 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8222,7 +8222,7 @@ bool TABLE::validate_default_values_of_unset_fields(THD *thd) const for (Field **fld= field; *fld; fld++) { if (!bitmap_is_set(write_set, (*fld)->field_index) && - !((*fld)->flags & NO_DEFAULT_VALUE_FLAG)) + !((*fld)->flags & (NO_DEFAULT_VALUE_FLAG | VERS_SYSTEM_FIELD))) { if (!(*fld)->is_null_in_record(s->default_values) && (*fld)->validate_value_in_record_with_warn(thd, s->default_values) && diff --git a/sql/unireg.cc b/sql/unireg.cc index fa30bab15a2e1..b7eb1cd3457e2 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -1086,6 +1086,7 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, null_count+= field->length & 7; if (field->default_value && !field->default_value->flags && + !field->vers_sys_field() && (!(field->flags & BLOB_FLAG) || field->real_field_type() == MYSQL_TYPE_GEOMETRY)) { @@ -1108,6 +1109,7 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, delete regfield; //To avoid memory leak } else if (regfield->real_type() == MYSQL_TYPE_ENUM && + !field->vers_sys_field() && (field->flags & NOT_NULL_FLAG)) { regfield->set_notnull(); diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index 4a717eead20da..1adb7b214f006 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -3611,6 +3611,9 @@ int ha_federatedx::discover_assisted(handlerton *hton, THD* thd, char buf[1024]; String query(buf, sizeof(buf), cs); static LEX_CSTRING cut_clause={STRING_WITH_LEN(" WITH SYSTEM VERSIONING")}; + static LEX_CSTRING cut_start={STRING_WITH_LEN("GENERATED ALWAYS AS ROW START")}; + static LEX_CSTRING cut_end={STRING_WITH_LEN("GENERATED ALWAYS AS ROW END")}; + static LEX_CSTRING set_ts={STRING_WITH_LEN("DEFAULT TIMESTAMP'1971-01-01 00:00:00'")}; int cut_offset; MYSQL_RES *res; MYSQL_ROW rdata; @@ -3649,7 +3652,21 @@ int ha_federatedx::discover_assisted(handlerton *hton, THD* thd, cut_offset= (int)query.length() - (int)cut_clause.length; if (cut_offset > 0 && !memcmp(query.ptr() + cut_offset, cut_clause.str, cut_clause.length)) + { query.length(cut_offset); + const char *ptr= strstr(query.ptr(), cut_start.str); + if (ptr) + { + query.replace((uint32) (ptr - query.ptr()), (uint32) cut_start.length, + set_ts.str, (uint32) set_ts.length); + } + ptr= strstr(query.ptr(), cut_end.str); + if (ptr) + { + query.replace((uint32) (ptr - query.ptr()), (uint32) cut_end.length, + set_ts.str, (uint32) set_ts.length); + } + } query.append(STRING_WITH_LEN(" CONNECTION='"), cs); query.append_for_single_quote(table_s->connect_string.str, table_s->connect_string.length);