From 0581c018b79230b7ce5a4d9e3af928b6152577f1 Mon Sep 17 00:00:00 2001 From: Kosov Eugene Date: Mon, 7 Nov 2016 22:01:29 +0300 Subject: [PATCH] SQL: NULL instead of optimized fields in versioned queries --- .../versioning/r/optimized_fields.result | 68 +++++++++++++++++++ .../suite/versioning/t/optimized_fields.test | 22 ++++++ sql/field.cc | 2 +- sql/field.h | 4 ++ sql/item.cc | 17 +++++ sql/share/errmsg-utf8.txt | 3 + 6 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/versioning/r/optimized_fields.result create mode 100644 mysql-test/suite/versioning/t/optimized_fields.test diff --git a/mysql-test/suite/versioning/r/optimized_fields.result b/mysql-test/suite/versioning/r/optimized_fields.result new file mode 100644 index 0000000000000..2e26643096793 --- /dev/null +++ b/mysql-test/suite/versioning/r/optimized_fields.result @@ -0,0 +1,68 @@ +create table t( +a int, +b int without system versioning +) with system versioning; +insert into t values(1, 2); +insert into t values(3, 4); +select * from t; +a b +1 2 +3 4 +select a from t for system_time as of timestamp now(6); +a +1 +3 +select a, b, b+0 from t for system_time as of timestamp now(6); +a b b+0 +1 NULL NULL +3 NULL NULL +Warnings: +Warning 4050 Attempt to read unversioned field 'b' in historical query +select * from t for system_time as of timestamp now(6); +a b +1 NULL +3 NULL +Warnings: +Warning 4050 Attempt to read unversioned field 'b' in historical query +select count(*) from t group by b for system_time as of timestamp now(6); +count(*) +2 +Warnings: +Warning 4050 Attempt to read unversioned field 'b' in historical query +select * from t for system_time as of timestamp now(6) order by b asc; +a b +1 NULL +3 NULL +Warnings: +Warning 4050 Attempt to read unversioned field 'b' in historical query +select * from t for system_time as of timestamp now(6) order by b desc; +a b +1 NULL +3 NULL +Warnings: +Warning 4050 Attempt to read unversioned field 'b' in historical query +select * from t group by a having a=2 for system_time as of timestamp now(6); +a b +Warnings: +Warning 4050 Attempt to read unversioned field 'b' in historical query +select * from t group by b having b=2 for system_time as of timestamp now(6); +a b +Warnings: +Warning 4050 Attempt to read unversioned field 'b' in historical query +select a from t where b=2 for system_time as of timestamp now(6); +a +Warnings: +Warning 4050 Attempt to read unversioned field 'b' in historical query +select a from t where b=NULL for system_time as of timestamp now(6); +a +Warnings: +Warning 4050 Attempt to read unversioned field 'b' in historical query +select count(*), b from t group by b having b=NULL for system_time as of timestamp now(6); +count(*) b +Warnings: +Warning 4050 Attempt to read unversioned field 'b' in historical query +select a, b from t; +a b +1 2 +3 4 +drop table t; diff --git a/mysql-test/suite/versioning/t/optimized_fields.test b/mysql-test/suite/versioning/t/optimized_fields.test new file mode 100644 index 0000000000000..62f245dc28d81 --- /dev/null +++ b/mysql-test/suite/versioning/t/optimized_fields.test @@ -0,0 +1,22 @@ +create table t( + a int, + b int without system versioning +) with system versioning; + +insert into t values(1, 2); +insert into t values(3, 4); +select * from t; +select a from t for system_time as of timestamp now(6); +select a, b, b+0 from t for system_time as of timestamp now(6); +select * from t for system_time as of timestamp now(6); +select count(*) from t group by b for system_time as of timestamp now(6); +select * from t for system_time as of timestamp now(6) order by b asc; +select * from t for system_time as of timestamp now(6) order by b desc; +select * from t group by a having a=2 for system_time as of timestamp now(6); +select * from t group by b having b=2 for system_time as of timestamp now(6); +select a from t where b=2 for system_time as of timestamp now(6); +select a from t where b=NULL for system_time as of timestamp now(6); +select count(*), b from t group by b having b=NULL for system_time as of timestamp now(6); +select a, b from t; + +drop table t; diff --git a/sql/field.cc b/sql/field.cc index c22ae9e2df36c..a7108924f5744 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1631,7 +1631,7 @@ Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, :ptr(ptr_arg), null_ptr(null_ptr_arg), table(0), orig_table(0), table_name(0), field_name(field_name_arg), option_list(0), option_struct(0), key_start(0), part_of_key(0), - part_of_key_not_clustered(0), part_of_sortkey(0), + part_of_key_not_clustered(0), force_null(false), part_of_sortkey(0), unireg_check(unireg_check_arg), field_length(length_arg), null_bit(null_bit_arg), is_created_from_null_item(FALSE), read_stats(NULL), collected_stats(0), vcol_info(0), check_constraint(0), diff --git a/sql/field.h b/sql/field.h index 16e53c72b11b1..f3c29c29cac11 100644 --- a/sql/field.h +++ b/sql/field.h @@ -707,6 +707,8 @@ class Field: public Value_source /* Field is part of the following keys */ key_map key_start, part_of_key, part_of_key_not_clustered; + bool force_null; + /* Bitmap of indexes that have records ordered by col1, ... this_field, ... @@ -1089,6 +1091,8 @@ class Field: public Value_source virtual uint size_of() const =0; // For new field inline bool is_null(my_ptrdiff_t row_offset= 0) const { + if (force_null) + return true; /* The table may have been marked as containing only NULL values for all fields if it is a NULL-complemented row of an OUTER JOIN diff --git a/sql/item.cc b/sql/item.cc index a76152c14e298..ec4ed9ab07f25 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2759,6 +2759,21 @@ void Item_field::set_field(Field *field_par) fixed= 1; if (field->table->s->tmp_table == SYSTEM_TMP_TABLE) any_privileges= 0; + + if (field->is_versioning_disabled() && context && context->select_lex && + context->select_lex->vers_conditions.type != + FOR_SYSTEM_TIME_UNSPECIFIED && + !field->force_null) + { + DBUG_ASSERT(context->select_lex->parent_lex && + context->select_lex->parent_lex->thd); + field->force_null= true; + THD *thd= context->select_lex->parent_lex->thd; + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NON_VERSIONED_FIELD_IN_VERSIONED_QUERY, + ER_THD(thd, ER_NON_VERSIONED_FIELD_IN_VERSIONED_QUERY), + field_name); + } } @@ -5907,6 +5922,8 @@ void Item_field::cleanup() it will be linked correctly next time by name of field and table alias. I.e. we can drop 'field'. */ + if (field) + field->force_null= false; field= 0; item_equal= NULL; null_value= FALSE; diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 5e3a725a895f4..e39677765a214 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7543,3 +7543,6 @@ ER_VERS_TRX_ID_UNSUPPORTED ER_VERS_RANGE_UNITS_MISMATCH eng "Range units mismatch" + +ER_NON_VERSIONED_FIELD_IN_VERSIONED_QUERY + eng "Attempt to read unversioned field '%s' in historical query"