Adding support for MySQL-5.6 temporal column types:

TIME, DATETIME, TIMESTAMP


added:
  mysql-test/r/type_temporal_mysql56.result
  mysql-test/std_data/mysql56datetime.MYD
  mysql-test/std_data/mysql56datetime.MYI
  mysql-test/std_data/mysql56datetime.frm
  mysql-test/std_data/mysql56time.MYD
  mysql-test/std_data/mysql56time.MYI
  mysql-test/std_data/mysql56time.frm
  mysql-test/std_data/mysql56timestamp.MYD
  mysql-test/std_data/mysql56timestamp.MYI
  mysql-test/std_data/mysql56timestamp.frm
  mysql-test/suite/rpl/r/rpl_temporal_mysql56.result
  mysql-test/suite/rpl/t/rpl_temporal_mysql56.test
  mysql-test/t/type_temporal_mysql56.test
  sql/compat56.cc
  sql/compat56.h
modified:
  client/mysqlbinlog.cc
  include/my_time.h
  include/mysql.h.pp
  include/mysql_com.h
  mysql-test/r/statistics.result
  mysql-test/r/strict.result
  mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_innodb.result
  mysql-test/suite/binlog/r/binlog_mysqlbinlog_row_myisam.result
  sql-common/my_time.c
  sql/CMakeLists.txt
  sql/field.cc
  sql/field.h
  sql/item.cc
  sql/item_strfunc.cc
  sql/item_sum.cc
  sql/item_timefunc.cc
  sql/log_event.cc
  sql/opt_range.cc
  sql/opt_table_elimination.cc
  sql/protocol.cc
  sql/rpl_utility.cc
  sql/rpl_utility.h
  sql/sql_partition.cc
  sql/sql_prepare.cc
  sql/sql_select.cc
  sql/sql_table.cc
  sql/table.cc
  storage/perfschema/pfs_engine_table.cc
This commit is contained in:
Alexander Barkov 2013-07-10 11:49:17 +04:00
parent 99019afccc
commit 5b0774ee1c
43 changed files with 1813 additions and 559 deletions

View file

@ -37,6 +37,7 @@
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
#include "sql_priv.h"
#include "log_event.h"
#include "compat56.h"
#include "sql_common.h"
#include "my_dir.h"
#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
@ -2562,3 +2563,4 @@ void *sql_alloc(size_t size)
#include "sql_string.cc"
#include "sql_list.cc"
#include "rpl_filter.cc"
#include "compat56.cc"

View file

@ -111,6 +111,8 @@ 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 +165,8 @@ int my_date_to_str(const MYSQL_TIME *l_time, char *to);
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];
@ -171,11 +175,22 @@ static inline longlong sec_part_unshift(longlong second_part, uint digits)
{
return second_part * (longlong)log_10_int[TIME_SECOND_PART_DIGITS - digits];
}
static inline ulong sec_part_truncate(ulong second_part, uint digits)
/* Date/time rounding and truncation functions */
static inline long my_time_fraction_remainder(long nr, uint decimals)
{
/* the cast here should be unnecessary! */
return second_part - second_part % (ulong)log_10_int[TIME_SECOND_PART_DIGITS - digits];
DBUG_ASSERT(decimals <= TIME_SECOND_PART_DIGITS);
return nr % (long) log_10_int[TIME_SECOND_PART_DIGITS - decimals];
}
static inline void my_time_trunc(MYSQL_TIME *ltime, uint decimals)
{
ltime->second_part-= my_time_fraction_remainder(ltime->second_part, decimals);
}
static inline void my_timeval_trunc(struct timeval *tv, uint decimals)
{
tv->tv_usec-= my_time_fraction_remainder(tv->tv_usec, decimals);
}
#define hrtime_to_my_time(X) ((my_time_t)hrtime_to_time(X))

View file

@ -49,6 +49,9 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
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,

View file

@ -400,6 +400,16 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
MYSQL_TYPE_BIT,
/*
mysql-5.6 compatibility temporal types.
They're only used internally for reading RBR
mysql-5.6 binary log events and mysql-5.6 frm files.
They're never sent to the client.
*/
MYSQL_TYPE_TIMESTAMP2,
MYSQL_TYPE_DATETIME2,
MYSQL_TYPE_TIME2,
MYSQL_TYPE_NEWDECIMAL=246,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,

View file

