summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2017-09-30 11:17:19 +0400
committerAlexander Barkov <bar@mariadb.org>2017-09-30 11:17:19 +0400
commitaa582dedcbd22182e06355b94d1de4fc62f71910 (patch)
tree647fdbdaba6cc1baad1ea133fb7590cb30904d0d /sql
parentca38b93e354baa5bbcaea00543dc1a99940072e4 (diff)
downloadmariadb-git-aa582dedcbd22182e06355b94d1de4fc62f71910.tar.gz
MDEV-13966 Parameter data type control for Item_temporal_func
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc22
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_func.cc13
-rw-r--r--sql/item_func.h1
-rw-r--r--sql/item_timefunc.h22
-rw-r--r--sql/sql_type.h6
6 files changed, 66 insertions, 0 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 840ab12a7ce..c62ca8029d3 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1069,6 +1069,17 @@ bool Item::check_type_can_return_int(const char *opname) const
}
+bool Item::check_type_can_return_decimal(const char *opname) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler->can_return_decimal())
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ handler->name().ptr(), opname);
+ return true;
+}
+
+
bool Item::check_type_can_return_real(const char *opname) const
{
const Type_handler *handler= type_handler();
@@ -1091,6 +1102,17 @@ bool Item::check_type_can_return_date(const char *opname) const
}
+bool Item::check_type_can_return_time(const char *opname) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler->can_return_time())
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ handler->name().ptr(), opname);
+ return true;
+}
+
+
bool Item::check_type_can_return_str_ascii(const char *opname) const
{
const Type_handler *handler= type_handler();
diff --git a/sql/item.h b/sql/item.h
index 6d918999e73..7662d358b42 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1710,9 +1710,11 @@ public:
bool check_type_or_binary(const char *opname, const Type_handler *handler) const;
bool check_type_general_purpose_string(const char *opname) const;
bool check_type_can_return_int(const char *opname) const;
+ bool check_type_can_return_decimal(const char *opname) const;
bool check_type_can_return_real(const char *opname) const;
bool check_type_can_return_str_ascii(const char *opname) const;
bool check_type_can_return_date(const char *opname) const;
+ bool check_type_can_return_time(const char *opname) const;
// It is not row => null inside is impossible
virtual bool null_inside() { return 0; }
// used in row subselects to get value of elements
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 5157c01348e..7db5e3bccc7 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -244,6 +244,19 @@ bool Item_func::check_argument_types_can_return_date(uint start,
}
+bool Item_func::check_argument_types_can_return_time(uint start,
+ uint end) const
+{
+ for (uint i= start; i < end ; i++)
+ {
+ DBUG_ASSERT(i < arg_count);
+ if (args[i]->check_type_can_return_time(func_name()))
+ return true;
+ }
+ return false;
+}
+
+
bool Item_func::check_argument_types_scalar(uint start, uint end) const
{
for (uint i= start; i < end; i++)
diff --git a/sql/item_func.h b/sql/item_func.h
index 6d59cae616e..c061c713de5 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -50,6 +50,7 @@ protected:
bool check_argument_types_can_return_real(uint start, uint end) const;
bool check_argument_types_can_return_str_ascii(uint start, uint end) const;
bool check_argument_types_can_return_date(uint start, uint end) const;
+ bool check_argument_types_can_return_time(uint start, uint end) const;
public:
table_map not_null_tables_cache;
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index cd67e900efe..6bbc37a78e2 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -782,6 +782,8 @@ public:
class Item_func_from_days :public Item_datefunc
{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_int(func_name()); }
public:
Item_func_from_days(THD *thd, Item *a): Item_datefunc(thd, a) {}
const char *func_name() const { return "from_days"; }
@@ -838,6 +840,8 @@ public:
class Item_func_from_unixtime :public Item_datetimefunc
{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_decimal(func_name()); }
Time_zone *tz;
public:
Item_func_from_unixtime(THD *thd, Item *a): Item_datetimefunc(thd, a) {}
@@ -865,6 +869,11 @@ class Time_zone;
*/
class Item_func_convert_tz :public Item_datetimefunc
{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_can_return_date(func_name()) ||
+ check_argument_types_can_return_str_ascii(1, arg_count);
+ }
/*
If time zone parameters are constants we are caching objects that
represent them (we use separate from_tz_cached/to_tz_cached members
@@ -891,6 +900,8 @@ class Item_func_convert_tz :public Item_datetimefunc
class Item_func_sec_to_time :public Item_timefunc
{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_decimal(func_name()); }
public:
Item_func_sec_to_time(THD *thd, Item *item): Item_timefunc(thd, item) {}
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
@@ -1130,6 +1141,8 @@ public:
class Item_func_makedate :public Item_datefunc
{
+ bool check_arguments() const
+ { return check_argument_types_can_return_int(0, arg_count); }
public:
Item_func_makedate(THD *thd, Item *a, Item *b):
Item_datefunc(thd, a, b) {}
@@ -1159,6 +1172,8 @@ public:
class Item_func_timediff :public Item_timefunc
{
+ bool check_arguments() const
+ { return check_argument_types_can_return_time(0, arg_count); }
public:
Item_func_timediff(THD *thd, Item *a, Item *b): Item_timefunc(thd, a, b) {}
const char *func_name() const { return "timediff"; }
@@ -1175,6 +1190,11 @@ public:
class Item_func_maketime :public Item_timefunc
{
+ bool check_arguments() const
+ {
+ return check_argument_types_can_return_int(0, 2) ||
+ args[2]->check_type_can_return_decimal(func_name());
+ }
public:
Item_func_maketime(THD *thd, Item *a, Item *b, Item *c):
Item_timefunc(thd, a, b, c)
@@ -1283,6 +1303,8 @@ public:
class Item_func_last_day :public Item_datefunc
{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_date(func_name()); }
public:
Item_func_last_day(THD *thd, Item *a): Item_datefunc(thd, a) {}
const char *func_name() const { return "last_day"; }
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 63351cb26c3..f570e91f882 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -704,9 +704,11 @@ public:
}
virtual bool is_scalar_type() const { return true; }
virtual bool can_return_int() const { return true; }
+ virtual bool can_return_decimal() const { return true; }
virtual bool can_return_real() const { return true; }
virtual bool can_return_str_ascii() const { return true; }
virtual bool can_return_date() const { return true; }
+ virtual bool can_return_time() const { return true; }
virtual bool is_general_purpose_string_type() const { return false; }
virtual uint Item_time_precision(Item *item) const;
virtual uint Item_datetime_precision(Item *item) const;
@@ -1003,9 +1005,11 @@ public:
const Name name() const { return m_name_row; }
bool is_scalar_type() const { return false; }
bool can_return_int() const { return false; }
+ bool can_return_decimal() const { return false; }
bool can_return_real() const { return false; }
bool can_return_str_ascii() const { return false; }
bool can_return_date() const { return false; }
+ bool can_return_time() const { return false; }
enum_field_types field_type() const
{
DBUG_ASSERT(0);
@@ -2677,9 +2681,11 @@ public:
TABLE *table) const;
bool can_return_int() const { return false; }
+ bool can_return_decimal() const { return false; }
bool can_return_real() const { return false; }
bool can_return_str_ascii() const { return false; }
bool can_return_date() const { return false; }
+ bool can_return_time() const { return false; }
bool is_traditional_type() const
{
return false;