mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
MDEV-13863 sql_mode=ORACLE: DECODE does not treat two NULLs as equivalent
This commit is contained in:
parent
c39a744616
commit
884bd1d61b
7 changed files with 406 additions and 12 deletions
|
@ -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;
|
||||
|
|
17
sql/item.h
17
sql/item.h
|
@ -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 @@ public:
|
|||
"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 @@ public:
|
|||
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 @@ public:
|
|||
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 @@ public:
|
|||
{
|
||||
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 @@ public:
|
|||
{
|
||||
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 @@ public:
|
|||
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 @@ public:
|
|||
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 @@ public:
|
|||
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 @@ public:
|
|||
}
|
||||
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 @@ public:
|
|||
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 @@ public:
|
|||
};
|
||||
|
||||
|
||||
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 @@ public:
|
|||
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 @@ protected:
|
|||
};
|
||||
|
||||
|
||||
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 ')'
|
||||
|
|
Loading…
Reference in a new issue