@ -220,7 +220,7 @@ db_name table_name column_name min_value max_value nulls_ratio avg_frequency his
test t1 a 0 49 0.0000 1.0000 4 SINGLE_PREC_HB 2E62A1D0
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000 4 SINGLE_PREC_HB 003FBFFF
test t1 c aaaa dddddddd 0.1250 7.0000 4 SINGLE_PREC_HB 0055AAFF
test t1 d 1989-03-12 1999-07-23 0.1500 8.5000 4 SINGLE_PREC_HB 009393FF
test t1 d 1989-03-12 1999-07-23 0.1500 8.5000 4 SINGLE_PREC_HB 001919FF
test t1 e 0.01 0.112 0.2250 6.2000 4 SINGLE_PREC_HB 000564E1
test t1 f 1 5 0.2000 6.4000 4 SINGLE_PREC_HB 3F7FBFBF
DELETE FROM mysql.column_stats;
@ -238,7 +238,7 @@ db_name table_name column_name min_value max_value nulls_ratio avg_frequency his
test t1 a 0 49 0.0000 1.0000 8 DOUBLE_PREC_HB 052F4363F4A1F9D0
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000 8 DOUBLE_PREC_HB 0000FF3FFFBFFFFF
test t1 c aaaa dddddddd 0.1250 7.0000 8 DOUBLE_PREC_HB 00005555AAAAFFFF
test t1 d 1989-03-12 1999-07-23 0.1500 8.5000 8 DOUBLE_PREC_HB 000026942694FFFF
test t1 d 1989-03-12 1999-07-23 0.1500 8.5000 8 DOUBLE_PREC_HB 0000031A031AFFFF
test t1 e 0.01 0.112 0.2250 6.2000 8 DOUBLE_PREC_HB 000005056464E1E1
test t1 f 1 5 0.2000 6.4000 8 DOUBLE_PREC_HB FF3FFF7FFFBFFFBF
DELETE FROM mysql.column_stats;

View file

@ -1135,7 +1135,7 @@ create table t1 (col1 date, col2 datetime, col3 timestamp);
insert into t1 values (0,0,0);
ERROR 22007: Incorrect date value: '0' for column 'col1' at row 1
insert into t1 values (0.0,0.0,0.0);
ERROR 22007: Incorrect date value: '0' for column 'col1' at row 1
ERROR 22007: Incorrect date value: '0.0' for column 'col1' at row 1
insert into t1 (col1) values (convert('0000-00-00',date));
ERROR 22007: Incorrect datetime value: '0000-00-00'
insert into t1 (col1) values (cast('0000-00-00' as date));

View file

@ -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;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -203,6 +203,29 @@ static uint skip_digits(const char **str, const char *end)
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 +355,14 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
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 +1129,27 @@ int my_TIME_to_str(const MYSQL_TIME *l_time, char *to, uint digits)
}
/**
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= longlong10_to_str((longlong) tm->tv_sec, to, 10);
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.

View file

@ -37,7 +37,7 @@ IF(SSL_DEFINES)
ENDIF()
SET (SQL_SOURCE
../sql-common/client.c derror.cc des_key_file.cc
../sql-common/client.c compat56.cc derror.cc des_key_file.cc
discover.cc ../libmysql/errmsg.c field.cc field_conv.cc
filesort_utils.cc
filesort.cc gstream.cc sha2.cc

445
sql/compat56.cc Normal file
View file

@ -0,0 +1,445 @@
/*
Copyright (c) 2004, 2012, Oracle and/or its affiliates.
Copyright (c) 2013, MariaDB Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include "my_global.h"
#include "compat56.h"
#include "myisampack.h"
#include "my_time.h"
/*** 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);
}
}
/****************************************/

46
sql/compat56.h Normal file
View file

@ -0,0 +1,46 @@
#ifndef COMPAT56_H_INCLUDED
#define COMPAT56_H_INCLUDED
/*
Copyright (c) 2004, 2012, Oracle and/or its affiliates.
Copyright (c) 2013 MariaDB Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/** 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 **/
#endif /* COMPAT56_H_INCLUDED */

File diff suppressed because it is too large Load diff

View file

