summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2017-12-14 18:14:21 +0300
committerAleksey Midenkov <midenok@gmail.com>2017-12-14 18:14:21 +0300
commit1668efb722d6d2fb483745d23915378167937d1d (patch)
treea2cc6994a50055784976b5069e8e6b6f23dd4f51 /sql
parent765569602d4211a5daa0f175faa78a4922819bc4 (diff)
downloadmariadb-git-1668efb722d6d2fb483745d23915378167937d1d.tar.gz
MDEV-14645: AS OF TIMESTAMP is misused as TRX_ID [fixes #396]
Diffstat (limited to 'sql')
-rw-r--r--sql/item_func.h24
-rw-r--r--sql/item_timefunc.cc20
-rw-r--r--sql/item_timefunc.h14
-rw-r--r--sql/sql_select.cc42
-rw-r--r--sql/sql_type.cc8
-rw-r--r--sql/sql_type.h3
6 files changed, 111 insertions, 0 deletions
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<Item_longlong_typecast>(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<Item_datetime_from_unixtime_typecast>(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;