Commit 884bd1d6 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-13863 sql_mode=ORACLE: DECODE does not treat two NULLs as equivalent

parent c39a7446
......@@ -28,6 +28,150 @@ EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11','def');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select case 12 when 10 then 'x10' when 11 then 'x11' else 'def' end AS "DECODE(12,10,'x10',11,'x11','def')"
Note 1003 select decode_oracle(12,10,'x10',11,'x11','def') AS "DECODE(12,10,'x10',11,'x11','def')"
CREATE TABLE decode (decode int);
DROP TABLE decode;
#
# MDEV-13863 sql_mode=ORACLE: DECODE does not treat two NULLs as equivalent
#
SELECT DECODE(10);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
SELECT DECODE(10,10);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
SELECT DECODE_ORACLE(10);
ERROR 42000: Incorrect parameter count in the call to native function 'DECODE_ORACLE'
SELECT DECODE_ORACLE(10,10);
ERROR 42000: Incorrect parameter count in the call to native function 'DECODE_ORACLE'
EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select decode_oracle(12,10,'x10',11,'x11') AS "DECODE(12,10,'x10',11,'x11')"
EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11','def');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select decode_oracle(12,10,'x10',11,'x11','def') AS "DECODE(12,10,'x10',11,'x11','def')"
EXPLAIN EXTENDED SELECT DECODE_ORACLE(12,10,'x10',11,'x11');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select decode_oracle(12,10,'x10',11,'x11') AS "DECODE_ORACLE(12,10,'x10',11,'x11')"
EXPLAIN EXTENDED SELECT DECODE_ORACLE(12,10,'x10',11,'x11','def');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select decode_oracle(12,10,'x10',11,'x11','def') AS "DECODE_ORACLE(12,10,'x10',11,'x11','def')"
CREATE TABLE t1 (a INT);
CREATE VIEW v1 AS
SELECT
DECODE(a,1,'x1',NULL,'xNULL') AS d1,
DECODE(a,1,'x1',NULL,'xNULL','xELSE') AS d2,
DECODE_ORACLE(a,1,'x1',NULL,'xNULL') AS d3,
DECODE_ORACLE(a,1,'x1',NULL,'xNULL','xELSE') AS d4
FROM t1;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE VIEW "v1" AS select decode_oracle("t1"."a",1,'x1',NULL,'xNULL') AS "d1",decode_oracle("t1"."a",1,'x1',NULL,'xNULL','xELSE') AS "d2",decode_oracle("t1"."a",1,'x1',NULL,'xNULL') AS "d3",decode_oracle("t1"."a",1,'x1',NULL,'xNULL','xELSE') AS "d4" from "t1" latin1 latin1_swedish_ci
DROP VIEW v1;
DROP TABLE t1;
SELECT DECODE(TIME'10:20:31','10:20:31','then1','10:20:32','then2','def');
DECODE(TIME'10:20:31','10:20:31','then1','10:20:32','then2','def')
then1
SELECT DECODE(TIME'10:20:32','10:20:31','then1','10:20:32','then2','def');
DECODE(TIME'10:20:32','10:20:31','then1','10:20:32','then2','def')
then2
SELECT DECODE(TIME'10:20:33','10:20:31','then1',NULL,'then2NULL','10:20:33','then3','def');
DECODE(TIME'10:20:33','10:20:31','then1',NULL,'then2NULL','10:20:33','then3','def')
then3
SELECT DECODE(NULL,TIME'10:20:31','then1',NULL,'then2NULL','10:20:33','then3','def');
DECODE(NULL,TIME'10:20:31','then1',NULL,'then2NULL','10:20:33','then3','def')
then2NULL
SELECT DECODE(TIMESTAMP'2001-01-01 10:20:31','2001-01-01 10:20:31','then1','2001-01-01 10:20:32','then2','def');
DECODE(TIMESTAMP'2001-01-01 10:20:31','2001-01-01 10:20:31','then1','2001-01-01 10:20:32','then2','def')
then1
SELECT DECODE(TIMESTAMP'2001-01-01 10:20:32','2001-01-01 10:20:31','then1','2001-01-01 10:20:32','then2','def');
DECODE(TIMESTAMP'2001-01-01 10:20:32','2001-01-01 10:20:31','then1','2001-01-01 10:20:32','then2','def')
then2
SELECT DECODE(TIMESTAMP'2001-01-01 10:20:33','2001-01-01 10:20:31','then1',NULL,'then2NULL','2001-01-01 10:20:33','then3','def');
DECODE(TIMESTAMP'2001-01-01 10:20:33','2001-01-01 10:20:31','then1',NULL,'then2NULL','2001-01-01 10:20:33','then3','def')
then3
SELECT DECODE(NULL,TIMESTAMP'2001-01-01 10:20:31','then1',NULL,'then2NULL','2001-01-01 10:20:33','then3','def');
DECODE(NULL,TIMESTAMP'2001-01-01 10:20:31','then1',NULL,'then2NULL','2001-01-01 10:20:33','then3','def')
then2NULL
SELECT DECODE('w1','w1','then1','w2','then2','def');
DECODE('w1','w1','then1','w2','then2','def')
then1
SELECT DECODE('w2','w1','then1','w2','then2','def');
DECODE('w2','w1','then1','w2','then2','def')
then2
SELECT DECODE('w3','w1','then1',NULL,'then2NULL','w3','then3','def');
DECODE('w3','w1','then1',NULL,'then2NULL','w3','then3','def')
then3
SELECT DECODE(NULL,'w1','then1',NULL,'then2NULL','w3','then3','def');
DECODE(NULL,'w1','then1',NULL,'then2NULL','w3','then3','def')
then2NULL
SELECT DECODE(1,1,'then1',2,'then2','def');
DECODE(1,1,'then1',2,'then2','def')
then1
SELECT DECODE(2,1,'then1',2,'then2','def');
DECODE(2,1,'then1',2,'then2','def')
then2
SELECT DECODE(3,1,'then1',NULL,'then2NULL',3,'then3','def');
DECODE(3,1,'then1',NULL,'then2NULL',3,'then3','def')
then3
SELECT DECODE(NULL,1,'then1',NULL,'then2NULL',3,'then3','def');
DECODE(NULL,1,'then1',NULL,'then2NULL',3,'then3','def')
then2NULL
SELECT DECODE(CAST(NULL AS SIGNED),1,'then1',NULL,'then2NULL',3,'then3','def');
DECODE(CAST(NULL AS SIGNED),1,'then1',NULL,'then2NULL',3,'then3','def')
then2NULL
SELECT DECODE(1.0,1.0,'then1',2.0,'then2','def');
DECODE(1.0,1.0,'then1',2.0,'then2','def')
then1
SELECT DECODE(2.0,1.0,'then1',2.0,'then2','def');
DECODE(2.0,1.0,'then1',2.0,'then2','def')
then2
SELECT DECODE(3.0,1.0,'then1',NULL,'then2NULL',3.0,'then3','def');
DECODE(3.0,1.0,'then1',NULL,'then2NULL',3.0,'then3','def')
then3
SELECT DECODE(NULL,1.0,'then1',NULL,'then2NULL',3.0,'then3','def');
DECODE(NULL,1.0,'then1',NULL,'then2NULL',3.0,'then3','def')
then2NULL
SELECT DECODE(CAST(NULL AS DECIMAL),1.0,'then1',NULL,'then2NULL',3.0,'then3','def');
DECODE(CAST(NULL AS DECIMAL),1.0,'then1',NULL,'then2NULL',3.0,'then3','def')
then2NULL
SELECT DECODE(1e0,1e0,'then1',2e0,'then2','def');
DECODE(1e0,1e0,'then1',2e0,'then2','def')
then1
SELECT DECODE(2e0,1e0,'then1',2e0,'then2','def');
DECODE(2e0,1e0,'then1',2e0,'then2','def')
then2
SELECT DECODE(3e0,1e0,'then1',NULL,'then2NULL',3e0,'then3','def');
DECODE(3e0,1e0,'then1',NULL,'then2NULL',3e0,'then3','def')
then3
SELECT DECODE(NULL,1e0,'then1',NULL,'then2NULL',3e0,'then3','def');
DECODE(NULL,1e0,'then1',NULL,'then2NULL',3e0,'then3','def')
then2NULL
SELECT DECODE(CAST(NULL AS DOUBLE),1e0,'then1',NULL,'then2NULL',3e0,'then3','def');
DECODE(CAST(NULL AS DOUBLE),1e0,'then1',NULL,'then2NULL',3e0,'then3','def')
then2NULL
SELECT DECODE(NULL,NULL,1,2) FROM DUAL;
DECODE(NULL,NULL,1,2)
1
SELECT DECODE(NULL,10,10,NULL,1,2) FROM DUAL;
DECODE(NULL,10,10,NULL,1,2)
1
SELECT DECODE_ORACLE(NULL,NULL,1,2) FROM DUAL;
DECODE_ORACLE(NULL,NULL,1,2)
1
SELECT DECODE_ORACLE(NULL,10,10,NULL,1,2) FROM DUAL;
DECODE_ORACLE(NULL,10,10,NULL,1,2)
1
CREATE OR REPLACE TABLE t1 (a VARCHAR(10) DEFAULT NULL);
INSERT INTO t1 VALUES (NULL),(1);
SELECT a, DECODE(a,NULL,1,2) FROM t1;
a DECODE(a,NULL,1,2)
NULL 1
1 2
DROP TABLE t1;
......@@ -19,3 +19,80 @@ EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11','def');
CREATE TABLE decode (decode int);
DROP TABLE decode;
--echo #
--echo # MDEV-13863 sql_mode=ORACLE: DECODE does not treat two NULLs as equivalent
--echo #
--error ER_PARSE_ERROR
SELECT DECODE(10);
--error ER_PARSE_ERROR
SELECT DECODE(10,10);
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
SELECT DECODE_ORACLE(10);
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
SELECT DECODE_ORACLE(10,10);
EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11');
EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11','def');
EXPLAIN EXTENDED SELECT DECODE_ORACLE(12,10,'x10',11,'x11');
EXPLAIN EXTENDED SELECT DECODE_ORACLE(12,10,'x10',11,'x11','def');
CREATE TABLE t1 (a INT);
CREATE VIEW v1 AS
SELECT
DECODE(a,1,'x1',NULL,'xNULL') AS d1,
DECODE(a,1,'x1',NULL,'xNULL','xELSE') AS d2,
DECODE_ORACLE(a,1,'x1',NULL,'xNULL') AS d3,
DECODE_ORACLE(a,1,'x1',NULL,'xNULL','xELSE') AS d4
FROM t1;
SHOW CREATE VIEW v1;
DROP VIEW v1;
DROP TABLE t1;
SELECT DECODE(TIME'10:20:31','10:20:31','then1','10:20:32','then2','def');
SELECT DECODE(TIME'10:20:32','10:20:31','then1','10:20:32','then2','def');
SELECT DECODE(TIME'10:20:33','10:20:31','then1',NULL,'then2NULL','10:20:33','then3','def');
SELECT DECODE(NULL,TIME'10:20:31','then1',NULL,'then2NULL','10:20:33','then3','def');
SELECT DECODE(TIMESTAMP'2001-01-01 10:20:31','2001-01-01 10:20:31','then1','2001-01-01 10:20:32','then2','def');
SELECT DECODE(TIMESTAMP'2001-01-01 10:20:32','2001-01-01 10:20:31','then1','2001-01-01 10:20:32','then2','def');
SELECT DECODE(TIMESTAMP'2001-01-01 10:20:33','2001-01-01 10:20:31','then1',NULL,'then2NULL','2001-01-01 10:20:33','then3','def');
SELECT DECODE(NULL,TIMESTAMP'2001-01-01 10:20:31','then1',NULL,'then2NULL','2001-01-01 10:20:33','then3','def');
SELECT DECODE('w1','w1','then1','w2','then2','def');
SELECT DECODE('w2','w1','then1','w2','then2','def');
SELECT DECODE('w3','w1','then1',NULL,'then2NULL','w3','then3','def');
SELECT DECODE(NULL,'w1','then1',NULL,'then2NULL','w3','then3','def');
SELECT DECODE(1,1,'then1',2,'then2','def');
SELECT DECODE(2,1,'then1',2,'then2','def');
SELECT DECODE(3,1,'then1',NULL,'then2NULL',3,'then3','def');
SELECT DECODE(NULL,1,'then1',NULL,'then2NULL',3,'then3','def');
SELECT DECODE(CAST(NULL AS SIGNED),1,'then1',NULL,'then2NULL',3,'then3','def');
SELECT DECODE(1.0,1.0,'then1',2.0,'then2','def');
SELECT DECODE(2.0,1.0,'then1',2.0,'then2','def');
SELECT DECODE(3.0,1.0,'then1',NULL,'then2NULL',3.0,'then3','def');
SELECT DECODE(NULL,1.0,'then1',NULL,'then2NULL',3.0,'then3','def');
SELECT DECODE(CAST(NULL AS DECIMAL),1.0,'then1',NULL,'then2NULL',3.0,'then3','def');
SELECT DECODE(1e0,1e0,'then1',2e0,'then2','def');
SELECT DECODE(2e0,1e0,'then1',2e0,'then2','def');
SELECT DECODE(3e0,1e0,'then1',NULL,'then2NULL',3e0,'then3','def');
SELECT DECODE(NULL,1e0,'then1',NULL,'then2NULL',3e0,'then3','def');
SELECT DECODE(CAST(NULL AS DOUBLE),1e0,'then1',NULL,'then2NULL',3e0,'then3','def');
SELECT DECODE(NULL,NULL,1,2) FROM DUAL;
SELECT DECODE(NULL,10,10,NULL,1,2) FROM DUAL;
SELECT DECODE_ORACLE(NULL,NULL,1,2) FROM DUAL;
SELECT DECODE_ORACLE(NULL,10,10,NULL,1,2) FROM DUAL;
CREATE OR REPLACE TABLE t1 (a VARCHAR(10) DEFAULT NULL);
INSERT INTO t1 VALUES (NULL),(1);
SELECT a, DECODE(a,NULL,1,2) FROM t1;
DROP TABLE t1;
......@@ -56,8 +56,23 @@ struct st_value
C_MODE_END
class Value: public st_value
{
public:
bool is_null() const { return m_type == DYN_COL_NULL; }
bool is_longlong() const
{
return m_type == DYN_COL_UINT || m_type == DYN_COL_INT;
}
bool is_double() const { return m_type == DYN_COL_DOUBLE; }
bool is_temporal() const { return m_type == DYN_COL_DATETIME; }
bool is_string() const { return m_type == DYN_COL_STRING; }
bool is_decimal() const { return m_type == DYN_COL_DECIMAL; }
};
template<size_t buffer_size>
class ValueBuffer: public st_value
class ValueBuffer: public Value
{
char buffer[buffer_size];
void reset_buffer()
......
......@@ -2859,6 +2859,16 @@ Item *Item_func_case_simple::find_item()
}
Item *Item_func_decode_oracle::find_item()
{
uint idx;
if (!Predicant_to_list_comparator::cmp_nulls_equal(this, &idx))
return args[idx + 1];
Item **pos= Item_func_decode_oracle::else_expr_addr();
return pos ? pos[0] : 0;
}
String *Item_func_case::str_op(String *str)
{
DBUG_ASSERT(fixed == 1);
......@@ -2988,7 +2998,8 @@ static void change_item_tree_if_needed(THD *thd,
bool Item_func_case_simple::prepare_predicant_and_values(THD *thd,
uint *found_types)
uint *found_types,
bool nulls_equal)
{
bool have_null= false;
uint type_cnt;
......@@ -2997,7 +3008,9 @@ bool Item_func_case_simple::prepare_predicant_and_values(THD *thd,
add_predicant(this, 0);
for (uint i= 0 ; i < ncases; i++)
{
if (add_value_skip_null("case..when", this, i * 2 + 1, &have_null))
if (nulls_equal ?
add_value("case..when", this, i * 2 + 1) :
add_value_skip_null("case..when", this, i * 2 + 1, &have_null))
return true;
}
all_values_added(&tmp, &type_cnt, &m_found_types);
......@@ -3021,7 +3034,16 @@ void Item_func_case_simple::fix_length_and_dec()
THD *thd= current_thd;
Item **else_ptr= Item_func_case_simple::else_expr_addr();
if (!aggregate_then_and_else_arguments(thd, &args[2], when_count(), else_ptr))
aggregate_switch_and_when_arguments(thd);
aggregate_switch_and_when_arguments(thd, false);
}
void Item_func_decode_oracle::fix_length_and_dec()
{
THD *thd= current_thd;
Item **else_ptr= Item_func_decode_oracle::else_expr_addr();
if (!aggregate_then_and_else_arguments(thd, &args[2], when_count(), else_ptr))
aggregate_switch_and_when_arguments(thd, true);
}
......@@ -3072,13 +3094,14 @@ bool Item_func_case::aggregate_then_and_else_arguments(THD *thd,
Aggregate the predicant expression and all WHEN expression types
and collations when string comparison
*/
bool Item_func_case_simple::aggregate_switch_and_when_arguments(THD *thd)
bool Item_func_case_simple::aggregate_switch_and_when_arguments(THD *thd,
bool nulls_eq)
{
Item **agg= arg_buffer;
uint nagg;
uint ncases= when_count();
m_found_types= 0;
if (prepare_predicant_and_values(thd, &m_found_types))
if (prepare_predicant_and_values(thd, &m_found_types, nulls_eq))
{
/*
If Predicant_to_list_comparator() fails to prepare components,
......@@ -3962,6 +3985,14 @@ void cmp_item_decimal::store_value(Item *item)
}
int cmp_item_decimal::cmp_not_null(const Value *val)
{
DBUG_ASSERT(!val->is_null());
DBUG_ASSERT(val->is_decimal());
return my_decimal_cmp(&value, &val->m_decimal);
}
int cmp_item_decimal::cmp(Item *arg)
{
my_decimal tmp_buf, *tmp= arg->val_decimal(&tmp_buf);
......@@ -3993,6 +4024,14 @@ void cmp_item_temporal::store_value_internal(Item *item,
}
int cmp_item_datetime::cmp_not_null(const Value *val)
{
DBUG_ASSERT(!val->is_null());
DBUG_ASSERT(val->is_temporal());
return value != pack_time(&val->value.m_time);
}
int cmp_item_datetime::cmp(Item *arg)
{
const bool rc= value != arg->val_datetime_packed();
......@@ -4000,6 +4039,14 @@ int cmp_item_datetime::cmp(Item *arg)
}
int cmp_item_time::cmp_not_null(const Value *val)
{
DBUG_ASSERT(!val->is_null());
DBUG_ASSERT(val->is_temporal());
return value != pack_time(&val->value.m_time);
}
int cmp_item_time::cmp(Item *arg)
{
const bool rc= value != arg->val_time_packed();
......
......@@ -1475,6 +1475,7 @@ class cmp_item :public Sql_alloc
"stored argument's value <> item's value"
*/
virtual int cmp(Item *item)= 0;
virtual int cmp_not_null(const Value *value)= 0;
// for optimized IN with row
virtual int compare(cmp_item *item)= 0;
virtual cmp_item *make_same()= 0;
......@@ -1519,6 +1520,12 @@ class cmp_item_sort_string :public cmp_item_string
value_res= item->val_str(&value);
m_null_value= item->null_value;
}
int cmp_not_null(const Value *val)
{
DBUG_ASSERT(!val->is_null());
DBUG_ASSERT(val->is_string());
return sortcmp(value_res, &val->m_string, cmp_charset) != 0;
}
int cmp(Item *arg)
{
char buff[STRING_BUFFER_USUAL_SIZE];
......@@ -1555,6 +1562,12 @@ class cmp_item_int : public cmp_item_scalar
value= item->val_int();
m_null_value= item->null_value;
}
int cmp_not_null(const Value *val)
{
DBUG_ASSERT(!val->is_null());
DBUG_ASSERT(val->is_longlong());
return value != val->value.m_longlong;
}
int cmp(Item *arg)
{
const bool rc= value != arg->val_int();
......@@ -1599,6 +1612,7 @@ class cmp_item_datetime: public cmp_item_temporal
{
store_value_internal(item, MYSQL_TYPE_DATETIME);
}
int cmp_not_null(const Value *val);
int cmp(Item *arg);
cmp_item *make_same();
};
......@@ -1614,6 +1628,7 @@ class cmp_item_time: public cmp_item_temporal
{
store_value_internal(item, MYSQL_TYPE_TIME);
}
int cmp_not_null(const Value *val);
int cmp(Item *arg);
cmp_item *make_same();
};
......@@ -1628,6 +1643,12 @@ class cmp_item_real : public cmp_item_scalar
value= item->val_real();
m_null_value= item->null_value;
}
int cmp_not_null(const Value *val)
{
DBUG_ASSERT(!val->is_null());
DBUG_ASSERT(val->is_double());
return value != val->value.m_double;
}
int cmp(Item *arg)
{
const bool rc= value != arg->val_real();
......@@ -1649,6 +1670,7 @@ class cmp_item_decimal : public cmp_item_scalar
cmp_item_decimal() {} /* Remove gcc warning */
void store_value(Item *item);
int cmp(Item *arg);
int cmp_not_null(const Value *val);
int compare(cmp_item *c);
cmp_item *make_same();
};
......@@ -1671,6 +1693,11 @@ class cmp_item_sort_string_in_static :public cmp_item_string
value_res= item->val_str(&value);
m_null_value= item->null_value;
}
int cmp_not_null(const Value *val)
{
DBUG_ASSERT(false);
return TRUE;
}
int cmp(Item *item)
{
// Should never be called
......@@ -1837,7 +1864,24 @@ class Predicant_to_list_comparator
return UNKNOWN;
return in_item->cmp(args->arguments()[m_comparators[i].m_arg_index]);
}
int cmp_args_nulls_equal(Item_args *args, uint i)
{
Predicant_to_value_comparator *cmp=
&m_comparators[m_comparators[i].m_handler_index];
cmp_item *in_item= cmp->m_cmp_item;
DBUG_ASSERT(in_item);
Item *predicant= args->arguments()[m_predicant_index];
Item *arg= args->arguments()[m_comparators[i].m_arg_index];
ValueBuffer<MAX_FIELD_WIDTH> val;
if (m_comparators[i].m_handler_index == i)
in_item->store_value(predicant);
m_comparators[i].m_handler->Item_save_in_value(arg, &val);
if (predicant->null_value && val.is_null())
return FALSE; // Two nulls are equal
if (predicant->null_value || val.is_null())
return UNKNOWN;
return in_item->cmp_not_null(&val);
}
/**
Predicant_to_value_comparator - a comparator for one pair (pred,valueN).
See comments above.
......@@ -2009,7 +2053,22 @@ class Predicant_to_list_comparator
}
return true; // Not found
}
/*
Same as above, but treats two NULLs as equal, e.g. as in DECODE_ORACLE().
*/
bool cmp_nulls_equal(Item_args *args, uint *idx)
{
for (uint i= 0 ; i < m_comparator_count ; i++)
{
DBUG_ASSERT(m_comparators[i].m_handler != NULL);
if (cmp_args_nulls_equal(args, i) == FALSE)
{
*idx= m_comparators[i].m_arg_index;
return false; // Found a matching value
}
}
return true; // Not found
}
};
......@@ -2103,12 +2162,14 @@ class Item_func_case_searched: public Item_func_case
class Item_func_case_simple: public Item_func_case,
public Predicant_to_list_comparator
{
protected:
uint m_found_types;
uint when_count() const { return (arg_count - 1) / 2; }
bool with_else() const { return arg_count % 2 == 0; }
Item **else_expr_addr() const { return with_else() ? &args[arg_count - 1] : 0; }
bool aggregate_switch_and_when_arguments(THD *thd);
bool prepare_predicant_and_values(THD *thd, uint *found_types);
bool aggregate_switch_and_when_arguments(THD *thd, bool nulls_equal);
bool prepare_predicant_and_values(THD *thd, uint *found_types,
bool nulls_equal);
public:
Item_func_case_simple(THD *thd, List<Item> &list)
:Item_func_case(thd, list),
......@@ -2142,6 +2203,22 @@ class Item_func_case_simple: public Item_func_case,
};
class Item_func_decode_oracle: public Item_func_case_simple
{
public:
Item_func_decode_oracle(THD *thd, List<Item> &list)
:Item_func_case_simple(thd, list)
{ }
const char *func_name() const { return "decode_oracle"; }
void print(String *str, enum_query_type query_type)
{ Item_func::print(str, query_type); }
void fix_length_and_dec();
Item *find_item();
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_decode_oracle>(thd, mem_root, this); }
};
/*
The Item_func_in class implements
in_expr IN (<in value list>)
......@@ -2321,6 +2398,11 @@ class cmp_item_row :public cmp_item
bool alloc_comparators(THD *thd, uint n);
bool prepare_comparators(THD *, Item **args, uint arg_count);
int cmp(Item *arg);
int cmp_not_null(const Value *val)
{
DBUG_ASSERT(false);
return TRUE;
}
int compare(cmp_item *arg);
cmp_item *make_same();
void store_value_by_template(THD *thd, cmp_item *tmpl, Item *);
......
......@@ -623,6 +623,19 @@ class Create_func_decode_histogram : public Create_func_arg2
};
class Create_func_decode_oracle : public Create_native_func
{
public:
virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_decode_oracle s_singleton;
protected:
Create_func_decode_oracle() {}
virtual ~Create_func_decode_oracle() {}
};
class Create_func_concat_ws : public Create_native_func
{
public:
......@@ -3894,6 +3907,21 @@ Create_func_decode_histogram::create_2_arg(THD *thd, Item *arg1, Item *arg2)
return new (thd->mem_root) Item_func_decode_histogram(thd, arg1, arg2);
}
Create_func_decode_oracle Create_func_decode_oracle::s_singleton;
Item*
Create_func_decode_oracle::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
uint arg_count= item_list ? item_list->elements : 0;
if (arg_count < 3)
{
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
return new (thd->mem_root) Item_func_decode_oracle(thd, *item_list);
}
Create_func_concat_ws Create_func_concat_ws::s_singleton;
Item*
......@@ -6851,6 +6879,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("DAYOFYEAR") }, BUILDER(Create_func_dayofyear)},
{ { C_STRING_WITH_LEN("DEGREES") }, BUILDER(Create_func_degrees)},
{ { C_STRING_WITH_LEN("DECODE_HISTOGRAM") }, BUILDER(Create_func_decode_histogram)},
{ { C_STRING_WITH_LEN("DECODE_ORACLE") }, BUILDER(Create_func_decode_oracle)},
{ { C_STRING_WITH_LEN("DES_DECRYPT") }, BUILDER(Create_func_des_decrypt)},
{ { C_STRING_WITH_LEN("DES_ENCRYPT") }, BUILDER(Create_func_des_encrypt)},
{ { C_STRING_WITH_LEN("DIMENSION") }, GEOM_BUILDER(Create_func_dimension)},
......
......@@ -9465,7 +9465,7 @@ column_default_non_parenthesized_expr:
| DECODE_SYM '(' expr ',' decode_when_list ')'
{
$5->push_front($3, thd->mem_root);
if (!($$= new (thd->mem_root) Item_func_case_simple(thd, *$5)))
if (!($$= new (thd->mem_root) Item_func_decode_oracle(thd, *$5)))
MYSQL_YYABORT;
}
| DEFAULT '(' simple_ident ')'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment