diff options
author | Aleksey Midenkov <midenok@gmail.com> | 2018-01-01 13:41:50 +0300 |
---|---|---|
committer | Aleksey Midenkov <midenok@gmail.com> | 2018-01-01 23:37:02 +0300 |
commit | 8efca72f4a47187a0c3bf689a1fa4aecd5452695 (patch) | |
tree | ab5149daa1f2565b1db053d530bcc6896e0176dd | |
parent | 157150cfcf5b95b19d332cb1373aeb5eb22d4f70 (diff) | |
download | mariadb-git-8efca72f4a47187a0c3bf689a1fa4aecd5452695.tar.gz |
MDEV-14792 INSERT without column list into table with explicit versioning columns produces bad data
-rw-r--r-- | include/mysql.h | 1 | ||||
-rw-r--r-- | mysql-test/suite/versioning/r/create.result | 4 | ||||
-rw-r--r-- | mysql-test/suite/versioning/r/cte.result | 18 | ||||
-rw-r--r-- | mysql-test/suite/versioning/r/insert.result | 33 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/create.test | 4 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/cte.test | 16 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/insert.test | 24 | ||||
-rw-r--r-- | sql/sql_base.cc | 41 | ||||
-rw-r--r-- | sql/sql_insert.cc | 18 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 18 | ||||
-rw-r--r-- | sql/sql_trigger.h | 7 | ||||
-rw-r--r-- | sql/table.cc | 33 | ||||
-rw-r--r-- | sql/table.h | 3 |
13 files changed, 74 insertions, 146 deletions
diff --git a/include/mysql.h b/include/mysql.h index 8d8e0589282..a42f90db1ae 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -145,7 +145,6 @@ typedef unsigned long long my_ulonglong; #define ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED #define ER_PRIMARY_KEY_BASED_ON_VIRTUAL_COLUMN ER_PRIMARY_KEY_BASED_ON_GENERATED_COLUMN #define ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN ER_WRONG_FK_OPTION_FOR_GENERATED_COLUMN -#define ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN #define ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN #define ER_UNSUPPORTED_ENGINE_FOR_VIRTUAL_COLUMNS ER_UNSUPPORTED_ENGINE_FOR_GENERATED_COLUMNS diff --git a/mysql-test/suite/versioning/r/create.result b/mysql-test/suite/versioning/r/create.result index 62401eaeef0..f806288d79f 100644 --- a/mysql-test/suite/versioning/r/create.result +++ b/mysql-test/suite/versioning/r/create.result @@ -323,8 +323,8 @@ t2 CREATE TABLE `t2` ( ) ENGINE=NON_DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING create or replace table t1 ( x26 int, -st bigint unsigned as row start invisible, -en bigint unsigned as row end invisible, +st bigint unsigned as row start, +en bigint unsigned as row end, period for system_time (st, en) ) with system versioning engine innodb; create or replace table t2 with system versioning engine myisam diff --git a/mysql-test/suite/versioning/r/cte.result b/mysql-test/suite/versioning/r/cte.result index 2310103a07b..fda5e086be2 100644 --- a/mysql-test/suite/versioning/r/cte.result +++ b/mysql-test/suite/versioning/r/cte.result @@ -47,24 +47,6 @@ emp_id name mgr salary 1 bill NULL 1000 20 john 1 500 30 jane 1 750 -with recursive -ancestors -as -( -select e.emp_id, e.name, e.mgr, e.salary -from emp as e -where name = 'bill' - union -select e.emp_id, e.name, e.mgr, e.salary -from emp as e, -ancestors as a -where e.mgr = a.emp_id -) -select * from ancestors -for system_time as of timestamp @ts_1; -emp_id name mgr salary -1 bill NULL 1000 -30 jane 1 750 /* Expected 3 rows */ with recursive ancestors diff --git a/mysql-test/suite/versioning/r/insert.result b/mysql-test/suite/versioning/r/insert.result index bd358edef09..0e18eb64439 100644 --- a/mysql-test/suite/versioning/r/insert.result +++ b/mysql-test/suite/versioning/r/insert.result @@ -304,13 +304,38 @@ select x, y, sys_trx_end = 18446744073709551615 as current from t1 for system_ti x y current 2 2 1 1 1 0 -create or replace table t1 (i int) with system versioning engine innodb; -insert into t1 values (1),(2); +create or replace table t1 (x int) with system versioning engine innodb; +insert into t1 values (1), (2); insert into t1 (sys_trx_start) select sys_trx_end from t1; -ERROR HY000: Column 'sys_trx_start' is not updatable +ERROR HY000: The value specified for generated column 'sys_trx_start' in table 't1' ignored insert into t1 (sys_trx_start, sys_trx_end) values (DEFAULT, 1); -ERROR HY000: Column 'sys_trx_end' is not updatable +ERROR HY000: The value specified for generated column 'sys_trx_end' in table 't1' ignored +select @@sql_mode into @saved_mode; +set sql_mode= ''; +insert into t1 (x, sys_trx_start, sys_trx_end) values (3, 4, 5); +Warnings: +Warning 1906 The value specified for generated column 'sys_trx_start' in table 't1' ignored +Warning 1906 The value specified for generated column 'sys_trx_end' in table 't1' ignored +set sql_mode= @saved_mode; insert into t1 (sys_trx_start, sys_trx_end) values (DEFAULT, DEFAULT); +select * from t1; +x +1 +2 +3 +NULL +# MDEV-14792 INSERT without column list into table with explicit versioning columns produces bad data +create or replace table t1 ( +i int, +s timestamp(6) as row start, +e timestamp(6) as row end, +c varchar(8), +period for system_time(s, e)) +with system versioning; +insert into t1 values (1, null, null, 'foo'); +select i, c, current_row(e) from t1; +i c current_row(e) +1 foo 1 drop table t1; drop table t2; drop procedure test_01; diff --git a/mysql-test/suite/versioning/t/create.test b/mysql-test/suite/versioning/t/create.test index ec2f26735bd..25046e2e4b1 100644 --- a/mysql-test/suite/versioning/t/create.test +++ b/mysql-test/suite/versioning/t/create.test @@ -289,8 +289,8 @@ show create table t2; create or replace table t1 ( x26 int, - st bigint unsigned as row start invisible, - en bigint unsigned as row end invisible, + st bigint unsigned as row start, + en bigint unsigned as row end, period for system_time (st, en) ) with system versioning engine innodb; --error ER_VERS_FIELD_WRONG_TYPE diff --git a/mysql-test/suite/versioning/t/cte.test b/mysql-test/suite/versioning/t/cte.test index b553a9c7114..9df0bb3dfba 100644 --- a/mysql-test/suite/versioning/t/cte.test +++ b/mysql-test/suite/versioning/t/cte.test @@ -51,22 +51,6 @@ as ) select * from ancestors; -with recursive -ancestors -as -( - select e.emp_id, e.name, e.mgr, e.salary - from emp as e - where name = 'bill' - union - select e.emp_id, e.name, e.mgr, e.salary - from emp as e, - ancestors as a - where e.mgr = a.emp_id -) -select * from ancestors -for system_time as of timestamp @ts_1; - /* Expected 3 rows */ with recursive ancestors diff --git a/mysql-test/suite/versioning/t/insert.test b/mysql-test/suite/versioning/t/insert.test index 8336e0a2671..c24d6bca398 100644 --- a/mysql-test/suite/versioning/t/insert.test +++ b/mysql-test/suite/versioning/t/insert.test @@ -206,13 +206,29 @@ insert into t1 values (1, null); update t1 set x= x + 1; select x, y, sys_trx_end = 18446744073709551615 as current from t1 for system_time all; -create or replace table t1 (i int) with system versioning engine innodb; -insert into t1 values (1),(2); ---error ER_NONUPDATEABLE_COLUMN +create or replace table t1 (x int) with system versioning engine innodb; +insert into t1 values (1), (2); +--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN insert into t1 (sys_trx_start) select sys_trx_end from t1; ---error ER_NONUPDATEABLE_COLUMN +--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN insert into t1 (sys_trx_start, sys_trx_end) values (DEFAULT, 1); +select @@sql_mode into @saved_mode; +set sql_mode= ''; +insert into t1 (x, sys_trx_start, sys_trx_end) values (3, 4, 5); +set sql_mode= @saved_mode; insert into t1 (sys_trx_start, sys_trx_end) values (DEFAULT, DEFAULT); +select * from t1; + +--echo # MDEV-14792 INSERT without column list into table with explicit versioning columns produces bad data +create or replace table t1 ( + i int, + s timestamp(6) as row start, + e timestamp(6) as row end, + c varchar(8), + period for system_time(s, e)) +with system versioning; +insert into t1 values (1, null, null, 'foo'); +select i, c, current_row(e) from t1; drop table t1; drop table t2; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 45d626697d9..a1d09faae6a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7500,6 +7500,7 @@ bool Field::vers_sys_invisible(THD *thd) const SELECT_LEX *slex= thd->lex->current_select; ulong vers_hide= thd->variables.vers_hide; DBUG_ASSERT(table); + DBUG_ASSERT(table->versioned()); DBUG_ASSERT(table->pos_in_table_list); TABLE_LIST *tl= table->pos_in_table_list; vers_system_time_t vers_type= tl->vers_conditions.type; @@ -7508,6 +7509,7 @@ bool Field::vers_sys_invisible(THD *thd) const slex->nest_level > 0 || vers_hide == VERS_HIDE_FULL || (invisible && ( + thd->lex->sql_command != SQLCOM_SELECT || vers_hide == VERS_HIDE_IMPLICIT || (vers_hide == VERS_HIDE_AUTO && ( vers_type == SYSTEM_TIME_UNSPECIFIED || @@ -7649,8 +7651,6 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, field->vers_sys_invisible(thd) : field->invisible)) { - if (thd->lex->sql_command != SQLCOM_CREATE_TABLE || - !(thd->lex->create_info.options & HA_VERSIONED_TABLE)) continue; } @@ -8059,25 +8059,21 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values, rfield->field_index == table->next_number_field->field_index) table->auto_increment_field_not_null= TRUE; Item::Type type= value->type(); - if (rfield->vcol_info && + bool vers_sys_field= table->versioned() && rfield->vers_sys_field(); + if ((rfield->vcol_info || vers_sys_field) && type != Item::DEFAULT_VALUE_ITEM && type != Item::NULL_ITEM && table->s->table_category != TABLE_CATEGORY_TEMPORARY) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN, - ER_THD(thd, ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN), + ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN, + ER_THD(thd, ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN), rfield->field_name.str, table->s->table_name.str); + if (vers_sys_field) + continue; } if (only_unvers_fields && !rfield->vers_update_unversioned()) only_unvers_fields= false; - if (table->versioned() && rfield->vers_sys_field()) - { - if (type == Item::DEFAULT_VALUE_ITEM) - continue; - my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), rfield->field_name.str); - goto err; - } if (rfield->stored_in_db() && (value->save_in_field(rfield, 0)) < 0 && !ignore_errors) @@ -8310,23 +8306,18 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values, /* Ensure that all fields are from the same table */ DBUG_ASSERT(field->table == table); - bool vers_sys_field= table->versioned() && field->vers_sys_field(); - - if (vers_sys_field && !ignore_errors) - { - my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), field->field_name.str); - goto err; - } - - if (field->invisible && !vers_sys_field) + if (field->invisible) { continue; } else value=v++; + + bool vers_sys_field= table->versioned() && field->vers_sys_field(); + if (field->field_index == autoinc_index) table->auto_increment_field_not_null= TRUE; - if (field->vcol_info) + if (field->vcol_info || (vers_sys_field && !ignore_errors)) { Item::Type type= value->type(); if (type != Item::DEFAULT_VALUE_ITEM && @@ -8334,9 +8325,11 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values, table->s->table_category != TABLE_CATEGORY_TEMPORARY) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN, - ER_THD(thd, ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN), + ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN, + ER_THD(thd, ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN), field->field_name.str, table->s->table_name.str); + if (vers_sys_field) + continue; } } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 994ad954ed2..b58a2ea8e24 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -682,17 +682,6 @@ Field **TABLE::field_to_fill() } -inline -Field **TABLE::vers_user_field_to_fill() -{ - if (versioned()) - { - return triggers && triggers->vers_user_fields() ? triggers->vers_user_fields() : vers_user_field; - } - return field_to_fill(); -} - - /** INSERT statement implementation @@ -1020,7 +1009,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, } table->reset_default_fields(); if (fill_record_n_invoke_before_triggers(thd, table, - table->vers_user_field_to_fill(), + table->field_to_fill(), *values, 0, TRG_EVENT_INSERT)) { if (values_list.elements != 1 && ! thd->is_error()) @@ -2612,9 +2601,6 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) } *field=0; - if (copy->versioned() && copy->vers_update_user_field(client_thd->mem_root)) - goto error; - if (share->virtual_fields || share->default_expressions || share->default_fields) { @@ -3913,7 +3899,7 @@ void select_insert::store_values(List<Item> &values) fill_record_n_invoke_before_triggers(thd, table, *fields, values, 1, TRG_EVENT_INSERT); else - fill_record_n_invoke_before_triggers(thd, table, table->vers_user_field_to_fill(), + fill_record_n_invoke_before_triggers(thd, table, table->field_to_fill(), values, 1, TRG_EVENT_INSERT); DBUG_VOID_RETURN; diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 44aad3ad9f6..53bc05e7c47 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1249,28 +1249,10 @@ bool Table_triggers_list::prepare_record_accessors(TABLE *table) *trg_fld= 0; DBUG_ASSERT(null_ptr <= extra_null_bitmap + null_bytes); bzero(extra_null_bitmap, null_bytes); - - if (table->versioned()) - { - vers_user_field= (Field **)alloc_root(&table->mem_root, - (table->s->fields - VERSIONING_FIELDS + 1) * - sizeof(Field*)); - if (!vers_user_field) - return 1; - Field **dst= vers_user_field; - for (Field **src= record0_field; *src; src++) - { - if ((*src)->vers_sys_field()) - continue; - *dst++= *src; - } - *dst= NULL; - } } else { record0_field= table->field; - vers_user_field= table->vers_user_field; } if (has_triggers(TRG_EVENT_UPDATE,TRG_ACTION_BEFORE) || diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 43cbec7e433..6c02afdb89c 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -146,10 +146,6 @@ class Table_triggers_list: public Sql_alloc Field **record0_field; uchar *extra_null_bitmap; /** - System Versioning: record0_field without system fields. - */ - Field **vers_user_field; - /** Copy of TABLE::Field array with field pointers set to TABLE::record[1] buffer instead of TABLE::record[0] (used for OLD values in on UPDATE trigger and DELETE trigger when it is called for REPLACE). @@ -212,7 +208,7 @@ public: /* End of character ser context. */ Table_triggers_list(TABLE *table_arg) - :record0_field(0), extra_null_bitmap(0), vers_user_field(0), record1_field(0), + :record0_field(0), extra_null_bitmap(0), record1_field(0), trigger_table(table_arg), m_has_unparseable_trigger(false), count(0) { @@ -277,7 +273,6 @@ public: TABLE_LIST *table_list); Field **nullable_fields() { return record0_field; } - Field **vers_user_fields() { return vers_user_field; } void reset_extra_null_bitmap() { size_t null_bytes= (trigger_table->s->stored_fields - diff --git a/sql/table.cc b/sql/table.cc index 882d4c88410..e0435ccf2ca 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3225,17 +3225,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, } (*field_ptr)= 0; // End marker - if (share->versioned) - { - if (outparam->vers_update_user_field()) - goto err; - outparam->vers_write= true; - } - else - { - outparam->vers_user_field= NULL; - outparam->vers_write= false; - } + outparam->vers_write= share->versioned; if (share->found_next_number_field) outparam->found_next_number_field= @@ -7792,27 +7782,6 @@ void TABLE::vers_update_fields() } -bool TABLE::vers_update_user_field(MEM_ROOT *_mem_root) -{ - DBUG_ASSERT(versioned()); - Field **dst= (Field **) alloc_root(_mem_root ? _mem_root : &mem_root, - (s->fields - VERSIONING_FIELDS + 1) * - sizeof(Field*)); - if (!dst) - return true; - - vers_user_field= dst; - for (Field **src= field; *src; src++) - { - if ((*src)->vers_sys_field()) - continue; - *dst++= *src; - } - (*dst)= NULL; - return false; -} - - bool TABLE_LIST::vers_vtmd_name(String& out) const { static const char *vtmd_suffix= "_vtmd"; diff --git a/sql/table.h b/sql/table.h index 656f4ae06a3..17d0f257ebb 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1151,7 +1151,6 @@ public: Field **default_field; /* Fields with non-constant DEFAULT */ Field *next_number_field; /* Set if next_number is activated */ Field *found_next_number_field; /* Set on open */ - Field **vers_user_field; /* Non-system fields */ Virtual_column_info **check_constraints; /* Table's triggers, 0 if there are no of them */ @@ -1509,8 +1508,6 @@ public: bool prepare_triggers_for_update_stmt_or_event(); Field **field_to_fill(); - Field **vers_user_field_to_fill(); - bool vers_update_user_field(MEM_ROOT *mem_root= NULL); bool validate_default_values_of_unset_fields(THD *thd) const; bool insert_all_rows_into_tmp_table(THD *thd, |