mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-12770 Add Type_handler::decimal_precision() + MDEV-12769
This patch for MDEV-12770 is also fixing: MDEV-12769 Arithmetic operators with temporal types create excessive column types
This commit is contained in:
@ -950,10 +950,10 @@ sec_to_time(1) + 0, from_unixtime(1) + 0;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`now() - now()` bigint(21) NOT NULL,
|
||||
`curtime() - curtime()` bigint(12) NOT NULL,
|
||||
`sec_to_time(1) + 0` bigint(12) DEFAULT NULL,
|
||||
`from_unixtime(1) + 0` bigint(21) DEFAULT NULL
|
||||
`now() - now()` bigint(16) NOT NULL,
|
||||
`curtime() - curtime()` int(9) NOT NULL,
|
||||
`sec_to_time(1) + 0` int(9) DEFAULT NULL,
|
||||
`from_unixtime(1) + 0` bigint(16) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
SELECT SEC_TO_TIME(3300000);
|
||||
@ -2054,11 +2054,11 @@ SEC_TO_TIME(1.123456)+0.1,
|
||||
SEC_TO_TIME(1.1234567)+0.1;
|
||||
SHOW COLUMNS FROM t1;
|
||||
Field Type Null Key Default Extra
|
||||
SEC_TO_TIME(1)+0.1 decimal(12,1) YES NULL
|
||||
SEC_TO_TIME(1.1)+0.1 decimal(13,1) YES NULL
|
||||
SEC_TO_TIME(1.12)+0.1 decimal(14,2) YES NULL
|
||||
SEC_TO_TIME(1.123456)+0.1 decimal(18,6) YES NULL
|
||||
SEC_TO_TIME(1.1234567)+0.1 decimal(18,6) YES NULL
|
||||
SEC_TO_TIME(1)+0.1 decimal(9,1) YES NULL
|
||||
SEC_TO_TIME(1.1)+0.1 decimal(9,1) YES NULL
|
||||
SEC_TO_TIME(1.12)+0.1 decimal(10,2) YES NULL
|
||||
SEC_TO_TIME(1.123456)+0.1 decimal(14,6) YES NULL
|
||||
SEC_TO_TIME(1.1234567)+0.1 decimal(14,6) YES NULL
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a DATE) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES ('2005-05-04'),('2000-02-23');
|
||||
|
@ -131,18 +131,18 @@ show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`a` datetime(4) DEFAULT NULL,
|
||||
`a+0` decimal(25,4) DEFAULT NULL,
|
||||
`a-1` decimal(25,4) DEFAULT NULL,
|
||||
`a*1` decimal(25,4) DEFAULT NULL,
|
||||
`a/2` decimal(28,8) DEFAULT NULL
|
||||
`a+0` decimal(19,4) DEFAULT NULL,
|
||||
`a-1` decimal(19,4) DEFAULT NULL,
|
||||
`a*1` decimal(19,4) DEFAULT NULL,
|
||||
`a/2` decimal(22,8) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
show create table t3;
|
||||
Table Create Table
|
||||
t3 CREATE TABLE `t3` (
|
||||
`max(a)` datetime(4) DEFAULT NULL,
|
||||
`min(a)` datetime(4) DEFAULT NULL,
|
||||
`sum(a)` decimal(46,4) DEFAULT NULL,
|
||||
`avg(a)` decimal(28,8) DEFAULT NULL
|
||||
`sum(a)` decimal(40,4) DEFAULT NULL,
|
||||
`avg(a)` decimal(22,8) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1, t2, t3;
|
||||
create table t1 (f0_datetime datetime(0), f1_datetime datetime(1), f2_datetime datetime(2), f3_datetime datetime(3), f4_datetime datetime(4), f5_datetime datetime(5), f6_datetime datetime(6));
|
||||
|
@ -221,7 +221,7 @@ MAX(t0)+1
|
||||
101011
|
||||
SHOW COLUMNS FROM t2;
|
||||
Field Type Null Key Default Extra
|
||||
MAX(t0)+1 bigint(12) YES NULL
|
||||
MAX(t0)+1 int(9) YES NULL
|
||||
DROP TABLE t2,t1;
|
||||
CREATE TABLE t1 (t0 TIME);
|
||||
INSERT INTO t1 VALUES ('10:10:10');
|
||||
@ -234,7 +234,7 @@ MAX(t0)+1.1
|
||||
101011.1
|
||||
SHOW COLUMNS FROM t2;
|
||||
Field Type Null Key Default Extra
|
||||
MAX(t0)+1.1 decimal(12,1) YES NULL
|
||||
MAX(t0)+1.1 decimal(9,1) YES NULL
|
||||
DROP TABLE t2,t1;
|
||||
CREATE TABLE t1 (t0 TIME);
|
||||
INSERT INTO t1 VALUES ('10:10:10');
|
||||
@ -260,7 +260,7 @@ MAX(t1)+1
|
||||
101011.0
|
||||
SHOW COLUMNS FROM t2;
|
||||
Field Type Null Key Default Extra
|
||||
MAX(t1)+1 decimal(13,1) YES NULL
|
||||
MAX(t1)+1 decimal(9,1) YES NULL
|
||||
DROP TABLE t2,t1;
|
||||
CREATE TABLE t1 (t0 DATETIME);
|
||||
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
|
||||
@ -273,7 +273,7 @@ MAX(t0)+1
|
||||
20010101101011
|
||||
SHOW COLUMNS FROM t2;
|
||||
Field Type Null Key Default Extra
|
||||
MAX(t0)+1 bigint(21) YES NULL
|
||||
MAX(t0)+1 bigint(16) YES NULL
|
||||
DROP TABLE t2,t1;
|
||||
CREATE TABLE t1 (t0 DATETIME);
|
||||
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
|
||||
@ -286,7 +286,7 @@ MAX(t0)+1.1
|
||||
20010101101011.1
|
||||
SHOW COLUMNS FROM t2;
|
||||
Field Type Null Key Default Extra
|
||||
MAX(t0)+1.1 decimal(21,1) YES NULL
|
||||
MAX(t0)+1.1 decimal(16,1) YES NULL
|
||||
DROP TABLE t2,t1;
|
||||
CREATE TABLE t1 (t0 DATETIME);
|
||||
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
|
||||
@ -312,7 +312,7 @@ MAX(t1)+1
|
||||
20010101101011.0
|
||||
SHOW COLUMNS FROM t2;
|
||||
Field Type Null Key Default Extra
|
||||
MAX(t1)+1 decimal(22,1) YES NULL
|
||||
MAX(t1)+1 decimal(16,1) YES NULL
|
||||
DROP TABLE t2,t1;
|
||||
#
|
||||
# MDEV-4858 Wrong results for a huge unsigned value inserted into a TIME column
|
||||
|
@ -145,18 +145,18 @@ show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`a` time(4) DEFAULT NULL,
|
||||
`a+0` decimal(16,4) DEFAULT NULL,
|
||||
`a-1` decimal(16,4) DEFAULT NULL,
|
||||
`a*1` decimal(16,4) DEFAULT NULL,
|
||||
`a/2` decimal(19,8) DEFAULT NULL
|
||||
`a+0` decimal(12,4) DEFAULT NULL,
|
||||
`a-1` decimal(12,4) DEFAULT NULL,
|
||||
`a*1` decimal(12,4) DEFAULT NULL,
|
||||
`a/2` decimal(15,8) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
show create table t3;
|
||||
Table Create Table
|
||||
t3 CREATE TABLE `t3` (
|
||||
`max(a)` time(4) DEFAULT NULL,
|
||||
`min(a)` time(4) DEFAULT NULL,
|
||||
`sum(a)` decimal(37,4) DEFAULT NULL,
|
||||
`avg(a)` decimal(19,8) DEFAULT NULL
|
||||
`sum(a)` decimal(33,4) DEFAULT NULL,
|
||||
`avg(a)` decimal(15,8) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1, t2, t3;
|
||||
create table t1 (f0_time time(0), f1_time time(1), f2_time time(2), f3_time time(3), f4_time time(4), f5_time time(5), f6_time time(6));
|
||||
|
@ -131,18 +131,18 @@ show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`a` timestamp(4) NOT NULL DEFAULT current_timestamp(4) ON UPDATE current_timestamp(4),
|
||||
`a+0` decimal(25,4) NOT NULL,
|
||||
`a-1` decimal(25,4) NOT NULL,
|
||||
`a*1` decimal(25,4) NOT NULL,
|
||||
`a/2` decimal(28,8) DEFAULT NULL
|
||||
`a+0` decimal(19,4) NOT NULL,
|
||||
`a-1` decimal(19,4) NOT NULL,
|
||||
`a*1` decimal(19,4) NOT NULL,
|
||||
`a/2` decimal(22,8) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
show create table t3;
|
||||
Table Create Table
|
||||
t3 CREATE TABLE `t3` (
|
||||
`max(a)` timestamp(4) NULL DEFAULT NULL,
|
||||
`min(a)` timestamp(4) NULL DEFAULT NULL,
|
||||
`sum(a)` decimal(46,4) DEFAULT NULL,
|
||||
`avg(a)` decimal(28,8) DEFAULT NULL
|
||||
`sum(a)` decimal(40,4) DEFAULT NULL,
|
||||
`avg(a)` decimal(22,8) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1, t2, t3;
|
||||
create table t1 (f0_timestamp timestamp(0), f1_timestamp timestamp(1), f2_timestamp timestamp(2), f3_timestamp timestamp(3), f4_timestamp timestamp(4), f5_timestamp timestamp(5), f6_timestamp timestamp(6));
|
||||
|
22
sql/item.cc
22
sql/item.cc
@ -541,28 +541,6 @@ Item::Item(THD *thd, Item *item):
|
||||
}
|
||||
|
||||
|
||||
uint Item::decimal_precision() const
|
||||
{
|
||||
Item_result restype= result_type();
|
||||
|
||||
if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
|
||||
{
|
||||
uint prec=
|
||||
my_decimal_length_to_precision(max_char_length(), decimals,
|
||||
unsigned_flag);
|
||||
return MY_MIN(prec, DECIMAL_MAX_PRECISION);
|
||||
}
|
||||
uint res= max_char_length();
|
||||
/*
|
||||
Return at least one decimal digit, even if Item::max_char_length()
|
||||
returned 0. This is important to avoid attempts to create fields of types
|
||||
INT(0) or DECIMAL(0,0) when converting NULL or empty strings to INT/DECIMAL:
|
||||
CREATE TABLE t1 AS SELECT CONVERT(NULL,SIGNED) AS a;
|
||||
*/
|
||||
return res ? MY_MIN(res, DECIMAL_MAX_PRECISION) : 1;
|
||||
}
|
||||
|
||||
|
||||
void Item::print_parenthesised(String *str, enum_query_type query_type,
|
||||
enum precedence parent_prec)
|
||||
{
|
||||
|
@ -1143,7 +1143,10 @@ public:
|
||||
inline uint float_length(uint decimals_par) const
|
||||
{ return decimals < FLOATING_POINT_DECIMALS ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
|
||||
/* Returns total number of decimal digits */
|
||||
virtual uint decimal_precision() const;
|
||||
virtual uint decimal_precision() const
|
||||
{
|
||||
return type_handler()->Item_decimal_precision(this);
|
||||
}
|
||||
/* Returns the number of integer part digits only */
|
||||
inline int decimal_int_part() const
|
||||
{ return my_decimal_int_part(decimal_precision(), decimals); }
|
||||
|
@ -3953,6 +3953,62 @@ uint Type_handler_temporal_result::
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
uint Type_handler_string_result::Item_decimal_precision(const Item *item) const
|
||||
{
|
||||
uint res= item->max_char_length();
|
||||
/*
|
||||
Return at least one decimal digit, even if Item::max_char_length()
|
||||
returned 0. This is important to avoid attempts to create fields of types
|
||||
INT(0) or DECIMAL(0,0) when converting NULL or empty strings to INT/DECIMAL:
|
||||
CREATE TABLE t1 AS SELECT CONVERT(NULL,SIGNED) AS a;
|
||||
*/
|
||||
return res ? MY_MIN(res, DECIMAL_MAX_PRECISION) : 1;
|
||||
}
|
||||
|
||||
uint Type_handler_real_result::Item_decimal_precision(const Item *item) const
|
||||
{
|
||||
uint res= item->max_char_length();
|
||||
return res ? MY_MIN(res, DECIMAL_MAX_PRECISION) : 1;
|
||||
}
|
||||
|
||||
uint Type_handler_decimal_result::Item_decimal_precision(const Item *item) const
|
||||
{
|
||||
uint prec= my_decimal_length_to_precision(item->max_char_length(),
|
||||
item->decimals,
|
||||
item->unsigned_flag);
|
||||
return MY_MIN(prec, DECIMAL_MAX_PRECISION);
|
||||
}
|
||||
|
||||
uint Type_handler_int_result::Item_decimal_precision(const Item *item) const
|
||||
{
|
||||
uint prec= my_decimal_length_to_precision(item->max_char_length(),
|
||||
item->decimals,
|
||||
item->unsigned_flag);
|
||||
return MY_MIN(prec, DECIMAL_MAX_PRECISION);
|
||||
}
|
||||
|
||||
uint Type_handler_time_common::Item_decimal_precision(const Item *item) const
|
||||
{
|
||||
return 7 + MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
|
||||
}
|
||||
|
||||
uint Type_handler_date_common::Item_decimal_precision(const Item *item) const
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
uint Type_handler_datetime_common::Item_decimal_precision(const Item *item) const
|
||||
{
|
||||
return 14 + MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
|
||||
}
|
||||
|
||||
uint Type_handler_timestamp_common::Item_decimal_precision(const Item *item) const
|
||||
{
|
||||
return 14 + MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
bool Type_handler_real_result::
|
||||
subquery_type_allows_materialization(const Item *inner,
|
||||
const Item *outer) const
|
||||
|
@ -639,6 +639,7 @@ public:
|
||||
virtual uint Item_time_precision(Item *item) const;
|
||||
virtual uint Item_datetime_precision(Item *item) const;
|
||||
virtual uint Item_decimal_scale(const Item *item) const;
|
||||
virtual uint Item_decimal_precision(const Item *item) const= 0;
|
||||
/*
|
||||
Returns how many digits a divisor adds into a division result.
|
||||
See Item::divisor_precision_increment() in item.h for more comments.
|
||||
@ -935,6 +936,11 @@ public:
|
||||
DBUG_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
uint Item_decimal_precision(const Item *item) const
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
return DECIMAL_MAX_PRECISION;
|
||||
}
|
||||
bool Item_save_in_value(Item *item, st_value *value) const;
|
||||
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
|
||||
{
|
||||
@ -1156,6 +1162,7 @@ public:
|
||||
void sortlength(THD *thd,
|
||||
const Type_std_attributes *item,
|
||||
SORT_FIELD_ATTR *attr) const;
|
||||
uint Item_decimal_precision(const Item *item) const;
|
||||
bool Item_save_in_value(Item *item, st_value *value) const;
|
||||
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
|
||||
Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const;
|
||||
@ -1217,6 +1224,7 @@ public:
|
||||
const Type_std_attributes *item,
|
||||
SORT_FIELD_ATTR *attr) const;
|
||||
uint32 max_display_length(const Item *item) const;
|
||||
uint Item_decimal_precision(const Item *item) const;
|
||||
bool Item_save_in_value(Item *item, st_value *value) const;
|
||||
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
|
||||
{
|
||||
@ -1278,6 +1286,7 @@ public:
|
||||
void sortlength(THD *thd,
|
||||
const Type_std_attributes *item,
|
||||
SORT_FIELD_ATTR *attr) const;
|
||||
uint Item_decimal_precision(const Item *item) const;
|
||||
bool Item_save_in_value(Item *item, st_value *value) const;
|
||||
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
|
||||
Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const;
|
||||
@ -1408,6 +1417,7 @@ public:
|
||||
{
|
||||
return Item_temporal_precision(item, false);
|
||||
}
|
||||
uint Item_decimal_precision(const Item *item) const;
|
||||
bool Item_save_in_value(Item *item, st_value *value) const;
|
||||
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
|
||||
{
|
||||
@ -1703,6 +1713,7 @@ public:
|
||||
{
|
||||
return Item_decimal_scale_with_seconds(item);
|
||||
}
|
||||
uint Item_decimal_precision(const Item *item) const;
|
||||
uint Item_divisor_precision_increment(const Item *item) const
|
||||
{
|
||||
return Item_divisor_precision_increment_with_seconds(item);
|
||||
@ -1780,6 +1791,7 @@ public:
|
||||
{
|
||||
return MYSQL_TIMESTAMP_DATE;
|
||||
}
|
||||
uint Item_decimal_precision(const Item *item) const;
|
||||
String *print_item_value(THD *thd, Item *item, String *str) const;
|
||||
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item **items, uint nitems) const;
|
||||
@ -1828,6 +1840,7 @@ public:
|
||||
{
|
||||
return Item_decimal_scale_with_seconds(item);
|
||||
}
|
||||
uint Item_decimal_precision(const Item *item) const;
|
||||
uint Item_divisor_precision_increment(const Item *item) const
|
||||
{
|
||||
return Item_divisor_precision_increment_with_seconds(item);
|
||||
@ -1889,6 +1902,7 @@ public:
|
||||
{
|
||||
return Item_decimal_scale_with_seconds(item);
|
||||
}
|
||||
uint Item_decimal_precision(const Item *item) const;
|
||||
uint Item_divisor_precision_increment(const Item *item) const
|
||||
{
|
||||
return Item_divisor_precision_increment_with_seconds(item);
|
||||
|
Reference in New Issue
Block a user