mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-12514 Split Item_temporal_func::fix_length_and_dec() + MDEV-12515
This patch implements MDEV-12514 according to the task descriptions. It automatically fixes: MDEV-12515 Wrong value when storing DATE_ADD() and ADDTIME() to a numeric field Additionally: a. Moves Item_func::set_attributes_temporal() to Type_str_attributes::fix_attributes_temporal(), which is a more proper place and name for it. b. Continues replacing calls for: set_handler_by_field_type(MYSQL_TYPE_XXX) to corresponding: set_handler(&type_handler_xxx) which is faster. Note, we should eventually get rid of almost all set_handler_by_field_type(). c. Makes type_handler_string, type_handler_time2, type_handler_newdate, type_handler_datetime2 public. (all built-in handlers will become public eventually) d. Removing Item_temporal_func::sql_mode, as it was not used.
This commit is contained in:
@ -3210,3 +3210,48 @@ DROP TABLE t1,t2;
|
||||
#
|
||||
# End of 10.1 tests
|
||||
#
|
||||
#
|
||||
# Start of 10.3 tests
|
||||
#
|
||||
#
|
||||
# MDEV-12515 Wrong value when storing DATE_ADD() and ADDTIME() to a numeric field
|
||||
#
|
||||
SET sql_mode='';
|
||||
CREATE TABLE t1 AS SELECT
|
||||
DATE_ADD('2001-01-01',INTERVAL 1 DAY) AS c1,
|
||||
ADDTIME('10:20:30',1) AS c2;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` varchar(19) DEFAULT NULL,
|
||||
`c2` varchar(26) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
SELECT * FROM t1;
|
||||
c1 c2
|
||||
2001-01-02 10:20:31
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t2 (c INT);
|
||||
INSERT INTO t2 SELECT DATE_ADD('2001-01-01',INTERVAL 1 DAY);
|
||||
Warnings:
|
||||
Warning 1265 Data truncated for column 'c' at row 1
|
||||
INSERT INTO t2 VALUES ('2001-01-02');
|
||||
Warnings:
|
||||
Warning 1265 Data truncated for column 'c' at row 1
|
||||
SELECT * FROM t2;
|
||||
c
|
||||
2001
|
||||
2001
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2 (a INT);
|
||||
INSERT INTO t2 VALUES (ADDTIME('10:20:30',1));
|
||||
Warnings:
|
||||
Warning 1265 Data truncated for column 'a' at row 1
|
||||
INSERT INTO t2 VALUES ('10:20:31');
|
||||
Warnings:
|
||||
Warning 1265 Data truncated for column 'a' at row 1
|
||||
SELECT * FROM t2;
|
||||
a
|
||||
10
|
||||
10
|
||||
DROP TABLE t2;
|
||||
SET sql_mode=DEFAULT;
|
||||
|
@ -3902,5 +3902,36 @@ SELECT 1 MOD COALESCE(a) FROM t1;
|
||||
ERROR HY000: Illegal parameter data types bigint and geometry for operation '%'
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-12514 Split Item_temporal_func::fix_length_and_dec()
|
||||
#
|
||||
SELECT DATE_ADD(POINT(1,1), INTERVAL 10 DAY);
|
||||
ERROR HY000: Illegal parameter data types geometry and interval for operation 'date_add_interval'
|
||||
SELECT DATE_SUB(POINT(1,1), INTERVAL 10 DAY);
|
||||
ERROR HY000: Illegal parameter data types geometry and interval for operation 'date_add_interval'
|
||||
SELECT POINT(1,1) + INTERVAL 10 DAY;
|
||||
ERROR HY000: Illegal parameter data types geometry and interval for operation 'date_add_interval'
|
||||
SELECT POINT(1,1) - INTERVAL 10 DAY;
|
||||
ERROR HY000: Illegal parameter data types geometry and interval for operation 'date_add_interval'
|
||||
SELECT INTERVAL 10 DAY + POINT(1,1);
|
||||
ERROR HY000: Illegal parameter data types geometry and interval for operation 'date_add_interval'
|
||||
SELECT INTERVAL 10 DAY + POINT(1,1);
|
||||
ERROR HY000: Illegal parameter data types geometry and interval for operation 'date_add_interval'
|
||||
SELECT ADDTIME(POINT(1,1), '10:10:10');
|
||||
ERROR HY000: Illegal parameter data types geometry and varchar for operation 'add_time'
|
||||
SELECT ADDTIME('10:10:10', POINT(1,1));
|
||||
ERROR HY000: Illegal parameter data types varchar and geometry for operation 'add_time'
|
||||
SELECT ADDTIME(POINT(1,1), TIME'10:10:10');
|
||||
ERROR HY000: Illegal parameter data types geometry and time for operation 'add_time'
|
||||
SELECT ADDTIME(TIME'10:10:10', POINT(1,1));
|
||||
ERROR HY000: Illegal parameter data types time and geometry for operation 'add_time'
|
||||
SELECT ADDTIME(POINT(1,1), TIMESTAMP'2001-01-01 10:10:10');
|
||||
ERROR HY000: Illegal parameter data types geometry and datetime for operation 'add_time'
|
||||
SELECT ADDTIME(TIMESTAMP'2001-01-01 10:10:10', POINT(1,1));
|
||||
ERROR HY000: Illegal parameter data types datetime and geometry for operation 'add_time'
|
||||
SELECT STR_TO_DATE(POINT(1,1),'%M %d,%Y');
|
||||
ERROR HY000: Illegal parameter data types geometry and varchar for operation 'str_to_date'
|
||||
SELECT STR_TO_DATE('2001-01-01', POINT(1,1));
|
||||
ERROR HY000: Illegal parameter data types varchar and geometry for operation 'str_to_date'
|
||||
#
|
||||
# End of 10.3 tests
|
||||
#
|
||||
|
@ -1817,3 +1817,35 @@ DROP TABLE t1,t2;
|
||||
--echo #
|
||||
--echo # End of 10.1 tests
|
||||
--echo #
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.3 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-12515 Wrong value when storing DATE_ADD() and ADDTIME() to a numeric field
|
||||
--echo #
|
||||
|
||||
SET sql_mode='';
|
||||
|
||||
CREATE TABLE t1 AS SELECT
|
||||
DATE_ADD('2001-01-01',INTERVAL 1 DAY) AS c1,
|
||||
ADDTIME('10:20:30',1) AS c2;
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t2 (c INT);
|
||||
INSERT INTO t2 SELECT DATE_ADD('2001-01-01',INTERVAL 1 DAY);
|
||||
INSERT INTO t2 VALUES ('2001-01-02');
|
||||
SELECT * FROM t2;
|
||||
DROP TABLE t2;
|
||||
|
||||
CREATE TABLE t2 (a INT);
|
||||
INSERT INTO t2 VALUES (ADDTIME('10:20:30',1));
|
||||
INSERT INTO t2 VALUES ('10:20:31');
|
||||
SELECT * FROM t2;
|
||||
DROP TABLE t2;
|
||||
|
||||
SET sql_mode=DEFAULT;
|
||||
|
@ -2090,6 +2090,40 @@ SELECT 1 MOD COALESCE(a) FROM t1;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-12514 Split Item_temporal_func::fix_length_and_dec()
|
||||
--echo #
|
||||
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT DATE_ADD(POINT(1,1), INTERVAL 10 DAY);
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT DATE_SUB(POINT(1,1), INTERVAL 10 DAY);
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT POINT(1,1) + INTERVAL 10 DAY;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT POINT(1,1) - INTERVAL 10 DAY;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT INTERVAL 10 DAY + POINT(1,1);
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT INTERVAL 10 DAY + POINT(1,1);
|
||||
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT ADDTIME(POINT(1,1), '10:10:10');
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT ADDTIME('10:10:10', POINT(1,1));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT ADDTIME(POINT(1,1), TIME'10:10:10');
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT ADDTIME(TIME'10:10:10', POINT(1,1));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT ADDTIME(POINT(1,1), TIMESTAMP'2001-01-01 10:10:10');
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT ADDTIME(TIMESTAMP'2001-01-01 10:10:10', POINT(1,1));
|
||||
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT STR_TO_DATE(POINT(1,1),'%M %d,%Y');
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT STR_TO_DATE('2001-01-01', POINT(1,1));
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.3 tests
|
||||
|
@ -75,18 +75,10 @@ public:
|
||||
{
|
||||
return count_string_length(item, nitems);
|
||||
}
|
||||
void set_attributes_temporal(uint int_part_length, uint dec)
|
||||
{
|
||||
collation.set_numeric();
|
||||
unsigned_flag= 0;
|
||||
decimals= MY_MIN(dec, TIME_SECOND_PART_DIGITS);
|
||||
uint length= decimals + int_part_length + (dec ? 1 : 0);
|
||||
fix_char_length(length);
|
||||
}
|
||||
void aggregate_attributes_temporal(uint int_part_length,
|
||||
Item **item, uint nitems)
|
||||
{
|
||||
set_attributes_temporal(int_part_length, count_max_decimals(item, nitems));
|
||||
fix_attributes_temporal(int_part_length, count_max_decimals(item, nitems));
|
||||
}
|
||||
|
||||
table_map not_null_tables_cache;
|
||||
|
@ -1458,34 +1458,6 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval)
|
||||
}
|
||||
|
||||
|
||||
void Item_temporal_func::fix_length_and_dec()
|
||||
{
|
||||
uint char_length= mysql_temporal_int_part_length(field_type());
|
||||
/*
|
||||
We set maybe_null to 1 as default as any bad argument with date or
|
||||
time can get us to return NULL.
|
||||
*/
|
||||
maybe_null= (arg_count > 0);
|
||||
if (decimals)
|
||||
{
|
||||
if (decimals == NOT_FIXED_DEC)
|
||||
char_length+= TIME_SECOND_PART_DIGITS + 1;
|
||||
else
|
||||
{
|
||||
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
|
||||
char_length+= decimals + 1;
|
||||
}
|
||||
}
|
||||
sql_mode= current_thd->variables.sql_mode &
|
||||
(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE);
|
||||
collation.set(field_type() == MYSQL_TYPE_STRING ?
|
||||
default_charset() : &my_charset_numeric,
|
||||
field_type() == MYSQL_TYPE_STRING ?
|
||||
DERIVATION_COERCIBLE : DERIVATION_NUMERIC,
|
||||
MY_REPERTOIRE_ASCII);
|
||||
fix_char_length(char_length);
|
||||
}
|
||||
|
||||
String *Item_temporal_func::val_str(String *str)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
@ -2009,8 +1981,8 @@ void Item_func_from_unixtime::fix_length_and_dec()
|
||||
THD *thd= current_thd;
|
||||
thd->time_zone_used= 1;
|
||||
tz= thd->variables.time_zone;
|
||||
decimals= args[0]->decimals;
|
||||
Item_temporal_func::fix_length_and_dec();
|
||||
fix_attributes_datetime_not_fixed_dec(args[0]->decimals);
|
||||
maybe_null= true;
|
||||
}
|
||||
|
||||
|
||||
@ -2039,8 +2011,8 @@ bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime,
|
||||
|
||||
void Item_func_convert_tz::fix_length_and_dec()
|
||||
{
|
||||
decimals= args[0]->temporal_precision(MYSQL_TYPE_DATETIME);
|
||||
Item_temporal_func::fix_length_and_dec();
|
||||
fix_attributes_datetime(args[0]->temporal_precision(MYSQL_TYPE_DATETIME));
|
||||
maybe_null= true;
|
||||
}
|
||||
|
||||
|
||||
@ -2093,6 +2065,13 @@ void Item_date_add_interval::fix_length_and_dec()
|
||||
{
|
||||
enum_field_types arg0_field_type;
|
||||
|
||||
if (!args[0]->type_handler()->is_traditional_type())
|
||||
{
|
||||
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
|
||||
args[0]->type_handler()->name().ptr(),
|
||||
"interval", func_name());
|
||||
return;
|
||||
}
|
||||
/*
|
||||
The field type for the result of an Item_datefunc is defined as
|
||||
follows:
|
||||
@ -2108,7 +2087,6 @@ void Item_date_add_interval::fix_length_and_dec()
|
||||
(This is because you can't know if the string contains a DATE,
|
||||
MYSQL_TIME or DATETIME argument)
|
||||
*/
|
||||
set_handler_by_field_type(MYSQL_TYPE_STRING);
|
||||
arg0_field_type= args[0]->field_type();
|
||||
uint interval_dec= 0;
|
||||
if (int_type == INTERVAL_MICROSECOND ||
|
||||
@ -2121,30 +2099,47 @@ void Item_date_add_interval::fix_length_and_dec()
|
||||
if (arg0_field_type == MYSQL_TYPE_DATETIME ||
|
||||
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
|
||||
{
|
||||
decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec);
|
||||
set_handler_by_field_type(MYSQL_TYPE_DATETIME);
|
||||
uint dec= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME),
|
||||
interval_dec);
|
||||
set_handler(&type_handler_datetime);
|
||||
fix_attributes_datetime(dec);
|
||||
}
|
||||
else if (arg0_field_type == MYSQL_TYPE_DATE)
|
||||
{
|
||||
if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
|
||||
set_handler_by_field_type(arg0_field_type);
|
||||
{
|
||||
set_handler(&type_handler_newdate);
|
||||
fix_attributes_date();
|
||||
}
|
||||
else
|
||||
{
|
||||
decimals= interval_dec;
|
||||
set_handler_by_field_type(MYSQL_TYPE_DATETIME);
|
||||
set_handler(&type_handler_datetime2);
|
||||
fix_attributes_datetime(interval_dec);
|
||||
}
|
||||
}
|
||||
else if (arg0_field_type == MYSQL_TYPE_TIME)
|
||||
{
|
||||
decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME), interval_dec);
|
||||
uint dec= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME), interval_dec);
|
||||
if (int_type >= INTERVAL_DAY && int_type != INTERVAL_YEAR_MONTH)
|
||||
set_handler_by_field_type(arg0_field_type);
|
||||
else
|
||||
set_handler_by_field_type(MYSQL_TYPE_DATETIME);
|
||||
{
|
||||
set_handler(&type_handler_time2);
|
||||
fix_attributes_time(dec);
|
||||
}
|
||||
else
|
||||
decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec);
|
||||
Item_temporal_func::fix_length_and_dec();
|
||||
{
|
||||
set_handler(&type_handler_datetime2);
|
||||
fix_attributes_datetime(dec);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint dec= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME),
|
||||
interval_dec);
|
||||
set_handler(&type_handler_string);
|
||||
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
|
||||
fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
|
||||
}
|
||||
maybe_null= true;
|
||||
}
|
||||
|
||||
|
||||
@ -2649,8 +2644,15 @@ err:
|
||||
void Item_func_add_time::fix_length_and_dec()
|
||||
{
|
||||
enum_field_types arg0_field_type;
|
||||
decimals= MY_MAX(args[0]->decimals, args[1]->decimals);
|
||||
|
||||
if (!args[0]->type_handler()->is_traditional_type() ||
|
||||
!args[1]->type_handler()->is_traditional_type())
|
||||
{
|
||||
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
|
||||
args[0]->type_handler()->name().ptr(),
|
||||
args[1]->type_handler()->name().ptr(), func_name());
|
||||
return;
|
||||
}
|
||||
/*
|
||||
The field type for the result of an Item_func_add_time function is defined
|
||||
as follows:
|
||||
@ -2661,24 +2663,32 @@ void Item_func_add_time::fix_length_and_dec()
|
||||
- Otherwise the result is MYSQL_TYPE_STRING
|
||||
*/
|
||||
|
||||
set_handler_by_field_type(MYSQL_TYPE_STRING);
|
||||
arg0_field_type= args[0]->field_type();
|
||||
if (arg0_field_type == MYSQL_TYPE_DATE ||
|
||||
arg0_field_type == MYSQL_TYPE_DATETIME ||
|
||||
arg0_field_type == MYSQL_TYPE_TIMESTAMP ||
|
||||
is_date)
|
||||
{
|
||||
set_handler_by_field_type(MYSQL_TYPE_DATETIME);
|
||||
decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME),
|
||||
uint dec= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME),
|
||||
args[1]->temporal_precision(MYSQL_TYPE_TIME));
|
||||
set_handler(&type_handler_datetime2);
|
||||
fix_attributes_datetime(dec);
|
||||
}
|
||||
else if (arg0_field_type == MYSQL_TYPE_TIME)
|
||||
{
|
||||
set_handler_by_field_type(MYSQL_TYPE_TIME);
|
||||
decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME),
|
||||
uint dec= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME),
|
||||
args[1]->temporal_precision(MYSQL_TYPE_TIME));
|
||||
set_handler(&type_handler_time2);
|
||||
fix_attributes_time(dec);
|
||||
}
|
||||
Item_temporal_func::fix_length_and_dec();
|
||||
else
|
||||
{
|
||||
uint dec= MY_MAX(args[0]->decimals, args[1]->decimals);
|
||||
set_handler(&type_handler_string);
|
||||
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
|
||||
fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
|
||||
}
|
||||
maybe_null= true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3169,6 +3179,14 @@ get_date_time_result_type(const char *format, uint length)
|
||||
|
||||
void Item_func_str_to_date::fix_length_and_dec()
|
||||
{
|
||||
if (!args[0]->type_handler()->is_traditional_type() ||
|
||||
!args[1]->type_handler()->is_traditional_type())
|
||||
{
|
||||
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
|
||||
args[0]->type_handler()->name().ptr(),
|
||||
args[1]->type_handler()->name().ptr(), func_name());
|
||||
return;
|
||||
}
|
||||
if (agg_arg_charsets(collation, args, 2, MY_COLL_ALLOW_CONV, 1))
|
||||
return;
|
||||
if (collation.collation->mbminlen > 1)
|
||||
@ -3180,8 +3198,10 @@ void Item_func_str_to_date::fix_length_and_dec()
|
||||
#endif
|
||||
}
|
||||
|
||||
set_handler_by_field_type(MYSQL_TYPE_DATETIME);
|
||||
decimals= TIME_SECOND_PART_DIGITS;
|
||||
maybe_null= true;
|
||||
set_handler(&type_handler_datetime2);
|
||||
fix_attributes_datetime(TIME_SECOND_PART_DIGITS);
|
||||
|
||||
if ((const_item= args[1]->const_item()))
|
||||
{
|
||||
char format_buff[64];
|
||||
@ -3195,25 +3215,29 @@ void Item_func_str_to_date::fix_length_and_dec()
|
||||
get_date_time_result_type(format->ptr(), format->length());
|
||||
switch (cached_format_type) {
|
||||
case DATE_ONLY:
|
||||
set_handler_by_field_type(MYSQL_TYPE_DATE);
|
||||
set_handler(&type_handler_newdate);
|
||||
fix_attributes_date();
|
||||
break;
|
||||
case TIME_MICROSECOND:
|
||||
decimals= 6;
|
||||
/* fall through */
|
||||
set_handler(&type_handler_time2);
|
||||
fix_attributes_time(TIME_SECOND_PART_DIGITS);
|
||||
break;
|
||||
case TIME_ONLY:
|
||||
set_handler_by_field_type(MYSQL_TYPE_TIME);
|
||||
set_handler(&type_handler_time2);
|
||||
fix_attributes_time(0);
|
||||
break;
|
||||
case DATE_TIME_MICROSECOND:
|
||||
decimals= 6;
|
||||
/* fall through */
|
||||
set_handler(&type_handler_datetime2);
|
||||
fix_attributes_datetime(TIME_SECOND_PART_DIGITS);
|
||||
break;
|
||||
case DATE_TIME:
|
||||
set_handler_by_field_type(MYSQL_TYPE_DATETIME);
|
||||
set_handler(&type_handler_datetime2);
|
||||
fix_attributes_datetime(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cached_timestamp_type= mysql_type_to_time_type(field_type());
|
||||
Item_temporal_func::fix_length_and_dec();
|
||||
}
|
||||
|
||||
|
||||
|
@ -31,16 +31,6 @@ enum date_time_format_types
|
||||
};
|
||||
|
||||
|
||||
static inline uint
|
||||
mysql_temporal_int_part_length(enum enum_field_types mysql_type)
|
||||
{
|
||||
static uint max_time_type_width[5]=
|
||||
{ MAX_DATETIME_WIDTH, MAX_DATETIME_WIDTH, MAX_DATE_WIDTH,
|
||||
MAX_DATETIME_WIDTH, MIN_TIME_WIDTH };
|
||||
return max_time_type_width[mysql_type_to_time_type(mysql_type)+2];
|
||||
}
|
||||
|
||||
|
||||
bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval);
|
||||
|
||||
class Item_func_period_add :public Item_int_func
|
||||
@ -531,7 +521,6 @@ public:
|
||||
|
||||
class Item_temporal_func: public Item_func
|
||||
{
|
||||
sql_mode_t sql_mode;
|
||||
public:
|
||||
Item_temporal_func(THD *thd): Item_func(thd) {}
|
||||
Item_temporal_func(THD *thd, Item *a): Item_func(thd, a) {}
|
||||
@ -549,7 +538,6 @@ public:
|
||||
{ return tmp_table_field_from_field_type(table, false, false); }
|
||||
int save_in_field(Field *field, bool no_conversions)
|
||||
{ return save_date_in_field(field, no_conversions); }
|
||||
void fix_length_and_dec();
|
||||
};
|
||||
|
||||
|
||||
@ -557,22 +545,20 @@ public:
|
||||
Abstract class for functions returning TIME, DATE, DATETIME or string values,
|
||||
whose data type depends on parameters and is set at fix_fields time.
|
||||
*/
|
||||
class Item_temporal_hybrid_func: public Item_temporal_func,
|
||||
public Type_handler_hybrid_field_type
|
||||
class Item_temporal_hybrid_func: public Item_hybrid_func
|
||||
{
|
||||
protected:
|
||||
String ascii_buf; // Conversion buffer
|
||||
public:
|
||||
Item_temporal_hybrid_func(THD *thd, Item *a, Item *b):
|
||||
Item_temporal_func(thd, a, b) {}
|
||||
const Type_handler *type_handler() const
|
||||
{ return Type_handler_hybrid_field_type::type_handler(); }
|
||||
enum_field_types field_type() const
|
||||
{ return Type_handler_hybrid_field_type::field_type(); }
|
||||
enum Item_result result_type () const
|
||||
{ return Type_handler_hybrid_field_type::result_type(); }
|
||||
enum Item_result cmp_type () const
|
||||
{ return Type_handler_hybrid_field_type::cmp_type(); }
|
||||
Item_hybrid_func(thd, a, b) {}
|
||||
|
||||
longlong val_int() { return val_int_from_date(); }
|
||||
double val_real() { return val_real_from_date(); }
|
||||
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date)= 0;
|
||||
my_decimal *val_decimal(my_decimal *decimal_value)
|
||||
{ return val_decimal_from_date(decimal_value); }
|
||||
|
||||
/**
|
||||
Fix the returned timestamp to match field_type(),
|
||||
which is important for val_str().
|
||||
@ -599,6 +585,11 @@ public:
|
||||
Item_datefunc(THD *thd, Item *a): Item_temporal_func(thd, a) { }
|
||||
Item_datefunc(THD *thd, Item *a, Item *b): Item_temporal_func(thd, a, b) { }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
fix_attributes_date();
|
||||
maybe_null= (arg_count > 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -635,6 +626,7 @@ public:
|
||||
Item_func_curtime(THD *thd, uint dec): Item_timefunc(thd), last_query_id(0)
|
||||
{ decimals= dec; }
|
||||
bool fix_fields(THD *, Item **);
|
||||
void fix_length_and_dec() { fix_attributes_time(decimals); }
|
||||
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
|
||||
/*
|
||||
Abstract method that defines which time zone is used for conversion.
|
||||
@ -722,6 +714,7 @@ public:
|
||||
Item_func_now(THD *thd, uint dec): Item_datetimefunc(thd), last_query_id(0)
|
||||
{ decimals= dec; }
|
||||
bool fix_fields(THD *, Item **);
|
||||
void fix_length_and_dec() { fix_attributes_datetime(decimals); }
|
||||
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
|
||||
virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)=0;
|
||||
bool check_vcol_func_processor(void *arg)
|
||||
@ -886,8 +879,8 @@ public:
|
||||
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
decimals= MY_MIN(args[0]->decimals, TIME_SECOND_PART_DIGITS);
|
||||
Item_timefunc::fix_length_and_dec();
|
||||
fix_attributes_time(args[0]->decimals);
|
||||
maybe_null= true;
|
||||
}
|
||||
const char *func_name() const { return "sec_to_time"; }
|
||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||
@ -1066,11 +1059,12 @@ public:
|
||||
Item_temporal_typecast(THD *thd, Item *a): Item_temporal_func(thd, a) {}
|
||||
virtual const char *cast_type() const = 0;
|
||||
void print(String *str, enum_query_type query_type);
|
||||
void fix_length_and_dec_generic()
|
||||
void fix_length_and_dec_generic(uint int_part_len)
|
||||
{
|
||||
if (decimals == NOT_FIXED_DEC)
|
||||
decimals= args[0]->temporal_precision(field_type());
|
||||
Item_temporal_func::fix_length_and_dec();
|
||||
fix_attributes_temporal(int_part_len, decimals);
|
||||
maybe_null= true;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1163,9 +1157,10 @@ public:
|
||||
const char *func_name() const { return "timediff"; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME),
|
||||
uint dec= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME),
|
||||
args[1]->temporal_precision(MYSQL_TYPE_TIME));
|
||||
Item_timefunc::fix_length_and_dec();
|
||||
fix_attributes_time(dec);
|
||||
maybe_null= true;
|
||||
}
|
||||
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
|
||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||
@ -1180,8 +1175,8 @@ public:
|
||||
{}
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
decimals= MY_MIN(args[2]->decimals, TIME_SECOND_PART_DIGITS);
|
||||
Item_timefunc::fix_length_and_dec();
|
||||
fix_attributes_time(args[2]->decimals);
|
||||
maybe_null= true;
|
||||
}
|
||||
const char *func_name() const { return "maketime"; }
|
||||
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
|
||||
|
@ -26,14 +26,10 @@ static Type_handler_long type_handler_long;
|
||||
static Type_handler_int24 type_handler_int24;
|
||||
static Type_handler_year type_handler_year;
|
||||
static Type_handler_time type_handler_time;
|
||||
static Type_handler_time2 type_handler_time2;
|
||||
static Type_handler_date type_handler_date;
|
||||
static Type_handler_newdate type_handler_newdate;
|
||||
static Type_handler_datetime2 type_handler_datetime2;
|
||||
static Type_handler_timestamp type_handler_timestamp;
|
||||
static Type_handler_timestamp2 type_handler_timestamp2;
|
||||
static Type_handler_olddecimal type_handler_olddecimal;
|
||||
static Type_handler_string type_handler_string;
|
||||
static Type_handler_tiny_blob type_handler_tiny_blob;
|
||||
static Type_handler_medium_blob type_handler_medium_blob;
|
||||
static Type_handler_long_blob type_handler_long_blob;
|
||||
@ -42,6 +38,7 @@ static Type_handler_blob type_handler_blob;
|
||||
|
||||
Type_handler_null type_handler_null;
|
||||
Type_handler_row type_handler_row;
|
||||
Type_handler_string type_handler_string;
|
||||
Type_handler_varchar type_handler_varchar;
|
||||
Type_handler_longlong type_handler_longlong;
|
||||
Type_handler_float type_handler_float;
|
||||
@ -52,6 +49,10 @@ Type_handler_bit type_handler_bit;
|
||||
Type_handler_enum type_handler_enum;
|
||||
Type_handler_set type_handler_set;
|
||||
|
||||
Type_handler_time2 type_handler_time2;
|
||||
Type_handler_newdate type_handler_newdate;
|
||||
Type_handler_datetime2 type_handler_datetime2;
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
Type_handler_geometry type_handler_geometry;
|
||||
#endif
|
||||
@ -1346,7 +1347,7 @@ bool Type_handler_date_common::
|
||||
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
func->set_attributes_temporal(MAX_DATE_WIDTH, 0);
|
||||
func->fix_attributes_date();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2688,7 +2689,7 @@ bool Type_handler_numeric::
|
||||
bool Type_handler::
|
||||
Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const
|
||||
{
|
||||
item->fix_length_and_dec_generic();
|
||||
item->fix_length_and_dec_generic(MIN_TIME_WIDTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2696,7 +2697,7 @@ bool Type_handler::
|
||||
bool Type_handler::
|
||||
Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const
|
||||
{
|
||||
item->fix_length_and_dec_generic();
|
||||
item->fix_length_and_dec_generic(MAX_DATE_WIDTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2705,7 +2706,7 @@ bool Type_handler::
|
||||
Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item)
|
||||
const
|
||||
{
|
||||
item->fix_length_and_dec_generic();
|
||||
item->fix_length_and_dec_generic(MAX_DATETIME_WIDTH);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
@ -23,6 +23,8 @@
|
||||
|
||||
#include "mysqld.h"
|
||||
#include "sql_array.h"
|
||||
#include "sql_const.h"
|
||||
#include "my_time.h"
|
||||
|
||||
class Field;
|
||||
class Item;
|
||||
@ -261,6 +263,54 @@ public:
|
||||
max_length= char_to_byte_length_safe(max_char_length_arg,
|
||||
collation.collation->mbmaxlen);
|
||||
}
|
||||
void fix_char_length_temporal_not_fixed_dec(uint int_part_length, uint dec)
|
||||
{
|
||||
uint char_length= int_part_length;
|
||||
if ((decimals= dec))
|
||||
{
|
||||
if (decimals == NOT_FIXED_DEC)
|
||||
char_length+= TIME_SECOND_PART_DIGITS + 1;
|
||||
else
|
||||
{
|
||||
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
|
||||
char_length+= decimals + 1;
|
||||
}
|
||||
}
|
||||
fix_char_length(char_length);
|
||||
}
|
||||
void fix_attributes_temporal_not_fixed_dec(uint int_part_length, uint dec)
|
||||
{
|
||||
collation.set_numeric();
|
||||
unsigned_flag= 0;
|
||||
fix_char_length_temporal_not_fixed_dec(int_part_length, dec);
|
||||
}
|
||||
void fix_attributes_time_not_fixed_dec(uint dec)
|
||||
{
|
||||
fix_attributes_temporal_not_fixed_dec(MIN_TIME_WIDTH, dec);
|
||||
}
|
||||
void fix_attributes_datetime_not_fixed_dec(uint dec)
|
||||
{
|
||||
fix_attributes_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
|
||||
}
|
||||
void fix_attributes_temporal(uint int_part_length, uint dec)
|
||||
{
|
||||
collation.set_numeric();
|
||||
unsigned_flag= 0;
|
||||
decimals= MY_MIN(dec, TIME_SECOND_PART_DIGITS);
|
||||
max_length= decimals + int_part_length + (dec ? 1 : 0);
|
||||
}
|
||||
void fix_attributes_date()
|
||||
{
|
||||
fix_attributes_temporal(MAX_DATE_WIDTH, 0);
|
||||
}
|
||||
void fix_attributes_time(uint dec)
|
||||
{
|
||||
fix_attributes_temporal(MIN_TIME_WIDTH, dec);
|
||||
}
|
||||
void fix_attributes_datetime(uint dec)
|
||||
{
|
||||
fix_attributes_temporal(MAX_DATETIME_WIDTH, dec);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1585,6 +1635,7 @@ public:
|
||||
|
||||
extern Type_handler_row type_handler_row;
|
||||
extern Type_handler_null type_handler_null;
|
||||
extern Type_handler_string type_handler_string;
|
||||
extern Type_handler_varchar type_handler_varchar;
|
||||
extern Type_handler_longlong type_handler_longlong;
|
||||
extern Type_handler_float type_handler_float;
|
||||
@ -1596,6 +1647,10 @@ extern Type_handler_bit type_handler_bit;
|
||||
extern Type_handler_enum type_handler_enum;
|
||||
extern Type_handler_set type_handler_set;
|
||||
|
||||
extern Type_handler_time2 type_handler_time2;
|
||||
extern Type_handler_newdate type_handler_newdate;
|
||||
extern Type_handler_datetime2 type_handler_datetime2;
|
||||
|
||||
|
||||
class Type_aggregator
|
||||
{
|
||||
|
Reference in New Issue
Block a user