@ -30,6 +30,7 @@
#include "sql_string.h" /* String */
#include "my_decimal.h" /* my_decimal */
#include "sql_error.h" /* MYSQL_ERROR */
#include "compat56.h"
class Send_field;
class Protocol;
@ -89,6 +90,42 @@ inline uint get_set_pack_length(int elements)
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 +465,54 @@ public:
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. For example,
it puts MYSQL_TYPE_STRING in case of CHAR, VARCHAR, SET and ENUM,
with extra data type details put into metadata.
Binlog behaviour slightly differs between various MySQL and MariaDB
versions for the temporal data types TIME, DATETIME and TIMESTAMP.
MySQL prior to 5.6 uses MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME
and MYSQL_TYPE_TIMESTAMP type codes in binlog and stores no
additional metadata.
MariaDB-5.3 implements new versions for TIME, DATATIME, TIMESTAMP
with fractional second precision, but uses the old format for the
types TIME(0), DATETIME(0), TIMESTAMP(0), and it still stores
MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME and MYSQL_TYPE_TIMESTAMP in binlog,
with no additional metadata.
So row-based replication between temporal data types of
different precision is not possible in MariaDB.
MySQL-5.6 also implements a new version of TIME, DATETIME, TIMESTAMP
which support fractional second precision 0..6, and use the new
format even for the types TIME(0), DATETIME(0), TIMESTAMP(0).
For these new data types, MySQL-5.6 stores new type codes
MYSQL_TYPE_TIME2, MYSQL_TYPE_DATETIME2, MYSQL_TYPE_TIMESTAMP2 in binlog,
with fractional precision 0..6 put into metadata.
This makes it in theory possible to do row-based replication between
columns of different fractional precision (e.g. from TIME(1) on master
to TIME(6) on slave). However, it's not currently fully implemented yet.
MySQL-5.6 can only do row-based replication from the old types
TIME, DATETIME, TIMESTAMP (represented by MYSQL_TYPE_TIME,
MYSQL_TYPE_DATETIME and MYSQL_TYPE_TIMESTAMP type codes in binlog)
to the new corresponding types TIME(0), DATETIME(0), TIMESTAMP(0).
Note: MariaDB starting from the version 10.0 understands the new
MySQL-5.6 type codes MYSQL_TYPE_TIME2, MYSQL_TYPE_DATETIME2,
MYSQL_TYPE_TIMESTAMP2. When started over MySQL-5.6 tables both on
master and on slave, MariaDB-10.0 can also do row-based replication
from the old types TIME, DATETIME, TIMESTAMP to the new MySQL-5.6
types TIME(0), DATETIME(0), TIMESTAMP(0).
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 +746,16 @@ public:
{ 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 +903,8 @@ protected:
{
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 +943,10 @@ public:
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 +959,11 @@ public:
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 +981,10 @@ public:
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 +1004,7 @@ public:
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 +1414,6 @@ public:
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 +1435,67 @@ public:
};
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());
}
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_real(min, max);
}
};
/**
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);
int store_decimal(const my_decimal *);
};
class Field_timestamp :public Field_temporal {
protected:
int store_TIME_with_warning(THD *, MYSQL_TIME *, const ErrConv *,
bool, bool);
@ -1353,21 +1503,14 @@ public:
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);
int store_time_dec(MYSQL_TIME *ltime, uint dec);
int store_decimal(const my_decimal *);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@ -1377,7 +1520,6 @@ public:
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 +1560,109 @@ public:
{
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 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);
}
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);
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 +1689,24 @@ public:
};
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 +1717,22 @@ public:
{
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 +1741,22 @@ public:
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 +1764,7 @@ public:
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; }
int store_decimal(const my_decimal *);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@ -1599,55 +1774,122 @@ public:
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; }
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);
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 +1898,6 @@ public:
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 +1931,149 @@ public:
{
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);
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);
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); }
void sort_string(uchar *to, uint length)
{
DBUG_ASSERT(length == pack_length());
memcpy(to, ptr, length);
}
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
};
/**
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 *);
uint32 pack_length() const;
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
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);
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 +2100,6 @@ public:
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 +2180,6 @@ public:
}
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 +2275,6 @@ public:
: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 +2420,7 @@ public:
{ 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 +2458,6 @@ public:
}
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 +2610,10 @@ public:
{
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)

View file

@ -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;
};
@ -3218,11 +3221,7 @@ void Item_param::set_time(MYSQL_TIME *tm, timestamp_type time_type,
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 +5677,17 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length)
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,

View file

@ -3972,7 +3972,9 @@ bool Item_func_dyncol_create::prepare_arguments(bool force_names_arg)
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_arguments(bool force_names_arg)
type= DYN_COL_DATE;
break;
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_TIME2:
type= DYN_COL_TIME;
break;
case MYSQL_TYPE_VARCHAR:

View file

@ -1307,16 +1307,16 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table,
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);

View file

@ -1574,7 +1574,7 @@ static void set_sec_part(ulong sec_part, MYSQL_TIME *ltime, Item *item)
{
ltime->second_part= sec_part;
if (item->decimals < TIME_SECOND_PART_DIGITS)
ltime->second_part= sec_part_truncate(ltime->second_part, item->decimals);
my_time_trunc(ltime, item->decimals);
}
}
@ -2411,7 +2411,7 @@ bool Item_time_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
if (get_arg0_time(ltime))
return 1;
if (decimals < TIME_SECOND_PART_DIGITS)
ltime->second_part= sec_part_truncate(ltime->second_part, decimals);
my_time_trunc(ltime, decimals);
/*
MYSQL_TIMESTAMP_TIME value can have non-zero day part,
which we should not lose.
@ -2450,8 +2450,7 @@ bool Item_datetime_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
return 1;
if (decimals < TIME_SECOND_PART_DIGITS)
ltime->second_part= sec_part_truncate(ltime->second_part, decimals);
my_time_trunc(ltime, decimals);
/*
ltime is valid MYSQL_TYPE_TIME (according to fuzzy_date).

View file

@ -48,6 +48,7 @@
#include <my_dir.h>
#include "sql_show.h" // append_identifier
#include <strfunc.h>
#include "compat56.h"
#endif /* MYSQL_CLIENT */
@ -2128,6 +2129,17 @@ log_event_print_value(IO_CACHE *file, const uchar *ptr,
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 +2154,41 @@ log_event_print_value(IO_CACHE *file, const uchar *ptr,
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(&ltime, packed);
int buflen= my_datetime_to_str(&ltime, 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(&ltime, packed);
int buflen= my_time_to_str(&ltime, 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 +9898,7 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
{
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();
}
/*

View file

@ -8014,10 +8014,10 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
*/
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 *cond, Item_field *min_max_arg_item,
*/
((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())
||
/*

View file

@ -1482,7 +1482,7 @@ void check_equality(Dep_analysis_context *ctx, Dep_module_expr **eq_mod,
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;
}
}

View file

@ -1427,7 +1427,7 @@ bool Protocol_binary::store(MYSQL_TIME *tm, int decimals)
DBUG_ASSERT(decimals == AUTO_SEC_PART_DIGITS ||
(decimals >= 0 && decimals <= TIME_SECOND_PART_DIGITS));
if (decimals != AUTO_SEC_PART_DIGITS)
tm->second_part= sec_part_truncate(tm->second_part, decimals);
my_time_trunc(tm, decimals);
int4store(pos+7, tm->second_part);
if (tm->second_part)
length=11;
@ -1469,7 +1469,7 @@ bool Protocol_binary::store_time(MYSQL_TIME *tm, int decimals)
DBUG_ASSERT(decimals == AUTO_SEC_PART_DIGITS ||
(decimals >= 0 && decimals <= TIME_SECOND_PART_DIGITS));
if (decimals != AUTO_SEC_PART_DIGITS)
tm->second_part= sec_part_truncate(tm->second_part, decimals);
my_time_trunc(tm, decimals);
int4store(pos+8, tm->second_part);
if (tm->second_part)
length=12;

View file

@ -109,12 +109,15 @@ max_display_length_for_field(enum_field_types sql_type, unsigned int metadata)
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 col, uchar *master_data) const
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, uint16 metadata, String *str, CHARSET_
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, uint16 metadata, String *str, CHARSET_
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_table(THD *thd, Relay_log_info *rli, TABLE *
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 *types, ulong size,
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 *types, ulong size,
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;

View file

@ -65,6 +65,14 @@ public:
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 @@ public:
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)
{

View file

@ -1563,7 +1563,7 @@ bool field_is_partition_charset(Field *field)
!(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, bool ok_with_charsets)
*/
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_types sql_type,
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_types sql_type,
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(Field **ptr,
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;

View file

@ -4409,7 +4409,7 @@ bool Protocol_local::store(const char *str, size_t length,
bool Protocol_local::store(MYSQL_TIME *time, int decimals)
{
if (decimals != AUTO_SEC_PART_DIGITS)
time->second_part= sec_part_truncate(time->second_part, decimals);
my_time_trunc(time, decimals);
return store_column(time, sizeof(MYSQL_TIME));
}
@ -4427,7 +4427,7 @@ bool Protocol_local::store_date(MYSQL_TIME *time)
bool Protocol_local::store_time(MYSQL_TIME *time, int decimals)
{
if (decimals != AUTO_SEC_PART_DIGITS)
time->second_part= sec_part_truncate(time->second_part, decimals);
my_time_trunc(time, decimals);
return store_column(time, sizeof(MYSQL_TIME));
}

View file

@ -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 *left_item, Item *right_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;

View file

@ -2790,6 +2790,8 @@ int prepare_create_field(Create_field *sql_field,
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 *sql_field,
(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<Create_field> *column_definitions)
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_CREATE_INFO *create_info,
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, TABLE *table,
*/
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 @@ err:
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;

View file

@ -3281,7 +3281,7 @@ bool get_field(MEM_ROOT *mem, Field *field, String *res)
}
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;
}

View file

@ -514,7 +514,7 @@ void PFS_engine_table::set_field_enum(Field *f, ulonglong value)
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));
}