From 1668efb722d6d2fb483745d23915378167937d1d Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 14 Dec 2017 18:14:21 +0300 Subject: MDEV-14645: AS OF TIMESTAMP is misused as TRX_ID [fixes #396] --- sql/item_func.h | 24 ++++++++++++++++++++++++ sql/item_timefunc.cc | 20 ++++++++++++++++++++ sql/item_timefunc.h | 14 ++++++++++++++ sql/sql_select.cc | 42 ++++++++++++++++++++++++++++++++++++++++++ sql/sql_type.cc | 8 ++++++++ sql/sql_type.h | 3 +++ 6 files changed, 111 insertions(+) (limited to 'sql') diff --git a/sql/item_func.h b/sql/item_func.h index f6640c9b719..4c78edcb1fa 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -988,6 +988,30 @@ public: }; +class Item_longlong_typecast :public Item_int_func +{ +public: + Item_longlong_typecast(THD *thd, Item *a): Item_int_func(thd, a) + { + } + const char *func_name() const { return "cast_as_longlong"; } + const char *cast_type() const { return "longlong"; } + const Type_handler *type_handler() const { return &type_handler_longlong; } + longlong val_int() + { + return args[0]->val_int(); + } + void fix_length_and_dec_generic() {} + void fix_length_and_dec() + { + args[0]->type_handler()->Item_longlong_typecast_fix_length_and_dec(this); + } + bool need_parentheses_in_default() { return true; } + Item *get_copy(THD *thd) + { return get_item_copy(thd, this); } +}; + + class Item_func_additive_op :public Item_num_op { diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index fd170a707c9..4563f4555f5 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2652,6 +2652,26 @@ bool Item_datetime_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) } +void Item_datetime_from_unixtime_typecast::fix_length_and_dec() +{ + Item_datetime_typecast::fix_length_and_dec(); + + switch (args[0]->result_type()) + { + case INT_RESULT: + case REAL_RESULT: + case DECIMAL_RESULT: + { + Item_func_from_unixtime *a= new (thd->mem_root) Item_func_from_unixtime(thd, args[0]); + a->fix_length_and_dec(); + args[0]= a; + break; + } + default:; + } +} + + /** MAKEDATE(a,b) is a date function that creates a date value from a year and day value. diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index adc7b2535a9..878179105be 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -1184,6 +1184,20 @@ public: }; +class Item_datetime_from_unixtime_typecast :public Item_datetime_typecast +{ + THD *thd; +public: + Item_datetime_from_unixtime_typecast(THD *_thd, Item *a, uint dec_arg): + Item_datetime_typecast(_thd, a, dec_arg), thd(_thd) {} + const char *func_name() const { return "cast_as_datetime_from_unixtime"; } + const char *cast_type() const { return "datetime"; } + void fix_length_and_dec(); + Item *get_copy(THD *thd) + { return get_item_copy(thd, this); } +}; + + class Item_func_makedate :public Item_datefunc { bool check_arguments() const diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cd6c7877354..dca4b60dc4d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -912,6 +912,48 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr if (tmp_from_ib || t->versioned_by_sql() || thd->variables.vers_innodb_algorithm_simple) { + if (vers_conditions) + { + if (vers_conditions.start) + { + switch (vers_conditions.unit_start) + { + case UNIT_TIMESTAMP: + { + vers_conditions.start= newx Item_datetime_from_unixtime_typecast( + thd, vers_conditions.start, 6); + break; + } + case UNIT_TRX_ID: + { + vers_conditions.start= newx Item_longlong_typecast( + thd, vers_conditions.start); + break; + } + default:; + } + } + + if (vers_conditions.end) + { + switch (vers_conditions.unit_end) + { + case UNIT_TIMESTAMP: + { + vers_conditions.end= newx Item_datetime_from_unixtime_typecast( + thd, vers_conditions.end, 6); + break; + } + case UNIT_TRX_ID: + { + vers_conditions.end= newx Item_longlong_typecast( + thd, vers_conditions.end); + break; + } + default:; + } + } + } switch (vers_conditions.type) { case FOR_SYSTEM_TIME_UNSPECIFIED: diff --git a/sql/sql_type.cc b/sql/sql_type.cc index b4860176c0c..e1fb9cb51a0 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -4447,6 +4447,14 @@ bool Type_handler:: } +bool Type_handler:: + Item_longlong_typecast_fix_length_and_dec(Item_longlong_typecast *item) const +{ + item->fix_length_and_dec_generic(); + return false; +} + + #ifdef HAVE_SPATIAL bool Type_handler_geometry:: diff --git a/sql/sql_type.h b/sql/sql_type.h index c400420586e..ac95c5a9c88 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -55,6 +55,7 @@ class Item_char_typecast; class Item_time_typecast; class Item_date_typecast; class Item_datetime_typecast; +class Item_longlong_typecast; class Item_func_plus; class Item_func_minus; class Item_func_mul; @@ -983,6 +984,8 @@ public: Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const; virtual bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item) const; + virtual bool + Item_longlong_typecast_fix_length_and_dec(Item_longlong_typecast *item) const; virtual bool Item_func_plus_fix_length_and_dec(Item_func_plus *func) const= 0; -- cgit v1.2.1