summaryrefslogtreecommitdiff
path: root/sql/item_cmpfunc.h
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2016-09-17 08:24:05 +0400
committerAlexander Barkov <bar@mariadb.org>2017-04-05 15:02:48 +0400
commit30bec863cf710f9135439f410e1c31e4df873fd1 (patch)
tree6f78961390733bfadec431053e9f909eeb88e2b5 /sql/item_cmpfunc.h
parent7e7ba7cb948910e138922d6524cc125f9aa02848 (diff)
downloadmariadb-git-30bec863cf710f9135439f410e1c31e4df873fd1.tar.gz
MDEV-10342 Providing compatibility for basic SQL built-in functions
Adding functions NVL() and NVL2().
Diffstat (limited to 'sql/item_cmpfunc.h')
-rw-r--r--sql/item_cmpfunc.h110
1 files changed, 102 insertions, 8 deletions
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 2af4a32d844..a94105b352d 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -993,6 +993,7 @@ public:
Case abbreviations that aggregate its result field type by two arguments:
IFNULL(arg1, arg2)
IF(switch, arg1, arg2)
+ NVL2(switch, arg1, arg2)
*/
class Item_func_case_abbreviation2 :public Item_func_hybrid_field_type
{
@@ -1003,6 +1004,34 @@ protected:
fix_attributes(items, 2);
}
uint decimal_precision2(Item **args) const;
+
+ void cache_type_info(const Item *source, bool maybe_null_arg)
+ {
+ Type_std_attributes::set(source);
+ set_handler_by_field_type(source->field_type());
+ maybe_null= maybe_null_arg;
+ }
+
+ void fix_length_and_dec2_eliminate_null(Item **items)
+ {
+ // Let IF(cond, expr, NULL) and IF(cond, NULL, expr) inherit type from expr.
+ if (items[0]->type() == NULL_ITEM)
+ {
+ cache_type_info(items[1], true);
+ // If both arguments are NULL, make resulting type BINARY(0).
+ if (items[1]->type() == NULL_ITEM)
+ set_handler_by_field_type(MYSQL_TYPE_STRING);
+ }
+ else if (items[1]->type() == NULL_ITEM)
+ {
+ cache_type_info(items[0], true);
+ }
+ else
+ {
+ fix_length_and_dec2(items);
+ }
+ }
+
public:
Item_func_case_abbreviation2(THD *thd, Item *a, Item *b):
Item_func_hybrid_field_type(thd, a, b) { }
@@ -1040,19 +1069,61 @@ public:
};
-class Item_func_if :public Item_func_case_abbreviation2
+/**
+ Case abbreviations that have a switch argument and
+ two return arguments to choose from. Returns the value
+ of either of the two return arguments depending on the switch argument value.
+
+ IF(switch, arg1, arg2)
+ NVL(switch, arg1, arg2)
+*/
+class Item_func_case_abbreviation2_switch: public Item_func_case_abbreviation2
{
+protected:
+ virtual Item *find_item() const= 0;
+
+public:
+ Item_func_case_abbreviation2_switch(THD *thd, Item *a, Item *b, Item *c)
+ :Item_func_case_abbreviation2(thd, a, b, c)
+ { }
+
+ bool date_op(MYSQL_TIME *ltime, uint fuzzydate)
+ {
+ return get_date_with_conversion_from_item(find_item(), ltime, fuzzydate);
+ }
+ longlong int_op()
+ {
+ return val_int_from_item(find_item());
+ }
+ double real_op()
+ {
+ return val_real_from_item(find_item());
+ }
+ my_decimal *decimal_op(my_decimal *decimal_value)
+ {
+ return val_decimal_from_item(find_item(), decimal_value);
+ }
+ String *str_op(String *str)
+ {
+ return val_str_from_item(find_item(), str);
+ }
+};
+
+
+class Item_func_if :public Item_func_case_abbreviation2_switch
+{
+protected:
+ Item *find_item() const { return args[0]->val_bool() ? args[1] : args[2]; }
+
public:
Item_func_if(THD *thd, Item *a, Item *b, Item *c):
- Item_func_case_abbreviation2(thd, a, b, c)
+ Item_func_case_abbreviation2_switch(thd, a, b, c)
{}
- bool date_op(MYSQL_TIME *ltime, uint fuzzydate);
- longlong int_op();
- double real_op();
- my_decimal *decimal_op(my_decimal *);
- String *str_op(String *);
bool fix_fields(THD *, Item **);
- void fix_length_and_dec();
+ void fix_length_and_dec()
+ {
+ fix_length_and_dec2_eliminate_null(args + 1);
+ }
uint decimal_precision() const
{
return Item_func_case_abbreviation2::decimal_precision2(args + 1);
@@ -1067,6 +1138,29 @@ private:
};
+class Item_func_nvl2 :public Item_func_case_abbreviation2_switch
+{
+protected:
+ Item *find_item() const { return args[0]->is_null() ? args[2] : args[1]; }
+
+public:
+ Item_func_nvl2(THD *thd, Item *a, Item *b, Item *c):
+ Item_func_case_abbreviation2_switch(thd, a, b, c)
+ {}
+ const char *func_name() const { return "nvl2"; }
+ void fix_length_and_dec()
+ {
+ fix_length_and_dec2_eliminate_null(args + 1);
+ }
+ uint decimal_precision() const
+ {
+ return Item_func_case_abbreviation2::decimal_precision2(args + 1);
+ }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_nvl2>(thd, mem_root, this); }
+};
+
+
class Item_func_nullif :public Item_func_hybrid_field_type
{
Arg_comparator cmp;