diff --git a/mysql-test/suite/versioning/r/optimized_fields.result b/mysql-test/suite/versioning/r/optimized_fields.result index 376eddb41b8..0cd59992ad3 100644 --- a/mysql-test/suite/versioning/r/optimized_fields.result +++ b/mysql-test/suite/versioning/r/optimized_fields.result @@ -1,4 +1,4 @@ -create table t( +create table t ( a int, b int without system versioning ) with system versioning; @@ -36,12 +36,14 @@ a b 3 NULL Warnings: Warning 4075 Attempt to read unversioned field `b` in historical query +Warning 4075 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 4075 Attempt to read unversioned field `b` in historical query +Warning 4075 Attempt to read unversioned field `b` in historical query select * from t group by a having a=2 system_time as of timestamp now(6); a b Warnings: @@ -50,6 +52,7 @@ select * from t group by b having b=2 system_time as of timestamp now(6); a b Warnings: Warning 4075 Attempt to read unversioned field `b` in historical query +Warning 4075 Attempt to read unversioned field `b` in historical query select a from t where b=2 system_time as of timestamp now(6); a Warnings: @@ -68,8 +71,56 @@ select count(*), b from t group by b having b=NULL system_time as of timestamp n count(*) b Warnings: Warning 4075 Attempt to read unversioned field `b` in historical query +Warning 4075 Attempt to read unversioned field `b` in historical query select a, b from t; a b 1 2 3 4 +select count(*) from t for system_time as of timestamp now(6) group by b; +count(*) +2 +Warnings: +Warning 4075 Attempt to read unversioned field `b` in historical query +select * from t for system_time as of timestamp now(6) group by b having b=2; +a b +Warnings: +Warning 4075 Attempt to read unversioned field `b` in historical query +Warning 4075 Attempt to read unversioned field `b` in historical query +select a from t for system_time as of timestamp now(6) where b=2; +a +Warnings: +Warning 4075 Attempt to read unversioned field `b` in historical query +select a from t for system_time as of timestamp now(6) where b=NULL; +a +Warnings: +Warning 4075 Attempt to read unversioned field `b` in historical query +select a from t for system_time as of timestamp now(6) where b is NULL; +a +1 +3 +Warnings: +Warning 4075 Attempt to read unversioned field `b` in historical query +select count(*), b from t for system_time as of timestamp now(6) group by b having b=NULL; +count(*) b +Warnings: +Warning 4075 Attempt to read unversioned field `b` in historical query +Warning 4075 Attempt to read unversioned field `b` in historical query +create or replace table t ( +a int, +b int not null without system versioning +) with system versioning; +insert into t values (1, 2), (3, 4); +select * from t for system_time as of timestamp now(6); +a b +1 NULL +3 NULL +Warnings: +Warning 4075 Attempt to read unversioned field `b` in historical query +select * from t for system_time as of timestamp now(6) where b is NULL; +a b +1 NULL +3 NULL +Warnings: +Warning 4075 Attempt to read unversioned field `b` in historical query +Warning 4075 Attempt to read unversioned field `b` in historical query drop table t; diff --git a/mysql-test/suite/versioning/t/optimized_fields.test b/mysql-test/suite/versioning/t/optimized_fields.test index 321fe6d104d..6c508d04508 100644 --- a/mysql-test/suite/versioning/t/optimized_fields.test +++ b/mysql-test/suite/versioning/t/optimized_fields.test @@ -1,4 +1,4 @@ -create table t( +create table t ( a int, b int without system versioning ) with system versioning; @@ -20,4 +20,21 @@ select a from t where b is NULL system_time as of timestamp now(6); select count(*), b from t group by b having b=NULL system_time as of timestamp now(6); select a, b from t; +select count(*) from t for system_time as of timestamp now(6) group by b; +select * from t for system_time as of timestamp now(6) group by b having b=2; +select a from t for system_time as of timestamp now(6) where b=2; +select a from t for system_time as of timestamp now(6) where b=NULL; +select a from t for system_time as of timestamp now(6) where b is NULL; +select count(*), b from t for system_time as of timestamp now(6) group by b having b=NULL; + +create or replace table t ( + a int, + b int not null without system versioning +) with system versioning; + +insert into t values (1, 2), (3, 4); + +select * from t for system_time as of timestamp now(6); +select * from t for system_time as of timestamp now(6) where b is NULL; + drop table t; diff --git a/sql/field.cc b/sql/field.cc index 3a1fee59937..ac0e59773be 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), force_null(false), part_of_sortkey(0), + part_of_key_not_clustered(0), 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 317ae018066..28d47b337a7 100644 --- a/sql/field.h +++ b/sql/field.h @@ -703,8 +703,6 @@ public: /* 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, ... @@ -1090,8 +1088,6 @@ public: 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 d27ab95aaa4..0df22234f88 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2759,20 +2759,6 @@ void Item_field::set_field(Field *field_par) fixed= 1; if (field->table->s->tmp_table == SYSTEM_TMP_TABLE) any_privileges= 0; - - field->force_null= false; - if (field->flags & VERS_OPTIMIZED_UPDATE_FLAG && context && - ((field->table->pos_in_table_list && - field->table->pos_in_table_list->vers_conditions) || - (context->select_lex && context->select_lex->vers_conditions))) - { - field->force_null= true; - push_warning_printf( - current_thd, Sql_condition::WARN_LEVEL_WARN, - ER_NON_VERSIONED_FIELD_IN_VERSIONED_QUERY, - ER_THD(current_thd, ER_NON_VERSIONED_FIELD_IN_VERSIONED_QUERY), - field_name); - } } @@ -10757,6 +10743,30 @@ bool Item_field::exclusive_dependence_on_grouping_fields_processor(void *arg) return true; } +Item *Item_field::vers_optimized_fields_transformer(THD *thd, uchar *) +{ + if (!field) + return this; + + if (field->flags & VERS_OPTIMIZED_UPDATE_FLAG && context && + ((field->table->pos_in_table_list && + field->table->pos_in_table_list->vers_conditions) || + (context->select_lex && context->select_lex->vers_conditions))) + { + push_warning_printf( + current_thd, Sql_condition::WARN_LEVEL_WARN, + ER_NON_VERSIONED_FIELD_IN_VERSIONED_QUERY, + ER_THD(current_thd, ER_NON_VERSIONED_FIELD_IN_VERSIONED_QUERY), + field_name); + + Item *null_item= new (thd->mem_root) Item_null(thd); + if (null_item) + return null_item; + } + + return this; +} + void Item::register_in(THD *thd) { next= thd->free_list; diff --git a/sql/item.h b/sql/item.h index eb695726472..ab2c9dd65a9 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1655,6 +1655,8 @@ public: virtual Item_field *field_for_view_update() { return 0; } + virtual Item *vers_optimized_fields_transformer(THD *thd, uchar *) + { return this; } virtual Item *neg_transformer(THD *thd) { return NULL; } virtual Item *update_value_transformer(THD *thd, uchar *select_arg) { return this; } @@ -2750,6 +2752,7 @@ public: uint32 max_display_length() const { return field->max_display_length(); } Item_field *field_for_view_update() { return this; } int fix_outer_field(THD *thd, Field **field, Item **reference); + virtual Item *vers_optimized_fields_transformer(THD *thd, uchar *); virtual Item *update_value_transformer(THD *thd, uchar *select_arg); Item *derived_field_transformer_for_having(THD *thd, uchar *arg); Item *derived_field_transformer_for_where(THD *thd, uchar *arg); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2ae574398fc..a1fc9f16b21 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1380,6 +1380,46 @@ JOIN::prepare(TABLE_LIST *tables_init, if (!procedure && result && result->prepare(fields_list, unit_arg)) goto err; /* purecov: inspected */ + if (!thd->stmt_arena->is_stmt_prepare()) + { + bool have_versioned_tables= false; + for (TABLE_LIST *table= tables_list; table; table= table->next_local) + { + if (table->table && table->table->versioned()) + { + have_versioned_tables= true; + break; + } + } + + if (have_versioned_tables) + { + Item_transformer transformer= &Item::vers_optimized_fields_transformer; + + if (conds) + { + conds= conds->transform(thd, transformer, NULL); + } + + for (ORDER *ord= order; ord; ord= ord->next) + { + ord->item_ptr= (*ord->item)->transform(thd, transformer, NULL); + ord->item= &ord->item_ptr; + } + + for (ORDER *ord= group_list; ord; ord= ord->next) + { + ord->item_ptr= (*ord->item)->transform(thd, transformer, NULL); + ord->item= &ord->item_ptr; + } + + if (having) + { + having= having->transform(thd, transformer, NULL); + } + } + } + unit= unit_arg; if (prepare_stage2()) goto err; @@ -3827,6 +3867,16 @@ void JOIN::exec_inner() result->send_result_set_metadata( procedure ? procedure_fields_list : *fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); + + { + List_iterator it(*columns_list); + while (Item *item= it++) + { + Item_transformer transformer= &Item::vers_optimized_fields_transformer; + it.replace(item->transform(thd, transformer, NULL)); + } + } + error= do_select(this, procedure); /* Accumulate the counts from all join iterations of all join parts. */ thd->inc_examined_row_count(join_examined_rows);