mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
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:
parent
99019afccc
commit
5b0774ee1c
43 changed files with 1813 additions and 559 deletions
|
@ -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"
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
89
mysql-test/r/type_temporal_mysql56.result
Normal file
89
mysql-test/r/type_temporal_mysql56.result
Normal 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;
|
BIN
mysql-test/std_data/mysql56datetime.MYD
Normal file
BIN
mysql-test/std_data/mysql56datetime.MYD
Normal file
Binary file not shown.
BIN
mysql-test/std_data/mysql56datetime.MYI
Normal file
BIN
mysql-test/std_data/mysql56datetime.MYI
Normal file
Binary file not shown.
BIN
mysql-test/std_data/mysql56datetime.frm
Normal file
BIN
mysql-test/std_data/mysql56datetime.frm
Normal file
Binary file not shown.
BIN
mysql-test/std_data/mysql56time.MYD
Normal file
BIN
mysql-test/std_data/mysql56time.MYD
Normal file
Binary file not shown.
BIN
mysql-test/std_data/mysql56time.MYI
Normal file
BIN
mysql-test/std_data/mysql56time.MYI
Normal file
Binary file not shown.
BIN
mysql-test/std_data/mysql56time.frm
Normal file
BIN
mysql-test/std_data/mysql56time.frm
Normal file
Binary file not shown.
BIN
mysql-test/std_data/mysql56timestamp.MYD
Normal file
BIN
mysql-test/std_data/mysql56timestamp.MYD
Normal file
Binary file not shown.
BIN
mysql-test/std_data/mysql56timestamp.MYI
Normal file
BIN
mysql-test/std_data/mysql56timestamp.MYI
Normal file
Binary file not shown.
BIN
mysql-test/std_data/mysql56timestamp.frm
Normal file
BIN
mysql-test/std_data/mysql56timestamp.frm
Normal file
Binary file not shown.
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
84
mysql-test/suite/rpl/r/rpl_temporal_mysql56.result
Normal file
84
mysql-test/suite/rpl/r/rpl_temporal_mysql56.result
Normal 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
|
48
mysql-test/suite/rpl/t/rpl_temporal_mysql56.test
Normal file
48
mysql-test/suite/rpl/t/rpl_temporal_mysql56.test
Normal 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
|
23
mysql-test/t/type_temporal_mysql56.test
Normal file
23
mysql-test/t/type_temporal_mysql56.test
Normal 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;
|
|
@ -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.
|
||||
|
|
|
@ -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
445
sql/compat56.cc
Normal 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
46
sql/compat56.h
Normal 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 */
|
731
sql/field.cc
731
sql/field.cc
File diff suppressed because it is too large
Load diff
610
sql/field.h
610
sql/field.h
|
@ -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)
|
||||
|
|
19
sql/item.cc
19
sql/item.cc
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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(<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 +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();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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())
|
||||
||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue