mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
lp:731124 Loss of precision on DISTINCT
many changes: * NOT_FIXED_DEC now create hires fields, not old ones. As a result, temp tables preserve microseconds (on DISTINCT, GROUP BY) * I_S tables force decimals=0 on temporal types (backward compatibility) * Item_func_coalesce calculates decimals for temporal types * no precision for TIME/DATETIME in CAST means 0, not NOT_FIXED_DEC * addtime/timediff calculate decimals from arguments (not NOT_FIXED_DEC) sql/field.h: NOT_FIXED_DEC now create hires fields, not old ones sql/item.h: force decimals=0 for I_S tables sql/item_cmpfunc.cc: Item_func_coalesce calculates decimals for temporal types sql/item_create.cc: no precision for TIME/DATETIME in CAST means 0, not NOT_FIXED_DEC sql/item_timefunc.cc: addtime calculates decimals from arguments (not NOT_FIXED_DEC) sql/item_timefunc.h: timediff calculates decimals from arguments (not NOT_FIXED_DEC)
This commit is contained in:
@@ -196,16 +196,16 @@ date format datetime
|
|||||||
0003-01-02 8:11:2.123456 %Y-%m-%d %H:%i:%S.%# 0003-01-02 08:11:02
|
0003-01-02 8:11:2.123456 %Y-%m-%d %H:%i:%S.%# 0003-01-02 08:11:02
|
||||||
03-01-02 8:11:2.123456 %Y-%m-%d %H:%i:%S.%# 2003-01-02 08:11:02
|
03-01-02 8:11:2.123456 %Y-%m-%d %H:%i:%S.%# 2003-01-02 08:11:02
|
||||||
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 2003-01-02 22:11:12
|
2003-01-02 10:11:12 PM %Y-%m-%d %h:%i:%S %p 2003-01-02 22:11:12
|
||||||
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12.123450
|
2003-01-02 01:11:12.12345AM %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 01:11:12
|
||||||
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.123450
|
2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12
|
||||||
2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.123450
|
2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12
|
||||||
2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12
|
2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12
|
||||||
10:20:10 %H:%i:%s 0000-00-00 10:20:10
|
10:20:10 %H:%i:%s 0000-00-00 10:20:10
|
||||||
10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10
|
10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10
|
||||||
10:20:10 %T 0000-00-00 10:20:10
|
10:20:10 %T 0000-00-00 10:20:10
|
||||||
10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10
|
10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10
|
||||||
10:20:10AM %r 0000-00-00 10:20:10
|
10:20:10AM %r 0000-00-00 10:20:10
|
||||||
10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000
|
10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10
|
||||||
15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58
|
15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58
|
||||||
15 September 2001 %d %M %Y 2001-09-15 00:00:00
|
15 September 2001 %d %M %Y 2001-09-15 00:00:00
|
||||||
15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00
|
15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00
|
||||||
@@ -487,7 +487,7 @@ str_to_date(a,b)
|
|||||||
create table t2 select str_to_date(a,b) from t1;
|
create table t2 select str_to_date(a,b) from t1;
|
||||||
describe t2;
|
describe t2;
|
||||||
Field Type Null Key Default Extra
|
Field Type Null Key Default Extra
|
||||||
str_to_date(a,b) datetime YES NULL
|
str_to_date(a,b) datetime(6) YES NULL
|
||||||
select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f") as f1,
|
select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f") as f1,
|
||||||
str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S") as f2,
|
str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S") as f2,
|
||||||
str_to_date("2003-01-02", "%Y-%m-%d") as f3,
|
str_to_date("2003-01-02", "%Y-%m-%d") as f3,
|
||||||
|
@@ -805,3 +805,16 @@ a
|
|||||||
2010-10-10
|
2010-10-10
|
||||||
20101010
|
20101010
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
create table t1 (f1 varchar(40));
|
||||||
|
insert into t1 values ('2010-10-10 00:00:00.0001'),('2010-10-10 00:00:00.0002'),('2010-10-10 00:00:00.0003');
|
||||||
|
select time(f1) from t1 ;
|
||||||
|
time(f1)
|
||||||
|
00:00:00.000100
|
||||||
|
00:00:00.000200
|
||||||
|
00:00:00.000300
|
||||||
|
select distinct time(f1) from t1 ;
|
||||||
|
time(f1)
|
||||||
|
00:00:00.000100
|
||||||
|
00:00:00.000200
|
||||||
|
00:00:00.000300
|
||||||
|
drop table t1;
|
||||||
|
@@ -195,17 +195,17 @@ time("1997-12-31 23:59:59.000001") as f9;
|
|||||||
describe t1;
|
describe t1;
|
||||||
Field Type Null Key Default Extra
|
Field Type Null Key Default Extra
|
||||||
f1 date YES NULL
|
f1 date YES NULL
|
||||||
f2 datetime YES NULL
|
f2 datetime(6) YES NULL
|
||||||
f3 time YES NULL
|
f3 time(6) YES NULL
|
||||||
f4 time YES NULL
|
f4 time(6) YES NULL
|
||||||
f5 time YES NULL
|
f5 time(6) YES NULL
|
||||||
f6 time YES NULL
|
f6 time YES NULL
|
||||||
f7 datetime YES NULL
|
f7 datetime(6) YES NULL
|
||||||
f8 date YES NULL
|
f8 date YES NULL
|
||||||
f9 time YES NULL
|
f9 time(6) YES NULL
|
||||||
select * from t1;
|
select * from t1;
|
||||||
f1 f2 f3 f4 f5 f6 f7 f8 f9
|
f1 f2 f3 f4 f5 f6 f7 f8 f9
|
||||||
1997-01-01 1998-01-02 01:01:00 49:01:01 46:58:57 -24:00:00 10:11:12 2001-12-01 01:01:01 1997-12-31 23:59:59
|
1997-01-01 1998-01-02 01:01:00.000003 49:01:01.000001 46:58:57.999999 8275:29:36.710655 10:11:12 2001-12-01 01:01:01.000000 1997-12-31 23:59:59.000001
|
||||||
create table test(t1 datetime, t2 time, t3 time, t4 datetime);
|
create table test(t1 datetime, t2 time, t3 time, t4 datetime);
|
||||||
insert into test values
|
insert into test values
|
||||||
('2001-01-01 01:01:01', '01:01:01', null, '2001-02-01 01:01:01'),
|
('2001-01-01 01:01:01', '01:01:01', null, '2001-02-01 01:01:01'),
|
||||||
@@ -230,8 +230,8 @@ SELECT TIMEDIFF(t1, t4) As ttt, TIMEDIFF(t2, t3) As qqq,
|
|||||||
TIMEDIFF(t3, t2) As eee, TIMEDIFF(t2, t4) As rrr from test;
|
TIMEDIFF(t3, t2) As eee, TIMEDIFF(t2, t4) As rrr from test;
|
||||||
ttt qqq eee rrr
|
ttt qqq eee rrr
|
||||||
-744:00:00 NULL NULL NULL
|
-744:00:00 NULL NULL NULL
|
||||||
838:59:59.999999 22:58:58 -22:58:58 NULL
|
838:59:59 22:58:58 -22:58:58 NULL
|
||||||
-838:59:59.999999 -22:58:58 22:58:58 NULL
|
-838:59:59 -22:58:58 22:58:58 NULL
|
||||||
NULL 26:02:02 -26:02:02 NULL
|
NULL 26:02:02 -26:02:02 NULL
|
||||||
00:00:00 -26:02:02 26:02:02 NULL
|
00:00:00 -26:02:02 26:02:02 NULL
|
||||||
NULL NULL NULL NULL
|
NULL NULL NULL NULL
|
||||||
|
@@ -37,7 +37,7 @@ Table Create Table
|
|||||||
t1 CREATE TABLE `t1` (
|
t1 CREATE TABLE `t1` (
|
||||||
`sec_to_time(12345)` time DEFAULT NULL,
|
`sec_to_time(12345)` time DEFAULT NULL,
|
||||||
`sec_to_time(12345.6789)` time(4) DEFAULT NULL,
|
`sec_to_time(12345.6789)` time(4) DEFAULT NULL,
|
||||||
`sec_to_time(1234567e-2)` time DEFAULT NULL,
|
`sec_to_time(1234567e-2)` time(6) DEFAULT NULL,
|
||||||
`now()` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
`now()` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
`curtime(0)` time NOT NULL DEFAULT '00:00:00',
|
`curtime(0)` time NOT NULL DEFAULT '00:00:00',
|
||||||
`utc_timestamp(1)` datetime(1) NOT NULL DEFAULT '0000-00-00 00:00:00.0',
|
`utc_timestamp(1)` datetime(1) NOT NULL DEFAULT '0000-00-00 00:00:00.0',
|
||||||
@@ -52,7 +52,7 @@ t1 CREATE TABLE `t1` (
|
|||||||
select * from t1;
|
select * from t1;
|
||||||
sec_to_time(12345) 03:25:45
|
sec_to_time(12345) 03:25:45
|
||||||
sec_to_time(12345.6789) 03:25:45.6789
|
sec_to_time(12345.6789) 03:25:45.6789
|
||||||
sec_to_time(1234567e-2) 03:25:45
|
sec_to_time(1234567e-2) 03:25:45.670000
|
||||||
now() 2011-01-01 01:01:01
|
now() 2011-01-01 01:01:01
|
||||||
curtime(0) 01:01:01
|
curtime(0) 01:01:01
|
||||||
utc_timestamp(1) 2010-12-31 22:01:01.1
|
utc_timestamp(1) 2010-12-31 22:01:01.1
|
||||||
|
@@ -624,3 +624,12 @@ select * from t1 where a = DATE('2010-10-10');
|
|||||||
select distinct a from t1 where a = DATE('2010-10-10');
|
select distinct a from t1 where a = DATE('2010-10-10');
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# lp:731124 Loss of precision on DISTINCT
|
||||||
|
#
|
||||||
|
create table t1 (f1 varchar(40));
|
||||||
|
insert into t1 values ('2010-10-10 00:00:00.0001'),('2010-10-10 00:00:00.0002'),('2010-10-10 00:00:00.0003');
|
||||||
|
select time(f1) from t1 ;
|
||||||
|
select distinct time(f1) from t1 ;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
27
sql/field.h
27
sql/field.h
@@ -1501,12 +1501,13 @@ new_Field_timestamp(uchar *ptr, uchar *null_ptr, uchar null_bit,
|
|||||||
enum Field::utype unireg_check, const char *field_name,
|
enum Field::utype unireg_check, const char *field_name,
|
||||||
TABLE_SHARE *share, uint dec, CHARSET_INFO *cs)
|
TABLE_SHARE *share, uint dec, CHARSET_INFO *cs)
|
||||||
{
|
{
|
||||||
if (dec==0 || dec == NOT_FIXED_DEC)
|
if (dec==0)
|
||||||
return new Field_timestamp(ptr, MAX_DATETIME_WIDTH, null_ptr, null_bit,
|
return new Field_timestamp(ptr, MAX_DATETIME_WIDTH, null_ptr, null_bit,
|
||||||
unireg_check, field_name, share, cs);
|
unireg_check, field_name, share, cs);
|
||||||
else
|
if (dec == NOT_FIXED_DEC)
|
||||||
return new Field_timestamp_hires(ptr, null_ptr, null_bit, unireg_check,
|
dec= MAX_DATETIME_PRECISION;
|
||||||
field_name, share, dec, cs);
|
return new Field_timestamp_hires(ptr, null_ptr, null_bit, unireg_check,
|
||||||
|
field_name, share, dec, cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Field_time *
|
static inline Field_time *
|
||||||
@@ -1514,12 +1515,13 @@ new_Field_time(uchar *ptr, uchar *null_ptr, uchar null_bit,
|
|||||||
enum Field::utype unireg_check, const char *field_name,
|
enum Field::utype unireg_check, const char *field_name,
|
||||||
uint dec, CHARSET_INFO *cs)
|
uint dec, CHARSET_INFO *cs)
|
||||||
{
|
{
|
||||||
if (dec == 0 || dec == NOT_FIXED_DEC)
|
if (dec == 0)
|
||||||
return new Field_time(ptr, MIN_TIME_WIDTH, null_ptr, null_bit,
|
return new Field_time(ptr, MIN_TIME_WIDTH, null_ptr, null_bit,
|
||||||
unireg_check, field_name, cs);
|
unireg_check, field_name, cs);
|
||||||
else
|
if (dec == NOT_FIXED_DEC)
|
||||||
return new Field_time_hires(ptr, null_ptr, null_bit,
|
dec= MAX_DATETIME_PRECISION;
|
||||||
unireg_check, field_name, dec, cs);
|
return new Field_time_hires(ptr, null_ptr, null_bit,
|
||||||
|
unireg_check, field_name, dec, cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Field_datetime *
|
static inline Field_datetime *
|
||||||
@@ -1527,12 +1529,13 @@ new_Field_datetime(uchar *ptr, uchar *null_ptr, uchar null_bit,
|
|||||||
enum Field::utype unireg_check,
|
enum Field::utype unireg_check,
|
||||||
const char *field_name, uint dec, CHARSET_INFO *cs)
|
const char *field_name, uint dec, CHARSET_INFO *cs)
|
||||||
{
|
{
|
||||||
if (dec == 0 || dec == NOT_FIXED_DEC)
|
if (dec == 0)
|
||||||
return new Field_datetime(ptr, MAX_DATETIME_WIDTH, null_ptr, null_bit,
|
return new Field_datetime(ptr, MAX_DATETIME_WIDTH, null_ptr, null_bit,
|
||||||
unireg_check, field_name, cs);
|
unireg_check, field_name, cs);
|
||||||
else
|
if (dec == NOT_FIXED_DEC)
|
||||||
return new Field_datetime_hires(ptr, null_ptr, null_bit,
|
dec= MAX_DATETIME_PRECISION;
|
||||||
unireg_check, field_name, dec, cs);
|
return new Field_datetime_hires(ptr, null_ptr, null_bit,
|
||||||
|
unireg_check, field_name, dec, cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Field_string :public Field_longstr {
|
class Field_string :public Field_longstr {
|
||||||
|
@@ -2075,7 +2075,7 @@ public:
|
|||||||
enum_field_types field_type_arg)
|
enum_field_types field_type_arg)
|
||||||
:Item_partition_func_safe_string(name_arg, length_arg, &my_charset_bin),
|
:Item_partition_func_safe_string(name_arg, length_arg, &my_charset_bin),
|
||||||
date_time_field_type(field_type_arg)
|
date_time_field_type(field_type_arg)
|
||||||
{ }
|
{ decimals= 0; }
|
||||||
enum_field_types field_type() const { return date_time_field_type; }
|
enum_field_types field_type() const { return date_time_field_type; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -2920,6 +2920,13 @@ 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(&hybrid_type, args, arg_count);
|
||||||
|
Item_result cmp_type;
|
||||||
|
agg_cmp_type(&cmp_type, args, arg_count);
|
||||||
|
if (cmp_type == TIME_RESULT)
|
||||||
|
{
|
||||||
|
count_real_length();
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (hybrid_type) {
|
switch (hybrid_type) {
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
count_only_length();
|
count_only_length();
|
||||||
|
@@ -5091,7 +5091,7 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
len= NOT_FIXED_DEC;
|
len= 0;
|
||||||
|
|
||||||
if (cast_type == ITEM_CAST_TIME)
|
if (cast_type == ITEM_CAST_TIME)
|
||||||
res= new (thd->mem_root) Item_time_typecast(a, len);
|
res= new (thd->mem_root) Item_time_typecast(a, len);
|
||||||
|
@@ -2379,7 +2379,7 @@ void Item_func_add_time::fix_length_and_dec()
|
|||||||
{
|
{
|
||||||
enum_field_types arg0_field_type;
|
enum_field_types arg0_field_type;
|
||||||
max_length= MAX_DATETIME_WIDTH;
|
max_length= MAX_DATETIME_WIDTH;
|
||||||
decimals= NOT_FIXED_DEC;
|
decimals= max(args[0]->decimals, args[1]->decimals);
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -765,7 +765,7 @@ public:
|
|||||||
const char *func_name() const { return "timediff"; }
|
const char *func_name() const { return "timediff"; }
|
||||||
void fix_length_and_dec()
|
void fix_length_and_dec()
|
||||||
{
|
{
|
||||||
decimals= NOT_FIXED_DEC;
|
decimals= max(args[0]->decimals, args[1]->decimals);
|
||||||
Item_timefunc::fix_length_and_dec();
|
Item_timefunc::fix_length_and_dec();
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user