maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #05729
merge for MySQL56 FSP data types
Hi Serg,
Please review the patch merging MySQL-5.6 fractional second precision
enabled data types.
Thanks.
=== modified file 'include/my_time.h'
--- include/my_time.h 2013-05-24 15:09:59 +0000
+++ include/my_time.h 2013-06-19 11:13:13 +0000
@@ -107,10 +107,37 @@ ulonglong TIME_to_ulonglong_time(const M
ulonglong TIME_to_ulonglong(const MYSQL_TIME *);
double TIME_to_double(const MYSQL_TIME *my_time);
+/** MySQL56 routines and macros **/
+#define MY_PACKED_TIME_GET_INT_PART(x) ((x) >> 24)
+#define MY_PACKED_TIME_GET_FRAC_PART(x) ((x) % (1LL << 24))
+#define MY_PACKED_TIME_MAKE(i, f) ((((longlong) (i)) << 24) + (f))
+#define MY_PACKED_TIME_MAKE_INT(i) ((((longlong) (i)) << 24))
+
+longlong TIME_to_longlong_datetime_packed(const MYSQL_TIME *);
+longlong TIME_to_longlong_time_packed(const MYSQL_TIME *);
+
+void TIME_from_longlong_datetime_packed(MYSQL_TIME *ltime, longlong nr);
+void TIME_from_longlong_time_packed(MYSQL_TIME *ltime, longlong nr);
+
+void my_datetime_packed_to_binary(longlong nr, uchar *ptr, uint dec);
+longlong my_datetime_packed_from_binary(const uchar *ptr, uint dec);
+uint my_datetime_binary_length(uint dec);
+
+void my_time_packed_to_binary(longlong nr, uchar *ptr, uint dec);
+longlong my_time_packed_from_binary(const uchar *ptr, uint dec);
+uint my_time_binary_length(uint dec);
+
+void my_timestamp_to_binary(const struct timeval *tm, uchar *ptr, uint dec);
+void my_timestamp_from_binary(struct timeval *tm, const uchar *ptr, uint dec);
+uint my_timestamp_binary_length(uint dec);
+/** End of MySQL routines and macros **/
+
longlong pack_time(MYSQL_TIME *my_time);
MYSQL_TIME *unpack_time(longlong packed, MYSQL_TIME *my_time);
int check_time_range(struct st_mysql_time *my_time, uint dec, int *warning);
+my_bool check_datetime_range(const MYSQL_TIME *ltime);
+
long calc_daynr(uint year,uint month,uint day);
uint calc_days_in_year(uint year);
@@ -163,6 +190,8 @@ int my_date_to_str(const MYSQL_TIME *l_t
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to, uint digits);
int my_TIME_to_str(const MYSQL_TIME *l_time, char *to, uint digits);
+int my_timeval_to_str(const struct timeval *tm, char *to, uint dec);
+
static inline longlong sec_part_shift(longlong second_part, uint digits)
{
return second_part / (longlong)log_10_int[TIME_SECOND_PART_DIGITS - digits];
=== modified file 'include/mysql.h.pp'
--- include/mysql.h.pp 2013-05-24 15:09:59 +0000
+++ include/mysql.h.pp 2013-06-18 10:35:35 +0000
@@ -49,6 +49,9 @@ enum enum_field_types { MYSQL_TYPE_DECIM
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
MYSQL_TYPE_BIT,
+ MYSQL_TYPE_TIMESTAMP2,
+ MYSQL_TYPE_DATETIME2,
+ MYSQL_TYPE_TIME2,
MYSQL_TYPE_NEWDECIMAL=246,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,
=== modified file 'include/mysql_com.h'
--- include/mysql_com.h 2013-06-06 19:32:29 +0000
+++ include/mysql_com.h 2013-06-18 10:35:35 +0000
@@ -400,6 +400,9 @@ enum enum_field_types { MYSQL_TYPE_DECIM
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
MYSQL_TYPE_BIT,
+ MYSQL_TYPE_TIMESTAMP2,
+ MYSQL_TYPE_DATETIME2,
+ MYSQL_TYPE_TIME2,
MYSQL_TYPE_NEWDECIMAL=246,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,
=== added file 'mysql-test/r/type_temporal_mysql56.result'
--- mysql-test/r/type_temporal_mysql56.result 1970-01-01 00:00:00 +0000
+++ mysql-test/r/type_temporal_mysql56.result 2013-06-19 08:01:51 +0000
@@ -0,0 +1,89 @@
+SHOW CREATE TABLE mysql56time;
+Table Create Table
+mysql56time CREATE TABLE `mysql56time` (
+ `t0` time DEFAULT NULL,
+ `t1` time(1) DEFAULT NULL,
+ `t2` time(2) DEFAULT NULL,
+ `t3` time(3) DEFAULT NULL,
+ `t4` time(4) DEFAULT NULL,
+ `t5` time(5) DEFAULT NULL,
+ `t6` time(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM mysql56time;;
+t0 838:59:59
+t1 838:59:59.0
+t2 838:59:59.00
+t3 838:59:59.000
+t4 838:59:59.0000
+t5 838:59:59.00000
+t6 838:59:59.000000
+t0 00:00:00
+t1 00:00:00.0
+t2 00:00:00.00
+t3 00:00:00.000
+t4 00:00:00.0000
+t5 00:00:00.00000
+t6 00:00:00.000000
+t0 -838:59:59
+t1 -838:59:59.0
+t2 -838:59:59.00
+t3 -838:59:59.000
+t4 -838:59:59.0000
+t5 -838:59:59.00000
+t6 -838:59:59.000000
+DROP TABLE mysql56time;
+SHOW CREATE TABLE mysql56datetime;
+Table Create Table
+mysql56datetime CREATE TABLE `mysql56datetime` (
+ `dt0` datetime DEFAULT NULL,
+ `dt1` datetime(1) DEFAULT NULL,
+ `dt2` datetime(2) DEFAULT NULL,
+ `dt3` datetime(3) DEFAULT NULL,
+ `dt4` datetime(4) DEFAULT NULL,
+ `dt5` datetime(5) DEFAULT NULL,
+ `dt6` datetime(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM mysql56datetime;;
+dt0 0000-00-00 00:00:00
+dt1 0000-00-00 00:00:00.0
+dt2 0000-00-00 00:00:00.00
+dt3 0000-00-00 00:00:00.000
+dt4 0000-00-00 00:00:00.0000
+dt5 0000-00-00 00:00:00.00000
+dt6 0000-00-00 00:00:00.000000
+dt0 9999-12-31 23:59:59
+dt1 9999-12-31 23:59:59.9
+dt2 9999-12-31 23:59:59.99
+dt3 9999-12-31 23:59:59.999
+dt4 9999-12-31 23:59:59.9999
+dt5 9999-12-31 23:59:59.99999
+dt6 9999-12-31 23:59:59.999999
+DROP TABLE mysql56datetime;
+SET TIME_ZONE='+00:00';
+SHOW CREATE TABLE mysql56timestamp;
+Table Create Table
+mysql56timestamp CREATE TABLE `mysql56timestamp` (
+ `ts0` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `ts1` timestamp(1) NOT NULL DEFAULT '0000-00-00 00:00:00.0',
+ `ts2` timestamp(2) NOT NULL DEFAULT '0000-00-00 00:00:00.00',
+ `ts3` timestamp(3) NOT NULL DEFAULT '0000-00-00 00:00:00.000',
+ `ts4` timestamp(4) NOT NULL DEFAULT '0000-00-00 00:00:00.0000',
+ `ts5` timestamp(5) NOT NULL DEFAULT '0000-00-00 00:00:00.00000',
+ `ts6` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM mysql56timestamp;;
+ts0 1970-01-01 00:00:01
+ts1 1970-01-01 00:00:01.0
+ts2 1970-01-01 00:00:01.00
+ts3 1970-01-01 00:00:01.000
+ts4 1970-01-01 00:00:01.0000
+ts5 1970-01-01 00:00:01.00000
+ts6 1970-01-01 00:00:01.000000
+ts0 2038-01-19 03:14:07
+ts1 2038-01-19 03:14:07.9
+ts2 2038-01-19 03:14:07.99
+ts3 2038-01-19 03:14:07.999
+ts4 2038-01-19 03:14:07.9999
+ts5 2038-01-19 03:14:07.99999
+ts6 2038-01-19 03:14:07.999999
+DROP TABLE mysql56timestamp;
=== added file 'mysql-test/std_data/mysql56datetime.MYD'
Binary files mysql-test/std_data/mysql56datetime.MYD 1970-01-01 00:00:00 +0000 and mysql-test/std_data/mysql56datetime.MYD 2013-06-19 07:53:28 +0000 differ
=== added file 'mysql-test/std_data/mysql56datetime.MYI'
Binary files mysql-test/std_data/mysql56datetime.MYI 1970-01-01 00:00:00 +0000 and mysql-test/std_data/mysql56datetime.MYI 2013-06-19 07:54:09 +0000 differ
=== added file 'mysql-test/std_data/mysql56datetime.frm'
Binary files mysql-test/std_data/mysql56datetime.frm 1970-01-01 00:00:00 +0000 and mysql-test/std_data/mysql56datetime.frm 2013-06-19 07:53:28 +0000 differ
=== added file 'mysql-test/std_data/mysql56time.MYD'
Binary files mysql-test/std_data/mysql56time.MYD 1970-01-01 00:00:00 +0000 and mysql-test/std_data/mysql56time.MYD 2013-06-19 07:53:28 +0000 differ
=== added file 'mysql-test/std_data/mysql56time.MYI'
Binary files mysql-test/std_data/mysql56time.MYI 1970-01-01 00:00:00 +0000 and mysql-test/std_data/mysql56time.MYI 2013-06-19 07:54:09 +0000 differ
=== added file 'mysql-test/std_data/mysql56time.frm'
Binary files mysql-test/std_data/mysql56time.frm 1970-01-01 00:00:00 +0000 and mysql-test/std_data/mysql56time.frm 2013-06-19 07:53:28 +0000 differ
=== added file 'mysql-test/std_data/mysql56timestamp.MYD'
Binary files mysql-test/std_data/mysql56timestamp.MYD 1970-01-01 00:00:00 +0000 and mysql-test/std_data/mysql56timestamp.MYD 2013-06-19 07:53:28 +0000 differ
=== added file 'mysql-test/std_data/mysql56timestamp.MYI'
Binary files mysql-test/std_data/mysql56timestamp.MYI 1970-01-01 00:00:00 +0000 and mysql-test/std_data/mysql56timestamp.MYI 2013-06-19 07:54:09 +0000 differ
=== added file 'mysql-test/std_data/mysql56timestamp.frm'
Binary files mysql-test/std_data/mysql56timestamp.frm 1970-01-01 00:00:00 +0000 and mysql-test/std_data/mysql56timestamp.frm 2013-06-19 07:53:28 +0000 differ
=== modified file 'mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result'
--- mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result 2013-04-15 08:55:27 +0000
+++ mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result 2013-06-18 10:35:35 +0000
@@ -2404,7 +2404,7 @@ BEGIN
### @28='1000:01:01' /* DATE meta=0 nullable=1 is_null=0 */
### @29=1000-01-01 00:00:00 /* DATETIME meta=0 nullable=1 is_null=0 */
### @30=75601 /* TIMESTAMP meta=0 nullable=0 is_null=0 */
-### @31='839:12:57' /* TIME meta=0 nullable=1 is_null=0 */
+### @31='-838:59:59' /* TIME meta=0 nullable=1 is_null=0 */
### @32=1901 /* YEAR meta=0 nullable=1 is_null=0 */
### @33='' /* STRING(1) meta=65025 nullable=1 is_null=0 */
### @34='' /* STRING(0) meta=65024 nullable=1 is_null=0 */
@@ -2766,7 +2766,7 @@ BEGIN
### @28='1000:01:01' /* DATE meta=0 nullable=1 is_null=0 */
### @29=1000-01-01 00:00:00 /* DATETIME meta=0 nullable=1 is_null=0 */
### @30=75601 /* TIMESTAMP meta=0 nullable=0 is_null=0 */
-### @31='839:12:57' /* TIME meta=0 nullable=1 is_null=0 */
+### @31='-838:59:59' /* TIME meta=0 nullable=1 is_null=0 */
### @32=1901 /* YEAR meta=0 nullable=1 is_null=0 */
### @33='' /* STRING(1) meta=65025 nullable=1 is_null=0 */
### @34='' /* STRING(0) meta=65024 nullable=1 is_null=0 */
@@ -3019,7 +3019,7 @@ BEGIN
### @28='1000:01:01' /* DATE meta=0 nullable=1 is_null=0 */
### @29=1000-01-01 00:00:00 /* DATETIME meta=0 nullable=1 is_null=0 */
### @30=75601 /* TIMESTAMP meta=0 nullable=0 is_null=0 */
-### @31='839:12:57' /* TIME meta=0 nullable=1 is_null=0 */
+### @31='-838:59:59' /* TIME meta=0 nullable=1 is_null=0 */
### @32=1901 /* YEAR meta=0 nullable=1 is_null=0 */
### @33='' /* STRING(1) meta=65025 nullable=1 is_null=0 */
### @34='' /* STRING(0) meta=65024 nullable=1 is_null=0 */
@@ -3551,7 +3551,7 @@ BEGIN
### @28='1000:01:01' /* DATE meta=0 nullable=1 is_null=0 */
### @29=1000-01-01 00:00:00 /* DATETIME meta=0 nullable=1 is_null=0 */
### @30=75601 /* TIMESTAMP meta=0 nullable=0 is_null=0 */
-### @31='839:12:57' /* TIME meta=0 nullable=1 is_null=0 */
+### @31='-838:59:59' /* TIME meta=0 nullable=1 is_null=0 */
### @32=1901 /* YEAR meta=0 nullable=1 is_null=0 */
### @33='' /* STRING(1) meta=65025 nullable=1 is_null=0 */
### @34='' /* STRING(0) meta=65024 nullable=1 is_null=0 */
=== modified file 'mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result'
--- mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result 2013-04-15 08:55:27 +0000
+++ mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result 2013-06-18 10:35:35 +0000
@@ -2404,7 +2404,7 @@ BEGIN
### @28='1000:01:01' /* DATE meta=0 nullable=1 is_null=0 */
### @29=1000-01-01 00:00:00 /* DATETIME meta=0 nullable=1 is_null=0 */
### @30=75601 /* TIMESTAMP meta=0 nullable=0 is_null=0 */
-### @31='839:12:57' /* TIME meta=0 nullable=1 is_null=0 */
+### @31='-838:59:59' /* TIME meta=0 nullable=1 is_null=0 */
### @32=1901 /* YEAR meta=0 nullable=1 is_null=0 */
### @33='' /* STRING(1) meta=65025 nullable=1 is_null=0 */
### @34='' /* STRING(0) meta=65024 nullable=1 is_null=0 */
@@ -2773,7 +2773,7 @@ BEGIN
### @28='1000:01:01' /* DATE meta=0 nullable=1 is_null=0 */
### @29=1000-01-01 00:00:00 /* DATETIME meta=0 nullable=1 is_null=0 */
### @30=75601 /* TIMESTAMP meta=0 nullable=0 is_null=0 */
-### @31='839:12:57' /* TIME meta=0 nullable=1 is_null=0 */
+### @31='-838:59:59' /* TIME meta=0 nullable=1 is_null=0 */
### @32=1901 /* YEAR meta=0 nullable=1 is_null=0 */
### @33='' /* STRING(1) meta=65025 nullable=1 is_null=0 */
### @34='' /* STRING(0) meta=65024 nullable=1 is_null=0 */
@@ -3028,7 +3028,7 @@ BEGIN
### @28='1000:01:01' /* DATE meta=0 nullable=1 is_null=0 */
### @29=1000-01-01 00:00:00 /* DATETIME meta=0 nullable=1 is_null=0 */
### @30=75601 /* TIMESTAMP meta=0 nullable=0 is_null=0 */
-### @31='839:12:57' /* TIME meta=0 nullable=1 is_null=0 */
+### @31='-838:59:59' /* TIME meta=0 nullable=1 is_null=0 */
### @32=1901 /* YEAR meta=0 nullable=1 is_null=0 */
### @33='' /* STRING(1) meta=65025 nullable=1 is_null=0 */
### @34='' /* STRING(0) meta=65024 nullable=1 is_null=0 */
@@ -3568,7 +3568,7 @@ BEGIN
### @28='1000:01:01' /* DATE meta=0 nullable=1 is_null=0 */
### @29=1000-01-01 00:00:00 /* DATETIME meta=0 nullable=1 is_null=0 */
### @30=75601 /* TIMESTAMP meta=0 nullable=0 is_null=0 */
-### @31='839:12:57' /* TIME meta=0 nullable=1 is_null=0 */
+### @31='-838:59:59' /* TIME meta=0 nullable=1 is_null=0 */
### @32=1901 /* YEAR meta=0 nullable=1 is_null=0 */
### @33='' /* STRING(1) meta=65025 nullable=1 is_null=0 */
### @34='' /* STRING(0) meta=65024 nullable=1 is_null=0 */
=== added file 'mysql-test/suite/rpl/r/rpl_temporal_mysql56.result'
--- mysql-test/suite/rpl/r/rpl_temporal_mysql56.result 1970-01-01 00:00:00 +0000
+++ mysql-test/suite/rpl/r/rpl_temporal_mysql56.result 2013-06-19 09:16:06 +0000
@@ -0,0 +1,84 @@
+include/master-slave.inc
+[connection master]
+SET TIME_ZONE='+00:00';
+SET TIME_ZONE='+00:00';
+INSERT INTO mysql56time VALUES ('01:01:01','01:01:01.1','01:01:01.11','01:01:01.111','01:01:01.1111','01:01:01.11111','01:01:01.111111');
+INSERT INTO mysql56datetime VALUES ('2001-01-01 01:01:01','2001-01-01 01:01:01.1','2001-01-01 01:01:01.11','2001-01-01 01:01:01.111','2001-01-01 01:01:01.1111','2001-01-01 01:01:01.11111','2001-01-01 01:01:01.111111');
+INSERT INTO mysql56timestamp VALUES ('2001-01-01 01:01:01','2001-01-01 01:01:01.1','2001-01-01 01:01:01.11','2001-01-01 01:01:01.111','2001-01-01 01:01:01.1111','2001-01-01 01:01:01.11111','2001-01-01 01:01:01.111111');
+SELECT * FROM mysql56time;;
+t0 838:59:59
+t1 838:59:59.0
+t2 838:59:59.00
+t3 838:59:59.000
+t4 838:59:59.0000
+t5 838:59:59.00000
+t6 838:59:59.000000
+t0 00:00:00
+t1 00:00:00.0
+t2 00:00:00.00
+t3 00:00:00.000
+t4 00:00:00.0000
+t5 00:00:00.00000
+t6 00:00:00.000000
+t0 -838:59:59
+t1 -838:59:59.0
+t2 -838:59:59.00
+t3 -838:59:59.000
+t4 -838:59:59.0000
+t5 -838:59:59.00000
+t6 -838:59:59.000000
+t0 01:01:01
+t1 01:01:01.1
+t2 01:01:01.11
+t3 01:01:01.111
+t4 01:01:01.1111
+t5 01:01:01.11111
+t6 01:01:01.111111
+SELECT * FROM mysql56datetime;;
+dt0 0000-00-00 00:00:00
+dt1 0000-00-00 00:00:00.0
+dt2 0000-00-00 00:00:00.00
+dt3 0000-00-00 00:00:00.000
+dt4 0000-00-00 00:00:00.0000
+dt5 0000-00-00 00:00:00.00000
+dt6 0000-00-00 00:00:00.000000
+dt0 9999-12-31 23:59:59
+dt1 9999-12-31 23:59:59.9
+dt2 9999-12-31 23:59:59.99
+dt3 9999-12-31 23:59:59.999
+dt4 9999-12-31 23:59:59.9999
+dt5 9999-12-31 23:59:59.99999
+dt6 9999-12-31 23:59:59.999999
+dt0 2001-01-01 01:01:01
+dt1 2001-01-01 01:01:01.1
+dt2 2001-01-01 01:01:01.11
+dt3 2001-01-01 01:01:01.111
+dt4 2001-01-01 01:01:01.1111
+dt5 2001-01-01 01:01:01.11111
+dt6 2001-01-01 01:01:01.111111
+SELECT * FROM mysql56timestamp;;
+ts0 1970-01-01 00:00:01
+ts1 1970-01-01 00:00:01.0
+ts2 1970-01-01 00:00:01.00
+ts3 1970-01-01 00:00:01.000
+ts4 1970-01-01 00:00:01.0000
+ts5 1970-01-01 00:00:01.00000
+ts6 1970-01-01 00:00:01.000000
+ts0 2038-01-19 03:14:07
+ts1 2038-01-19 03:14:07.9
+ts2 2038-01-19 03:14:07.99
+ts3 2038-01-19 03:14:07.999
+ts4 2038-01-19 03:14:07.9999
+ts5 2038-01-19 03:14:07.99999
+ts6 2038-01-19 03:14:07.999999
+ts0 2001-01-01 01:01:01
+ts1 2001-01-01 01:01:01.1
+ts2 2001-01-01 01:01:01.11
+ts3 2001-01-01 01:01:01.111
+ts4 2001-01-01 01:01:01.1111
+ts5 2001-01-01 01:01:01.11111
+ts6 2001-01-01 01:01:01.111111
+DROP TABLE mysql56time;
+DROP TABLE mysql56datetime;
+DROP TABLE mysql56timestamp;
+include/rpl_end.inc
=== added file 'mysql-test/suite/rpl/t/rpl_temporal_mysql56.test'
--- mysql-test/suite/rpl/t/rpl_temporal_mysql56.test 1970-01-01 00:00:00 +0000
+++ mysql-test/suite/rpl/t/rpl_temporal_mysql56.test 2013-06-19 09:14:52 +0000
@@ -0,0 +1,48 @@
+--source include/master-slave.inc
+
+connection master;
+SET TIME_ZONE='+00:00';
+let $MYSQLD_MASTER_DATADIR= `select @@datadir`;
+
+connection slave;
+SET TIME_ZONE='+00:00';
+let $MYSQLD_SLAVE_DATADIR= `select @@datadir`;
+
+--copy_file std_data/mysql56time.frm $MYSQLD_MASTER_DATADIR/test/mysql56time.frm
+--copy_file std_data/mysql56time.MYD $MYSQLD_MASTER_DATADIR/test/mysql56time.MYD
+--copy_file std_data/mysql56time.MYI $MYSQLD_MASTER_DATADIR/test/mysql56time.MYI
+--copy_file std_data/mysql56time.frm $MYSQLD_SLAVE_DATADIR/test/mysql56time.frm
+--copy_file std_data/mysql56time.MYD $MYSQLD_SLAVE_DATADIR/test/mysql56time.MYD
+--copy_file std_data/mysql56time.MYI $MYSQLD_SLAVE_DATADIR/test/mysql56time.MYI
+
+--copy_file std_data/mysql56datetime.frm $MYSQLD_MASTER_DATADIR/test/mysql56datetime.frm
+--copy_file std_data/mysql56datetime.MYD $MYSQLD_MASTER_DATADIR/test/mysql56datetime.MYD
+--copy_file std_data/mysql56datetime.MYI $MYSQLD_MASTER_DATADIR/test/mysql56datetime.MYI
+--copy_file std_data/mysql56datetime.frm $MYSQLD_SLAVE_DATADIR/test/mysql56datetime.frm
+--copy_file std_data/mysql56datetime.MYD $MYSQLD_SLAVE_DATADIR/test/mysql56datetime.MYD
+--copy_file std_data/mysql56datetime.MYI $MYSQLD_SLAVE_DATADIR/test/mysql56datetime.MYI
+
+--copy_file std_data/mysql56timestamp.frm $MYSQLD_MASTER_DATADIR/test/mysql56timestamp.frm
+--copy_file std_data/mysql56timestamp.MYD $MYSQLD_MASTER_DATADIR/test/mysql56timestamp.MYD
+--copy_file std_data/mysql56timestamp.MYI $MYSQLD_MASTER_DATADIR/test/mysql56timestamp.MYI
+--copy_file std_data/mysql56timestamp.frm $MYSQLD_SLAVE_DATADIR/test/mysql56timestamp.frm
+--copy_file std_data/mysql56timestamp.MYD $MYSQLD_SLAVE_DATADIR/test/mysql56timestamp.MYD
+--copy_file std_data/mysql56timestamp.MYI $MYSQLD_SLAVE_DATADIR/test/mysql56timestamp.MYI
+
+connection master;
+INSERT INTO mysql56time VALUES ('01:01:01','01:01:01.1','01:01:01.11','01:01:01.111','01:01:01.1111','01:01:01.11111','01:01:01.111111');
+INSERT INTO mysql56datetime VALUES ('2001-01-01 01:01:01','2001-01-01 01:01:01.1','2001-01-01 01:01:01.11','2001-01-01 01:01:01.111','2001-01-01 01:01:01.1111','2001-01-01 01:01:01.11111','2001-01-01 01:01:01.111111');
+INSERT INTO mysql56timestamp VALUES ('2001-01-01 01:01:01','2001-01-01 01:01:01.1','2001-01-01 01:01:01.11','2001-01-01 01:01:01.111','2001-01-01 01:01:01.1111','2001-01-01 01:01:01.11111','2001-01-01 01:01:01.111111');
+sync_slave_with_master;
+
+connection slave;
+--query_vertical SELECT * FROM mysql56time;
+--query_vertical SELECT * FROM mysql56datetime;
+--query_vertical SELECT * FROM mysql56timestamp;
+
+connection master;
+DROP TABLE mysql56time;
+DROP TABLE mysql56datetime;
+DROP TABLE mysql56timestamp;
+
+--source include/rpl_end.inc
=== added file 'mysql-test/t/type_temporal_mysql56.test'
--- mysql-test/t/type_temporal_mysql56.test 1970-01-01 00:00:00 +0000
+++ mysql-test/t/type_temporal_mysql56.test 2013-06-19 09:01:02 +0000
@@ -0,0 +1,23 @@
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--copy_file std_data/mysql56time.frm $MYSQLD_DATADIR/test/mysql56time.frm
+--copy_file std_data/mysql56time.MYD $MYSQLD_DATADIR/test/mysql56time.MYD
+--copy_file std_data/mysql56time.MYI $MYSQLD_DATADIR/test/mysql56time.MYI
+SHOW CREATE TABLE mysql56time;
+--query_vertical SELECT * FROM mysql56time;
+DROP TABLE mysql56time;
+
+--copy_file std_data/mysql56datetime.frm $MYSQLD_DATADIR/test/mysql56datetime.frm
+--copy_file std_data/mysql56datetime.MYD $MYSQLD_DATADIR/test/mysql56datetime.MYD
+--copy_file std_data/mysql56datetime.MYI $MYSQLD_DATADIR/test/mysql56datetime.MYI
+SHOW CREATE TABLE mysql56datetime;
+--query_vertical SELECT * FROM mysql56datetime;
+DROP TABLE mysql56datetime;
+
+--copy_file std_data/mysql56timestamp.frm $MYSQLD_DATADIR/test/mysql56timestamp.frm
+--copy_file std_data/mysql56timestamp.MYD $MYSQLD_DATADIR/test/mysql56timestamp.MYD
+--copy_file std_data/mysql56timestamp.MYI $MYSQLD_DATADIR/test/mysql56timestamp.MYI
+SET TIME_ZONE='+00:00';
+SHOW CREATE TABLE mysql56timestamp;
+--query_vertical SELECT * FROM mysql56timestamp;
+DROP TABLE mysql56timestamp;
=== modified file 'sql-common/my_time.c'
--- sql-common/my_time.c 2013-04-07 12:00:16 +0000
+++ sql-common/my_time.c 2013-06-19 11:59:45 +0000
@@ -18,6 +18,7 @@
#include <my_time.h>
#include <m_string.h>
#include <m_ctype.h>
+#include <myisampack.h>
/* Windows version of localtime_r() is declared in my_ptrhead.h */
#include <my_pthread.h>
#include <mysqld_error.h>
@@ -203,6 +204,29 @@ static uint skip_digits(const char **str
return s - start;
}
+
+/**
+ Check datetime, date, or normalized time (i.e. time without days) range.
+ @param ltime Datetime value.
+ @returns
+ @retval FALSE on success
+ @retval TRUE on error
+*/
+my_bool check_datetime_range(const MYSQL_TIME *ltime)
+{
+ /*
+ In case of MYSQL_TIMESTAMP_TIME hour value can be up to TIME_MAX_HOUR.
+ In case of MYSQL_TIMESTAMP_DATETIME it cannot be bigger than 23.
+ */
+ return
+ ltime->year > 9999 || ltime->month > 12 || ltime->day > 31 ||
+ ltime->minute > 59 || ltime->second > 59 ||
+ ltime->second_part > TIME_MAX_SECOND_PART ||
+ (ltime->hour >
+ (ltime->time_type == MYSQL_TIMESTAMP_TIME ? TIME_MAX_HOUR : 23));
+}
+
+
/*
Convert a timestamp string to a MYSQL_TIME value.
@@ -332,9 +356,14 @@ str_to_datetime(const char *str, uint le
uint second_part;
const char *start= ++str;
*was_cut= get_digits(&second_part, &number_of_fields, &str, end, 6);
- if (str - start < 6)
- second_part*= log_10_int[6 - (str - start)];
- l_time->second_part= second_part;
+ if (number_of_fields == 7)
+ {
+ if (str - start < 6)
+ second_part*= log_10_int[6 - (str - start)];
+ l_time->second_part= second_part;
+ }
+ else
+ l_time->second_part= 0;
if (skip_digits(&str, end))
*was_cut= 1;
}
@@ -1101,6 +1130,27 @@ int my_TIME_to_str(const MYSQL_TIME *l_t
}
+/**
+ Print a timestamp with an optional fractional part: XXXXX[.YYYYY]
+
+ @param tm The timestamp value to print.
+ @param OUT to The string pointer to print at.
+ @param dec Precision, in the range 0..6.
+ @return The length of the result string.
+*/
+int my_timeval_to_str(const struct timeval *tm, char *to, uint dec)
+{
+ char *pos= to + sprintf(to, "%d", (int) tm->tv_sec);
+ if (dec)
+ {
+ *pos++= '.';
+ pos= fmt_number((uint) sec_part_shift(tm->tv_usec, dec), pos, dec);
+ }
+ *pos= '\0';
+ return (int) (pos - to);
+}
+
+
/*
Convert datetime value specified as number to broken-down TIME
representation and form value of DATETIME type as side-effect.
@@ -1346,6 +1396,432 @@ ulonglong TIME_to_ulonglong(const MYSQL_
return 0;
}
+
+/*** MySQL56 TIME low-level memory and disk representation routines ***/
+
+/*
+ In-memory format:
+
+ 1 bit sign (Used for sign, when on disk)
+ 1 bit unused (Reserved for wider hour range, e.g. for intervals)
+ 10 bit hour (0-836)
+ 6 bit minute (0-59)
+ 6 bit second (0-59)
+ 24 bits microseconds (0-999999)
+
+ Total: 48 bits = 6 bytes
+ Suhhhhhh.hhhhmmmm.mmssssss.ffffffff.ffffffff.ffffffff
+*/
+
+
+/**
+ Convert time value to MySQL56 numeric packed representation.
+
+ @param ltime The value to convert.
+ @return Numeric packed representation.
+*/
+longlong TIME_to_longlong_time_packed(const MYSQL_TIME *ltime)
+{
+ /* If month is 0, we mix day with hours: "1 00:10:10" -> "24:00:10" */
+ long hms= (((ltime->month ? 0 : ltime->day * 24) + ltime->hour) << 12) |
+ (ltime->minute << 6) | ltime->second;
+ longlong tmp= MY_PACKED_TIME_MAKE(hms, ltime->second_part);
+ return ltime->neg ? -tmp : tmp;
+}
+
+
+
+/**
+ Convert MySQL56 time packed numeric representation to time.
+
+ @param OUT ltime The MYSQL_TIME variable to set.
+ @param tmp The packed numeric representation.
+*/
+void TIME_from_longlong_time_packed(MYSQL_TIME *ltime, longlong tmp)
+{
+ long hms;
+ if ((ltime->neg= (tmp < 0)))
+ tmp= -tmp;
+ hms= MY_PACKED_TIME_GET_INT_PART(tmp);
+ ltime->year= (uint) 0;
+ ltime->month= (uint) 0;
+ ltime->day= (uint) 0;
+ ltime->hour= (uint) (hms >> 12) % (1 << 10); /* 10 bits starting at 12th */
+ ltime->minute= (uint) (hms >> 6) % (1 << 6); /* 6 bits starting at 6th */
+ ltime->second= (uint) hms % (1 << 6); /* 6 bits starting at 0th */
+ ltime->second_part= MY_PACKED_TIME_GET_FRAC_PART(tmp);
+ ltime->time_type= MYSQL_TIMESTAMP_TIME;
+}
+
+
+/**
+ Calculate binary size of MySQL56 packed numeric time representation.
+
+ @param dec Precision.
+*/
+uint my_time_binary_length(uint dec)
+{
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ return 3 + (dec + 1) / 2;
+}
+
+
+/*
+ On disk we convert from signed representation to unsigned
+ representation using TIMEF_OFS, so all values become binary comparable.
+*/
+#define TIMEF_OFS 0x800000000000LL
+#define TIMEF_INT_OFS 0x800000LL
+
+
+/**
+ Convert MySQL56 in-memory numeric time representation to on-disk representation
+
+ @param nr Value in packed numeric time format.
+ @param OUT ptr The buffer to put value at.
+ @param dec Precision.
+*/
+void my_time_packed_to_binary(longlong nr, uchar *ptr, uint dec)
+{
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ /* Make sure the stored value was previously properly rounded or truncated */
+ DBUG_ASSERT((MY_PACKED_TIME_GET_FRAC_PART(nr) %
+ (int) log_10_int[TIME_SECOND_PART_DIGITS - dec]) == 0);
+
+ switch (dec)
+ {
+ case 0:
+ default:
+ mi_int3store(ptr, TIMEF_INT_OFS + MY_PACKED_TIME_GET_INT_PART(nr));
+ break;
+
+ case 1:
+ case 2:
+ mi_int3store(ptr, TIMEF_INT_OFS + MY_PACKED_TIME_GET_INT_PART(nr));
+ ptr[3]= (unsigned char) (char) (MY_PACKED_TIME_GET_FRAC_PART(nr) / 10000);
+ break;
+
+ case 4:
+ case 3:
+ mi_int3store(ptr, TIMEF_INT_OFS + MY_PACKED_TIME_GET_INT_PART(nr));
+ mi_int2store(ptr + 3, MY_PACKED_TIME_GET_FRAC_PART(nr) / 100);
+ break;
+
+ case 5:
+ case 6:
+ mi_int6store(ptr, nr + TIMEF_OFS);
+ break;
+ }
+}
+
+
+/**
+ Convert MySQL56 on-disk time representation to in-memory packed numeric
+ representation.
+
+ @param ptr The pointer to read the value at.
+ @param dec Precision.
+ @return Packed numeric time representation.
+*/
+longlong my_time_packed_from_binary(const uchar *ptr, uint dec)
+{
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+
+ switch (dec)
+ {
+ case 0:
+ default:
+ {
+ longlong intpart= mi_uint3korr(ptr) - TIMEF_INT_OFS;
+ return MY_PACKED_TIME_MAKE_INT(intpart);
+ }
+ case 1:
+ case 2:
+ {
+ longlong intpart= mi_uint3korr(ptr) - TIMEF_INT_OFS;
+ int frac= (uint) ptr[3];
+ if (intpart < 0 && frac)
+ {
+ /*
+ Negative values are stored with reverse fractional part order,
+ for binary sort compatibility.
+
+ Disk value intpart frac Time value Memory value
+ 800000.00 0 0 00:00:00.00 0000000000.000000
+ 7FFFFF.FF -1 255 -00:00:00.01 FFFFFFFFFF.FFD8F0
+ 7FFFFF.9D -1 99 -00:00:00.99 FFFFFFFFFF.F0E4D0
+ 7FFFFF.00 -1 0 -00:00:01.00 FFFFFFFFFF.000000
+ 7FFFFE.FF -1 255 -00:00:01.01 FFFFFFFFFE.FFD8F0
+ 7FFFFE.F6 -2 246 -00:00:01.10 FFFFFFFFFE.FE7960
+
+ Formula to convert fractional part from disk format
+ (now stored in "frac" variable) to absolute value: "0x100 - frac".
+ To reconstruct in-memory value, we shift
+ to the next integer value and then substruct fractional part.
+ */
+ intpart++; /* Shift to the next integer value */
+ frac-= 0x100; /* -(0x100 - frac) */
+ }
+ return MY_PACKED_TIME_MAKE(intpart, frac * 10000);
+ }
+
+ case 3:
+ case 4:
+ {
+ longlong intpart= mi_uint3korr(ptr) - TIMEF_INT_OFS;
+ int frac= mi_uint2korr(ptr + 3);
+ if (intpart < 0 && frac)
+ {
+ /*
+ Fix reverse fractional part order: "0x10000 - frac".
+ See comments for FSP=1 and FSP=2 above.
+ */
+ intpart++; /* Shift to the next integer value */
+ frac-= 0x10000; /* -(0x10000-frac) */
+ }
+ return MY_PACKED_TIME_MAKE(intpart, frac * 100);
+ }
+
+ case 5:
+ case 6:
+ return ((longlong) mi_uint6korr(ptr)) - TIMEF_OFS;
+ }
+}
+
+
+/*** MySQL56 DATETIME low-level memory and disk representation routines ***/
+
+/*
+ 1 bit sign (used when on disk)
+ 17 bits year*13+month (year 0-9999, month 0-12)
+ 5 bits day (0-31)
+ 5 bits hour (0-23)
+ 6 bits minute (0-59)
+ 6 bits second (0-59)
+ 24 bits microseconds (0-999999)
+
+ Total: 64 bits = 8 bytes
+
+ SYYYYYYY.YYYYYYYY.YYdddddh.hhhhmmmm.mmssssss.ffffffff.ffffffff.ffffffff
+*/
+
+/**
+ Convert datetime to MySQL56 packed numeric datetime representation.
+ @param ltime The value to convert.
+ @return Packed numeric representation of ltime.
+*/
+longlong TIME_to_longlong_datetime_packed(const MYSQL_TIME *ltime)
+{
+ longlong ymd= ((ltime->year * 13 + ltime->month) << 5) | ltime->day;
+ longlong hms= (ltime->hour << 12) | (ltime->minute << 6) | ltime->second;
+ longlong tmp= MY_PACKED_TIME_MAKE(((ymd << 17) | hms), ltime->second_part);
+ DBUG_ASSERT(!check_datetime_range(ltime)); /* Make sure no overflow */
+ return ltime->neg ? -tmp : tmp;
+}
+
+
+/**
+ Convert MySQL56 packed numeric datetime representation to MYSQL_TIME.
+ @param OUT ltime The datetime variable to convert to.
+ @param tmp The packed numeric datetime value.
+*/
+void TIME_from_longlong_datetime_packed(MYSQL_TIME *ltime, longlong tmp)
+{
+ longlong ymd, hms;
+ longlong ymdhms, ym;
+ if ((ltime->neg= (tmp < 0)))
+ tmp= -tmp;
+
+ ltime->second_part= MY_PACKED_TIME_GET_FRAC_PART(tmp);
+ ymdhms= MY_PACKED_TIME_GET_INT_PART(tmp);
+
+ ymd= ymdhms >> 17;
+ ym= ymd >> 5;
+ hms= ymdhms % (1 << 17);
+
+ ltime->day= ymd % (1 << 5);
+ ltime->month= ym % 13;
+ ltime->year= ym / 13;
+
+ ltime->second= hms % (1 << 6);
+ ltime->minute= (hms >> 6) % (1 << 6);
+ ltime->hour= (hms >> 12);
+
+ ltime->time_type= MYSQL_TIMESTAMP_DATETIME;
+}
+
+
+/**
+ Calculate binary size of MySQL56 packed datetime representation.
+ @param dec Precision.
+*/
+uint my_datetime_binary_length(uint dec)
+{
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ return 5 + (dec + 1) / 2;
+}
+
+
+/*
+ On disk we store as unsigned number with DATETIMEF_INT_OFS offset,
+ for HA_KETYPE_BINARY compatibilty purposes.
+*/
+#define DATETIMEF_INT_OFS 0x8000000000LL
+
+
+/**
+ Convert MySQL56 on-disk datetime representation
+ to in-memory packed numeric representation.
+
+ @param ptr The pointer to read value at.
+ @param dec Precision.
+ @return In-memory packed numeric datetime representation.
+*/
+longlong my_datetime_packed_from_binary(const uchar *ptr, uint dec)
+{
+ longlong intpart= mi_uint5korr(ptr) - DATETIMEF_INT_OFS;
+ int frac;
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ switch (dec)
+ {
+ case 0:
+ default:
+ return MY_PACKED_TIME_MAKE_INT(intpart);
+ case 1:
+ case 2:
+ frac= ((int) (signed char) ptr[5]) * 10000;
+ break;
+ case 3:
+ case 4:
+ frac= mi_sint2korr(ptr + 5) * 100;
+ break;
+ case 5:
+ case 6:
+ frac= mi_sint3korr(ptr + 5);
+ break;
+ }
+ return MY_PACKED_TIME_MAKE(intpart, frac);
+}
+
+
+/**
+ Store MySQL56 in-memory numeric packed datetime representation to disk.
+
+ @param nr In-memory numeric packed datetime representation.
+ @param OUT ptr The pointer to store at.
+ @param dec Precision, 1-6.
+*/
+void my_datetime_packed_to_binary(longlong nr, uchar *ptr, uint dec)
+{
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ /* The value being stored must have been properly rounded or truncated */
+ DBUG_ASSERT((MY_PACKED_TIME_GET_FRAC_PART(nr) %
+ (int) log_10_int[TIME_SECOND_PART_DIGITS - dec]) == 0);
+
+ mi_int5store(ptr, MY_PACKED_TIME_GET_INT_PART(nr) + DATETIMEF_INT_OFS);
+ switch (dec)
+ {
+ case 0:
+ default:
+ break;
+ case 1:
+ case 2:
+ ptr[5]= (unsigned char) (char) (MY_PACKED_TIME_GET_FRAC_PART(nr) / 10000);
+ break;
+ case 3:
+ case 4:
+ mi_int2store(ptr + 5, MY_PACKED_TIME_GET_FRAC_PART(nr) / 100);
+ break;
+ case 5:
+ case 6:
+ mi_int3store(ptr + 5, MY_PACKED_TIME_GET_FRAC_PART(nr));
+ }
+}
+
+
+/*** MySQL56 TIMESTAMP low-level memory and disk representation routines ***/
+
+/**
+ Calculate on-disk size of a timestamp value.
+
+ @param dec Precision.
+*/
+uint my_timestamp_binary_length(uint dec)
+{
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ return 4 + (dec + 1) / 2;
+}
+
+
+/**
+ Convert MySQL56 binary timestamp representation to in-memory representation.
+
+ @param OUT tm The variable to convert to.
+ @param ptr The pointer to read the value from.
+ @param dec Precision.
+*/
+void my_timestamp_from_binary(struct timeval *tm, const uchar *ptr, uint dec)
+{
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ tm->tv_sec= mi_uint4korr(ptr);
+ switch (dec)
+ {
+ case 0:
+ default:
+ tm->tv_usec= 0;
+ break;
+ case 1:
+ case 2:
+ tm->tv_usec= ((int) ptr[4]) * 10000;
+ break;
+ case 3:
+ case 4:
+ tm->tv_usec= mi_sint2korr(ptr + 4) * 100;
+ break;
+ case 5:
+ case 6:
+ tm->tv_usec= mi_sint3korr(ptr + 4);
+ }
+}
+
+
+/**
+ Convert MySQL56 in-memory timestamp representation to on-disk representation.
+
+ @param tm The value to convert.
+ @param OUT ptr The pointer to store the value to.
+ @param dec Precision.
+*/
+void my_timestamp_to_binary(const struct timeval *tm, uchar *ptr, uint dec)
+{
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ /* Stored value must have been previously properly rounded or truncated */
+ DBUG_ASSERT((tm->tv_usec %
+ (int) log_10_int[TIME_SECOND_PART_DIGITS - dec]) == 0);
+ mi_int4store(ptr, tm->tv_sec);
+ switch (dec)
+ {
+ case 0:
+ default:
+ break;
+ case 1:
+ case 2:
+ ptr[4]= (unsigned char) (char) (tm->tv_usec / 10000);
+ break;
+ case 3:
+ case 4:
+ mi_int2store(ptr + 4, tm->tv_usec / 100);
+ break;
+ /* Impossible second precision. Fall through */
+ case 5:
+ case 6:
+ mi_int3store(ptr + 4, tm->tv_usec);
+ }
+}
+
+/****************************************/
+
+
double TIME_to_double(const MYSQL_TIME *my_time)
{
double d= (double)TIME_to_ulonglong(my_time);
=== modified file 'sql/field.cc'
--- sql/field.cc 2013-06-06 19:32:29 +0000
+++ sql/field.cc 2013-06-19 04:51:38 +0000
@@ -87,6 +87,7 @@ const char field_separator=',';
#define FIELDTYPE_NUM (FIELDTYPE_TEAR_FROM + (255 - FIELDTYPE_TEAR_TO))
static inline int field_type2index (enum_field_types field_type)
{
+ field_type= real_type_to_type(field_type);
return (field_type < FIELDTYPE_TEAR_FROM ?
field_type :
((int)FIELDTYPE_TEAR_FROM) + (field_type - FIELDTYPE_TEAR_TO) - 1);
@@ -947,8 +948,10 @@ static enum_field_types field_types_merg
enum_field_types Field::field_type_merge(enum_field_types a,
enum_field_types b)
{
- DBUG_ASSERT(a < FIELDTYPE_TEAR_FROM || a > FIELDTYPE_TEAR_TO);
- DBUG_ASSERT(b < FIELDTYPE_TEAR_FROM || b > FIELDTYPE_TEAR_TO);
+ DBUG_ASSERT(real_type_to_type(a) < FIELDTYPE_TEAR_FROM ||
+ real_type_to_type(a) > FIELDTYPE_TEAR_TO);
+ DBUG_ASSERT(real_type_to_type(b) < FIELDTYPE_TEAR_FROM ||
+ real_type_to_type(b) > FIELDTYPE_TEAR_TO);
return field_types_merge_rules[field_type2index(a)]
[field_type2index(b)];
}
@@ -1042,8 +1045,8 @@ CPP_UNNAMED_NS_END
Item_result Field::result_merge_type(enum_field_types field_type)
{
- DBUG_ASSERT(field_type < FIELDTYPE_TEAR_FROM || field_type
- > FIELDTYPE_TEAR_TO);
+ DBUG_ASSERT(real_type_to_type(field_type) < FIELDTYPE_TEAR_FROM ||
+ real_type_to_type(field_type) > FIELDTYPE_TEAR_TO);
return field_types_result_type[field_type2index(field_type)];
}
@@ -1130,6 +1133,111 @@ void Field::make_sort_key(uchar *buff,ui
/**
+ @brief
+ Determine the relative position of the field value in a numeric interval
+
+ @details
+ The function returns a double number between 0.0 and 1.0 as the relative
+ position of the value of the this field in the numeric interval of [min,max].
+ If the value is not in the interval the the function returns 0.0 when
+ the value is less than min, and, 1.0 when the value is greater than max.
+
+ @param min value of the left end of the interval
+ @param max value of the right end of the interval
+
+ @return
+ relative position of the field value in the numeric interval [min,max]
+*/
+
+double Field::pos_in_interval_val_real(Field *min, Field *max)
+{
+ double n, d;
+ n= val_real() - min->val_real();
+ if (n < 0)
+ return 0.0;
+ d= max->val_real() - min->val_real();
+ if (d <= 0)
+ return 1.0;
+ return min(n/d, 1.0);
+}
+
+
+static
+inline ulonglong char_prefix_to_ulonglong(uchar *src)
+{
+ uint sz= sizeof(ulonglong);
+ for (uint i= 0; i < sz/2; i++)
+ {
+ uchar tmp= src[i];
+ src[i]= src[sz-1-i];
+ src[sz-1-i]= tmp;
+ }
+ return uint8korr(src);
+}
+
+
+/**
+ @brief
+ Determine the relative position of the field value in a string interval
+
+ @details
+ The function returns a double number between 0.0 and 1.0 as the relative
+ position of the value of the this field in the string interval of [min,max].
+ If the value is not in the interval the the function returns 0.0 when
+ the value is less than min, and, 1.0 when the value is greater than max.
+
+ @note
+ To calculate the relative position of the string value v in the interval
+ [min, max] the function first converts the beginning of these three
+ strings v, min, max into the strings that are used for byte comparison.
+ For each string not more sizeof(ulonglong) first bytes are taken
+ from the result of conversion. Then these bytes are interpreted as the
+ big-endian representation of an ulonglong integer. The values of these
+ integer numbers obtained for the strings v, min, max are used to calculate
+ the position of v in [min,max] in the same way is it's done for numeric
+ fields (see Field::pos_in_interval_val_real).
+
+ @todo
+ Improve the procedure for the case when min and max have the same
+ beginning
+
+ @param min value of the left end of the interval
+ @param max value of the right end of the interval
+
+ @return
+ relative position of the field value in the string interval [min,max]
+*/
+
+double Field::pos_in_interval_val_str(Field *min, Field *max, uint data_offset)
+{
+ uchar mp_prefix[sizeof(ulonglong)];
+ uchar minp_prefix[sizeof(ulonglong)];
+ uchar maxp_prefix[sizeof(ulonglong)];
+ ulonglong mp, minp, maxp;
+ my_strnxfrm(charset(), mp_prefix, sizeof(mp),
+ ptr + data_offset,
+ data_length());
+ my_strnxfrm(charset(), minp_prefix, sizeof(minp),
+ min->ptr + data_offset,
+ min->data_length());
+ my_strnxfrm(charset(), maxp_prefix, sizeof(maxp),
+ max->ptr + data_offset,
+ max->data_length());
+ mp= char_prefix_to_ulonglong(mp_prefix);
+ minp= char_prefix_to_ulonglong(minp_prefix);
+ maxp= char_prefix_to_ulonglong(maxp_prefix);
+ double n, d;
+ n= mp - minp;
+ if (n < 0)
+ return 0.0;
+ d= maxp - minp;
+ if (d <= 0)
+ return 1.0;
+ return min(n/d, 1.0);
+}
+
+
+/**
Numeric fields base class constructor.
*/
Field_num::Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
@@ -1275,36 +1383,6 @@ bool Field_num::get_int(CHARSET_INFO *cs
/**
- @brief
- Determine the relative position of the field value in a numeric interval
-
- @details
- The function returns a double number between 0.0 and 1.0 as the relative
- position of the value of the this field in the numeric interval of [min,max].
- If the value is not in the interval the the function returns 0.0 when
- the value is less than min, and, 1.0 when the value is greater than max.
-
- @param min value of the left end of the interval
- @param max value of the right end of the interval
-
- @return
- relative position of the field value in the numeric interval [min,max]
-*/
-
-double Field_num::pos_in_interval(Field *min, Field *max)
-{
- double n, d;
- n= val_real() - min->val_real();
- if (n < 0)
- return 0.0;
- d= max->val_real() - min->val_real();
- if (d <= 0)
- return 1.0;
- return min(n/d, 1.0);
-}
-
-
-/**
Process decimal library return codes and issue warnings for overflow and
truncation.
@@ -4485,13 +4563,12 @@ Field_timestamp::Field_timestamp(uchar *
uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg,
const char *field_name_arg,
- TABLE_SHARE *share,
- CHARSET_INFO *cs)
- :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, cs)
+ TABLE_SHARE *share)
+ :Field_temporal(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg)
{
/* For 4.0 MYD and 4.0 InnoDB compatibility */
- flags|= UNSIGNED_FLAG | BINARY_FLAG;
+ flags|= UNSIGNED_FLAG;
if (unireg_check != NONE)
{
/*
@@ -4690,6 +4767,16 @@ String *Field_timestamp::val_str(String
*to++= (char) ('0'+(char) (temp));
*to= 0;
val_buffer->set_charset(&my_charset_numeric);
+
+ if (uint dec= decimals())
+ {
+ ulong sec_part= (ulong) sec_part_shift(ltime.second_part, dec);
+ char *buf= const_cast<char*>(val_buffer->ptr() + MAX_DATETIME_WIDTH);
+ for (int i= dec; i > 0; i--, sec_part/= 10)
+ buf[i]= (char)(sec_part % 10) + '0';
+ buf[0]= '.';
+ buf[dec + 1]= 0;
+ }
return val_buffer;
}
@@ -4883,7 +4970,7 @@ my_time_t Field_timestamp_hires::get_tim
return mi_uint4korr(ptr);
}
-double Field_timestamp_hires::val_real(void)
+double Field_timestamp_with_dec::val_real(void)
{
MYSQL_TIME ltime;
if (get_date(<ime, TIME_NO_ZERO_DATE))
@@ -4894,31 +4981,14 @@ double Field_timestamp_hires::val_real(v
ltime.minute * 1e2 + ltime.second + ltime.second_part*1e-6;
}
-String *Field_timestamp_hires::val_str(String *val_buffer, String *val_ptr)
-{
- String *tmp= Field_timestamp::val_str(val_buffer, val_ptr);
- ulong sec_part= (ulong)read_bigendian(ptr+4, sec_part_bytes[dec]);
-
- if (tmp->ptr() == zero_timestamp)
- return tmp;
-
- char *buf= const_cast<char*>(tmp->ptr() + MAX_DATETIME_WIDTH);
- for (int i=dec; i>0; i--, sec_part/=10)
- buf[i]= (char)(sec_part % 10) + '0';
- buf[0]= '.';
- buf[dec+1]= 0;
- return tmp;
-}
-
-
-my_decimal *Field_timestamp_hires::val_decimal(my_decimal *d)
+my_decimal *Field_timestamp_with_dec::val_decimal(my_decimal *d)
{
MYSQL_TIME ltime;
get_date(<ime, 0);
return TIME_to_my_decimal(<ime, d);
}
-int Field_timestamp_hires::store_decimal(const my_decimal *d)
+int Field_timestamp_with_dec::store_decimal(const my_decimal *d)
{
ulonglong nr;
ulong sec_part;
@@ -4941,7 +5011,7 @@ int Field_timestamp_hires::store_decimal
return store_TIME_with_warning(thd, <ime, &str, error, tmp != -1);
}
-int Field_timestamp_hires::set_time()
+int Field_timestamp_with_dec::set_time()
{
THD *thd= get_thd();
set_notnull();
@@ -4949,7 +5019,7 @@ int Field_timestamp_hires::set_time()
return 0;
}
-bool Field_timestamp_hires::send_binary(Protocol *protocol)
+bool Field_timestamp_with_dec::send_binary(Protocol *protocol)
{
MYSQL_TIME ltime;
Field_timestamp::get_date(<ime, 0);
@@ -4970,23 +5040,85 @@ int Field_timestamp_hires::cmp(const uch
}
-void Field_timestamp_hires::sort_string(uchar *to,uint length)
-{
- DBUG_ASSERT(length == Field_timestamp_hires::pack_length());
- memcpy(to, ptr, length);
-}
-
uint32 Field_timestamp_hires::pack_length() const
{
return 4 + sec_part_bytes[dec];
}
-void Field_timestamp_hires::make_field(Send_field *field)
+void Field_timestamp_with_dec::make_field(Send_field *field)
{
Field::make_field(field);
field->decimals= dec;
}
+
+/*************************************************************
+** MySQL-5.6 compatible TIMESTAMP(N)
+**************************************************************/
+
+void Field_timestampf::store_TIME(my_time_t timestamp, ulong sec_part)
+{
+ struct timeval tm;
+ tm.tv_sec= timestamp;
+ tm.tv_usec= sec_part;
+ my_timeval_trunc(&tm, dec);
+ my_timestamp_to_binary(&tm, ptr, dec);
+}
+
+
+my_time_t Field_timestampf::get_timestamp(ulong *sec_part) const
+{
+ struct timeval tm;
+ my_timestamp_from_binary(&tm, ptr, dec);
+ *sec_part= tm.tv_usec;
+ return tm.tv_sec;
+}
+
+
+void Field_timestampf::sql_type(String &res) const
+{
+ if (!dec)
+ {
+ res.set_ascii(STRING_WITH_LEN("timestamp"));
+ return;
+ }
+ CHARSET_INFO *cs=res.charset();
+ res.length(cs->cset->snprintf(cs, (char*) res.ptr(), res.alloced_length(),
+ "timestamp(%u)", dec));
+}
+
+
+/*************************************************************/
+uint Field_temporal::is_equal(Create_field *new_field)
+{
+ return new_field->sql_type == real_type() &&
+ new_field->length == max_display_length();
+}
+
+
+void Field_temporal::set_warnings(MYSQL_ERROR::enum_warning_level trunc_level,
+ const ErrConv *str, int was_cut,
+ timestamp_type ts_type)
+{
+ /*
+ error code logic:
+ MYSQL_TIME_WARN_TRUNCATED means that the value was not a date/time at all.
+ it will be stored as zero date/time.
+ MYSQL_TIME_WARN_OUT_OF_RANGE means that the value was a date/time,
+ that is, it was parsed as such, but the value was invalid.
+
+ Also, MYSQL_TIME_WARN_TRUNCATED is used when storing a DATETIME in
+ a DATE field and non-zero time part is thrown away.
+ */
+ if (was_cut & MYSQL_TIME_WARN_TRUNCATED)
+ set_datetime_warning(trunc_level, WARN_DATA_TRUNCATED,
+ str, mysql_type_to_time_type(type()), 1);
+ if (was_cut & MYSQL_TIME_WARN_OUT_OF_RANGE)
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE,
+ str, mysql_type_to_time_type(type()), 1);
+}
+
+
/*
Store string into a date/time field
@@ -4997,21 +5129,21 @@ void Field_timestamp_hires::make_field(S
3 Datetime value that was cut (warning level NOTE)
This is used by opt_range.cc:get_mm_leaf().
*/
-int Field_temporal::store_TIME_with_warning(MYSQL_TIME *ltime,
- const ErrConv *str,
- int was_cut, int have_smth_to_conv)
+int Field_temporal_with_date::store_TIME_with_warning(MYSQL_TIME *ltime,
+ const ErrConv *str,
+ int was_cut,
+ int have_smth_to_conv)
{
MYSQL_ERROR::enum_warning_level trunc_level= MYSQL_ERROR::WARN_LEVEL_WARN;
int ret= 2;
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
- if (was_cut == 0 &&
- have_smth_to_conv == 0 &&
- mysql_type_to_time_type(type()) != MYSQL_TIMESTAMP_TIME) // special case: zero date
+ if (was_cut == 0 && have_smth_to_conv == 0) // special case: zero date
+ {
was_cut= MYSQL_TIME_WARN_OUT_OF_RANGE;
- else
- if (!have_smth_to_conv)
+ }
+ else if (!have_smth_to_conv)
{
bzero(ltime, sizeof(*ltime));
was_cut= MYSQL_TIME_WARN_TRUNCATED;
@@ -5025,39 +5157,13 @@ int Field_temporal::store_TIME_with_warn
was_cut|= MYSQL_TIME_WARN_TRUNCATED;
ret= 3;
}
- else if (!(was_cut & MYSQL_TIME_WARN_TRUNCATED) &&
- mysql_type_to_time_type(type()) == MYSQL_TIMESTAMP_TIME &&
- (ltime->year || ltime->month))
- {
- ltime->year= ltime->month= ltime->day= 0;
- trunc_level= MYSQL_ERROR::WARN_LEVEL_NOTE;
- was_cut|= MYSQL_TIME_WARN_TRUNCATED;
- ret= 3;
- }
-
- /*
- error code logic:
- MYSQL_TIME_WARN_TRUNCATED means that the value was not a date/time at all.
- it will be stored as zero date/time.
- MYSQL_TIME_WARN_OUT_OF_RANGE means that the value was a date/time,
- that is, it was parsed as such, but the value was invalid.
-
- Also, MYSQL_TIME_WARN_TRUNCATED is used when storing a DATETIME in
- a DATE field and non-zero time part is thrown away.
- */
- if (was_cut & MYSQL_TIME_WARN_TRUNCATED)
- set_datetime_warning(trunc_level, WARN_DATA_TRUNCATED,
- str, mysql_type_to_time_type(type()), 1);
- if (was_cut & MYSQL_TIME_WARN_OUT_OF_RANGE)
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE,
- str, mysql_type_to_time_type(type()), 1);
-
+ set_warnings(trunc_level, str, was_cut, mysql_type_to_time_type(type()));
store_TIME(ltime);
return was_cut ? ret : 0;
}
-int Field_temporal::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_temporal_with_date::store(const char *from, uint len, CHARSET_INFO *cs)
{
MYSQL_TIME ltime;
int error;
@@ -5075,7 +5181,7 @@ int Field_temporal::store(const char *fr
}
-int Field_temporal::store(double nr)
+int Field_temporal_with_date::store(double nr)
{
int error= 0;
MYSQL_TIME ltime;
@@ -5092,7 +5198,18 @@ int Field_temporal::store(double nr)
}
-int Field_temporal::store(longlong nr, bool unsigned_val)
+int Field_temporal::store_decimal(const my_decimal *d)
+{
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ double val;
+ /* TODO: use decimal2string? */
+ int err= warn_if_overflow(my_decimal2double(E_DEC_FATAL_ERROR &
+ ~E_DEC_OVERFLOW, d, &val));
+ return err | store(val);
+}
+
+
+int Field_temporal_with_date::store(longlong nr, bool unsigned_val)
{
int error;
MYSQL_TIME ltime;
@@ -5110,7 +5227,7 @@ int Field_temporal::store(longlong nr, b
}
-int Field_temporal::store_time_dec(MYSQL_TIME *ltime, uint dec)
+int Field_temporal_with_date::store_time_dec(MYSQL_TIME *ltime, uint dec)
{
int error = 0, have_smth_to_conv= 1;
MYSQL_TIME l_time= *ltime;
@@ -5144,6 +5261,35 @@ my_decimal *Field_temporal::val_decimal(
** In number context: HHMMSS
** Stored as a 3 byte unsigned int
****************************************************************************/
+int Field_time::store_TIME_with_warning(MYSQL_TIME *ltime,
+ const ErrConv *str,
+ int was_cut,
+ int have_smth_to_conv)
+{
+ MYSQL_ERROR::enum_warning_level trunc_level= MYSQL_ERROR::WARN_LEVEL_WARN;
+ int ret= 2;
+
+ ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+
+ if (!have_smth_to_conv)
+ {
+ bzero(ltime, sizeof(*ltime));
+ was_cut= MYSQL_TIME_WARN_TRUNCATED;
+ ret= 1;
+ }
+ else if (!(was_cut & MYSQL_TIME_WARN_TRUNCATED) &&
+ (ltime->year || ltime->month))
+ {
+ ltime->year= ltime->month= ltime->day= 0;
+ trunc_level= MYSQL_ERROR::WARN_LEVEL_NOTE;
+ was_cut|= MYSQL_TIME_WARN_TRUNCATED;
+ ret= 3;
+ }
+ set_warnings(trunc_level, str, was_cut, MYSQL_TIMESTAMP_TIME);
+ store_TIME(ltime);
+ return was_cut ? ret : 0;
+}
+
void Field_time::store_TIME(MYSQL_TIME *ltime)
{
@@ -5229,32 +5375,16 @@ longlong Field_time::val_int(void)
my_charset_bin
*/
-String *Field_time::val_str(String *val_buffer,
- String *val_ptr __attribute__((unused)))
+String *Field_time::val_str(String *str,
+ String *unused __attribute__((unused)))
{
ASSERT_COLUMN_MARKED_FOR_READ;
MYSQL_TIME ltime;
- long tmp=(long) sint3korr(ptr);
- ltime.neg= 0;
- if (tmp < 0)
- {
- tmp= -tmp;
- ltime.neg= 1;
- }
- ltime.year= ltime.month= 0;
- ltime.day= (uint) 0;
- ltime.hour= (uint) (tmp/10000);
- ltime.minute= (uint) (tmp/100 % 100);
- ltime.second= (uint) (tmp % 100);
- ltime.second_part= 0;
-
- val_buffer->alloc(MAX_DATE_STRING_REP_LENGTH);
- uint length= (uint) my_time_to_str(<ime,
- const_cast<char*>(val_buffer->ptr()), 0);
- val_buffer->length(length);
- val_buffer->set_charset(&my_charset_numeric);
-
- return val_buffer;
+ get_date(<ime, TIME_TIME_ONLY);
+ str->alloc(field_length + 1);
+ str->length(my_time_to_str(<ime, const_cast<char*>(str->ptr()), decimals()));
+ str->set_charset(&my_charset_numeric);
+ return str;
}
@@ -5297,8 +5427,8 @@ bool Field_time::get_date(MYSQL_TIME *lt
bool Field_time::send_binary(Protocol *protocol)
{
MYSQL_TIME ltime;
- Field_time::get_date(<ime, TIME_TIME_ONLY);
- return protocol->store_time(<ime, 0);
+ get_date(<ime, TIME_TIME_ONLY);
+ return protocol->store_time(<ime, decimals());
}
@@ -5335,7 +5465,7 @@ void Field_time_hires::store_TIME(MYSQL_
store_bigendian(packed, ptr, Field_time_hires::pack_length());
}
-int Field_time_hires::store_decimal(const my_decimal *d)
+int Field_time_with_dec::store_decimal(const my_decimal *d)
{
ulonglong nr;
ulong sec_part;
@@ -5354,35 +5484,23 @@ uint32 Field_time_hires::pack_length() c
return time_hires_bytes[dec];
}
-longlong Field_time_hires::val_int(void)
+longlong Field_time_with_dec::val_int(void)
{
ASSERT_COLUMN_MARKED_FOR_READ;
MYSQL_TIME ltime;
- Field_time_hires::get_date(<ime, TIME_TIME_ONLY);
+ get_date(<ime, TIME_TIME_ONLY);
longlong val= TIME_to_ulonglong_time(<ime);
return ltime.neg ? -val : val;
}
-double Field_time_hires::val_real(void)
+double Field_time_with_dec::val_real(void)
{
ASSERT_COLUMN_MARKED_FOR_READ;
MYSQL_TIME ltime;
- Field_time_hires::get_date(<ime, TIME_TIME_ONLY);
+ get_date(<ime, TIME_TIME_ONLY);
return TIME_to_double(<ime);
}
-String *Field_time_hires::val_str(String *str,
- String *unused __attribute__((unused)))
-{
- ASSERT_COLUMN_MARKED_FOR_READ;
- MYSQL_TIME ltime;
- Field_time_hires::get_date(<ime, TIME_TIME_ONLY);
- str->alloc(field_length+1);
- str->length(my_time_to_str(<ime, (char*) str->ptr(), dec));
- str->set_charset(&my_charset_bin);
- return str;
-}
-
bool Field_time_hires::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
uint32 len= pack_length();
@@ -5402,14 +5520,6 @@ bool Field_time_hires::get_date(MYSQL_TI
}
-bool Field_time_hires::send_binary(Protocol *protocol)
-{
- MYSQL_TIME ltime;
- Field_time_hires::get_date(<ime, TIME_TIME_ONLY);
- return protocol->store_time(<ime, dec);
-}
-
-
int Field_time_hires::cmp(const uchar *a_ptr, const uchar *b_ptr)
{
ulonglong a=read_bigendian(a_ptr, Field_time_hires::pack_length());
@@ -5431,13 +5541,51 @@ void Field_time_hires::sql_type(String &
"time(%u)", dec));
}
-void Field_time_hires::make_field(Send_field *field)
+void Field_time_with_dec::make_field(Send_field *field)
{
Field::make_field(field);
field->decimals= dec;
}
/****************************************************************************
+** time type with fsp (MySQL-5.6 version)
+** In string context: HH:MM:SS.FFFFFF
+** In number context: HHMMSS.FFFFFF
+****************************************************************************/
+
+void Field_timef::sql_type(String &res) const
+{
+ if (dec == 0)
+ {
+ res.set_ascii(STRING_WITH_LEN("time"));
+ return;
+ }
+ const CHARSET_INFO *cs= res.charset();
+ res.length(cs->cset->snprintf(cs, (char*) res.ptr(), res.alloced_length(),
+ "time(%d)", dec));
+}
+
+int Field_timef::reset()
+{
+ my_time_packed_to_binary(0, ptr, dec);
+ return 0;
+}
+
+void Field_timef::store_TIME(MYSQL_TIME *ltime)
+{
+ my_time_trunc(ltime, decimals());
+ longlong tmp= TIME_to_longlong_time_packed(ltime);
+ my_time_packed_to_binary(tmp, ptr, dec);
+}
+
+bool Field_timef::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+{
+ longlong tmp= my_time_packed_from_binary(ptr, dec);
+ TIME_from_longlong_time_packed(ltime, tmp);
+ return false;
+}
+
+/****************************************************************************
** year type
** Save in a byte the year 0, 1901->2155
** Can handle 2 byte or 4 byte years!
@@ -5792,8 +5940,8 @@ bool Field_datetime::send_binary(Protoco
Field_datetime::get_date(&tm, TIME_FUZZY_DATE);
return protocol->store(&tm, 0);
}
-
-
+
+
double Field_datetime::val_real(void)
{
return (double) Field_datetime::val_int();
@@ -5924,7 +6072,7 @@ void Field_datetime_hires::store_TIME(MY
store_bigendian(packed, ptr, Field_datetime_hires::pack_length());
}
-int Field_datetime_hires::store_decimal(const my_decimal *d)
+int Field_datetime_with_dec::store_decimal(const my_decimal *d)
{
ulonglong nr;
ulong sec_part;
@@ -5949,38 +6097,38 @@ int Field_datetime_hires::store_decimal(
return store_TIME_with_warning(<ime, &str, error, tmp != -1);
}
-bool Field_datetime_hires::send_binary(Protocol *protocol)
+bool Field_datetime_with_dec::send_binary(Protocol *protocol)
{
MYSQL_TIME ltime;
- Field_datetime_hires::get_date(<ime, TIME_FUZZY_DATE);
+ get_date(<ime, TIME_FUZZY_DATE);
return protocol->store(<ime, dec);
}
-double Field_datetime_hires::val_real(void)
+double Field_datetime_with_dec::val_real(void)
{
MYSQL_TIME ltime;
- Field_datetime_hires::get_date(<ime, TIME_FUZZY_DATE);
+ get_date(<ime, TIME_FUZZY_DATE);
return TIME_to_double(<ime);
}
-longlong Field_datetime_hires::val_int(void)
+longlong Field_datetime_with_dec::val_int(void)
{
MYSQL_TIME ltime;
- Field_datetime_hires::get_date(<ime, TIME_FUZZY_DATE);
+ get_date(<ime, TIME_FUZZY_DATE);
return TIME_to_ulonglong_datetime(<ime);
}
-String *Field_datetime_hires::val_str(String *str,
- String *unused __attribute__((unused)))
+String *Field_datetime_with_dec::val_str(String *str,
+ String *unused __attribute__((unused)))
{
MYSQL_TIME ltime;
- Field_datetime_hires::get_date(<ime, TIME_FUZZY_DATE);
+ get_date(<ime, TIME_FUZZY_DATE);
str->alloc(field_length+1);
str->length(field_length);
my_datetime_to_str(<ime, (char*) str->ptr(), dec);
- str->set_charset(&my_charset_bin);
+ str->set_charset(&my_charset_numeric);
return str;
}
@@ -6007,27 +6155,61 @@ int Field_datetime_hires::cmp(const ucha
return a < b ? -1 : a > b ? 1 : 0;
}
-void Field_datetime_hires::sort_string(uchar *to,
- uint length __attribute__((unused)))
+void Field_datetime_hires::sql_type(String &res) const
{
- DBUG_ASSERT(length == Field_datetime_hires::pack_length());
- memcpy(to, ptr, length);
+ CHARSET_INFO *cs= res.charset();
+ res.length(cs->cset->snprintf(cs, (char*) res.ptr(), res.alloced_length(),
+ "datetime(%u)", dec));
+}
+
+void Field_datetime_with_dec::make_field(Send_field *field)
+{
+ Field::make_field(field);
+ field->decimals= dec;
}
-void Field_datetime_hires::sql_type(String &res) const
+/****************************************************************************
+** MySQL-5.6 compatible DATETIME(N)
+**
+****************************************************************************/
+void Field_datetimef::sql_type(String &res) const
{
- CHARSET_INFO *cs=res.charset();
+ if (dec == 0)
+ {
+ res.set_ascii(STRING_WITH_LEN("datetime"));
+ return;
+ }
+ CHARSET_INFO *cs= res.charset();
res.length(cs->cset->snprintf(cs, (char*) res.ptr(), res.alloced_length(),
"datetime(%u)", dec));
}
-void Field_datetime_hires::make_field(Send_field *field)
+int Field_datetimef::reset()
{
- Field::make_field(field);
- field->decimals= dec;
+ my_datetime_packed_to_binary(0, ptr, dec);
+ return 0;
+}
+
+void Field_datetimef::store_TIME(MYSQL_TIME *ltime)
+{
+ my_datetime_trunc(ltime, decimals());
+ longlong tmp= TIME_to_longlong_datetime_packed(ltime);
+ my_datetime_packed_to_binary(tmp, ptr, dec);
+}
+
+bool Field_datetimef::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+{
+ longlong tmp= my_datetime_packed_from_binary(ptr, dec);
+ TIME_from_longlong_datetime_packed(ltime, tmp);
+ if (!tmp)
+ return fuzzydate & TIME_NO_ZERO_DATE;
+ if (!ltime->month || !ltime->day)
+ return !(fuzzydate & TIME_FUZZY_DATE);
+ return false;
}
+
/****************************************************************************
** string type
** A string may be varchar or binary
@@ -6198,80 +6380,6 @@ int Field_str::store(double nr)
return store(buff, length, &my_charset_numeric);
}
-static
-inline ulonglong char_prefix_to_ulonglong(uchar *src)
-{
- uint sz= sizeof(ulonglong);
- for (uint i= 0; i < sz/2; i++)
- {
- uchar tmp= src[i];
- src[i]= src[sz-1-i];
- src[sz-1-i]= tmp;
- }
- return uint8korr(src);
-}
-
-/**
- @brief
- Determine the relative position of the field value in a string interval
-
- @details
- The function returns a double number between 0.0 and 1.0 as the relative
- position of the value of the this field in the string interval of [min,max].
- If the value is not in the interval the the function returns 0.0 when
- the value is less than min, and, 1.0 when the value is greater than max.
-
- @note
- To calculate the relative position of the string value v in the interval
- [min, max] the function first converts the beginning of these three
- strings v, min, max into the strings that are used for byte comparison.
- For each string not more sizeof(ulonglong) first bytes are taken
- from the result of conversion. Then these bytes are interpreted as the
- big-endian representation of an ulonglong integer. The values of these
- integer numbers obtained for the strings v, min, max are used to calculate
- the position of v in [min,max] in the same way is it's done for numeric
- fields (see Field_num::pos_in_interval).
-
- @todo
- Improve the procedure for the case when min and max have the same
- beginning
-
- @param min value of the left end of the interval
- @param max value of the right end of the interval
-
- @return
- relative position of the field value in the string interval [min,max]
-*/
-
-double Field_str::pos_in_interval(Field *min, Field *max)
-{
- uchar mp_prefix[sizeof(ulonglong)];
- uchar minp_prefix[sizeof(ulonglong)];
- uchar maxp_prefix[sizeof(ulonglong)];
- ulonglong mp, minp, maxp;
- my_strnxfrm(charset(), mp_prefix, sizeof(mp),
- ptr + length_size(),
- data_length());
- my_strnxfrm(charset(), minp_prefix, sizeof(minp),
- min->ptr + length_size(),
- min->data_length());
- my_strnxfrm(charset(), maxp_prefix, sizeof(maxp),
- max->ptr + length_size(),
- max->data_length());
- mp= char_prefix_to_ulonglong(mp_prefix);
- minp= char_prefix_to_ulonglong(minp_prefix);
- maxp= char_prefix_to_ulonglong(maxp_prefix);
- double n, d;
- n= mp - minp;
- if (n < 0)
- return 0.0;
- d= maxp - minp;
- if (d <= 0)
- return 1.0;
- return min(n/d, 1.0);
-}
-
-
uint Field::is_equal(Create_field *new_field)
{
return (new_field->sql_type == real_type());
@@ -8482,36 +8590,6 @@ my_decimal *Field_bit::val_decimal(my_de
}
-/**
- @brief
- Determine the relative position of the field value in a bit interval
-
- @details
- The function returns a double number between 0.0 and 1.0 as the relative
- position of the value of the this field in the bit interval of [min,max].
- If the value is not in the interval the the function returns 0.0 when
- the value is less than min, and, 1.0 when the value is greater than max.
-
- @param min value of the left end of the interval
- @param max value of the right end of the interval
-
- @return
- relative position of the field value in the bit interval [min,max]
-*/
-
-double Field_bit::pos_in_interval(Field *min, Field *max)
-{
- double n, d;
- n= val_real() - min->val_real();
- if (n < 0)
- return 0.0;
- d= max->val_real() - min->val_real();
- if (d <= 0)
- return 1.0;
- return min(n/d, 1.0);
-}
-
-
/*
Compare two bit fields using pointers within the record.
SYNOPSIS
@@ -9144,7 +9222,7 @@ bool Create_field::init(THD *thd, char *
it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
*/
if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) &&
- (fld_type_modifier & NOT_NULL_FLAG) && fld_type != MYSQL_TYPE_TIMESTAMP)
+ (fld_type_modifier & NOT_NULL_FLAG) && !is_timestamp_type(fld_type))
flags|= NO_DEFAULT_VALUE_FLAG;
if (fld_length != NULL)
@@ -9306,6 +9384,7 @@ bool Create_field::init(THD *thd, char *
}
break;
case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_TIMESTAMP2:
if (length > MAX_DATETIME_PRECISION)
{
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
@@ -9323,6 +9402,7 @@ bool Create_field::init(THD *thd, char *
length= MAX_DATE_WIDTH;
break;
case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_TIME2:
if (length > MAX_DATETIME_PRECISION)
{
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
@@ -9332,6 +9412,7 @@ bool Create_field::init(THD *thd, char *
length+= MIN_TIME_WIDTH + (length ? 1 : 0);
break;
case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_DATETIME2:
if (length > MAX_DATETIME_PRECISION)
{
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
@@ -9413,17 +9494,6 @@ bool Create_field::init(THD *thd, char *
DBUG_RETURN(TRUE);
}
- switch (fld_type) {
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_NEWDATE:
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_TIMESTAMP:
- charset= &my_charset_numeric;
- flags|= BINARY_FLAG;
- default: break;
- }
-
DBUG_RETURN(FALSE); /* success */
}
@@ -9462,10 +9532,16 @@ uint32 calc_pack_length(enum_field_types
case MYSQL_TYPE_TIME: return length > MIN_TIME_WIDTH
? time_hires_bytes[length - 1 - MIN_TIME_WIDTH]
: 3;
+ case MYSQL_TYPE_TIME2:
+ return length > MIN_TIME_WIDTH ?
+ my_time_binary_length(length - MIN_TIME_WIDTH - 1) : 3;
case MYSQL_TYPE_TIMESTAMP:
return length > MAX_DATETIME_WIDTH
? 4 + sec_part_bytes[length - 1 - MAX_DATETIME_WIDTH]
: 4;
+ case MYSQL_TYPE_TIMESTAMP2:
+ return length > MAX_DATETIME_WIDTH ?
+ my_timestamp_binary_length(length - MAX_DATETIME_WIDTH - 1) : 4;
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_LONG : return 4;
case MYSQL_TYPE_FLOAT : return sizeof(float);
@@ -9474,6 +9550,9 @@ uint32 calc_pack_length(enum_field_types
return length > MAX_DATETIME_WIDTH
? datetime_hires_bytes[length - 1 - MAX_DATETIME_WIDTH]
: 8;
+ case MYSQL_TYPE_DATETIME2:
+ return length > MAX_DATETIME_WIDTH ?
+ my_datetime_binary_length(length - MAX_DATETIME_WIDTH - 1) : 5;
case MYSQL_TYPE_LONGLONG: return 8; /* Don't crash if no longlong */
case MYSQL_TYPE_NULL : return 0;
case MYSQL_TYPE_TINY_BLOB: return 1+portable_sizeof_char_ptr;
@@ -9538,16 +9617,6 @@ Field *make_field(TABLE_SHARE *share, uc
null_bit= ((uchar) 1) << null_bit;
}
- switch (field_type) {
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_NEWDATE:
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_TIMESTAMP:
- field_charset= &my_charset_numeric;
- default: break;
- }
-
DBUG_PRINT("debug", ("field_type: %d, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s",
field_type, field_length, interval,
FLAGSTR(pack_flag, FIELDFLAG_BINARY),
@@ -9661,30 +9730,51 @@ Field *make_field(TABLE_SHARE *share, uc
uint dec= field_length > MAX_DATETIME_WIDTH ?
field_length - MAX_DATETIME_WIDTH - 1: 0;
return new_Field_timestamp(ptr, null_pos, null_bit, unireg_check,
- field_name, share, dec, field_charset);
+ field_name, share, dec);
+ }
+ case MYSQL_TYPE_TIMESTAMP2:
+ {
+ uint dec= field_length > MAX_DATETIME_WIDTH ?
+ field_length - MAX_DATETIME_WIDTH - 1: 0;
+ return new Field_timestampf(ptr, null_pos, null_bit, unireg_check,
+ field_name, share, dec);
}
case MYSQL_TYPE_YEAR:
return new Field_year(ptr,field_length,null_pos,null_bit,
unireg_check, field_name);
case MYSQL_TYPE_DATE:
return new Field_date(ptr,null_pos,null_bit,
- unireg_check, field_name, field_charset);
+ unireg_check, field_name);
case MYSQL_TYPE_NEWDATE:
return new Field_newdate(ptr,null_pos,null_bit,
- unireg_check, field_name, field_charset);
+ unireg_check, field_name);
case MYSQL_TYPE_TIME:
{
uint dec= field_length > MIN_TIME_WIDTH ?
field_length - MIN_TIME_WIDTH - 1: 0;
return new_Field_time(ptr, null_pos, null_bit, unireg_check,
- field_name, dec, field_charset);
+ field_name, dec);
+ }
+ case MYSQL_TYPE_TIME2:
+ {
+ uint dec= field_length > MIN_TIME_WIDTH ?
+ field_length - MIN_TIME_WIDTH - 1: 0;
+ return new Field_timef(ptr, null_pos, null_bit, unireg_check,
+ field_name, dec);
}
case MYSQL_TYPE_DATETIME:
{
uint dec= field_length > MAX_DATETIME_WIDTH ?
field_length - MAX_DATETIME_WIDTH - 1: 0;
return new_Field_datetime(ptr, null_pos, null_bit, unireg_check,
- field_name, dec, field_charset);
+ field_name, dec);
+ }
+ case MYSQL_TYPE_DATETIME2:
+ {
+ uint dec= field_length > MAX_DATETIME_WIDTH ?
+ field_length - MAX_DATETIME_WIDTH - 1: 0;
+ return new Field_datetimef(ptr, null_pos, null_bit, unireg_check,
+ field_name, dec);
}
case MYSQL_TYPE_NULL:
return new Field_null(ptr, field_length, unireg_check, field_name,
=== modified file 'sql/field.h'
--- sql/field.h 2013-06-06 15:51:28 +0000
+++ sql/field.h 2013-06-19 09:46:34 +0000
@@ -89,6 +89,42 @@ inline uint get_set_pack_length(int elem
return len > 4 ? 8 : len;
}
+
+/**
+ Recognizer for concrete data type (called real_type for some reason),
+ returning true if it is one of the TIMESTAMP types.
+*/
+inline bool is_timestamp_type(enum_field_types type)
+{
+ return type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_TIMESTAMP2;
+}
+
+
+/**
+ Convert temporal real types as retuned by field->real_type()
+ to field type as returned by field->type().
+
+ @param real_type Real type.
+ @retval Field type.
+*/
+inline enum_field_types real_type_to_type(enum_field_types real_type)
+{
+ switch (real_type)
+ {
+ case MYSQL_TYPE_TIME2:
+ return MYSQL_TYPE_TIME;
+ case MYSQL_TYPE_DATETIME2:
+ return MYSQL_TYPE_DATETIME;
+ case MYSQL_TYPE_TIMESTAMP2:
+ return MYSQL_TYPE_TIMESTAMP;
+ case MYSQL_TYPE_NEWDATE:
+ return MYSQL_TYPE_DATE;
+ /* Note: NEWDECIMAL is a type, not only a real_type */
+ default: return real_type;
+ }
+}
+
+
/*
Virtual_column_info is the class to contain additional
characteristics that is specific for a virtual/computed
@@ -428,6 +464,27 @@ class Field
virtual uint32 key_length() const { return pack_length(); }
virtual enum_field_types type() const =0;
virtual enum_field_types real_type() const { return type(); }
+ virtual enum_field_types binlog_type() const
+ {
+ /*
+ Binlog stores field->type() as type code by default.
+ This puts MYSQL_TYPE_STRING in case of CHAR, VARCHAR, SET and ENUM,
+ with extra data type details put into metadata.
+
+ We cannot store field->type() in case of temporal types with
+ fractional seconds: TIME(n), DATETIME(n) and TIMESTAMP(n),
+ because binlog records with MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME
+ type codes do not have metadata.
+ So for MySQL-5.6 temporal data types with fractional seconds we'll store
+ real_type() type codes instead, i.e.
+ MYSQL_TYPE_TIME2, MYSQL_TYPE_DATETIME2, MYSQL_TYPE_TIMESTAMP2,
+ and put precision into metatada.
+
+ Note: perhaps binlog should eventually be modified to store
+ real_type() instead of type() for all column types.
+ */
+ return type();
+ }
inline int cmp(const uchar *str) { return cmp(ptr,str); }
virtual int cmp_max(const uchar *a, const uchar *b, uint max_len)
{ return cmp(a, b); }
@@ -661,6 +718,16 @@ class Field
{ return binary() ? &my_charset_bin : charset(); }
virtual CHARSET_INFO *sort_charset(void) const { return charset(); }
virtual bool has_charset(void) const { return FALSE; }
+ /*
+ match_collation_to_optimize_range() is to distinguish in
+ range optimizer (see opt_range.cc) between real string types:
+ CHAR, VARCHAR, TEXT
+ and the other string-alike types with result_type() == STRING_RESULT:
+ DATE, TIME, DATETIME, TIMESTAMP
+ We need it to decide whether to test if collation of the operation
+ matches collation of the field (needed only for real string types).
+ */
+ virtual bool match_collation_to_optimize_range() const { return false; }
virtual void set_charset(CHARSET_INFO *charset_arg) { }
virtual enum Derivation derivation(void) const
{ return DERIVATION_IMPLICIT; }
@@ -808,7 +875,8 @@ class Field
{
return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0;
}
-
+ double pos_in_interval_val_real(Field *min, Field *max);
+ double pos_in_interval_val_str(Field *min, Field *max, uint data_offset);
};
@@ -847,7 +915,10 @@ class Field_num :public Field {
bool get_int(CHARSET_INFO *cs, const char *from, uint len,
longlong *rnd, ulonglong unsigned_max,
longlong signed_min, longlong signed_max);
- double pos_in_interval(Field *min, Field *max);
+ double pos_in_interval(Field *min, Field *max)
+ {
+ return pos_in_interval_val_real(min, max);
+ }
};
@@ -860,23 +931,11 @@ class Field_str :public Field {
uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg, CHARSET_INFO *charset);
Item_result result_type () const { return STRING_RESULT; }
- /*
- match_collation_to_optimize_range() is to distinguish in
- range optimizer (see opt_range.cc) between real string types:
- CHAR, VARCHAR, TEXT
- and the other string-alike types with result_type() == STRING_RESULT:
- DATE, TIME, DATETIME, TIMESTAMP
- We need it to decide whether to test if collation of the operation
- matches collation of the field (needed only for real string types).
- QQ: shouldn't DATE/TIME types have their own XXX_RESULT types eventually?
- */
- virtual bool match_collation_to_optimize_range() const=0;
uint decimals() const { return NOT_FIXED_DEC; }
int store(double nr);
int store(longlong nr, bool unsigned_val)=0;
int store_decimal(const my_decimal *);
int store(const char *to,uint length,CHARSET_INFO *cs)=0;
- uint size_of() const { return sizeof(*this); }
uint repertoire(void) const
{
return my_charset_repertoire(field_charset);
@@ -894,7 +953,10 @@ class Field_str :public Field {
uint is_equal(Create_field *new_field);
bool eq_cmp_as_binary() { return test(flags & BINARY_FLAG); }
virtual uint length_size() { return 0; }
- double pos_in_interval(Field *min, Field *max);
+ double pos_in_interval(Field *min, Field *max)
+ {
+ return pos_in_interval_val_str(min, max, length_size());
+ }
};
/* base class for Field_string, Field_varstring and Field_blob */
@@ -914,6 +976,7 @@ class Field_longstr :public Field_str
int store_decimal(const my_decimal *d);
uint32 max_data_length() const;
+ bool match_collation_to_optimize_range() const { return true; }
};
/* base class for float and double and decimal (old one) */
@@ -1323,7 +1386,6 @@ class Field_null :public Field_str {
unireg_check_arg, field_name_arg, cs)
{}
enum_field_types type() const { return MYSQL_TYPE_NULL;}
- bool match_collation_to_optimize_range() const { return FALSE; }
int store(const char *to, uint length, CHARSET_INFO *cs)
{ null[0]=1; return 0; }
int store(double nr) { null[0]=1; return 0; }
@@ -1345,7 +1407,67 @@ class Field_null :public Field_str {
};
-class Field_timestamp :public Field_str {
+class Field_temporal: public Field {
+public:
+ Field_temporal(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
+ const char *field_name_arg)
+ :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
+ field_name_arg)
+ { flags|= BINARY_FLAG; }
+ Item_result result_type () const { return STRING_RESULT; }
+ uint32 max_display_length() { return field_length; }
+ bool str_needs_quotes() { return TRUE; }
+ enum Derivation derivation(void) const { return DERIVATION_NUMERIC; }
+ uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
+ CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
+ const CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
+ bool binary() const { return true; }
+ enum Item_result cmp_type () const { return TIME_RESULT; }
+ uint is_equal(Create_field *new_field);
+ bool eq_def(Field *field)
+ {
+ return (Field::eq_def(field) && decimals() == field->decimals());
+ }
+ int store_decimal(const my_decimal *);
+ my_decimal *val_decimal(my_decimal*);
+ void set_warnings(MYSQL_ERROR::enum_warning_level trunc_level,
+ const ErrConv *str, int was_cut, timestamp_type ts_type);
+ double pos_in_interval(Field *min, Field *max)
+ {
+ return pos_in_interval_val_str(min, max, 0);
+ }
+};
+
+
+/**
+ Abstract class for:
+ - DATE
+ - DATETIME
+ - DATETIME(1..6)
+ - DATETIME(0..6) - MySQL56 version
+*/
+class Field_temporal_with_date: public Field_temporal {
+protected:
+ int store_TIME_with_warning(MYSQL_TIME *ltime, const ErrConv *str,
+ int was_cut, int have_smth_to_conv);
+ virtual void store_TIME(MYSQL_TIME *ltime) = 0;
+public:
+ Field_temporal_with_date(uchar *ptr_arg, uint32 len_arg,
+ uchar *null_ptr_arg, uchar null_bit_arg,
+ utype unireg_check_arg,
+ const char *field_name_arg)
+ :Field_temporal(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg)
+ {}
+ int store(const char *to, uint length, CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr, bool unsigned_val);
+ int store_time_dec(MYSQL_TIME *ltime, uint dec);
+};
+
+
+class Field_timestamp :public Field_temporal {
protected:
int store_TIME_with_warning(THD *, MYSQL_TIME *, const ErrConv *,
bool, bool);
@@ -1353,17 +1475,9 @@ class Field_timestamp :public Field_str
Field_timestamp(uchar *ptr_arg, uint32 len_arg,
uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
- TABLE_SHARE *share, CHARSET_INFO *cs);
- Field_timestamp(bool maybe_null_arg, const char *field_name_arg,
- CHARSET_INFO *cs);
+ TABLE_SHARE *share);
enum_field_types type() const { return MYSQL_TYPE_TIMESTAMP;}
- bool match_collation_to_optimize_range() const { return FALSE; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
- enum Item_result cmp_type () const { return TIME_RESULT; }
- enum Derivation derivation(void) const { return DERIVATION_NUMERIC; }
- uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
- CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
- bool binary() const { return 1; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
int store(longlong nr, bool unsigned_val);
@@ -1377,7 +1491,6 @@ class Field_timestamp :public Field_str
uint32 pack_length() const { return 4; }
void sql_type(String &str) const;
bool zero_pack() const { return 0; }
- uint decimals() const { return 0; }
virtual int set_time();
virtual void set_default()
{
@@ -1418,46 +1531,112 @@ class Field_timestamp :public Field_str
{
return unpack_int32(to, from, from_end);
}
+ uint size_of() const { return sizeof(*this); }
};
-class Field_timestamp_hires :public Field_timestamp {
+/**
+ Abstract class for:
+ - TIMESTAMP(1..6)
+ - TIMESTAMP(0..6) - MySQL56 version
+*/
+class Field_timestamp_with_dec :public Field_timestamp {
+protected:
uint dec;
public:
- Field_timestamp_hires(uchar *ptr_arg,
- uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
- TABLE_SHARE *share, uint dec_arg, CHARSET_INFO *cs) :
- Field_timestamp(ptr_arg, MAX_DATETIME_WIDTH + dec_arg + 1, null_ptr_arg,
- null_bit_arg, unireg_check_arg, field_name_arg, share, cs),
+ Field_timestamp_with_dec(uchar *ptr_arg,
+ uchar *null_ptr_arg, uchar null_bit_arg,
+ enum utype unireg_check_arg,
+ const char *field_name_arg,
+ TABLE_SHARE *share, uint dec_arg) :
+ Field_timestamp(ptr_arg,
+ MAX_DATETIME_WIDTH + dec_arg + test(dec_arg), null_ptr_arg,
+ null_bit_arg, unireg_check_arg, field_name_arg, share),
dec(dec_arg)
{
- DBUG_ASSERT(dec);
DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
}
- void sql_type(String &str) const;
- my_time_t get_timestamp(ulong *sec_part) const;
- void store_TIME(my_time_t timestamp, ulong sec_part);
- int store_decimal(const my_decimal *d);
- double val_real(void);
- String *val_str(String*,String *);
- my_decimal* val_decimal(my_decimal*);
- bool send_binary(Protocol *protocol);
- int cmp(const uchar *,const uchar *);
- void sort_string(uchar *buff,uint length);
uint decimals() const { return dec; }
- int set_time();
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
- void make_field(Send_field *field);
- uint32 pack_length() const;
uchar *pack(uchar *to, const uchar *from, uint max_length)
{ return Field::pack(to, from, max_length); }
const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
uint param_data)
{ return Field::unpack(to, from, from_end, param_data); }
+ void make_field(Send_field *field);
+ void sort_string(uchar *to, uint length)
+ {
+ DBUG_ASSERT(length == pack_length());
+ memcpy(to, ptr, length);
+ }
+ bool send_binary(Protocol *protocol);
+ double val_real(void);
+ my_decimal* val_decimal(my_decimal*);
+ int store_decimal(const my_decimal *d);
+ int set_time();
+};
+
+
+class Field_timestamp_hires :public Field_timestamp_with_dec {
+public:
+ Field_timestamp_hires(uchar *ptr_arg,
+ uchar *null_ptr_arg, uchar null_bit_arg,
+ enum utype unireg_check_arg,
+ const char *field_name_arg,
+ TABLE_SHARE *share, uint dec_arg) :
+ Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, share, dec_arg)
+ {
+ DBUG_ASSERT(dec);
+ }
+ void sql_type(String &str) const;
+ my_time_t get_timestamp(ulong *sec_part) const;
+ void store_TIME(my_time_t timestamp, ulong sec_part);
+ int cmp(const uchar *,const uchar *);
+ uint32 pack_length() const;
+ uint size_of() const { return sizeof(*this); }
+};
+
+
+/**
+ TIMESTAMP(0..6) - MySQL56 version
+*/
+class Field_timestampf :public Field_timestamp_with_dec {
+ int do_save_field_metadata(uchar *metadata_ptr)
+ {
+ *metadata_ptr= decimals();
+ return 1;
+ }
+public:
+ Field_timestampf(uchar *ptr_arg,
+ uchar *null_ptr_arg, uchar null_bit_arg,
+ enum utype unireg_check_arg,
+ const char *field_name_arg,
+ TABLE_SHARE *share, uint dec_arg) :
+ Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, share, dec_arg)
+ {}
+ enum_field_types real_type() const { return MYSQL_TYPE_TIMESTAMP2; }
+ enum_field_types binlog_type() const { return MYSQL_TYPE_TIMESTAMP2; }
+ uint32 pack_length() const
+ {
+ return my_timestamp_binary_length(dec);
+ }
+ uint row_pack_length() { return pack_length(); }
+ uint pack_length_from_metadata(uint field_metadata)
+ {
+ DBUG_ENTER("Field_timestampf::pack_length_from_metadata");
+ uint tmp= my_timestamp_binary_length(field_metadata);
+ DBUG_RETURN(tmp);
+ }
+ int cmp(const uchar *a_ptr,const uchar *b_ptr)
+ {
+ return memcmp(a_ptr, b_ptr, pack_length());
+ }
+ void store_TIME(my_time_t timestamp, ulong sec_part);
+ void sql_type(String &str) const;
+ my_time_t get_timestamp(ulong *sec_part) const;
uint size_of() const { return sizeof(*this); }
- bool eq_def(Field *field)
- { return Field_str::eq_def(field) && dec == field->decimals(); }
};
@@ -1484,56 +1663,24 @@ class Field_year :public Field_tiny {
};
-class Field_temporal: public Field_str {
-protected:
- int store_TIME_with_warning(MYSQL_TIME *ltime, const ErrConv *str,
- int was_cut, int have_smth_to_conv);
- virtual void store_TIME(MYSQL_TIME *ltime) = 0;
-public:
- Field_temporal(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
- uchar null_bit_arg, utype unireg_check_arg,
- const char *field_name_arg, CHARSET_INFO *charset_arg)
- :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
- field_name_arg, charset_arg)
- { flags|= BINARY_FLAG; }
- enum Derivation derivation(void) const { return DERIVATION_NUMERIC; }
- uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
- CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
- bool binary() const { return 1; }
- bool match_collation_to_optimize_range() const { return FALSE; }
- enum Item_result cmp_type () const { return TIME_RESULT; }
- int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(double nr);
- int store(longlong nr, bool unsigned_val);
- int store_time_dec(MYSQL_TIME *ltime, uint dec);
- my_decimal *val_decimal(my_decimal*);
- bool eq_def(Field *field)
- {
- return (Field_str::eq_def(field) && decimals() == field->decimals());
- }
-};
-
-class Field_date :public Field_temporal {
+class Field_date :public Field_temporal_with_date {
void store_TIME(MYSQL_TIME *ltime);
public:
Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
- CHARSET_INFO *cs)
- :Field_temporal(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, cs) {}
+ enum utype unireg_check_arg, const char *field_name_arg)
+ :Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg) {}
enum_field_types type() const { return MYSQL_TYPE_DATE;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
- uint decimals() const { return 0; }
bool send_binary(Protocol *protocol);
int cmp(const uchar *,const uchar *);
void sort_string(uchar *buff,uint length);
uint32 pack_length() const { return 4; }
void sql_type(String &str) const;
- bool zero_pack() const { return 1; }
uchar *pack(uchar* to, const uchar *from,
uint max_length __attribute__((unused)))
{
@@ -1544,23 +1691,22 @@ class Field_date :public Field_temporal
{
return unpack_int32(to, from, from_end);
}
+ uint size_of() const { return sizeof(*this); }
};
-class Field_newdate :public Field_temporal {
+class Field_newdate :public Field_temporal_with_date {
void store_TIME(MYSQL_TIME *ltime);
public:
Field_newdate(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
- CHARSET_INFO *cs)
- :Field_temporal(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, cs)
+ enum utype unireg_check_arg, const char *field_name_arg)
+ :Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg)
{}
enum_field_types type() const { return MYSQL_TYPE_DATE;}
enum_field_types real_type() const { return MYSQL_TYPE_NEWDATE; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; }
int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
- uint decimals() const { return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -1569,19 +1715,22 @@ class Field_newdate :public Field_tempor
void sort_string(uchar *buff,uint length);
uint32 pack_length() const { return 3; }
void sql_type(String &str) const;
- bool zero_pack() const { return 1; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
+ uint size_of() const { return sizeof(*this); }
};
class Field_time :public Field_temporal {
- void store_TIME(MYSQL_TIME *ltime);
+protected:
+ virtual void store_TIME(MYSQL_TIME *ltime);
+ int store_TIME_with_warning(MYSQL_TIME *ltime, const ErrConv *str,
+ int was_cut, int have_smth_to_conv);
public:
Field_time(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg,
uchar null_bit_arg, enum utype unireg_check_arg,
- const char *field_name_arg, CHARSET_INFO *cs)
+ const char *field_name_arg)
:Field_temporal(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, cs)
+ unireg_check_arg, field_name_arg)
{}
enum_field_types type() const { return MYSQL_TYPE_TIME;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; }
@@ -1589,7 +1738,6 @@ class Field_time :public Field_temporal
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
int store(longlong nr, bool unsigned_val);
- uint decimals() const { return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -1599,55 +1747,125 @@ class Field_time :public Field_temporal
void sort_string(uchar *buff,uint length);
uint32 pack_length() const { return 3; }
void sql_type(String &str) const;
- bool zero_pack() const { return 1; }
+ uint size_of() const { return sizeof(*this); }
};
-class Field_time_hires :public Field_time {
+
+/**
+ Abstract class for:
+ - TIME(1..6)
+ - TIME(0..6) - MySQL56 version
+*/
+class Field_time_with_dec :public Field_time {
+protected:
uint dec;
+public:
+ Field_time_with_dec(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
+ enum utype unireg_check_arg, const char *field_name_arg,
+ uint dec_arg)
+ :Field_time(ptr_arg, MIN_TIME_WIDTH + dec_arg + test(dec_arg), null_ptr_arg,
+ null_bit_arg, unireg_check_arg, field_name_arg),
+ dec(dec_arg)
+ {
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ }
+ uint decimals() const { return dec; }
+ enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
+ int store_decimal(const my_decimal *d);
+ longlong val_int(void);
+ double val_real(void);
+ void make_field(Send_field *);
+};
+
+
+/**
+ TIME(1..6)
+*/
+class Field_time_hires :public Field_time_with_dec {
longlong zero_point;
void store_TIME(MYSQL_TIME *ltime);
public:
Field_time_hires(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
- uint dec_arg, CHARSET_INFO *cs)
- :Field_time(ptr_arg, MIN_TIME_WIDTH + dec_arg + 1, null_ptr_arg,
- null_bit_arg, unireg_check_arg, field_name_arg, cs),
- dec(dec_arg)
+ uint dec_arg)
+ :Field_time_with_dec(ptr_arg, null_ptr_arg,
+ null_bit_arg, unireg_check_arg, field_name_arg,
+ dec_arg)
{
DBUG_ASSERT(dec);
- DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
zero_point= sec_part_shift(
((TIME_MAX_VALUE_SECONDS+1LL)*TIME_SECOND_PART_FACTOR), dec);
}
- enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
- uint decimals() const { return dec; }
- int store_decimal(const my_decimal *d);
- longlong val_int(void);
- double val_real(void);
- String *val_str(String*,String *);
int reset(void);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
- bool send_binary(Protocol *protocol);
int cmp(const uchar *,const uchar *);
void sort_string(uchar *buff,uint length);
uint32 pack_length() const;
void sql_type(String &str) const;
- void make_field(Send_field *);
uint size_of() const { return sizeof(*this); }
};
-class Field_datetime :public Field_temporal {
+
+/**
+ TIME(0..6) - MySQL56 version
+*/
+class Field_timef :public Field_time_with_dec {
+ void store_TIME(MYSQL_TIME *ltime);
+ int do_save_field_metadata(uchar *metadata_ptr)
+ {
+ *metadata_ptr= decimals();
+ return 1;
+ }
+public:
+ Field_timef(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
+ enum utype unireg_check_arg, const char *field_name_arg,
+ uint dec_arg)
+ :Field_time_with_dec(ptr_arg, null_ptr_arg,
+ null_bit_arg, unireg_check_arg, field_name_arg,
+ dec_arg)
+ {
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ }
+ enum_field_types real_type() const { return MYSQL_TYPE_TIME2; }
+ enum_field_types binlog_type() const { return MYSQL_TYPE_TIME2; }
+ uint32 pack_length() const
+ {
+ return my_time_binary_length(dec);
+ }
+ uint row_pack_length() { return pack_length(); }
+ uint pack_length_from_metadata(uint field_metadata)
+ {
+ DBUG_ENTER("Field_timef::pack_length_from_metadata");
+ uint tmp= my_time_binary_length(field_metadata);
+ DBUG_RETURN(tmp);
+ }
+ void sort_string(uchar *to, uint length)
+ {
+ DBUG_ASSERT(length == Field_timef::pack_length());
+ memcpy(to, ptr, length);
+ }
+ int cmp(const uchar *a_ptr, const uchar *b_ptr)
+ {
+ return memcmp(a_ptr, b_ptr, pack_length());
+ }
+ int reset();
+ bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
+ void sql_type(String &str) const;
+ uint size_of() const { return sizeof(*this); }
+};
+
+
+class Field_datetime :public Field_temporal_with_date {
void store_TIME(MYSQL_TIME *ltime);
public:
Field_datetime(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg,
uchar null_bit_arg, enum utype unireg_check_arg,
- const char *field_name_arg, CHARSET_INFO *cs)
- :Field_temporal(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, cs)
+ const char *field_name_arg)
+ :Field_temporal_with_date(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg)
{}
enum_field_types type() const { return MYSQL_TYPE_DATETIME;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; }
- uint decimals() const { return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -1656,7 +1874,6 @@ class Field_datetime :public Field_tempo
void sort_string(uchar *buff,uint length);
uint32 pack_length() const { return 8; }
void sql_type(String &str) const;
- bool zero_pack() const { return 1; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
virtual int set_time();
virtual void set_default()
@@ -1690,85 +1907,152 @@ class Field_datetime :public Field_tempo
{
return unpack_int64(to, from, from_end);
}
+ uint size_of() const { return sizeof(*this); }
};
-class Field_datetime_hires :public Field_datetime {
- void store_TIME(MYSQL_TIME *ltime);
+/**
+ Abstract class for:
+ - DATETIME(1..6)
+ - DATETIME(0..6) - MySQL56 version
+*/
+class Field_datetime_with_dec :public Field_datetime {
+protected:
uint dec;
public:
- Field_datetime_hires(uchar *ptr_arg, uchar *null_ptr_arg,
- uchar null_bit_arg, enum utype unireg_check_arg,
- const char *field_name_arg, uint dec_arg,
- CHARSET_INFO *cs)
- :Field_datetime(ptr_arg, MAX_DATETIME_WIDTH + dec_arg + 1,
+ Field_datetime_with_dec(uchar *ptr_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, enum utype unireg_check_arg,
+ const char *field_name_arg, uint dec_arg)
+ :Field_datetime(ptr_arg, MAX_DATETIME_WIDTH + dec_arg + test(dec_arg),
null_ptr_arg, null_bit_arg, unireg_check_arg,
- field_name_arg, cs), dec(dec_arg)
+ field_name_arg), dec(dec_arg)
{
- DBUG_ASSERT(dec);
DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
}
- enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
uint decimals() const { return dec; }
+ enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
void make_field(Send_field *field);
+ bool send_binary(Protocol *protocol);
+ uchar *pack(uchar *to, const uchar *from, uint max_length)
+ { return Field::pack(to, from, max_length); }
+ const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
+ uint param_data)
+ { return Field::unpack(to, from, from_end, param_data); }
+ void sort_string(uchar *to, uint length)
+ {
+ DBUG_ASSERT(length == pack_length());
+ memcpy(to, ptr, length);
+ }
int store_decimal(const my_decimal *d);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
- bool send_binary(Protocol *protocol);
+};
+
+
+/**
+ DATETIME(1..6)
+*/
+class Field_datetime_hires :public Field_datetime_with_dec {
+ void store_TIME(MYSQL_TIME *ltime);
+public:
+ Field_datetime_hires(uchar *ptr_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, enum utype unireg_check_arg,
+ const char *field_name_arg, uint dec_arg)
+ :Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, dec_arg)
+ {
+ DBUG_ASSERT(dec);
+ }
int cmp(const uchar *,const uchar *);
- void sort_string(uchar *buff,uint length);
uint32 pack_length() const;
void sql_type(String &str) const;
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
- uchar *pack(uchar *to, const uchar *from, uint max_length)
- { return Field::pack(to, from, max_length); }
- const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end,
- uint param_data)
- { return Field::unpack(to, from, from_end, param_data); }
uint size_of() const { return sizeof(*this); }
};
+
+/**
+ DATETIME(0..6) - MySQL56 version
+*/
+class Field_datetimef :public Field_datetime_with_dec {
+ void store_TIME(MYSQL_TIME *ltime);
+ int do_save_field_metadata(uchar *metadata_ptr)
+ {
+ *metadata_ptr= decimals();
+ return 1;
+ }
+public:
+ Field_datetimef(uchar *ptr_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, enum utype unireg_check_arg,
+ const char *field_name_arg, uint dec_arg)
+ :Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, dec_arg)
+ {}
+ enum_field_types real_type() const { return MYSQL_TYPE_DATETIME2; }
+ enum_field_types binlog_type() const { return MYSQL_TYPE_DATETIME2; }
+ uint32 pack_length() const
+ {
+ return my_datetime_binary_length(dec);
+ }
+ uint row_pack_length() { return pack_length(); }
+ uint pack_length_from_metadata(uint field_metadata)
+ {
+ DBUG_ENTER("Field_datetimef::pack_length_from_metadata");
+ uint tmp= my_datetime_binary_length(field_metadata);
+ DBUG_RETURN(tmp);
+ }
+ int cmp(const uchar *a_ptr, const uchar *b_ptr)
+ {
+ return memcmp(a_ptr, b_ptr, pack_length());
+ }
+ int reset();
+ bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
+ void sql_type(String &str) const;
+ uint size_of() const { return sizeof(*this); }
+};
+
+
static inline Field_timestamp *
new_Field_timestamp(uchar *ptr, uchar *null_ptr, uchar null_bit,
enum Field::utype unireg_check, const char *field_name,
- TABLE_SHARE *share, uint dec, CHARSET_INFO *cs)
+ TABLE_SHARE *share, uint dec)
{
if (dec==0)
return new Field_timestamp(ptr, MAX_DATETIME_WIDTH, null_ptr, null_bit,
- unireg_check, field_name, share, cs);
+ unireg_check, field_name, share);
if (dec == NOT_FIXED_DEC)
dec= MAX_DATETIME_PRECISION;
return new Field_timestamp_hires(ptr, null_ptr, null_bit, unireg_check,
- field_name, share, dec, cs);
+ field_name, share, dec);
}
static inline Field_time *
new_Field_time(uchar *ptr, uchar *null_ptr, uchar null_bit,
enum Field::utype unireg_check, const char *field_name,
- uint dec, CHARSET_INFO *cs)
+ uint dec)
{
if (dec == 0)
return new Field_time(ptr, MIN_TIME_WIDTH, null_ptr, null_bit,
- unireg_check, field_name, cs);
+ unireg_check, field_name);
if (dec == NOT_FIXED_DEC)
dec= MAX_DATETIME_PRECISION;
return new Field_time_hires(ptr, null_ptr, null_bit,
- unireg_check, field_name, dec, cs);
+ unireg_check, field_name, dec);
}
static inline Field_datetime *
new_Field_datetime(uchar *ptr, uchar *null_ptr, uchar null_bit,
enum Field::utype unireg_check,
- const char *field_name, uint dec, CHARSET_INFO *cs)
+ const char *field_name, uint dec)
{
if (dec == 0)
return new Field_datetime(ptr, MAX_DATETIME_WIDTH, null_ptr, null_bit,
- unireg_check, field_name, cs);
+ unireg_check, field_name);
if (dec == NOT_FIXED_DEC)
dec= MAX_DATETIME_PRECISION;
return new Field_datetime_hires(ptr, null_ptr, null_bit,
- unireg_check, field_name, dec, cs);
+ unireg_check, field_name, dec);
}
class Field_string :public Field_longstr {
@@ -1795,7 +2079,6 @@ class Field_string :public Field_longstr
orig_table->s->frm_version < FRM_VER_TRUE_VARCHAR ?
MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING);
}
- bool match_collation_to_optimize_range() const { return TRUE; }
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; }
bool zero_pack() const { return 0; }
@@ -1876,7 +2159,6 @@ class Field_varstring :public Field_long
}
enum_field_types type() const { return MYSQL_TYPE_VARCHAR; }
- bool match_collation_to_optimize_range() const { return TRUE; }
enum ha_base_keytype key_type() const;
uint row_pack_length() { return field_length; }
bool zero_pack() const { return 0; }
@@ -1972,7 +2254,6 @@ class Field_blob :public Field_longstr {
:Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, "temp", system_charset_info),
packlength(packlength_arg) {}
enum_field_types type() const { return MYSQL_TYPE_BLOB;}
- bool match_collation_to_optimize_range() const { return TRUE; }
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; }
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2118,7 +2399,7 @@ class Field_geom :public Field_blob {
{ geom_type= geom_type_arg; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; }
enum_field_types type() const { return MYSQL_TYPE_GEOMETRY; }
- bool match_collation_to_optimize_range() const { return FALSE; }
+ bool match_collation_to_optimize_range() const { return false; }
void sql_type(String &str) const;
int store(const char *to, uint length, CHARSET_INFO *charset);
int store(double nr);
@@ -2156,7 +2437,6 @@ class Field_enum :public Field_str {
}
Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
enum_field_types type() const { return MYSQL_TYPE_STRING; }
- bool match_collation_to_optimize_range() const { return FALSE; }
enum Item_result cmp_type () const { return INT_RESULT; }
enum ha_base_keytype key_type() const;
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2309,7 +2589,10 @@ class Field_bit :public Field {
{
store(*((longlong *)val), TRUE);
}
- double pos_in_interval(Field *min, Field *max);
+ double pos_in_interval(Field *min, Field *max)
+ {
+ return pos_in_interval_val_real(min, max);
+ }
void get_image(uchar *buff, uint length, CHARSET_INFO *cs)
{ get_key_image(buff, length, itRAW); }
void set_image(const uchar *buff,uint length, CHARSET_INFO *cs)
=== modified file 'sql/item.cc'
--- sql/item.cc 2013-06-06 19:32:29 +0000
+++ sql/item.cc 2013-06-18 10:35:35 +0000
@@ -651,9 +651,12 @@ Item_result Item::cmp_type() const
case MYSQL_TYPE_GEOMETRY:
return STRING_RESULT;
case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_TIMESTAMP2:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_TIME2:
case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_DATETIME2:
case MYSQL_TYPE_NEWDATE:
return TIME_RESULT;
};
@@ -1461,6 +1464,7 @@ Item_splocal::Item_splocal(const LEX_STR
{
maybe_null= TRUE;
+ sp_var_type= real_type_to_type(sp_var_type);
m_type= sp_map_item_type(sp_var_type);
m_field_type= sp_var_type;
m_result_type= sp_map_result_type(sp_var_type);
@@ -3218,11 +3222,7 @@ void Item_param::set_time(MYSQL_TIME *tm
value.time= *tm;
value.time.time_type= time_type;
- if (value.time.year > 9999 || value.time.month > 12 ||
- value.time.day > 31 ||
- (time_type != MYSQL_TIMESTAMP_TIME && value.time.hour > 23) ||
- value.time.minute > 59 || value.time.second > 59 ||
- value.time.second_part > TIME_MAX_SECOND_PART)
+ if (check_datetime_range(&value.time))
{
ErrConvTime str(&value.time);
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
@@ -5678,19 +5678,17 @@ Field *Item::tmp_table_field_from_field_
break;
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_DATE:
- field= new Field_newdate(0, null_ptr, 0, Field::NONE, name, &my_charset_bin);
+ field= new Field_newdate(0, null_ptr, 0, Field::NONE, name);
break;
case MYSQL_TYPE_TIME:
- field= new_Field_time(0, null_ptr, 0, Field::NONE, name,
- decimals, &my_charset_bin);
+ field= new_Field_time(0, null_ptr, 0, Field::NONE, name, decimals);
break;
case MYSQL_TYPE_TIMESTAMP:
field= new_Field_timestamp(0, null_ptr, 0,
- Field::NONE, name, 0, decimals, &my_charset_bin);
+ Field::NONE, name, 0, decimals);
break;
case MYSQL_TYPE_DATETIME:
- field= new_Field_datetime(0, null_ptr, 0, Field::NONE, name,
- decimals, &my_charset_bin);
+ field= new_Field_datetime(0, null_ptr, 0, Field::NONE, name, decimals);
break;
case MYSQL_TYPE_YEAR:
field= new Field_year((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
=== modified file 'sql/item_strfunc.cc'
--- sql/item_strfunc.cc 2013-06-06 19:32:29 +0000
+++ sql/item_strfunc.cc 2013-06-18 10:35:35 +0000
@@ -3972,7 +3972,9 @@ bool Item_func_dyncol_create::prepare_ar
type= DYN_COL_NULL;
break;
case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_TIMESTAMP2:
case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_DATETIME2:
type= DYN_COL_DATETIME;
break;
case MYSQL_TYPE_DATE:
@@ -3980,6 +3982,7 @@ bool Item_func_dyncol_create::prepare_ar
type= DYN_COL_DATE;
break;
case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_TIME2:
type= DYN_COL_TIME;
break;
case MYSQL_TYPE_VARCHAR:
=== modified file 'sql/item_sum.cc'
--- sql/item_sum.cc 2013-06-06 15:51:28 +0000
+++ sql/item_sum.cc 2013-06-18 10:35:35 +0000
@@ -1307,16 +1307,16 @@ Field *Item_sum_hybrid::create_tmp_field
switch (args[0]->field_type()) {
case MYSQL_TYPE_DATE:
field= new Field_newdate(0, maybe_null ? (uchar*)"" : 0, 0, Field::NONE,
- name, collation.collation);
+ name);
break;
case MYSQL_TYPE_TIME:
field= new_Field_time(0, maybe_null ? (uchar*)"" : 0, 0, Field::NONE,
- name, decimals, collation.collation);
+ name, decimals);
break;
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATETIME:
field= new_Field_datetime(0, maybe_null ? (uchar*)"" : 0, 0, Field::NONE,
- name, decimals, collation.collation);
+ name, decimals);
break;
default:
return Item_sum::create_tmp_field(group, table, convert_blob_length);
=== modified file 'sql/item_timefunc.h'
--- sql/item_timefunc.h 2013-03-13 21:33:52 +0000
+++ sql/item_timefunc.h 2013-06-18 10:35:35 +0000
@@ -34,9 +34,14 @@ static inline enum enum_mysql_timestamp_
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_TIME:
+ case MYSQL_TYPE_TIME2:
+ return MYSQL_TIMESTAMP_TIME;
case MYSQL_TYPE_TIMESTAMP:
- case MYSQL_TYPE_DATETIME: return MYSQL_TIMESTAMP_DATETIME;
+ case MYSQL_TYPE_TIMESTAMP2:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_DATETIME2:
+ return MYSQL_TIMESTAMP_DATETIME;
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_DATE: return MYSQL_TIMESTAMP_DATE;
default: return MYSQL_TIMESTAMP_ERROR;
=== modified file 'sql/log_event.cc'
--- sql/log_event.cc 2013-06-06 19:32:29 +0000
+++ sql/log_event.cc 2013-06-18 10:35:35 +0000
@@ -2128,6 +2128,17 @@ log_event_print_value(IO_CACHE *file, co
return 4;
}
+ case MYSQL_TYPE_TIMESTAMP2:
+ {
+ char buf[MAX_DATE_STRING_REP_LENGTH];
+ struct timeval tm;
+ my_timestamp_from_binary(&tm, ptr, meta);
+ int buflen= my_timeval_to_str(&tm, buf, meta);
+ my_b_write(file, buf, buflen);
+ my_snprintf(typestr, typestr_length, "TIMESTAMP(%d)", meta);
+ return my_timestamp_binary_length(meta);
+ }
+
case MYSQL_TYPE_DATETIME:
{
ulong d, t;
@@ -2142,15 +2153,41 @@ log_event_print_value(IO_CACHE *file, co
return 8;
}
+ case MYSQL_TYPE_DATETIME2:
+ {
+ char buf[MAX_DATE_STRING_REP_LENGTH];
+ MYSQL_TIME ltime;
+ longlong packed= my_datetime_packed_from_binary(ptr, meta);
+ TIME_from_longlong_datetime_packed(<ime, packed);
+ int buflen= my_datetime_to_str(<ime, buf, meta);
+ my_b_write_quoted(file, (uchar *) buf, buflen);
+ my_snprintf(typestr, typestr_length, "DATETIME(%d)", meta);
+ return my_datetime_binary_length(meta);
+ }
+
case MYSQL_TYPE_TIME:
{
- uint32 i32= uint3korr(ptr);
- my_b_printf(file, "'%02d:%02d:%02d'",
- i32 / 10000, (i32 % 10000) / 100, i32 % 100);
+ int32 tmp= sint3korr(ptr);
+ int32 i32= tmp >= 0 ? tmp : - tmp;
+ const char *sign= tmp < 0 ? "-" : "";
+ my_b_printf(file, "'%s%02d:%02d:%02d'",
+ sign, i32 / 10000, (i32 % 10000) / 100, i32 % 100, i32);
my_snprintf(typestr, typestr_length, "TIME");
return 3;
}
-
+
+ case MYSQL_TYPE_TIME2:
+ {
+ char buf[MAX_DATE_STRING_REP_LENGTH];
+ MYSQL_TIME ltime;
+ longlong packed= my_time_packed_from_binary(ptr, meta);
+ TIME_from_longlong_time_packed(<ime, packed);
+ int buflen= my_time_to_str(<ime, buf, meta);
+ my_b_write_quoted(file, (uchar *) buf, buflen);
+ my_snprintf(typestr, typestr_length, "TIME(%d)", meta);
+ return my_time_binary_length(meta);
+ }
+
case MYSQL_TYPE_NEWDATE:
{
uint32 tmp= uint3korr(ptr);
@@ -9860,7 +9897,7 @@ Table_map_log_event::Table_map_log_event
{
m_coltype= reinterpret_cast<uchar*>(m_memory);
for (unsigned int i= 0 ; i < m_table->s->fields ; ++i)
- m_coltype[i]= m_table->field[i]->type();
+ m_coltype[i]= m_table->field[i]->binlog_type();
}
/*
=== modified file 'sql/opt_range.cc'
--- sql/opt_range.cc 2013-06-06 19:32:29 +0000
+++ sql/opt_range.cc 2013-06-18 10:35:35 +0000
@@ -8014,10 +8014,10 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND
*/
if (field->result_type() == STRING_RESULT &&
- ((Field_str*) field)->match_collation_to_optimize_range() &&
+ field->match_collation_to_optimize_range() &&
value->result_type() == STRING_RESULT &&
key_part->image_type == Field::itRAW &&
- ((Field_str*)field)->charset() != conf_func->compare_collation() &&
+ field->charset() != conf_func->compare_collation() &&
!(conf_func->compare_collation()->state & MY_CS_BINSORT &&
(type == Item_func::EQUAL_FUNC || type == Item_func::EQ_FUNC)))
goto end;
@@ -12885,7 +12885,7 @@ check_group_min_max_predicates(Item *con
*/
((args[1]->result_type() == STRING_RESULT &&
image_type == Field::itRAW &&
- ((Field_str*) min_max_arg_item->field)->charset() !=
+ min_max_arg_item->field->charset() !=
pred->compare_collation())
||
/*
=== modified file 'sql/opt_table_elimination.cc'
--- sql/opt_table_elimination.cc 2012-02-17 11:19:38 +0000
+++ sql/opt_table_elimination.cc 2013-06-18 10:35:35 +0000
@@ -1482,7 +1482,7 @@ void check_equality(Dep_analysis_context
collation of the operation differ from the field collation.
*/
if (field->cmp_type() == STRING_RESULT &&
- ((Field_str*)field)->charset() != cond->compare_collation())
+ field->charset() != cond->compare_collation())
return;
}
}
=== modified file 'sql/rpl_utility.cc'
--- sql/rpl_utility.cc 2013-06-06 15:51:28 +0000
+++ sql/rpl_utility.cc 2013-06-19 05:07:00 +0000
@@ -109,12 +109,15 @@ max_display_length_for_field(enum_field_
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_TIME2:
return 3;
case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_TIMESTAMP2:
return 4;
case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_DATETIME2:
return 8;
case MYSQL_TYPE_BIT:
@@ -262,12 +265,21 @@ uint32 table_def::calc_field_size(uint c
case MYSQL_TYPE_TIME:
length= 3;
break;
+ case MYSQL_TYPE_TIME2:
+ length= my_time_binary_length(m_field_metadata[col]);
+ break;
case MYSQL_TYPE_TIMESTAMP:
length= 4;
break;
+ case MYSQL_TYPE_TIMESTAMP2:
+ length= my_timestamp_binary_length(m_field_metadata[col]);
+ break;
case MYSQL_TYPE_DATETIME:
length= 8;
break;
+ case MYSQL_TYPE_DATETIME2:
+ length= my_datetime_binary_length(m_field_metadata[col]);
+ break;
case MYSQL_TYPE_BIT:
{
/*
@@ -376,6 +388,7 @@ void show_sql_type(enum_field_types type
break;
case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_TIMESTAMP2:
str->set_ascii(STRING_WITH_LEN("timestamp"));
break;
@@ -393,10 +406,12 @@ void show_sql_type(enum_field_types type
break;
case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_TIME2:
str->set_ascii(STRING_WITH_LEN("time"));
break;
case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_DATETIME2:
str->set_ascii(STRING_WITH_LEN("datetime"));
break;
@@ -615,6 +630,23 @@ can_convert_field_to(Field *field,
else
DBUG_RETURN(false);
}
+ else if (metadata == 0 &&
+ ((field->real_type() == MYSQL_TYPE_TIMESTAMP2 &&
+ source_type == MYSQL_TYPE_TIMESTAMP) ||
+ (field->real_type() == MYSQL_TYPE_TIME2 &&
+ source_type == MYSQL_TYPE_TIME) ||
+ (field->real_type() == MYSQL_TYPE_DATETIME2 &&
+ source_type == MYSQL_TYPE_DATETIME)))
+ {
+ /*
+ TS-TODO: conversion from FSP1>FSP2.
+ Can do non-lossy conversion
+ from old TIME, TIMESTAMP, DATETIME
+ to MySQL56 TIME(0), TIMESTAMP(0), DATETIME(0).
+ */
+ *order_var= -1;
+ DBUG_RETURN(true);
+ }
else if (!slave_type_conversions_options)
DBUG_RETURN(false);
@@ -739,6 +771,9 @@ can_convert_field_to(Field *field,
case MYSQL_TYPE_NULL:
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_TIMESTAMP2:
+ case MYSQL_TYPE_DATETIME2:
+ case MYSQL_TYPE_TIME2:
DBUG_RETURN(false);
}
DBUG_RETURN(false); // To keep GCC happy
@@ -939,7 +974,7 @@ TABLE *table_def::create_conversion_tabl
DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d,"
" maybe_null: %d, unsigned_flag: %d, pack_length: %u",
- type(col), target_table->field[col]->field_name,
+ binlog_type(col), target_table->field[col]->field_name,
max_length, decimals, TRUE, FALSE, pack_length));
field_def->init_for_tmp_table(type(col),
max_length,
@@ -993,7 +1028,7 @@ table_def::table_def(unsigned char *type
int index= 0;
for (unsigned int i= 0; i < m_size; i++)
{
- switch (m_type[i]) {
+ switch (binlog_type(i)) {
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
@@ -1042,6 +1077,11 @@ table_def::table_def(unsigned char *type
m_field_metadata[i]= x;
break;
}
+ case MYSQL_TYPE_TIME2:
+ case MYSQL_TYPE_DATETIME2:
+ case MYSQL_TYPE_TIMESTAMP2:
+ m_field_metadata[i]= field_metadata[index++];
+ break;
default:
m_field_metadata[i]= 0;
break;
=== modified file 'sql/rpl_utility.h'
--- sql/rpl_utility.h 2013-05-07 11:05:09 +0000
+++ sql/rpl_utility.h 2013-06-18 10:35:35 +0000
@@ -65,6 +65,14 @@ class table_def
ulong size() const { return m_size; }
+ /**
+ Returns internal binlog type code for one field,
+ without translation to real types.
+ */
+ enum_field_types binlog_type(ulong index) const
+ {
+ return static_cast<enum_field_types>(m_type[index]);
+ }
/*
Return a representation of the type data for one field.
@@ -82,7 +90,7 @@ class table_def
either MYSQL_TYPE_STRING, MYSQL_TYPE_ENUM, or MYSQL_TYPE_SET, so
we might need to modify the type to get the real type.
*/
- enum_field_types source_type= static_cast<enum_field_types>(m_type[index]);
+ enum_field_types source_type= binlog_type(index);
uint16 source_metadata= m_field_metadata[index];
switch (source_type)
{
=== modified file 'sql/sql_partition.cc'
--- sql/sql_partition.cc 2013-06-06 15:51:28 +0000
+++ sql/sql_partition.cc 2013-06-18 10:35:35 +0000
@@ -1563,7 +1563,7 @@ bool field_is_partition_charset(Field *f
!(field->type() == MYSQL_TYPE_VARCHAR))
return FALSE;
{
- CHARSET_INFO *cs= ((Field_str*)field)->charset();
+ CHARSET_INFO *cs= field->charset();
if (!(field->type() == MYSQL_TYPE_STRING) ||
!(cs->state & MY_CS_BINSORT))
return TRUE;
@@ -1606,7 +1606,7 @@ bool check_part_func_fields(Field **ptr,
*/
if (field_is_partition_charset(field))
{
- CHARSET_INFO *cs= ((Field_str*)field)->charset();
+ CHARSET_INFO *cs= field->charset();
if (!ok_with_charsets ||
cs->mbmaxlen > 1 ||
cs->strxfrm_multiply > 1)
@@ -2090,6 +2090,8 @@ static int check_part_field(enum_field_t
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIME2:
+ case MYSQL_TYPE_DATETIME2:
*result_type= STRING_RESULT;
*need_cs_check= TRUE;
return FALSE;
@@ -2102,6 +2104,7 @@ static int check_part_field(enum_field_t
case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_TIMESTAMP2:
case MYSQL_TYPE_NULL:
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
@@ -2974,7 +2977,7 @@ static void copy_to_part_field_buffers(F
restore_ptr++;
if (!field->maybe_null() || !field->is_null())
{
- CHARSET_INFO *cs= ((Field_str*)field)->charset();
+ CHARSET_INFO *cs= field->charset();
uint max_len= field->pack_length();
uint data_len= field->data_length();
uchar *field_buf= *field_bufs;
=== modified file 'sql/sql_select.cc'
--- sql/sql_select.cc 2013-06-06 19:32:29 +0000
+++ sql/sql_select.cc 2013-06-18 10:35:35 +0000
@@ -4307,7 +4307,7 @@ add_key_field(JOIN *join,
{
if ((*value)->cmp_type() != STRING_RESULT)
return;
- if (((Field_str*)field)->charset() != cond->compare_collation())
+ if (field->charset() != cond->compare_collation())
return;
}
}
@@ -11857,7 +11857,7 @@ static bool check_simple_equality(Item *
if (field_item->cmp_type() == STRING_RESULT)
{
- CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset();
+ CHARSET_INFO *cs= field_item->field->charset();
if (!item)
{
Item_func_eq *eq_item;
=== modified file 'sql/sql_table.cc'
--- sql/sql_table.cc 2013-06-06 19:32:29 +0000
+++ sql/sql_table.cc 2013-06-18 10:35:36 +0000
@@ -2790,6 +2790,8 @@ int prepare_create_field(Create_field *s
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIME2:
+ case MYSQL_TYPE_DATETIME2:
case MYSQL_TYPE_NULL:
sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
break;
@@ -2808,6 +2810,7 @@ int prepare_create_field(Create_field *s
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
break;
case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_TIMESTAMP2:
/* fall-through */
default:
sql_field->pack_flag=(FIELDFLAG_NUMBER |
@@ -2893,7 +2896,7 @@ void promote_first_timestamp_column(List
while ((column_definition= it++) != NULL)
{
- if (column_definition->sql_type == MYSQL_TYPE_TIMESTAMP || // TIMESTAMP
+ if (is_timestamp_type(column_definition->sql_type) || // TIMESTAMP
column_definition->unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy
{
if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
@@ -3854,7 +3857,7 @@ mysql_prepare_create_table(THD *thd, HA_
if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
!sql_field->def &&
- sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
+ is_timestamp_type(sql_field->sql_type) &&
(sql_field->flags & NOT_NULL_FLAG) &&
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
{
@@ -5950,7 +5953,8 @@ mysql_prepare_alter_table(THD *thd, TABL
*/
if ((def->sql_type == MYSQL_TYPE_DATE ||
def->sql_type == MYSQL_TYPE_NEWDATE ||
- def->sql_type == MYSQL_TYPE_DATETIME) &&
+ def->sql_type == MYSQL_TYPE_DATETIME ||
+ def->sql_type == MYSQL_TYPE_DATETIME2) &&
!alter_info->datetime_field &&
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
thd->variables.sql_mode & MODE_NO_ZERO_DATE)
@@ -7582,6 +7586,7 @@ bool mysql_alter_table(THD *thd,char *ne
t_type= MYSQL_TIMESTAMP_DATE;
break;
case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_DATETIME2:
f_val= "0000-00-00 00:00:00";
t_type= MYSQL_TIMESTAMP_DATETIME;
break;
=== modified file 'sql/sql_time.h'
--- sql/sql_time.h 2012-08-31 12:15:52 +0000
+++ sql/sql_time.h 2013-06-18 10:35:36 +0000
@@ -110,4 +110,23 @@ extern DATE_TIME_FORMAT global_time_form
extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];
extern LEX_STRING interval_type_to_name[];
+/* Date/time rounding and truncation functions */
+inline long my_time_fraction_remainder(long nr, uint decimals)
+{
+ DBUG_ASSERT(decimals <= TIME_SECOND_PART_DIGITS);
+ return nr % (long) log_10_int[TIME_SECOND_PART_DIGITS - decimals];
+}
+inline void my_time_trunc(MYSQL_TIME *ltime, uint decimals)
+{
+ ltime->second_part-= my_time_fraction_remainder(ltime->second_part, decimals);
+}
+inline void my_datetime_trunc(MYSQL_TIME *ltime, uint decimals)
+{
+ return my_time_trunc(ltime, decimals);
+}
+inline void my_timeval_trunc(struct timeval *tv, uint decimals)
+{
+ tv->tv_usec-= my_time_fraction_remainder(tv->tv_usec, decimals);
+}
+
#endif /* SQL_TIME_INCLUDED */
=== modified file 'sql/table.cc'
--- sql/table.cc 2013-06-06 19:32:29 +0000
+++ sql/table.cc 2013-06-18 10:35:36 +0000
@@ -3281,7 +3281,7 @@ bool get_field(MEM_ROOT *mem, Field *fie
}
if (!(to= strmake_root(mem, str.ptr(), length)))
length= 0; // Safety fix
- res->set(to, length, ((Field_str*)field)->charset());
+ res->set(to, length, field->charset());
return 0;
}
=== modified file 'storage/perfschema/pfs_engine_table.cc'
--- storage/perfschema/pfs_engine_table.cc 2013-06-06 19:32:29 +0000
+++ storage/perfschema/pfs_engine_table.cc 2013-06-18 10:35:36 +0000
@@ -514,7 +514,7 @@ void PFS_engine_table::set_field_enum(Fi
void PFS_engine_table::set_field_timestamp(Field *f, ulonglong value)
{
- DBUG_ASSERT(f->real_type() == MYSQL_TYPE_TIMESTAMP);
+ DBUG_ASSERT(is_timestamp_type(f->real_type()));
Field_timestamp *f2= (Field_timestamp*) f;
f2->store_TIME((long)(value / 1000000), (value % 1000000));
}
Follow ups