Commit 8b5da9f7 authored by Alexander Barkov's avatar Alexander Barkov

Merge from 5.3

pending merges:
  Alexander Barkov 2013-09-09 MDEV-4863 COALESCE(time_or_datetime) returns...
parents 42f56557 c2b38529
...@@ -1950,3 +1950,112 @@ NULL ...@@ -1950,3 +1950,112 @@ NULL
Warnings: Warnings:
Warning 1411 Incorrect datetime value: '2020' for function str_to_date Warning 1411 Incorrect datetime value: '2020' for function str_to_date
SET TIME_ZONE=DEFAULT; SET TIME_ZONE=DEFAULT;
#
# MDEV-4863 COALESCE(time_or_datetime) returns wrong results in numeric context
#
CREATE TABLE t1 (a TIMESTAMP(3));
INSERT INTO t1 VALUES ('2001-01-01 10:20:30.999');
SELECT CAST(COALESCE(a,a) AS SIGNED) AS c1, CAST(COALESCE(a,a) AS DECIMAL(25,3)) AS c2, ROUND(COALESCE(a,a)) AS c2 FROM t1;
c1 c2 c2
20010101102030 20010101102030.999 20010101102031
DROP TABLE t1;
CREATE TABLE t1 (a TIME(3));
INSERT INTO t1 VALUES ('10:20:30.999');
SELECT CAST(COALESCE(a,a) AS SIGNED) AS c1, CAST(COALESCE(a,a) AS DECIMAL(25,3)) AS c2, ROUND(COALESCE(a,a)) AS c2 FROM t1;
c1 c2 c2
102030 102030.999 102031
DROP TABLE t1;
SELECT
CAST(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
CAST(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
CONCAT(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
TIME(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
DATE(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
TIMESTAMP(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
c1 c2 c3 c4 c5 c6 c7
20010101000000 20010101000000.0000 20010101000000 2001-01-01 00:00:00.000000 00:00:00.000000 2001-01-01 2001-01-01 00:00:00.000000
SELECT
CAST(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS SIGNED) AS c1,
CAST(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS DECIMAL(25,4)) AS c2,
COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))+0e0 AS c3,
CONCAT(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c4,
TIME(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c5,
DATE(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c6,
TIMESTAMP(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c7;
c1 c2 c3 c4 c5 c6 c7
20010102102030 20010102102030.0000 20010102102030 2001-01-02 10:20:30.000000 10:20:30.000000 2001-01-02 2001-01-02 10:20:30.000000
SELECT
CAST(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
CAST(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
CONCAT(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
TIME(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
DATE(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
TIMESTAMP(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
c1 c2 c3 c4 c5 c6 c7
20010101000000 20010101000000.0000 20010101000000 2001-01-01 00:00:00.000000 00:00:00.000000 2001-01-01 2001-01-01 00:00:00.000000
SELECT
CAST(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS SIGNED) AS c1,
CAST(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS DECIMAL(25,4)) AS c2,
IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))+0e0 AS c3,
CONCAT(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c4,
TIME(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c5,
DATE(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c6,
TIMESTAMP(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c7;
c1 c2 c3 c4 c5 c6 c7
20010102102030 20010102102030.0000 20010102102030 2001-01-02 10:20:30.000000 10:20:30.000000 2001-01-02 2001-01-02 10:20:30.000000
SELECT
CAST(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
CAST(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
CONCAT(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
TIME(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
DATE(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
TIMESTAMP(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
c1 c2 c3 c4 c5 c6 c7
20010101000000 20010101000000.0000 20010101000000 2001-01-01 00:00:00.000000 00:00:00.000000 2001-01-01 2001-01-01 00:00:00.000000
SELECT
CAST(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
CAST(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
CONCAT(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
TIME(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
DATE(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
TIMESTAMP(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
c1 c2 c3 c4 c5 c6 c7
20010102102030 20010102102030.0000 20010102102030 2001-01-02 10:20:30.000000 10:20:30.000000 2001-01-02 2001-01-02 10:20:30.000000
SELECT
CAST(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS SIGNED) AS c1,
CAST(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS DECIMAL(25,4)) AS c2,
CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END+0e0 AS c3,
CONCAT(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c4,
TIME(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c5,
DATE(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c6,
TIMESTAMP(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c7;
c1 c2 c3 c4 c5 c6 c7
20010101000000 20010101000000.0000 20010101000000 2001-01-01 00:00:00.000000 00:00:00.000000 2001-01-01 2001-01-01 00:00:00.000000
SELECT
CAST(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS SIGNED) AS c1,
CAST(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS DECIMAL(25,4)) AS c2,
CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END+0e0 AS c3,
CONCAT(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c4,
TIME(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c5,
DATE(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c6,
TIMESTAMP(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c7;
c1 c2 c3 c4 c5 c6 c7
20010102102030 20010102102030.0000 20010102102030 2001-01-02 10:20:30.000000 10:20:30.000000 2001-01-02 2001-01-02 10:20:30.000000
CREATE TABLE t1 AS SELECT
CONCAT(COALESCE(TIME(101010),TIME(101010))) AS c1,
CONCAT(IF(0,TIME(101010),TIME(101010))) AS c2,
CONCAT(IFNULL(TIME(101010),TIME(101010))) AS c3,
CONCAT(CASE WHEN 1 THEN TIME(101010) ELSE TIME(101010) END) AS c4;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(10) DEFAULT NULL,
`c2` varchar(10) DEFAULT NULL,
`c3` varchar(10) DEFAULT NULL,
`c4` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
...@@ -657,13 +657,8 @@ create table t1 (d date, t time) engine=myisam; ...@@ -657,13 +657,8 @@ create table t1 (d date, t time) engine=myisam;
insert into t1 values ('2000-12-03','22:55:23'),('2008-05-03','10:19:31'); insert into t1 values ('2000-12-03','22:55:23'),('2008-05-03','10:19:31');
select case when d = '2012-12-12' then d else t end as cond, group_concat( d ) from t1 group by cond; select case when d = '2012-12-12' then d else t end as cond, group_concat( d ) from t1 group by cond;
cond group_concat( d ) cond group_concat( d )
NULL 2000-12-03 0000-00-00 10:19:31 2008-05-03
NULL 2008-05-03 0000-00-00 22:55:23 2000-12-03
Warnings:
Warning 1292 Incorrect datetime value: '22:55:23'
Warning 1292 Incorrect datetime value: '10:19:31'
Warning 1292 Incorrect datetime value: '22:55:23'
Warning 1292 Incorrect datetime value: '10:19:31'
drop table t1; drop table t1;
# #
# Semantics of the condition <non-nullable datetime field> IS NULL # Semantics of the condition <non-nullable datetime field> IS NULL
......
...@@ -1192,3 +1192,96 @@ SELECT 1 FROM DUAL WHERE SECOND(TIMEDIFF(NULL, '12:12:12')); ...@@ -1192,3 +1192,96 @@ SELECT 1 FROM DUAL WHERE SECOND(TIMEDIFF(NULL, '12:12:12'));
SET TIME_ZONE='+02:00'; SET TIME_ZONE='+02:00';
SELECT UNIX_TIMESTAMP(STR_TO_DATE('2020','%Y')); SELECT UNIX_TIMESTAMP(STR_TO_DATE('2020','%Y'));
SET TIME_ZONE=DEFAULT; SET TIME_ZONE=DEFAULT;
--echo #
--echo # MDEV-4863 COALESCE(time_or_datetime) returns wrong results in numeric context
--echo #
CREATE TABLE t1 (a TIMESTAMP(3));
INSERT INTO t1 VALUES ('2001-01-01 10:20:30.999');
SELECT CAST(COALESCE(a,a) AS SIGNED) AS c1, CAST(COALESCE(a,a) AS DECIMAL(25,3)) AS c2, ROUND(COALESCE(a,a)) AS c2 FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a TIME(3));
INSERT INTO t1 VALUES ('10:20:30.999');
SELECT CAST(COALESCE(a,a) AS SIGNED) AS c1, CAST(COALESCE(a,a) AS DECIMAL(25,3)) AS c2, ROUND(COALESCE(a,a)) AS c2 FROM t1;
DROP TABLE t1;
SELECT
CAST(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
CAST(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
CONCAT(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
TIME(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
DATE(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
TIMESTAMP(COALESCE(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
SELECT
CAST(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS SIGNED) AS c1,
CAST(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS DECIMAL(25,4)) AS c2,
COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))+0e0 AS c3,
CONCAT(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c4,
TIME(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c5,
DATE(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c6,
TIMESTAMP(COALESCE(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c7;
SELECT
CAST(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
CAST(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
CONCAT(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
TIME(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
DATE(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
TIMESTAMP(IFNULL(DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
SELECT
CAST(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS SIGNED) AS c1,
CAST(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01')) AS DECIMAL(25,4)) AS c2,
IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))+0e0 AS c3,
CONCAT(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c4,
TIME(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c5,
DATE(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c6,
TIMESTAMP(IFNULL(TIMESTAMP('2001-01-02 10:20:30'),DATE('2001-01-01'))) AS c7;
SELECT
CAST(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
CAST(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
CONCAT(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
TIME(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
DATE(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
TIMESTAMP(IF(1,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
SELECT
CAST(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS SIGNED) AS c1,
CAST(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30')) AS DECIMAL(25,4)) AS c2,
IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))+0e0 AS c3,
CONCAT(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c4,
TIME(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c5,
DATE(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c6,
TIMESTAMP(IF(0,DATE('2001-01-01'),TIMESTAMP('2001-01-02 10:20:30'))) AS c7;
SELECT
CAST(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS SIGNED) AS c1,
CAST(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS DECIMAL(25,4)) AS c2,
CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END+0e0 AS c3,
CONCAT(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c4,
TIME(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c5,
DATE(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c6,
TIMESTAMP(CASE WHEN 1 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c7;
SELECT
CAST(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS SIGNED) AS c1,
CAST(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END AS DECIMAL(25,4)) AS c2,
CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END+0e0 AS c3,
CONCAT(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c4,
TIME(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c5,
DATE(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c6,
TIMESTAMP(CASE WHEN 0 THEN DATE('2001-01-01') ELSE TIMESTAMP('2001-01-02 10:20:30') END) AS c7;
CREATE TABLE t1 AS SELECT
CONCAT(COALESCE(TIME(101010),TIME(101010))) AS c1,
CONCAT(IF(0,TIME(101010),TIME(101010))) AS c2,
CONCAT(IFNULL(TIME(101010),TIME(101010))) AS c3,
CONCAT(CASE WHEN 1 THEN TIME(101010) ELSE TIME(101010) END) AS c4;
SHOW CREATE TABLE t1;
DROP TABLE t1;
...@@ -85,6 +85,34 @@ inline uint get_set_pack_length(int elements) ...@@ -85,6 +85,34 @@ inline uint get_set_pack_length(int elements)
return len > 4 ? 8 : len; return len > 4 ? 8 : len;
} }
static inline enum enum_mysql_timestamp_type
mysql_type_to_time_type(enum enum_field_types mysql_type)
{
switch(mysql_type) {
case MYSQL_TYPE_TIME: return MYSQL_TIMESTAMP_TIME;
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATETIME: return MYSQL_TIMESTAMP_DATETIME;
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_DATE: return MYSQL_TIMESTAMP_DATE;
default: return MYSQL_TIMESTAMP_ERROR;
}
}
/**
Tests if field type is temporal, i.e. represents
DATE, TIME, DATETIME or TIMESTAMP types in SQL.
@param type Field type, as returned by field->type().
@retval true If field type is temporal
@retval false If field type is not temporal
*/
inline bool is_temporal_type(enum_field_types type)
{
return mysql_type_to_time_type(type) != MYSQL_TIMESTAMP_ERROR;
}
/* /*
Virtual_column_info is the class to contain additional Virtual_column_info is the class to contain additional
characteristics that is specific for a virtual/computed characteristics that is specific for a virtual/computed
......
...@@ -2376,12 +2376,13 @@ void ...@@ -2376,12 +2376,13 @@ void
Item_func_ifnull::fix_length_and_dec() Item_func_ifnull::fix_length_and_dec()
{ {
uint32 char_length; uint32 char_length;
agg_result_type(&hybrid_type, args, 2); agg_result_type(&cached_result_type, args, 2);
cached_field_type= agg_field_type(args, 2);
maybe_null=args[1]->maybe_null; maybe_null=args[1]->maybe_null;
decimals= max(args[0]->decimals, args[1]->decimals); decimals= max(args[0]->decimals, args[1]->decimals);
unsigned_flag= args[0]->unsigned_flag && args[1]->unsigned_flag; unsigned_flag= args[0]->unsigned_flag && args[1]->unsigned_flag;
if (hybrid_type == DECIMAL_RESULT || hybrid_type == INT_RESULT) if (cached_result_type == DECIMAL_RESULT || cached_result_type == INT_RESULT)
{ {
int len0= args[0]->max_char_length() - args[0]->decimals int len0= args[0]->max_char_length() - args[0]->decimals
- (args[0]->unsigned_flag ? 0 : 1); - (args[0]->unsigned_flag ? 0 : 1);
...@@ -2394,9 +2395,9 @@ Item_func_ifnull::fix_length_and_dec() ...@@ -2394,9 +2395,9 @@ Item_func_ifnull::fix_length_and_dec()
else else
char_length= max(args[0]->max_char_length(), args[1]->max_char_length()); char_length= max(args[0]->max_char_length(), args[1]->max_char_length());
switch (hybrid_type) { switch (cached_result_type) {
case STRING_RESULT: case STRING_RESULT:
if (agg_arg_charsets_for_comparison(collation, args, arg_count)) if (count_string_result_length(cached_field_type, args, arg_count))
return; return;
break; break;
case DECIMAL_RESULT: case DECIMAL_RESULT:
...@@ -2411,7 +2412,6 @@ Item_func_ifnull::fix_length_and_dec() ...@@ -2411,7 +2412,6 @@ Item_func_ifnull::fix_length_and_dec()
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
fix_char_length(char_length); fix_char_length(char_length);
cached_field_type= agg_field_type(args, 2);
} }
...@@ -2425,11 +2425,6 @@ uint Item_func_ifnull::decimal_precision() const ...@@ -2425,11 +2425,6 @@ uint Item_func_ifnull::decimal_precision() const
} }
enum_field_types Item_func_ifnull::field_type() const
{
return cached_field_type;
}
Field *Item_func_ifnull::tmp_table_field(TABLE *table) Field *Item_func_ifnull::tmp_table_field(TABLE *table)
{ {
return tmp_table_field_from_field_type(table, 0); return tmp_table_field_from_field_type(table, 0);
...@@ -2503,6 +2498,18 @@ Item_func_ifnull::str_op(String *str) ...@@ -2503,6 +2498,18 @@ Item_func_ifnull::str_op(String *str)
} }
bool Item_func_ifnull::date_op(MYSQL_TIME *ltime, uint fuzzydate)
{
DBUG_ASSERT(fixed == 1);
if (!args[0]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES))
return (null_value= false);
if (!args[1]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES))
return (null_value= false);
bzero((char*) ltime,sizeof(*ltime));
return null_value= !(fuzzydate & TIME_FUZZY_DATES);
}
/** /**
Perform context analysis of an IF item tree. Perform context analysis of an IF item tree.
...@@ -2597,20 +2604,20 @@ Item_func_if::fix_length_and_dec() ...@@ -2597,20 +2604,20 @@ Item_func_if::fix_length_and_dec()
} }
agg_result_type(&cached_result_type, args + 1, 2); agg_result_type(&cached_result_type, args + 1, 2);
cached_field_type= agg_field_type(args + 1, 2);
maybe_null= args[1]->maybe_null || args[2]->maybe_null; maybe_null= args[1]->maybe_null || args[2]->maybe_null;
decimals= max(args[1]->decimals, args[2]->decimals); decimals= max(args[1]->decimals, args[2]->decimals);
unsigned_flag=args[1]->unsigned_flag && args[2]->unsigned_flag; unsigned_flag=args[1]->unsigned_flag && args[2]->unsigned_flag;
if (cached_result_type == STRING_RESULT) if (cached_result_type == STRING_RESULT)
{ {
if (agg_arg_charsets_for_string_result(collation, args + 1, 2)) count_string_result_length(cached_field_type, args + 1, 2);
return; return;
} }
else else
{ {
collation.set_numeric(); // Number collation.set_numeric(); // Number
} }
cached_field_type= agg_field_type(args + 1, 2);
uint32 char_length; uint32 char_length;
if ((cached_result_type == DECIMAL_RESULT ) if ((cached_result_type == DECIMAL_RESULT )
...@@ -2640,7 +2647,7 @@ uint Item_func_if::decimal_precision() const ...@@ -2640,7 +2647,7 @@ uint Item_func_if::decimal_precision() const
double double
Item_func_if::val_real() Item_func_if::real_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_bool() ? args[1] : args[2]; Item *arg= args[0]->val_bool() ? args[1] : args[2];
...@@ -2650,7 +2657,7 @@ Item_func_if::val_real() ...@@ -2650,7 +2657,7 @@ Item_func_if::val_real()
} }
longlong longlong
Item_func_if::val_int() Item_func_if::int_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_bool() ? args[1] : args[2]; Item *arg= args[0]->val_bool() ? args[1] : args[2];
...@@ -2660,7 +2667,7 @@ Item_func_if::val_int() ...@@ -2660,7 +2667,7 @@ Item_func_if::val_int()
} }
String * String *
Item_func_if::val_str(String *str) Item_func_if::str_op(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_bool() ? args[1] : args[2]; Item *arg= args[0]->val_bool() ? args[1] : args[2];
...@@ -2673,7 +2680,7 @@ Item_func_if::val_str(String *str) ...@@ -2673,7 +2680,7 @@ Item_func_if::val_str(String *str)
my_decimal * my_decimal *
Item_func_if::val_decimal(my_decimal *decimal_value) Item_func_if::decimal_op(my_decimal *decimal_value)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_bool() ? args[1] : args[2]; Item *arg= args[0]->val_bool() ? args[1] : args[2];
...@@ -2683,6 +2690,14 @@ Item_func_if::val_decimal(my_decimal *decimal_value) ...@@ -2683,6 +2690,14 @@ Item_func_if::val_decimal(my_decimal *decimal_value)
} }
bool Item_func_if::date_op(MYSQL_TIME *ltime, uint fuzzydate)
{
DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_bool() ? args[1] : args[2];
return (null_value= arg->get_date(ltime, fuzzydate));
}
void void
Item_func_nullif::fix_length_and_dec() Item_func_nullif::fix_length_and_dec()
{ {
...@@ -2841,7 +2856,7 @@ Item *Item_func_case::find_item(String *str) ...@@ -2841,7 +2856,7 @@ Item *Item_func_case::find_item(String *str)
} }
String *Item_func_case::val_str(String *str) String *Item_func_case::str_op(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
String *res; String *res;
...@@ -2859,7 +2874,7 @@ String *Item_func_case::val_str(String *str) ...@@ -2859,7 +2874,7 @@ String *Item_func_case::val_str(String *str)
} }
longlong Item_func_case::val_int() longlong Item_func_case::int_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH]; char buff[MAX_FIELD_WIDTH];
...@@ -2877,7 +2892,7 @@ longlong Item_func_case::val_int() ...@@ -2877,7 +2892,7 @@ longlong Item_func_case::val_int()
return res; return res;
} }
double Item_func_case::val_real() double Item_func_case::real_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH]; char buff[MAX_FIELD_WIDTH];
...@@ -2896,7 +2911,7 @@ double Item_func_case::val_real() ...@@ -2896,7 +2911,7 @@ double Item_func_case::val_real()
} }
my_decimal *Item_func_case::val_decimal(my_decimal *decimal_value) my_decimal *Item_func_case::decimal_op(my_decimal *decimal_value)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH]; char buff[MAX_FIELD_WIDTH];
...@@ -2916,6 +2931,18 @@ my_decimal *Item_func_case::val_decimal(my_decimal *decimal_value) ...@@ -2916,6 +2931,18 @@ my_decimal *Item_func_case::val_decimal(my_decimal *decimal_value)
} }
bool Item_func_case::date_op(MYSQL_TIME *ltime, uint fuzzydate)
{
DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH];
String dummy_str(buff, sizeof(buff), default_charset());
Item *item= find_item(&dummy_str);
if (!item)
return (null_value= true);
return (null_value= item->get_date(ltime, fuzzydate));
}
bool Item_func_case::fix_fields(THD *thd, Item **ref) bool Item_func_case::fix_fields(THD *thd, Item **ref)
{ {
/* /*
...@@ -2984,6 +3011,9 @@ void Item_func_case::fix_length_and_dec() ...@@ -2984,6 +3011,9 @@ void Item_func_case::fix_length_and_dec()
if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1)))) if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1))))
return; return;
if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
maybe_null= 1;
/* /*
Aggregate all THEN and ELSE expression types Aggregate all THEN and ELSE expression types
and collations when string result and collations when string result
...@@ -2996,9 +3026,11 @@ void Item_func_case::fix_length_and_dec() ...@@ -2996,9 +3026,11 @@ void Item_func_case::fix_length_and_dec()
agg[nagg++]= args[else_expr_num]; agg[nagg++]= args[else_expr_num];
agg_result_type(&cached_result_type, agg, nagg); agg_result_type(&cached_result_type, agg, nagg);
cached_field_type= agg_field_type(agg, nagg);
if (cached_result_type == STRING_RESULT) if (cached_result_type == STRING_RESULT)
{ {
if (agg_arg_charsets_for_string_result(collation, agg, nagg)) if (count_string_result_length(cached_field_type, agg, nagg))
return; return;
/* /*
Copy all THEN and ELSE items back to args[] array. Copy all THEN and ELSE items back to args[] array.
...@@ -3011,11 +3043,22 @@ void Item_func_case::fix_length_and_dec() ...@@ -3011,11 +3043,22 @@ void Item_func_case::fix_length_and_dec()
change_item_tree_if_needed(thd, &args[else_expr_num], agg[nagg++]); change_item_tree_if_needed(thd, &args[else_expr_num], agg[nagg++]);
} }
else else
{
collation.set_numeric(); collation.set_numeric();
max_length=0;
decimals=0;
unsigned_flag= TRUE;
for (uint i= 0; i < ncases; i+= 2)
agg_num_lengths(args[i + 1]);
if (else_expr_num != -1)
agg_num_lengths(args[else_expr_num]);
max_length= my_decimal_precision_to_length_no_truncation(max_length +
decimals, decimals,
unsigned_flag);
}
cached_field_type= agg_field_type(agg, nagg);
/* /*
Aggregate first expression and all THEN expression types Aggregate first expression and all WHEN expression types
and collations when string comparison and collations when string comparison
*/ */
if (first_expr_num != -1) if (first_expr_num != -1)
...@@ -3101,30 +3144,6 @@ void Item_func_case::fix_length_and_dec() ...@@ -3101,30 +3144,6 @@ void Item_func_case::fix_length_and_dec()
args[i]->cmp_context= item_cmp_type(left_result_type, args[i]->cmp_context= item_cmp_type(left_result_type,
args[i]->result_type()); args[i]->result_type());
} }
if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
maybe_null=1;
max_length=0;
decimals=0;
unsigned_flag= TRUE;
if (cached_result_type == STRING_RESULT)
{
for (uint i= 0; i < ncases; i+= 2)
agg_str_lengths(args[i + 1]);
if (else_expr_num != -1)
agg_str_lengths(args[else_expr_num]);
}
else
{
for (uint i= 0; i < ncases; i+= 2)
agg_num_lengths(args[i + 1]);
if (else_expr_num != -1)
agg_num_lengths(args[else_expr_num]);
max_length= my_decimal_precision_to_length_no_truncation(max_length +
decimals, decimals,
unsigned_flag);
}
} }
...@@ -3232,7 +3251,7 @@ double Item_func_coalesce::real_op() ...@@ -3232,7 +3251,7 @@ double Item_func_coalesce::real_op()
} }
bool Item_func_coalesce::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) bool Item_func_coalesce::date_op(MYSQL_TIME *ltime,uint fuzzydate)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
null_value= 0; null_value= 0;
...@@ -3265,21 +3284,11 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value) ...@@ -3265,21 +3284,11 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
void Item_func_coalesce::fix_length_and_dec() void Item_func_coalesce::fix_length_and_dec()
{ {
cached_field_type= agg_field_type(args, arg_count); cached_field_type= agg_field_type(args, arg_count);
agg_result_type(&hybrid_type, args, arg_count); agg_result_type(&cached_result_type, args, arg_count);
Item_result cmp_type; switch (cached_result_type) {
agg_cmp_type(&cmp_type, args, arg_count);
///< @todo let result_type() return TIME_RESULT and remove this special case
if (cmp_type == TIME_RESULT)
{
count_real_length();
return;
}
switch (hybrid_type) {
case STRING_RESULT: case STRING_RESULT:
decimals= NOT_FIXED_DEC; if (count_string_result_length(cached_field_type, args, arg_count))
if (agg_arg_charsets_for_string_result(collation, args, arg_count))
return; return;
count_only_length();
break; break;
case DECIMAL_RESULT: case DECIMAL_RESULT:
count_decimal_length(); count_decimal_length();
...@@ -3288,7 +3297,7 @@ void Item_func_coalesce::fix_length_and_dec() ...@@ -3288,7 +3297,7 @@ void Item_func_coalesce::fix_length_and_dec()
count_real_length(); count_real_length();
break; break;
case INT_RESULT: case INT_RESULT:
count_only_length(); count_only_length(args, arg_count);
decimals= 0; decimals= 0;
break; break;
case ROW_RESULT: case ROW_RESULT:
......
...@@ -734,24 +734,19 @@ public: ...@@ -734,24 +734,19 @@ public:
}; };
class Item_func_coalesce :public Item_func_numhybrid class Item_func_coalesce :public Item_func_hybrid_field_type
{ {
protected:
enum_field_types cached_field_type;
Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {}
public: public:
Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {} Item_func_coalesce(Item *a, Item *b) :Item_func_hybrid_field_type(a, b) {}
Item_func_coalesce(List<Item> &list) :Item_func_hybrid_field_type(list) {}
double real_op(); double real_op();
longlong int_op(); longlong int_op();
String *str_op(String *); String *str_op(String *);
my_decimal *decimal_op(my_decimal *); my_decimal *decimal_op(my_decimal *);
bool date_op(MYSQL_TIME *ltime,uint fuzzydate);
void fix_length_and_dec(); void fix_length_and_dec();
void find_num_type() {}
enum Item_result result_type () const { return hybrid_type; }
const char *func_name() const { return "coalesce"; } const char *func_name() const { return "coalesce"; }
table_map not_null_tables() const { return 0; } table_map not_null_tables() const { return 0; }
enum_field_types field_type() const { return cached_field_type; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
}; };
...@@ -765,7 +760,7 @@ public: ...@@ -765,7 +760,7 @@ public:
longlong int_op(); longlong int_op();
String *str_op(String *str); String *str_op(String *str);
my_decimal *decimal_op(my_decimal *); my_decimal *decimal_op(my_decimal *);
enum_field_types field_type() const; bool date_op(MYSQL_TIME *ltime,uint fuzzydate);
void fix_length_and_dec(); void fix_length_and_dec();
void update_used_tables() void update_used_tables()
{ {
...@@ -778,20 +773,17 @@ public: ...@@ -778,20 +773,17 @@ public:
}; };
class Item_func_if :public Item_func class Item_func_if :public Item_func_hybrid_field_type
{ {
enum Item_result cached_result_type;
enum_field_types cached_field_type;
public: public:
Item_func_if(Item *a,Item *b,Item *c) Item_func_if(Item *a,Item *b,Item *c)
:Item_func(a,b,c), cached_result_type(INT_RESULT) :Item_func_hybrid_field_type(a,b,c)
{} {}
double val_real(); bool date_op(MYSQL_TIME *ltime, uint fuzzydate);
longlong val_int(); longlong int_op();
String *val_str(String *str); double real_op();
my_decimal *val_decimal(my_decimal *); my_decimal *decimal_op(my_decimal *);
enum Item_result result_type () const { return cached_result_type; } String *str_op(String *);
enum_field_types field_type() const { return cached_field_type; }
bool fix_fields(THD *, Item **); bool fix_fields(THD *, Item **);
void fix_length_and_dec(); void fix_length_and_dec();
void update_used_tables() void update_used_tables()
...@@ -1228,21 +1220,20 @@ public: ...@@ -1228,21 +1220,20 @@ public:
function and only comparators for there result types are used. function and only comparators for there result types are used.
*/ */
class Item_func_case :public Item_func class Item_func_case :public Item_func_hybrid_field_type
{ {
int first_expr_num, else_expr_num; int first_expr_num, else_expr_num;
enum Item_result cached_result_type, left_result_type; enum Item_result left_result_type;
String tmp_value; String tmp_value;
uint ncases; uint ncases;
Item_result cmp_type; Item_result cmp_type;
DTCollation cmp_collation; DTCollation cmp_collation;
enum_field_types cached_field_type;
cmp_item *cmp_items[6]; /* For all result types */ cmp_item *cmp_items[6]; /* For all result types */
cmp_item *case_item; cmp_item *case_item;
public: public:
Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg) Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
:Item_func(), first_expr_num(-1), else_expr_num(-1), :Item_func_hybrid_field_type(), first_expr_num(-1), else_expr_num(-1),
cached_result_type(INT_RESULT), left_result_type(INT_RESULT), case_item(0) left_result_type(INT_RESULT), case_item(0)
{ {
ncases= list.elements; ncases= list.elements;
if (first_expr_arg) if (first_expr_arg)
...@@ -1258,10 +1249,11 @@ public: ...@@ -1258,10 +1249,11 @@ public:
set_arguments(list); set_arguments(list);
bzero(&cmp_items, sizeof(cmp_items)); bzero(&cmp_items, sizeof(cmp_items));
} }
double val_real(); double real_op();
longlong val_int(); longlong int_op();
String *val_str(String *); String *str_op(String *);
my_decimal *val_decimal(my_decimal *); my_decimal *decimal_op(my_decimal *);
bool date_op(MYSQL_TIME *ltime, uint fuzzydate);
bool fix_fields(THD *thd, Item **ref); bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec(); void fix_length_and_dec();
void update_used_tables() void update_used_tables()
...@@ -1272,8 +1264,6 @@ public: ...@@ -1272,8 +1264,6 @@ public:
} }
uint decimal_precision() const; uint decimal_precision() const;
table_map not_null_tables() const { return 0; } table_map not_null_tables() const { return 0; }
enum Item_result result_type () const { return cached_result_type; }
enum_field_types field_type() const { return cached_field_type; }
const char *func_name() const { return "case"; } const char *func_name() const { return "case"; }
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
Item *find_item(String *str); Item *find_item(String *str);
......
This diff is collapsed.
...@@ -149,13 +149,16 @@ public: ...@@ -149,13 +149,16 @@ public:
void print_op(String *str, enum_query_type query_type); void print_op(String *str, enum_query_type query_type);
void print_args(String *str, uint from, enum_query_type query_type); void print_args(String *str, uint from, enum_query_type query_type);
virtual void fix_num_length_and_dec(); virtual void fix_num_length_and_dec();
void count_only_length(); void count_only_length(Item **item, uint nitems);
void count_real_length(); void count_real_length();
void count_decimal_length(); void count_decimal_length();
inline bool get_arg0_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) inline bool get_arg0_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
{ {
return (null_value=args[0]->get_date(ltime, fuzzy_date)); return (null_value=args[0]->get_date(ltime, fuzzy_date));
} }
void count_datetime_length(Item **item, uint nitems);
bool count_string_result_length(enum_field_types field_type,
Item **item, uint nitems);
inline bool get_arg0_time(MYSQL_TIME *ltime) inline bool get_arg0_time(MYSQL_TIME *ltime)
{ {
return (null_value=args[0]->get_time(ltime)); return (null_value=args[0]->get_time(ltime));
...@@ -410,38 +413,33 @@ public: ...@@ -410,38 +413,33 @@ public:
}; };
class Item_func_numhybrid: public Item_func class Item_func_hybrid_result_type: public Item_func
{ {
protected: protected:
Item_result hybrid_type; Item_result cached_result_type;
public: public:
Item_func_numhybrid() :Item_func(), hybrid_type(REAL_RESULT) Item_func_hybrid_result_type() :Item_func(), cached_result_type(REAL_RESULT)
{}
Item_func_numhybrid(Item *a) :Item_func(a), hybrid_type(REAL_RESULT)
{ collation.set_numeric(); } { collation.set_numeric(); }
Item_func_numhybrid(Item *a,Item *b) Item_func_hybrid_result_type(Item *a) :Item_func(a), cached_result_type(REAL_RESULT)
:Item_func(a,b), hybrid_type(REAL_RESULT)
{ collation.set_numeric(); } { collation.set_numeric(); }
Item_func_numhybrid(List<Item> &list) Item_func_hybrid_result_type(Item *a,Item *b)
:Item_func(list), hybrid_type(REAL_RESULT) :Item_func(a,b), cached_result_type(REAL_RESULT)
{ collation.set_numeric(); }
Item_func_hybrid_result_type(Item *a,Item *b,Item *c)
:Item_func(a,b,c), cached_result_type(REAL_RESULT)
{ collation.set_numeric(); }
Item_func_hybrid_result_type(List<Item> &list)
:Item_func(list), cached_result_type(REAL_RESULT)
{ collation.set_numeric(); } { collation.set_numeric(); }
enum Item_result result_type () const { return hybrid_type; } enum Item_result result_type () const { return cached_result_type; }
void fix_length_and_dec();
void fix_num_length_and_dec();
virtual void find_num_type()= 0; /* To be called from fix_length_and_dec */
inline void fix_decimals()
{
DBUG_ASSERT(result_type() == DECIMAL_RESULT);
if (decimals == NOT_FIXED_DEC)
set_if_smaller(decimals, max_length - 1);
}
double val_real(); double val_real();
longlong val_int(); longlong val_int();
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
String *val_str(String*str); String *val_str(String*str);
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
/** /**
@brief Performs the operation that this functions implements when the @brief Performs the operation that this functions implements when the
...@@ -478,9 +476,75 @@ public: ...@@ -478,9 +476,75 @@ public:
@return The result of the operation. @return The result of the operation.
*/ */
virtual String *str_op(String *)= 0; virtual String *str_op(String *)= 0;
bool is_null() { update_null_value(); return null_value; }
/**
@brief Performs the operation that this functions implements when
field type is a temporal type.
@return The result of the operation.
*/
virtual bool date_op(MYSQL_TIME *res, uint fuzzy_date)= 0;
};
class Item_func_hybrid_field_type :public Item_func_hybrid_result_type
{
protected:
enum_field_types cached_field_type;
public:
Item_func_hybrid_field_type()
:Item_func_hybrid_result_type(), cached_field_type(MYSQL_TYPE_DOUBLE)
{}
Item_func_hybrid_field_type(Item *a, Item *b)
:Item_func_hybrid_result_type(a, b), cached_field_type(MYSQL_TYPE_DOUBLE)
{}
Item_func_hybrid_field_type(Item *a, Item *b, Item *c)
:Item_func_hybrid_result_type(a, b, c),
cached_field_type(MYSQL_TYPE_DOUBLE)
{}
Item_func_hybrid_field_type(List<Item> &list)
:Item_func_hybrid_result_type(list),
cached_field_type(MYSQL_TYPE_DOUBLE)
{}
enum_field_types field_type() const { return cached_field_type; }
};
class Item_func_numhybrid: public Item_func_hybrid_result_type
{
protected:
inline void fix_decimals()
{
DBUG_ASSERT(result_type() == DECIMAL_RESULT);
if (decimals == NOT_FIXED_DEC)
set_if_smaller(decimals, max_length - 1);
}
public:
Item_func_numhybrid() :Item_func_hybrid_result_type()
{ }
Item_func_numhybrid(Item *a) :Item_func_hybrid_result_type(a)
{ }
Item_func_numhybrid(Item *a,Item *b)
:Item_func_hybrid_result_type(a,b)
{ }
Item_func_numhybrid(Item *a,Item *b,Item *c)
:Item_func_hybrid_result_type(a,b,c)
{ }
Item_func_numhybrid(List<Item> &list)
:Item_func_hybrid_result_type(list)
{ }
void fix_length_and_dec();
void fix_num_length_and_dec();
virtual void find_num_type()= 0; /* To be called from fix_length_and_dec */
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
bool date_op(MYSQL_TIME *ltime, uint fuzzydate) { DBUG_ASSERT(0); return true; }
}; };
/* function where type of result detected by first argument */ /* function where type of result detected by first argument */
class Item_func_num1: public Item_func_numhybrid class Item_func_num1: public Item_func_numhybrid
{ {
...@@ -490,7 +554,6 @@ public: ...@@ -490,7 +554,6 @@ public:
void fix_num_length_and_dec(); void fix_num_length_and_dec();
void find_num_type(); void find_num_type();
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
}; };
...@@ -507,7 +570,6 @@ class Item_num_op :public Item_func_numhybrid ...@@ -507,7 +570,6 @@ class Item_num_op :public Item_func_numhybrid
} }
void find_num_type(); void find_num_type();
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
}; };
......
...@@ -1435,12 +1435,8 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval) ...@@ -1435,12 +1435,8 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval)
void Item_temporal_func::fix_length_and_dec() void Item_temporal_func::fix_length_and_dec()
{ {
static const uint max_time_type_width[5]=
{ MAX_DATETIME_WIDTH, MAX_DATETIME_WIDTH, MAX_DATE_WIDTH,
MAX_DATETIME_WIDTH, MIN_TIME_WIDTH };
set_persist_maybe_null(1); set_persist_maybe_null(1);
max_length= max_time_type_width[mysql_type_to_time_type(field_type())+2]; max_length= mysql_temporal_int_part_length(field_type());
if (decimals) if (decimals)
{ {
if (decimals == NOT_FIXED_DEC) if (decimals == NOT_FIXED_DEC)
......
...@@ -30,19 +30,17 @@ enum date_time_format_types ...@@ -30,19 +30,17 @@ enum date_time_format_types
TIME_ONLY= 0, TIME_MICROSECOND, DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND TIME_ONLY= 0, TIME_MICROSECOND, DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
}; };
static inline enum enum_mysql_timestamp_type
mysql_type_to_time_type(enum enum_field_types mysql_type) static inline uint
mysql_temporal_int_part_length(enum enum_field_types mysql_type)
{ {
switch(mysql_type) { static uint max_time_type_width[5]=
case MYSQL_TYPE_TIME: return MYSQL_TIMESTAMP_TIME; { MAX_DATETIME_WIDTH, MAX_DATETIME_WIDTH, MAX_DATE_WIDTH,
case MYSQL_TYPE_TIMESTAMP: MAX_DATETIME_WIDTH, MIN_TIME_WIDTH };
case MYSQL_TYPE_DATETIME: return MYSQL_TIMESTAMP_DATETIME; return max_time_type_width[mysql_type_to_time_type(mysql_type)+2];
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_DATE: return MYSQL_TIMESTAMP_DATE;
default: return MYSQL_TIMESTAMP_ERROR;
}
} }
bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval); bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval);
class Item_func_period_add :public Item_int_func class Item_func_period_add :public Item_int_func
...@@ -421,9 +419,11 @@ public: ...@@ -421,9 +419,11 @@ public:
max_length=17 + (decimals ? decimals + 1 : 0); max_length=17 + (decimals ? decimals + 1 : 0);
set_persist_maybe_null(1); set_persist_maybe_null(1);
} }
void find_num_type() { hybrid_type= decimals ? DECIMAL_RESULT : INT_RESULT; } void find_num_type()
{ cached_result_type= decimals ? DECIMAL_RESULT : INT_RESULT; }
double real_op() { DBUG_ASSERT(0); return 0; } double real_op() { DBUG_ASSERT(0); return 0; }
String *str_op(String *str) { DBUG_ASSERT(0); return 0; } String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
bool date_op(MYSQL_TIME *ltime, uint fuzzydate) { DBUG_ASSERT(0); return true; }
}; };
......
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