diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-11-28 20:59:56 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-11-28 20:59:56 +0200 |
commit | 74b214e1c030748c965316404a9a01b97cd50007 (patch) | |
tree | c75f40ed1b4bbb6ee62fcd909312e66f191356ed | |
parent | 1883da2a7e7f1fff067b62fbfdc9174e24b93a12 (diff) | |
parent | 3a393f8c8422f52934f54f000068a13764a7d599 (diff) | |
download | mariadb-git-74b214e1c030748c965316404a9a01b97cd50007.tar.gz |
Merge 10.4 into HEAD
161 files changed, 8199 insertions, 1237 deletions
diff --git a/.travis.yml b/.travis.yml index 95e0796099b..629e3b31523 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ language: cpp os: - linux - osx -osx_image: xcode9.1 +osx_image: xcode10.1 compiler: - gcc - clang diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc index ea4cce92dda..d37c8e2f752 100644 --- a/extra/mariabackup/fil_cur.cc +++ b/extra/mariabackup/fil_cur.cc @@ -109,7 +109,6 @@ xb_fil_node_close_file( ut_a(fil_system.n_open > 0); fil_system.n_open--; - fil_n_file_opened--; if (node->space->purpose == FIL_TYPE_TABLESPACE && fil_is_user_tablespace_id(node->space->id)) { @@ -159,8 +158,11 @@ xb_fil_cur_open( /* In the backup mode we should already have a tablespace handle created by fil_ibd_load() unless it is a system tablespace. Otherwise we open the file here. */ - if (cursor->is_system() || srv_operation == SRV_OPERATION_RESTORE_DELTA - || xb_close_files) { + if (!node->is_open()) { + ut_ad(cursor->is_system() + || srv_operation == SRV_OPERATION_RESTORE_DELTA + || xb_close_files); + node->handle = os_file_create_simple_no_error_handling( 0, node->name, OS_FILE_OPEN, @@ -178,7 +180,6 @@ xb_fil_cur_open( mutex_enter(&fil_system.mutex); fil_system.n_open++; - fil_n_file_opened++; if (node->space->purpose == FIL_TYPE_TABLESPACE && fil_is_user_tablespace_id(node->space->id)) { diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 3bad9dcf9c9..a79ad40b8e2 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -3083,11 +3083,8 @@ xb_load_single_table_tablespace( ut_a(space != NULL); - if (!fil_node_create(file->filepath(), ulint(n_pages), space, - false, false)) { - ut_error; - } - + space->add(file->filepath(), OS_FILE_CLOSED, ulint(n_pages), + false, false); /* by opening the tablespace we forcing node and space objects in the cache to be populated with fields from space header */ space->open(); @@ -3764,22 +3761,17 @@ xb_filters_free() } /*********************************************************************//** -Creates or opens the log files and closes them. -@return DB_SUCCESS or error code */ +Create log file metadata. */ static -ulint +void open_or_create_log_file( /*====================*/ fil_space_t* space, - ibool* log_file_created, /*!< out: TRUE if new log file - created */ ulint i) /*!< in: log file number in group */ { char name[10000]; ulint dirnamelen; - *log_file_created = FALSE; - os_normalize_path(srv_log_group_home_dir); dirnamelen = strlen(srv_log_group_home_dir); @@ -3791,14 +3783,13 @@ open_or_create_log_file( name[dirnamelen++] = OS_PATH_SEPARATOR; } - sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i); + sprintf(name + dirnamelen, "%s%zu", "ib_logfile", i); ut_a(fil_validate()); - ut_a(fil_node_create(name, ulint(srv_log_file_size >> srv_page_size_shift), - space, false, false)); - - return(DB_SUCCESS); + space->add(name, OS_FILE_CLOSED, + ulint(srv_log_file_size >> srv_page_size_shift), + false, false); } /*********************************************************************** @@ -4058,13 +4049,6 @@ fail: xb_filters_init(); - { - ibool log_file_created; - ibool log_created = FALSE; - ibool log_opened = FALSE; - ulint err; - ulint i; - xb_fil_io_init(); srv_n_file_io_threads = srv_n_read_io_threads; @@ -4077,36 +4061,8 @@ fail: "innodb_redo_log", SRV_LOG_SPACE_FIRST_ID, 0, FIL_TYPE_LOG, NULL); - for (i = 0; i < srv_n_log_files; i++) { - err = open_or_create_log_file(space, &log_file_created, i); - if (err != DB_SUCCESS) { - goto fail; - } - - if (log_file_created) { - log_created = TRUE; - } else { - log_opened = TRUE; - } - if ((log_opened && log_created)) { - msg( - "mariabackup: Error: all log files must be created at the same time.\n" - "mariabackup: All log files must be created also in database creation.\n" - "mariabackup: If you want bigger or smaller log files, shut down the\n" - "mariabackup: database and make sure there were no errors in shutdown.\n" - "mariabackup: Then delete the existing log files. Edit the .cnf file\n" - "mariabackup: and start the database again.\n"); - - goto fail; - } - } - - /* log_file_created must not be TRUE, if online */ - if (log_file_created) { - msg("mariabackup: Something wrong with source files...\n"); - goto fail; - } - + for (ulint i = 0; i < srv_n_log_files; i++) { + open_or_create_log_file(space, i); } /* create extra LSN dir if it does not exist. */ diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 51e1bd1ab21..d0234a6b68e 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -295,6 +295,7 @@ int SSL_connect(SSL* ssl) sendClientHello(*ssl); if (!ssl->GetError()) ssl->useStates().UseConnect() = CLIENT_HELLO_SENT; + /* fall through */ case CLIENT_HELLO_SENT : neededState = ssl->getSecurity().get_resuming() ? @@ -302,13 +303,14 @@ int SSL_connect(SSL* ssl) while (ssl->getStates().getClient() < neededState) { if (ssl->GetError()) break; processReply(*ssl); - // if resumption failed, reset needed state + // if resumption failed, reset needed state if (neededState == serverFinishedComplete) if (!ssl->getSecurity().get_resuming()) neededState = serverHelloDoneComplete; } if (!ssl->GetError()) ssl->useStates().UseConnect() = FIRST_REPLY_DONE; + /* fall through */ case FIRST_REPLY_DONE : if(ssl->getCrypto().get_certManager().sendVerify()) @@ -326,6 +328,7 @@ int SSL_connect(SSL* ssl) if (!ssl->GetError()) ssl->useStates().UseConnect() = FINISHED_DONE; + /* fall through */ case FINISHED_DONE : if (!ssl->getSecurity().get_resuming()) @@ -335,6 +338,7 @@ int SSL_connect(SSL* ssl) } if (!ssl->GetError()) ssl->useStates().UseConnect() = SECOND_REPLY_DONE; + /* fall through */ case SECOND_REPLY_DONE : ssl->verifyState(serverFinishedComplete); @@ -343,7 +347,7 @@ int SSL_connect(SSL* ssl) if (ssl->GetError()) { GetErrors().Add(ssl->GetError()); return SSL_FATAL_ERROR; - } + } return SSL_SUCCESS; default : @@ -371,7 +375,6 @@ int SSL_accept(SSL* ssl) ssl->SetError(no_error); if (ssl->GetError() == YasslError(SSL_ERROR_WANT_WRITE)) { - ssl->SetError(no_error); ssl->SendWriteBuffered(); if (!ssl->GetError()) @@ -385,6 +388,7 @@ int SSL_accept(SSL* ssl) processReply(*ssl); if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_FIRST_REPLY_DONE; + /* fall through */ case ACCEPT_FIRST_REPLY_DONE : sendServerHello(*ssl); @@ -401,9 +405,10 @@ int SSL_accept(SSL* ssl) sendServerHelloDone(*ssl); ssl->flushBuffer(); } - + if (!ssl->GetError()) ssl->useStates().UseAccept() = SERVER_HELLO_DONE; + /* fall through */ case SERVER_HELLO_DONE : if (!ssl->getSecurity().get_resuming()) { @@ -414,6 +419,7 @@ int SSL_accept(SSL* ssl) } if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_SECOND_REPLY_DONE; + /* fall through */ case ACCEPT_SECOND_REPLY_DONE : sendChangeCipher(*ssl); @@ -422,6 +428,7 @@ int SSL_accept(SSL* ssl) if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_FINISHED_DONE; + /* fall through */ case ACCEPT_FINISHED_DONE : if (ssl->getSecurity().get_resuming()) { @@ -432,6 +439,7 @@ int SSL_accept(SSL* ssl) } if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_THIRD_REPLY_DONE; + /* fall through */ case ACCEPT_THIRD_REPLY_DONE : ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); diff --git a/include/my_time.h b/include/my_time.h index 94632bbbf38..27011be8b47 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -108,12 +108,14 @@ typedef struct st_mysql_time_status { int warnings; uint precision; + uint nanoseconds; } MYSQL_TIME_STATUS; static inline void my_time_status_init(MYSQL_TIME_STATUS *status) { status->warnings= 0; status->precision= 0; + status->nanoseconds= 0; } my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date, diff --git a/mysql-test/include/innodb_encrypt_tables.combinations b/mysql-test/include/innodb_encrypt_tables.combinations new file mode 100644 index 00000000000..cb32fea998a --- /dev/null +++ b/mysql-test/include/innodb_encrypt_tables.combinations @@ -0,0 +1,14 @@ +[crypt] +innodb_encrypt_tables=ON +plugin-load-add=$FILE_KEY_MANAGEMENT_SO +loose-file-key-management +loose-file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys.txt +file-key-management-encryption-algorithm=aes_ctr + +[clear] +innodb_encrypt_tables=OFF +plugin-load-add=$FILE_KEY_MANAGEMENT_SO +loose-file-key-management +loose-file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys.txt +file-key-management-encryption-algorithm=aes_ctr + diff --git a/mysql-test/include/innodb_encrypt_tables.inc b/mysql-test/include/innodb_encrypt_tables.inc new file mode 100644 index 00000000000..31ab7999aef --- /dev/null +++ b/mysql-test/include/innodb_encrypt_tables.inc @@ -0,0 +1,4 @@ +# The goal of including this file is to enable innodb_encrypt_tables combinations +# (see include/innodb_encrypt_tables.combinations) + +--source include/have_innodb.inc diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result index 8bd3774162b..007f5585c27 100644 --- a/mysql-test/main/func_time.result +++ b/mysql-test/main/func_time.result @@ -6295,3 +6295,14 @@ Warning 1292 Truncated incorrect time value: '50326 garbage' SELECT TIME('- 01:00:00'), TIME('- 1 01:00:00'); TIME('- 01:00:00') TIME('- 1 01:00:00') -01:00:00 -25:00:00 +# +# MDEV-17854 Assertion `decimals <= 6' failed in my_time_fraction_remainder on SELECT with NULLIF and FROM_UNIXTIME on incorrect time +# +SET time_zone='+00:00'; +SELECT NULLIF(FROM_UNIXTIME('foo'), '2012-12-12 21:10:14'); +NULLIF(FROM_UNIXTIME('foo'), '2012-12-12 21:10:14') +1970-01-01 00:00:00 +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: 'foo' +Warning 1292 Truncated incorrect DECIMAL value: 'foo' +SET time_zone=DEFAULT; diff --git a/mysql-test/main/func_time.test b/mysql-test/main/func_time.test index e47667ff7a2..630083ef97e 100644 --- a/mysql-test/main/func_time.test +++ b/mysql-test/main/func_time.test @@ -3123,3 +3123,12 @@ SELECT CAST('50326 garbage' as time); SELECT TIME('- 01:00:00'), TIME('- 1 01:00:00'); + + +--echo # +--echo # MDEV-17854 Assertion `decimals <= 6' failed in my_time_fraction_remainder on SELECT with NULLIF and FROM_UNIXTIME on incorrect time +--echo # + +SET time_zone='+00:00'; +SELECT NULLIF(FROM_UNIXTIME('foo'), '2012-12-12 21:10:14'); +SET time_zone=DEFAULT; diff --git a/mysql-test/main/func_time_round.result b/mysql-test/main/func_time_round.result new file mode 100644 index 00000000000..208baae8cf9 --- /dev/null +++ b/mysql-test/main/func_time_round.result @@ -0,0 +1,1374 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; +CREATE TABLE t1_datetime_in_varchar (id SERIAL, a VARCHAR(64)); +INSERT INTO t1_datetime_in_varchar (a) VALUES +('2000-12-31 23:59:59'), +('2000-12-31 23:59:59.9'), +('2000-12-31 23:59:59.99'), +('2000-12-31 23:59:59.999'), +('2000-12-31 23:59:59.9999'), +('2000-12-31 23:59:59.99999'), +('2000-12-31 23:59:59.999999'), +('2000-12-31 23:59:59.9999999'); +CREATE TABLE t1_datetime_in_decimal (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_datetime_in_decimal (a) VALUES +(20001231235959), +(20001231235959.9), +(20001231235959.99), +(20001231235959.999), +(20001231235959.9999), +(20001231235959.99999), +(20001231235959.999999), +(20001231235959.9999999); +CREATE TABLE t1_time_in_varchar (id SERIAL, a VARCHAR(64)); +INSERT INTO t1_time_in_varchar (a) VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.99'), +('00:00:00.999'), +('00:00:00.9999'), +('00:00:00.99999'), +('00:00:00.999999'), +('00:00:00.9999999'); +INSERT INTO t1_time_in_varchar (a) VALUES +('837:59:59.9999999'), +('838:59:59'), +('838:59:59.9'), +('838:59:59.99'), +('838:59:59.999'), +('838:59:59.9999'), +('838:59:59.99999'), +('838:59:59.999999'), +('838:59:59.9999999'), +('839:59:59.9999999'), +('87649414:59:59.999999'), +('87649414:59:59.9999999'), +('87649415:59:59.999999'), +('87649415:59:59.9999999'); +CREATE TABLE t1_time_in_decimal (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_time_in_decimal (a) VALUES +(0), +(0.9), +(0.99), +(0.999), +(0.9999), +(0.99999), +(0.999999), +(0.9999999); +INSERT INTO t1_time_in_decimal (a) VALUES +(8375959.9999999), +(8385959), +(8385959.9), +(8385959.99), +(8385959.999), +(8385959.9999), +(8385959.99999), +(8385959.999999), +(8385959.9999999), +(8395959.9999999), +(876494145959.999999), +(876494145959.9999999), +(876494155959.999999), +(876494155959.9999999); +# +# TIME: LEAST/GREATEST +# +SELECT GREATEST(TIME'00:00:00', a) FROM t1_time_in_varchar; +GREATEST(TIME'00:00:00', a) +00:00:00.000000 +00:00:00.900000 +00:00:00.990000 +00:00:00.999000 +00:00:00.999900 +00:00:00.999990 +00:00:00.999999 +00:00:01.000000 +838:00:00.000000 +838:59:59.000000 +838:59:59.900000 +838:59:59.990000 +838:59:59.999000 +838:59:59.999900 +838:59:59.999990 +838:59:59.999999 +838:59:59.999999 +838:59:59.999999 +838:59:59.999999 +838:59:59.999999 +838:59:59.999999 +838:59:59.999999 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Warning 1292 Truncated incorrect time value: '838:59:59.9999999' +Warning 1292 Truncated incorrect time value: '839:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649414:59:59.999999' +Warning 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +SELECT GREATEST(TIME'00:00:00', a) FROM t1_time_in_decimal; +GREATEST(TIME'00:00:00', a) +00:00:00.000000 +00:00:00.900000 +00:00:00.990000 +00:00:00.999000 +00:00:00.999900 +00:00:00.999990 +00:00:00.999999 +00:00:01.000000 +838:00:00.000000 +838:59:59.000000 +838:59:59.900000 +838:59:59.990000 +838:59:59.999000 +838:59:59.999900 +838:59:59.999990 +838:59:59.999999 +838:59:59.999999 +838:59:59.999999 +NULL +NULL +NULL +NULL +Warnings: +Warning 1292 Incorrect time value: '8385959.9999999000' for column 'a' at row 17 +Warning 1292 Incorrect time value: '8395959.9999999000' for column 'a' at row 18 +Warning 1292 Incorrect time value: '876494145959.9999990000' for column 'a' at row 19 +Warning 1292 Incorrect time value: '876494145959.9999999000' for column 'a' at row 20 +Warning 1292 Incorrect time value: '876494155959.9999990000' for column 'a' at row 21 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column 'a' at row 22 +SELECT GREATEST(TIME'00:00:00', '00:00:00.0000004'); +GREATEST(TIME'00:00:00', '00:00:00.0000004') +00:00:00.000000 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.0000004' +SELECT GREATEST(TIME'00:00:00', 0.0000004); +GREATEST(TIME'00:00:00', 0.0000004) +00:00:00.000000 +SELECT GREATEST(TIME'00:00:00', '00:00:00.0000005'); +GREATEST(TIME'00:00:00', '00:00:00.0000005') +00:00:00.000001 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.0000005' +SELECT GREATEST(TIME'00:00:00', 0.0000005); +GREATEST(TIME'00:00:00', 0.0000005) +00:00:00.000001 +# +# Functions with a single TIME input, conversion from DATETIME-in-VARCHAR +# +SELECT SECOND(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +SECOND(a) CAST(a AS TIME(6)) a +59 23:59:59.000000 2000-12-31 23:59:59 +59 23:59:59.900000 2000-12-31 23:59:59.9 +59 23:59:59.990000 2000-12-31 23:59:59.99 +59 23:59:59.999000 2000-12-31 23:59:59.999 +59 23:59:59.999900 2000-12-31 23:59:59.9999 +59 23:59:59.999990 2000-12-31 23:59:59.99999 +59 23:59:59.999999 2000-12-31 23:59:59.999999 +0 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT MINUTE(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +MINUTE(a) CAST(a AS TIME(6)) a +59 23:59:59.000000 2000-12-31 23:59:59 +59 23:59:59.900000 2000-12-31 23:59:59.9 +59 23:59:59.990000 2000-12-31 23:59:59.99 +59 23:59:59.999000 2000-12-31 23:59:59.999 +59 23:59:59.999900 2000-12-31 23:59:59.9999 +59 23:59:59.999990 2000-12-31 23:59:59.99999 +59 23:59:59.999999 2000-12-31 23:59:59.999999 +0 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT HOUR(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +HOUR(a) CAST(a AS TIME(6)) a +23 23:59:59.000000 2000-12-31 23:59:59 +23 23:59:59.900000 2000-12-31 23:59:59.9 +23 23:59:59.990000 2000-12-31 23:59:59.99 +23 23:59:59.999000 2000-12-31 23:59:59.999 +23 23:59:59.999900 2000-12-31 23:59:59.9999 +23 23:59:59.999990 2000-12-31 23:59:59.99999 +23 23:59:59.999999 2000-12-31 23:59:59.999999 +0 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT EXTRACT(SECOND FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +EXTRACT(SECOND FROM a) CAST(a AS TIME(6)) a +59 23:59:59.000000 2000-12-31 23:59:59 +59 23:59:59.900000 2000-12-31 23:59:59.9 +59 23:59:59.990000 2000-12-31 23:59:59.99 +59 23:59:59.999000 2000-12-31 23:59:59.999 +59 23:59:59.999900 2000-12-31 23:59:59.9999 +59 23:59:59.999990 2000-12-31 23:59:59.99999 +59 23:59:59.999999 2000-12-31 23:59:59.999999 +0 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT EXTRACT(MINUTE FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +EXTRACT(MINUTE FROM a) CAST(a AS TIME(6)) a +59 23:59:59.000000 2000-12-31 23:59:59 +59 23:59:59.900000 2000-12-31 23:59:59.9 +59 23:59:59.990000 2000-12-31 23:59:59.99 +59 23:59:59.999000 2000-12-31 23:59:59.999 +59 23:59:59.999900 2000-12-31 23:59:59.9999 +59 23:59:59.999990 2000-12-31 23:59:59.99999 +59 23:59:59.999999 2000-12-31 23:59:59.999999 +0 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT EXTRACT(HOUR FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +EXTRACT(HOUR FROM a) CAST(a AS TIME(6)) a +23 23:59:59.000000 2000-12-31 23:59:59 +23 23:59:59.900000 2000-12-31 23:59:59.9 +23 23:59:59.990000 2000-12-31 23:59:59.99 +23 23:59:59.999000 2000-12-31 23:59:59.999 +23 23:59:59.999900 2000-12-31 23:59:59.9999 +23 23:59:59.999990 2000-12-31 23:59:59.99999 +23 23:59:59.999999 2000-12-31 23:59:59.999999 +0 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT TIME_TO_SEC(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +TIME_TO_SEC(a) CAST(a AS TIME(6)) a +86399.000000 23:59:59.000000 2000-12-31 23:59:59 +86399.900000 23:59:59.900000 2000-12-31 23:59:59.9 +86399.990000 23:59:59.990000 2000-12-31 23:59:59.99 +86399.999000 23:59:59.999000 2000-12-31 23:59:59.999 +86399.999900 23:59:59.999900 2000-12-31 23:59:59.9999 +86399.999990 23:59:59.999990 2000-12-31 23:59:59.99999 +86399.999999 23:59:59.999999 2000-12-31 23:59:59.999999 +0.000000 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +# +# Functions with a single TIME input, conversion from DATETIME-in-DECIMAL +# +SELECT SECOND(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +SECOND(a) CAST(a AS TIME(6)) a +59 23:59:59.000000 20001231235959.0000000000 +59 23:59:59.900000 20001231235959.9000000000 +59 23:59:59.990000 20001231235959.9900000000 +59 23:59:59.999000 20001231235959.9990000000 +59 23:59:59.999900 20001231235959.9999000000 +59 23:59:59.999990 20001231235959.9999900000 +59 23:59:59.999999 20001231235959.9999990000 +0 00:00:00.000000 20001231235959.9999999000 +SELECT MINUTE(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +MINUTE(a) CAST(a AS TIME(6)) a +59 23:59:59.000000 20001231235959.0000000000 +59 23:59:59.900000 20001231235959.9000000000 +59 23:59:59.990000 20001231235959.9900000000 +59 23:59:59.999000 20001231235959.9990000000 +59 23:59:59.999900 20001231235959.9999000000 +59 23:59:59.999990 20001231235959.9999900000 +59 23:59:59.999999 20001231235959.9999990000 +0 00:00:00.000000 20001231235959.9999999000 +SELECT HOUR(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +HOUR(a) CAST(a AS TIME(6)) a +23 23:59:59.000000 20001231235959.0000000000 +23 23:59:59.900000 20001231235959.9000000000 +23 23:59:59.990000 20001231235959.9900000000 +23 23:59:59.999000 20001231235959.9990000000 +23 23:59:59.999900 20001231235959.9999000000 +23 23:59:59.999990 20001231235959.9999900000 +23 23:59:59.999999 20001231235959.9999990000 +0 00:00:00.000000 20001231235959.9999999000 +SELECT EXTRACT(SECOND FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +EXTRACT(SECOND FROM a) CAST(a AS TIME(6)) a +59 23:59:59.000000 20001231235959.0000000000 +59 23:59:59.900000 20001231235959.9000000000 +59 23:59:59.990000 20001231235959.9900000000 +59 23:59:59.999000 20001231235959.9990000000 +59 23:59:59.999900 20001231235959.9999000000 +59 23:59:59.999990 20001231235959.9999900000 +59 23:59:59.999999 20001231235959.9999990000 +0 00:00:00.000000 20001231235959.9999999000 +SELECT EXTRACT(MINUTE FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +EXTRACT(MINUTE FROM a) CAST(a AS TIME(6)) a +59 23:59:59.000000 20001231235959.0000000000 +59 23:59:59.900000 20001231235959.9000000000 +59 23:59:59.990000 20001231235959.9900000000 +59 23:59:59.999000 20001231235959.9990000000 +59 23:59:59.999900 20001231235959.9999000000 +59 23:59:59.999990 20001231235959.9999900000 +59 23:59:59.999999 20001231235959.9999990000 +0 00:00:00.000000 20001231235959.9999999000 +SELECT EXTRACT(HOUR FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +EXTRACT(HOUR FROM a) CAST(a AS TIME(6)) a +23 23:59:59.000000 20001231235959.0000000000 +23 23:59:59.900000 20001231235959.9000000000 +23 23:59:59.990000 20001231235959.9900000000 +23 23:59:59.999000 20001231235959.9990000000 +23 23:59:59.999900 20001231235959.9999000000 +23 23:59:59.999990 20001231235959.9999900000 +23 23:59:59.999999 20001231235959.9999990000 +0 00:00:00.000000 20001231235959.9999999000 +SELECT TIME_TO_SEC(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +TIME_TO_SEC(a) CAST(a AS TIME(6)) a +86399.000000 23:59:59.000000 20001231235959.0000000000 +86399.900000 23:59:59.900000 20001231235959.9000000000 +86399.990000 23:59:59.990000 20001231235959.9900000000 +86399.999000 23:59:59.999000 20001231235959.9990000000 +86399.999900 23:59:59.999900 20001231235959.9999000000 +86399.999990 23:59:59.999990 20001231235959.9999900000 +86399.999999 23:59:59.999999 20001231235959.9999990000 +0.000000 00:00:00.000000 20001231235959.9999999000 +# +# Functions with a single TIME interval input, conversion from TIME-interval-in-VARCHAR +# +SELECT +EXTRACT(DAY FROM a), +EXTRACT(HOUR FROM a), +EXTRACT(MINUTE FROM a), +EXTRACT(SECOND FROM a), +EXTRACT(MICROSECOND FROM a), +CAST(a AS INTERVAL DAY_SECOND(6)), +a +FROM t1_time_in_varchar ORDER BY id; +EXTRACT(DAY FROM a) EXTRACT(HOUR FROM a) EXTRACT(MINUTE FROM a) EXTRACT(SECOND FROM a) EXTRACT(MICROSECOND FROM a) CAST(a AS INTERVAL DAY_SECOND(6)) a +0 0 0 0 0 00:00:00.000000 00:00:00 +0 0 0 0 900000 00:00:00.900000 00:00:00.9 +0 0 0 0 990000 00:00:00.990000 00:00:00.99 +0 0 0 0 999000 00:00:00.999000 00:00:00.999 +0 0 0 0 999900 00:00:00.999900 00:00:00.9999 +0 0 0 0 999990 00:00:00.999990 00:00:00.99999 +0 0 0 0 999999 00:00:00.999999 00:00:00.999999 +0 0 0 1 0 00:00:01.000000 00:00:00.9999999 +34 22 0 0 0 34 22:00:00.000000 837:59:59.9999999 +34 22 59 59 0 34 22:59:59.000000 838:59:59 +34 22 59 59 900000 34 22:59:59.900000 838:59:59.9 +34 22 59 59 990000 34 22:59:59.990000 838:59:59.99 +34 22 59 59 999000 34 22:59:59.999000 838:59:59.999 +34 22 59 59 999900 34 22:59:59.999900 838:59:59.9999 +34 22 59 59 999990 34 22:59:59.999990 838:59:59.99999 +34 22 59 59 999999 34 22:59:59.999999 838:59:59.999999 +34 23 0 0 0 34 23:00:00.000000 838:59:59.9999999 +35 0 0 0 0 35 00:00:00.000000 839:59:59.9999999 +3652058 22 59 59 999999 3652058 22:59:59.999999 87649414:59:59.999999 +3652058 23 0 0 0 3652058 23:00:00.000000 87649414:59:59.9999999 +3652058 23 59 59 999999 3652058 23:59:59.999999 87649415:59:59.999999 +3652058 23 59 59 999999 3652058 23:59:59.999999 87649415:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '837:59:59.9999999' +Note 1292 Truncated incorrect time value: '838:59:59.9999999' +Note 1292 Truncated incorrect time value: '838:59:59.9999999' +Note 1292 Truncated incorrect time value: '838:59:59.9999999' +Note 1292 Truncated incorrect time value: '838:59:59.9999999' +Note 1292 Truncated incorrect time value: '838:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '838:59:59.9999999' +Note 1292 Truncated incorrect time value: '839:59:59.9999999' +Note 1292 Truncated incorrect time value: '839:59:59.9999999' +Note 1292 Truncated incorrect time value: '839:59:59.9999999' +Note 1292 Truncated incorrect time value: '839:59:59.9999999' +Note 1292 Truncated incorrect time value: '839:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '839:59:59.9999999' +Note 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Note 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Note 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Note 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Note 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '87649414:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '87649415:59:59.9999999' +SELECT +TIME_TO_SEC(a), +CAST(a AS TIME(6)), +a +FROM t1_time_in_varchar ORDER BY id; +TIME_TO_SEC(a) CAST(a AS TIME(6)) a +0.000000 00:00:00.000000 00:00:00 +0.900000 00:00:00.900000 00:00:00.9 +0.990000 00:00:00.990000 00:00:00.99 +0.999000 00:00:00.999000 00:00:00.999 +0.999900 00:00:00.999900 00:00:00.9999 +0.999990 00:00:00.999990 00:00:00.99999 +0.999999 00:00:00.999999 00:00:00.999999 +1.000000 00:00:01.000000 00:00:00.9999999 +3016800.000000 838:00:00.000000 837:59:59.9999999 +3020399.000000 838:59:59.000000 838:59:59 +3020399.900000 838:59:59.900000 838:59:59.9 +3020399.990000 838:59:59.990000 838:59:59.99 +3020399.999000 838:59:59.999000 838:59:59.999 +3020399.999900 838:59:59.999900 838:59:59.9999 +3020399.999990 838:59:59.999990 838:59:59.99999 +3020399.999999 838:59:59.999999 838:59:59.999999 +3020399.999999 838:59:59.999999 838:59:59.9999999 +3020399.999999 838:59:59.999999 839:59:59.9999999 +3020399.999999 838:59:59.999999 87649414:59:59.999999 +3020399.999999 838:59:59.999999 87649414:59:59.9999999 +3020399.999999 838:59:59.999999 87649415:59:59.999999 +3020399.999999 838:59:59.999999 87649415:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Warning 1292 Truncated incorrect time value: '838:59:59.9999999' +Warning 1292 Truncated incorrect time value: '838:59:59.9999999' +Warning 1292 Truncated incorrect time value: '839:59:59.9999999' +Warning 1292 Truncated incorrect time value: '839:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649414:59:59.999999' +Warning 1292 Truncated incorrect time value: '87649414:59:59.999999' +Warning 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +# +# Functions with a single TIME interval input, conversion from TIME-interval-in-DECIMAL +# +SELECT +EXTRACT(DAY FROM a), +EXTRACT(HOUR FROM a), +EXTRACT(MINUTE FROM a), +EXTRACT(SECOND FROM a), +EXTRACT(MICROSECOND FROM a), +CAST(a AS INTERVAL DAY_SECOND(6)), +a +FROM t1_time_in_decimal ORDER BY id; +EXTRACT(DAY FROM a) EXTRACT(HOUR FROM a) EXTRACT(MINUTE FROM a) EXTRACT(SECOND FROM a) EXTRACT(MICROSECOND FROM a) CAST(a AS INTERVAL DAY_SECOND(6)) a +0 0 0 0 0 00:00:00.000000 0.0000000000 +0 0 0 0 900000 00:00:00.900000 0.9000000000 +0 0 0 0 990000 00:00:00.990000 0.9900000000 +0 0 0 0 999000 00:00:00.999000 0.9990000000 +0 0 0 0 999900 00:00:00.999900 0.9999000000 +0 0 0 0 999990 00:00:00.999990 0.9999900000 +0 0 0 0 999999 00:00:00.999999 0.9999990000 +0 0 0 1 0 00:00:01.000000 0.9999999000 +34 22 0 0 0 34 22:00:00.000000 8375959.9999999000 +34 22 59 59 0 34 22:59:59.000000 8385959.0000000000 +34 22 59 59 900000 34 22:59:59.900000 8385959.9000000000 +34 22 59 59 990000 34 22:59:59.990000 8385959.9900000000 +34 22 59 59 999000 34 22:59:59.999000 8385959.9990000000 +34 22 59 59 999900 34 22:59:59.999900 8385959.9999000000 +34 22 59 59 999990 34 22:59:59.999990 8385959.9999900000 +34 22 59 59 999999 34 22:59:59.999999 8385959.9999990000 +34 23 0 0 0 34 23:00:00.000000 8385959.9999999000 +35 0 0 0 0 35 00:00:00.000000 8395959.9999999000 +3652058 22 59 59 999999 3652058 22:59:59.999999 876494145959.9999990000 +3652058 23 0 0 0 3652058 23:00:00.000000 876494145959.9999999000 +3652058 23 59 59 999999 3652058 23:59:59.999999 876494155959.9999990000 +3652058 23 59 59 999999 3652058 23:59:59.999999 876494155959.9999999000 +Warnings: +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.0000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9900000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9990000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9999000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9999900000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9999990000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9999999000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8375959.9999999000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.0000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9900000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9990000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9999000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9999900000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9999990000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9999999000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8395959.9999999000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '876494145959.9999990000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '876494145959.9999999000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '876494155959.9999990000' +Warning 1292 Incorrect time value: '876494155959.9999999000' for column 'a' at row 22 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column 'a' at row 22 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column 'a' at row 22 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column 'a' at row 22 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column 'a' at row 22 +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '876494155959.9999999000' +SELECT +TIME_TO_SEC(a), +CAST(a AS TIME(6)), +a +FROM t1_time_in_decimal ORDER BY id; +TIME_TO_SEC(a) CAST(a AS TIME(6)) a +0.000000 00:00:00.000000 0.0000000000 +0.900000 00:00:00.900000 0.9000000000 +0.990000 00:00:00.990000 0.9900000000 +0.999000 00:00:00.999000 0.9990000000 +0.999900 00:00:00.999900 0.9999000000 +0.999990 00:00:00.999990 0.9999900000 +0.999999 00:00:00.999999 0.9999990000 +1.000000 00:00:01.000000 0.9999999000 +3016800.000000 838:00:00.000000 8375959.9999999000 +3020399.000000 838:59:59.000000 8385959.0000000000 +3020399.900000 838:59:59.900000 8385959.9000000000 +3020399.990000 838:59:59.990000 8385959.9900000000 +3020399.999000 838:59:59.999000 8385959.9990000000 +3020399.999900 838:59:59.999900 8385959.9999000000 +3020399.999990 838:59:59.999990 8385959.9999900000 +3020399.999999 838:59:59.999999 8385959.9999990000 +3020399.999999 838:59:59.999999 8385959.9999999000 +3020399.999999 838:59:59.999999 8395959.9999999000 +NULL NULL 876494145959.9999990000 +NULL NULL 876494145959.9999999000 +NULL NULL 876494155959.9999990000 +NULL NULL 876494155959.9999999000 +Warnings: +Warning 1292 Incorrect time value: '8385959.9999999000' for column 'a' at row 17 +Warning 1292 Incorrect time value: '8385959.9999999000' for column 'a' at row 17 +Warning 1292 Incorrect time value: '8395959.9999999000' for column 'a' at row 18 +Warning 1292 Incorrect time value: '8395959.9999999000' for column 'a' at row 18 +Warning 1292 Incorrect time value: '876494145959.9999990000' for column 'a' at row 19 +Warning 1292 Incorrect time value: '876494145959.9999990000' for column 'a' at row 19 +Warning 1292 Incorrect time value: '876494145959.9999999000' for column 'a' at row 20 +Warning 1292 Incorrect time value: '876494145959.9999999000' for column 'a' at row 20 +Warning 1292 Incorrect time value: '876494155959.9999990000' for column 'a' at row 21 +Warning 1292 Incorrect time value: '876494155959.9999990000' for column 'a' at row 21 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column 'a' at row 22 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column 'a' at row 22 +# +# Functions with a single DATE input, conversion from DATETIME-in-VARCHAR +# +SELECT QUARTER(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +QUARTER(a) CAST(a AS DATE) a +4 2000-12-31 2000-12-31 23:59:59 +4 2000-12-31 2000-12-31 23:59:59.9 +4 2000-12-31 2000-12-31 23:59:59.99 +4 2000-12-31 2000-12-31 23:59:59.999 +4 2000-12-31 2000-12-31 23:59:59.9999 +4 2000-12-31 2000-12-31 23:59:59.99999 +4 2000-12-31 2000-12-31 23:59:59.999999 +1 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +DAY(a) CAST(a AS DATE) a +31 2000-12-31 2000-12-31 23:59:59 +31 2000-12-31 2000-12-31 23:59:59.9 +31 2000-12-31 2000-12-31 23:59:59.99 +31 2000-12-31 2000-12-31 23:59:59.999 +31 2000-12-31 2000-12-31 23:59:59.9999 +31 2000-12-31 2000-12-31 23:59:59.99999 +31 2000-12-31 2000-12-31 23:59:59.999999 +1 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT MONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +MONTH(a) CAST(a AS DATE) a +12 2000-12-31 2000-12-31 23:59:59 +12 2000-12-31 2000-12-31 23:59:59.9 +12 2000-12-31 2000-12-31 23:59:59.99 +12 2000-12-31 2000-12-31 23:59:59.999 +12 2000-12-31 2000-12-31 23:59:59.9999 +12 2000-12-31 2000-12-31 23:59:59.99999 +12 2000-12-31 2000-12-31 23:59:59.999999 +1 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT YEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +YEAR(a) CAST(a AS DATE) a +2000 2000-12-31 2000-12-31 23:59:59 +2000 2000-12-31 2000-12-31 23:59:59.9 +2000 2000-12-31 2000-12-31 23:59:59.99 +2000 2000-12-31 2000-12-31 23:59:59.999 +2000 2000-12-31 2000-12-31 23:59:59.9999 +2000 2000-12-31 2000-12-31 23:59:59.99999 +2000 2000-12-31 2000-12-31 23:59:59.999999 +2001 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT DAYNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +DAYNAME(a) CAST(a AS DATE) a +Sunday 2000-12-31 2000-12-31 23:59:59 +Sunday 2000-12-31 2000-12-31 23:59:59.9 +Sunday 2000-12-31 2000-12-31 23:59:59.99 +Sunday 2000-12-31 2000-12-31 23:59:59.999 +Sunday 2000-12-31 2000-12-31 23:59:59.9999 +Sunday 2000-12-31 2000-12-31 23:59:59.99999 +Sunday 2000-12-31 2000-12-31 23:59:59.999999 +Monday 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT MONTHNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +MONTHNAME(a) CAST(a AS DATE) a +December 2000-12-31 2000-12-31 23:59:59 +December 2000-12-31 2000-12-31 23:59:59.9 +December 2000-12-31 2000-12-31 23:59:59.99 +December 2000-12-31 2000-12-31 23:59:59.999 +December 2000-12-31 2000-12-31 23:59:59.9999 +December 2000-12-31 2000-12-31 23:59:59.99999 +December 2000-12-31 2000-12-31 23:59:59.999999 +January 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT LAST_DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +LAST_DAY(a) CAST(a AS DATE) a +2000-12-31 2000-12-31 2000-12-31 23:59:59 +2000-12-31 2000-12-31 2000-12-31 23:59:59.9 +2000-12-31 2000-12-31 2000-12-31 23:59:59.99 +2000-12-31 2000-12-31 2000-12-31 23:59:59.999 +2000-12-31 2000-12-31 2000-12-31 23:59:59.9999 +2000-12-31 2000-12-31 2000-12-31 23:59:59.99999 +2000-12-31 2000-12-31 2000-12-31 23:59:59.999999 +2000-12-31 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT TO_DAYS(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +TO_DAYS(a) CAST(a AS DATE) a +730850 2000-12-31 2000-12-31 23:59:59 +730850 2000-12-31 2000-12-31 23:59:59.9 +730850 2000-12-31 2000-12-31 23:59:59.99 +730850 2000-12-31 2000-12-31 23:59:59.999 +730850 2000-12-31 2000-12-31 23:59:59.9999 +730850 2000-12-31 2000-12-31 23:59:59.99999 +730850 2000-12-31 2000-12-31 23:59:59.999999 +730851 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT DAYOFYEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +DAYOFYEAR(a) CAST(a AS DATE) a +366 2000-12-31 2000-12-31 23:59:59 +366 2000-12-31 2000-12-31 23:59:59.9 +366 2000-12-31 2000-12-31 23:59:59.99 +366 2000-12-31 2000-12-31 23:59:59.999 +366 2000-12-31 2000-12-31 23:59:59.9999 +366 2000-12-31 2000-12-31 23:59:59.99999 +366 2000-12-31 2000-12-31 23:59:59.999999 +1 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +CREATE TABLE t1 (a VARCHAR(32)); +INSERT INTO t1 VALUES +('2002-01-05 23:59:59'), +('2002-01-05 23:59:59.999999'), +('2002-01-05 23:59:59.9999999'); +SELECT YEARWEEK(a), a FROM t1; +YEARWEEK(a) a +200152 2002-01-05 23:59:59 +200152 2002-01-05 23:59:59.999999 +200201 2002-01-05 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2002-01-05 23:59:59.9999999' +SELECT WEEK(a), a FROM t1; +WEEK(a) a +0 2002-01-05 23:59:59 +0 2002-01-05 23:59:59.999999 +1 2002-01-05 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2002-01-05 23:59:59.9999999' +SELECT WEEKDAY(a), a FROM t1; +WEEKDAY(a) a +5 2002-01-05 23:59:59 +5 2002-01-05 23:59:59.999999 +6 2002-01-05 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2002-01-05 23:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(32,9)); +INSERT INTO t1 VALUES +(20020105235959), +(20020105235959.999999), +(20020105235959.9999999); +SELECT YEARWEEK(a), a FROM t1; +YEARWEEK(a) a +200152 20020105235959.000000000 +200152 20020105235959.999999000 +200201 20020105235959.999999900 +SELECT WEEK(a), a FROM t1; +WEEK(a) a +0 20020105235959.000000000 +0 20020105235959.999999000 +1 20020105235959.999999900 +SELECT WEEKDAY(a), a FROM t1; +WEEKDAY(a) a +5 20020105235959.000000000 +5 20020105235959.999999000 +6 20020105235959.999999900 +DROP TABLE t1; +# +# Functions with a single DATE input, conversion from DATETIME-in-DECIMAL +# +SELECT QUARTER(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +QUARTER(a) CAST(a AS DATE) a +4 2000-12-31 20001231235959.0000000000 +4 2000-12-31 20001231235959.9000000000 +4 2000-12-31 20001231235959.9900000000 +4 2000-12-31 20001231235959.9990000000 +4 2000-12-31 20001231235959.9999000000 +4 2000-12-31 20001231235959.9999900000 +4 2000-12-31 20001231235959.9999990000 +1 2000-12-31 20001231235959.9999999000 +SELECT DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +DAY(a) CAST(a AS DATE) a +31 2000-12-31 20001231235959.0000000000 +31 2000-12-31 20001231235959.9000000000 +31 2000-12-31 20001231235959.9900000000 +31 2000-12-31 20001231235959.9990000000 +31 2000-12-31 20001231235959.9999000000 +31 2000-12-31 20001231235959.9999900000 +31 2000-12-31 20001231235959.9999990000 +1 2000-12-31 20001231235959.9999999000 +SELECT MONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +MONTH(a) CAST(a AS DATE) a +12 2000-12-31 20001231235959.0000000000 +12 2000-12-31 20001231235959.9000000000 +12 2000-12-31 20001231235959.9900000000 +12 2000-12-31 20001231235959.9990000000 +12 2000-12-31 20001231235959.9999000000 +12 2000-12-31 20001231235959.9999900000 +12 2000-12-31 20001231235959.9999990000 +1 2000-12-31 20001231235959.9999999000 +SELECT YEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +YEAR(a) CAST(a AS DATE) a +2000 2000-12-31 20001231235959.0000000000 +2000 2000-12-31 20001231235959.9000000000 +2000 2000-12-31 20001231235959.9900000000 +2000 2000-12-31 20001231235959.9990000000 +2000 2000-12-31 20001231235959.9999000000 +2000 2000-12-31 20001231235959.9999900000 +2000 2000-12-31 20001231235959.9999990000 +2001 2000-12-31 20001231235959.9999999000 +SELECT DAYNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +DAYNAME(a) CAST(a AS DATE) a +Sunday 2000-12-31 20001231235959.0000000000 +Sunday 2000-12-31 20001231235959.9000000000 +Sunday 2000-12-31 20001231235959.9900000000 +Sunday 2000-12-31 20001231235959.9990000000 +Sunday 2000-12-31 20001231235959.9999000000 +Sunday 2000-12-31 20001231235959.9999900000 +Sunday 2000-12-31 20001231235959.9999990000 +Monday 2000-12-31 20001231235959.9999999000 +SELECT MONTHNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +MONTHNAME(a) CAST(a AS DATE) a +December 2000-12-31 20001231235959.0000000000 +December 2000-12-31 20001231235959.9000000000 +December 2000-12-31 20001231235959.9900000000 +December 2000-12-31 20001231235959.9990000000 +December 2000-12-31 20001231235959.9999000000 +December 2000-12-31 20001231235959.9999900000 +December 2000-12-31 20001231235959.9999990000 +January 2000-12-31 20001231235959.9999999000 +SELECT YEARWEEK(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +YEARWEEK(a) CAST(a AS DATE) a +200053 2000-12-31 20001231235959.0000000000 +200053 2000-12-31 20001231235959.9000000000 +200053 2000-12-31 20001231235959.9900000000 +200053 2000-12-31 20001231235959.9990000000 +200053 2000-12-31 20001231235959.9999000000 +200053 2000-12-31 20001231235959.9999900000 +200053 2000-12-31 20001231235959.9999990000 +200053 2000-12-31 20001231235959.9999999000 +SELECT LAST_DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +LAST_DAY(a) CAST(a AS DATE) a +2000-12-31 2000-12-31 20001231235959.0000000000 +2000-12-31 2000-12-31 20001231235959.9000000000 +2000-12-31 2000-12-31 20001231235959.9900000000 +2000-12-31 2000-12-31 20001231235959.9990000000 +2000-12-31 2000-12-31 20001231235959.9999000000 +2000-12-31 2000-12-31 20001231235959.9999900000 +2000-12-31 2000-12-31 20001231235959.9999990000 +2000-12-31 2000-12-31 20001231235959.9999999000 +SELECT TO_DAYS(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +TO_DAYS(a) CAST(a AS DATE) a +730850 2000-12-31 20001231235959.0000000000 +730850 2000-12-31 20001231235959.9000000000 +730850 2000-12-31 20001231235959.9900000000 +730850 2000-12-31 20001231235959.9990000000 +730850 2000-12-31 20001231235959.9999000000 +730850 2000-12-31 20001231235959.9999900000 +730850 2000-12-31 20001231235959.9999990000 +730851 2000-12-31 20001231235959.9999999000 +SELECT DAYOFYEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +DAYOFYEAR(a) CAST(a AS DATE) a +366 2000-12-31 20001231235959.0000000000 +366 2000-12-31 20001231235959.9000000000 +366 2000-12-31 20001231235959.9900000000 +366 2000-12-31 20001231235959.9990000000 +366 2000-12-31 20001231235959.9999000000 +366 2000-12-31 20001231235959.9999900000 +366 2000-12-31 20001231235959.9999990000 +1 2000-12-31 20001231235959.9999999000 +SELECT DAYOFMONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +DAYOFMONTH(a) CAST(a AS DATE) a +31 2000-12-31 20001231235959.0000000000 +31 2000-12-31 20001231235959.9000000000 +31 2000-12-31 20001231235959.9900000000 +31 2000-12-31 20001231235959.9990000000 +31 2000-12-31 20001231235959.9999000000 +31 2000-12-31 20001231235959.9999900000 +31 2000-12-31 20001231235959.9999990000 +1 2000-12-31 20001231235959.9999999000 +# +# Functions with a single DATETIME input, conversion from DATETIME-in-VARCHAR +# +SELECT TO_SECONDS(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +TO_SECONDS(a) CAST(a AS DATETIME(6)) a +63145526399 2000-12-31 23:59:59.000000 2000-12-31 23:59:59 +63145526399 2000-12-31 23:59:59.900000 2000-12-31 23:59:59.9 +63145526399 2000-12-31 23:59:59.990000 2000-12-31 23:59:59.99 +63145526399 2000-12-31 23:59:59.999000 2000-12-31 23:59:59.999 +63145526399 2000-12-31 23:59:59.999900 2000-12-31 23:59:59.9999 +63145526399 2000-12-31 23:59:59.999990 2000-12-31 23:59:59.99999 +63145526399 2000-12-31 23:59:59.999999 2000-12-31 23:59:59.999999 +63145526400 2001-01-01 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SET time_zone='+00:00'; +SELECT UNIX_TIMESTAMP(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +UNIX_TIMESTAMP(a) CAST(a AS DATETIME(6)) a +978307199.000000 2000-12-31 23:59:59.000000 2000-12-31 23:59:59 +978307199.900000 2000-12-31 23:59:59.900000 2000-12-31 23:59:59.9 +978307199.990000 2000-12-31 23:59:59.990000 2000-12-31 23:59:59.99 +978307199.999000 2000-12-31 23:59:59.999000 2000-12-31 23:59:59.999 +978307199.999900 2000-12-31 23:59:59.999900 2000-12-31 23:59:59.9999 +978307199.999990 2000-12-31 23:59:59.999990 2000-12-31 23:59:59.99999 +978307199.999999 2000-12-31 23:59:59.999999 2000-12-31 23:59:59.999999 +978307200.000000 2001-01-01 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SET time_zone=DEFAULT; +SELECT CONVERT_TZ(a, '+00:00','+00:00'), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +CONVERT_TZ(a, '+00:00','+00:00') CAST(a AS DATETIME(6)) a +2000-12-31 23:59:59.000000 2000-12-31 23:59:59.000000 2000-12-31 23:59:59 +2000-12-31 23:59:59.900000 2000-12-31 23:59:59.900000 2000-12-31 23:59:59.9 +2000-12-31 23:59:59.990000 2000-12-31 23:59:59.990000 2000-12-31 23:59:59.99 +2000-12-31 23:59:59.999000 2000-12-31 23:59:59.999000 2000-12-31 23:59:59.999 +2000-12-31 23:59:59.999900 2000-12-31 23:59:59.999900 2000-12-31 23:59:59.9999 +2000-12-31 23:59:59.999990 2000-12-31 23:59:59.999990 2000-12-31 23:59:59.99999 +2000-12-31 23:59:59.999999 2000-12-31 23:59:59.999999 2000-12-31 23:59:59.999999 +2001-01-01 00:00:00.000000 2001-01-01 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +# +# Functions with a single DATETIME input, conversion from DATETIME-in-DECIMAL +# +SELECT TO_SECONDS(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +TO_SECONDS(a) CAST(a AS DATETIME(6)) a +63145526399 2000-12-31 23:59:59.000000 20001231235959.0000000000 +63145526399 2000-12-31 23:59:59.900000 20001231235959.9000000000 +63145526399 2000-12-31 23:59:59.990000 20001231235959.9900000000 +63145526399 2000-12-31 23:59:59.999000 20001231235959.9990000000 +63145526399 2000-12-31 23:59:59.999900 20001231235959.9999000000 +63145526399 2000-12-31 23:59:59.999990 20001231235959.9999900000 +63145526399 2000-12-31 23:59:59.999999 20001231235959.9999990000 +63145526400 2001-01-01 00:00:00.000000 20001231235959.9999999000 +SET time_zone='+00:00'; +SELECT UNIX_TIMESTAMP(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +UNIX_TIMESTAMP(a) CAST(a AS DATETIME(6)) a +978307199.000000 2000-12-31 23:59:59.000000 20001231235959.0000000000 +978307199.900000 2000-12-31 23:59:59.900000 20001231235959.9000000000 +978307199.990000 2000-12-31 23:59:59.990000 20001231235959.9900000000 +978307199.999000 2000-12-31 23:59:59.999000 20001231235959.9990000000 +978307199.999900 2000-12-31 23:59:59.999900 20001231235959.9999000000 +978307199.999990 2000-12-31 23:59:59.999990 20001231235959.9999900000 +978307199.999999 2000-12-31 23:59:59.999999 20001231235959.9999990000 +978307200.000000 2001-01-01 00:00:00.000000 20001231235959.9999999000 +SET time_zone=DEFAULT; +SELECT CONVERT_TZ(a, '+00:00','+00:00'), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +CONVERT_TZ(a, '+00:00','+00:00') CAST(a AS DATETIME(6)) a +2000-12-31 23:59:59.000000 2000-12-31 23:59:59.000000 20001231235959.0000000000 +2000-12-31 23:59:59.900000 2000-12-31 23:59:59.900000 20001231235959.9000000000 +2000-12-31 23:59:59.990000 2000-12-31 23:59:59.990000 20001231235959.9900000000 +2000-12-31 23:59:59.999000 2000-12-31 23:59:59.999000 20001231235959.9990000000 +2000-12-31 23:59:59.999900 2000-12-31 23:59:59.999900 20001231235959.9999000000 +2000-12-31 23:59:59.999990 2000-12-31 23:59:59.999990 20001231235959.9999900000 +2000-12-31 23:59:59.999999 2000-12-31 23:59:59.999999 20001231235959.9999990000 +2001-01-01 00:00:00.000000 2001-01-01 00:00:00.000000 20001231235959.9999999000 +DROP TABLE t1_datetime_in_varchar; +DROP TABLE t1_datetime_in_decimal; +DROP TABLE t1_time_in_varchar; +DROP TABLE t1_time_in_decimal; +# +# Functions that construct DATETIME +# +SET time_zone='+00:00'; +CREATE TABLE t1_unix_timestamp (id SERIAL, a DECIMAL(30,10)); +INSERT INTO t1_unix_timestamp (a) VALUES +(980639999), +(980639999.9), +(980639999.999999), +(980639999.9999999), +(2147483647), +(2147483647.9), +(2147483647.999999), +(2147483647.9999999); +SELECT a, FROM_UNIXTIME(a) FROM t1_unix_timestamp ORDER BY id; +a FROM_UNIXTIME(a) +980639999.0000000000 2001-01-27 23:59:59.000000 +980639999.9000000000 2001-01-27 23:59:59.900000 +980639999.9999990000 2001-01-27 23:59:59.999999 +980639999.9999999000 2001-01-28 00:00:00.000000 +2147483647.0000000000 2038-01-19 03:14:07.000000 +2147483647.9000000000 2038-01-19 03:14:07.900000 +2147483647.9999990000 2038-01-19 03:14:07.999999 +2147483647.9999999000 NULL +DROP TABLE t1_unix_timestamp; +SET time_zone=DEFAULT; +# +# Functions that construct TIME +# +CREATE TABLE t1_sec (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_sec (a) VALUES +(59), +(59.9), +(59.999999), +(59.9999999), +(3020398), +(3020398.999999), +(3020398.9999999), +(3020399), +(3020399.999999), +(3020399.9999999), +(9223372036854775807), +(9223372036854775807.9), +(9223372036854775807.999999), +(9223372036854775807.9999999), +(18446744073709551615), +(18446744073709551615.9), +(18446744073709551615.999999), +(18446744073709551615.9999999); +SELECT a, SEC_TO_TIME(a) FROM t1_sec ORDER BY id; +a SEC_TO_TIME(a) +59.0000000000 00:00:59.000000 +59.9000000000 00:00:59.900000 +59.9999990000 00:00:59.999999 +59.9999999000 00:01:00.000000 +3020398.0000000000 838:59:58.000000 +3020398.9999990000 838:59:58.999999 +3020398.9999999000 838:59:59.000000 +3020399.0000000000 838:59:59.000000 +3020399.9999990000 838:59:59.999999 +3020399.9999999000 838:59:59.999999 +9223372036854775807.0000000000 838:59:59.999999 +9223372036854775807.9000000000 838:59:59.999999 +9223372036854775807.9999990000 838:59:59.999999 +9223372036854775807.9999999000 838:59:59.999999 +18446744073709551615.0000000000 838:59:59.999999 +18446744073709551615.9000000000 838:59:59.999999 +18446744073709551615.9999990000 838:59:59.999999 +18446744073709551615.9999999000 838:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect seconds value: '3020400' +Warning 1292 Truncated incorrect seconds value: '9223372036854775807.0000000000' +Warning 1292 Truncated incorrect seconds value: '9223372036854775807.9000000000' +Warning 1292 Truncated incorrect seconds value: '9223372036854775807.9999990000' +Warning 1292 Truncated incorrect seconds value: '9223372036854775807.9999999000' +Warning 1292 Truncated incorrect seconds value: '18446744073709551615.0000000000' +Warning 1292 Truncated incorrect seconds value: '18446744073709551615.9000000000' +Warning 1292 Truncated incorrect seconds value: '18446744073709551615.9999990000' +Warning 1292 Truncated incorrect seconds value: '18446744073709551615.9999999000' +DROP TABLE t1_sec; +CREATE TABLE t1_sec (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_sec (a) VALUES +(0), +(0.9), +(0.999999), +(0.9999999); +SELECT a, MAKETIME(0, 0, a) FROM t1_sec ORDER BY id; +a MAKETIME(0, 0, a) +0.0000000000 00:00:00.000000 +0.9000000000 00:00:00.900000 +0.9999990000 00:00:00.999999 +0.9999999000 00:00:01.000000 +DROP TABLE t1_sec; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +SELECT +'----', +a, +DATE_FORMAT(a, '%Y') AS yyyy, +DATE_FORMAT(a, '%Y-%m-%d') AS d, +DATE_FORMAT(a, '%H:%i:%s') AS t0, +DATE_FORMAT(a, '%H:%i:%s.%f') AS t6, +DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s') AS dt0, +DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s.%f') AS dt6 +FROM t1; +---- ---- +a 2017-12-31 23:59:59 +yyyy 2017 +d 2017-12-31 +t0 23:59:59 +t6 23:59:59.000000 +dt0 2017-12-31 23:59:59 +dt6 2017-12-31 23:59:59.000000 +---- ---- +a 2017-12-31 23:59:59.9 +yyyy 2017 +d 2017-12-31 +t0 23:59:59 +t6 23:59:59.900000 +dt0 2017-12-31 23:59:59 +dt6 2017-12-31 23:59:59.900000 +---- ---- +a 2017-12-31 23:59:59.999999 +yyyy 2017 +d 2017-12-31 +t0 23:59:59 +t6 23:59:59.999999 +dt0 2017-12-31 23:59:59 +dt6 2017-12-31 23:59:59.999999 +---- ---- +a 2017-12-31 23:59:59.9999999 +yyyy 2018 +d 2018-01-01 +t0 00:00:00 +t6 00:00:00.000000 +dt0 2018-01-01 00:00:00 +dt6 2018-01-01 00:00:00.000000 +Warnings: +Level Note +Code 1292 +Message Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Level Note +Code 1292 +Message Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Level Note +Code 1292 +Message Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Level Note +Code 1292 +Message Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Level Note +Code 1292 +Message Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Level Note +Code 1292 +Message Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(32,9)); +INSERT INTO t1 VALUES +(20171231235959), +(20171231235959.9), +(20171231235959.999999), +(20171231235959.9999999); +SELECT +'----', +a, +DATE_FORMAT(a, '%Y') AS yyyy, +DATE_FORMAT(a, '%Y-%m-%d') AS d, +DATE_FORMAT(a, '%H:%i:%s') AS t0, +DATE_FORMAT(a, '%H:%i:%s.%f') AS t6, +DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s') AS dt0, +DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s.%f') AS dt6 +FROM t1; +---- ---- +a 20171231235959.000000000 +yyyy 2017 +d 2017-12-31 +t0 23:59:59 +t6 23:59:59.000000 +dt0 2017-12-31 23:59:59 +dt6 2017-12-31 23:59:59.000000 +---- ---- +a 20171231235959.900000000 +yyyy 2017 +d 2017-12-31 +t0 23:59:59 +t6 23:59:59.900000 +dt0 2017-12-31 23:59:59 +dt6 2017-12-31 23:59:59.900000 +---- ---- +a 20171231235959.999999000 +yyyy 2017 +d 2017-12-31 +t0 23:59:59 +t6 23:59:59.999999 +dt0 2017-12-31 23:59:59 +dt6 2017-12-31 23:59:59.999999 +---- ---- +a 20171231235959.999999900 +yyyy 2018 +d 2018-01-01 +t0 00:00:00 +t6 00:00:00.000000 +dt0 2018-01-01 00:00:00 +dt6 2018-01-01 00:00:00.000000 +DROP TABLE t1; +# +# Functions with two temporal parameters that round nanoseconds in both parameters in MySQL +# +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +INSERT INTO t2 VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.999999'), +('00:00:00.9999999'); +SELECT TIMESTAMP(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +TIMESTAMP(t1.a, t2.a) a a +2017-12-31 23:59:59.000000 2017-12-31 23:59:59 00:00:00 +2017-12-31 23:59:59.900000 2017-12-31 23:59:59 00:00:00.9 +2017-12-31 23:59:59.999999 2017-12-31 23:59:59 00:00:00.999999 +2018-01-01 00:00:00.000000 2017-12-31 23:59:59 00:00:00.9999999 +2017-12-31 23:59:59.900000 2017-12-31 23:59:59.9 00:00:00 +2018-01-01 00:00:00.800000 2017-12-31 23:59:59.9 00:00:00.9 +2018-01-01 00:00:00.899999 2017-12-31 23:59:59.9 00:00:00.999999 +2018-01-01 00:00:00.900000 2017-12-31 23:59:59.9 00:00:00.9999999 +2017-12-31 23:59:59.999999 2017-12-31 23:59:59.999999 00:00:00 +2018-01-01 00:00:00.899999 2017-12-31 23:59:59.999999 00:00:00.9 +2018-01-01 00:00:00.999998 2017-12-31 23:59:59.999999 00:00:00.999999 +2018-01-01 00:00:00.999999 2017-12-31 23:59:59.999999 00:00:00.9999999 +2018-01-01 00:00:00.000000 2017-12-31 23:59:59.9999999 00:00:00 +2018-01-01 00:00:00.900000 2017-12-31 23:59:59.9999999 00:00:00.9 +2018-01-01 00:00:00.999999 2017-12-31 23:59:59.9999999 00:00:00.999999 +2018-01-01 00:00:01.000000 2017-12-31 23:59:59.9999999 00:00:00.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +SELECT ADDTIME(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +ADDTIME(t1.a, t2.a) a a +2017-12-31 23:59:59 2017-12-31 23:59:59 00:00:00 +2017-12-31 23:59:59.900000 2017-12-31 23:59:59 00:00:00.9 +2017-12-31 23:59:59.999999 2017-12-31 23:59:59 00:00:00.999999 +2018-01-01 00:00:00 2017-12-31 23:59:59 00:00:00.9999999 +2017-12-31 23:59:59.900000 2017-12-31 23:59:59.9 00:00:00 +2018-01-01 00:00:00.800000 2017-12-31 23:59:59.9 00:00:00.9 +2018-01-01 00:00:00.899999 2017-12-31 23:59:59.9 00:00:00.999999 +2018-01-01 00:00:00.900000 2017-12-31 23:59:59.9 00:00:00.9999999 +2017-12-31 23:59:59.999999 2017-12-31 23:59:59.999999 00:00:00 +2018-01-01 00:00:00.899999 2017-12-31 23:59:59.999999 00:00:00.9 +2018-01-01 00:00:00.999998 2017-12-31 23:59:59.999999 00:00:00.999999 +2018-01-01 00:00:00.999999 2017-12-31 23:59:59.999999 00:00:00.9999999 +2018-01-01 00:00:00 2017-12-31 23:59:59.9999999 00:00:00 +2018-01-01 00:00:00.900000 2017-12-31 23:59:59.9999999 00:00:00.9 +2018-01-01 00:00:00.999999 2017-12-31 23:59:59.9999999 00:00:00.999999 +2018-01-01 00:00:01 2017-12-31 23:59:59.9999999 00:00:00.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +DROP TABLE t1, t2; +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('23:59:59'), +('23:59:59.9'), +('23:59:59.999999'), +('23:59:59.9999999'); +INSERT INTO t2 VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.999999'), +('00:00:00.9999999'); +SELECT TIMEDIFF(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +TIMEDIFF(t1.a, t2.a) a a +23:59:59.000000 23:59:59 00:00:00 +23:59:58.100000 23:59:59 00:00:00.9 +23:59:58.000001 23:59:59 00:00:00.999999 +23:59:58.000000 23:59:59 00:00:00.9999999 +23:59:59.900000 23:59:59.9 00:00:00 +23:59:59.000000 23:59:59.9 00:00:00.9 +23:59:58.900001 23:59:59.9 00:00:00.999999 +23:59:58.900000 23:59:59.9 00:00:00.9999999 +23:59:59.999999 23:59:59.999999 00:00:00 +23:59:59.099999 23:59:59.999999 00:00:00.9 +23:59:59.000000 23:59:59.999999 00:00:00.999999 +23:59:58.999999 23:59:59.999999 00:00:00.9999999 +24:00:00.000000 23:59:59.9999999 00:00:00 +23:59:59.100000 23:59:59.9999999 00:00:00.9 +23:59:59.000001 23:59:59.9999999 00:00:00.999999 +23:59:59.000000 23:59:59.9999999 00:00:00.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +DROP TABLE t1, t2; +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2001-12-31 23:59:59'), +('2001-12-31 23:59:59.9'), +('2001-12-31 23:59:59.999999'), +('2001-12-31 23:59:59.9999999'); +INSERT INTO t2 VALUES +('2001-12-31 23:59:59'), +('2001-12-31 23:59:59.9'), +('2001-12-31 23:59:59.999999'), +('2001-12-31 23:59:59.9999999'); +SELECT TIMESTAMPDIFF(MICROSECOND,t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +TIMESTAMPDIFF(MICROSECOND,t1.a, t2.a) a a +0 2001-12-31 23:59:59 2001-12-31 23:59:59 +900000 2001-12-31 23:59:59 2001-12-31 23:59:59.9 +999999 2001-12-31 23:59:59 2001-12-31 23:59:59.999999 +1000000 2001-12-31 23:59:59 2001-12-31 23:59:59.9999999 +-900000 2001-12-31 23:59:59.9 2001-12-31 23:59:59 +0 2001-12-31 23:59:59.9 2001-12-31 23:59:59.9 +99999 2001-12-31 23:59:59.9 2001-12-31 23:59:59.999999 +100000 2001-12-31 23:59:59.9 2001-12-31 23:59:59.9999999 +-999999 2001-12-31 23:59:59.999999 2001-12-31 23:59:59 +-99999 2001-12-31 23:59:59.999999 2001-12-31 23:59:59.9 +0 2001-12-31 23:59:59.999999 2001-12-31 23:59:59.999999 +1 2001-12-31 23:59:59.999999 2001-12-31 23:59:59.9999999 +-1000000 2001-12-31 23:59:59.9999999 2001-12-31 23:59:59 +-100000 2001-12-31 23:59:59.9999999 2001-12-31 23:59:59.9 +-1 2001-12-31 23:59:59.9999999 2001-12-31 23:59:59.999999 +0 2001-12-31 23:59:59.9999999 2001-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +DROP TABLE t1, t2; +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('23:59:59'), +('23:59:59.9'), +('23:59:59.999999'), +('23:59:59.9999999'); +INSERT INTO t2 VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.999999'), +('00:00:00.9999999'); +SELECT TIMEDIFF(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +TIMEDIFF(t1.a, t2.a) a a +23:59:59.000000 23:59:59 00:00:00 +23:59:58.100000 23:59:59 00:00:00.9 +23:59:58.000001 23:59:59 00:00:00.999999 +23:59:58.000000 23:59:59 00:00:00.9999999 +23:59:59.900000 23:59:59.9 00:00:00 +23:59:59.000000 23:59:59.9 00:00:00.9 +23:59:58.900001 23:59:59.9 00:00:00.999999 +23:59:58.900000 23:59:59.9 00:00:00.9999999 +23:59:59.999999 23:59:59.999999 00:00:00 +23:59:59.099999 23:59:59.999999 00:00:00.9 +23:59:59.000000 23:59:59.999999 00:00:00.999999 +23:59:58.999999 23:59:59.999999 00:00:00.9999999 +24:00:00.000000 23:59:59.9999999 00:00:00 +23:59:59.100000 23:59:59.9999999 00:00:00.9 +23:59:59.000001 23:59:59.9999999 00:00:00.999999 +23:59:59.000000 23:59:59.9999999 00:00:00.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +DROP TABLE t1, t2; +# +# STR_TO_DATE behaviour is questionable in MySQL 5.6 (MySQL Bug #92474) +# +# It truncates nanoseconds, but this may change in the future. +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +SELECT +a, +STR_TO_DATE(a, '%Y-%m-%d %H:%i:%s') AS c0, +STR_TO_DATE(a, '%Y-%m-%d %H:%i:%s.%f') AS c6 +FROM t1; +a c0 c6 +2017-12-31 23:59:59 2017-12-31 23:59:59 2017-12-31 23:59:59.000000 +2017-12-31 23:59:59.9 2017-12-31 23:59:59 2017-12-31 23:59:59.900000 +2017-12-31 23:59:59.999999 2017-12-31 23:59:59 2017-12-31 23:59:59.999999 +2017-12-31 23:59:59.9999999 2017-12-31 23:59:59 2017-12-31 23:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9' +Warning 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.999999' +Warning 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Warning 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +DROP TABLE t1; +# +# DATE_ADD behaviour is questionable in MySQL 5.6 (MySQL Bug#92473) +# It rounds nanoseconds in the first argument, but truncates nanoseconds in the second argument. +# This may change in the future, to round both arguments. +# +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +CREATE TABLE t2 (b DECIMAL(32,9)); +INSERT INTO t2 VALUES +(0), +(0.9), +(0.999999), +(0.9999999); +SELECT a, b, DATE_ADD(a, INTERVAL b SECOND) FROM t1,t2 ORDER BY a,b; +a b DATE_ADD(a, INTERVAL b SECOND) +2017-12-31 23:59:59 0.000000000 2017-12-31 23:59:59.000000 +2017-12-31 23:59:59 0.900000000 2017-12-31 23:59:59.900000 +2017-12-31 23:59:59 0.999999000 2017-12-31 23:59:59.999999 +2017-12-31 23:59:59 0.999999900 2017-12-31 23:59:59.999999 +2017-12-31 23:59:59.9 0.000000000 2017-12-31 23:59:59.900000 +2017-12-31 23:59:59.9 0.900000000 2018-01-01 00:00:00.800000 +2017-12-31 23:59:59.9 0.999999000 2018-01-01 00:00:00.899999 +2017-12-31 23:59:59.9 0.999999900 2018-01-01 00:00:00.899999 +2017-12-31 23:59:59.999999 0.000000000 2017-12-31 23:59:59.999999 +2017-12-31 23:59:59.999999 0.900000000 2018-01-01 00:00:00.899999 +2017-12-31 23:59:59.999999 0.999999000 2018-01-01 00:00:00.999998 +2017-12-31 23:59:59.999999 0.999999900 2018-01-01 00:00:00.999998 +2017-12-31 23:59:59.9999999 0.000000000 2018-01-01 00:00:00.000000 +2017-12-31 23:59:59.9999999 0.900000000 2018-01-01 00:00:00.900000 +2017-12-31 23:59:59.9999999 0.999999000 2018-01-01 00:00:00.999999 +2017-12-31 23:59:59.9999999 0.999999900 2018-01-01 00:00:00.999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +DROP TABLE t1, t2; diff --git a/mysql-test/main/func_time_round.test b/mysql-test/main/func_time_round.test new file mode 100644 index 00000000000..12d3a50a10f --- /dev/null +++ b/mysql-test/main/func_time_round.test @@ -0,0 +1,461 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; + +CREATE TABLE t1_datetime_in_varchar (id SERIAL, a VARCHAR(64)); +INSERT INTO t1_datetime_in_varchar (a) VALUES +('2000-12-31 23:59:59'), +('2000-12-31 23:59:59.9'), +('2000-12-31 23:59:59.99'), +('2000-12-31 23:59:59.999'), +('2000-12-31 23:59:59.9999'), +('2000-12-31 23:59:59.99999'), +('2000-12-31 23:59:59.999999'), +('2000-12-31 23:59:59.9999999'); + +CREATE TABLE t1_datetime_in_decimal (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_datetime_in_decimal (a) VALUES +(20001231235959), +(20001231235959.9), +(20001231235959.99), +(20001231235959.999), +(20001231235959.9999), +(20001231235959.99999), +(20001231235959.999999), +(20001231235959.9999999); + + +CREATE TABLE t1_time_in_varchar (id SERIAL, a VARCHAR(64)); +INSERT INTO t1_time_in_varchar (a) VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.99'), +('00:00:00.999'), +('00:00:00.9999'), +('00:00:00.99999'), +('00:00:00.999999'), +('00:00:00.9999999'); +INSERT INTO t1_time_in_varchar (a) VALUES +('837:59:59.9999999'), +('838:59:59'), +('838:59:59.9'), +('838:59:59.99'), +('838:59:59.999'), +('838:59:59.9999'), +('838:59:59.99999'), +('838:59:59.999999'), +('838:59:59.9999999'), +('839:59:59.9999999'), +('87649414:59:59.999999'), +('87649414:59:59.9999999'), +('87649415:59:59.999999'), +('87649415:59:59.9999999'); + + +CREATE TABLE t1_time_in_decimal (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_time_in_decimal (a) VALUES +(0), +(0.9), +(0.99), +(0.999), +(0.9999), +(0.99999), +(0.999999), +(0.9999999); +INSERT INTO t1_time_in_decimal (a) VALUES +(8375959.9999999), +(8385959), +(8385959.9), +(8385959.99), +(8385959.999), +(8385959.9999), +(8385959.99999), +(8385959.999999), +(8385959.9999999), +(8395959.9999999), +(876494145959.999999), +(876494145959.9999999), +(876494155959.999999), +(876494155959.9999999); + +--echo # +--echo # TIME: LEAST/GREATEST +--echo # + +SELECT GREATEST(TIME'00:00:00', a) FROM t1_time_in_varchar; +SELECT GREATEST(TIME'00:00:00', a) FROM t1_time_in_decimal; + +SELECT GREATEST(TIME'00:00:00', '00:00:00.0000004'); +SELECT GREATEST(TIME'00:00:00', 0.0000004); + +SELECT GREATEST(TIME'00:00:00', '00:00:00.0000005'); +SELECT GREATEST(TIME'00:00:00', 0.0000005); + + +--echo # +--echo # Functions with a single TIME input, conversion from DATETIME-in-VARCHAR +--echo # + +SELECT SECOND(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT MINUTE(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT HOUR(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; + +SELECT EXTRACT(SECOND FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT EXTRACT(MINUTE FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT EXTRACT(HOUR FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; + +SELECT TIME_TO_SEC(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; + + +--echo # +--echo # Functions with a single TIME input, conversion from DATETIME-in-DECIMAL +--echo # + + +SELECT SECOND(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT MINUTE(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT HOUR(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; + +SELECT EXTRACT(SECOND FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT EXTRACT(MINUTE FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT EXTRACT(HOUR FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; + +SELECT TIME_TO_SEC(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; + + +--echo # +--echo # Functions with a single TIME interval input, conversion from TIME-interval-in-VARCHAR +--echo # + +SELECT + EXTRACT(DAY FROM a), + EXTRACT(HOUR FROM a), + EXTRACT(MINUTE FROM a), + EXTRACT(SECOND FROM a), + EXTRACT(MICROSECOND FROM a), + CAST(a AS INTERVAL DAY_SECOND(6)), + a +FROM t1_time_in_varchar ORDER BY id; + +SELECT + TIME_TO_SEC(a), + CAST(a AS TIME(6)), + a +FROM t1_time_in_varchar ORDER BY id; + +--echo # +--echo # Functions with a single TIME interval input, conversion from TIME-interval-in-DECIMAL +--echo # + +SELECT + EXTRACT(DAY FROM a), + EXTRACT(HOUR FROM a), + EXTRACT(MINUTE FROM a), + EXTRACT(SECOND FROM a), + EXTRACT(MICROSECOND FROM a), + CAST(a AS INTERVAL DAY_SECOND(6)), + a +FROM t1_time_in_decimal ORDER BY id; + +SELECT + TIME_TO_SEC(a), + CAST(a AS TIME(6)), + a +FROM t1_time_in_decimal ORDER BY id; + + +--echo # +--echo # Functions with a single DATE input, conversion from DATETIME-in-VARCHAR +--echo # + +SELECT QUARTER(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT MONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT YEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; + +SELECT DAYNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT MONTHNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; + +SELECT LAST_DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT TO_DAYS(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT DAYOFYEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; + + +CREATE TABLE t1 (a VARCHAR(32)); +INSERT INTO t1 VALUES +('2002-01-05 23:59:59'), +('2002-01-05 23:59:59.999999'), +('2002-01-05 23:59:59.9999999'); +SELECT YEARWEEK(a), a FROM t1; +SELECT WEEK(a), a FROM t1; +SELECT WEEKDAY(a), a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(32,9)); +INSERT INTO t1 VALUES +(20020105235959), +(20020105235959.999999), +(20020105235959.9999999); +SELECT YEARWEEK(a), a FROM t1; +SELECT WEEK(a), a FROM t1; +SELECT WEEKDAY(a), a FROM t1; +DROP TABLE t1; + +--echo # +--echo # Functions with a single DATE input, conversion from DATETIME-in-DECIMAL +--echo # + +SELECT QUARTER(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT MONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT YEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; + +SELECT DAYNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT MONTHNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT YEARWEEK(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; + +SELECT LAST_DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT TO_DAYS(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT DAYOFYEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT DAYOFMONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; + + +--echo # +--echo # Functions with a single DATETIME input, conversion from DATETIME-in-VARCHAR +--echo # + +SELECT TO_SECONDS(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; + +SET time_zone='+00:00'; +SELECT UNIX_TIMESTAMP(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +SET time_zone=DEFAULT; + +SELECT CONVERT_TZ(a, '+00:00','+00:00'), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; + + +--echo # +--echo # Functions with a single DATETIME input, conversion from DATETIME-in-DECIMAL +--echo # + +SELECT TO_SECONDS(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; + +SET time_zone='+00:00'; +SELECT UNIX_TIMESTAMP(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +SET time_zone=DEFAULT; + +SELECT CONVERT_TZ(a, '+00:00','+00:00'), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; + +DROP TABLE t1_datetime_in_varchar; +DROP TABLE t1_datetime_in_decimal; +DROP TABLE t1_time_in_varchar; +DROP TABLE t1_time_in_decimal; + + +--echo # +--echo # Functions that construct DATETIME +--echo # + +SET time_zone='+00:00'; +CREATE TABLE t1_unix_timestamp (id SERIAL, a DECIMAL(30,10)); +INSERT INTO t1_unix_timestamp (a) VALUES +(980639999), +(980639999.9), +(980639999.999999), +(980639999.9999999), +(2147483647), +(2147483647.9), +(2147483647.999999), +(2147483647.9999999); +SELECT a, FROM_UNIXTIME(a) FROM t1_unix_timestamp ORDER BY id; +DROP TABLE t1_unix_timestamp; +SET time_zone=DEFAULT; + + +--echo # +--echo # Functions that construct TIME +--echo # + +CREATE TABLE t1_sec (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_sec (a) VALUES +(59), +(59.9), +(59.999999), +(59.9999999), +(3020398), +(3020398.999999), +(3020398.9999999), +(3020399), +(3020399.999999), +(3020399.9999999), +(9223372036854775807), +(9223372036854775807.9), +(9223372036854775807.999999), +(9223372036854775807.9999999), +(18446744073709551615), +(18446744073709551615.9), +(18446744073709551615.999999), +(18446744073709551615.9999999); +SELECT a, SEC_TO_TIME(a) FROM t1_sec ORDER BY id; +DROP TABLE t1_sec; + + +CREATE TABLE t1_sec (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_sec (a) VALUES +(0), +(0.9), +(0.999999), +(0.9999999); +SELECT a, MAKETIME(0, 0, a) FROM t1_sec ORDER BY id; +DROP TABLE t1_sec; + + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +--vertical_results +SELECT + '----', + a, + DATE_FORMAT(a, '%Y') AS yyyy, + DATE_FORMAT(a, '%Y-%m-%d') AS d, + DATE_FORMAT(a, '%H:%i:%s') AS t0, + DATE_FORMAT(a, '%H:%i:%s.%f') AS t6, + DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s') AS dt0, + DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s.%f') AS dt6 +FROM t1; +--horizontal_results +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(32,9)); +INSERT INTO t1 VALUES +(20171231235959), +(20171231235959.9), +(20171231235959.999999), +(20171231235959.9999999); +--vertical_results +SELECT + '----', + a, + DATE_FORMAT(a, '%Y') AS yyyy, + DATE_FORMAT(a, '%Y-%m-%d') AS d, + DATE_FORMAT(a, '%H:%i:%s') AS t0, + DATE_FORMAT(a, '%H:%i:%s.%f') AS t6, + DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s') AS dt0, + DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s.%f') AS dt6 +FROM t1; +--horizontal_results +DROP TABLE t1; + + +--echo # +--echo # Functions with two temporal parameters that round nanoseconds in both parameters in MySQL +--echo # + +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +INSERT INTO t2 VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.999999'), +('00:00:00.9999999'); + +SELECT TIMESTAMP(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +SELECT ADDTIME(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; + +DROP TABLE t1, t2; + + +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('23:59:59'), +('23:59:59.9'), +('23:59:59.999999'), +('23:59:59.9999999'); +INSERT INTO t2 VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.999999'), +('00:00:00.9999999'); +SELECT TIMEDIFF(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +DROP TABLE t1, t2; + + +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2001-12-31 23:59:59'), +('2001-12-31 23:59:59.9'), +('2001-12-31 23:59:59.999999'), +('2001-12-31 23:59:59.9999999'); +INSERT INTO t2 VALUES +('2001-12-31 23:59:59'), +('2001-12-31 23:59:59.9'), +('2001-12-31 23:59:59.999999'), +('2001-12-31 23:59:59.9999999'); +SELECT TIMESTAMPDIFF(MICROSECOND,t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +DROP TABLE t1, t2; + +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('23:59:59'), +('23:59:59.9'), +('23:59:59.999999'), +('23:59:59.9999999'); +INSERT INTO t2 VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.999999'), +('00:00:00.9999999'); +SELECT TIMEDIFF(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +DROP TABLE t1, t2; + + +--echo # +--echo # STR_TO_DATE behaviour is questionable in MySQL 5.6 (MySQL Bug #92474) +--echo # + +--echo # It truncates nanoseconds, but this may change in the future. +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); + +SELECT + a, + STR_TO_DATE(a, '%Y-%m-%d %H:%i:%s') AS c0, + STR_TO_DATE(a, '%Y-%m-%d %H:%i:%s.%f') AS c6 +FROM t1; +DROP TABLE t1; + + +--echo # +--echo # DATE_ADD behaviour is questionable in MySQL 5.6 (MySQL Bug#92473) +--echo # It rounds nanoseconds in the first argument, but truncates nanoseconds in the second argument. +--echo # This may change in the future, to round both arguments. +--echo # + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +CREATE TABLE t2 (b DECIMAL(32,9)); +INSERT INTO t2 VALUES +(0), +(0.9), +(0.999999), +(0.9999999); +SELECT a, b, DATE_ADD(a, INTERVAL b SECOND) FROM t1,t2 ORDER BY a,b; +DROP TABLE t1, t2; diff --git a/mysql-test/main/information_schema.result b/mysql-test/main/information_schema.result index b6e331a0382..4a39eea6115 100644 --- a/mysql-test/main/information_schema.result +++ b/mysql-test/main/information_schema.result @@ -664,7 +664,7 @@ proc body longblob proc definer char(141) proc created timestamp proc modified timestamp -proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') +proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') proc comment text proc character_set_client char(32) proc collation_connection char(32) diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 5ee85eee7de..cf25f377142 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -1209,7 +1209,8 @@ The following specify which files/extra groups are read (specified before remain ERROR_FOR_DIVISION_BY_ZERO, TRADITIONAL, NO_AUTO_CREATE_USER, HIGH_NOT_PRECEDENCE, NO_ENGINE_SUBSTITUTION, PAD_CHAR_TO_FULL_LENGTH, - EMPTY_STRING_IS_NULL, SIMULTANEOUS_ASSIGNMENT + EMPTY_STRING_IS_NULL, SIMULTANEOUS_ASSIGNMENT, + TIME_ROUND_FRACTIONAL --sql-safe-updates If set to 1, UPDATEs and DELETEs need either a key in the WHERE clause, or a LIMIT clause, or else they will aborted. Prevents the common mistake of accidentally diff --git a/mysql-test/main/sql_mode.result b/mysql-test/main/sql_mode.result index 238bae2efd8..25a90703bf5 100644 --- a/mysql-test/main/sql_mode.result +++ b/mysql-test/main/sql_mode.result @@ -476,10 +476,14 @@ select @@sql_mode; @@sql_mode REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_TABLE_OPTIONS,ANSI set sql_mode=2147483648*2*2*2; -ERROR 42000: Variable 'sql_mode' can't be set to the value of '17179869184' select @@sql_mode; @@sql_mode -REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_TABLE_OPTIONS,ANSI +TIME_ROUND_FRACTIONAL +set sql_mode=2147483648*2*2*2*2; +ERROR 42000: Variable 'sql_mode' can't be set to the value of '34359738368' +select @@sql_mode; +@@sql_mode +TIME_ROUND_FRACTIONAL set sql_mode=PAD_CHAR_TO_FULL_LENGTH; create table t1 (a int auto_increment primary key, b char(5)); insert into t1 (b) values('a'),('b\t'),('c '); diff --git a/mysql-test/main/sql_mode.test b/mysql-test/main/sql_mode.test index 8cf50f73f6f..97f5cf42791 100644 --- a/mysql-test/main/sql_mode.test +++ b/mysql-test/main/sql_mode.test @@ -263,8 +263,10 @@ set sql_mode=4194304; select @@sql_mode; set sql_mode=16384+(65536*4); select @@sql_mode; +set sql_mode=2147483648*2*2*2; +select @@sql_mode; --error 1231 -set sql_mode=2147483648*2*2*2; # that mode does not exist +set sql_mode=2147483648*2*2*2*2; # that mode does not exist select @@sql_mode; # diff --git a/mysql-test/main/system_mysql_db.result b/mysql-test/main/system_mysql_db.result index a4c414888ca..bdc1df85131 100644 --- a/mysql-test/main/system_mysql_db.result +++ b/mysql-test/main/system_mysql_db.result @@ -191,7 +191,7 @@ proc CREATE TABLE `proc` ( `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, @@ -217,7 +217,7 @@ event CREATE TABLE `event` ( `ends` datetime DEFAULT NULL, `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `originator` int(10) unsigned NOT NULL, `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', diff --git a/mysql-test/main/system_mysql_db_fix40123.result b/mysql-test/main/system_mysql_db_fix40123.result index d76a2ef923e..abb6fbb38e1 100644 --- a/mysql-test/main/system_mysql_db_fix40123.result +++ b/mysql-test/main/system_mysql_db_fix40123.result @@ -192,7 +192,7 @@ proc CREATE TABLE `proc` ( `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, @@ -218,7 +218,7 @@ event CREATE TABLE `event` ( `ends` datetime DEFAULT NULL, `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `originator` int(10) unsigned NOT NULL, `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', diff --git a/mysql-test/main/system_mysql_db_fix50030.result b/mysql-test/main/system_mysql_db_fix50030.result index fdc708db313..b3a0caa282f 100644 --- a/mysql-test/main/system_mysql_db_fix50030.result +++ b/mysql-test/main/system_mysql_db_fix50030.result @@ -192,7 +192,7 @@ proc CREATE TABLE `proc` ( `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, @@ -218,7 +218,7 @@ event CREATE TABLE `event` ( `ends` datetime DEFAULT NULL, `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `originator` int(10) unsigned NOT NULL, `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', diff --git a/mysql-test/main/system_mysql_db_fix50117.result b/mysql-test/main/system_mysql_db_fix50117.result index d76a2ef923e..abb6fbb38e1 100644 --- a/mysql-test/main/system_mysql_db_fix50117.result +++ b/mysql-test/main/system_mysql_db_fix50117.result @@ -192,7 +192,7 @@ proc CREATE TABLE `proc` ( `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, @@ -218,7 +218,7 @@ event CREATE TABLE `event` ( `ends` datetime DEFAULT NULL, `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `originator` int(10) unsigned NOT NULL, `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', diff --git a/mysql-test/main/type_date_round.result b/mysql-test/main/type_date_round.result new file mode 100644 index 00000000000..0da78c6afe5 --- /dev/null +++ b/mysql-test/main/type_date_round.result @@ -0,0 +1,174 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; +# +# DATE: SET +# +CREATE TABLE t1 (a DATE, b DATETIME(4)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +SELECT a FROM t1; +a +2000-12-31 +DROP TABLE t1; +CREATE TABLE t1 (a DATE, b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999'); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +2000-12-31 +2000-12-31 +DROP TABLE t1; +CREATE TABLE t1 (a DATE, b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,20001231235959.9999); +INSERT INTO t1 VALUES(NULL,20001231235959.9999999); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +2000-12-31 +2000-12-31 +DROP TABLE t1; +# +# DATE: ALTER +# +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +ALTER TABLE t1 MODIFY a DATE; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +SELECT a FROM t1; +a +2000-12-31 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +ALTER TABLE t1 MODIFY a DATE; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +2000-12-31 +2000-12-31 +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +ALTER TABLE t1 MODIFY a DATE; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +2000-12-31 +2000-12-31 +DROP TABLE t1; +# +# DATE: CAST +# +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +SELECT a, CAST(a AS DATE) FROM t1; +a CAST(a AS DATE) +2000-12-31 23:59:59.9999 2000-12-31 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +SELECT a, CAST(a AS DATE) FROM t1; +a CAST(a AS DATE) +2000-12-31 23:59:59.9999 2000-12-31 +2000-12-31 23:59:59.9999999 2000-12-31 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +SELECT a, CAST(a AS DATE) FROM t1; +a CAST(a AS DATE) +20001231235959.9999000000 2000-12-31 +20001231235959.9999999000 2000-12-31 +DROP TABLE t1; +# +# Equal field propagation +# +CREATE TABLE t1 (a DATE); +INSERT INTO t1 VALUES (20010101); +INSERT INTO t1 VALUES (20010102); +SELECT * FROM t1 WHERE a= 20010101235959.9999999; +a +2001-01-02 +SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999'; +a +2001-01-02 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND a>='2001-01-01 23:59:59.9999999'; +a +2001-01-02 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND CONCAT(a)='2001-01-02'; +a +2001-01-02 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND a>='2001-01-01 23:59:59.9999999'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2001-01-02' +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND CONCAT(a)='2001-01-02'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2001-01-02' +DROP TABLE t1; +# +# Comparing non-temporal to DATE +# +# Although conversion from non-temporal to DATE (e.g. on SET) does not round, +# comparison between non-temporal to DATE is performed as DATETIME. +# So rounding does happen here. +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('2001-01-01 23:59:59.9999999'); +SELECT * FROM t1 WHERE a=DATE'2001-01-02'; +a +2001-01-01 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1 WHERE CONCAT(a)=DATE'2001-01-02'; +a +2001-01-01 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1 WHERE COALESCE(a)=DATE'2001-01-02'; +a +2001-01-01 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (20010101235959.9999999); +SELECT * FROM t1 WHERE a=DATE'2001-01-02'; +a +20010101235959.9999999 +SELECT * FROM t1 WHERE COALESCE(a)=DATE'2001-01-02'; +a +20010101235959.9999999 +DROP TABLE t1; diff --git a/mysql-test/main/type_date_round.test b/mysql-test/main/type_date_round.test new file mode 100644 index 00000000000..61e1d0a401c --- /dev/null +++ b/mysql-test/main/type_date_round.test @@ -0,0 +1,113 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; + +--echo # +--echo # DATE: SET +--echo # + +CREATE TABLE t1 (a DATE, b DATETIME(4)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DATE, b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DATE, b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,20001231235959.9999); +INSERT INTO t1 VALUES(NULL,20001231235959.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +--echo # +--echo # DATE: ALTER +--echo # + +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +ALTER TABLE t1 MODIFY a DATE; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +ALTER TABLE t1 MODIFY a DATE; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +ALTER TABLE t1 MODIFY a DATE; +SELECT a FROM t1; +DROP TABLE t1; + +--echo # +--echo # DATE: CAST +--echo # + +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +SELECT a, CAST(a AS DATE) FROM t1; +DROP TABLE t1; + +# This truncates microseconds but rounds nanoseconds (MySQL Bug #92475) +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +SELECT a, CAST(a AS DATE) FROM t1; +DROP TABLE t1; + +# This truncates microseconds but rounds nanoseconds (MySQL Bug #92475) +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +SELECT a, CAST(a AS DATE) FROM t1; +DROP TABLE t1; + + +--echo # +--echo # Equal field propagation +--echo # + +CREATE TABLE t1 (a DATE); +INSERT INTO t1 VALUES (20010101); +INSERT INTO t1 VALUES (20010102); +# DATE is compared to non-temporal as DATETIME +# In the below queries nanoseconds should round to microseconds +SELECT * FROM t1 WHERE a= 20010101235959.9999999; +SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999'; +SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND a>='2001-01-01 23:59:59.9999999'; +SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND CONCAT(a)='2001-01-02'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND a>='2001-01-01 23:59:59.9999999'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND CONCAT(a)='2001-01-02'; +DROP TABLE t1; + + +--echo # +--echo # Comparing non-temporal to DATE +--echo # + +--echo # Although conversion from non-temporal to DATE (e.g. on SET) does not round, +--echo # comparison between non-temporal to DATE is performed as DATETIME. +--echo # So rounding does happen here. + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('2001-01-01 23:59:59.9999999'); +SELECT * FROM t1 WHERE a=DATE'2001-01-02'; +SELECT * FROM t1 WHERE CONCAT(a)=DATE'2001-01-02'; +SELECT * FROM t1 WHERE COALESCE(a)=DATE'2001-01-02'; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (20010101235959.9999999); +SELECT * FROM t1 WHERE a=DATE'2001-01-02'; +SELECT * FROM t1 WHERE COALESCE(a)=DATE'2001-01-02'; +DROP TABLE t1; diff --git a/mysql-test/main/type_datetime_round.result b/mysql-test/main/type_datetime_round.result new file mode 100644 index 00000000000..c6584223268 --- /dev/null +++ b/mysql-test/main/type_datetime_round.result @@ -0,0 +1,205 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; +# +# DATETIME: SET +# +CREATE TABLE t1 (a DATETIME(3), b DATETIME(4)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a DATETIME(3), b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999'); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a DATETIME(3), b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,20001231235959.9999); +INSERT INTO t1 VALUES(NULL,20001231235959.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +# +# DATETIME: ALTER +# +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +ALTER TABLE t1 MODIFY a DATETIME(3); +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +ALTER TABLE t1 MODIFY a DATETIME(3); +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +ALTER TABLE t1 MODIFY a DATETIME(3); +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +# +# Corner case: +# ALTER DATETIME to a shorter DATETIME +# All values round, maximum possible value truncates. +# +SET time_zone='+00:00'; +CREATE TABLE t1 (ID INT, a DATETIME(6), comment VARCHAR(64)); +INSERT INTO t1 VALUES (0, '9999-12-30 23:59:58.999999', 'Should round'); +INSERT INTO t1 VALUES (1, '9999-12-31 22:59:59.999999', 'Should round'); +INSERT INTO t1 VALUES (2, '9999-12-31 23:59:58.999999', 'Should round'); +INSERT INTO t1 VALUES (3, '9999-12-31 23:59:59.999999', 'Should truncate'); +ALTER TABLE t1 MODIFY a DATETIME(5); +Warnings: +Warning 1264 Out of range value for column 'a' at row 4 +SELECT * FROM t1; +ID a comment +0 9999-12-30 23:59:59.00000 Should round +1 9999-12-31 23:00:00.00000 Should round +2 9999-12-31 23:59:59.00000 Should round +3 9999-12-31 23:59:59.99999 Should truncate +DROP TABLE t1; +SET time_zone=DEFAULT; +# +# NOW +# +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE OR REPLACE TABLE t1 (id SERIAL, a DATETIME(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIME(6)); +SELECT * FROM t1; +id a +1 2011-01-01 00:00:00.0000 +2 2011-01-01 00:00:00.0000 +3 2011-01-01 00:00:00.0000 +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; +# +# DATETIME: CAST +# +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +SELECT a, CAST(a AS DATETIME(3)) FROM t1; +a CAST(a AS DATETIME(3)) +2000-12-31 23:59:59.9999 2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +SELECT a, CAST(a AS DATETIME(3)) FROM t1; +a CAST(a AS DATETIME(3)) +2000-12-31 23:59:59.9999 2001-01-01 00:00:00.000 +2000-12-31 23:59:59.9999999 2001-01-01 00:00:00.000 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +SELECT a, CAST(a AS DATETIME(3)) FROM t1; +a CAST(a AS DATETIME(3)) +20001231235959.9999000000 2001-01-01 00:00:00.000 +20001231235959.9999999000 2001-01-01 00:00:00.000 +DROP TABLE t1; +# +# Equal field propagation +# +CREATE TABLE t1 (a DATETIME(6)); +INSERT INTO t1 VALUES (20010101235959.999999); +INSERT INTO t1 VALUES (20010101235959.9999999); +SELECT * FROM t1 WHERE a=20010101235959.9999999; +a +2001-01-02 00:00:00.000000 +SELECT * FROM t1 WHERE a='20010101235959.9999999'; +a +2001-01-02 00:00:00.000000 +Warnings: +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +SELECT * FROM t1 WHERE a='20010101235959.9999999' AND a>='20010101235959.9999999'; +a +2001-01-02 00:00:00.000000 +Warnings: +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +SELECT * FROM t1 WHERE a='20010101235959.9999999' AND CONCAT(a)='2001-01-02 00:00:00.000000'; +a +2001-01-02 00:00:00.000000 +Warnings: +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='20010101235959.9999999' AND a>='20010101235959.9999999'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-02 00:00:00' +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='20010101235959.9999999' AND CONCAT(a)='2001-01-02 00:00:00.000000'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-02 00:00:00' +DROP TABLE t1; +# +# Comparing non-temporal to DATETIME +# +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('2001-01-01 23:59:59.9999999'); +SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-02 00:00:00'; +a +2001-01-01 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1 WHERE CONCAT(a)=TIMESTAMP'2001-01-02 00:00:00'; +a +2001-01-01 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-02 00:00:00'; +a +2001-01-01 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (20010101235959.9999999); +SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-02 00:00:00'; +a +20010101235959.9999999 +SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-02 00:00:00'; +a +20010101235959.9999999 +DROP TABLE t1; +# +# Literal corner case +# +SELECT TIMESTAMP'9999-12-31 23:59:59.999999'; +TIMESTAMP'9999-12-31 23:59:59.999999' +9999-12-31 23:59:59.999999 +SELECT TIME'9999-12-31 23:59:59.9999999'; +ERROR HY000: Incorrect TIME value: '9999-12-31 23:59:59.9999999' diff --git a/mysql-test/main/type_datetime_round.test b/mysql-test/main/type_datetime_round.test new file mode 100644 index 00000000000..15aec2cf4e0 --- /dev/null +++ b/mysql-test/main/type_datetime_round.test @@ -0,0 +1,147 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; + +--echo # +--echo # DATETIME: SET +--echo # + +CREATE TABLE t1 (a DATETIME(3), b DATETIME(4)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DATETIME(3), b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DATETIME(3), b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,20001231235959.9999); +INSERT INTO t1 VALUES(NULL,20001231235959.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +--echo # +--echo # DATETIME: ALTER +--echo # + +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +ALTER TABLE t1 MODIFY a DATETIME(3); +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +ALTER TABLE t1 MODIFY a DATETIME(3); +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +ALTER TABLE t1 MODIFY a DATETIME(3); +SELECT a FROM t1; +DROP TABLE t1; + + +--echo # +--echo # Corner case: +--echo # ALTER DATETIME to a shorter DATETIME +--echo # All values round, maximum possible value truncates. +--echo # + +SET time_zone='+00:00'; +CREATE TABLE t1 (ID INT, a DATETIME(6), comment VARCHAR(64)); +INSERT INTO t1 VALUES (0, '9999-12-30 23:59:58.999999', 'Should round'); +INSERT INTO t1 VALUES (1, '9999-12-31 22:59:59.999999', 'Should round'); +INSERT INTO t1 VALUES (2, '9999-12-31 23:59:58.999999', 'Should round'); +INSERT INTO t1 VALUES (3, '9999-12-31 23:59:59.999999', 'Should truncate'); +ALTER TABLE t1 MODIFY a DATETIME(5); +SELECT * FROM t1; +DROP TABLE t1; +SET time_zone=DEFAULT; + + +--echo # +--echo # NOW +--echo # + +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE OR REPLACE TABLE t1 (id SERIAL, a DATETIME(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIME(6)); +SELECT * FROM t1; +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; + + +--echo # +--echo # DATETIME: CAST +--echo # + +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +SELECT a, CAST(a AS DATETIME(3)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +SELECT a, CAST(a AS DATETIME(3)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +SELECT a, CAST(a AS DATETIME(3)) FROM t1; +DROP TABLE t1; + + +--echo # +--echo # Equal field propagation +--echo # + +CREATE TABLE t1 (a DATETIME(6)); +INSERT INTO t1 VALUES (20010101235959.999999); +INSERT INTO t1 VALUES (20010101235959.9999999); +SELECT * FROM t1 WHERE a=20010101235959.9999999; +SELECT * FROM t1 WHERE a='20010101235959.9999999'; +SELECT * FROM t1 WHERE a='20010101235959.9999999' AND a>='20010101235959.9999999'; +SELECT * FROM t1 WHERE a='20010101235959.9999999' AND CONCAT(a)='2001-01-02 00:00:00.000000'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='20010101235959.9999999' AND a>='20010101235959.9999999'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='20010101235959.9999999' AND CONCAT(a)='2001-01-02 00:00:00.000000'; +DROP TABLE t1; + +--echo # +--echo # Comparing non-temporal to DATETIME +--echo # + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('2001-01-01 23:59:59.9999999'); +SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-02 00:00:00'; +SELECT * FROM t1 WHERE CONCAT(a)=TIMESTAMP'2001-01-02 00:00:00'; +SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-02 00:00:00'; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (20010101235959.9999999); +SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-02 00:00:00'; +SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-02 00:00:00'; +DROP TABLE t1; + +--echo # +--echo # Literal corner case +--echo # + +SELECT TIMESTAMP'9999-12-31 23:59:59.999999'; +--error ER_WRONG_VALUE +SELECT TIME'9999-12-31 23:59:59.9999999'; diff --git a/mysql-test/main/type_time_round.result b/mysql-test/main/type_time_round.result new file mode 100644 index 00000000000..31e97c888db --- /dev/null +++ b/mysql-test/main/type_time_round.result @@ -0,0 +1,260 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; +# +# TIME: SET +# +CREATE TABLE t1 (a TIME(3), b TIME(4)); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a TIME(3), b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999'); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999999'); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +00:00:01.000 +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a TIME(3), b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,0.9999); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +00:00:01.000 +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a TIME(3), b DOUBLE); +INSERT INTO t1 VALUES(NULL,0.9999); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +00:00:01.000 +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a TIME(6), b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999999'); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +SELECT a FROM t1; +a +00:00:01.000000 +DROP TABLE t1; +CREATE TABLE t1 (a TIME(6), b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +00:00:01.000000 +DROP TABLE t1; +CREATE TABLE t1 (a TIME(6), b DOUBLE); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +00:00:01.000000 +DROP TABLE t1; +# +# TIME: ALTER +# +CREATE TABLE t1 (a TIME(4)); +INSERT INTO t1 VALUES('00:00:00.9999'); +ALTER TABLE t1 MODIFY a TIME(3); +SELECT a FROM t1; +a +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('00:00:00.9999'); +INSERT INTO t1 VALUES('00:00:00.9999999'); +ALTER TABLE t1 MODIFY a TIME(3); +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +SELECT a FROM t1; +a +00:00:01.000 +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +ALTER TABLE t1 MODIFY a TIME(3); +SELECT a FROM t1; +a +00:00:01.000 +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +ALTER TABLE t1 MODIFY a TIME(3); +Warnings: +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +00:00:01.000 +00:00:01.000 +DROP TABLE t1; +# +# TIME: CAST +# +CREATE TABLE t1 (a TIME(4)); +INSERT INTO t1 VALUES('00:00:00.9999'); +SELECT a, CAST(a AS TIME(3)) FROM t1; +a CAST(a AS TIME(3)) +00:00:00.9999 00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('00:00:00.9999'); +INSERT INTO t1 VALUES('00:00:00.9999999'); +SELECT a, CAST(a AS TIME(3)) FROM t1; +a CAST(a AS TIME(3)) +00:00:00.9999 00:00:01.000 +00:00:00.9999999 00:00:01.000 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(3)) FROM t1; +a CAST(a AS TIME(3)) +0.9999000000 00:00:01.000 +0.9999999000 00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(3)) FROM t1; +a CAST(a AS TIME(3)) +0.9999 00:00:01.000 +0.9999999 00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('00:00:00.9999999'); +SELECT a, CAST(a AS TIME(6)) FROM t1; +a CAST(a AS TIME(6)) +00:00:00.9999999 00:00:01.000000 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(6)) FROM t1; +a CAST(a AS TIME(6)) +0.9999999000 00:00:01.000000 +DROP TABLE t1; +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(6)) FROM t1; +a CAST(a AS TIME(6)) +0.9999999 00:00:01.000000 +DROP TABLE t1; +# +# NOW +# +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE OR REPLACE TABLE t1 (id SERIAL, a TIME(4)); +INSERT INTO t1 (a) VALUES (now(6)); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6)); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +INSERT INTO t1 (a) VALUES (CURRENT_TIME(6)); +SELECT * FROM t1; +id a +1 24:00:00.0000 +2 24:00:00.0000 +3 24:00:00.0000 +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; +# +# Equal field propagation +# +CREATE TABLE t1 (a TIME(6)); +INSERT INTO t1 VALUES (0.999999); +INSERT INTO t1 VALUES (0.9999999); +SELECT * FROM t1 WHERE a=0.9999999; +a +00:00:01.000000 +SELECT * FROM t1 WHERE a='0.9999999'; +a +00:00:01.000000 +Warnings: +Note 1292 Truncated incorrect time value: '0.9999999' +SELECT * FROM t1 WHERE a='0.9999999' AND a>='0.9999999'; +a +00:00:01.000000 +Warnings: +Note 1292 Truncated incorrect time value: '0.9999999' +Note 1292 Truncated incorrect time value: '0.9999999' +SELECT * FROM t1 WHERE a='0.9999999' AND CONCAT(a)='00:00:01.000000'; +a +00:00:01.000000 +Warnings: +Note 1292 Truncated incorrect time value: '0.9999999' +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0.9999999' AND a>='0.9999999'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1292 Truncated incorrect time value: '0.9999999' +Note 1292 Truncated incorrect time value: '0.9999999' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:01' +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0.9999999' AND CONCAT(a)='00:00:01.000000'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1292 Truncated incorrect time value: '0.9999999' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:01' +DROP TABLE t1; +# +# Comparing non-temporal to TIME +# +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('22:59:59.9999999'); +SELECT * FROM t1 WHERE a=TIME'23:00:00'; +a +22:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '22:59:59.9999999' +SELECT * FROM t1 WHERE CONCAT(a)=TIME'23:00:00'; +a +22:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '22:59:59.9999999' +SELECT * FROM t1 WHERE COALESCE(a)=TIME'23:00:00'; +a +22:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '22:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (225959.9999999); +SELECT * FROM t1 WHERE a=TIME'23:00:00'; +a +225959.9999999 +SELECT * FROM t1 WHERE COALESCE(a)=TIME'23:00:00'; +a +225959.9999999 +DROP TABLE t1; +# +# Literal corner case +# +SELECT TIME'838:59:59.999999'; +TIME'838:59:59.999999' +838:59:59.999999 +SELECT TIME'838:59:59.9999999'; +ERROR HY000: Incorrect TIME value: '838:59:59.9999999' +SELECT TIME'839:00:00'; +ERROR HY000: Incorrect TIME value: '839:00:00' diff --git a/mysql-test/main/type_time_round.test b/mysql-test/main/type_time_round.test new file mode 100644 index 00000000000..6d4b2d8947a --- /dev/null +++ b/mysql-test/main/type_time_round.test @@ -0,0 +1,184 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; + +--echo # +--echo # TIME: SET +--echo # + +CREATE TABLE t1 (a TIME(3), b TIME(4)); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME(3), b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999'); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME(3), b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,0.9999); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME(3), b DOUBLE); +INSERT INTO t1 VALUES(NULL,0.9999); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME(6), b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME(6), b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME(6), b DOUBLE); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +--echo # +--echo # TIME: ALTER +--echo # + +CREATE TABLE t1 (a TIME(4)); +INSERT INTO t1 VALUES('00:00:00.9999'); +ALTER TABLE t1 MODIFY a TIME(3); +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('00:00:00.9999'); +INSERT INTO t1 VALUES('00:00:00.9999999'); +ALTER TABLE t1 MODIFY a TIME(3); +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +ALTER TABLE t1 MODIFY a TIME(3); +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +ALTER TABLE t1 MODIFY a TIME(3); +SELECT a FROM t1; +DROP TABLE t1; + +--echo # +--echo # TIME: CAST +--echo # + +CREATE TABLE t1 (a TIME(4)); +INSERT INTO t1 VALUES('00:00:00.9999'); +SELECT a, CAST(a AS TIME(3)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('00:00:00.9999'); +INSERT INTO t1 VALUES('00:00:00.9999999'); +SELECT a, CAST(a AS TIME(3)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(3)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(3)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('00:00:00.9999999'); +SELECT a, CAST(a AS TIME(6)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(6)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(6)) FROM t1; +DROP TABLE t1; + + +--echo # +--echo # NOW +--echo # + +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE OR REPLACE TABLE t1 (id SERIAL, a TIME(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIME(6)); +SELECT * FROM t1; +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; + + +--echo # +--echo # Equal field propagation +--echo # + +CREATE TABLE t1 (a TIME(6)); +INSERT INTO t1 VALUES (0.999999); +INSERT INTO t1 VALUES (0.9999999); +SELECT * FROM t1 WHERE a=0.9999999; +SELECT * FROM t1 WHERE a='0.9999999'; +SELECT * FROM t1 WHERE a='0.9999999' AND a>='0.9999999'; +SELECT * FROM t1 WHERE a='0.9999999' AND CONCAT(a)='00:00:01.000000'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0.9999999' AND a>='0.9999999'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0.9999999' AND CONCAT(a)='00:00:01.000000'; +DROP TABLE t1; + + +--echo # +--echo # Comparing non-temporal to TIME +--echo # + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('22:59:59.9999999'); +SELECT * FROM t1 WHERE a=TIME'23:00:00'; +SELECT * FROM t1 WHERE CONCAT(a)=TIME'23:00:00'; +SELECT * FROM t1 WHERE COALESCE(a)=TIME'23:00:00'; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (225959.9999999); +SELECT * FROM t1 WHERE a=TIME'23:00:00'; +SELECT * FROM t1 WHERE COALESCE(a)=TIME'23:00:00'; +DROP TABLE t1; + +--echo # +--echo # Literal corner case +--echo # + +SELECT TIME'838:59:59.999999'; +--error ER_WRONG_VALUE +SELECT TIME'838:59:59.9999999'; +--error ER_WRONG_VALUE +SELECT TIME'839:00:00'; diff --git a/mysql-test/main/type_timestamp_round.result b/mysql-test/main/type_timestamp_round.result new file mode 100644 index 00000000000..69b2c8fdeba --- /dev/null +++ b/mysql-test/main/type_timestamp_round.result @@ -0,0 +1,164 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; +# +# TIMESTAMP: SET +# +CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b TIMESTAMP(4) NULL DEFAULT NULL); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999'); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,20001231235959.9999); +INSERT INTO t1 VALUES(NULL,20001231235959.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +# +# TIMESTAMP: ALTER +# +CREATE TABLE t1 (a TIMESTAMP(4) NULL DEFAULT NULL); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL; +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL; +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL; +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +# +# Corner case: +# ALTER TIMESTAMP to a shorter TIMESTAMP +# All values round, maximum possible value truncates. +# +SET time_zone='+00:00'; +CREATE TABLE t1 (ID INT, a TIMESTAMP(6), comment VARCHAR(64)); +INSERT INTO t1 VALUES (0, '2038-01-18 23:59:59.999999', 'Should round'); +INSERT INTO t1 VALUES (1, '2038-01-19 03:14:06.999999', 'Should round'); +INSERT INTO t1 VALUES (2, '2038-01-19 03:14:07.999999', 'Should truncate'); +ALTER TABLE t1 MODIFY a TIMESTAMP(5); +Warnings: +Warning 1264 Out of range value for column 'a' at row 3 +SELECT * FROM t1; +ID a comment +0 2038-01-19 00:00:00.00000 Should round +1 2038-01-19 03:14:07.00000 Should round +2 2038-01-19 03:14:07.99999 Should truncate +DROP TABLE t1; +SET time_zone=DEFAULT; +# +# NOW +# +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE OR REPLACE TABLE t1 (id SERIAL, a TIMESTAMP(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIME(6)); +SELECT * FROM t1; +id a +1 2011-01-01 00:00:00.0000 +2 2011-01-01 00:00:00.0000 +3 2011-01-01 00:00:00.0000 +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; +# +# DATETIME to TIMESTAMP conversion with DST change +# +SET sql_mode=IF(@@version LIKE '%MariaDB%', +'STRICT_ALL_TABLES,TIME_ROUND_FRACTIONAL', +'STRICT_ALL_TABLES'); +SET time_zone='Europe/Moscow'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.0' /* Winter time */); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.9' /* Rounds to the DST gap */); +ERROR 22007: Incorrect datetime value: '2010-03-28 01:59:59.9' for column 'a' at row 1 +SELECT * FROM t1; +a +2010-03-28 01:59:59 +DROP TABLE t1; +SET time_zone=DEFAULT; +SET sql_mode=@default_sql_mode; +SET sql_mode=IF(@@version LIKE '%MariaDB%','TIME_ROUND_FRACTIONAL',''); +SET time_zone='Europe/Moscow'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.0' /* Winter time */); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.9' /* Rounds to the DST gap, then gets fixed to the first second of the summer time */); +Warnings: +Warning 1299 Invalid TIMESTAMP value in column 'a' at row 1 +SELECT a, UNIX_TIMESTAMP(a) FROM t1; +a UNIX_TIMESTAMP(a) +2010-03-28 01:59:59 1269730799 +2010-03-28 03:00:00 1269730800 +DROP TABLE t1; +SET time_zone=DEFAULT; +SET sql_mode=@default_sql_mode; +# +# Comparing non-temporal to TIMESTAMP +# +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('2001-01-01 23:59:59.9999999'); +CREATE TABLE t2 (a TIMESTAMP); +INSERT INTO t2 VALUES ('2001-01-02 00:00:00'); +SELECT * FROM t1,t2 WHERE t1.a=t2.a; +a a +2001-01-01 23:59:59.9999999 2001-01-02 00:00:00 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1,t2 WHERE CONCAT(t1.a)=t2.a; +a a +2001-01-01 23:59:59.9999999 2001-01-02 00:00:00 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a; +a a +2001-01-01 23:59:59.9999999 2001-01-02 00:00:00 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +DROP TABLE t1,t2; +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (20010101235959.9999999); +CREATE TABLE t2 (a TIMESTAMP); +INSERT INTO t2 VALUES ('2001-01-02 00:00:00'); +SELECT * FROM t1,t2 WHERE t1.a=t2.a; +a a +20010101235959.9999999 2001-01-02 00:00:00 +SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a; +a a +20010101235959.9999999 2001-01-02 00:00:00 +DROP TABLE t1,t2; diff --git a/mysql-test/main/type_timestamp_round.test b/mysql-test/main/type_timestamp_round.test new file mode 100644 index 00000000000..2ed01cc2a82 --- /dev/null +++ b/mysql-test/main/type_timestamp_round.test @@ -0,0 +1,138 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; + +--echo # +--echo # TIMESTAMP: SET +--echo # + +CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b TIMESTAMP(4) NULL DEFAULT NULL); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,20001231235959.9999); +INSERT INTO t1 VALUES(NULL,20001231235959.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +--echo # +--echo # TIMESTAMP: ALTER +--echo # + +CREATE TABLE t1 (a TIMESTAMP(4) NULL DEFAULT NULL); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL; +SELECT a FROM t1; +DROP TABLE t1; + + +--echo # +--echo # Corner case: +--echo # ALTER TIMESTAMP to a shorter TIMESTAMP +--echo # All values round, maximum possible value truncates. +--echo # + +SET time_zone='+00:00'; +CREATE TABLE t1 (ID INT, a TIMESTAMP(6), comment VARCHAR(64)); +INSERT INTO t1 VALUES (0, '2038-01-18 23:59:59.999999', 'Should round'); +INSERT INTO t1 VALUES (1, '2038-01-19 03:14:06.999999', 'Should round'); +INSERT INTO t1 VALUES (2, '2038-01-19 03:14:07.999999', 'Should truncate'); +ALTER TABLE t1 MODIFY a TIMESTAMP(5); +SELECT * FROM t1; +DROP TABLE t1; +SET time_zone=DEFAULT; + +--echo # +--echo # NOW +--echo # + +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE OR REPLACE TABLE t1 (id SERIAL, a TIMESTAMP(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIME(6)); +SELECT * FROM t1; +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; + + +--echo # +--echo # DATETIME to TIMESTAMP conversion with DST change +--echo # + +--disable_warnings +SET sql_mode=IF(@@version LIKE '%MariaDB%', + 'STRICT_ALL_TABLES,TIME_ROUND_FRACTIONAL', + 'STRICT_ALL_TABLES'); +--enable_warnings +SET time_zone='Europe/Moscow'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.0' /* Winter time */); +--error ER_TRUNCATED_WRONG_VALUE +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.9' /* Rounds to the DST gap */); +SELECT * FROM t1; +DROP TABLE t1; +SET time_zone=DEFAULT; +--disable_warnings +SET sql_mode=@default_sql_mode; +--enable_warnings + +SET sql_mode=IF(@@version LIKE '%MariaDB%','TIME_ROUND_FRACTIONAL',''); +SET time_zone='Europe/Moscow'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.0' /* Winter time */); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.9' /* Rounds to the DST gap, then gets fixed to the first second of the summer time */); +SELECT a, UNIX_TIMESTAMP(a) FROM t1; +DROP TABLE t1; +SET time_zone=DEFAULT; +--disable_warnings +SET sql_mode=@default_sql_mode; +--enable_warnings + + +--echo # +--echo # Comparing non-temporal to TIMESTAMP +--echo # + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('2001-01-01 23:59:59.9999999'); +CREATE TABLE t2 (a TIMESTAMP); +INSERT INTO t2 VALUES ('2001-01-02 00:00:00'); +SELECT * FROM t1,t2 WHERE t1.a=t2.a; +SELECT * FROM t1,t2 WHERE CONCAT(t1.a)=t2.a; +SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a; +DROP TABLE t1,t2; + +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (20010101235959.9999999); +CREATE TABLE t2 (a TIMESTAMP); +INSERT INTO t2 VALUES ('2001-01-02 00:00:00'); +SELECT * FROM t1,t2 WHERE t1.a=t2.a; +SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a; +DROP TABLE t1,t2; diff --git a/mysql-test/main/udf.result b/mysql-test/main/udf.result index 6af6b167511..13eb186135b 100644 --- a/mysql-test/main/udf.result +++ b/mysql-test/main/udf.result @@ -465,3 +465,108 @@ a b Hello HL DROP FUNCTION METAPHON; DROP TABLE t1; + +MDEV-15073: Generic UDAF parser code in server for windows functions + +CREATE AGGREGATE FUNCTION avgcost +RETURNS REAL SONAME "UDF_EXAMPLE_LIB"; +CREATE AGGREGATE FUNCTION avg2 +RETURNS REAL SONAME "UDF_EXAMPLE_LIB"; +CREATE FUNCTION myfunc_double RETURNS REAL SONAME "UDF_EXAMPLE_LIB"; +create table t1(pk int primary key, +a int, +sum int, +price float(24)); +insert into t1 values +(1, 1, 100, 50.00), +(2, 1, 100, 100.00), +(3, 1, 100, 50.00), +(4, 1, 100, 50.00), +(5, 1, 100, 50.00), +(6, 1, 100, NULL), +(7, 1, NULL, NULL), +(8, 2, 2, 2), +(9, 2, 4, 4); +select pk, a, sum, price, avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +from t1; +pk a sum price avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +1 1 100 50 75.0000 +2 1 100 100 66.6667 +3 1 100 50 66.6667 +4 1 100 50 50.0000 +5 1 100 50 50.0000 +6 1 100 NULL 50.0000 +7 1 NULL NULL 0.0000 +8 2 2 2 3.3333 +9 2 4 4 3.3333 +select pk, a, sum, price, avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +pk a sum price avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +1 1 100 50 50.0000 +2 1 100 100 75.0000 +3 1 100 50 75.0000 +4 1 100 50 50.0000 +5 1 100 50 50.0000 +6 1 100 NULL 50.0000 +7 1 NULL NULL 0.0000 +8 2 2 2 2.0000 +9 2 4 4 3.3333 +select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +from t1; +pk a sum price avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +1 1 100 50 0.7500 +2 1 100 100 0.6667 +3 1 100 50 0.6667 +4 1 100 50 0.5000 +5 1 100 50 0.5000 +6 1 100 NULL 0.5000 +7 1 NULL NULL 0.0000 +8 2 2 2 1.0000 +9 2 4 4 1.0000 +select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +pk a sum price avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +1 1 100 50 0.5000 +2 1 100 100 0.7500 +3 1 100 50 0.7500 +4 1 100 50 0.5000 +5 1 100 50 0.5000 +6 1 100 NULL 0.5000 +7 1 NULL NULL 0.0000 +8 2 2 2 1.0000 +9 2 4 4 1.0000 +select pk, a, sum, price, tttttttt(sprice,sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from ' at line 1 +select pk, a, sum, price, myfunc_double(sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from ' at line 1 +select pk, a, sum, price, round(sprice,sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from ' at line 1 +select pk, a, sum, price, myfunc_double(sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from ' at line 1 +set @save_sql_mode = @@sql_mode; +set sql_mode="oracle"; +select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +pk a sum price avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +1 1 100 50 0.5000 +2 1 100 100 0.7500 +3 1 100 50 0.7500 +4 1 100 50 0.5000 +5 1 100 50 0.5000 +6 1 100 NULL 0.5000 +7 1 NULL NULL 0.0000 +8 2 2 2 1.0000 +9 2 4 4 1.0000 +set sql_mode= @save_sql_mode; +drop table t1; +DROP FUNCTION avgcost; +DROP FUNCTION avg2; +DROP FUNCTION myfunc_double; diff --git a/mysql-test/main/udf.test b/mysql-test/main/udf.test index c3a25c6bcce..43d66dc68e2 100644 --- a/mysql-test/main/udf.test +++ b/mysql-test/main/udf.test @@ -528,3 +528,69 @@ DROP FUNCTION METAPHON; #INSERT INTO t1 (a) VALUES ('Hello'); #SELECT * FROM t1; DROP TABLE t1; + +--echo +--echo MDEV-15073: Generic UDAF parser code in server for windows functions +--echo + +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +eval CREATE AGGREGATE FUNCTION avgcost + RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +eval CREATE AGGREGATE FUNCTION avg2 + RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +eval CREATE FUNCTION myfunc_double RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; + +create table t1(pk int primary key, + a int, + sum int, + price float(24)); +insert into t1 values + (1, 1, 100, 50.00), + (2, 1, 100, 100.00), + (3, 1, 100, 50.00), + (4, 1, 100, 50.00), + (5, 1, 100, 50.00), + (6, 1, 100, NULL), + (7, 1, NULL, NULL), + (8, 2, 2, 2), + (9, 2, 4, 4); + +--sorted_result +select pk, a, sum, price, avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +from t1; +--sorted_result +select pk, a, sum, price, avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; + +--sorted_result +select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +from t1; +--sorted_result +select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +--error ER_PARSE_ERROR +select pk, a, sum, price, tttttttt(sprice,sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +--error ER_PARSE_ERROR +select pk, a, sum, price, myfunc_double(sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +--error ER_PARSE_ERROR +select pk, a, sum, price, round(sprice,sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +--error ER_PARSE_ERROR +select pk, a, sum, price, myfunc_double(sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; + +set @save_sql_mode = @@sql_mode; +set sql_mode="oracle"; +--sorted_result +select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +set sql_mode= @save_sql_mode; + +drop table t1; +DROP FUNCTION avgcost; +DROP FUNCTION avg2; +DROP FUNCTION myfunc_double; diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index 5a7fdbd63c9..e682a8599c4 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -61,7 +61,7 @@ def mysql event modified 9 '0000-00-00 00:00:00' NO timestamp NULL NULL NULL NUL def mysql event name 2 '' NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) PRI select,insert,update,references NEVER NULL def mysql event on_completion 14 'DROP' NO enum 8 24 NULL NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE') select,insert,update,references NEVER NULL def mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references NEVER NULL -def mysql event sql_mode 15 '' NO set 539 1617 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') select,insert,update,references NEVER NULL +def mysql event sql_mode 15 '' NO set 561 1683 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') select,insert,update,references NEVER NULL def mysql event starts 11 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select,insert,update,references NEVER NULL def mysql event status 13 'ENABLED' NO enum 18 54 NULL NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') select,insert,update,references NEVER NULL def mysql event time_zone 18 'SYSTEM' NO char 64 64 NULL NULL NULL latin1 latin1_swedish_ci char(64) select,insert,update,references NEVER NULL @@ -133,7 +133,7 @@ def mysql proc returns 10 NULL NO longblob 4294967295 4294967295 NULL NULL NULL def mysql proc security_type 8 'DEFINER' NO enum 7 21 NULL NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER') select,insert,update,references NEVER NULL def mysql proc specific_name 4 '' NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references NEVER NULL def mysql proc sql_data_access 6 'CONTAINS_SQL' NO enum 17 51 NULL NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') select,insert,update,references NEVER NULL -def mysql proc sql_mode 15 '' NO set 539 1617 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') select,insert,update,references NEVER NULL +def mysql proc sql_mode 15 '' NO set 561 1683 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') select,insert,update,references NEVER NULL def mysql proc type 3 NULL NO enum 12 36 NULL NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') PRI select,insert,update,references NEVER NULL def mysql procs_priv Db 2 '' NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references NEVER NULL def mysql procs_priv Grantor 6 '' NO char 141 423 NULL NULL NULL utf8 utf8_bin char(141) MUL select,insert,update,references NEVER NULL @@ -380,7 +380,7 @@ NULL mysql event starts datetime NULL NULL NULL NULL datetime NULL mysql event ends datetime NULL NULL NULL NULL datetime 3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') 3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE') -3.0000 mysql event sql_mode set 539 1617 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') +3.0000 mysql event sql_mode set 561 1683 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') 3.0000 mysql event comment char 64 192 utf8 utf8_bin char(64) NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned 1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64) @@ -451,7 +451,7 @@ NULL mysql innodb_table_stats sum_of_other_index_sizes bigint NULL NULL NULL NUL 3.0000 mysql proc definer char 141 423 utf8 utf8_bin char(141) NULL mysql proc created timestamp NULL NULL NULL NULL timestamp NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp -3.0000 mysql proc sql_mode set 539 1617 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') +3.0000 mysql proc sql_mode set 561 1683 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') 1.0000 mysql proc comment text 65535 65535 utf8 utf8_bin text 3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32) 3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32) diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result index 440478b892d..d5af88994f6 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result @@ -61,7 +61,7 @@ def mysql event modified 9 '0000-00-00 00:00:00' NO timestamp NULL NULL NULL NUL def mysql event name 2 '' NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) PRI NEVER NULL def mysql event on_completion 14 'DROP' NO enum 8 24 NULL NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE') NEVER NULL def mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned NEVER NULL -def mysql event sql_mode 15 '' NO set 539 1617 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NEVER NULL +def mysql event sql_mode 15 '' NO set 561 1683 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NEVER NULL def mysql event starts 11 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL def mysql event status 13 'ENABLED' NO enum 18 54 NULL NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NEVER NULL def mysql event time_zone 18 'SYSTEM' NO char 64 64 NULL NULL NULL latin1 latin1_swedish_ci char(64) NEVER NULL @@ -119,7 +119,7 @@ def mysql proc returns 10 NULL NO longblob 4294967295 4294967295 NULL NULL NULL def mysql proc security_type 8 'DEFINER' NO enum 7 21 NULL NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER') NEVER NULL def mysql proc specific_name 4 '' NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) NEVER NULL def mysql proc sql_data_access 6 'CONTAINS_SQL' NO enum 17 51 NULL NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') NEVER NULL -def mysql proc sql_mode 15 '' NO set 539 1617 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NEVER NULL +def mysql proc sql_mode 15 '' NO set 561 1683 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NEVER NULL def mysql proc type 3 NULL NO enum 12 36 NULL NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') PRI NEVER NULL def mysql procs_priv Db 2 '' NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI NEVER NULL def mysql procs_priv Grantor 6 '' NO char 141 423 NULL NULL NULL utf8 utf8_bin char(141) MUL NEVER NULL @@ -377,7 +377,7 @@ NULL mysql event starts datetime NULL NULL NULL NULL datetime NULL mysql event ends datetime NULL NULL NULL NULL datetime 3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') 3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE') -3.0000 mysql event sql_mode set 539 1617 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') +3.0000 mysql event sql_mode set 561 1683 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') 3.0000 mysql event comment char 64 192 utf8 utf8_bin char(64) NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned 1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64) @@ -434,7 +434,7 @@ NULL mysql index_stats avg_frequency decimal NULL NULL NULL NULL decimal(12,4) 3.0000 mysql proc definer char 141 423 utf8 utf8_bin char(141) NULL mysql proc created timestamp NULL NULL NULL NULL timestamp NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp -3.0000 mysql proc sql_mode set 539 1617 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') +3.0000 mysql proc sql_mode set 561 1683 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') 1.0000 mysql proc comment text 65535 65535 utf8 utf8_bin text 3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32) 3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index e84832458a3..bfceb370682 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -44,8 +44,15 @@ galera_kill_ddl : MDEV-17108 Test failure on galera.galera_kill_ddl galera_var_node_address : MDEV-17151 Galera test failure on galera.galera_var_node_address galera_binlog_stmt_autoinc: MDEV-17106 Test failure on galera.galera_binlog_stmt_autoinc galera_gc_fc_limit : MDEV-17061 Test failure on galera.galera_gc_fc_limit -partition : MDEV-13881 galera.partition failed in buildbot with wrong result galera_as_slave_replication_budle : MDEV-15785 Test case galera_as_slave_replication_bundle caused debug assertion galera_wan : MDEV-17259: Test failure on galera.galera_wan galera_pc_ignore_sb : MDEV-17357 Test failure on galera.galera_pc_ignore_sb galera_drop_database : test +galera_autoinc_sst_xtrabackup : xtrabackup is deprecated +galera_ist_xtrabackup-v2 : xtrabackup is deprecated +galera_sst_xtrabackup-v2_data_dir : xtrabackup is deprecated +galera_sst_xtrabackup-v2_encrypt_with_key : xtrabackup is deprecated +galera_sst_xtrabackup-v2-options : xtrabackup is deprecated +galera_ist_innodb_flush_logs : xtrabackup is deprecated +galera_sst_xtrabackup-v2 : xtrabackup is deprecated + diff --git a/mysql-test/suite/galera/include/have_filekeymanagement.inc b/mysql-test/suite/galera/include/have_filekeymanagement.inc new file mode 100644 index 00000000000..f5507ca4548 --- /dev/null +++ b/mysql-test/suite/galera/include/have_filekeymanagement.inc @@ -0,0 +1,3 @@ +# +# Used in galera/suite.pm to check file key management plugin +# diff --git a/mysql-test/suite/galera/include/have_xtrabackup.inc b/mysql-test/suite/galera/include/have_xtrabackup.inc deleted file mode 100644 index 0dd693f2c63..00000000000 --- a/mysql-test/suite/galera/include/have_xtrabackup.inc +++ /dev/null @@ -1,4 +0,0 @@ -# -# suite.pm will make sure that all tests including this file -# will be skipped as needed -# diff --git a/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result b/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result new file mode 100644 index 00000000000..d0fac1e3d14 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result @@ -0,0 +1,47 @@ +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +CREATE PROCEDURE p1 () +BEGIN +DECLARE x INT DEFAULT 1; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; +WHILE 1 DO +INSERT INTO t1 VALUES (DEFAULT); +COMMIT; +END WHILE; +END| +CALL p1();; +connection node_2; +CALL p1();; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; +Killing server ... +INSERT INTO t1 VALUES (DEFAULT); +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1a; +INSERT INTO t1 VALUES (DEFAULT); +connection node_1; +Got one of the listed errors +connection node_2; +Got one of the listed errors +connection node_1a; +connection node_2a; +count_equal +1 +CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member 0"); +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE +2 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +connection node_1a; +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE +2 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +DROP PROCEDURE p1; +DROP TABLE t1; +CALL mtr.add_suppression("gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"); +CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member 0"); diff --git a/mysql-test/suite/galera/r/galera_ist_mariabackup,debug.rdiff b/mysql-test/suite/galera/r/galera_ist_mariabackup,debug.rdiff new file mode 100644 index 00000000000..9684e290778 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ist_mariabackup,debug.rdiff @@ -0,0 +1,114 @@ +--- r/galera_ist_mariabackup.result 2018-11-21 22:30:21.968817468 +0200 ++++ r/galera_ist_mariabackup.reject 2018-11-22 09:16:27.832601754 +0200 +@@ -285,3 +285,111 @@ + DROP TABLE t1; + COMMIT; + SET AUTOCOMMIT=ON; ++Performing State Transfer on a server that has been killed and restarted ++while a DDL was in progress on it ++connection node_1; ++CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++connection node_2; ++START TRANSACTION; ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++COMMIT; ++SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; ++connection node_1; ++ALTER TABLE t1 ADD COLUMN f2 INTEGER; ++connection node_2; ++SET wsrep_sync_wait = 0; ++Killing server ... ++connection node_1; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++COMMIT; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++connection node_2; ++Performing --wsrep-recover ... ++connection node_2; ++Starting server ... ++Using --wsrep-start-position when starting mysqld ... ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++COMMIT; ++connection node_1; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++COMMIT; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++COMMIT; ++connection node_1a_galera_st_kill_slave_ddl; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++ROLLBACK; ++SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; ++COUNT(*) = 2 ++1 ++SELECT COUNT(*) = 35 FROM t1; ++COUNT(*) = 35 ++1 ++SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; ++COUNT(*) = 0 ++1 ++COMMIT; ++SET AUTOCOMMIT=ON; ++connection node_1; ++SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; ++COUNT(*) = 2 ++1 ++SELECT COUNT(*) = 35 FROM t1; ++COUNT(*) = 35 ++1 ++SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; ++COUNT(*) = 0 ++1 ++DROP TABLE t1; ++COMMIT; ++SET AUTOCOMMIT=ON; ++SET GLOBAL debug_dbug = $debug_orig; diff --git a/mysql-test/suite/galera/r/galera_ist_mariabackup.result b/mysql-test/suite/galera/r/galera_ist_mariabackup.result new file mode 100644 index 00000000000..8a7c02ab1b6 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ist_mariabackup.result @@ -0,0 +1,287 @@ +connection node_1; +connection node_2; +Performing State Transfer on a server that has been temporarily disconnected +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Unloading wsrep provider ... +SET GLOBAL wsrep_provider = 'none'; +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_disconnect_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +connection node_2; +Loading wsrep provider ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_disconnect_slave; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been shut down cleanly and restarted +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Shutting down server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_shutdown_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +connection node_2; +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_shutdown_slave; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Killing server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +connection node_2; +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_kill_slave; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/r/galera_ist_mariabackup_innodb_flush_logs,debug.rdiff b/mysql-test/suite/galera/r/galera_ist_mariabackup_innodb_flush_logs,debug.rdiff new file mode 100644 index 00000000000..792f98b4427 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ist_mariabackup_innodb_flush_logs,debug.rdiff @@ -0,0 +1,114 @@ +--- r/galera_ist_mariabackup_innodb_flush_logs.result 2018-11-21 21:34:20.157054441 +0200 ++++ r/galera_ist_mariabackup_innodb_flush_logs.reject 2018-11-22 09:16:16.824604445 +0200 +@@ -94,3 +94,111 @@ + DROP TABLE t1; + COMMIT; + SET AUTOCOMMIT=ON; ++Performing State Transfer on a server that has been killed and restarted ++while a DDL was in progress on it ++connection node_1; ++CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++connection node_2; ++START TRANSACTION; ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++COMMIT; ++SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; ++connection node_1; ++ALTER TABLE t1 ADD COLUMN f2 INTEGER; ++connection node_2; ++SET wsrep_sync_wait = 0; ++Killing server ... ++connection node_1; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++COMMIT; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++connection node_2; ++Performing --wsrep-recover ... ++connection node_2; ++Starting server ... ++Using --wsrep-start-position when starting mysqld ... ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++COMMIT; ++connection node_1; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++COMMIT; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++COMMIT; ++connection node_1a_galera_st_kill_slave_ddl; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++ROLLBACK; ++SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; ++COUNT(*) = 2 ++1 ++SELECT COUNT(*) = 35 FROM t1; ++COUNT(*) = 35 ++1 ++SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; ++COUNT(*) = 0 ++1 ++COMMIT; ++SET AUTOCOMMIT=ON; ++connection node_1; ++SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; ++COUNT(*) = 2 ++1 ++SELECT COUNT(*) = 35 FROM t1; ++COUNT(*) = 35 ++1 ++SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; ++COUNT(*) = 0 ++1 ++DROP TABLE t1; ++COMMIT; ++SET AUTOCOMMIT=ON; ++SET GLOBAL debug_dbug = $debug_orig; diff --git a/mysql-test/suite/galera/r/galera_ist_mariabackup_innodb_flush_logs.result b/mysql-test/suite/galera/r/galera_ist_mariabackup_innodb_flush_logs.result new file mode 100644 index 00000000000..7813b5a58fc --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ist_mariabackup_innodb_flush_logs.result @@ -0,0 +1,96 @@ +Performing State Transfer on a server that has been killed and restarted +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Killing server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +connection node_2; +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_kill_slave; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/r/galera_ist_mysqldump,debug.rdiff b/mysql-test/suite/galera/r/galera_ist_mysqldump,debug.rdiff index 74e6abd713f..141b1ebd25f 100644 --- a/mysql-test/suite/galera/r/galera_ist_mysqldump,debug.rdiff +++ b/mysql-test/suite/galera/r/galera_ist_mysqldump,debug.rdiff @@ -1,11 +1,12 @@ ---- r/galera_ist_mysqldump.result 2018-09-11 12:38:42.027479411 +0300 -+++ r/galera_ist_mysqldump.reject 2018-09-17 10:28:44.483441364 +0300 -@@ -180,6 +180,103 @@ +--- r/galera_ist_mysqldump.result 2018-11-22 14:25:28.551554055 +0200 ++++ r/galera_ist_mysqldump.reject 2018-11-22 15:46:33.119441931 +0200 +@@ -200,6 +200,114 @@ DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it ++connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; @@ -14,6 +15,7 @@ +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); ++connection node_2; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); @@ -22,9 +24,12 @@ +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; ++connection node_1; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; ++connection node_2; +SET wsrep_sync_wait = 0; +Killing server ... ++connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); @@ -39,6 +44,7 @@ +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); @@ -46,7 +52,9 @@ +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++connection node_2; +Performing --wsrep-recover ... ++connection node_2; +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; @@ -57,6 +65,7 @@ +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; ++connection node_1; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); @@ -71,6 +80,7 @@ +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; ++connection node_1a_galera_st_kill_slave_ddl; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); @@ -88,6 +98,7 @@ +1 +COMMIT; +SET AUTOCOMMIT=ON; ++connection node_1; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 @@ -101,6 +112,6 @@ +COMMIT; +SET AUTOCOMMIT=ON; +SET GLOBAL debug_dbug = $debug_orig; + connection node_1; CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); DROP USER sst; - CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); diff --git a/mysql-test/suite/galera/r/galera_sst_mariabackup,debug.rdiff b/mysql-test/suite/galera/r/galera_sst_mariabackup,debug.rdiff index 8b091eb370a..819bcba7cac 100644 --- a/mysql-test/suite/galera/r/galera_sst_mariabackup,debug.rdiff +++ b/mysql-test/suite/galera/r/galera_sst_mariabackup,debug.rdiff @@ -1,5 +1,5 @@ ---- galera_sst_mariabackup.result -+++ galera_sst_mariabackup,debug.reject +--- r/galera_sst_mariabackup.result 2018-11-21 16:50:35.766982279 +0200 ++++ r/galera_sst_mariabackup.reject 2018-11-22 09:20:10.344408266 +0200 @@ -286,5 +286,113 @@ DROP TABLE t1; COMMIT; diff --git a/mysql-test/suite/galera/r/galera_sst_mariabackup_encrypt_with_key.result b/mysql-test/suite/galera/r/galera_sst_mariabackup_encrypt_with_key.result new file mode 100644 index 00000000000..990e0a29506 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_mariabackup_encrypt_with_key.result @@ -0,0 +1,3 @@ +SELECT 1; +1 +1 diff --git a/mysql-test/suite/galera/r/galera_sst_mariabackup_table_options.result b/mysql-test/suite/galera/r/galera_sst_mariabackup_table_options.result new file mode 100644 index 00000000000..9180ed5e421 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_mariabackup_table_options.result @@ -0,0 +1,997 @@ +connection node_1; +connection node_2; +Performing State Transfer on a server that starts from a clean var directory +This is accomplished by shutting down node #2 and removing its var directory before restarting it +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +CREATE TABLE t2 (f1 CHAR(255)) ENGINE=InnoDB PAGE_COMPRESSED=1; +CREATE TABLE t3 (f1 CHAR(255)) ENGINE=InnoDB PAGE_COMPRESSED=1 ENCRYPTED=NO; +CREATE TABLE t4 (f1 CHAR(255)) ENGINE=InnoDB PAGE_COMPRESSED=1 ENCRYPTED=YES; +CREATE TABLE t5 (f1 CHAR(255)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +CREATE TABLE t6 (f1 CHAR(255)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED ENCRYPTED=NO; +CREATE TABLE t7 (f1 CHAR(255)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED ENCRYPTED=YES; +CREATE TABLE t8 (f1 CHAR(255)) ENGINE=InnoDB ENCRYPTED=NO; +CREATE TABLE t9 (f1 CHAR(255)) ENGINE=InnoDB ENCRYPTED=YES; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +insert into t9 values ('node1_committed_before'); +insert into t9 values ('node1_committed_before'); +insert into t9 values ('node1_committed_before'); +insert into t9 values ('node1_committed_before'); +insert into t9 values ('node1_committed_before'); +insert into t8 values ('node1_committed_before'); +insert into t8 values ('node1_committed_before'); +insert into t8 values ('node1_committed_before'); +insert into t8 values ('node1_committed_before'); +insert into t8 values ('node1_committed_before'); +insert into t7 values ('node1_committed_before'); +insert into t7 values ('node1_committed_before'); +insert into t7 values ('node1_committed_before'); +insert into t7 values ('node1_committed_before'); +insert into t7 values ('node1_committed_before'); +insert into t6 values ('node1_committed_before'); +insert into t6 values ('node1_committed_before'); +insert into t6 values ('node1_committed_before'); +insert into t6 values ('node1_committed_before'); +insert into t6 values ('node1_committed_before'); +insert into t5 values ('node1_committed_before'); +insert into t5 values ('node1_committed_before'); +insert into t5 values ('node1_committed_before'); +insert into t5 values ('node1_committed_before'); +insert into t5 values ('node1_committed_before'); +insert into t4 values ('node1_committed_before'); +insert into t4 values ('node1_committed_before'); +insert into t4 values ('node1_committed_before'); +insert into t4 values ('node1_committed_before'); +insert into t4 values ('node1_committed_before'); +insert into t3 values ('node1_committed_before'); +insert into t3 values ('node1_committed_before'); +insert into t3 values ('node1_committed_before'); +insert into t3 values ('node1_committed_before'); +insert into t3 values ('node1_committed_before'); +insert into t2 values ('node1_committed_before'); +insert into t2 values ('node1_committed_before'); +insert into t2 values ('node1_committed_before'); +insert into t2 values ('node1_committed_before'); +insert into t2 values ('node1_committed_before'); +insert into t1 values ('node1_committed_before'); +insert into t1 values ('node1_committed_before'); +insert into t1 values ('node1_committed_before'); +insert into t1 values ('node1_committed_before'); +insert into t1 values ('node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +insert into t9 values ('node2_committed_before'); +insert into t9 values ('node2_committed_before'); +insert into t9 values ('node2_committed_before'); +insert into t9 values ('node2_committed_before'); +insert into t9 values ('node2_committed_before'); +insert into t8 values ('node2_committed_before'); +insert into t8 values ('node2_committed_before'); +insert into t8 values ('node2_committed_before'); +insert into t8 values ('node2_committed_before'); +insert into t8 values ('node2_committed_before'); +insert into t7 values ('node2_committed_before'); +insert into t7 values ('node2_committed_before'); +insert into t7 values ('node2_committed_before'); +insert into t7 values ('node2_committed_before'); +insert into t7 values ('node2_committed_before'); +insert into t6 values ('node2_committed_before'); +insert into t6 values ('node2_committed_before'); +insert into t6 values ('node2_committed_before'); +insert into t6 values ('node2_committed_before'); +insert into t6 values ('node2_committed_before'); +insert into t5 values ('node2_committed_before'); +insert into t5 values ('node2_committed_before'); +insert into t5 values ('node2_committed_before'); +insert into t5 values ('node2_committed_before'); +insert into t5 values ('node2_committed_before'); +insert into t4 values ('node2_committed_before'); +insert into t4 values ('node2_committed_before'); +insert into t4 values ('node2_committed_before'); +insert into t4 values ('node2_committed_before'); +insert into t4 values ('node2_committed_before'); +insert into t3 values ('node2_committed_before'); +insert into t3 values ('node2_committed_before'); +insert into t3 values ('node2_committed_before'); +insert into t3 values ('node2_committed_before'); +insert into t3 values ('node2_committed_before'); +insert into t2 values ('node2_committed_before'); +insert into t2 values ('node2_committed_before'); +insert into t2 values ('node2_committed_before'); +insert into t2 values ('node2_committed_before'); +insert into t2 values ('node2_committed_before'); +insert into t1 values ('node2_committed_before'); +insert into t1 values ('node2_committed_before'); +insert into t1 values ('node2_committed_before'); +insert into t1 values ('node2_committed_before'); +insert into t1 values ('node2_committed_before'); +COMMIT; +Shutting down server ... +connection node_1; +Cleaning var directory ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +insert into t9 values ('node1_committed_during'); +insert into t9 values ('node1_committed_during'); +insert into t9 values ('node1_committed_during'); +insert into t9 values ('node1_committed_during'); +insert into t9 values ('node1_committed_during'); +insert into t8 values ('node1_committed_during'); +insert into t8 values ('node1_committed_during'); +insert into t8 values ('node1_committed_during'); +insert into t8 values ('node1_committed_during'); +insert into t8 values ('node1_committed_during'); +insert into t7 values ('node1_committed_during'); +insert into t7 values ('node1_committed_during'); +insert into t7 values ('node1_committed_during'); +insert into t7 values ('node1_committed_during'); +insert into t7 values ('node1_committed_during'); +insert into t6 values ('node1_committed_during'); +insert into t6 values ('node1_committed_during'); +insert into t6 values ('node1_committed_during'); +insert into t6 values ('node1_committed_during'); +insert into t6 values ('node1_committed_during'); +insert into t5 values ('node1_committed_during'); +insert into t5 values ('node1_committed_during'); +insert into t5 values ('node1_committed_during'); +insert into t5 values ('node1_committed_during'); +insert into t5 values ('node1_committed_during'); +insert into t4 values ('node1_committed_during'); +insert into t4 values ('node1_committed_during'); +insert into t4 values ('node1_committed_during'); +insert into t4 values ('node1_committed_during'); +insert into t4 values ('node1_committed_during'); +insert into t3 values ('node1_committed_during'); +insert into t3 values ('node1_committed_during'); +insert into t3 values ('node1_committed_during'); +insert into t3 values ('node1_committed_during'); +insert into t3 values ('node1_committed_during'); +insert into t2 values ('node1_committed_during'); +insert into t2 values ('node1_committed_during'); +insert into t2 values ('node1_committed_during'); +insert into t2 values ('node1_committed_during'); +insert into t2 values ('node1_committed_during'); +insert into t1 values ('node1_committed_during'); +insert into t1 values ('node1_committed_during'); +insert into t1 values ('node1_committed_during'); +insert into t1 values ('node1_committed_during'); +insert into t1 values ('node1_committed_during'); +COMMIT; +START TRANSACTION; +insert into t9 values ('node1_to_be_committed_after'); +insert into t9 values ('node1_to_be_committed_after'); +insert into t9 values ('node1_to_be_committed_after'); +insert into t9 values ('node1_to_be_committed_after'); +insert into t9 values ('node1_to_be_committed_after'); +insert into t8 values ('node1_to_be_committed_after'); +insert into t8 values ('node1_to_be_committed_after'); +insert into t8 values ('node1_to_be_committed_after'); +insert into t8 values ('node1_to_be_committed_after'); +insert into t8 values ('node1_to_be_committed_after'); +insert into t7 values ('node1_to_be_committed_after'); +insert into t7 values ('node1_to_be_committed_after'); +insert into t7 values ('node1_to_be_committed_after'); +insert into t7 values ('node1_to_be_committed_after'); +insert into t7 values ('node1_to_be_committed_after'); +insert into t6 values ('node1_to_be_committed_after'); +insert into t6 values ('node1_to_be_committed_after'); +insert into t6 values ('node1_to_be_committed_after'); +insert into t6 values ('node1_to_be_committed_after'); +insert into t6 values ('node1_to_be_committed_after'); +insert into t5 values ('node1_to_be_committed_after'); +insert into t5 values ('node1_to_be_committed_after'); +insert into t5 values ('node1_to_be_committed_after'); +insert into t5 values ('node1_to_be_committed_after'); +insert into t5 values ('node1_to_be_committed_after'); +insert into t4 values ('node1_to_be_committed_after'); +insert into t4 values ('node1_to_be_committed_after'); +insert into t4 values ('node1_to_be_committed_after'); +insert into t4 values ('node1_to_be_committed_after'); +insert into t4 values ('node1_to_be_committed_after'); +insert into t3 values ('node1_to_be_committed_after'); +insert into t3 values ('node1_to_be_committed_after'); +insert into t3 values ('node1_to_be_committed_after'); +insert into t3 values ('node1_to_be_committed_after'); +insert into t3 values ('node1_to_be_committed_after'); +insert into t2 values ('node1_to_be_committed_after'); +insert into t2 values ('node1_to_be_committed_after'); +insert into t2 values ('node1_to_be_committed_after'); +insert into t2 values ('node1_to_be_committed_after'); +insert into t2 values ('node1_to_be_committed_after'); +insert into t1 values ('node1_to_be_committed_after'); +insert into t1 values ('node1_to_be_committed_after'); +insert into t1 values ('node1_to_be_committed_after'); +insert into t1 values ('node1_to_be_committed_after'); +insert into t1 values ('node1_to_be_committed_after'); +connect node_1a_galera_st_clean_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +insert into t9 values ('node1_to_be_rollbacked_after'); +insert into t9 values ('node1_to_be_rollbacked_after'); +insert into t9 values ('node1_to_be_rollbacked_after'); +insert into t9 values ('node1_to_be_rollbacked_after'); +insert into t9 values ('node1_to_be_rollbacked_after'); +insert into t8 values ('node1_to_be_rollbacked_after'); +insert into t8 values ('node1_to_be_rollbacked_after'); +insert into t8 values ('node1_to_be_rollbacked_after'); +insert into t8 values ('node1_to_be_rollbacked_after'); +insert into t8 values ('node1_to_be_rollbacked_after'); +insert into t7 values ('node1_to_be_rollbacked_after'); +insert into t7 values ('node1_to_be_rollbacked_after'); +insert into t7 values ('node1_to_be_rollbacked_after'); +insert into t7 values ('node1_to_be_rollbacked_after'); +insert into t7 values ('node1_to_be_rollbacked_after'); +insert into t6 values ('node1_to_be_rollbacked_after'); +insert into t6 values ('node1_to_be_rollbacked_after'); +insert into t6 values ('node1_to_be_rollbacked_after'); +insert into t6 values ('node1_to_be_rollbacked_after'); +insert into t6 values ('node1_to_be_rollbacked_after'); +insert into t5 values ('node1_to_be_rollbacked_after'); +insert into t5 values ('node1_to_be_rollbacked_after'); +insert into t5 values ('node1_to_be_rollbacked_after'); +insert into t5 values ('node1_to_be_rollbacked_after'); +insert into t5 values ('node1_to_be_rollbacked_after'); +insert into t4 values ('node1_to_be_rollbacked_after'); +insert into t4 values ('node1_to_be_rollbacked_after'); +insert into t4 values ('node1_to_be_rollbacked_after'); +insert into t4 values ('node1_to_be_rollbacked_after'); +insert into t4 values ('node1_to_be_rollbacked_after'); +insert into t3 values ('node1_to_be_rollbacked_after'); +insert into t3 values ('node1_to_be_rollbacked_after'); +insert into t3 values ('node1_to_be_rollbacked_after'); +insert into t3 values ('node1_to_be_rollbacked_after'); +insert into t3 values ('node1_to_be_rollbacked_after'); +insert into t2 values ('node1_to_be_rollbacked_after'); +insert into t2 values ('node1_to_be_rollbacked_after'); +insert into t2 values ('node1_to_be_rollbacked_after'); +insert into t2 values ('node1_to_be_rollbacked_after'); +insert into t2 values ('node1_to_be_rollbacked_after'); +insert into t1 values ('node1_to_be_rollbacked_after'); +insert into t1 values ('node1_to_be_rollbacked_after'); +insert into t1 values ('node1_to_be_rollbacked_after'); +insert into t1 values ('node1_to_be_rollbacked_after'); +insert into t1 values ('node1_to_be_rollbacked_after'); +connection node_2; +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +COMMIT; +connection node_1; +insert into t9 values ('node1_to_be_committed_after'); +insert into t9 values ('node1_to_be_committed_after'); +insert into t9 values ('node1_to_be_committed_after'); +insert into t9 values ('node1_to_be_committed_after'); +insert into t9 values ('node1_to_be_committed_after'); +insert into t8 values ('node1_to_be_committed_after'); +insert into t8 values ('node1_to_be_committed_after'); +insert into t8 values ('node1_to_be_committed_after'); +insert into t8 values ('node1_to_be_committed_after'); +insert into t8 values ('node1_to_be_committed_after'); +insert into t7 values ('node1_to_be_committed_after'); +insert into t7 values ('node1_to_be_committed_after'); +insert into t7 values ('node1_to_be_committed_after'); +insert into t7 values ('node1_to_be_committed_after'); +insert into t7 values ('node1_to_be_committed_after'); +insert into t6 values ('node1_to_be_committed_after'); +insert into t6 values ('node1_to_be_committed_after'); +insert into t6 values ('node1_to_be_committed_after'); +insert into t6 values ('node1_to_be_committed_after'); +insert into t6 values ('node1_to_be_committed_after'); +insert into t5 values ('node1_to_be_committed_after'); +insert into t5 values ('node1_to_be_committed_after'); +insert into t5 values ('node1_to_be_committed_after'); +insert into t5 values ('node1_to_be_committed_after'); +insert into t5 values ('node1_to_be_committed_after'); +insert into t4 values ('node1_to_be_committed_after'); +insert into t4 values ('node1_to_be_committed_after'); +insert into t4 values ('node1_to_be_committed_after'); +insert into t4 values ('node1_to_be_committed_after'); +insert into t4 values ('node1_to_be_committed_after'); +insert into t3 values ('node1_to_be_committed_after'); +insert into t3 values ('node1_to_be_committed_after'); +insert into t3 values ('node1_to_be_committed_after'); +insert into t3 values ('node1_to_be_committed_after'); +insert into t3 values ('node1_to_be_committed_after'); +insert into t2 values ('node1_to_be_committed_after'); +insert into t2 values ('node1_to_be_committed_after'); +insert into t2 values ('node1_to_be_committed_after'); +insert into t2 values ('node1_to_be_committed_after'); +insert into t2 values ('node1_to_be_committed_after'); +insert into t1 values ('node1_to_be_committed_after'); +insert into t1 values ('node1_to_be_committed_after'); +insert into t1 values ('node1_to_be_committed_after'); +insert into t1 values ('node1_to_be_committed_after'); +insert into t1 values ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +insert into t9 values ('node1_committed_after'); +insert into t9 values ('node1_committed_after'); +insert into t9 values ('node1_committed_after'); +insert into t9 values ('node1_committed_after'); +insert into t9 values ('node1_committed_after'); +insert into t8 values ('node1_committed_after'); +insert into t8 values ('node1_committed_after'); +insert into t8 values ('node1_committed_after'); +insert into t8 values ('node1_committed_after'); +insert into t8 values ('node1_committed_after'); +insert into t7 values ('node1_committed_after'); +insert into t7 values ('node1_committed_after'); +insert into t7 values ('node1_committed_after'); +insert into t7 values ('node1_committed_after'); +insert into t7 values ('node1_committed_after'); +insert into t6 values ('node1_committed_after'); +insert into t6 values ('node1_committed_after'); +insert into t6 values ('node1_committed_after'); +insert into t6 values ('node1_committed_after'); +insert into t6 values ('node1_committed_after'); +insert into t5 values ('node1_committed_after'); +insert into t5 values ('node1_committed_after'); +insert into t5 values ('node1_committed_after'); +insert into t5 values ('node1_committed_after'); +insert into t5 values ('node1_committed_after'); +insert into t4 values ('node1_committed_after'); +insert into t4 values ('node1_committed_after'); +insert into t4 values ('node1_committed_after'); +insert into t4 values ('node1_committed_after'); +insert into t4 values ('node1_committed_after'); +insert into t3 values ('node1_committed_after'); +insert into t3 values ('node1_committed_after'); +insert into t3 values ('node1_committed_after'); +insert into t3 values ('node1_committed_after'); +insert into t3 values ('node1_committed_after'); +insert into t2 values ('node1_committed_after'); +insert into t2 values ('node1_committed_after'); +insert into t2 values ('node1_committed_after'); +insert into t2 values ('node1_committed_after'); +insert into t2 values ('node1_committed_after'); +insert into t1 values ('node1_committed_after'); +insert into t1 values ('node1_committed_after'); +insert into t1 values ('node1_committed_after'); +insert into t1 values ('node1_committed_after'); +insert into t1 values ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_clean_slave; +ROLLBACK; +SELECT COUNT(*) FROM t1; +COUNT(*) +30 +SELECT COUNT(*) FROM t2; +COUNT(*) +30 +SELECT COUNT(*) FROM t3; +COUNT(*) +30 +SELECT COUNT(*) FROM t4; +COUNT(*) +30 +SELECT COUNT(*) FROM t5; +COUNT(*) +30 +SELECT COUNT(*) FROM t6; +COUNT(*) +30 +SELECT COUNT(*) FROM t7; +COUNT(*) +30 +SELECT COUNT(*) FROM t8; +COUNT(*) +30 +SELECT COUNT(*) FROM t9; +COUNT(*) +30 +SELECT * FROM t1; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t2; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t3; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t4; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t5; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t6; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t7; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t8; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t9; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) FROM t1; +COUNT(*) +30 +SELECT COUNT(*) FROM t2; +COUNT(*) +30 +SELECT COUNT(*) FROM t3; +COUNT(*) +30 +SELECT COUNT(*) FROM t4; +COUNT(*) +30 +SELECT COUNT(*) FROM t5; +COUNT(*) +30 +SELECT COUNT(*) FROM t6; +COUNT(*) +30 +SELECT COUNT(*) FROM t7; +COUNT(*) +30 +SELECT COUNT(*) FROM t8; +COUNT(*) +30 +SELECT COUNT(*) FROM t9; +COUNT(*) +30 +SELECT * FROM t1; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t2; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t3; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t4; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t5; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t6; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t7; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t8; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +SELECT * FROM t9; +f1 +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node1_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node2_committed_before +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_committed_during +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_to_be_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +node1_committed_after +COMMIT; +DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8,t9; +COMMIT; +SET AUTOCOMMIT=ON; +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key,debug.rdiff b/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key,debug.rdiff new file mode 100644 index 00000000000..4a7db96dc22 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key,debug.rdiff @@ -0,0 +1,106 @@ +--- r/galera_sst_mysqldump_with_key.result 2018-11-19 09:56:30.081976558 +0200 ++++ r/galera_sst_mysqldump_with_key.reject 2018-11-19 10:47:41.609299365 +0200 +@@ -183,6 +183,103 @@ + DROP TABLE t1; + COMMIT; + SET AUTOCOMMIT=ON; ++Performing State Transfer on a server that has been killed and restarted ++while a DDL was in progress on it ++CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++START TRANSACTION; ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++COMMIT; ++SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; ++ALTER TABLE t1 ADD COLUMN f2 INTEGER; ++SET wsrep_sync_wait = 0; ++Killing server ... ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++COMMIT; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++Performing --wsrep-recover ... ++Starting server ... ++Using --wsrep-start-position when starting mysqld ... ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++COMMIT; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++COMMIT; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++COMMIT; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++ROLLBACK; ++SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; ++COUNT(*) = 2 ++1 ++SELECT COUNT(*) = 35 FROM t1; ++COUNT(*) = 35 ++1 ++SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; ++COUNT(*) = 0 ++1 ++COMMIT; ++SET AUTOCOMMIT=ON; ++SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; ++COUNT(*) = 2 ++1 ++SELECT COUNT(*) = 35 FROM t1; ++COUNT(*) = 35 ++1 ++SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; ++COUNT(*) = 0 ++1 ++DROP TABLE t1; ++COMMIT; ++SET AUTOCOMMIT=ON; ++SET GLOBAL debug_dbug = $debug_orig; + CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); + DROP USER sst; + CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); diff --git a/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key.result b/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key.result index 02dde169911..3de446fec32 100644 --- a/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key.result +++ b/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key.result @@ -204,114 +204,17 @@ COUNT(*) = 0 DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; -Performing State Transfer on a server that has been killed and restarted -while a DDL was in progress on it connection node_1; -CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; -SET AUTOCOMMIT=OFF; -START TRANSACTION; -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); connection node_2; -START TRANSACTION; -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -COMMIT; -SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; connection node_1; -ALTER TABLE t1 ADD COLUMN f2 INTEGER; connection node_2; -SET wsrep_sync_wait = 0; -Killing server ... connection node_1; -SET AUTOCOMMIT=OFF; -START TRANSACTION; -INSERT INTO t1 (f1) VALUES ('node1_committed_during'); -INSERT INTO t1 (f1) VALUES ('node1_committed_during'); -INSERT INTO t1 (f1) VALUES ('node1_committed_during'); -INSERT INTO t1 (f1) VALUES ('node1_committed_during'); -INSERT INTO t1 (f1) VALUES ('node1_committed_during'); -COMMIT; -START TRANSACTION; -INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; -SET AUTOCOMMIT=OFF; -START TRANSACTION; -INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); connection node_2; -Performing --wsrep-recover ... connection node_2; -Starting server ... -Using --wsrep-start-position when starting mysqld ... -SET AUTOCOMMIT=OFF; -START TRANSACTION; -INSERT INTO t1 (f1) VALUES ('node2_committed_after'); -INSERT INTO t1 (f1) VALUES ('node2_committed_after'); -INSERT INTO t1 (f1) VALUES ('node2_committed_after'); -INSERT INTO t1 (f1) VALUES ('node2_committed_after'); -INSERT INTO t1 (f1) VALUES ('node2_committed_after'); -COMMIT; connection node_1; -INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -COMMIT; -SET AUTOCOMMIT=OFF; -START TRANSACTION; -INSERT INTO t1 (f1) VALUES ('node1_committed_after'); -INSERT INTO t1 (f1) VALUES ('node1_committed_after'); -INSERT INTO t1 (f1) VALUES ('node1_committed_after'); -INSERT INTO t1 (f1) VALUES ('node1_committed_after'); -INSERT INTO t1 (f1) VALUES ('node1_committed_after'); -COMMIT; connection node_1a_galera_st_kill_slave_ddl; -INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -ROLLBACK; -SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; -COUNT(*) = 2 -1 -SELECT COUNT(*) = 35 FROM t1; -COUNT(*) = 35 -1 -SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; -COUNT(*) = 0 -1 -COMMIT; -SET AUTOCOMMIT=ON; connection node_1; -SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; -COUNT(*) = 2 -1 -SELECT COUNT(*) = 35 FROM t1; -COUNT(*) = 35 -1 -SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; -COUNT(*) = 0 -1 -DROP TABLE t1; -COMMIT; -SET AUTOCOMMIT=ON; -SET GLOBAL debug_dbug = $debug_orig; connection node_1; CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); DROP USER sst; diff --git a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_data_dir,debug.rdiff b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_data_dir,debug.rdiff new file mode 100644 index 00000000000..ac232020037 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_data_dir,debug.rdiff @@ -0,0 +1,103 @@ +--- r/galera_sst_xtrabackup-v2_data_dir.result 2018-11-19 12:27:24.795221479 +0200 ++++ r/galera_sst_xtrabackup-v2_data_dir.reject 2018-11-19 19:15:38.774008404 +0200 +@@ -260,3 +260,100 @@ + DROP TABLE t1; + COMMIT; + SET AUTOCOMMIT=ON; ++Performing State Transfer on a server that has been killed and restarted ++while a DDL was in progress on it ++CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES ('node1_committed_before'); ++START TRANSACTION; ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES ('node2_committed_before'); ++COMMIT; ++SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; ++ALTER TABLE t1 ADD COLUMN f2 INTEGER; ++SET wsrep_sync_wait = 0; ++Killing server ... ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++COMMIT; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++Performing --wsrep-recover ... ++Starting server ... ++Using --wsrep-start-position when starting mysqld ... ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++COMMIT; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++COMMIT; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++COMMIT; ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++ROLLBACK; ++SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; ++COUNT(*) = 2 ++1 ++SELECT COUNT(*) = 35 FROM t1; ++COUNT(*) = 35 ++1 ++SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; ++COUNT(*) = 0 ++1 ++COMMIT; ++SET AUTOCOMMIT=ON; ++SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; ++COUNT(*) = 2 ++1 ++SELECT COUNT(*) = 35 FROM t1; ++COUNT(*) = 35 ++1 ++SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; ++COUNT(*) = 0 ++1 ++DROP TABLE t1; ++COMMIT; ++SET AUTOCOMMIT=ON; ++SET GLOBAL debug_dbug = $debug_orig; diff --git a/mysql-test/suite/galera/r/galera_var_reject_queries.result b/mysql-test/suite/galera/r/galera_var_reject_queries.result index 98380238fcb..caf98566595 100644 --- a/mysql-test/suite/galera/r/galera_var_reject_queries.result +++ b/mysql-test/suite/galera/r/galera_var_reject_queries.result @@ -7,7 +7,6 @@ SET GLOBAL wsrep_reject_queries = ALL; SELECT * FROM t1; ERROR 08S01: WSREP has not yet prepared node for application use SET GLOBAL wsrep_reject_queries = ALL_KILL; -ERROR HY000: Lost connection to MySQL server during query connection node_1a; SELECT * FROM t1; Got one of the listed errors diff --git a/mysql-test/suite/galera/r/partition.result b/mysql-test/suite/galera/r/partition.result index 3835de514aa..bdf6df25589 100644 --- a/mysql-test/suite/galera/r/partition.result +++ b/mysql-test/suite/galera/r/partition.result @@ -119,9 +119,9 @@ SET GLOBAL wsrep_load_data_splitting = ON; CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; connection node_2; -SELECT COUNT(*) = 20002 FROM t1; -COUNT(*) = 20002 -1 +SELECT COUNT(*) FROM t1; +COUNT(*) +20002 wsrep_last_committed_diff 1 DROP TABLE t1; @@ -131,9 +131,9 @@ SET GLOBAL wsrep_load_data_splitting = ON; CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; connection node_2; -SELECT COUNT(*) = 101 FROM t1; -COUNT(*) = 101 -1 +SELECT COUNT(*) FROM t1; +COUNT(*) +101 wsrep_last_committed_diff 1 DROP TABLE t1; @@ -144,9 +144,9 @@ SET GLOBAL wsrep_load_data_splitting = OFF; CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; connection node_2; -SELECT COUNT(*) = 20002 FROM t1; -COUNT(*) = 20002 -1 +SELECT COUNT(*) FROM t1; +COUNT(*) +20002 wsrep_last_committed_diff 1 DROP TABLE t1; diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 233aa020a94..1aabc697db1 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -98,10 +98,8 @@ if (which(socat)) { sub skip_combinations { my %skip = (); - $skip{'include/have_xtrabackup.inc'} = 'Need innobackupex' - unless which(innobackupex); - $skip{'include/have_xtrabackup.inc'} = 'Need socat or nc' - unless $ENV{MTR_GALERA_TFMT}; + $skip{'include/have_filekeymanagement.inc'} = 'needs file_key_management plugin' + unless $ENV{FILE_KEY_MANAGEMENT_SO}; $skip{'include/have_mariabackup.inc'} = 'Need mariabackup' unless which(mariabackup); $skip{'include/have_mariabackup.inc'} = 'Need ss' diff --git a/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.cnf b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.cnf new file mode 100644 index 00000000000..7e557717744 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.cnf @@ -0,0 +1,12 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=mariabackup +wsrep_sst_auth="root:" + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' + diff --git a/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test new file mode 100644 index 00000000000..731059dc584 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test @@ -0,0 +1,96 @@ +# +# Test that autoincrement works correctly while the cluster membership +# is changing and SST takes place. +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_mariabackup.inc + +--connection node_1 +--let $connection_id = `SELECT CONNECTION_ID()` + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; + +# Issue an endless stream of autoincrement inserts + +DELIMITER |; +CREATE PROCEDURE p1 () +BEGIN + DECLARE x INT DEFAULT 1; + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; + + WHILE 1 DO + INSERT INTO t1 VALUES (DEFAULT); + COMMIT; + END WHILE; +END| +DELIMITER ;| + +--send CALL p1(); +--sleep 2 + +--connection node_2 +--send CALL p1(); +--sleep 2 + +# Kill and restart node #2 + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +--source include/kill_galera.inc + +--sleep 10 +--source include/start_mysqld.inc +--sleep 25 +--source include/wait_until_connected_again.inc + +INSERT INTO t1 VALUES (DEFAULT); + +# Terminate the stored procedure + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +--disable_query_log +--eval KILL CONNECTION $connection_id +--enable_query_log + +INSERT INTO t1 VALUES (DEFAULT); + +--connection node_1 +# CR_SERVER_LOST +--error 2013,2006 +--reap + +--connection node_2 +# CR_SERVER_LOST +--error 2013,2006 +--reap + +--sleep 10 + +# Confirm that the count is correct and that the cluster is intact + +--connection node_1a +--let $count = `SELECT COUNT(*) FROM t1` + +--connection node_2a +--disable_query_log +--eval SELECT COUNT(*) = $count AS count_equal FROM t1 +--enable_query_log + +CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member 0"); + +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +--connection node_1a +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +DROP PROCEDURE p1; +DROP TABLE t1; + +CALL mtr.add_suppression("gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"); +CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member 0"); diff --git a/mysql-test/suite/galera/t/galera_ist_mariabackup.cnf b/mysql-test/suite/galera/t/galera_ist_mariabackup.cnf new file mode 100644 index 00000000000..75dff78149d --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_mariabackup.cnf @@ -0,0 +1,12 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=mariabackup +wsrep_sst_auth=root: + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' + diff --git a/mysql-test/suite/galera/t/galera_ist_mariabackup.test b/mysql-test/suite/galera/t/galera_ist_mariabackup.test new file mode 100644 index 00000000000..6ef4f65ccd4 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_mariabackup.test @@ -0,0 +1,16 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_mariabackup.inc + +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + +--source suite/galera/include/galera_st_disconnect_slave.inc +--source suite/galera/include/galera_st_shutdown_slave.inc + +--source suite/galera/include/galera_st_kill_slave.inc +--source suite/galera/include/galera_st_kill_slave_ddl.inc + +--source include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.cnf b/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.cnf new file mode 100644 index 00000000000..1542376b2b8 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.cnf @@ -0,0 +1,14 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=mariabackup +wsrep_sst_auth=root: + +innodb_flush_log_at_trx_commit=0 + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' + diff --git a/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.test b/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.test new file mode 100644 index 00000000000..07838702deb --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.test @@ -0,0 +1,12 @@ +# +# This test performs server kill and IST while innodb_flush_logs_on_trx_commit = 0 +# This confirms that IST can properly catch up even in the face of relaxed single-node durability +# +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--source suite/galera/include/galera_st_kill_slave.inc +--source suite/galera/include/galera_st_kill_slave_ddl.inc diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key.cnf b/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key.cnf new file mode 100644 index 00000000000..5a989ea8177 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key.cnf @@ -0,0 +1,12 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=mariabackup +wsrep_sst_auth="root:" +wsrep_debug=ON + +[SST] +tkey=@ENV.MYSQL_TEST_DIR/std_data/galera-key.pem +tcert=@ENV.MYSQL_TEST_DIR/std_data/galera-cert.pem +encrypt=3 +transferfmt=@ENV.MTR_GALERA_TFMT diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key.test b/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key.test new file mode 100644 index 00000000000..4449ea43c43 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key.test @@ -0,0 +1,14 @@ +# +# This test checks that key and cert encryption options can be passed to mariabackup via the my.cnf file +# Initial SST happens via mariabackup, so there is not much to do in the body of the test +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_mariabackup.inc + +SELECT 1; + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_table_options.cnf b/mysql-test/suite/galera/t/galera_sst_mariabackup_table_options.cnf new file mode 100644 index 00000000000..336296e9bfe --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_table_options.cnf @@ -0,0 +1,16 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=mariabackup +wsrep_sst_auth="root:" +wsrep_debug=ON + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' + +[sst] +transferfmt=@ENV.MTR_GALERA_TFMT +streamfmt=xbstream diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_table_options.test b/mysql-test/suite/galera/t/galera_sst_mariabackup_table_options.test new file mode 100644 index 00000000000..9d4f50f66ee --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_table_options.test @@ -0,0 +1,229 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_filekeymanagement.inc +--source include/innodb_encrypt_tables.inc +--source include/innodb_page_size_small.inc +--source include/have_mariabackup.inc + +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + +--echo Performing State Transfer on a server that starts from a clean var directory +--echo This is accomplished by shutting down node #2 and removing its var directory before restarting it + +--connection node_1 +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +CREATE TABLE t2 (f1 CHAR(255)) ENGINE=InnoDB PAGE_COMPRESSED=1; +CREATE TABLE t3 (f1 CHAR(255)) ENGINE=InnoDB PAGE_COMPRESSED=1 ENCRYPTED=NO; +CREATE TABLE t4 (f1 CHAR(255)) ENGINE=InnoDB PAGE_COMPRESSED=1 ENCRYPTED=YES; +CREATE TABLE t5 (f1 CHAR(255)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +CREATE TABLE t6 (f1 CHAR(255)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED ENCRYPTED=NO; +CREATE TABLE t7 (f1 CHAR(255)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED ENCRYPTED=YES; +CREATE TABLE t8 (f1 CHAR(255)) ENGINE=InnoDB ENCRYPTED=NO; +CREATE TABLE t9 (f1 CHAR(255)) ENGINE=InnoDB ENCRYPTED=YES; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +let $tables = 9; +while ($tables) +{ + let $rows = 5; + while($rows) + { + eval insert into t$tables values ('node1_committed_before'); + dec $rows; + } + dec $tables; +} +COMMIT; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 5 FROM t7; +--source include/wait_condition.inc + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +let $tables = 9; +while ($tables) +{ + let $rows = 5; + while($rows) + { + eval insert into t$tables values ('node2_committed_before'); + dec $rows; + } + dec $tables; +} +COMMIT; + +--echo Shutting down server ... +--source include/shutdown_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--echo Cleaning var directory ... +--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/mtr +--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/performance_schema +--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/test +--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/mysql +--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +let $tables = 9; +while ($tables) +{ + let $rows = 5; + while($rows) + { + eval insert into t$tables values ('node1_committed_during'); + dec $rows; + } + dec $tables; +} +COMMIT; + +START TRANSACTION; +let $tables = 9; +while ($tables) +{ + let $rows = 5; + while($rows) + { + eval insert into t$tables values ('node1_to_be_committed_after'); + dec $rows; + } + dec $tables; +} + +--connect node_1a_galera_st_clean_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +let $tables = 9; +while ($tables) +{ + let $rows = 5; + while($rows) + { + eval insert into t$tables values ('node1_to_be_rollbacked_after'); + dec $rows; + } + dec $tables; +} + +--connection node_2 +--echo Starting server ... +--source include/start_mysqld.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +while ($tables) +{ + let $rows = 5; + while($rows) + { + eval insert into t$tables values ('node2_committed_after'); + dec $rows; + } + dec $tables; +} +COMMIT; + +--connection node_1 +let $tables = 9; +while ($tables) +{ + let $rows = 5; + while($rows) + { + eval insert into t$tables values ('node1_to_be_committed_after'); + dec $rows; + } + dec $tables; +} +COMMIT; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +let $tables = 9; +while ($tables) +{ + let $rows = 5; + while($rows) + { + eval insert into t$tables values ('node1_committed_after'); + dec $rows; + } + dec $tables; +} +COMMIT; + +--connection node_1a_galera_st_clean_slave +while ($tables) +{ + let $rows = 5; + while($rows) + { + eval insert into t$tables values ('node1_to_be_rollbacked_after'); + dec $rows; + } + dec $tables; +} +ROLLBACK; + +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM t2; +SELECT COUNT(*) FROM t3; +SELECT COUNT(*) FROM t4; +SELECT COUNT(*) FROM t5; +SELECT COUNT(*) FROM t6; +SELECT COUNT(*) FROM t7; +SELECT COUNT(*) FROM t8; +SELECT COUNT(*) FROM t9; +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; +SELECT * FROM t4; +SELECT * FROM t5; +SELECT * FROM t6; +SELECT * FROM t7; +SELECT * FROM t8; +SELECT * FROM t9; +COMMIT; +SET AUTOCOMMIT=ON; + +--connection node_1 +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM t2; +SELECT COUNT(*) FROM t3; +SELECT COUNT(*) FROM t4; +SELECT COUNT(*) FROM t5; +SELECT COUNT(*) FROM t6; +SELECT COUNT(*) FROM t7; +SELECT COUNT(*) FROM t8; +SELECT COUNT(*) FROM t9; +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; +SELECT * FROM t4; +SELECT * FROM t5; +SELECT * FROM t6; +SELECT * FROM t7; +SELECT * FROM t8; +SELECT * FROM t9; +COMMIT; + +DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8,t9; +COMMIT; +SET AUTOCOMMIT=ON; + +# Restore original auto_increment_offset values. +--source include/auto_increment_offset_restore.inc +--source include/galera_end.inc diff --git a/mysql-test/suite/galera/t/galera_var_reject_queries.test b/mysql-test/suite/galera/t/galera_var_reject_queries.test index 6859855c35f..8b80c04e3be 100644 --- a/mysql-test/suite/galera/t/galera_var_reject_queries.test +++ b/mysql-test/suite/galera/t/galera_var_reject_queries.test @@ -18,8 +18,11 @@ SET GLOBAL wsrep_reject_queries = ALL; --error ER_UNKNOWN_COM_ERROR SELECT * FROM t1; -# Lost connection ---error 2013 +# +# Original behavior was lost connection, +# but since 10.1, we allow controlling connection to remain alive +# +--error 0,2013 SET GLOBAL wsrep_reject_queries = ALL_KILL; --connection node_1a diff --git a/mysql-test/suite/galera/t/partition.test b/mysql-test/suite/galera/t/partition.test index bb5a02411c3..0159ef8f607 100644 --- a/mysql-test/suite/galera/t/partition.test +++ b/mysql-test/suite/galera/t/partition.test @@ -129,7 +129,10 @@ CREATE TABLE t1 (pk INT PRIMARY KEY) --let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` --connection node_2 -SELECT COUNT(*) = 20002 FROM t1; +--let $wait_condition = SELECT COUNT(*) = 20002 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) FROM t1; # LOAD-ing 20002 rows causes 3 commits to be registered --disable_query_log @@ -157,7 +160,10 @@ CREATE TABLE t1 (pk INT PRIMARY KEY) --let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` --connection node_2 -SELECT COUNT(*) = 101 FROM t1; +--let $wait_condition = SELECT COUNT(*) = 101 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) FROM t1; # LOAD-ing 101 rows causes 1 commit to be registered --disable_query_log @@ -186,7 +192,9 @@ CREATE TABLE t1 (pk INT PRIMARY KEY) --let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` --connection node_2 -SELECT COUNT(*) = 20002 FROM t1; +--let $wait_condition = SELECT COUNT(*) = 20002 FROM t1; +--source include/wait_condition.inc +SELECT COUNT(*) FROM t1; # LOAD-ing 20002 rows causes 1 commit to be registered --disable_query_log diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index a9b9b00b40c..e640baebf7d 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -1,3 +1,4 @@ galera_slave_options_do :MDEV-8798 galera_slave_options_ignore : MDEV-8798 - +galera_innobackupex_backup : xtrabackup is deprecated +galera_ipv6_xtrabackup-v2 : xtrabackup is deprecated diff --git a/mysql-test/suite/innodb/r/truncate.result b/mysql-test/suite/innodb/r/truncate.result index 3ade1e7f8de..f584ffadc05 100644 --- a/mysql-test/suite/innodb/r/truncate.result +++ b/mysql-test/suite/innodb/r/truncate.result @@ -6,3 +6,39 @@ connection default; TRUNCATE TABLE t; disconnect dml; DROP TABLE t; +# +# MDEV-17816 Crash in TRUNCATE TABLE when table creation fails +# +CREATE TABLE t1 (c VARCHAR(1024), KEY(c)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +INSERT INTO t1 SET c='character'; +ALTER TABLE t1 ROW_FORMAT=REDUNDANT; +TRUNCATE TABLE t1; +ERROR HY000: Index column size too large. The maximum column size is 767 bytes +SELECT * FROM t1; +c +character +DROP TABLE t1; +# +# MDEV-17831 TRUNCATE TABLE removes ROW_FORMAT=COMPRESSED +# +CREATE TABLE t1 (a SERIAL) ENGINE=InnoDB KEY_BLOCK_SIZE=4; +TRUNCATE TABLE t1; +SHOW TABLE STATUS; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary +t1 InnoDB # Compressed # # # # # # 1 # # NULL latin1_swedish_ci NULL key_block_size=4 0 N +DROP TABLE t1; +# +# MDEV-17859 Operating system errors in file operations +# after failed CREATE +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +call mtr.add_suppression("InnoDB: (Operating system )?[Ee]rror number"); +call mtr.add_suppression("InnoDB: Cannot create file '.*t1\\.ibd"); +FLUSH TABLES; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +ERROR HY000: Tablespace for table '`test`.`t1`' exists. Please DISCARD the tablespace before IMPORT +SELECT * FROM t1; +a +1 +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/truncate.test b/mysql-test/suite/innodb/t/truncate.test index cf71ca83c4c..5a80f7c49e3 100644 --- a/mysql-test/suite/innodb/t/truncate.test +++ b/mysql-test/suite/innodb/t/truncate.test @@ -15,3 +15,41 @@ TRUNCATE TABLE t; disconnect dml; DROP TABLE t; + +--echo # +--echo # MDEV-17816 Crash in TRUNCATE TABLE when table creation fails +--echo # +CREATE TABLE t1 (c VARCHAR(1024), KEY(c)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +INSERT INTO t1 SET c='character'; +# FIXME: MDEV-17833 ALTER TABLE is not enforcing prefix index size limit +ALTER TABLE t1 ROW_FORMAT=REDUNDANT; +--error ER_INDEX_COLUMN_TOO_LONG +TRUNCATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +--echo # +--echo # MDEV-17831 TRUNCATE TABLE removes ROW_FORMAT=COMPRESSED +--echo # +CREATE TABLE t1 (a SERIAL) ENGINE=InnoDB KEY_BLOCK_SIZE=4; +TRUNCATE TABLE t1; +--replace_column 3 # 5 # 6 # 7 # 8 # 9 # 10 # 12 # 13 # +SHOW TABLE STATUS; +DROP TABLE t1; + +--echo # +--echo # MDEV-17859 Operating system errors in file operations +--echo # after failed CREATE +--echo # +let $MYSQLD_DATADIR= `select @@datadir`; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +call mtr.add_suppression("InnoDB: (Operating system )?[Ee]rror number"); +call mtr.add_suppression("InnoDB: Cannot create file '.*t1\\.ibd"); +FLUSH TABLES; +--move_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/test/hidden.frm +--error ER_TABLESPACE_EXISTS +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +--move_file $MYSQLD_DATADIR/test/hidden.frm $MYSQLD_DATADIR/test/t1.frm +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/suite/rpl/r/rpl_temporal_round.result b/mysql-test/suite/rpl/r/rpl_temporal_round.result new file mode 100644 index 00000000000..df8cc431a74 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_temporal_round.result @@ -0,0 +1,50 @@ +include/master-slave.inc +[connection master] +SET sql_mode=TIME_ROUND_FRACTIONAL; +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE TABLE t1 (id SERIAL, a TIMESTAMP(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES ('2011-01-01 23:59:59.999999'); +CREATE TABLE t2 (id SERIAL, a DATETIME(4)); +INSERT INTO t2 (a) VALUES (now(6)); +INSERT INTO t2 (a) VALUES ('2011-01-01 23:59:59.999999'); +CREATE TABLE t3 (id SERIAL, a TIME(4)); +INSERT INTO t3 (a) VALUES (now(6)); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +INSERT INTO t3 (a) VALUES ('2011-01-01 23:59:59.999999'); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +SELECT * FROM t1; +id a +1 2011-01-01 00:00:00.0000 +2 2011-01-02 00:00:00.0000 +SELECT * FROM t2; +id a +1 2011-01-01 00:00:00.0000 +2 2011-01-02 00:00:00.0000 +SELECT * FROM t3; +id a +1 24:00:00.0000 +2 24:00:00.0000 +connection slave; +connection slave; +SET time_zone='+00:00'; +SELECT * FROM t1; +id a +1 2011-01-01 00:00:00.0000 +2 2011-01-02 00:00:00.0000 +SELECT * FROM t2; +id a +1 2011-01-01 00:00:00.0000 +2 2011-01-02 00:00:00.0000 +SELECT * FROM t3; +id a +1 24:00:00.0000 +2 24:00:00.0000 +connection master; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_temporal_round.test b/mysql-test/suite/rpl/t/rpl_temporal_round.test new file mode 100644 index 00000000000..c13c18bddb5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_round.test @@ -0,0 +1,35 @@ +--source include/master-slave.inc + +SET sql_mode=TIME_ROUND_FRACTIONAL; +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); + +CREATE TABLE t1 (id SERIAL, a TIMESTAMP(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES ('2011-01-01 23:59:59.999999'); + +CREATE TABLE t2 (id SERIAL, a DATETIME(4)); +INSERT INTO t2 (a) VALUES (now(6)); +INSERT INTO t2 (a) VALUES ('2011-01-01 23:59:59.999999'); + +CREATE TABLE t3 (id SERIAL, a TIME(4)); +INSERT INTO t3 (a) VALUES (now(6)); +INSERT INTO t3 (a) VALUES ('2011-01-01 23:59:59.999999'); + +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +sync_slave_with_master; +connection slave; +SET time_zone='+00:00'; +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +connection master; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/sys_vars/r/sql_mode_basic.result b/mysql-test/suite/sys_vars/r/sql_mode_basic.result index a200f620a7c..d911e80b780 100644 --- a/mysql-test/suite/sys_vars/r/sql_mode_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_mode_basic.result @@ -367,7 +367,15 @@ SELECT @@global.sql_mode; @@global.sql_mode REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT SET @@global.sql_mode = 17179869184; -ERROR 42000: Variable 'sql_mode' can't be set to the value of '17179869184' +SELECT @@global.sql_mode; +@@global.sql_mode +TIME_ROUND_FRACTIONAL +SET @@global.sql_mode = 34359738367; +SELECT @@global.sql_mode; +@@global.sql_mode +REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT,TIME_ROUND_FRACTIONAL +SET @@global.sql_mode = 34359738368; +ERROR 42000: Variable 'sql_mode' can't be set to the value of '34359738368' SET @@global.sql_mode = 0.4; ERROR 42000: Incorrect argument type to variable 'sql_mode' '#---------------------FN_DYNVARS_152_08----------------------#' diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 835145531b9..29e80c79e7c 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -3845,7 +3845,7 @@ VARIABLE_COMMENT Sets the sql mode NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT +ENUM_VALUE_LIST REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT,TIME_ROUND_FRACTIONAL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SQL_NOTES diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 26acbfad9c6..56f7a136983 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -4755,7 +4755,7 @@ VARIABLE_COMMENT Sets the sql mode NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT +ENUM_VALUE_LIST REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT,TIME_ROUND_FRACTIONAL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SQL_NOTES diff --git a/mysql-test/suite/sys_vars/t/sql_mode_basic.test b/mysql-test/suite/sys_vars/t/sql_mode_basic.test index b4841ecd3ff..68be8ba969b 100644 --- a/mysql-test/suite/sys_vars/t/sql_mode_basic.test +++ b/mysql-test/suite/sys_vars/t/sql_mode_basic.test @@ -310,8 +310,14 @@ SELECT @@global.sql_mode; SET @@global.sql_mode = 17179869183; SELECT @@global.sql_mode; ---Error ER_WRONG_VALUE_FOR_VAR SET @@global.sql_mode = 17179869184; +SELECT @@global.sql_mode; + +SET @@global.sql_mode = 34359738367; +SELECT @@global.sql_mode; + +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.sql_mode = 34359738368; # use of decimal values diff --git a/mysql-test/suite/versioning/r/sysvars.result b/mysql-test/suite/versioning/r/sysvars.result index b23742462d1..acc5d62e069 100644 --- a/mysql-test/suite/versioning/r/sysvars.result +++ b/mysql-test/suite/versioning/r/sysvars.result @@ -130,3 +130,14 @@ show status like "Feature_system_versioning"; Variable_name Value Feature_system_versioning 2 drop table t; +# +# MDEV-16991 Rounding vs truncation for TIME, DATETIME, TIMESTAMP +# +SET sql_mode=TIME_ROUND_FRACTIONAL; +SET @@global.system_versioning_asof= timestamp'2001-12-31 23:59:59.9999999'; +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +SELECT @@global.system_versioning_asof; +@@global.system_versioning_asof +2002-01-01 00:00:00.000000 +SET @@global.system_versioning_asof= DEFAULT; diff --git a/mysql-test/suite/versioning/t/sysvars.test b/mysql-test/suite/versioning/t/sysvars.test index 160af12fe02..52fab81b8e6 100644 --- a/mysql-test/suite/versioning/t/sysvars.test +++ b/mysql-test/suite/versioning/t/sysvars.test @@ -87,3 +87,13 @@ select * from t for system_time between '0-0-0' and current_timestamp(6); show status like "Feature_system_versioning"; drop table t; + + +--echo # +--echo # MDEV-16991 Rounding vs truncation for TIME, DATETIME, TIMESTAMP +--echo # + +SET sql_mode=TIME_ROUND_FRACTIONAL; +SET @@global.system_versioning_asof= timestamp'2001-12-31 23:59:59.9999999'; +SELECT @@global.system_versioning_asof; +SET @@global.system_versioning_asof= DEFAULT; diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index 0d59862f26f..6c61ebee425 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -80,7 +80,7 @@ CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsign CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=Aria transactional=1 CHARACTER SET utf8 comment='Leap seconds information for time zones'; -CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob NOT NULL, body longblob NOT NULL, definer char(141) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'IGNORE_BAD_TABLE_OPTIONS', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH', 'EMPTY_STRING_IS_NULL', 'SIMULTANEOUS_ASSIGNMENT') DEFAULT '' NOT NULL, comment text collate utf8_bin NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, aggregate enum('NONE', 'GROUP') DEFAULT 'NONE' NOT NULL, PRIMARY KEY (db,name,type)) engine=Aria transactional=1 character set utf8 comment='Stored Procedures'; +CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob NOT NULL, body longblob NOT NULL, definer char(141) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'IGNORE_BAD_TABLE_OPTIONS', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH', 'EMPTY_STRING_IS_NULL', 'SIMULTANEOUS_ASSIGNMENT', 'TIME_ROUND_FRACTIONAL') DEFAULT '' NOT NULL, comment text collate utf8_bin NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, aggregate enum('NONE', 'GROUP') DEFAULT 'NONE' NOT NULL, PRIMARY KEY (db,name,type)) engine=Aria transactional=1 character set utf8 comment='Stored Procedures'; CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NOT NULL, Grantor char(141) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; @@ -101,7 +101,7 @@ PREPARE stmt FROM @str; EXECUTE stmt; DROP PREPARE stmt; -CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) engine=Aria transactional=1 DEFAULT CHARSET=utf8 COMMENT 'Events'; +CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) engine=Aria transactional=1 DEFAULT CHARSET=utf8 COMMENT 'Events'; SET @create_innodb_table_stats="CREATE TABLE IF NOT EXISTS innodb_table_stats ( database_name VARCHAR(64) NOT NULL, diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index fd68367b42a..eb620322cd0 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -417,7 +417,8 @@ ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL, 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH', 'EMPTY_STRING_IS_NULL', - 'SIMULTANEOUS_ASSIGNMENT' + 'SIMULTANEOUS_ASSIGNMENT', + 'TIME_ROUND_FRACTIONAL' ) DEFAULT '' NOT NULL, DEFAULT CHARACTER SET utf8; @@ -553,7 +554,8 @@ ALTER TABLE event MODIFY sql_mode 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH', 'EMPTY_STRING_IS_NULL', - 'SIMULTANEOUS_ASSIGNMENT' + 'SIMULTANEOUS_ASSIGNMENT', + 'TIME_ROUND_FRACTIONAL' ) DEFAULT '' NOT NULL AFTER on_completion; ALTER TABLE event MODIFY name char(64) CHARACTER SET utf8 NOT NULL default ''; diff --git a/sql-common/my_time.c b/sql-common/my_time.c index d16970c0a5f..2aa657ca14e 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -256,6 +256,14 @@ static void get_microseconds(ulong *val, MYSQL_TIME_STATUS *status, *val= (ulong) (tmp * log_10_int[6 - (*str - start)]); else *val= tmp; + if (str[0] < end && my_isdigit(&my_charset_latin1, str[0][0])) + { + /* + We don't need the exact nanoseconds value. + Knowing the first digit is enough for rounding. + */ + status->nanoseconds= 100 * (uint)(str[0][0] - '0'); + } if (skip_digits(str, end)) status->warnings|= MYSQL_TIME_NOTE_TRUNCATED; } diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index a6803982171..db056a9f08e 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -479,14 +479,24 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) uint not_used; if (!starts_null) { - table->field[ET_FIELD_STARTS]->get_date(&time, TIME_NO_ZERO_DATE); + /* + The expected data type for these columns in mysql.events: + starts, ends, execute_at, last_executed + is DATETIME. No nanosecond truncation should normally be needed, + unless the DBA changes them, e.g. to VARCHAR, DECIMAL, etc. + For this unexpected case let's use the default round mode, + according to the current session settings. + */ + table->field[ET_FIELD_STARTS]->get_date(&time, TIME_NO_ZERO_DATE | + thd->temporal_round_mode()); starts= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used); } ends_null= table->field[ET_FIELD_ENDS]->is_null(); if (!ends_null) { - table->field[ET_FIELD_ENDS]->get_date(&time, TIME_NO_ZERO_DATE); + table->field[ET_FIELD_ENDS]->get_date(&time, TIME_NO_ZERO_DATE | + thd->temporal_round_mode()); ends= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used); } @@ -502,8 +512,8 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) DBUG_ASSERT(!(starts_null && ends_null && !expression && execute_at_null)); if (!expression && !execute_at_null) { - if (table->field[ET_FIELD_EXECUTE_AT]->get_date(&time, - TIME_NO_ZERO_DATE)) + if (table->field[ET_FIELD_EXECUTE_AT]->get_date(&time, TIME_NO_ZERO_DATE | + thd->temporal_round_mode())) DBUG_RETURN(TRUE); execute_at= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used); } @@ -535,8 +545,8 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) if (!table->field[ET_FIELD_LAST_EXECUTED]->is_null()) { - table->field[ET_FIELD_LAST_EXECUTED]->get_date(&time, - TIME_NO_ZERO_DATE); + table->field[ET_FIELD_LAST_EXECUTED]->get_date(&time, TIME_NO_ZERO_DATE | + thd->temporal_round_mode()); last_executed= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used); } diff --git a/sql/event_parse_data.cc b/sql/event_parse_data.cc index bfda8438885..00d625879de 100644 --- a/sql/event_parse_data.cc +++ b/sql/event_parse_data.cc @@ -216,7 +216,13 @@ Event_parse_data::init_execute_at(THD *thd) (starts_null && ends_null))); DBUG_ASSERT(starts_null && ends_null); - if (item_execute_at->get_date(thd, <ime, TIME_NO_ZERO_DATE)) + /* + The expected data type is DATETIME. No nanoseconds truncation should + normally be needed. Using the default rounding mode. + See more comments in event_data_object.cc. + */ + if (item_execute_at->get_date(thd, <ime, TIME_NO_ZERO_DATE | + thd->temporal_round_mode())) goto wrong_value; ltime_utc= TIME_to_timestamp(thd,<ime,¬_used); @@ -378,7 +384,8 @@ Event_parse_data::init_starts(THD *thd) if (item_starts->fix_fields(thd, &item_starts)) goto wrong_value; - if (item_starts->get_date(thd, <ime, TIME_NO_ZERO_DATE)) + if (item_starts->get_date(thd, <ime, TIME_NO_ZERO_DATE | + thd->temporal_round_mode())) goto wrong_value; ltime_utc= TIME_to_timestamp(thd, <ime, ¬_used); @@ -433,7 +440,8 @@ Event_parse_data::init_ends(THD *thd) goto error_bad_params; DBUG_PRINT("info", ("convert to TIME")); - if (item_ends->get_date(thd, <ime, TIME_NO_ZERO_DATE)) + if (item_ends->get_date(thd, <ime, TIME_NO_ZERO_DATE | + thd->temporal_round_mode())) goto error_bad_params; ltime_utc= TIME_to_timestamp(thd, <ime, ¬_used); diff --git a/sql/field.cc b/sql/field.cc index cc95a8c8e84..21d4aea6fb4 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5084,10 +5084,11 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, const Datetime *dt, } -date_mode_t Field_timestamp::sql_mode_for_timestamp(THD *thd) const +date_conv_mode_t Timestamp::sql_mode_for_timestamp(THD *thd) { // We don't want to store invalid or fuzzy datetime values in TIMESTAMP - return date_mode_t((thd->variables.sql_mode & MODE_NO_ZERO_DATE) | MODE_NO_ZERO_IN_DATE); + return date_conv_mode_t((thd->variables.sql_mode & MODE_NO_ZERO_DATE) | + MODE_NO_ZERO_IN_DATE); } @@ -5096,7 +5097,7 @@ int Field_timestamp::store_time_dec(const MYSQL_TIME *ltime, uint dec) int warn; ErrConvTime str(ltime); THD *thd= get_thd(); - Datetime dt(thd, &warn, ltime, sql_mode_for_timestamp(thd), decimals()); + Datetime dt(thd, &warn, ltime, Timestamp::DatetimeOptions(thd), decimals()); return store_TIME_with_warning(thd, &dt, &str, warn); } @@ -5106,7 +5107,7 @@ int Field_timestamp::store(const char *from,size_t len,CHARSET_INFO *cs) ErrConvString str(from, len, cs); THD *thd= get_thd(); MYSQL_TIME_STATUS st; - Datetime dt(&st, from, len, cs, sql_mode_for_timestamp(thd), decimals()); + Datetime dt(thd, &st, from, len, cs, Timestamp::DatetimeOptions(thd), decimals()); return store_TIME_with_warning(thd, &dt, &str, st.warnings); } @@ -5116,7 +5117,7 @@ int Field_timestamp::store(double nr) int error; ErrConvDouble str(nr); THD *thd= get_thd(); - Datetime dt(&error, nr, sql_mode_for_timestamp(thd), decimals()); + Datetime dt(thd, &error, nr, Timestamp::DatetimeOptions(thd), decimals()); return store_TIME_with_warning(thd, &dt, &str, error); } @@ -5127,14 +5128,29 @@ int Field_timestamp::store(longlong nr, bool unsigned_val) Longlong_hybrid tmp(nr, unsigned_val); ErrConvInteger str(tmp); THD *thd= get_thd(); - Datetime dt(&error, tmp, sql_mode_for_timestamp(thd)); + Datetime dt(thd, &error, tmp, Timestamp::DatetimeOptions(thd)); return store_TIME_with_warning(thd, &dt, &str, error); } int Field_timestamp::store_timestamp(my_time_t ts, ulong sec_part) { - store_TIMESTAMP(Timestamp(ts, sec_part).trunc(decimals())); + int warn= 0; + time_round_mode_t mode= Datetime::default_round_mode(get_thd()); + store_TIMESTAMP(Timestamp(ts, sec_part).round(decimals(), mode, &warn)); + if (warn) + { + /* + We're here if rounding would overflow outside of the supported TIMESTAMP + range, so truncation happened instead: + CREATE TABLE t1 (a TIMESTAMP(6)); + INSERT INTO t1 VALUES ('maximum-possible-timestamp.999999'); + ALTER TABLE t1 MODIFY a TIMESTAMP(5); + SELECT * FROM t1; --> 'maximum-possible-timestamp.99999' (5 digits) + Raise a warning, like DATETIME does for '9999-12-31 23:59:59.999999'. + */ + set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + } if (ts == 0 && sec_part == 0 && get_thd()->variables.sql_mode & (ulonglong) TIME_NO_ZERO_DATE) { @@ -5157,7 +5173,7 @@ double Field_timestamp::val_real(void) longlong Field_timestamp::val_int(void) { MYSQL_TIME ltime; - if (get_date(<ime, TIME_NO_ZERO_DATE)) + if (get_date(<ime, Datetime::Options(TIME_NO_ZERO_DATE, get_thd()))) return 0; return ltime.year * 10000000000LL + ltime.month * 100000000LL + @@ -5177,7 +5193,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr) to= (char*) val_buffer->ptr(); val_buffer->length(field_length); - if (get_date(<ime, TIME_NO_ZERO_DATE)) + if (get_date(<ime, Datetime::Options(TIME_NO_ZERO_DATE, get_thd()))) { /* Zero time is "000000" */ val_ptr->set(zero_timestamp, field_length, &my_charset_numeric); return val_ptr; @@ -5407,7 +5423,7 @@ my_time_t Field_timestamp_hires::get_timestamp(const uchar *pos, double Field_timestamp_with_dec::val_real(void) { MYSQL_TIME ltime; - if (get_date(<ime, TIME_NO_ZERO_DATE)) + if (get_date(<ime, Datetime::Options(TIME_NO_ZERO_DATE, get_thd()))) return 0; return ltime.year * 1e10 + ltime.month * 1e8 + @@ -5427,7 +5443,7 @@ int Field_timestamp::store_decimal(const my_decimal *d) int error; THD *thd= get_thd(); ErrConvDecimal str(d); - Datetime dt(&error, d, sql_mode_for_timestamp(thd), decimals()); + Datetime dt(thd, &error, d, Timestamp::DatetimeOptions(thd), decimals()); return store_TIME_with_warning(thd, &dt, &str, error); } @@ -5570,7 +5586,8 @@ int Field_datetime::store(const char *from, size_t len, CHARSET_INFO *cs) { MYSQL_TIME_STATUS st; ErrConvString str(from, len, cs); - Datetime dt(&st, from, len, cs, sql_mode_for_dates(get_thd()), decimals()); + THD *thd= get_thd(); + Datetime dt(thd, &st, from, len, cs, Datetime::Options(thd), decimals()); return store_TIME_with_warning(&dt, &str, st.warnings); } @@ -5578,7 +5595,8 @@ int Field_datetime::store(double nr) { int error; ErrConvDouble str(nr); - Datetime dt(&error, nr, sql_mode_for_dates(get_thd()), decimals()); + THD *thd= get_thd(); + Datetime dt(thd, &error, nr, Datetime::Options(thd), decimals()); return store_TIME_with_warning(&dt, &str, error); } @@ -5588,7 +5606,8 @@ int Field_datetime::store(longlong nr, bool unsigned_val) int error; Longlong_hybrid tmp(nr, unsigned_val); ErrConvInteger str(tmp); - Datetime dt(&error, tmp, sql_mode_for_dates(get_thd())); + THD *thd= get_thd(); + Datetime dt(thd, &error, tmp, Datetime::Options(thd)); return store_TIME_with_warning(&dt, &str, error); } @@ -5597,7 +5616,7 @@ int Field_datetime::store_time_dec(const MYSQL_TIME *ltime, uint dec) int error; ErrConvTime str(ltime); THD *thd= get_thd(); - Datetime dt(thd, &error, ltime, sql_mode_for_dates(thd), decimals()); + Datetime dt(thd, &error, ltime, Datetime::Options(thd), decimals()); return store_TIME_with_warning(&dt, &str, error); } @@ -5606,7 +5625,8 @@ int Field_datetime::store_decimal(const my_decimal *d) { int error; ErrConvDecimal str(d); - Datetime tm(&error, d, sql_mode_for_dates(get_thd()), decimals()); + THD *thd= get_thd(); + Datetime tm(thd, &error, d, Datetime::Options(thd), decimals()); return store_TIME_with_warning(&tm, &str, error); } @@ -5617,7 +5637,7 @@ Field_temporal_with_date::validate_value_in_record(THD *thd, { DBUG_ASSERT(!is_null_in_record(record)); MYSQL_TIME ltime; - return get_TIME(<ime, ptr_in_record(record), sql_mode_for_dates(thd)); + return get_TIME(<ime, ptr_in_record(record), Datetime::Options(thd)); } @@ -5657,7 +5677,8 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd, const_item->field_type() != MYSQL_TYPE_TIMESTAMP) || const_item->decimals != decimals()) { - Datetime dt(thd, const_item, date_mode_t(0)); + Datetime::Options opt(TIME_CONV_NONE, thd); + Datetime dt(thd, const_item, opt, decimals()); if (!dt.is_valid_datetime()) return NULL; /* @@ -5672,7 +5693,7 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd, case ANY_SUBST: if (!is_temporal_type_with_date(const_item->field_type())) { - Datetime dt(thd, const_item, Datetime::comparison_flags_for_get_date()); + Datetime dt(thd, const_item, Datetime::Options_cmp(thd)); if (!dt.is_valid_datetime()) return NULL; return new (thd->mem_root) @@ -5724,7 +5745,17 @@ int Field_time::store(const char *from,size_t len,CHARSET_INFO *cs) ErrConvString str(from, len, cs); MYSQL_TIME_STATUS st; THD *thd= get_thd(); - Time tm(thd, &st, from, len, cs, sql_mode_for_dates(thd), decimals()); + /* + Unlike number-to-time conversion, we need to additionally pass + MODE_NO_ZERO_DATE here (if it presents in the current sql_mode): + SET sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE'; + INSERT INTO t1 VALUES ('0000-00-00 00:00:00'); -- error + INSERT INTO t1 VALUES (0); -- ok + In the first INSERT we have a zero date. + In the second INSERT we don't have a zero date (it is just a zero time). + */ + Time::Options opt(sql_mode_for_dates(thd), thd); + Time tm(thd, &st, from, len, cs, opt, decimals()); return store_TIME_with_warning(&tm, &str, st.warnings); } @@ -5733,7 +5764,7 @@ int Field_time::store_time_dec(const MYSQL_TIME *ltime, uint dec) { ErrConvTime str(ltime); int warn; - Time tm(&warn, ltime, curdays, decimals()); + Time tm(&warn, ltime, curdays, Time::Options(get_thd()), decimals()); return store_TIME_with_warning(&tm, &str, warn); } @@ -5742,7 +5773,7 @@ int Field_time::store(double nr) { ErrConvDouble str(nr); int was_cut; - Time tm(get_thd(), &was_cut, nr, Time::Options(), decimals()); + Time tm(get_thd(), &was_cut, nr, Time::Options(get_thd()), decimals()); return store_TIME_with_warning(&tm, &str, was_cut); } @@ -5752,8 +5783,14 @@ int Field_time::store(longlong nr, bool unsigned_val) Longlong_hybrid tmp(nr, unsigned_val); ErrConvInteger str(tmp); int was_cut; - // Need fractional digit truncation if nr overflows to '838:59:59.999999' - Time tm(get_thd(), &was_cut, tmp, Time::Options(), decimals()); + THD *thd= get_thd(); + /* + Need fractional digit truncation if nr overflows to '838:59:59.999999'. + The constructor used below will always truncate (never round). + We don't need to care to overwrite the default session rounding mode + from HALF_UP to TRUNCATE. + */ + Time tm(thd, &was_cut, tmp, Time::Options(thd), decimals()); return store_TIME_with_warning(&tm, &str, was_cut); } @@ -5805,7 +5842,7 @@ String *Field_time::val_str(String *str, { ASSERT_COLUMN_MARKED_FOR_READ; MYSQL_TIME ltime; - get_date(<ime, TIME_TIME_ONLY); + get_date(<ime, Datetime::Options(TIME_TIME_ONLY, get_thd())); str->alloc(field_length + 1); str->length(my_time_to_str(<ime, const_cast<char*>(str->ptr()), decimals())); str->set_charset(&my_charset_numeric); @@ -5815,7 +5852,8 @@ String *Field_time::val_str(String *str, bool Field_time::check_zero_in_date_with_warn(date_mode_t fuzzydate) { - if (!(fuzzydate & TIME_TIME_ONLY) && (fuzzydate & TIME_NO_ZERO_IN_DATE)) + date_conv_mode_t tmp= date_conv_mode_t(fuzzydate); + if (!(tmp & TIME_TIME_ONLY) && (tmp & TIME_NO_ZERO_IN_DATE)) { THD *thd= get_thd(); push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, @@ -5860,7 +5898,7 @@ bool Field_time::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) bool Field_time::send_binary(Protocol *protocol) { MYSQL_TIME ltime; - get_date(<ime, TIME_TIME_ONLY); + get_date(<ime, Time::Options(TIME_TIME_ONLY, get_thd())); return protocol->store_time(<ime, decimals()); } @@ -5911,7 +5949,7 @@ int Field_time::store_decimal(const my_decimal *d) { ErrConvDecimal str(d); int was_cut; - Time tm(get_thd(), &was_cut, d, Time::Options(), decimals()); + Time tm(get_thd(), &was_cut, d, Time::Options(get_thd()), decimals()); return store_TIME_with_warning(&tm, &str, was_cut); } @@ -5971,8 +6009,7 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx, if (const_item->field_type() != MYSQL_TYPE_TIME) { // Get the value of const_item with conversion from DATETIME to TIME - Time tm(get_thd(), const_item, - Time::Options(Time::comparison_flags_for_get_date(), mode)); + Time tm(get_thd(), const_item, Time::Options_cmp(thd, mode)); if (!tm.is_valid_time()) return NULL; /* @@ -5996,10 +6033,6 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx, if (const_item->field_type() != MYSQL_TYPE_TIME || const_item->decimals != decimals()) { - Time tm(get_thd(), const_item, - Time::Options(TIME_TIME_ONLY, mode)); - if (!tm.is_valid_time()) - return NULL; /* Note, the value returned in "ltime" can have more fractional digits that decimals(). The Item_time_literal constructor will @@ -6014,6 +6047,10 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx, The optimized WHERE will return with "Impossible WHERE", without having to do the full table scan. */ + Time tm(thd, const_item, Time::Options(TIME_TIME_ONLY, thd, mode), + decimals()); + if (!tm.is_valid_time()) + return NULL; return new (thd->mem_root) Item_time_literal(thd, tm.get_mysql_time(), decimals()); } @@ -6027,7 +6064,7 @@ longlong Field_time_with_dec::val_int(void) { ASSERT_COLUMN_MARKED_FOR_READ; MYSQL_TIME ltime; - get_date(<ime, TIME_TIME_ONLY); + get_date(<ime, Time::Options(TIME_TIME_ONLY, get_thd())); longlong val= TIME_to_ulonglong_time(<ime); return ltime.neg ? -val : val; } @@ -6036,7 +6073,7 @@ double Field_time_with_dec::val_real(void) { ASSERT_COLUMN_MARKED_FOR_READ; MYSQL_TIME ltime; - get_date(<ime, TIME_TIME_ONLY); + get_date(<ime, Time::Options(TIME_TIME_ONLY, get_thd())); return TIME_to_double(<ime); } @@ -6268,7 +6305,8 @@ int Field_date_common::store(const char *from, size_t len, CHARSET_INFO *cs) { MYSQL_TIME_STATUS st; ErrConvString str(from, len, cs); - Datetime dt(&st, from, len, cs, sql_mode_for_dates(get_thd())); + THD *thd= get_thd(); + Datetime dt(thd, &st, from, len, cs, Date::Options(thd), 0); return store_TIME_with_warning(&dt, &str, st.warnings); } @@ -6276,7 +6314,8 @@ int Field_date_common::store(double nr) { int error; ErrConvDouble str(nr); - Datetime dt(&error, nr, sql_mode_for_dates(get_thd())); + THD *thd= get_thd(); + Datetime dt(thd, &error, nr, Date::Options(thd), 0); return store_TIME_with_warning(&dt, &str, error); } @@ -6285,7 +6324,8 @@ int Field_date_common::store(longlong nr, bool unsigned_val) int error; Longlong_hybrid tmp(nr, unsigned_val); ErrConvInteger str(tmp); - Datetime dt(&error, tmp, sql_mode_for_dates(get_thd())); + THD *thd= get_thd(); + Datetime dt(thd, &error, tmp, Date::Options(thd)); return store_TIME_with_warning(&dt, &str, error); } @@ -6294,7 +6334,7 @@ int Field_date_common::store_time_dec(const MYSQL_TIME *ltime, uint dec) int error; ErrConvTime str(ltime); THD *thd= get_thd(); - Datetime dt(thd, &error, ltime, sql_mode_for_dates(thd)); + Datetime dt(thd, &error, ltime, Date::Options(thd), 0); return store_TIME_with_warning(&dt, &str, error); } @@ -6302,7 +6342,8 @@ int Field_date_common::store_decimal(const my_decimal *d) { int error; ErrConvDecimal str(d); - Datetime tm(&error, d, sql_mode_for_dates(get_thd())); + THD *thd= get_thd(); + Datetime tm(thd, &error, d, Date::Options(thd), 0); return store_TIME_with_warning(&tm, &str, error); } @@ -6512,8 +6553,14 @@ Item *Field_newdate::get_equal_const_item(THD *thd, const Context &ctx, case ANY_SUBST: if (!is_temporal_type_with_date(const_item->field_type())) { - // Get the value of const_item with conversion from TIME to DATETIME - Datetime dt(thd, const_item, Datetime::comparison_flags_for_get_date()); + /* + DATE is compared to DATETIME-alike non-temporal values + (such as VARCHAR, DECIMAL) as DATETIME, e.g.: + WHERE date_column=20010101235959.0000009 + So here we convert the constant to DATETIME normally. + In case if TIME_ROUND_FRACTIONAL is enabled, nanoseconds will round. + */ + Datetime dt(thd, const_item, Datetime::Options_cmp(thd)); if (!dt.is_valid_datetime()) return NULL; /* @@ -6540,10 +6587,17 @@ Item *Field_newdate::get_equal_const_item(THD *thd, const Context &ctx, case IDENTITY_SUBST: if (const_item->field_type() != MYSQL_TYPE_DATE) { - Date d(thd, const_item, date_mode_t(0)); - if (!d.is_valid_date()) + /* + DATE is compared to non-temporal as DATETIME. + We need to convert to DATETIME first, taking into account the + current session rounding mode (even though this is IDENTITY_SUBSTS!), + then convert the result to DATE. + */ + Datetime dt(thd, const_item, Datetime::Options(TIME_CONV_NONE, thd)); + if (!dt.is_valid_datetime()) return NULL; - return new (thd->mem_root) Item_date_literal(thd, d.get_mysql_time()); + return new (thd->mem_root) + Item_date_literal(thd, Date(&dt).get_mysql_time()); } break; } @@ -6693,7 +6747,8 @@ int Field_datetime::set_time() { THD *thd= table->in_use; set_notnull(); - store_datetime(Datetime(thd, thd->query_start_timeval(), decimals())); + // Here we always truncate (not round), no matter what sql_mode is + store_datetime(Datetime(thd, thd->query_start_timeval()).trunc(decimals())); return 0; } diff --git a/sql/field.h b/sql/field.h index 7c5552ec13c..cca3b186668 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1346,7 +1346,6 @@ public: void copy_from_tmp(int offset); uint fill_cache_field(struct st_cache_field *copy); virtual bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); - bool get_time(MYSQL_TIME *ltime) { return get_date(ltime, TIME_TIME_ONLY); } virtual TYPELIB *get_typelib() const { return NULL; } virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; } virtual CHARSET_INFO *charset_for_protocol(void) const @@ -2643,7 +2642,8 @@ public: int save_in_field(Field *to) { MYSQL_TIME ltime; - if (get_date(<ime, date_mode_t(0))) + // For temporal types no truncation needed. Rounding mode is not important. + if (get_date(<ime, TIME_CONV_NONE | TIME_FRAC_NONE)) return to->reset(); return to->store_time_dec(<ime, decimals()); } @@ -2721,7 +2721,6 @@ public: class Field_timestamp :public Field_temporal { protected: - date_mode_t sql_mode_for_timestamp(THD *thd) const; int store_TIME_with_warning(THD *, const Datetime *, const ErrConv *, int warn); virtual void store_TIMEVAL(const timeval &tv) @@ -2771,10 +2770,15 @@ public: { return get_timestamp(ptr, sec_part); } - // This is used by storage/perfschema - void store_TIME(my_time_t timestamp, ulong sec_part) + /* + This method is used by storage/perfschema and + Item_func_now_local::save_in_field(). + */ + void store_TIME(my_time_t ts, ulong sec_part) { - store_TIMESTAMP(Timestamp(timestamp, sec_part).trunc(decimals())); + int warn; + time_round_mode_t mode= Datetime::default_round_mode(get_thd()); + store_TIMESTAMP(Timestamp(ts, sec_part).round(decimals(), mode, &warn)); } bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); uchar *pack(uchar *to, const uchar *from, diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 7a064f64570..2f56be60dd6 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -438,19 +438,19 @@ void Field::do_field_temporal(Copy_field *copy, date_mode_t fuzzydate) void Field::do_field_datetime(Copy_field *copy) { - return do_field_temporal(copy, date_mode_t(0)); + return do_field_temporal(copy, Datetime::Options(TIME_CONV_NONE, current_thd)); } void Field::do_field_date(Copy_field *copy) { - return do_field_temporal(copy, date_mode_t(0)); + return do_field_temporal(copy, Date::Options(TIME_CONV_NONE)); } void Field_time::do_field_time(Copy_field *copy) { - return do_field_temporal(copy, TIME_TIME_ONLY); + return do_field_temporal(copy, Time::Options(current_thd)); } diff --git a/sql/filesort.cc b/sql/filesort.cc index cbe79967647..d0cb77ac63d 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1051,7 +1051,10 @@ Type_handler_temporal_result::make_sort_key(uchar *to, Item *item, Sort_param *param) const { MYSQL_TIME buf; - if (item->get_date_result(current_thd, &buf, TIME_INVALID_DATES)) + // This is a temporal type. No nanoseconds. Rounding mode is not important. + DBUG_ASSERT(item->cmp_type() == TIME_RESULT); + static const Temporal::Options opt(TIME_INVALID_DATES, TIME_FRAC_NONE); + if (item->get_date_result(current_thd, &buf, opt)) { DBUG_ASSERT(item->maybe_null); DBUG_ASSERT(item->null_value); diff --git a/sql/item.cc b/sql/item.cc index 26a8aa44b80..99f801bb292 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -118,12 +118,12 @@ void Item::push_note_converted_to_positive_complement(THD *thd) longlong Item::val_datetime_packed_result(THD *thd) { MYSQL_TIME ltime, tmp; - if (get_date_result(thd, <ime, Datetime::comparison_flags_for_get_date())) + if (get_date_result(thd, <ime, Datetime::Options_cmp(thd))) return 0; if (ltime.time_type != MYSQL_TIMESTAMP_TIME) return pack_time(<ime); - if ((null_value= time_to_datetime_with_warn(thd, <ime, - &tmp, date_mode_t(0)))) + if ((null_value= time_to_datetime_with_warn(thd, <ime, &tmp, + TIME_CONV_NONE))) return 0; return pack_time(&tmp); } @@ -305,7 +305,7 @@ int Item::save_date_in_field(Field *field, bool no_conversions) { MYSQL_TIME ltime; THD *thd= field->table->in_use; - if (get_date(thd, <ime, sql_mode_for_dates(thd))) + if (get_date(thd, <ime, Datetime::Options(thd))) return set_field_to_null_with_conversions(field, no_conversions); field->set_notnull(); return field->store_time_dec(<ime, decimals); @@ -9732,7 +9732,8 @@ bool Item_cache_temporal::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzz int Item_cache_temporal::save_in_field(Field *field, bool no_conversions) { MYSQL_TIME ltime; - if (get_date(field->get_thd(), <ime, date_mode_t(0))) + // This is a temporal type. No nanoseconds, so round mode is not important. + if (get_date(field->get_thd(), <ime, TIME_CONV_NONE | TIME_FRAC_NONE)) return set_field_to_null_with_conversions(field, no_conversions); field->set_notnull(); int error= field->store_time_dec(<ime, decimals); diff --git a/sql/item.h b/sql/item.h index 2c9395ff89d..2ee2eabddac 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1636,28 +1636,28 @@ public: bool get_date_from_real(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); bool get_date_from_string(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); bool get_time(THD *thd, MYSQL_TIME *ltime) - { return get_date(thd, ltime, Time::flags_for_get_date()); } + { return get_date(thd, ltime, Time::Options(thd)); } // Get a DATE or DATETIME value in numeric packed format for comparison virtual longlong val_datetime_packed(THD *thd) { - date_mode_t fuzzydate= Datetime::comparison_flags_for_get_date(); - return Datetime(current_thd, this, fuzzydate).to_packed(); + return Datetime(thd, this, Datetime::Options_cmp(thd)).to_packed(); } // Get a TIME value in numeric packed format for comparison virtual longlong val_time_packed(THD *thd) { - return Time(thd, this, Time::comparison_flags_for_get_date()).to_packed(); + return Time(thd, this, Time::Options_cmp(thd)).to_packed(); } longlong val_datetime_packed_result(THD *thd); longlong val_time_packed_result(THD *thd) { MYSQL_TIME ltime; - date_mode_t fuzzydate= Time::comparison_flags_for_get_date(); - return get_date_result(thd, <ime, fuzzydate) ? 0 : pack_time(<ime); + return get_date_result(thd, <ime, Time::Options_cmp(thd)) ? 0 : + pack_time(<ime); } virtual bool get_date_result(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { return get_date(thd, ltime,fuzzydate); } + /* The method allows to determine nullness of a complex expression without fully evaluating it, instead of calling val/result*() then @@ -6441,8 +6441,8 @@ public: Item *make_literal(THD *); longlong val_datetime_packed(THD *thd) { - date_mode_t fuzzy= Datetime::comparison_flags_for_get_date(); - return has_value() ? Datetime(thd, this, fuzzy).to_packed() : 0; + Datetime::Options_cmp opt(thd); + return has_value() ? Datetime(thd, this, opt).to_packed() : 0; } longlong val_time_packed(THD *thd) { @@ -6481,7 +6481,7 @@ public: } longlong val_time_packed(THD *thd) { - return Time(thd, this, Time::comparison_flags_for_get_date()).to_packed(); + return Time(thd, this, Time::Options_cmp(thd)).to_packed(); } longlong val_int() { @@ -6516,7 +6516,7 @@ public: } longlong val_time_packed(THD *thd) { - return Time(thd, this, Time::comparison_flags_for_get_date()).to_packed(); + return Time(thd, this, Time::Options_cmp(thd)).to_packed(); } longlong val_int() { return has_value() ? Date(this).to_longlong() : 0; } double val_real() { return has_value() ? Date(this).to_double() : 0; } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 9488391f602..15f1f917b35 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2312,7 +2312,8 @@ bool Item_func_ifnull::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydat DBUG_ASSERT(fixed == 1); for (uint i= 0; i < 2; i++) { - Datetime dt(thd, args[i], fuzzydate & ~TIME_FUZZY_DATES); + Datetime_truncation_not_needed dt(thd, args[i], + fuzzydate & ~TIME_FUZZY_DATES); if (!(dt.copy_to_mysql_time(ltime, mysql_timestamp_type()))) return (null_value= false); } @@ -2812,7 +2813,7 @@ Item_func_nullif::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) DBUG_ASSERT(fixed == 1); if (!compare()) return (null_value= true); - Datetime dt(thd, args[2], fuzzydate); + Datetime_truncation_not_needed dt(thd, args[2], fuzzydate); return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type())); } @@ -2987,7 +2988,7 @@ bool Item_func_case::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) Item *item= find_item(); if (!item) return (null_value= true); - Datetime dt(thd, item, fuzzydate); + Datetime_truncation_not_needed dt(thd, item, fuzzydate); return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type())); } @@ -3339,7 +3340,8 @@ bool Item_func_coalesce::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzyd DBUG_ASSERT(fixed == 1); for (uint i= 0; i < arg_count; i++) { - Datetime dt(thd, args[i], fuzzydate & ~TIME_FUZZY_DATES); + Datetime_truncation_not_needed dt(thd, args[i], + fuzzydate & ~TIME_FUZZY_DATES); if (!dt.copy_to_mysql_time(ltime, mysql_timestamp_type())) return (null_value= false); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index cf210a71433..213f666dd74 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1127,7 +1127,7 @@ public: bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - Datetime dt(thd, find_item(), fuzzydate); + Datetime_truncation_not_needed dt(thd, find_item(), fuzzydate); return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type())); } bool time_op(THD *thd, MYSQL_TIME *ltime) diff --git a/sql/item_func.cc b/sql/item_func.cc index c176a7e43a7..ee2367a87b0 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2610,13 +2610,13 @@ bool Item_func_min_max::get_time_native(THD *thd, MYSQL_TIME *ltime) { DBUG_ASSERT(fixed == 1); - Time value(thd, args[0], Time::Options(), decimals); + Time value(thd, args[0], Time::Options(thd), decimals); if (!value.is_valid_time()) return (null_value= true); for (uint i= 1; i < arg_count ; i++) { - Time tmp(thd, args[i], Time::Options(), decimals); + Time tmp(thd, args[i], Time::Options(thd), decimals); if (!tmp.is_valid_time()) return (null_value= true); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 6c82c580858..6f2af72dabf 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -4544,7 +4544,7 @@ bool Item_func_dyncol_create::prepare_arguments(THD *thd, bool force_names_arg) case DYN_COL_DATETIME: case DYN_COL_DATE: args[valpos]->get_date(thd, &vals[i].x.time_value, - sql_mode_for_dates(thd)); + Datetime::Options(thd)); break; case DYN_COL_TIME: args[valpos]->get_time(thd, &vals[i].x.time_value); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 0e52b2988a3..b571289ca12 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3235,6 +3235,25 @@ bool Item_udf_sum::add() DBUG_RETURN(0); } + +bool Item_udf_sum::supports_removal() const +{ + DBUG_ENTER("Item_udf_sum::supports_remove"); + DBUG_PRINT("info", ("support: %d", udf.supports_removal())); + DBUG_RETURN(udf.supports_removal()); +} + + +void Item_udf_sum::remove() +{ + my_bool tmp_null_value; + DBUG_ENTER("Item_udf_sum::remove"); + udf.remove(&tmp_null_value); + null_value= tmp_null_value; + DBUG_VOID_RETURN; +} + + void Item_udf_sum::cleanup() { /* diff --git a/sql/item_sum.h b/sql/item_sum.h index 1a21c257221..01583d32f45 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -384,7 +384,9 @@ protected: Item **orig_args, *tmp_orig_args[2]; static size_t ram_limitation(THD *thd); - +public: + // Methods used by ColumnStore + Item **get_orig_args() const { return orig_args; } public: void mark_as_sum_func(); @@ -1561,6 +1563,8 @@ public: void clear(); bool add(); + bool supports_removal() const; + void remove(); void reset_field() {}; void update_field() {}; void cleanup(); @@ -1826,6 +1830,14 @@ class Item_func_group_concat : public Item_sum element_count count __attribute__((unused)), void* item_arg); public: + // Methods used by ColumnStore + bool get_distinct() const { return distinct; } + uint get_count_field() const { return arg_count_field; } + uint get_order_field() const { return arg_count_order; } + const String* get_separator() const { return separator; } + ORDER** get_order() const { return order; } + +public: Item_func_group_concat(THD *thd, Name_resolution_context *context_arg, bool is_distinct, List<Item> *is_select, const SQL_I_List<ORDER> &is_order, String *is_separator, diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index df4dc8cb96d..1b728f561b7 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -131,7 +131,7 @@ static bool extract_date_time(THD *thd, DATE_TIME_FORMAT *format, timestamp_type cached_timestamp_type, const char **sub_pattern_end, const char *date_time_type, - date_mode_t fuzzydate) + date_conv_mode_t fuzzydate) { int weekday= 0, yearday= 0, daypart= 0; int week_number= -1; @@ -808,8 +808,9 @@ longlong Item_func_period_diff::val_int() longlong Item_func_to_days::val_int() { DBUG_ASSERT(fixed == 1); - Date d(current_thd, args[0], TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE); - return (null_value= !d.is_valid_date()) ? 0 : d.daynr(); + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.daynr(); } @@ -817,14 +818,15 @@ longlong Item_func_to_seconds::val_int_endpoint(bool left_endp, bool *incl_endp) { DBUG_ASSERT(fixed == 1); - Datetime dt(current_thd, args[0], TIME_FUZZY_DATES); + // val_int_endpoint() is called only if args[0] is a temporal Item_field + Datetime_from_temporal dt(current_thd, args[0], TIME_FUZZY_DATES); if ((null_value= !dt.is_valid_datetime())) { /* got NULL, leave the incl_endp intact */ return LONGLONG_MIN; } /* Set to NULL if invalid date, but keep the value */ - null_value= dt.check_date(TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE); + null_value= dt.check_date(TIME_NO_ZEROS); /* Even if the evaluation return NULL, seconds is useful for pruning */ @@ -835,7 +837,11 @@ longlong Item_func_to_seconds::val_int() { DBUG_ASSERT(fixed == 1); THD *thd= current_thd; - Datetime dt(thd, args[0], TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE); + /* + Unlike val_int_endpoint(), we cannot use Datetime_from_temporal here. + The argument can be of a non-temporal data type. + */ + Datetime dt(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd)); return (null_value= !dt.is_valid_datetime()) ? 0 : dt.to_seconds(); } @@ -880,7 +886,8 @@ enum_monotonicity_info Item_func_to_seconds::get_monotonicity_info() const longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp) { DBUG_ASSERT(fixed == 1); - Datetime dt(current_thd, args[0], date_mode_t(0)); + // val_int_endpoint() is only called if args[0] is a temporal Item_field + Datetime_from_temporal dt(current_thd, args[0], TIME_CONV_NONE); longlong res; if ((null_value= !dt.is_valid_datetime())) { @@ -889,7 +896,7 @@ longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp) } res= (longlong) dt.daynr(); /* Set to NULL if invalid date, but keep the value */ - null_value= dt.check_date(TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE); + null_value= dt.check_date(TIME_NO_ZEROS); if (null_value) { /* @@ -933,22 +940,25 @@ longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp) longlong Item_func_dayofyear::val_int() { DBUG_ASSERT(fixed == 1); - Date d(current_thd, args[0], TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE); - return (null_value= !d.is_valid_date()) ? 0 : d.dayofyear(); + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.dayofyear(); } longlong Item_func_dayofmonth::val_int() { DBUG_ASSERT(fixed == 1); - Date d(current_thd, args[0], date_mode_t(0)); - return (null_value= !d.is_valid_date()) ? 0 : d.get_mysql_time()->day; + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.get_mysql_time()->day; } longlong Item_func_month::val_int() { DBUG_ASSERT(fixed == 1); - Date d(current_thd, args[0], date_mode_t(0)); - return (null_value= !d.is_valid_date()) ? 0 : d.get_mysql_time()->month; + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.get_mysql_time()->month; } @@ -970,9 +980,9 @@ String* Item_func_monthname::val_str(String* str) DBUG_ASSERT(fixed == 1); const char *month_name; uint err; - Date d(current_thd, args[0], date_mode_t(0)); - - if ((null_value= (!d.is_valid_date() || !d.get_mysql_time()->month))) + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); + if ((null_value= (!d.is_valid_datetime() || !d.get_mysql_time()->month))) return (String *) 0; month_name= locale->month_names->type_names[d.get_mysql_time()->month - 1]; @@ -989,21 +999,24 @@ String* Item_func_monthname::val_str(String* str) longlong Item_func_quarter::val_int() { DBUG_ASSERT(fixed == 1); - Date d(current_thd, args[0], date_mode_t(0)); - return (null_value= !d.is_valid_date()) ? 0 : d.quarter(); + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.quarter(); } longlong Item_func_hour::val_int() { DBUG_ASSERT(fixed == 1); - Time tm(current_thd, args[0], Time::Options_for_cast()); + THD *thd= current_thd; + Time tm(thd, args[0], Time::Options_for_cast(thd)); return (null_value= !tm.is_valid_time()) ? 0 : tm.get_mysql_time()->hour; } longlong Item_func_minute::val_int() { DBUG_ASSERT(fixed == 1); - Time tm(current_thd, args[0], Time::Options_for_cast()); + THD *thd= current_thd; + Time tm(thd, args[0], Time::Options_for_cast(thd)); return (null_value= !tm.is_valid_time()) ? 0 : tm.get_mysql_time()->minute; } @@ -1013,7 +1026,8 @@ longlong Item_func_minute::val_int() longlong Item_func_second::val_int() { DBUG_ASSERT(fixed == 1); - Time tm(current_thd, args[0], Time::Options_for_cast()); + THD *thd= current_thd; + Time tm(thd, args[0], Time::Options_for_cast(thd)); return (null_value= !tm.is_valid_time()) ? 0 : tm.get_mysql_time()->second; } @@ -1062,8 +1076,8 @@ longlong Item_func_week::val_int() DBUG_ASSERT(fixed == 1); uint week_format; THD *thd= current_thd; - Date d(thd, args[0], TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE); - if ((null_value= !d.is_valid_date())) + Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd)); + if ((null_value= !d.is_valid_datetime())) return 0; if (arg_count > 1) week_format= (uint)args[1]->val_int(); @@ -1076,8 +1090,9 @@ longlong Item_func_week::val_int() longlong Item_func_yearweek::val_int() { DBUG_ASSERT(fixed == 1); - Date d(current_thd, args[0], TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE); - return (null_value= !d.is_valid_date()) ? 0 : + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.yearweek((week_mode((uint) args[1]->val_int()) | WEEK_YEAR)); } @@ -1085,8 +1100,9 @@ longlong Item_func_yearweek::val_int() longlong Item_func_weekday::val_int() { DBUG_ASSERT(fixed == 1); - Date d(current_thd, args[0], TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE); - return ((null_value= !d.is_valid_date())) ? 0 : + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd)); + return ((null_value= !d.is_valid_datetime())) ? 0 : calc_weekday(d.daynr(), odbc_type) + MY_TEST(odbc_type); } @@ -1123,8 +1139,9 @@ String* Item_func_dayname::val_str(String* str) longlong Item_func_year::val_int() { DBUG_ASSERT(fixed == 1); - Date d(current_thd, args[0], date_mode_t(0)); - return (null_value= !d.is_valid_date()) ? 0 : d.get_mysql_time()->year; + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.get_mysql_time()->year; } @@ -1155,7 +1172,8 @@ enum_monotonicity_info Item_func_year::get_monotonicity_info() const longlong Item_func_year::val_int_endpoint(bool left_endp, bool *incl_endp) { DBUG_ASSERT(fixed == 1); - Datetime dt(current_thd, args[0], date_mode_t(0)); + // val_int_endpoint() is cally only if args[0] is a temporal Item_field + Datetime_from_temporal dt(current_thd, args[0], TIME_CONV_NONE); if ((null_value= !dt.is_valid_datetime())) { /* got NULL, leave the incl_endp intact */ @@ -1200,7 +1218,7 @@ bool Item_func_unix_timestamp::get_timestamp_value(my_time_t *seconds, } THD *thd= current_thd; - Datetime dt(thd, args[0], TIME_NO_ZERO_IN_DATE); + Datetime dt(thd, args[0], Datetime::Options(TIME_NO_ZERO_IN_DATE, thd)); if ((null_value= !dt.is_valid_datetime())) return true; @@ -1264,7 +1282,8 @@ longlong Item_func_unix_timestamp::val_int_endpoint(bool left_endp, bool *incl_e longlong Item_func_time_to_sec::int_op() { DBUG_ASSERT(fixed == 1); - Time tm(current_thd, args[0], Time::Options_for_cast()); + THD *thd= current_thd; + Time tm(thd, args[0], Time::Options_for_cast(thd)); return ((null_value= !tm.is_valid_time())) ? 0 : tm.to_seconds(); } @@ -1272,7 +1291,8 @@ longlong Item_func_time_to_sec::int_op() my_decimal *Item_func_time_to_sec::decimal_op(my_decimal* buf) { DBUG_ASSERT(fixed == 1); - Time tm(current_thd, args[0], Time::Options_for_cast()); + THD *thd= current_thd; + Time tm(thd, args[0], Time::Options_for_cast(thd)); if ((null_value= !tm.is_valid_time())) return 0; const MYSQL_TIME *ltime= tm.get_mysql_time(); @@ -1621,9 +1641,8 @@ int Item_func_now_local::save_in_field(Field *field, bool no_conversions) { THD *thd= field->get_thd(); my_time_t ts= thd->query_start(); - uint dec= MY_MIN(decimals, field->decimals()); - ulong sec_part= dec ? thd->query_start_sec_part() : 0; - sec_part-= my_time_fraction_remainder(sec_part, dec); + ulong sec_part= decimals ? thd->query_start_sec_part() : 0; + sec_part-= my_time_fraction_remainder(sec_part, decimals); field->set_notnull(); ((Field_timestamp*)field)->store_TIME(ts, sec_part); return 0; @@ -1698,9 +1717,10 @@ bool Item_func_sysdate_local::get_date(THD *thd, MYSQL_TIME *res, bool Item_func_sec_to_time::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed == 1); - VSec6 sec(thd, args[0], "seconds", LONGLONG_MAX); + VSec9 sec(thd, args[0], "seconds", LONGLONG_MAX); if ((null_value= sec.is_null())) return true; + sec.round(decimals, thd->temporal_round_mode()); if (sec.sec_to_time(ltime, decimals) && !sec.truncated()) sec.make_truncated_warning(thd, "seconds"); return false; @@ -1858,10 +1878,10 @@ String *Item_func_date_format::val_str(String *str) uint size; const MY_LOCALE *lc= 0; DBUG_ASSERT(fixed == 1); - - if ((null_value= args[0]->get_date(current_thd, &l_time, - is_time_format ? TIME_TIME_ONLY : - date_mode_t(0)))) + date_conv_mode_t mode= is_time_format ? TIME_TIME_ONLY : TIME_CONV_NONE; + THD *thd= current_thd; + if ((null_value= args[0]->get_date(thd, &l_time, + Temporal::Options(mode, thd)))) return 0; if (!(format = args[1]->val_str(str)) || !format->length()) @@ -1918,12 +1938,16 @@ bool Item_func_from_unixtime::get_date(THD *thd, MYSQL_TIME *ltime, bzero((char *)ltime, sizeof(*ltime)); ltime->time_type= MYSQL_TIMESTAMP_TIME; - VSec6 sec(thd, args[0], "unixtime", TIMESTAMP_MAX_VALUE); + VSec9 sec(thd, args[0], "unixtime", TIMESTAMP_MAX_VALUE); DBUG_ASSERT(sec.sec() <= TIMESTAMP_MAX_VALUE); if (sec.is_null() || sec.truncated() || sec.neg()) return (null_value= 1); + sec.round(MY_MIN(decimals, TIME_SECOND_PART_DIGITS), thd->temporal_round_mode()); + if (sec.sec() > TIMESTAMP_MAX_VALUE) + return (null_value= true); // Went out of range after rounding + tz->gmt_sec_to_TIME(ltime, (my_time_t) sec.sec()); ltime->second_part= sec.usec(); @@ -1952,7 +1976,8 @@ bool Item_func_convert_tz::get_date(THD *thd, MYSQL_TIME *ltime, if ((null_value= (from_tz == 0 || to_tz == 0))) return true; - Datetime *dt= new(ltime) Datetime(thd, args[0], TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE); + Datetime::Options opt(TIME_NO_ZEROS, thd); + Datetime *dt= new(ltime) Datetime(thd, args[0], opt); if ((null_value= !dt->is_valid_datetime())) return true; @@ -2133,7 +2158,8 @@ uint Extract_source::week(THD *thd) const longlong Item_extract::val_int() { DBUG_ASSERT(fixed == 1); - Extract_source dt(current_thd, args[0], m_date_mode); + THD *thd= current_thd; + Extract_source dt(thd, args[0], m_date_mode); if ((null_value= !dt.is_valid_extract_source())) return 0; switch (int_type) { @@ -2141,7 +2167,7 @@ longlong Item_extract::val_int() case INTERVAL_YEAR_MONTH: return dt.year_month(); case INTERVAL_QUARTER: return dt.quarter(); case INTERVAL_MONTH: return dt.month(); - case INTERVAL_WEEK: return dt.week(current_thd); + case INTERVAL_WEEK: return dt.week(thd); case INTERVAL_DAY: return dt.day(); case INTERVAL_DAY_HOUR: return dt.day_hour(); case INTERVAL_DAY_MINUTE: return dt.day_minute(); @@ -2420,7 +2446,7 @@ void Item_char_typecast::fix_length_and_dec_internal(CHARSET_INFO *from_cs) bool Item_time_typecast::get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) { - Time *tm= new(to) Time(thd, args[0], Time::Options_for_cast(mode), + Time *tm= new(to) Time(thd, args[0], Time::Options_for_cast(mode, thd), MY_MIN(decimals, TIME_SECOND_PART_DIGITS)); return (null_value= !tm->is_valid_time()); } @@ -2429,7 +2455,8 @@ bool Item_time_typecast::get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) bool Item_date_typecast::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { date_mode_t tmp= (fuzzydate | sql_mode_for_dates(thd)) & ~TIME_TIME_ONLY; - Date *d= new(ltime) Date(thd, args[0], tmp); + // Force truncation + Date *d= new(ltime) Date(thd, args[0], Date::Options(date_conv_mode_t(tmp))); return (null_value= !d->is_valid_date()); } @@ -2437,7 +2464,9 @@ bool Item_date_typecast::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzy bool Item_datetime_typecast::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { date_mode_t tmp= (fuzzydate | sql_mode_for_dates(thd)) & ~TIME_TIME_ONLY; - Datetime *dt= new(ltime) Datetime(thd, args[0], tmp, + // Force rounding if the current sql_mode says so + Datetime::Options opt(date_conv_mode_t(tmp), thd); + Datetime *dt= new(ltime) Datetime(thd, args[0], opt, MY_MIN(decimals, TIME_SECOND_PART_DIGITS)); return (null_value= !dt->is_valid_datetime()); } @@ -2558,6 +2587,7 @@ bool Item_func_timediff::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzy return (null_value= adjust_time_range_with_warn(thd, ltime, decimals)); } + /** MAKETIME(h,m,s) is a time function that calculates a time value from the total number of hours, minutes, and seconds. @@ -2569,7 +2599,7 @@ bool Item_func_maketime::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzy DBUG_ASSERT(fixed == 1); Longlong_hybrid hour(args[0]->val_int(), args[0]->unsigned_flag); longlong minute= args[1]->val_int(); - VSec6 sec(thd, args[2], "seconds", 59); + VSec9 sec(thd, args[2], "seconds", 59); DBUG_ASSERT(sec.sec() <= 59); if (args[0]->null_value || args[1]->null_value || sec.is_null() || @@ -2577,7 +2607,8 @@ bool Item_func_maketime::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzy return (null_value= 1); int warn; - new(ltime) Time(&warn, hour.neg(), hour.abs(), (uint) minute, sec); + new(ltime) Time(&warn, hour.neg(), hour.abs(), (uint) minute, sec, + thd->temporal_round_mode(), decimals); if (warn) { // use check_time_range() to set ltime to the max value depending on dec @@ -2607,7 +2638,8 @@ bool Item_func_maketime::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzy longlong Item_func_microsecond::val_int() { DBUG_ASSERT(fixed == 1); - Time tm(current_thd, args[0], Time::Options_for_cast()); + THD *thd= current_thd; + Time tm(thd, args[0], Time::Options_for_cast(thd)); return ((null_value= !tm.is_valid_time())) ? 0 : tm.get_mysql_time()->second_part; } @@ -2621,12 +2653,12 @@ longlong Item_func_timestamp_diff::val_int() long months= 0; int neg= 1; THD *thd= current_thd; - date_mode_t fuzzydate= TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE; + Datetime::Options opt(TIME_NO_ZEROS, thd); null_value= 0; - if (Datetime(thd, args[0], fuzzydate).copy_to_mysql_time(<ime1) || - Datetime(thd, args[1], fuzzydate).copy_to_mysql_time(<ime2)) + if (Datetime(thd, args[0], opt).copy_to_mysql_time(<ime1) || + Datetime(thd, args[1], opt).copy_to_mysql_time(<ime2)) goto null_date; if (calc_time_diff(<ime2,<ime1, 1, @@ -2935,7 +2967,8 @@ bool Item_func_str_to_date::get_date_common(THD *thd, MYSQL_TIME *ltime, date_time_format.format.length= format->length(); if (extract_date_time(thd, &date_time_format, val->ptr(), val->length(), ltime, tstype, 0, "datetime", - fuzzydate | sql_mode_for_dates(thd))) + date_conv_mode_t(fuzzydate) | + sql_mode_for_dates(thd))) return (null_value=1); return (null_value= 0); } @@ -2943,8 +2976,10 @@ bool Item_func_str_to_date::get_date_common(THD *thd, MYSQL_TIME *ltime, bool Item_func_last_day::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - Date *d= new(ltime) Date(thd, args[0], fuzzydate & ~TIME_TIME_ONLY); - if ((null_value= (!d->is_valid_date() || ltime->month == 0))) + Datetime::Options opt(date_conv_mode_t(fuzzydate & ~TIME_TIME_ONLY), + time_round_mode_t(fuzzydate)); + Datetime *d= new(ltime) Datetime(thd, args[0], opt); + if ((null_value= (!d->is_valid_datetime() || ltime->month == 0))) return true; uint month_idx= ltime->month-1; ltime->day= days_in_month[month_idx]; diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 318bef22ad1..d9ab45ed46d 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -993,12 +993,12 @@ class Item_extract :public Item_int_func, EXTRACT(DAY FROM '-24:00:00') -> -1 */ set_handler(handler_by_length(max_length= length + 1/*sign*/, 11)); - m_date_mode= TIME_INTERVAL_DAY; + m_date_mode= Temporal::Options(TIME_INTERVAL_DAY, current_thd); } void set_time_length(uint32 length) { set_handler(handler_by_length(max_length= length + 1/*sign*/, 11)); - m_date_mode= TIME_INTERVAL_hhmmssff; + m_date_mode= Temporal::Options(TIME_INTERVAL_hhmmssff, current_thd); } public: const interval_type int_type; // keep it public @@ -1080,6 +1080,9 @@ class Item_char_typecast :public Item_str_func void check_truncation_with_warn(String *src, size_t dstlen); void fix_length_and_dec_internal(CHARSET_INFO *fromcs); public: + // Methods used by ColumnStore + uint get_cast_length() const { return cast_length; } +public: Item_char_typecast(THD *thd, Item *a, uint length_arg, CHARSET_INFO *cs_arg): Item_str_func(thd, a), cast_length(length_arg), cast_cs(cs_arg), m_suppress_warning_to_error_escalation(false) {} @@ -1117,7 +1120,7 @@ public: { } String *val_str(String *to) { - Interval_DDhhmmssff it(current_thd, args[0]); + Interval_DDhhmmssff it(current_thd, args[0], m_fsp); null_value= !it.is_valid_interval_DDhhmmssff(); return it.to_string(to, m_fsp); } @@ -1222,7 +1225,7 @@ public: } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - Datetime dt(thd, args[0], date_mode_t(0)); + Datetime dt(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); if (!dt.is_valid_datetime()) return null_value= true; Interval_DDhhmmssff it(thd, args[1]); @@ -1250,6 +1253,9 @@ class Item_func_add_time :public Item_handled_func { int sign; public: + // Methods used by ColumnStore + int get_sign() const { return sign; } +public: Item_func_add_time(THD *thd, Item *a, Item *b, bool neg_arg) :Item_handled_func(thd, a, b), sign(neg_arg ? -1 : 1) { } @@ -1335,6 +1341,9 @@ class Item_func_timestamp_diff :public Item_longlong_func { return check_argument_types_can_return_date(0, arg_count); } const interval_type int_type; public: + // Methods used by ColumnStore + interval_type get_int_type() const { return int_type; }; +public: Item_func_timestamp_diff(THD *thd, Item *a, Item *b, interval_type type_arg): Item_longlong_func(thd, a, b), int_type(type_arg) {} const char *func_name() const { return "timestampdiff"; } @@ -1461,7 +1470,8 @@ public: bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const { - Datetime dt(thd, item->arguments()[0], date_mode_t(0)); + Datetime::Options opt(TIME_CONV_NONE, thd); + Datetime dt(thd, item->arguments()[0], opt); if (!dt.is_valid_datetime() || dt.check_date_with_warn(thd, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)) return (item->null_value= true); @@ -1489,7 +1499,11 @@ public: bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const { - Date d(thd, item->arguments()[0], date_mode_t(0)); + /* + The first argument is known to be of the DATE data type (not DATETIME). + We don't need rounding here. + */ + Date d(thd, item->arguments()[0], TIME_CONV_NONE); if (!d.is_valid_date() || d.check_date_with_warn(thd, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)) return (item->null_value= true); @@ -1542,10 +1556,10 @@ public: bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to, date_mode_t fuzzy) const { - if (item->arguments()[0]->get_date(thd, to, date_mode_t(0)) || + if (item->arguments()[0]-> + get_date(thd, to, Datetime::Options(TIME_CONV_NONE, thd)) || (to->time_type != MYSQL_TIMESTAMP_TIME && - check_date_with_warn(thd, to, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE, - MYSQL_TIMESTAMP_ERROR))) + check_date_with_warn(thd, to, TIME_NO_ZEROS, MYSQL_TIMESTAMP_ERROR))) return (item->null_value= true); return (item->null_value= add(thd, item->arguments()[1], int_type(item), sub(item), to)); @@ -1581,7 +1595,8 @@ public: MYSQL_TIME *to, date_mode_t fuzzy) const { DBUG_ASSERT(item->is_fixed()); - Datetime dt(thd, item->arguments()[0], date_mode_t(0)); + Datetime::Options opt(TIME_CONV_NONE, thd); + Datetime dt(thd, item->arguments()[0], opt); if (!dt.is_valid_datetime()) return item->null_value= true; Interval_DDhhmmssff it(thd, item->arguments()[1]); @@ -1650,7 +1665,8 @@ public: { DBUG_ASSERT(item->is_fixed()); // Detect a proper timestamp type based on the argument values - Temporal_hybrid l_time1(thd, item->arguments()[0], TIME_TIME_ONLY); + Temporal_hybrid l_time1(thd, item->arguments()[0], + Temporal::Options(TIME_TIME_ONLY, thd)); if (!l_time1.is_valid_temporal()) return (item->null_value= true); Interval_DDhhmmssff l_time2(thd, item->arguments()[1]); diff --git a/sql/item_vers.cc b/sql/item_vers.cc index 6946ae0e1e5..c4bb734096f 100644 --- a/sql/item_vers.cc +++ b/sql/item_vers.cc @@ -142,7 +142,9 @@ Item_func_trt_id::val_int() else { MYSQL_TIME commit_ts; - if (args[0]->get_date(current_thd, &commit_ts, date_mode_t(0))) + THD *thd= current_thd; + Datetime::Options opt(TIME_CONV_NONE, thd); + if (args[0]->get_date(thd, &commit_ts, opt)) { null_value= true; return 0; diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index de7018c53cb..6927b181d92 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -268,7 +268,8 @@ int str2my_decimal(uint mask, const char *from, size_t length, integer part cannot be larger that 1e18 (otherwise it's an overflow). fractional part is microseconds. */ -bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, ulong *microsec) +bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, + ulong *microsec, ulong *nanosec) { int pos; @@ -286,6 +287,7 @@ bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, ulong *microsec) } *microsec= d->frac ? static_cast<longlong>(d->buf[pos+1]) / (DIG_BASE/1000000) : 0; + *nanosec= d->frac ? static_cast<longlong>(d->buf[pos+1]) % (DIG_BASE/1000000) : 0; if (pos > 1) { diff --git a/sql/my_decimal.h b/sql/my_decimal.h index b22c686cc90..c196d43e001 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -362,7 +362,8 @@ inline bool str_set_decimal(const my_decimal *val, String *str, } -bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, ulong *microsec); +bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, + ulong *microsec, ulong *nanosec); my_decimal *seconds2my_decimal(bool sign, ulonglong sec, ulong microsec, my_decimal *d); diff --git a/sql/sp.cc b/sql/sp.cc index 723f30ec85d..d37ea543219 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -200,7 +200,8 @@ TABLE_FIELD_TYPE proc_table_fields[MYSQL_PROC_FIELD_COUNT] = "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES'," "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER'," "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH'," - "'EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT')") }, + "'EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT'," + "'TIME_ROUND_FRACTIONAL')") }, { NULL, 0 } }, { diff --git a/sql/sql_basic_types.h b/sql/sql_basic_types.h index 5062817f911..a790b68fc0c 100644 --- a/sql/sql_basic_types.h +++ b/sql/sql_basic_types.h @@ -26,13 +26,15 @@ typedef int64 query_id_t; /* "fuzzydate" with strict data type control. + Represents a mixture of *only* data type conversion flags, without rounding. Please keep "explicit" in constructors and conversion methods. */ -class date_mode_t +class date_conv_mode_t { public: enum value_t { + CONV_NONE= 0U, /* FUZZY_DATES is used for the result will only be used for comparison purposes. Conversion is as relaxed as possible. @@ -41,17 +43,33 @@ public: TIME_ONLY= 4U, INTERVAL_hhmmssff= 8U, INTERVAL_DAY= 16U, + RANGE0_LAST= INTERVAL_DAY, NO_ZERO_IN_DATE= (1UL << 23), // MODE_NO_ZERO_IN_DATE NO_ZERO_DATE= (1UL << 24), // MODE_NO_ZERO_DATE INVALID_DATES= (1UL << 25) // MODE_INVALID_DATES }; + /* + BIT-OR for all known values. Let's have a separate enum for it. + - We don't put this value "value_t", to avoid handling it in switch(). + - We don't put this value as a static const inside the class, + because "gdb" would display it every time when we do "print" + for a time_round_mode_t value. + - We can't put into into a function returning this value, because + it's not allowed to use functions in static_assert. + */ + enum known_values_t + { + KNOWN_MODES= FUZZY_DATES | + TIME_ONLY | INTERVAL_hhmmssff | INTERVAL_DAY | + NO_ZERO_IN_DATE | NO_ZERO_DATE | INVALID_DATES + }; private: value_t m_mode; public: // Constructors - explicit date_mode_t(ulonglong fuzzydate) + explicit date_conv_mode_t(ulonglong fuzzydate) :m_mode((value_t) fuzzydate) { } @@ -66,9 +84,148 @@ public: } // Unary operators - date_mode_t operator~() const + ulonglong operator~() const { - return date_mode_t(~m_mode); + return ~m_mode; + } + + // Dyadic bitwise operators + date_conv_mode_t operator&(const date_conv_mode_t &other) const + { + return date_conv_mode_t(m_mode & other.m_mode); + } + date_conv_mode_t operator&(const ulonglong other) const + { + return date_conv_mode_t(m_mode & other); + } + + date_conv_mode_t operator|(const date_conv_mode_t &other) const + { + return date_conv_mode_t(m_mode | other.m_mode); + } + + // Dyadic bitwise assignment operators + date_conv_mode_t &operator&=(const date_conv_mode_t &other) + { + m_mode= value_t(m_mode & other.m_mode); + return *this; + } + + date_conv_mode_t &operator|=(const date_conv_mode_t &other) + { + m_mode= value_t(m_mode | other.m_mode); + return *this; + } +}; + + +/* + Fractional rounding mode for temporal data types. +*/ +class time_round_mode_t +{ +public: + enum value_t + { + /* + Use FRAC_NONE when the value needs no rounding nor truncation, + because it is already known not to haveany fractional digits outside + of the requested precision. + */ + FRAC_NONE= 0, + FRAC_TRUNCATE= date_conv_mode_t::RANGE0_LAST << 1, // 32 + FRAC_ROUND= date_conv_mode_t::RANGE0_LAST << 2 // 64 + }; + // BIT-OR for all known values. See comments in time_conv_mode_t. + enum known_values_t + { + KNOWN_MODES= FRAC_TRUNCATE | FRAC_ROUND + }; +private: + value_t m_mode; +public: + // Constructors + explicit time_round_mode_t(ulonglong mode) + :m_mode((value_t) mode) + { + DBUG_ASSERT(mode == FRAC_NONE || + mode == FRAC_TRUNCATE || + mode == FRAC_ROUND); + } + // Conversion operators + explicit operator ulonglong() const + { + return m_mode; + } + value_t mode() const + { + return m_mode; + } + // Comparison operators + bool operator==(const time_round_mode_t &other) + { + return m_mode == other.m_mode; + } +}; + + +/* + "fuzzydate" with strict data type control. + Used as a parameter to get_date() and represents a mixture of: + - data type conversion flags + - fractional second rounding flags + Please keep "explicit" in constructors and conversion methods. +*/ +class date_mode_t +{ +public: + enum value_t + { + CONV_NONE= date_conv_mode_t::CONV_NONE, // 0 + FUZZY_DATES= date_conv_mode_t::FUZZY_DATES, // 1 + TIME_ONLY= date_conv_mode_t::TIME_ONLY, // 4 + INTERVAL_hhmmssff= date_conv_mode_t::INTERVAL_hhmmssff, // 8 + INTERVAL_DAY= date_conv_mode_t::INTERVAL_DAY, // 16 + FRAC_TRUNCATE= time_round_mode_t::FRAC_TRUNCATE, // 32 + FRAC_ROUND= time_round_mode_t::FRAC_ROUND, // 64 + NO_ZERO_IN_DATE= date_conv_mode_t::NO_ZERO_IN_DATE, // (1UL << 23) + NO_ZERO_DATE= date_conv_mode_t::NO_ZERO_DATE, // (1UL << 24) + INVALID_DATES= date_conv_mode_t::INVALID_DATES, // (1UL << 25) + }; +protected: + value_t m_mode; +public: + + // Constructors + explicit date_mode_t(ulonglong fuzzydate) + :m_mode((value_t) fuzzydate) + { } + + // Conversion operators + explicit operator ulonglong() const + { + return m_mode; + } + explicit operator bool() const + { + return m_mode != 0; + } + explicit operator date_conv_mode_t() const + { + return date_conv_mode_t(ulonglong(m_mode) & date_conv_mode_t::KNOWN_MODES); + } + explicit operator time_round_mode_t() const + { + return time_round_mode_t(ulonglong(m_mode) & time_round_mode_t::KNOWN_MODES); + } + // Unary operators + ulonglong operator~() const + { + return ~m_mode; + } + bool operator!() const + { + return !m_mode; } // Dyadic bitwise operators @@ -76,6 +233,10 @@ public: { return date_mode_t(m_mode & other.m_mode); } + date_mode_t operator&(ulonglong other) const + { + return date_mode_t(m_mode & other); + } date_mode_t operator|(const date_mode_t &other) const { @@ -94,22 +255,81 @@ public: m_mode= value_t(m_mode | other.m_mode); return *this; } + + date_mode_t &operator|=(const date_conv_mode_t &other) + { + m_mode= value_t(m_mode | ulonglong(other)); + return *this; + } }; -const date_mode_t - TIME_FUZZY_DATES (date_mode_t::value_t::FUZZY_DATES), - TIME_TIME_ONLY (date_mode_t::value_t::TIME_ONLY), - TIME_INTERVAL_hhmmssff (date_mode_t::value_t::INTERVAL_hhmmssff), - TIME_INTERVAL_DAY (date_mode_t::value_t::INTERVAL_DAY), - TIME_NO_ZERO_IN_DATE (date_mode_t::value_t::NO_ZERO_IN_DATE), - TIME_NO_ZERO_DATE (date_mode_t::value_t::NO_ZERO_DATE), - TIME_INVALID_DATES (date_mode_t::value_t::INVALID_DATES); +// Bitwise OR out-of-class operators for data type mixtures +static inline date_mode_t operator|(const date_mode_t &a, + const date_conv_mode_t &b) +{ + return date_mode_t(ulonglong(a) | ulonglong(b)); +} + +static inline date_mode_t operator|(const date_conv_mode_t &a, + const time_round_mode_t &b) +{ + return date_mode_t(ulonglong(a) | ulonglong(b)); +} + + +static inline date_mode_t operator|(const date_conv_mode_t &a, + const date_mode_t &b) +{ + return date_mode_t(ulonglong(a) | ulonglong(b)); +} + + +// Bitwise AND out-of-class operators for data type mixtures +static inline date_conv_mode_t operator&(const date_mode_t &a, + const date_conv_mode_t &b) +{ + return date_conv_mode_t(ulonglong(a) & ulonglong(b)); +} + +static inline date_conv_mode_t operator&(const date_conv_mode_t &a, + const date_mode_t &b) +{ + return date_conv_mode_t(ulonglong(a) & ulonglong(b)); +} + +static inline date_conv_mode_t operator&(sql_mode_t &a, + const date_conv_mode_t &b) +{ + return date_conv_mode_t(a & ulonglong(b)); +} + + +static const date_conv_mode_t + TIME_CONV_NONE (date_conv_mode_t::CONV_NONE), + TIME_FUZZY_DATES (date_conv_mode_t::FUZZY_DATES), + TIME_TIME_ONLY (date_conv_mode_t::TIME_ONLY), + TIME_INTERVAL_hhmmssff (date_conv_mode_t::INTERVAL_hhmmssff), + TIME_INTERVAL_DAY (date_conv_mode_t::INTERVAL_DAY), + TIME_NO_ZERO_IN_DATE (date_conv_mode_t::NO_ZERO_IN_DATE), + TIME_NO_ZERO_DATE (date_conv_mode_t::NO_ZERO_DATE), + TIME_INVALID_DATES (date_conv_mode_t::INVALID_DATES); + +// An often used combination +static const date_conv_mode_t + TIME_NO_ZEROS (date_conv_mode_t::NO_ZERO_DATE| + date_conv_mode_t::NO_ZERO_IN_DATE); // Flags understood by str_to_xxx, number_to_xxx, check_date -static const date_mode_t +static const date_conv_mode_t TIME_MODE_FOR_XXX_TO_DATE (date_mode_t::NO_ZERO_IN_DATE | date_mode_t::NO_ZERO_DATE | date_mode_t::INVALID_DATES); +static const time_round_mode_t + TIME_FRAC_NONE (time_round_mode_t::FRAC_NONE), + TIME_FRAC_TRUNCATE (time_round_mode_t::FRAC_TRUNCATE), + TIME_FRAC_ROUND (time_round_mode_t::FRAC_ROUND); + + #endif diff --git a/sql/sql_class.h b/sql/sql_class.h index 8174a8b313b..1997add96dc 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -158,6 +158,7 @@ enum enum_binlog_row_image { #define MODE_PAD_CHAR_TO_FULL_LENGTH (1ULL << 31) #define MODE_EMPTY_STRING_IS_NULL (1ULL << 32) #define MODE_SIMULTANEOUS_ASSIGNMENT (1ULL << 33) +#define MODE_TIME_ROUND_FRACTIONAL (1ULL << 34) /* Bits for different old style modes */ #define OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE (1 << 0) @@ -3419,6 +3420,11 @@ public: { return Timeval(query_start(), query_start_sec_part()); } + time_round_mode_t temporal_round_mode() const + { + return variables.sql_mode & MODE_TIME_ROUND_FRACTIONAL ? + TIME_FRAC_ROUND : TIME_FRAC_TRUNCATE; + } private: struct { @@ -4957,13 +4963,17 @@ my_eof(THD *thd) (A)->variables.sql_log_bin_off= 0;} -inline date_mode_t sql_mode_for_dates(THD *thd) +inline date_conv_mode_t sql_mode_for_dates(THD *thd) { + static_assert((date_conv_mode_t::KNOWN_MODES & + time_round_mode_t::KNOWN_MODES) == 0, + "date_conv_mode_t and time_round_mode_t must use different " + "bit values"); static_assert(MODE_NO_ZERO_DATE == date_mode_t::NO_ZERO_DATE && MODE_NO_ZERO_IN_DATE == date_mode_t::NO_ZERO_IN_DATE && MODE_INVALID_DATES == date_mode_t::INVALID_DATES, "sql_mode_t and date_mode_t values must be equal"); - return date_mode_t(thd->variables.sql_mode & + return date_conv_mode_t(thd->variables.sql_mode & (MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE | MODE_INVALID_DATES)); } @@ -6104,6 +6114,10 @@ class multi_delete :public select_result_interceptor bool error_handled; public: + // Methods used by ColumnStore + uint get_num_of_tables() const { return num_of_tables; } + TABLE_LIST* get_tables() const { return delete_tables; } +public: multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables); ~multi_delete(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1f9cd305847..3b2e57abcf5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2385,7 +2385,8 @@ com_multi_end: /* wsrep BF abort in query exec phase */ mysql_mutex_lock(&thd->LOCK_thd_data); do_end_of_statement= thd->wsrep_conflict_state != REPLAYING && - thd->wsrep_conflict_state != RETRY_AUTOCOMMIT; + thd->wsrep_conflict_state != RETRY_AUTOCOMMIT && + !thd->killed; mysql_mutex_unlock(&thd->LOCK_thd_data); } else diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 96e07b19dd8..6b530a95efb 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -8217,6 +8217,7 @@ static int get_part_iter_for_interval_via_mapping(partition_info *part_info, field->type() == MYSQL_TYPE_DATETIME)) { /* Monotonic, but return NULL for dates with zeros in month/day. */ + DBUG_ASSERT(field->cmp_type() == TIME_RESULT); // No rounding/truncation zero_in_start_date= field->get_date(&start_date, date_mode_t(0)); DBUG_PRINT("info", ("zero start %u %04d-%02d-%02d", zero_in_start_date, start_date.year, @@ -8241,6 +8242,7 @@ static int get_part_iter_for_interval_via_mapping(partition_info *part_info, !part_info->part_expr->null_value) { MYSQL_TIME end_date; + DBUG_ASSERT(field->cmp_type() == TIME_RESULT); // No rounding/truncation bool zero_in_end_date= field->get_date(&end_date, date_mode_t(0)); /* This is an optimization for TO_DAYS()/TO_SECONDS() to avoid scanning diff --git a/sql/sql_time.cc b/sql/sql_time.cc index 35a4e1e47c3..3977df675b3 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -289,8 +289,8 @@ ulong convert_month_to_period(ulong month) bool -check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, date_mode_t fuzzydate, - timestamp_type ts_type) +check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, + date_conv_mode_t fuzzydate, timestamp_type ts_type) { int unused; if (check_date(ltime, fuzzydate, &unused)) @@ -372,34 +372,37 @@ public: /* Character set-aware version of ascii_to_datetime_or_date_or_time() */ -bool Temporal::str_to_datetime_or_date_or_time(MYSQL_TIME_STATUS *st, +bool Temporal::str_to_datetime_or_date_or_time(THD *thd, MYSQL_TIME_STATUS *st, const char *str, size_t length, CHARSET_INFO *cs, date_mode_t fuzzydate) { TemporalAsciiBuffer tmp(str, length, cs); - return ascii_to_datetime_or_date_or_time(st, tmp.str, tmp.length, fuzzydate); + return ascii_to_datetime_or_date_or_time(st, tmp.str, tmp.length, fuzzydate)|| + add_nanoseconds(thd, &st->warnings, fuzzydate, st->nanoseconds); } /* Character set-aware version of str_to_datetime_or_date() */ -bool Temporal::str_to_datetime_or_date(MYSQL_TIME_STATUS *status, +bool Temporal::str_to_datetime_or_date(THD *thd, MYSQL_TIME_STATUS *status, const char *str, size_t length, CHARSET_INFO *cs, date_mode_t flags) { TemporalAsciiBuffer tmp(str, length, cs); - return ascii_to_datetime_or_date(status, tmp.str, tmp.length, flags); + return ascii_to_datetime_or_date(status, tmp.str, tmp.length, flags) || + add_nanoseconds(thd, &status->warnings, flags, status->nanoseconds); } /* Character set-aware version of ascii_to_temporal() */ -bool Temporal::str_to_temporal(MYSQL_TIME_STATUS *status, +bool Temporal::str_to_temporal(THD *thd, MYSQL_TIME_STATUS *status, const char *str, size_t length, CHARSET_INFO *cs, date_mode_t flags) { TemporalAsciiBuffer tmp(str, length, cs); - return ascii_to_temporal(status, tmp.str, tmp.length, flags); + return ascii_to_temporal(status, tmp.str, tmp.length, flags) || + add_nanoseconds(thd, &status->warnings, flags, status->nanoseconds); } @@ -1307,7 +1310,7 @@ time_to_datetime(THD *thd, const MYSQL_TIME *from, MYSQL_TIME *to) bool time_to_datetime_with_warn(THD *thd, const MYSQL_TIME *from, MYSQL_TIME *to, - date_mode_t fuzzydate) + date_conv_mode_t fuzzydate) { int warn= 0; DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_TIME); diff --git a/sql/sql_time.h b/sql/sql_time.h index 433374e2e9a..cfbff205667 100644 --- a/sql/sql_time.h +++ b/sql/sql_time.h @@ -57,7 +57,7 @@ bool int_to_datetime_with_warn(THD *thd, const Longlong_hybrid &nr, bool time_to_datetime(THD *thd, const MYSQL_TIME *tm, MYSQL_TIME *dt); bool time_to_datetime_with_warn(THD *thd, const MYSQL_TIME *tm, MYSQL_TIME *dt, - date_mode_t fuzzydate); + date_conv_mode_t fuzzydate); inline void datetime_to_date(MYSQL_TIME *ltime) { @@ -166,13 +166,20 @@ non_zero_date(const MYSQL_TIME *ltime) non_zero_hhmmssuu(ltime)); } static inline bool -check_date(const MYSQL_TIME *ltime, date_mode_t flags, int *was_cut) +check_date(const MYSQL_TIME *ltime, date_conv_mode_t flags, int *was_cut) { return check_date(ltime, non_zero_date(ltime), ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), was_cut); } -bool check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, date_mode_t fuzzy_date, - timestamp_type ts_type); +bool check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, + date_conv_mode_t fuzzy_date, timestamp_type ts_type); +static inline bool +check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, + date_mode_t fuzzydate, timestamp_type ts_type) +{ + return check_date_with_warn(thd, ltime, date_conv_mode_t(fuzzydate), ts_type); +} + bool adjust_time_range_with_warn(THD *thd, MYSQL_TIME *ltime, uint dec); longlong pack_time(const MYSQL_TIME *my_time); diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 60c3747f2ea..f92ce45bc97 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -156,12 +156,24 @@ VDec_op::VDec_op(Item_func_hybrid_field_type *item) } -date_mode_t Temporal::sql_mode_for_dates(THD *thd) +date_conv_mode_t Temporal::sql_mode_for_dates(THD *thd) { return ::sql_mode_for_dates(thd); } +time_round_mode_t Temporal::default_round_mode(THD *thd) +{ + return thd->temporal_round_mode(); +} + + +time_round_mode_t Timestamp::default_round_mode(THD *thd) +{ + return thd->temporal_round_mode(); +} + + my_decimal *Temporal::to_decimal(my_decimal *to) const { return date2my_decimal(this, to); @@ -183,8 +195,8 @@ void Temporal::make_from_str(THD *thd, Warn *warn, push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_YES, ErrConvString(str, length,cs).ptr());); - if (str_to_temporal(warn, str, length, cs, fuzzydate)) - make_fuzzy_date(&warn->warnings, fuzzydate); + if (str_to_temporal(thd, warn, str, length, cs, fuzzydate)) + make_fuzzy_date(&warn->warnings, date_conv_mode_t(fuzzydate)); if (warn->warnings) warn->set_str(str, length, &my_charset_bin); } @@ -197,14 +209,14 @@ Temporal_hybrid::Temporal_hybrid(THD *thd, Item *item, date_mode_t fuzzydate) } -void Sec6::make_from_decimal(const my_decimal *d) +void Sec6::make_from_decimal(const my_decimal *d, ulong *nanoseconds) { - m_neg= my_decimal2seconds(d, &m_sec, &m_usec); + m_neg= my_decimal2seconds(d, &m_sec, &m_usec, nanoseconds); m_truncated= (m_sec >= LONGLONG_MAX); } -void Sec6::make_from_double(double nr) +void Sec6::make_from_double(double nr, ulong *nanoseconds) { if ((m_neg= nr < 0)) nr= -nr; @@ -216,7 +228,9 @@ void Sec6::make_from_double(double nr) else { m_sec= (ulonglong) nr; - m_usec= (ulong) ((nr - floor(nr)) * 1000000); + m_usec= (ulong) ((nr - floor(nr)) * 1000000000); + *nanoseconds= m_usec % 1000; + m_usec/= 1000; } } @@ -235,8 +249,8 @@ bool Sec6::convert_to_mysql_time(THD *thd, int *warn, MYSQL_TIME *ltime, bool rc= fuzzydate & (TIME_INTERVAL_hhmmssff | TIME_INTERVAL_DAY) ? to_datetime_or_to_interval_hhmmssff(ltime, warn) : fuzzydate & TIME_TIME_ONLY ? - to_datetime_or_time(ltime, warn, fuzzydate) : - to_datetime_or_date(ltime, warn, fuzzydate); + to_datetime_or_time(ltime, warn, date_conv_mode_t(fuzzydate)) : + to_datetime_or_date(ltime, warn, date_conv_mode_t(fuzzydate)); DBUG_ASSERT(*warn || !rc); if (truncated()) *warn|= MYSQL_TIME_WARN_TRUNCATED; @@ -259,7 +273,7 @@ void Temporal::push_conversion_warnings(THD *thd, bool totally_useless_value, in } -VSec6::VSec6(THD *thd, Item *item, const char *type_str, ulonglong limit) +VSec9::VSec9(THD *thd, Item *item, const char *type_str, ulonglong limit) { if (item->decimals == 0) { // optimize for an important special case @@ -277,7 +291,7 @@ VSec6::VSec6(THD *thd, Item *item, const char *type_str, ulonglong limit) else if (item->cmp_type() == REAL_RESULT) { double nr= item->val_real(); - make_from_double(nr); + make_from_double(nr, &m_nsec); m_is_null= item->null_value; if (!m_is_null && m_sec > limit) { @@ -293,7 +307,7 @@ VSec6::VSec6(THD *thd, Item *item, const char *type_str, ulonglong limit) else { VDec tmp(item); - (m_is_null= tmp.is_null()) ? reset() : make_from_decimal(tmp.ptr()); + (m_is_null= tmp.is_null()) ? reset() : make_from_decimal(tmp.ptr(), &m_nsec); if (!m_is_null && m_sec > limit) { m_sec= limit; @@ -352,7 +366,8 @@ const LEX_CSTRING Interval_DDhhmmssff::m_type_name= Interval_DDhhmmssff::Interval_DDhhmmssff(THD *thd, Status *st, bool push_warnings, - Item *item, ulong max_hour) + Item *item, ulong max_hour, + time_round_mode_t mode, uint dec) { switch (item->cmp_type()) { case ROW_RESULT: @@ -361,7 +376,8 @@ Interval_DDhhmmssff::Interval_DDhhmmssff(THD *thd, Status *st, break; case TIME_RESULT: { - if (item->get_date(thd, this, TIME_TIME_ONLY)) + // Rounding mode is not important here + if (item->get_date(thd, this, Options(TIME_TIME_ONLY, TIME_FRAC_NONE))) time_type= MYSQL_TIMESTAMP_NONE; else if (time_type != MYSQL_TIMESTAMP_TIME) { @@ -392,6 +408,8 @@ Interval_DDhhmmssff::Interval_DDhhmmssff(THD *thd, Status *st, } else { + if (mode == TIME_FRAC_ROUND) + time_round_or_set_max(dec, &st->warnings, max_hour, st->nanoseconds); if (hour > max_hour) { st->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE; @@ -450,7 +468,8 @@ uint Interval_DDhhmmssff::fsp(THD *thd, Item *item) if (!item->const_item() || item->is_expensive()) return TIME_SECOND_PART_DIGITS; Status st; - Interval_DDhhmmssff it(thd, &st, false/*no warnings*/, item, UINT_MAX32); + Interval_DDhhmmssff it(thd, &st, false/*no warnings*/, item, UINT_MAX32, + TIME_FRAC_TRUNCATE, TIME_SECOND_PART_DIGITS); return it.is_valid_interval_DDhhmmssff() ? st.precision : TIME_SECOND_PART_DIGITS; } @@ -459,13 +478,101 @@ uint Interval_DDhhmmssff::fsp(THD *thd, Item *item) void Time::make_from_item(THD *thd, int *warn, Item *item, const Options opt) { *warn= 0; - if (item->get_date(thd, this, opt.get_date_flags())) + if (item->get_date(thd, this, opt)) time_type= MYSQL_TIMESTAMP_NONE; else valid_MYSQL_TIME_to_valid_value(thd, warn, opt); } +static uint msec_round_add[7]= +{ + 500000000, + 50000000, + 5000000, + 500000, + 50000, + 5000, + 0 +}; + + +Sec9 & Sec9::round(uint dec) +{ + DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); + if (Sec6::add_nanoseconds(m_nsec + msec_round_add[dec])) + m_sec++; + m_nsec= 0; + Sec6::trunc(dec); + return *this; +} + + +void Timestamp::round_or_set_max(uint dec, int *warn) +{ + DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); + if (add_nanoseconds_usec(msec_round_add[dec]) && + tv_sec++ >= TIMESTAMP_MAX_VALUE) + { + tv_sec= TIMESTAMP_MAX_VALUE; + tv_usec= TIME_MAX_SECOND_PART; + *warn|= MYSQL_TIME_WARN_OUT_OF_RANGE; + } + my_timeval_trunc(this, dec); +} + + +bool Temporal::add_nanoseconds_with_round(THD *thd, int *warn, + date_conv_mode_t mode, + ulong nsec) +{ + switch (time_type) { + case MYSQL_TIMESTAMP_TIME: + { + ulong max_hour= (mode & (TIME_INTERVAL_DAY | TIME_INTERVAL_hhmmssff)) ? + TIME_MAX_INTERVAL_HOUR : TIME_MAX_HOUR; + time_round_or_set_max(6, warn, max_hour, nsec); + return false; + } + case MYSQL_TIMESTAMP_DATETIME: + return datetime_round_or_invalidate(thd, 6, warn, nsec); + case MYSQL_TIMESTAMP_DATE: + return false; + case MYSQL_TIMESTAMP_NONE: + return false; + case MYSQL_TIMESTAMP_ERROR: + break; + } + DBUG_ASSERT(0); + return false; +} + + +void Temporal::time_round_or_set_max(uint dec, int *warn, + ulong max_hour, ulong nsec) +{ + DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); + if (add_nanoseconds_mmssff(nsec) && ++hour > max_hour) + { + time_hhmmssff_set_max(max_hour); + *warn|= MYSQL_TIME_WARN_OUT_OF_RANGE; + } + my_time_trunc(this, dec); +} + + +void Time::round_or_set_max(uint dec, int *warn, ulong nsec) +{ + Temporal::time_round_or_set_max(dec, warn, TIME_MAX_HOUR, nsec); + DBUG_ASSERT(is_valid_time_slow()); +} + + +void Time::round_or_set_max(uint dec, int *warn) +{ + round_or_set_max(dec, warn, msec_round_add[dec]); +} + /** Create from a DATETIME by subtracting a given number of days, implementing an optimized version of calc_time_diff(). @@ -586,9 +693,10 @@ Time::Time(int *warn, bool neg, ulonglong hour, uint minute, const Sec6 &second) } -void Temporal_with_date::make_from_item(THD *thd, Item *item, date_mode_t flags) +void Temporal_with_date::make_from_item(THD *thd, Item *item, + date_mode_t fuzzydate) { - flags&= ~TIME_TIME_ONLY; + date_conv_mode_t flags= date_conv_mode_t(fuzzydate) & ~TIME_TIME_ONLY; /* Some TIME type items return error when trying to do get_date() without TIME_TIME_ONLY set (e.g. Item_field for Field_time). @@ -596,10 +704,11 @@ void Temporal_with_date::make_from_item(THD *thd, Item *item, date_mode_t flags) In the legacy time->datetime conversion mode we do not add TIME_TIME_ONLY and leave it to get_date() to check date. */ - date_mode_t time_flag= (item->field_type() == MYSQL_TYPE_TIME && + date_conv_mode_t time_flag= (item->field_type() == MYSQL_TYPE_TIME && !(thd->variables.old_behavior & OLD_MODE_ZERO_DATE_TIME_CAST)) ? - TIME_TIME_ONLY : date_mode_t(0); - if (item->get_date(thd, this, flags | time_flag)) + TIME_TIME_ONLY : TIME_CONV_NONE; + Options opt(flags | time_flag, time_round_mode_t(fuzzydate)); + if (item->get_date(thd, this, opt)) time_type= MYSQL_TIMESTAMP_NONE; else if (time_type == MYSQL_TIMESTAMP_TIME) { @@ -612,22 +721,17 @@ void Temporal_with_date::make_from_item(THD *thd, Item *item, date_mode_t flags) } -void Temporal_with_date::make_from_item(THD *thd, Item *item) +void Temporal_with_date::check_date_or_invalidate(int *warn, + date_conv_mode_t flags) { - return make_from_item(thd, item, sql_mode_for_dates(thd)); -} - - -void Temporal_with_date::check_date_or_invalidate(int *warn, date_mode_t flags) -{ - if (check_date(this, pack_time(this) != 0, - ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), warn)) + if (::check_date(this, pack_time(this) != 0, + ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), warn)) time_type= MYSQL_TIMESTAMP_NONE; } void Datetime::make_from_time(THD *thd, int *warn, const MYSQL_TIME *from, - date_mode_t flags) + date_conv_mode_t flags) { DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_TIME); if (time_to_datetime(thd, from, this)) @@ -641,7 +745,7 @@ void Datetime::make_from_time(THD *thd, int *warn, const MYSQL_TIME *from, void Datetime::make_from_datetime(THD *thd, int *warn, const MYSQL_TIME *from, - date_mode_t flags) + date_conv_mode_t flags) { DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_DATE || from->time_type == MYSQL_TIMESTAMP_DATETIME); @@ -667,7 +771,7 @@ Datetime::Datetime(THD *thd, const timeval &tv) Datetime::Datetime(THD *thd, int *warn, const MYSQL_TIME *from, - date_mode_t flags) + date_conv_mode_t flags) { DBUG_ASSERT(bool(flags & TIME_TIME_ONLY) == false); switch (from->time_type) { @@ -687,6 +791,84 @@ Datetime::Datetime(THD *thd, int *warn, const MYSQL_TIME *from, } +bool Temporal::datetime_add_nanoseconds_or_invalidate(THD *thd, int *warn, ulong nsec) +{ + if (!add_nanoseconds_mmssff(nsec)) + return false; + /* + Overflow happened on minutes. Now we need to add 1 hour to the value. + Catch a special case for the maximum possible date and hour==23, to + truncate '9999-12-31 23:59:59.9999999' (with 7 fractional digits) + to '9999-12-31 23:59:59.999999' (with 6 fractional digits), + with a warning, instead of returning an error, so this statement: + INSERT INTO (datetime_column) VALUES ('9999-12-31 23:59:59.9999999'); + inserts a value truncated to 6 fractional digits, instead of zero + date '0000-00-00 00:00:00.000000'. + */ + if (year == 9999 && month == 12 && day == 31 && hour == 23) + { + minute= 59; + second= 59; + second_part= 999999; + *warn= MYSQL_TIME_WARN_OUT_OF_RANGE; + return false; + } + INTERVAL interval; + memset(&interval, 0, sizeof(interval)); + interval.hour= 1; + /* date_add_interval cannot handle bad dates */ + if (check_date(TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE, warn) || + date_add_interval(thd, this, INTERVAL_HOUR, interval)) + { + make_from_out_of_range(warn); + return true; + } + return false; +} + + +bool Temporal::datetime_round_or_invalidate(THD *thd, uint dec, int *warn, ulong nsec) +{ + DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); + if (datetime_add_nanoseconds_or_invalidate(thd, warn, nsec)) + return true; + my_time_trunc(this, dec); + return false; + +} + + +bool Datetime::round_or_invalidate(THD *thd, uint dec, int *warn) +{ + return round_or_invalidate(thd, dec, warn, msec_round_add[dec]); +} + + +Datetime_from_temporal::Datetime_from_temporal(THD *thd, Item *temporal, + date_conv_mode_t fuzzydate) + :Datetime(thd, temporal, Options(fuzzydate, TIME_FRAC_NONE)) +{ + // Exact rounding mode does not matter + DBUG_ASSERT(temporal->cmp_type() == TIME_RESULT); +} + + +Datetime_truncation_not_needed::Datetime_truncation_not_needed(THD *thd, Item *item, + date_conv_mode_t mode) + :Datetime(thd, item, Options(mode, TIME_FRAC_NONE)) +{ + /* + The called Datetime() constructor only would truncate nanoseconds if they + existed (but we know there were no nanoseconds). Here we assert that there + are also no microsecond digits outside of the scale specified in "dec". + */ + DBUG_ASSERT(!is_valid_datetime() || + fraction_remainder(MY_MIN(item->decimals, + TIME_SECOND_PART_DIGITS)) == 0); +} + +/********************************************************************/ + uint Type_std_attributes::count_max_decimals(Item **item, uint nitems) { uint res= 0; @@ -3151,14 +3333,16 @@ void Type_handler_row::Item_update_null_value(Item *item) const void Type_handler_time_common::Item_update_null_value(Item *item) const { MYSQL_TIME ltime; - (void) item->get_date(current_thd, <ime, TIME_TIME_ONLY); + THD *thd= current_thd; + (void) item->get_date(thd, <ime, Time::Options(TIME_TIME_ONLY, thd)); } void Type_handler_temporal_with_date::Item_update_null_value(Item *item) const { MYSQL_TIME ltime; - (void) item->get_date(current_thd, <ime, sql_mode_for_dates(current_thd)); + THD *thd= current_thd; + (void) item->get_date(thd, <ime, Datetime::Options(thd)); } @@ -5013,7 +5197,7 @@ bool Type_handler_temporal_result:: */ return func->get_date_native(thd, ltime, fuzzydate & TIME_TIME_ONLY ? - sql_mode_for_dates(thd) : + Datetime::Options(thd) : fuzzydate); } @@ -5847,14 +6031,15 @@ uint Type_handler_string_result::Item_temporal_precision(THD *thd, Item *item, String *tmp; MYSQL_TIME_STATUS status; DBUG_ASSERT(item->is_fixed()); + // Nanosecond rounding is not needed here, for performance purposes if ((tmp= item->val_str(&buf)) && (is_time ? Time(thd, &status, tmp->ptr(), tmp->length(), tmp->charset(), - Time::Options(TIME_TIME_ONLY, + Time::Options(TIME_TIME_ONLY, TIME_FRAC_TRUNCATE, Time::DATETIME_TO_TIME_YYYYMMDD_TRUNCATE)). is_valid_time() : - Datetime(&status, tmp->ptr(), tmp->length(), tmp->charset(), - TIME_FUZZY_DATES). + Datetime(thd, &status, tmp->ptr(), tmp->length(), tmp->charset(), + Datetime::Options(TIME_FUZZY_DATES, TIME_FRAC_TRUNCATE)). is_valid_datetime())) return MY_MIN(status.precision, TIME_SECOND_PART_DIGITS); return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS); @@ -6104,7 +6289,8 @@ bool Type_handler_temporal_with_date:: Item_save_in_value(THD *thd, Item *item, st_value *value) const { value->m_type= DYN_COL_DATETIME; - item->get_date(thd, &value->value.m_time, sql_mode_for_dates(thd)); + item->get_date(thd, &value->value.m_time, + Datetime::Options(thd, TIME_FRAC_NONE)); return check_null(item, value); } @@ -6298,7 +6484,7 @@ bool Type_handler:: Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const { item->get_date(protocol->thd, &buf->value.m_time, - sql_mode_for_dates(protocol->thd)); + Datetime::Options(protocol->thd)); if (!item->null_value) return protocol->store(&buf->value.m_time, item->decimals); return protocol->store_null(); @@ -6309,7 +6495,7 @@ bool Type_handler:: Item_send_date(Item *item, Protocol *protocol, st_value *buf) const { item->get_date(protocol->thd, &buf->value.m_time, - sql_mode_for_dates(protocol->thd)); + Date::Options(protocol->thd)); if (!item->null_value) return protocol->store_date(&buf->value.m_time); return protocol->store_null(); @@ -7502,8 +7688,8 @@ int Type_handler_temporal_with_date::stored_field_cmp_to_item(THD *thd, Item *item) const { MYSQL_TIME field_time, item_time, item_time2, *item_time_cmp= &item_time; - field->get_date(&field_time, TIME_INVALID_DATES); - item->get_date(thd, &item_time, TIME_INVALID_DATES); + field->get_date(&field_time, Datetime::Options(TIME_INVALID_DATES, thd)); + item->get_date(thd, &item_time, Datetime::Options(TIME_INVALID_DATES, thd)); if (item_time.time_type == MYSQL_TIMESTAMP_TIME && time_to_datetime(thd, &item_time, item_time_cmp= &item_time2)) return 1; @@ -7516,8 +7702,8 @@ int Type_handler_time_common::stored_field_cmp_to_item(THD *thd, Item *item) const { MYSQL_TIME field_time, item_time; - field->get_time(&field_time); - item->get_time(thd, &item_time); + field->get_date(&field_time, Time::Options(thd)); + item->get_date(thd, &item_time, Time::Options(thd)); return my_time_compare(&field_time, &item_time); } @@ -7612,7 +7798,7 @@ Type_handler_date_common::create_literal_item(THD *thd, { Temporal::Warn st; Item_literal *item= NULL; - Temporal_hybrid tmp(thd, &st, str, length, cs, sql_mode_for_dates(thd)); + Temporal_hybrid tmp(thd, &st, str, length, cs, Temporal_hybrid::Options(thd)); if (tmp.is_valid_temporal() && tmp.get_mysql_time()->time_type == MYSQL_TIMESTAMP_DATE && !have_important_literal_warnings(&st)) @@ -7632,7 +7818,7 @@ Type_handler_temporal_with_date::create_literal_item(THD *thd, { Temporal::Warn st; Item_literal *item= NULL; - Temporal_hybrid tmp(thd, &st, str, length, cs, sql_mode_for_dates(thd)); + Temporal_hybrid tmp(thd, &st, str, length, cs, Temporal_hybrid::Options(thd)); if (tmp.is_valid_temporal() && tmp.get_mysql_time()->time_type == MYSQL_TIMESTAMP_DATETIME && !have_important_literal_warnings(&st)) @@ -7653,7 +7839,7 @@ Type_handler_time_common::create_literal_item(THD *thd, { MYSQL_TIME_STATUS st; Item_literal *item= NULL; - Time::Options opt(TIME_TIME_ONLY, Time::DATETIME_TO_TIME_DISALLOW); + Time::Options opt(TIME_TIME_ONLY, thd, Time::DATETIME_TO_TIME_DISALLOW); Time tmp(thd, &st, str, length, cs, opt); if (tmp.is_valid_time() && !have_important_literal_warnings(&st)) diff --git a/sql/sql_type.h b/sql/sql_type.h index 273542c201c..a5d8f4ae6df 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -216,8 +216,8 @@ protected: ulong m_usec; // The fractional part, between 0 and 999999 bool m_neg; // false if positive, true of negative bool m_truncated; // Indicates if the constructor truncated the value - void make_from_decimal(const my_decimal *d); - void make_from_double(double d); + void make_from_decimal(const my_decimal *d, ulong *nanoseconds); + void make_from_double(double d, ulong *nanoseconds); void make_from_int(const Longlong_hybrid &nr) { m_neg= nr.neg(); @@ -230,14 +230,27 @@ protected: m_sec= m_usec= m_neg= m_truncated= 0; } Sec6() { } + bool add_nanoseconds(uint nanoseconds) + { + DBUG_ASSERT(nanoseconds <= 1000000000); + if (nanoseconds < 500) + return false; + m_usec+= (nanoseconds + 500) / 1000; + if (m_usec < 1000000) + return false; + m_usec%= 1000000; + return true; + } public: explicit Sec6(double nr) { - make_from_double(nr); + ulong nanoseconds; + make_from_double(nr, &nanoseconds); } explicit Sec6(const my_decimal *d) { - make_from_decimal(d); + ulong nanoseconds; + make_from_decimal(d, &nanoseconds); } explicit Sec6(const Longlong_hybrid &nr) { @@ -303,7 +316,8 @@ protected: } public: // [-][DD]hhhmmss.ff, YYMMDDhhmmss.ff, YYYYMMDDhhmmss.ff - bool to_datetime_or_time(MYSQL_TIME *to, int *warn, date_mode_t mode) const + bool to_datetime_or_time(MYSQL_TIME *to, int *warn, + date_conv_mode_t mode) const { bool rc= m_sec > 9999999 && m_sec <= 99991231235959ULL && !m_neg ? ::number_to_datetime_or_date(m_sec, m_usec, to, @@ -316,7 +330,8 @@ public: Convert a number in formats YYYYMMDDhhmmss.ff or YYMMDDhhmmss.ff to TIMESTAMP'YYYY-MM-DD hh:mm:ss.ff' */ - bool to_datetime_or_date(MYSQL_TIME *to, int *warn, date_mode_t flags) const + bool to_datetime_or_date(MYSQL_TIME *to, int *warn, + date_conv_mode_t flags) const { if (m_neg) { @@ -349,6 +364,11 @@ public: ltime->second_part= m_usec; return false; } + Sec6 &trunc(uint dec) + { + m_usec-= my_time_fraction_remainder(m_usec, dec); + return *this; + } size_t to_string(char *to, size_t nbytes) const { return m_usec ? @@ -360,11 +380,45 @@ public: }; -class VSec6: public Sec6 +class Sec9: public Sec6 +{ +protected: + ulong m_nsec; // Nanoseconds 0..999 + void make_from_int(const Longlong_hybrid &nr) + { + Sec6::make_from_int(nr); + m_nsec= 0; + } + Sec9() { } +public: + Sec9(const my_decimal *d) + { + Sec6::make_from_decimal(d, &m_nsec); + } + Sec9(double d) + { + Sec6::make_from_double(d, &m_nsec); + } + ulong nsec() const { return m_nsec; } + Sec9 &trunc(uint dec) + { + m_nsec= 0; + Sec6::trunc(dec); + return *this; + } + Sec9 &round(uint dec); + Sec9 &round(uint dec, time_round_mode_t mode) + { + return mode == TIME_FRAC_TRUNCATE ? trunc(dec) : round(dec); + } +}; + + +class VSec9: public Sec9 { bool m_is_null; public: - VSec6(THD *thd, Item *item, const char *type_str, ulonglong limit); + VSec9(THD *thd, Item *item, const char *type_str, ulonglong limit); bool is_null() const { return m_is_null; } }; @@ -524,7 +578,24 @@ public: }; public: - static date_mode_t sql_mode_for_dates(THD *thd); + static date_conv_mode_t sql_mode_for_dates(THD *thd); + static time_round_mode_t default_round_mode(THD *thd); + class Options: public date_mode_t + { + public: + explicit Options(date_mode_t flags) + :date_mode_t(flags) + { } + Options(date_conv_mode_t flags, time_round_mode_t round_mode) + :date_mode_t(flags | round_mode) + { + DBUG_ASSERT(ulonglong(flags) <= UINT_MAX32); + } + Options(date_conv_mode_t flags, THD *thd) + :Options(flags, default_round_mode(thd)) + { } + }; + bool is_valid_temporal() const { DBUG_ASSERT(time_type != MYSQL_TIMESTAMP_ERROR); @@ -550,7 +621,7 @@ public: TIME/DATE/DATETIME failed. We return a zero date if allowed, otherwise - null. */ - void make_fuzzy_date(int *warn, date_mode_t fuzzydate) + void make_fuzzy_date(int *warn, date_conv_mode_t fuzzydate) { /* In the following scenario: @@ -590,14 +661,21 @@ protected: const Sec6 &nr, date_mode_t mode) { if (nr.convert_to_mysql_time(thd, &st->warnings, this, mode)) - make_fuzzy_date(&st->warnings, mode); + make_fuzzy_date(&st->warnings, date_conv_mode_t(mode)); + } + void make_from_sec9(THD *thd, MYSQL_TIME_STATUS *st, + const Sec9 &nr, date_mode_t mode) + { + if (nr.convert_to_mysql_time(thd, &st->warnings, this, mode) || + add_nanoseconds(thd, &st->warnings, mode, nr.nsec())) + make_fuzzy_date(&st->warnings, date_conv_mode_t(mode)); } void make_from_str(THD *thd, Warn *warn, const char *str, size_t length, CHARSET_INFO *cs, date_mode_t fuzzydate); void make_from_double(THD *thd, Warn *warn, double nr, date_mode_t mode) { - make_from_sec6(thd, warn, Sec6(nr), mode); + make_from_sec9(thd, warn, Sec9(nr), mode); if (warn->warnings) warn->set_double(nr); } @@ -615,7 +693,7 @@ protected: void make_from_decimal(THD *thd, Warn *warn, const my_decimal *nr, date_mode_t mode) { - make_from_sec6(thd, warn, Sec6(nr), mode); + make_from_sec9(thd, warn, Sec9(nr), mode); if (warn->warnings) warn->set_decimal(nr); } @@ -670,15 +748,15 @@ protected: return rc; } // Character set aware versions for string conversion routines - bool str_to_temporal(MYSQL_TIME_STATUS *st, + bool str_to_temporal(THD *thd, MYSQL_TIME_STATUS *st, const char *str, size_t length, CHARSET_INFO *cs, date_mode_t fuzzydate); - bool str_to_datetime_or_date_or_time(MYSQL_TIME_STATUS *st, + bool str_to_datetime_or_date_or_time(THD *thd, MYSQL_TIME_STATUS *st, const char *str, size_t length, - CHARSET_INFO *cs, date_mode_t fuzzydate); - bool str_to_datetime_or_date(MYSQL_TIME_STATUS *st, + CHARSET_INFO *cs, date_mode_t mode); + bool str_to_datetime_or_date(THD *thd, MYSQL_TIME_STATUS *st, const char *str, size_t length, - CHARSET_INFO *cs, date_mode_t fuzzydate); + CHARSET_INFO *cs, date_mode_t mode); bool has_valid_mmssff() const { @@ -694,6 +772,67 @@ protected: { return year == 0 && month == 0 && day == 0; } + bool check_date(date_conv_mode_t flags, int *warn) const + { + return ::check_date(this, flags, warn); + } + void time_hhmmssff_set_max(ulong max_hour) + { + hour= max_hour; + minute= TIME_MAX_MINUTE; + second= TIME_MAX_SECOND; + second_part= TIME_MAX_SECOND_PART; + } + /* + Add nanoseconds to ssff + retval true if seconds overflowed (the caller should increment minutes) + false if no overflow happened + */ + bool add_nanoseconds_ssff(uint nanoseconds) + { + DBUG_ASSERT(nanoseconds <= 1000000000); + if (nanoseconds < 500) + return false; + second_part+= (nanoseconds + 500) / 1000; + if (second_part < 1000000) + return false; + second_part%= 1000000; + if (second < 59) + { + second++; + return false; + } + second= 0; + return true; + } + /* + Add nanoseconds to mmssff + retval true if hours overflowed (the caller should increment hours) + false if no overflow happened + */ + bool add_nanoseconds_mmssff(uint nanoseconds) + { + if (!add_nanoseconds_ssff(nanoseconds)) + return false; + if (minute < 59) + { + minute++; + return false; + } + minute= 0; + return true; + } + void time_round_or_set_max(uint dec, int *warn, ulong max_hour, ulong nsec); + bool datetime_add_nanoseconds_or_invalidate(THD *thd, int *warn, ulong nsec); + bool datetime_round_or_invalidate(THD *thd, uint dec, int *warn, ulong nsec); + bool add_nanoseconds_with_round(THD *thd, int *warn, + date_conv_mode_t mode, ulong nsec); + bool add_nanoseconds(THD *thd, int *warn, date_mode_t mode, ulong nsec) + { + date_conv_mode_t cmode= date_conv_mode_t(mode); + return time_round_mode_t(mode) == TIME_FRAC_ROUND ? + add_nanoseconds_with_round(thd, warn, cmode, nsec) : false; + } public: static void *operator new(size_t size, MYSQL_TIME *ltime) throw() { @@ -717,10 +856,28 @@ public: class Temporal_hybrid: public Temporal { public: + class Options: public Temporal::Options + { + public: + Options(THD *thd) + :Temporal::Options(sql_mode_for_dates(thd), default_round_mode(thd)) + { } + Options(date_conv_mode_t flags, time_round_mode_t round_mode) + :Temporal::Options(flags, round_mode) + { } + explicit Options(const Temporal::Options &opt) + :Temporal::Options(opt) + { } + explicit Options(date_mode_t fuzzydate) + :Temporal::Options(fuzzydate) + { } + }; + +public: // Contructors for Item Temporal_hybrid(THD *thd, Item *item, date_mode_t fuzzydate); Temporal_hybrid(THD *thd, Item *item) - :Temporal_hybrid(thd, item, sql_mode_for_dates(thd)) + :Temporal_hybrid(thd, item, Options(thd)) { } Temporal_hybrid(Item *item) :Temporal_hybrid(current_thd, item) @@ -964,14 +1121,20 @@ public: DBUG_ASSERT(fsp <= TIME_SECOND_PART_DIGITS); return max_int_part_char_length() + (fsp ? 1 : 0) + fsp; } + public: Interval_DDhhmmssff(THD *thd, Status *st, bool push_warnings, - Item *item, ulong max_hour); - Interval_DDhhmmssff(THD *thd, Item *item) + Item *item, ulong max_hour, + time_round_mode_t mode, uint dec); + Interval_DDhhmmssff(THD *thd, Item *item, uint dec) { Status st; - new(this) Interval_DDhhmmssff(thd, &st, true, item, max_useful_hour()); + new(this) Interval_DDhhmmssff(thd, &st, true, item, max_useful_hour(), + default_round_mode(thd), dec); } + Interval_DDhhmmssff(THD *thd, Item *item) + :Interval_DDhhmmssff(thd, item, TIME_SECOND_PART_DIGITS) + { } const MYSQL_TIME *get_mysql_time() const { DBUG_ASSERT(is_valid_interval_DDhhmmssff_slow()); @@ -1028,27 +1191,35 @@ public: DATETIME_TO_TIME_YYYYMMDD_00000000_ONLY, DATETIME_TO_TIME_MINUS_CURRENT_DATE }; - class Options + class Options: public Temporal::Options { - date_mode_t m_get_date_flags; datetime_to_time_mode_t m_datetime_to_time_mode; public: - Options() - :m_get_date_flags(flags_for_get_date()), - m_datetime_to_time_mode(DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS) + Options(THD *thd) + :Temporal::Options(default_flags_for_get_date(), default_round_mode(thd)), + m_datetime_to_time_mode(default_datetime_to_time_mode()) { } - Options(date_mode_t flags) - :m_get_date_flags(flags), - m_datetime_to_time_mode(DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS) + Options(date_conv_mode_t flags, THD *thd) + :Temporal::Options(flags, default_round_mode(thd)), + m_datetime_to_time_mode(default_datetime_to_time_mode()) { } - Options(date_mode_t flags, datetime_to_time_mode_t dtmode) - :m_get_date_flags(flags), + Options(date_conv_mode_t flags, THD *thd, datetime_to_time_mode_t dtmode) + :Temporal::Options(flags, default_round_mode(thd)), m_datetime_to_time_mode(dtmode) { } - date_mode_t get_date_flags() const - { return m_get_date_flags; } + Options(date_conv_mode_t fuzzydate, time_round_mode_t round_mode, + datetime_to_time_mode_t datetime_to_time_mode) + :Temporal::Options(fuzzydate, round_mode), + m_datetime_to_time_mode(datetime_to_time_mode) + { } + datetime_to_time_mode_t datetime_to_time_mode() const { return m_datetime_to_time_mode; } + + static datetime_to_time_mode_t default_datetime_to_time_mode() + { + return DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS; + } }; /* CAST(AS TIME) historically does not mix days to hours. @@ -1058,14 +1229,28 @@ public: class Options_for_cast: public Options { public: - Options_for_cast() - :Options(flags_for_get_date(), DATETIME_TO_TIME_YYYYMMDD_TRUNCATE) + Options_for_cast(THD *thd) + :Options(default_flags_for_get_date(), default_round_mode(thd), + DATETIME_TO_TIME_YYYYMMDD_TRUNCATE) { } - Options_for_cast(date_mode_t mode) - :Options(flags_for_get_date() | (mode & TIME_FUZZY_DATES), + Options_for_cast(date_mode_t mode, THD *thd) + :Options(default_flags_for_get_date() | (mode & TIME_FUZZY_DATES), + default_round_mode(thd), DATETIME_TO_TIME_YYYYMMDD_TRUNCATE) { } }; + + class Options_cmp: public Options + { + public: + Options_cmp(THD *thd) + :Options(comparison_flags_for_get_date(), thd) + { } + Options_cmp(THD *thd, datetime_to_time_mode_t dtmode) + :Options(comparison_flags_for_get_date(), + default_round_mode(thd), dtmode) + { } + }; private: bool is_valid_value_slow() const { @@ -1199,6 +1384,15 @@ private: time_type= MYSQL_TIMESTAMP_NONE; DBUG_ASSERT(is_valid_value_slow()); } +public: + void round_or_set_max(uint dec, int *warn, ulong nsec); +private: + void round_or_set_max(uint dec, int *warn); + + /* + All make_from_xxx() methods initialize *warn. + The old value gets lost. + */ void make_from_datetime_move_day_to_hour(int *warn, const MYSQL_TIME *from); void make_from_datetime_with_days_diff(int *warn, const MYSQL_TIME *from, long curdays); @@ -1213,7 +1407,7 @@ public: Time(int *warn, bool neg, ulonglong hour, uint minute, const Sec6 &second); Time() { time_type= MYSQL_TIMESTAMP_NONE; } Time(Item *item) - :Time(current_thd, item, Options()) + :Time(current_thd, item) { } Time(THD *thd, Item *item, const Options opt) { @@ -1221,18 +1415,18 @@ public: make_from_item(thd, &warn, item, opt); } Time(THD *thd, Item *item) - :Time(thd, item, Options()) + :Time(thd, item, Options(thd)) { } Time(int *warn, const MYSQL_TIME *from, long curdays); Time(THD *thd, MYSQL_TIME_STATUS *status, const char *str, size_t len, CHARSET_INFO *cs, const Options opt) { - if (str_to_datetime_or_date_or_time(status, str, len, cs, - opt.get_date_flags())) + if (str_to_datetime_or_date_or_time(thd, status, str, len, cs, opt)) time_type= MYSQL_TIMESTAMP_NONE; // The below call will optionally add notes to already collected warnings: - xxx_to_time_result_to_valid_value(thd, &status->warnings, opt); + else + xxx_to_time_result_to_valid_value(thd, &status->warnings, opt); } protected: @@ -1242,34 +1436,50 @@ protected: time_type= MYSQL_TIMESTAMP_NONE; xxx_to_time_result_to_valid_value(thd, warn, opt); } + Time(THD *thd, int *warn, const Sec9 &nr, const Options &opt) + :Time(thd, warn, static_cast<Sec6>(nr), opt) + { + if (is_valid_time() && time_round_mode_t(opt) == TIME_FRAC_ROUND) + round_or_set_max(6, warn, nr.nsec()); + } public: Time(THD *thd, int *warn, const Longlong_hybrid &nr, const Options &opt) :Time(thd, warn, Sec6(nr), opt) { } Time(THD *thd, int *warn, double nr, const Options &opt) - :Time(thd, warn, Sec6(nr), opt) + :Time(thd, warn, Sec9(nr), opt) { } Time(THD *thd, int *warn, const my_decimal *d, const Options &opt) - :Time(thd, warn, Sec6(d), opt) + :Time(thd, warn, Sec9(d), opt) { } Time(THD *thd, Item *item, const Options opt, uint dec) :Time(thd, item, opt) { - trunc(dec); + round(dec, time_round_mode_t(opt)); } - Time(int *warn, const MYSQL_TIME *from, long curdays, uint dec) + Time(int *warn, const MYSQL_TIME *from, long curdays, + const Time::Options &opt, uint dec) :Time(warn, from, curdays) { - trunc(dec); + round(dec, time_round_mode_t(opt), warn); + } + Time(int *warn, bool neg, ulonglong hour, uint minute, const Sec9 &second, + time_round_mode_t mode, uint dec) + :Time(warn, neg, hour, minute, second) + { + DBUG_ASSERT(is_valid_time()); + if ((ulonglong) mode == (ulonglong) TIME_FRAC_ROUND) + round_or_set_max(6, warn, second.nsec()); + round(dec, mode, warn); } Time(THD *thd, MYSQL_TIME_STATUS *status, const char *str, size_t len, CHARSET_INFO *cs, const Options &opt, uint dec) :Time(thd, status, str, len, cs, opt) { - trunc(dec); + round(dec, time_round_mode_t(opt), &status->warnings); } Time(THD *thd, int *warn, const Longlong_hybrid &nr, const Options &opt, uint dec) @@ -1278,23 +1488,24 @@ public: /* Decimal digit truncation is needed here in case if nr was out of the supported TIME range, so "this" was set to '838:59:59.999999'. + We always do truncation (not rounding) here, independently from "opt". */ trunc(dec); } Time(THD *thd, int *warn, double nr, const Options &opt, uint dec) :Time(thd, warn, nr, opt) { - trunc(dec); + round(dec, time_round_mode_t(opt), warn); } Time(THD *thd, int *warn, const my_decimal *d, const Options &opt, uint dec) :Time(thd, warn, d, opt) { - trunc(dec); + round(dec, time_round_mode_t(opt), warn); } - static date_mode_t flags_for_get_date() + static date_conv_mode_t default_flags_for_get_date() { return TIME_TIME_ONLY | TIME_INVALID_DATES; } - static date_mode_t comparison_flags_for_get_date() + static date_conv_mode_t comparison_flags_for_get_date() { return TIME_TIME_ONLY | TIME_INVALID_DATES | TIME_FUZZY_DATES; } bool is_valid_time() const { @@ -1367,6 +1578,12 @@ public: { return is_valid_time() ? Temporal::to_packed() : 0; } + long fraction_remainder(uint dec) const + { + DBUG_ASSERT(is_valid_time()); + return Temporal::fraction_remainder(dec); + } + Time &trunc(uint dec) { if (is_valid_time()) @@ -1374,6 +1591,32 @@ public: DBUG_ASSERT(is_valid_value_slow()); return *this; } + Time &round(uint dec, int *warn) + { + if (is_valid_time()) + round_or_set_max(dec, warn); + DBUG_ASSERT(is_valid_value_slow()); + return *this; + } + Time &round(uint dec, time_round_mode_t mode, int *warn) + { + switch (mode.mode()) { + case time_round_mode_t::FRAC_NONE: + DBUG_ASSERT(fraction_remainder(dec) == 0); + return trunc(dec); + case time_round_mode_t::FRAC_TRUNCATE: + return trunc(dec); + case time_round_mode_t::FRAC_ROUND: + return round(dec, warn); + } + return *this; + } + Time &round(uint dec, time_round_mode_t mode) + { + int warn= 0; + return round(dec, mode, &warn); + } + }; @@ -1402,10 +1645,23 @@ public: class Temporal_with_date: public Temporal { +public: + class Options: public Temporal::Options + { + public: + Options(date_conv_mode_t fuzzydate, time_round_mode_t mode): + Temporal::Options(fuzzydate, mode) + {} + explicit Options(const Temporal::Options &opt) + :Temporal::Options(opt) + { } + explicit Options(date_mode_t mode) + :Temporal::Options(mode) + { } + }; protected: - void check_date_or_invalidate(int *warn, date_mode_t flags); + void check_date_or_invalidate(int *warn, date_conv_mode_t flags); void make_from_item(THD *thd, Item *item, date_mode_t flags); - void make_from_item(THD *thd, Item *item); ulong daynr() const { @@ -1430,39 +1686,35 @@ protected: uint week= calc_week(this, week_behaviour, &year); return week + year * 100; } - +public: Temporal_with_date() { time_type= MYSQL_TIMESTAMP_NONE; } - Temporal_with_date(THD *thd, Item *item, date_mode_t flags) - { - make_from_item(thd, item, flags); - } - Temporal_with_date(THD *thd, Item *item) + Temporal_with_date(THD *thd, Item *item, date_mode_t fuzzydate) { - make_from_item(thd, item); + make_from_item(thd, item, fuzzydate); } Temporal_with_date(int *warn, const Sec6 &nr, date_mode_t flags) { DBUG_ASSERT(bool(flags & TIME_TIME_ONLY) == false); - if (nr.to_datetime_or_date(this, warn, flags)) + if (nr.to_datetime_or_date(this, warn, date_conv_mode_t(flags))) time_type= MYSQL_TIMESTAMP_NONE; } - Temporal_with_date(MYSQL_TIME_STATUS *status, + Temporal_with_date(THD *thd, MYSQL_TIME_STATUS *status, const char *str, size_t len, CHARSET_INFO *cs, date_mode_t flags) { DBUG_ASSERT(bool(flags & TIME_TIME_ONLY) == false); - if (str_to_datetime_or_date(status, str, len, cs, flags)) + if (str_to_datetime_or_date(thd, status, str, len, cs, flags)) time_type= MYSQL_TIMESTAMP_NONE; } public: - bool check_date_with_warn(THD *thd, date_mode_t flags) + bool check_date_with_warn(THD *thd, date_conv_mode_t flags) { return ::check_date_with_warn(thd, this, flags, MYSQL_TIMESTAMP_ERROR); } - static date_mode_t comparison_flags_for_get_date() + static date_conv_mode_t comparison_flags_for_get_date() { return TIME_INVALID_DATES | TIME_FUZZY_DATES; } }; @@ -1488,22 +1740,41 @@ class Date: public Temporal_with_date return !check_datetime_range(this); } public: - Date(THD *thd, Item *item, date_mode_t flags) - :Temporal_with_date(thd, item, flags) + class Options: public Temporal_with_date::Options { - if (time_type == MYSQL_TIMESTAMP_DATETIME) - datetime_to_date(this); - DBUG_ASSERT(is_valid_value_slow()); - } - Date(THD *thd, Item *item) - :Temporal_with_date(thd, item) + public: + explicit Options(date_conv_mode_t fuzzydate) + :Temporal_with_date::Options(fuzzydate, TIME_FRAC_TRUNCATE) + { } + Options(THD *thd, time_round_mode_t mode) + :Temporal_with_date::Options(sql_mode_for_dates(thd), mode) + { } + explicit Options(THD *thd) + :Temporal_with_date::Options(sql_mode_for_dates(thd), TIME_FRAC_TRUNCATE) + { } + explicit Options(date_mode_t fuzzydate) + :Temporal_with_date::Options(fuzzydate) + { } + }; +public: + Date(Item *item, date_mode_t fuzzydate) + :Date(current_thd, item, fuzzydate) + { } + Date(THD *thd, Item *item, date_mode_t fuzzydate) + :Temporal_with_date(thd, item, fuzzydate) { if (time_type == MYSQL_TIMESTAMP_DATETIME) datetime_to_date(this); DBUG_ASSERT(is_valid_value_slow()); } + Date(THD *thd, Item *item, date_conv_mode_t fuzzydate) + :Date(thd, item, Options(fuzzydate)) + { } + Date(THD *thd, Item *item) + :Temporal_with_date(Date(thd, item, Options(thd, TIME_FRAC_TRUNCATE))) + { } Date(Item *item) - :Date(current_thd, item) + :Temporal_with_date(Date(current_thd, item)) { } Date(const Temporal_with_date *d) :Temporal_with_date(*d) @@ -1603,98 +1874,141 @@ class Datetime: public Temporal_with_date DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATETIME); return !check_datetime_range(this); } + bool add_nanoseconds_or_invalidate(THD *thd, int *warn, ulong nsec) + { + DBUG_ASSERT(is_valid_datetime_slow()); + bool rc= Temporal::datetime_add_nanoseconds_or_invalidate(thd, warn, nsec); + DBUG_ASSERT(is_valid_value_slow()); + return rc; + } void date_to_datetime_if_needed() { if (time_type == MYSQL_TIMESTAMP_DATE) date_to_datetime(this); } void make_from_time(THD *thd, int *warn, const MYSQL_TIME *from, - date_mode_t flags); + date_conv_mode_t flags); void make_from_datetime(THD *thd, int *warn, const MYSQL_TIME *from, - date_mode_t flags); -public: - Datetime(THD *thd, Item *item, date_mode_t flags) - :Temporal_with_date(thd, item, flags) + date_conv_mode_t flags); + bool round_or_invalidate(THD *thd, uint dec, int *warn); + bool round_or_invalidate(THD *thd, uint dec, int *warn, ulong nsec) { - date_to_datetime_if_needed(); + DBUG_ASSERT(is_valid_datetime_slow()); + bool rc= Temporal::datetime_round_or_invalidate(thd, dec, warn, nsec); DBUG_ASSERT(is_valid_value_slow()); + return rc; } - Datetime(THD *thd, Item *item) - :Temporal_with_date(thd, item) +public: + + class Options: public Temporal_with_date::Options + { + public: + Options(date_conv_mode_t fuzzydate, time_round_mode_t nanosecond_rounding) + :Temporal_with_date::Options(fuzzydate, nanosecond_rounding) + { } + Options(THD *thd) + :Temporal_with_date::Options(sql_mode_for_dates(thd), default_round_mode(thd)) + { } + Options(THD *thd, time_round_mode_t rounding_mode) + :Temporal_with_date::Options(sql_mode_for_dates(thd), rounding_mode) + { } + Options(date_conv_mode_t fuzzydate, THD *thd) + :Temporal_with_date::Options(fuzzydate, default_round_mode(thd)) + { } + }; + + class Options_cmp: public Options + { + public: + Options_cmp(THD *thd) + :Options(comparison_flags_for_get_date(), thd) + { } + }; + +public: + Datetime(THD *thd, Item *item, date_mode_t fuzzydate) + :Temporal_with_date(thd, item, fuzzydate) { date_to_datetime_if_needed(); DBUG_ASSERT(is_valid_value_slow()); } + Datetime(THD *thd, Item *item) + :Temporal_with_date(Datetime(thd, item, Options(thd))) + { } Datetime(Item *item) :Datetime(current_thd, item) { } - Datetime(THD *thd, int *warn, const MYSQL_TIME *from, date_mode_t flags); + + Datetime(THD *thd, int *warn, const MYSQL_TIME *from, date_conv_mode_t flags); Datetime() { set_zero_time(this, MYSQL_TIMESTAMP_DATETIME); } - Datetime(MYSQL_TIME_STATUS *status, + Datetime(THD *thd, MYSQL_TIME_STATUS *status, const char *str, size_t len, CHARSET_INFO *cs, - date_mode_t flags) - :Temporal_with_date(status, str, len, cs, flags) + const date_mode_t fuzzydate) + :Temporal_with_date(thd, status, str, len, cs, fuzzydate) { date_to_datetime_if_needed(); DBUG_ASSERT(is_valid_value_slow()); } protected: - Datetime(int *warn, const Sec6 &nr, date_mode_t flags) + Datetime(THD *thd, int *warn, const Sec6 &nr, date_mode_t flags) :Temporal_with_date(warn, nr, flags) { date_to_datetime_if_needed(); DBUG_ASSERT(is_valid_value_slow()); } + Datetime(THD *thd, int *warn, const Sec9 &nr, date_mode_t fuzzydate) + :Datetime(thd, warn, static_cast<const Sec6>(nr), fuzzydate) + { + if (is_valid_datetime() && + time_round_mode_t(fuzzydate) == TIME_FRAC_ROUND) + round_or_invalidate(thd, 6, warn, nr.nsec()); + DBUG_ASSERT(is_valid_value_slow()); + } public: - Datetime(int *warn, const Longlong_hybrid &nr, date_mode_t mode) - :Datetime(warn, Sec6(nr), mode) + Datetime(THD *thd, int *warn, const Longlong_hybrid &nr, date_mode_t mode) + :Datetime(thd, warn, Sec6(nr), mode) { } - Datetime(int *warn, double nr, date_mode_t fuzzydate) - :Datetime(warn, Sec6(nr), fuzzydate) + Datetime(THD *thd, int *warn, double nr, date_mode_t fuzzydate) + :Datetime(thd, warn, Sec9(nr), fuzzydate) { } - Datetime(int *warn, const my_decimal *d, date_mode_t fuzzydate) - :Datetime(warn, Sec6(d), fuzzydate) + Datetime(THD *thd, int *warn, const my_decimal *d, date_mode_t fuzzydate) + :Datetime(thd, warn, Sec9(d), fuzzydate) { } Datetime(THD *thd, const timeval &tv); - Datetime(THD *thd, Item *item, date_mode_t flags, uint dec) - :Datetime(thd, item, flags) + Datetime(THD *thd, Item *item, date_mode_t fuzzydate, uint dec) + :Datetime(thd, item, fuzzydate) { - trunc(dec); + int warn= 0; + round(thd, dec, time_round_mode_t(fuzzydate), &warn); } - Datetime(MYSQL_TIME_STATUS *status, + Datetime(THD *thd, MYSQL_TIME_STATUS *status, const char *str, size_t len, CHARSET_INFO *cs, date_mode_t fuzzydate, uint dec) - :Datetime(status, str, len, cs, fuzzydate) + :Datetime(thd, status, str, len, cs, fuzzydate) { - trunc(dec); + round(thd, dec, time_round_mode_t(fuzzydate), &status->warnings); } - Datetime(int *warn, double nr, date_mode_t fuzzydate, uint dec) - :Datetime(warn, nr, fuzzydate) + Datetime(THD *thd, int *warn, double nr, date_mode_t fuzzydate, uint dec) + :Datetime(thd, warn, nr, fuzzydate) { - trunc(dec); + round(thd, dec, time_round_mode_t(fuzzydate), warn); } - Datetime(int *warn, const my_decimal *d, date_mode_t fuzzydate, uint dec) - :Datetime(warn, d, fuzzydate) + Datetime(THD *thd, int *warn, const my_decimal *d, date_mode_t fuzzydate, uint dec) + :Datetime(thd, warn, d, fuzzydate) { - trunc(dec); + round(thd, dec, time_round_mode_t(fuzzydate), warn); } Datetime(THD *thd, int *warn, const MYSQL_TIME *from, date_mode_t fuzzydate, uint dec) - :Datetime(thd, warn, from, fuzzydate) - { - trunc(dec); - } - Datetime(THD *thd, const timeval &tv, uint dec) - :Datetime(thd, tv) + :Datetime(thd, warn, from, date_conv_mode_t(fuzzydate) & ~TIME_TIME_ONLY) { - DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); - trunc(dec); + round(thd, dec, time_round_mode_t(fuzzydate), warn); } bool is_valid_datetime() const @@ -1706,14 +2020,14 @@ public: DBUG_ASSERT(is_valid_value_slow()); return time_type == MYSQL_TIMESTAMP_DATETIME; } - bool check_date(date_mode_t flags, int *warnings) const + bool check_date(date_conv_mode_t flags, int *warnings) const { DBUG_ASSERT(is_valid_datetime_slow()); return ::check_date(this, (year || month || day), ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), warnings); } - bool check_date(date_mode_t flags) const + bool check_date(date_conv_mode_t flags) const { int dummy; /* unused */ return check_date(flags, &dummy); @@ -1728,6 +2042,27 @@ public: DBUG_ASSERT(is_valid_datetime_slow()); return Temporal_with_date::daynr(); } + ulong dayofyear() const + { + DBUG_ASSERT(is_valid_datetime_slow()); + return Temporal_with_date::dayofyear(); + } + uint quarter() const + { + DBUG_ASSERT(is_valid_datetime_slow()); + return Temporal_with_date::quarter(); + } + uint week(uint week_behaviour) const + { + DBUG_ASSERT(is_valid_datetime_slow()); + return Temporal_with_date::week(week_behaviour); + } + uint yearweek(uint week_behaviour) const + { + DBUG_ASSERT(is_valid_datetime_slow()); + return Temporal_with_date::yearweek(week_behaviour); + } + longlong hhmmss_to_seconds_abs() const { DBUG_ASSERT(is_valid_datetime_slow()); @@ -1800,6 +2135,12 @@ public: { return is_valid_datetime() ? Temporal::to_packed() : 0; } + long fraction_remainder(uint dec) const + { + DBUG_ASSERT(is_valid_datetime()); + return Temporal::fraction_remainder(dec); + } + Datetime &trunc(uint dec) { if (is_valid_datetime()) @@ -1807,21 +2148,129 @@ public: DBUG_ASSERT(is_valid_value_slow()); return *this; } + Datetime &round(THD *thd, uint dec, int *warn) + { + if (is_valid_datetime()) + round_or_invalidate(thd, dec, warn); + DBUG_ASSERT(is_valid_value_slow()); + return *this; + } + Datetime &round(THD *thd, uint dec, time_round_mode_t mode, int *warn) + { + switch (mode.mode()) { + case time_round_mode_t::FRAC_NONE: + DBUG_ASSERT(fraction_remainder(dec) == 0); + return trunc(dec); + case time_round_mode_t::FRAC_TRUNCATE: + return trunc(dec); + case time_round_mode_t::FRAC_ROUND: + return round(thd, dec, warn); + } + return *this; + } + Datetime &round(THD *thd, uint dec, time_round_mode_t mode) + { + int warn= 0; + return round(thd, dec, mode, &warn); + } + +}; + + +/* + Datetime to be created from an Item who is known to be of a temporal + data type. For temporal data types we don't need nanosecond rounding + or truncation, as their precision is limited. +*/ +class Datetime_from_temporal: public Datetime +{ +public: + // The constructor DBUG_ASSERTs on a proper Item data type. + Datetime_from_temporal(THD *thd, Item *temporal, date_conv_mode_t flags); +}; + + +/* + Datetime to be created from an Item who is known not to have digits outside + of the specified scale. So it's not important which rounding method to use. + TRUNCATE should work. + Typically, Item is of a temporal data type, but this is not strictly required. +*/ +class Datetime_truncation_not_needed: public Datetime +{ +public: + Datetime_truncation_not_needed(THD *thd, Item *item, date_conv_mode_t mode); + Datetime_truncation_not_needed(THD *thd, Item *item, date_mode_t mode) + :Datetime_truncation_not_needed(thd, item, date_conv_mode_t(mode)) + { } }; class Timestamp: protected Timeval { +protected: + void round_or_set_max(uint dec, int *warn); + bool add_nanoseconds_usec(uint nanoseconds) + { + DBUG_ASSERT(nanoseconds <= 1000000000); + if (nanoseconds < 500) + return false; + tv_usec+= (nanoseconds + 500) / 1000; + if (tv_usec < 1000000) + return false; + tv_usec%= 1000000; + return true; + } +public: + static date_conv_mode_t sql_mode_for_timestamp(THD *thd); + static time_round_mode_t default_round_mode(THD *thd); + class DatetimeOptions: public date_mode_t + { + public: + DatetimeOptions(date_conv_mode_t fuzzydate, time_round_mode_t round_mode) + :date_mode_t(fuzzydate | round_mode) + { } + DatetimeOptions(THD *thd) + :DatetimeOptions(sql_mode_for_timestamp(thd), default_round_mode(thd)) + { } + }; public: Timestamp(my_time_t timestamp, ulong sec_part) :Timeval(timestamp, sec_part) { } const struct timeval &tv() const { return *this; } + long fraction_remainder(uint dec) const + { + return my_time_fraction_remainder(tv_usec, dec); + } Timestamp &trunc(uint dec) { my_timeval_trunc(this, dec); return *this; } + Timestamp &round(uint dec, int *warn) + { + round_or_set_max(dec, warn); + return *this; + } + Timestamp &round(uint dec, time_round_mode_t mode, int *warn) + { + switch (mode.mode()) { + case time_round_mode_t::FRAC_NONE: + DBUG_ASSERT(fraction_remainder(dec) == 0); + return trunc(dec); + case time_round_mode_t::FRAC_TRUNCATE: + return trunc(dec); + case time_round_mode_t::FRAC_ROUND: + return round(dec, warn); + } + return *this; + } + Timestamp &round(uint dec, time_round_mode_t mode) + { + int warn= 0; + return round(dec, mode, &warn); + } }; diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 9a036156de6..aee4869bd40 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -76,6 +76,8 @@ static const char *init_syms(udf_func *tmp, char *nm) (void)strmov(end, "_add"); if (!((tmp->func_add= (Udf_func_add) dlsym(tmp->dlhandle, nm)))) return nm; + (void)strmov(end, "_remove"); + tmp->func_remove= (Udf_func_add) dlsym(tmp->dlhandle, nm); } (void) strmov(end,"_deinit"); @@ -565,6 +567,7 @@ int mysql_create_function(THD *thd,udf_func *udf) u_d->func_deinit= udf->func_deinit; u_d->func_clear= udf->func_clear; u_d->func_add= udf->func_add; + u_d->func_remove= udf->func_remove; /* create entry in mysql.func table */ diff --git a/sql/sql_udf.h b/sql/sql_udf.h index 6e6fed2a81a..4fa75759269 100644 --- a/sql/sql_udf.h +++ b/sql/sql_udf.h @@ -47,6 +47,7 @@ typedef struct st_udf_func Udf_func_deinit func_deinit; Udf_func_clear func_clear; Udf_func_add func_add; + Udf_func_add func_remove; ulong usage_count; } udf_func; @@ -131,6 +132,20 @@ class udf_handler :public Sql_alloc func(&initid, &f_args, &is_null, &error); *null_value= (my_bool) (is_null || error); } + bool supports_removal() const + { return MY_TEST(u_d->func_remove); } + void remove(my_bool *null_value) + { + DBUG_ASSERT(u_d->func_remove); + if (get_arguments()) + { + *null_value=1; + return; + } + Udf_func_add func= u_d->func_remove; + func(&initid, &f_args, &is_null, &error); + *null_value= (my_bool) (is_null || error); + } String *val_str(String *str,String *save_str); }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b2f1131f594..1d9fde183cd 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -11350,6 +11350,21 @@ window_func: { ((Item_sum *) $1)->mark_as_window_func_sum_expr(); } + | + function_call_generic + { + Item* item = (Item*)$1; + /* Only UDF aggregate here possible */ + if ((item == NULL) || + (item->type() != Item::SUM_FUNC_ITEM) + || (((Item_sum *)item)->sum_func() != Item_sum::UDF_SUM_FUNC)) + { + thd->parse_error(); + MYSQL_YYABORT; + } + + ((Item_sum *) $1)->mark_as_window_func_sum_expr(); + } ; simple_window_func: diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index e17e959d1e5..843309ad1a9 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -11384,6 +11384,21 @@ window_func: { ((Item_sum *) $1)->mark_as_window_func_sum_expr(); } + | + function_call_generic + { + Item* item = (Item*)$1; + /* Only UDF aggregate here possible */ + if ((item == NULL) || + (item->type() != Item::SUM_FUNC_ITEM) + || (((Item_sum *)item)->sum_func() != Item_sum::UDF_SUM_FUNC)) + { + thd->parse_error(); + MYSQL_YYABORT; + } + + ((Item_sum *) $1)->mark_as_window_func_sum_expr(); + } ; simple_window_func: diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 92c7d329bb9..3a4871875e5 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3353,6 +3353,7 @@ static const char *sql_mode_names[]= "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO", "TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE", "NO_ENGINE_SUBSTITUTION", "PAD_CHAR_TO_FULL_LENGTH", "EMPTY_STRING_IS_NULL", "SIMULTANEOUS_ASSIGNMENT", + "TIME_ROUND_FRACTIONAL", 0 }; diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic index dbc3565e202..1c41cc22411 100644 --- a/sql/sys_vars.ic +++ b/sql/sys_vars.ic @@ -2659,7 +2659,8 @@ public: if (!Sys_var_enum::do_check(thd, var)) return false; MYSQL_TIME ltime; - bool res= var->value->get_date(thd, <ime, date_mode_t(0)); + Datetime::Options opt(TIME_CONV_NONE, thd); + bool res= var->value->get_date(thd, <ime, opt); if (!res) { var->save_result.ulonglong_value= SYSTEM_TIME_AS_OF; @@ -2676,7 +2677,9 @@ private: { if (var->value) { - res= var->value->get_date(current_thd, &out.ltime, date_mode_t(0)); + THD *thd= current_thd; + Datetime::Options opt(TIME_CONV_NONE, thd); + res= var->value->get_date(thd, &out.ltime, opt); } else // set DEFAULT from global var { diff --git a/sql/table.cc b/sql/table.cc index 6fed129f7e8..8630320090f 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3958,6 +3958,7 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table) create_info->table_options= share->db_create_options; create_info->avg_row_length= share->avg_row_length; create_info->row_type= share->row_type; + create_info->key_block_size= share->key_block_size; create_info->default_table_charset= share->table_charset; create_info->table_charset= 0; create_info->comment= share->comment; diff --git a/sql/udf_example.c b/sql/udf_example.c index 6db2b5e737a..bdc995b51fc 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -173,6 +173,13 @@ void avgcost_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error void avgcost_clear( UDF_INIT* initid, char* is_null, char *error ); void avgcost_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); double avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); +my_bool avg2_init( UDF_INIT* initid, UDF_ARGS* args, char* message ); +void avg2_deinit( UDF_INIT* initid ); +void avg2_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); +void avg2_clear( UDF_INIT* initid, char* is_null, char *error ); +void avg2_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); +void avg2_remove( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); +double avg2( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message); char *is_const(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error); @@ -1049,6 +1056,138 @@ avgcost( UDF_INIT* initid, UDF_ARGS* args __attribute__((unused)), return data->totalprice/(double)data->totalquantity; } + +/* +** Average 2 (number, sum)*/ +struct avg2_data +{ + ulonglong count; + double sum; +}; + + +my_bool +avg2_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) +{ + struct avg2_data* data; + + if (args->arg_count != 2) + { + strcpy( + message, + "wrong number of arguments: AVG2() requires two arguments" + ); + return 1; + } + + if ((args->arg_type[0] != INT_RESULT) || (args->arg_type[1] != REAL_RESULT) ) + { + strcpy( + message, + "wrong argument type: AVG2() requires an INT and a REAL" + ); + return 1; + } + + /* + ** force arguments to double. + */ + /*args->arg_type[0] = REAL_RESULT; + args->arg_type[1] = REAL_RESULT;*/ + + initid->maybe_null = 0; /* The result may be null */ + initid->decimals = 4; /* We want 4 decimals in the result */ + initid->max_length = 20; /* 6 digits + . + 10 decimals */ + + if (!(data = (struct avg2_data*) malloc(sizeof(struct avg2_data)))) + { + strmov(message,"Couldn't allocate memory"); + return 1; + } + data->count = 0; + data->sum = 0.0; + + initid->ptr = (char*)data; + + return 0; +} + +void +avg2_deinit( UDF_INIT* initid ) +{ + free(initid->ptr); +} + + +/* This is only for MySQL 4.0 compability */ +void +avg2_reset(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* message) +{ + avgcost_clear(initid, is_null, message); + avgcost_add(initid, args, is_null, message); +} + +/* This is needed to get things to work in MySQL 4.1.1 and above */ + +void +avg2_clear(UDF_INIT* initid, char* is_null __attribute__((unused)), + char* message __attribute__((unused))) +{ + struct avg2_data* data = (struct avg2_data*)initid->ptr; + data->sum= 0.0; + data->count= 0; +} + + +void +avg2_add(UDF_INIT* initid, UDF_ARGS* args, + char* is_null __attribute__((unused)), + char* message __attribute__((unused))) +{ + if (args->args[0] && args->args[1]) + { + struct avg2_data* data = (struct avg2_data*)initid->ptr; + longlong quantity = *((longlong*)args->args[0]); + double sum = *((double*)args->args[1]); + + data->count += quantity; + data->sum += sum; + } +} + + +void +avg2_remove(UDF_INIT* initid, UDF_ARGS* args, + char* is_null __attribute__((unused)), + char* message __attribute__((unused))) +{ + if (args->args[0] && args->args[1]) + { + struct avg2_data* data = (struct avg2_data*)initid->ptr; + longlong quantity = *((longlong*)args->args[0]); + double sum = *((double*)args->args[1]); + + data->count -= quantity; + data->sum -= sum; + } +} + + +double +avg2( UDF_INIT* initid, UDF_ARGS* args __attribute__((unused)), + char* is_null, char* error __attribute__((unused))) +{ + struct avg2_data* data = (struct avg2_data*)initid->ptr; + if (!data->count) + { + *is_null = 1; + return 0.0; + } + + *is_null = 0; + return data->sum/(double)data->count; +} + my_bool myfunc_argument_name_init(UDF_INIT *initid, UDF_ARGS *args, char *message); char *myfunc_argument_name(UDF_INIT *initid, UDF_ARGS *args, char *result, diff --git a/sql/udf_example.def b/sql/udf_example.def index 74230b638bf..903c2b74893 100644 --- a/sql/udf_example.def +++ b/sql/udf_example.def @@ -23,6 +23,13 @@ EXPORTS avgcost_add avgcost_clear avgcost + avg2_init + avg2_deinit + avg2_reset + avg2_add + avg2_remove + avg2_clear + avg2 is_const is_const_init check_const_len diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index bc52bff0de9..833a39cb027 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2262,7 +2262,7 @@ int wsrep_wait_committing_connections_close(int wait_time) } -void wsrep_close_client_connections(my_bool wait_to_end) +void wsrep_close_client_connections(my_bool wait_to_end, THD *except_caller_thd) { /* First signal all threads that it's time to die @@ -2284,6 +2284,12 @@ void wsrep_close_client_connections(my_bool wait_to_end) if (!is_client_connection(tmp)) continue; + if (tmp == except_caller_thd) + { + DBUG_ASSERT(is_client_connection(tmp)); + continue; + } + if (is_replaying_connection(tmp)) { tmp->set_killed(KILL_CONNECTION); @@ -2295,7 +2301,16 @@ void wsrep_close_client_connections(my_bool wait_to_end) continue; WSREP_DEBUG("closing connection %lld", (longlong) tmp->thread_id); - wsrep_close_thread(tmp); + + /* + instead of wsrep_close_thread() we do now soft kill by THD::awake + */ + mysql_mutex_lock(&tmp->LOCK_thd_data); + + tmp->awake(KILL_CONNECTION); + + mysql_mutex_unlock(&tmp->LOCK_thd_data); + } mysql_mutex_unlock(&LOCK_thread_count); @@ -2313,7 +2328,8 @@ void wsrep_close_client_connections(my_bool wait_to_end) #ifndef __bsdi__ // Bug in BSDI kernel if (is_client_connection(tmp) && !abort_replicated(tmp) && - !is_replaying_connection(tmp)) + !is_replaying_connection(tmp) && + tmp != except_caller_thd) { WSREP_INFO("killing local connection: %lld", (longlong) tmp->thread_id); close_connection(tmp,0); diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 819a56b9f23..b434c248347 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -160,7 +160,6 @@ extern "C" query_id_t wsrep_thd_query_id(THD *thd); extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); -extern void wsrep_close_client_connections(my_bool wait_to_end); extern int wsrep_wait_committing_connections_close(int wait_time); extern void wsrep_close_applier(THD *thd); extern void wsrep_wait_appliers_close(THD *thd); @@ -308,7 +307,8 @@ void thd_binlog_trx_reset(THD * thd); typedef void (*wsrep_thd_processor_fun)(THD *); pthread_handler_t start_wsrep_THD(void *arg); int wsrep_wait_committing_connections_close(int wait_time); -void wsrep_close_client_connections(my_bool wait_to_end); +extern void wsrep_close_client_connections(my_bool wait_to_end, + THD *except_caller_thd = NULL); void wsrep_close_applier(THD *thd); void wsrep_close_applier_threads(int count); void wsrep_wait_appliers_close(THD *thd); diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index f8a494416e2..1471ad91a96 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -428,7 +428,8 @@ bool wsrep_reject_queries_update(sys_var *self, THD* thd, enum_var_type type) WSREP_INFO("Rejecting client queries due to manual setting"); break; case WSREP_REJECT_ALL_KILL: - wsrep_close_client_connections(FALSE); + /* close all client connections, but this one */ + wsrep_close_client_connections(FALSE, thd); WSREP_INFO("Rejecting client queries and killing connections due to manual setting"); break; default: diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index f1650aaef34..4bce7495b0c 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -225,7 +225,7 @@ btr_root_block_get( } buf_block_t* block = btr_block_get( - page_id_t(index->table->space->id, index->page), + page_id_t(index->table->space_id, index->page), page_size_t(index->table->space->flags), mode, index, mtr); @@ -250,9 +250,9 @@ btr_root_block_get( const page_t* root = buf_block_get_frame(block); ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF - + root, index->table->space->id)); + + root, index->table->space_id)); ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP - + root, index->table->space->id)); + + root, index->table->space_id)); } #endif /* UNIV_BTR_DEBUG */ @@ -363,7 +363,7 @@ btr_root_adjust_on_import( buf_block_t* block; page_zip_des_t* page_zip; dict_table_t* table = index->table; - const page_id_t page_id(table->space->id, index->page); + const page_id_t page_id(table->space_id, index->page); const page_size_t page_size(table->space->flags); DBUG_EXECUTE_IF("ib_import_trigger_corruption_3", @@ -405,10 +405,10 @@ btr_root_adjust_on_import( if (err == DB_SUCCESS && (!btr_root_fseg_adjust_on_import( FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF - + page, page_zip, table->space->id, &mtr) + + page, page_zip, table->space_id, &mtr) || !btr_root_fseg_adjust_on_import( FIL_PAGE_DATA + PAGE_BTR_SEG_TOP - + page, page_zip, table->space->id, &mtr))) { + + page, page_zip, table->space_id, &mtr))) { err = DB_CORRUPTION; } @@ -477,7 +477,7 @@ btr_page_alloc_for_ibuf( ut_a(node_addr.page != FIL_NULL); new_block = buf_page_get( - page_id_t(index->table->space->id, node_addr.page), + page_id_t(index->table->space_id, node_addr.page), page_size_t(index->table->space->flags), RW_X_LATCH, mtr); @@ -930,11 +930,11 @@ btr_node_ptr_get_child( mtr_t* mtr) /*!< in: mtr */ { ut_ad(rec_offs_validate(node_ptr, index, offsets)); - ut_ad(index->table->space->id + ut_ad(index->table->space_id == page_get_space_id(page_align(node_ptr))); return btr_block_get( - page_id_t(index->table->space->id, + page_id_t(index->table->space_id, btr_node_ptr_get_child_page_no(node_ptr, offsets)), page_size_t(index->table->space->flags), RW_SX_LATCH, index, mtr); @@ -1448,7 +1448,7 @@ btr_read_autoinc(dict_index_t* index) mtr.start(); ib_uint64_t autoinc; if (buf_block_t* block = buf_page_get( - page_id_t(index->table->space->id, index->page), + page_id_t(index->table->space_id, index->page), page_size_t(index->table->space->flags), RW_S_LATCH, &mtr)) { autoinc = page_get_autoinc(block->frame); @@ -1480,7 +1480,7 @@ btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no) mtr_t mtr; mtr.start(); buf_block_t* block = buf_page_get( - page_id_t(index->table->space->id, index->page), + page_id_t(index->table->space_id, index->page), page_size_t(index->table->space->flags), RW_S_LATCH, &mtr); @@ -2031,7 +2031,7 @@ btr_root_raise_and_insert( #endif /* UNIV_ZIP_DEBUG */ #ifdef UNIV_BTR_DEBUG if (!dict_index_is_ibuf(index)) { - ulint space = index->table->space->id; + ulint space = index->table->space_id; ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF + root, space)); @@ -3981,7 +3981,7 @@ retry: btr_search_drop_page_hash_index(block); /* Remove the page from the level list */ - btr_level_list_remove(index->table->space->id, + btr_level_list_remove(index->table->space_id, page_size, page, index, mtr); if (dict_index_is_spatial(index)) { @@ -4111,7 +4111,7 @@ retry: #endif /* UNIV_BTR_DEBUG */ /* Remove the page from the level list */ - btr_level_list_remove(index->table->space->id, + btr_level_list_remove(index->table->space_id, page_size, page, index, mtr); ut_ad(btr_node_ptr_get_child_page_no( @@ -4352,7 +4352,7 @@ btr_discard_only_page_on_level( #ifdef UNIV_BTR_DEBUG if (!dict_index_is_ibuf(index)) { const page_t* root = buf_block_get_frame(block); - const ulint space = index->table->space->id; + const ulint space = index->table->space_id; ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF + root, space)); ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP @@ -4463,7 +4463,7 @@ btr_discard_page( if (left_page_no != FIL_NULL) { merge_block = btr_block_get( - page_id_t(index->table->space->id, left_page_no), + page_id_t(index->table->space_id, left_page_no), page_size, RW_X_LATCH, index, mtr); merge_page = buf_block_get_frame(merge_block); @@ -4479,7 +4479,7 @@ btr_discard_page( == btr_cur_get_rec(&parent_cursor))); } else if (right_page_no != FIL_NULL) { merge_block = btr_block_get( - page_id_t(index->table->space->id, right_page_no), + page_id_t(index->table->space_id, right_page_no), page_size, RW_X_LATCH, index, mtr); merge_page = buf_block_get_frame(merge_block); @@ -4528,7 +4528,7 @@ btr_discard_page( } /* Remove the page from the level list */ - btr_level_list_remove(index->table->space->id, page_size, + btr_level_list_remove(index->table->space_id, page_size, page, index, mtr); #ifdef UNIV_ZIP_DEBUG @@ -5121,7 +5121,7 @@ btr_validate_level( ret = false; } - ut_a(index->table->space->id == block->page.id.space()); + ut_a(index->table->space_id == block->page.id.space()); ut_a(block->page.id.space() == page_get_space_id(page)); #ifdef UNIV_ZIP_DEBUG page_zip = buf_block_get_page_zip(block); @@ -5159,7 +5159,7 @@ btr_validate_level( savepoint2 = mtr_set_savepoint(&mtr); block = btr_block_get( - page_id_t(index->table->space->id, + page_id_t(index->table->space_id, left_page_no), table_page_size, RW_SX_LATCH, index, &mtr); @@ -5188,7 +5188,7 @@ loop: ut_a(!page_zip || page_zip_validate(page_zip, page, index)); #endif /* UNIV_ZIP_DEBUG */ - ut_a(block->page.id.space() == index->table->space->id); + ut_a(block->page.id.space() == index->table->space_id); if (fseg_page_is_free(space, block->page.id.page_no())) { @@ -5231,7 +5231,7 @@ loop: savepoint = mtr_set_savepoint(&mtr); right_block = btr_block_get( - page_id_t(index->table->space->id, right_page_no), + page_id_t(index->table->space_id, right_page_no), table_page_size, RW_SX_LATCH, index, &mtr); @@ -5417,13 +5417,13 @@ loop: &mtr, savepoint, right_block); btr_block_get( - page_id_t(index->table->space->id, + page_id_t(index->table->space_id, parent_right_page_no), table_page_size, RW_SX_LATCH, index, &mtr); right_block = btr_block_get( - page_id_t(index->table->space->id, + page_id_t(index->table->space_id, right_page_no), table_page_size, RW_SX_LATCH, index, &mtr); @@ -5501,14 +5501,14 @@ node_ptr_fails: if (parent_right_page_no != FIL_NULL) { btr_block_get( page_id_t( - index->table->space->id, + index->table->space_id, parent_right_page_no), table_page_size, RW_SX_LATCH, index, &mtr); } } else if (parent_page_no != FIL_NULL) { btr_block_get( - page_id_t(index->table->space->id, + page_id_t(index->table->space_id, parent_page_no), table_page_size, RW_SX_LATCH, index, &mtr); @@ -5516,7 +5516,7 @@ node_ptr_fails: } block = btr_block_get( - page_id_t(index->table->space->id, right_page_no), + page_id_t(index->table->space_id, right_page_no), table_page_size, RW_SX_LATCH, index, &mtr); @@ -5662,7 +5662,7 @@ btr_can_merge_with_page( index = btr_cur_get_index(cursor); page = btr_cur_get_page(cursor); - const page_id_t page_id(index->table->space->id, page_no); + const page_id_t page_id(index->table->space_id, page_no); const page_size_t page_size(index->table->space->flags); mblock = btr_block_get(page_id, page_size, RW_X_LATCH, index, mtr); diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 2b4bd842fa6..f4e0242958a 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -120,7 +120,7 @@ PageBulk::init() } } else { new_block = btr_block_get( - page_id_t(m_index->table->space->id, m_page_no), + page_id_t(m_index->table->space_id, m_page_no), page_size_t(m_index->table->space->flags), RW_X_LATCH, m_index, &m_mtr); @@ -669,7 +669,7 @@ PageBulk::latch() if (!buf_page_optimistic_get(RW_X_LATCH, m_block, m_modify_clock, __FILE__, __LINE__, &m_mtr)) { m_block = buf_page_get_gen( - page_id_t(m_index->table->space->id, m_page_no), + page_id_t(m_index->table->space_id, m_page_no), page_size_t(m_index->table->space->flags), RW_X_LATCH, m_block, BUF_GET_IF_IN_POOL, __FILE__, __LINE__, &m_mtr, &m_err); @@ -1029,7 +1029,7 @@ BtrBulk::finish(dberr_t err) ut_ad(last_page_no != FIL_NULL); last_block = btr_block_get( - page_id_t(m_index->table->space->id, last_page_no), + page_id_t(m_index->table->space_id, last_page_no), page_size_t(m_index->table->space->flags), RW_X_LATCH, m_index, &mtr); first_rec = page_rec_get_next( diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 8a127d50c22..03c99ac54a2 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -761,7 +761,7 @@ btr_cur_optimistic_latch_leaves( if (left_page_no != FIL_NULL) { cursor->left_block = btr_block_get( - page_id_t(cursor->index->table->space->id, + page_id_t(cursor->index->table->space_id, left_page_no), page_size_t(cursor->index->table->space ->flags), @@ -1440,7 +1440,7 @@ btr_cur_search_to_nth_level_func( const page_size_t page_size(index->table->space->flags); /* Start with the root page. */ - page_id_t page_id(index->table->space->id, index->page); + page_id_t page_id(index->table->space_id, index->page); if (root_leaf_rw_latch == RW_X_LATCH) { node_ptr_max_size = btr_node_ptr_max_size(index); @@ -2552,7 +2552,7 @@ btr_cur_open_at_index_side_func( page_cursor = btr_cur_get_page_cur(cursor); cursor->index = index; - page_id_t page_id(index->table->space->id, index->page); + page_id_t page_id(index->table->space_id, index->page); const page_size_t page_size(index->table->space->flags); if (root_leaf_rw_latch == RW_X_LATCH) { @@ -2910,7 +2910,7 @@ btr_cur_open_at_rnd_pos_func( page_cursor = btr_cur_get_page_cur(cursor); cursor->index = index; - page_id_t page_id(index->table->space->id, index->page); + page_id_t page_id(index->table->space_id, index->page); const page_size_t page_size(index->table->space->flags); dberr_t err = DB_SUCCESS; @@ -7430,7 +7430,7 @@ struct btr_blob_log_check_t { if (m_op == BTR_STORE_INSERT_BULK) { mtr_x_lock(dict_index_get_lock(index), m_mtr); m_pcur->btr_cur.page_cur.block = btr_block_get( - page_id_t(index->table->space->id, page_no), + page_id_t(index->table->space_id, page_no), page_size_t(index->table->space->flags), RW_X_LATCH, index, m_mtr); m_pcur->btr_cur.page_cur.rec @@ -8038,6 +8038,7 @@ btr_free_externally_stored_field( & ~((BTR_EXTERN_OWNER_FLAG | BTR_EXTERN_INHERITED_FLAG) << 24))); ut_ad(space_id == index->table->space->id); + ut_ad(space_id == index->table->space_id); const page_size_t ext_page_size(dict_table_page_size(index->table)); const page_size_t& rec_page_size(rec == NULL diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc index 9ff7aee63ed..81373c788d4 100644 --- a/storage/innobase/btr/btr0defragment.cc +++ b/storage/innobase/btr/btr0defragment.cc @@ -166,7 +166,7 @@ btr_defragment_add_index( mtr_start(&mtr); // Load index rood page. buf_block_t* block = btr_block_get( - page_id_t(index->table->space->id, index->page), + page_id_t(index->table->space_id, index->page), page_size_t(index->table->space->flags), RW_NO_LATCH, index, &mtr); page_t* page = NULL; @@ -314,7 +314,7 @@ btr_defragment_save_defrag_stats_if_needed( dict_index_t* index) /*!< in: index */ { if (srv_defragment_stats_accuracy != 0 // stats tracking disabled - && index->table->space->id != 0 // do not track system tables + && index->table->space_id != 0 // do not track system tables && index->stat_defrag_modified_counter >= srv_defragment_stats_accuracy) { dict_stats_defrag_pool_add(index); @@ -492,7 +492,7 @@ btr_defragment_merge_pages( from_block); btr_search_drop_page_hash_index(from_block); btr_level_list_remove( - index->table->space->id, + index->table->space_id, page_size, from_block->frame, index, mtr); btr_node_ptr_delete(index, from_block, mtr); btr_page_free(index, from_block, mtr); @@ -569,7 +569,7 @@ btr_defragment_n_pages( return NULL; } - if (!index->table->space || !index->table->space->id) { + if (!index->table->space || !index->table->space_id) { /* Ignore space 0. */ return NULL; } @@ -594,7 +594,7 @@ btr_defragment_n_pages( break; } - blocks[i] = btr_block_get(page_id_t(index->table->space->id, + blocks[i] = btr_block_get(page_id_t(index->table->space_id, page_no), page_size, RW_X_LATCH, index, mtr); } diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 8df0dd795de..6b6158d5892 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -174,10 +174,25 @@ btr_pcur_store_position( cursor->rel_pos = BTR_PCUR_ON; } - cursor->old_rec = dict_index_copy_rec_order_prefix( - index, rec, &cursor->old_n_fields, - &cursor->old_rec_buf, &cursor->buf_size); + if (index->is_ibuf()) { + ut_ad(!index->table->not_redundant()); + cursor->old_n_fields = rec_get_n_fields_old(rec); + } else if (page_rec_is_leaf(rec)) { + cursor->old_n_fields = dict_index_get_n_unique_in_tree(index); + } else if (index->is_spatial()) { + ut_ad(dict_index_get_n_unique_in_tree_nonleaf(index) + == DICT_INDEX_SPATIAL_NODEPTR_SIZE); + /* For R-tree, we have to compare + the child page numbers as well. */ + cursor->old_n_fields = DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1; + } else { + cursor->old_n_fields = dict_index_get_n_unique_in_tree(index); + } + cursor->old_rec = rec_copy_prefix_to_buf(rec, index, + cursor->old_n_fields, + &cursor->old_rec_buf, + &cursor->buf_size); cursor->block_when_stored = block; /* Function try to check if block is S/X latch. */ diff --git a/storage/innobase/btr/btr0scrub.cc b/storage/innobase/btr/btr0scrub.cc index 22e997b60aa..7d8966d4109 100644 --- a/storage/innobase/btr/btr0scrub.cc +++ b/storage/innobase/btr/btr0scrub.cc @@ -450,14 +450,14 @@ btr_pessimistic_scrub( mtr->release_block_at_savepoint(scrub_data->savepoint, block); buf_block_t* get_block __attribute__((unused)) = btr_block_get( - page_id_t(index->table->space->id, left_page_no), + page_id_t(index->table->space_id, left_page_no), page_size, RW_X_LATCH, index, mtr); /** * Refetch block and re-initialize page */ block = btr_block_get( - page_id_t(index->table->space->id, page_no), + page_id_t(index->table->space_id, page_no), page_size, RW_X_LATCH, index, mtr); page = buf_block_get_frame(block); @@ -471,7 +471,7 @@ btr_pessimistic_scrub( if (right_page_no != FIL_NULL) { buf_block_t* get_block __attribute__((unused))= btr_block_get( - page_id_t(index->table->space->id, right_page_no), + page_id_t(index->table->space_id, right_page_no), page_size, RW_X_LATCH, index, mtr); } @@ -787,7 +787,7 @@ btr_scrub_page( /* check that table/index still match now that they are loaded */ if (!scrub_data->current_table->space - || scrub_data->current_table->space->id != scrub_data->space) { + || scrub_data->current_table->space_id != scrub_data->space) { /* this is truncate table */ mtr_commit(mtr); return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE; diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index c8abed82f6a..2c0905fa01e 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -663,7 +663,7 @@ btr_search_update_hash_ref( const rec_fmt_t format = page_is_comp(block->frame) ? REC_FMT_LEAF : REC_FMT_LEAF_FLEXIBLE; - ut_ad(block->page.id.space() == index->table->space->id); + ut_ad(block->page.id.space() == index->table->space_id); ut_ad(index == cursor->index); ut_ad(!dict_index_is_ibuf(index)); ut_ad(!!page_is_comp(block->frame) == index->table->not_redundant() @@ -1372,7 +1372,7 @@ btr_search_build_page_hash_index( rec_offs_init(offsets_); ut_ad(ahi_latch == btr_get_search_latch(index)); ut_ad(index); - ut_ad(block->page.id.space() == index->table->space->id); + ut_ad(block->page.id.space() == index->table->space_id); ut_a(!dict_index_is_ibuf(index)); ut_ad(page_is_leaf(block->frame)); @@ -1691,7 +1691,7 @@ void btr_search_update_hash_on_delete(btr_cur_t* cursor) return; } - ut_ad(block->page.id.space() == index->table->space->id); + ut_ad(block->page.id.space() == index->table->space_id); ut_a(index == cursor->index); ut_a(block->curr_n_fields > 0 || block->curr_n_bytes > 0); ut_a(!dict_index_is_ibuf(index)); @@ -1852,7 +1852,7 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) return; } - ut_ad(block->page.id.space() == index->table->space->id); + ut_ad(block->page.id.space() == index->table->space_id); btr_search_check_free_space_in_heap(index); table = btr_get_search_table(index); diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index e47680e39f2..28542b61198 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -5465,46 +5465,6 @@ dict_index_build_node_ptr( return(tuple); } -/**********************************************************************//** -Copies an initial segment of a physical record, long enough to specify an -index entry uniquely. -@return pointer to the prefix record */ -rec_t* -dict_index_copy_rec_order_prefix( -/*=============================*/ - const dict_index_t* index, /*!< in: index */ - const rec_t* rec, /*!< in: record for which to - copy prefix */ - ulint* n_fields,/*!< out: number of fields copied */ - byte** buf, /*!< in/out: memory buffer for the - copied prefix, or NULL */ - ulint* buf_size)/*!< in/out: buffer size */ -{ - ulint n; - - UNIV_PREFETCH_R(rec); - - if (dict_index_is_ibuf(index)) { - ut_ad(!dict_table_is_comp(index->table)); - n = rec_get_n_fields_old(rec); - } else { - if (page_rec_is_leaf(rec)) { - n = dict_index_get_n_unique_in_tree(index); - } else if (dict_index_is_spatial(index)) { - ut_ad(dict_index_get_n_unique_in_tree_nonleaf(index) - == DICT_INDEX_SPATIAL_NODEPTR_SIZE); - /* For R-tree, we have to compare - the child page numbers as well. */ - n = DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1; - } else { - n = dict_index_get_n_unique_in_tree(index); - } - } - - *n_fields = n; - return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size)); -} - /** Convert a physical record into a search tuple. @param[in] rec index record (not necessarily in an index page) @param[in] index index diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index f19a894bc64..1540f7e53bc 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -3007,7 +3007,7 @@ err_exit: } if (err == DB_SUCCESS && cached && table->is_readable()) { - if (table->space && !fil_space_get_size(table->space->id)) { + if (table->space && !fil_space_get_size(table->space_id)) { table->corrupted = true; table->file_unreadable = true; } else if (table->supports_instant()) { diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 9e15ccddc0f..71ab258f25e 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1513,7 +1513,7 @@ dict_stats_analyze_index_below_cur( offsets_rec = rec_get_offsets(rec, index, offsets1, REC_FMT_NODE_PTR, ULINT_UNDEFINED, &heap); - page_id_t page_id(index->table->space->id, + page_id_t page_id(index->table->space_id, btr_node_ptr_get_child_page_no( rec, offsets_rec)); const page_size_t page_size(index->table->space->flags); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 3e86ae267c2..9c4f1a0290d 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -165,9 +165,6 @@ ulint fil_n_pending_log_flushes = 0; /** Number of pending tablespace flushes */ ulint fil_n_pending_tablespace_flushes = 0; -/** Number of files currently open */ -ulint fil_n_file_opened = 0; - /** The tablespace memory cache. This variable is NULL before the module is initialized. */ fil_system_t fil_system; @@ -433,36 +430,25 @@ fil_space_is_flushed( /** Append a file to the chain of files of a space. @param[in] name file name of a file that is not open -@param[in] size file size in entire database blocks -@param[in,out] space tablespace from fil_space_create() -@param[in] is_raw whether this is a raw device or partition -@param[in] atomic_write true if the file could use atomic write +@param[in] handle file handle, or OS_FILE_CLOSED +@param[in] size file size in entire database pages +@param[in] is_raw whether this is a raw device +@param[in] atomic_write true if atomic write could be enabled @param[in] max_pages maximum number of pages in file, -ULINT_MAX means the file size is unlimited. -@return pointer to the file name -@retval NULL if error */ -static -fil_node_t* -fil_node_create_low( - const char* name, - ulint size, - fil_space_t* space, - bool is_raw, - bool atomic_write, - ulint max_pages = ULINT_MAX) +or ULINT_MAX for unlimited +@return file object */ +fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle, + ulint size, bool is_raw, bool atomic_write, + ulint max_pages) { fil_node_t* node; ut_ad(name != NULL); ut_ad(fil_system.is_initialised()); - if (space == NULL) { - return(NULL); - } - node = reinterpret_cast<fil_node_t*>(ut_zalloc_nokey(sizeof(*node))); - node->handle = OS_FILE_CLOSED; + node->handle = handle; node->name = mem_strdup(name); @@ -479,55 +465,114 @@ fil_node_create_low( node->init_size = size; node->max_size = max_pages; - mutex_enter(&fil_system.mutex); - - space->size += size; - - node->space = space; + node->space = this; node->atomic_write = atomic_write; - UT_LIST_ADD_LAST(space->chain, node); + mutex_enter(&fil_system.mutex); + this->size += size; + UT_LIST_ADD_LAST(chain, node); + if (node->is_open()) { + fil_system.n_open++; + } mutex_exit(&fil_system.mutex); - return(node); + return node; } -/** Appends a new file to the chain of files of a space. File must be closed. -@param[in] name file name (file must be closed) -@param[in] size file size in database blocks, rounded downwards to - an integer -@param[in,out] space space where to append -@param[in] is_raw true if a raw device or a raw disk partition -@param[in] atomic_write true if the file could use atomic write -@param[in] max_pages maximum number of pages in file, -ULINT_MAX means the file size is unlimited. -@return pointer to the file name -@retval NULL if error */ -char* -fil_node_create( - const char* name, - ulint size, - fil_space_t* space, - bool is_raw, - bool atomic_write, - ulint max_pages) +/** Read the first page of a data file. +@param[in] first whether this is the very first read +@return whether the page was found valid */ +bool fil_node_t::read_page0(bool first) { - fil_node_t* node; + ut_ad(mutex_own(&fil_system.mutex)); + ut_a(space->purpose != FIL_TYPE_LOG); + const page_size_t page_size(space->flags); + const ulint psize = page_size.physical(); + + os_offset_t size_bytes = os_file_get_size(handle); + ut_a(size_bytes != (os_offset_t) -1); + const ulint min_size = FIL_IBD_FILE_INITIAL_SIZE * psize; - node = fil_node_create_low( - name, size, space, is_raw, atomic_write, max_pages); + if (size_bytes < min_size) { + ib::error() << "The size of the file " << name + << " is only " << size_bytes + << " bytes, should be at least " << min_size; + return false; + } - return(node == NULL ? NULL : node->name); + byte* buf2 = static_cast<byte*>(ut_malloc_nokey(2 * psize)); + + /* Align the memory for file i/o if we might have O_DIRECT set */ + byte* page = static_cast<byte*>(ut_align(buf2, psize)); + IORequest request(IORequest::READ); + if (!os_file_read(request, handle, page, 0, psize)) { + ib::error() << "Unable to read first page of file " << name; + ut_free(buf2); + return false; + } + const ulint space_id = fsp_header_get_space_id(page); + ulint flags = fsp_header_get_flags(page); + const ulint size = fsp_header_get_field(page, FSP_SIZE); + const ulint free_limit = fsp_header_get_field(page, FSP_FREE_LIMIT); + const ulint free_len = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE + + page); + /* Try to read crypt_data from page 0 if it is not yet read. */ + if (!space->crypt_data) { + space->crypt_data = fil_space_read_crypt_data(page_size, page); + } + ut_free(buf2); + + if (!fsp_flags_is_valid(flags, space->id)) { + ulint cflags = fsp_flags_convert_from_101(flags); + if (cflags == ULINT_UNDEFINED + || (cflags ^ space->flags) & ~FSP_FLAGS_MEM_MASK) { + ib::error() + << "Expected tablespace flags " + << ib::hex(space->flags) + << " but found " << ib::hex(flags) + << " in the file " << name; + return false; + } + + flags = cflags; + } + + if (UNIV_UNLIKELY(space_id != space->id)) { + ib::error() << "Expected tablespace id " << space->id + << " but found " << space_id + << " in the file " << name; + return false; + } + + ut_ad(space->free_limit == 0 || space->free_limit == free_limit); + ut_ad(space->free_len == 0 || space->free_len == free_len); + space->size_in_header = size; + space->free_limit = free_limit; + space->free_len = free_len; + + if (first) { + /* Truncate the size to a multiple of extent size. */ + ulint mask = psize * FSP_EXTENT_SIZE - 1; + + if (size_bytes <= mask) { + /* .ibd files start smaller than an + extent size. Do not truncate valid data. */ + } else { + size_bytes &= ~os_offset_t(mask); + } + + this->size = ulint(size_bytes / psize); + space->size += this->size; + } + + return true; } /** Open a file node of a tablespace. @param[in,out] node File node @return false if the file can't be opened, otherwise true */ -static -bool -fil_node_open_file( - fil_node_t* node) +static bool fil_node_open_file(fil_node_t* node) { bool success; bool read_only_mode; @@ -554,9 +599,12 @@ fil_node_open_file( from a file opened for async I/O! */ retry: - node->handle = os_file_create_simple_no_error_handling( - innodb_data_file_key, node->name, OS_FILE_OPEN, - OS_FILE_READ_ONLY, read_only_mode, &success); + node->handle = os_file_create( + innodb_data_file_key, node->name, + node->is_raw_disk + ? OS_FILE_OPEN_RAW | OS_FILE_ON_ERROR_NO_EXIT + : OS_FILE_OPEN | OS_FILE_ON_ERROR_NO_EXIT, + OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success); if (!success) { /* The following call prints an error message */ @@ -572,155 +620,52 @@ retry: return(false); } - os_offset_t size_bytes = os_file_get_size(node->handle); - ut_a(size_bytes != (os_offset_t) -1); - - ut_a(space->purpose != FIL_TYPE_LOG); - const page_size_t page_size(space->flags); - const ulint psize = page_size.physical(); - const ulint min_size = FIL_IBD_FILE_INITIAL_SIZE - * psize; - - if (size_bytes < min_size) { - ib::error() << "The size of the file " << node->name - << " is only " << size_bytes - << " bytes, should be at least " << min_size; + if (!node->read_page0(first_time_open)) { os_file_close(node->handle); node->handle = OS_FILE_CLOSED; - return(false); - } - - /* Read the first page of the tablespace */ - - byte* buf2 = static_cast<byte*>(ut_malloc_nokey(2 * psize)); - - /* Align the memory for file i/o if we might have O_DIRECT - set */ - byte* page = static_cast<byte*>(ut_align(buf2, psize)); - - IORequest request(IORequest::READ); - - success = os_file_read( - request, - node->handle, page, 0, psize); - - const ulint space_id - = fsp_header_get_space_id(page); - ulint flags = fsp_header_get_flags(page); - const ulint size = fsp_header_get_field( - page, FSP_SIZE); - const ulint free_limit = fsp_header_get_field( - page, FSP_FREE_LIMIT); - const ulint free_len = flst_get_len( - FSP_HEADER_OFFSET + FSP_FREE + page); - - /* Try to read crypt_data from page 0 if it is not yet - read. */ - if (!space->crypt_data) { - space->crypt_data = fil_space_read_crypt_data( - page_size_t(space->flags), page); - } - - ut_free(buf2); - os_file_close(node->handle); - node->handle = OS_FILE_CLOSED; - - if (!fsp_flags_is_valid(flags, space->id)) { - ulint cflags = fsp_flags_convert_from_101(flags); - if (cflags == ULINT_UNDEFINED - || (cflags ^ space->flags) & ~FSP_FLAGS_MEM_MASK) { - ib::error() - << "Expected tablespace flags " - << ib::hex(space->flags) - << " but found " << ib::hex(flags) - << " in the file " << node->name; - return(false); - } - - flags = cflags; - } - - if (UNIV_UNLIKELY(space_id != space->id)) { - ib::error() - << "Expected tablespace id " << space->id - << " but found " << space_id - << " in the file" << node->name; - return(false); - } - - ut_ad(space->free_limit == 0 - || space->free_limit == free_limit); - ut_ad(space->free_len == 0 - || space->free_len == free_len); - space->size_in_header = size; - space->free_limit = free_limit; - space->free_len = free_len; - - if (first_time_open) { - /* Truncate the size to a multiple of extent size. */ - ulint mask = psize * FSP_EXTENT_SIZE - 1; - - if (size_bytes <= mask) { - /* .ibd files start smaller than an - extent size. Do not truncate valid data. */ - } else { - size_bytes &= ~os_offset_t(mask); - } - - node->size = ulint(size_bytes / psize); - space->size += node->size; + return false; } - } - - /* printf("Opening file %s\n", node->name); */ - - /* Open the file for reading and writing, in Windows normally in the - unbuffered async I/O mode, though global variables may make - os_file_create() to fall back to the normal file I/O mode. */ - - if (space->purpose == FIL_TYPE_LOG) { + } else if (space->purpose == FIL_TYPE_LOG) { node->handle = os_file_create( innodb_log_file_key, node->name, OS_FILE_OPEN, OS_FILE_AIO, OS_LOG_FILE, read_only_mode, &success); - } else if (node->is_raw_disk) { - node->handle = os_file_create( - innodb_data_file_key, node->name, OS_FILE_OPEN_RAW, - OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success); } else { node->handle = os_file_create( - innodb_data_file_key, node->name, OS_FILE_OPEN, + innodb_data_file_key, node->name, + node->is_raw_disk + ? OS_FILE_OPEN_RAW | OS_FILE_ON_ERROR_NO_EXIT + : OS_FILE_OPEN | OS_FILE_ON_ERROR_NO_EXIT, OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success); + } - if (first_time_open) { - /* - For the temporary tablespace and during the - non-redo-logged adjustments in - IMPORT TABLESPACE, we do not care about - the atomicity of writes. - - Atomic writes is supported if the file can be used - with atomic_writes (not log file), O_DIRECT is - used (tested in ha_innodb.cc) and the file is - device and file system that supports atomic writes - for the given block size - */ - space->atomic_write_supported - = space->purpose == FIL_TYPE_TEMPORARY - || space->purpose == FIL_TYPE_IMPORT - || (node->atomic_write - && srv_use_atomic_writes - && my_test_if_atomic_write( - node->handle, - int(page_size_t(space->flags) - .physical()))); - } - } + if (space->purpose != FIL_TYPE_LOG) { + /* + For the temporary tablespace and during the + non-redo-logged adjustments in + IMPORT TABLESPACE, we do not care about + the atomicity of writes. + + Atomic writes is supported if the file can be used + with atomic_writes (not log file), O_DIRECT is + used (tested in ha_innodb.cc) and the file is + device and file system that supports atomic writes + for the given block size + */ + space->atomic_write_supported + = space->purpose == FIL_TYPE_TEMPORARY + || space->purpose == FIL_TYPE_IMPORT + || (node->atomic_write + && srv_use_atomic_writes + && my_test_if_atomic_write( + node->handle, + int(page_size_t(space->flags) + .physical()))); + } ut_a(success); ut_a(node->is_open()); fil_system.n_open++; - fil_n_file_opened++; if (fil_space_belongs_in_lru(space)) { @@ -755,7 +700,6 @@ void fil_node_t::close() ut_ad(!is_open()); ut_a(fil_system.n_open > 0); fil_system.n_open--; - fil_n_file_opened--; if (fil_space_belongs_in_lru(space)) { ut_a(UT_LIST_GET_LEN(fil_system.LRU) > 0); @@ -1390,7 +1334,7 @@ Error messages are issued to the server log. @param[in] purpose tablespace purpose @param[in,out] crypt_data encryption information @param[in] mode encryption mode -@return pointer to created tablespace, to be filled in with fil_node_create() +@return pointer to created tablespace, to be filled in with fil_space_t::add() @retval NULL on failure (such as when the same tablespace exists) */ fil_space_t* fil_space_create( @@ -1466,7 +1410,7 @@ fil_space_create( if (space->purpose == FIL_TYPE_TEMPORARY) { /* SysTablespace::open_or_create() would pass - size!=0 to fil_node_create(), so first_time_open + size!=0 to fil_space_t::add(), so first_time_open would not hold in fil_node_open_file(), and we must assign this manually. We do not care about the durability or atomicity of writes to the @@ -3219,17 +3163,17 @@ err_exit: free(crypt_data); *err = DB_ERROR; } else { - fil_node_t* node = fil_node_create_low(path, size, space, - false, true); + fil_node_t* file = space->add(path, OS_FILE_CLOSED, size, + false, true); mtr_t mtr; mtr.start(); fil_op_write_log( - MLOG_FILE_CREATE2, space_id, 0, node->name, + MLOG_FILE_CREATE2, space_id, 0, file->name, NULL, space->flags & ~FSP_FLAGS_MEM_MASK, &mtr); - fil_name_write(space, 0, node, &mtr); + fil_name_write(space, 0, file, &mtr); mtr.commit(); - node->block_size = block_size; + file->block_size = block_size; space->punch_hole = punch_hole; *err = DB_SUCCESS; @@ -3597,17 +3541,17 @@ skip_validate: fil_space_t* space = fil_space_create( tablename.m_name, id, flags, purpose, crypt_data); + if (!space) { + goto error; + } /* We do not measure the size of the file, that is why we pass the 0 below */ - if (fil_node_create_low( - df_remote.is_open() ? df_remote.filepath() : - df_dict.is_open() ? df_dict.filepath() : - df_default.filepath(), 0, space, false, - true) == NULL) { - goto error; - } + space->add( + df_remote.is_open() ? df_remote.filepath() : + df_dict.is_open() ? df_dict.filepath() : + df_default.filepath(), OS_FILE_CLOSED, 0, false, true); if (validate && purpose != FIL_TYPE_IMPORT && !srv_read_only_mode) { df_remote.close(); @@ -3956,9 +3900,7 @@ fil_ibd_load( the rounding formula for extents and pages is somewhat complex; we let fil_node_open() do that task. */ - if (!fil_node_create_low(file.filepath(), 0, space, false, false)) { - ut_error; - } + space->add(file.filepath(), OS_FILE_CLOSED, 0, false, false); return(FIL_LOAD_OK); } @@ -4859,8 +4801,8 @@ fil_mtr_rename_log( { ut_ad(old_table->space != fil_system.temp_space); ut_ad(new_table->space != fil_system.temp_space); - ut_ad(old_table->space_id == old_table->space->id); - ut_ad(new_table->space_id == new_table->space->id); + ut_ad(old_table->space->id == old_table->space_id); + ut_ad(new_table->space->id == new_table->space_id); /* If neither table is file-per-table, there will be no renaming of files. */ diff --git a/storage/innobase/fsp/fsp0space.cc b/storage/innobase/fsp/fsp0space.cc index df234f7274e..88b34be4952 100644 --- a/storage/innobase/fsp/fsp0space.cc +++ b/storage/innobase/fsp/fsp0space.cc @@ -123,18 +123,15 @@ Tablespace::open_or_create(bool is_temp) is_temp ? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE, NULL); + if (!space) { + return DB_ERROR; + } } ut_a(fil_validate()); - /* Create the tablespace node entry for this data file. */ - if (!fil_node_create( - it->m_filepath, it->m_size, space, false, - TRUE)) { - - err = DB_ERROR; - break; - } + space->add(it->m_filepath, OS_FILE_CLOSED, it->m_size, + false, true); } return(err); diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc index b411d315927..aec2a3914b8 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -907,12 +907,18 @@ SysTablespace::open_or_create( space = fil_system.temp_space = fil_space_create( name(), SRV_TMP_SPACE_ID, flags(), FIL_TYPE_TEMPORARY, NULL); + if (!space) { + return DB_ERROR; + } } else { ut_ad(!fil_system.sys_space); ut_ad(space_id() == TRX_SYS_SPACE); space = fil_system.sys_space = fil_space_create( name(), TRX_SYS_SPACE, flags(), FIL_TYPE_TABLESPACE, NULL); + if (!space) { + return DB_ERROR; + } } ut_a(fil_validate()); @@ -923,15 +929,8 @@ SysTablespace::open_or_create( : m_last_file_size_max) : it->m_size); - /* Add the datafile to the fil_system cache. */ - if (!fil_node_create( - it->m_filepath, it->m_size, - space, it->m_type != SRV_NOT_RAW, - TRUE, max_size)) { - - err = DB_ERROR; - break; - } + space->add(it->m_filepath, OS_FILE_CLOSED, it->m_size, + it->m_type != SRV_NOT_RAW, true, max_size); } return(err); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 3a7323bfcbd..2fad7ed01a6 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1741,7 +1741,7 @@ fts_create_in_mem_aux_table( { dict_table_t* new_table = dict_mem_table_create( aux_table_name, NULL, n_cols, 0, table->flags, - table->space->id == TRX_SYS_SPACE + table->space_id == TRX_SYS_SPACE ? 0 : table->space->purpose == FIL_TYPE_TEMPORARY ? DICT_TF2_TEMPORARY : DICT_TF2_USE_FILE_PER_TABLE); @@ -1770,7 +1770,7 @@ fts_create_one_common_table( const char* fts_suffix, mem_heap_t* heap) { - dict_table_t* new_table = NULL; + dict_table_t* new_table; dberr_t error; bool is_config = strcmp(fts_suffix, "CONFIG") == 0; @@ -1823,11 +1823,13 @@ fts_create_one_common_table( } if (error != DB_SUCCESS) { - trx->error_state = error; dict_mem_table_free(new_table); new_table = NULL; ib::warn() << "Failed to create FTS common table " << fts_table_name; + trx->error_state = DB_SUCCESS; + row_drop_table_for_mysql(fts_table_name, trx, SQLCOM_DROP_DB); + trx->error_state = error; } return(new_table); } @@ -1968,7 +1970,7 @@ fts_create_one_index_table( mem_heap_t* heap) { dict_field_t* field; - dict_table_t* new_table = NULL; + dict_table_t* new_table; char table_name[MAX_FULL_NAME_LEN]; dberr_t error; CHARSET_INFO* charset; @@ -2032,11 +2034,13 @@ fts_create_one_index_table( } if (error != DB_SUCCESS) { - trx->error_state = error; dict_mem_table_free(new_table); new_table = NULL; ib::warn() << "Failed to create FTS index table " << table_name; + trx->error_state = DB_SUCCESS; + row_drop_table_for_mysql(table_name, trx, SQLCOM_DROP_DB); + trx->error_state = error; } return(new_table); diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index 04c45f50acd..1d3a4e13d82 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -740,7 +740,7 @@ rtr_adjust_upper_level( new_prdt.op = 0; lock_prdt_update_parent(block, new_block, &prdt, &new_prdt, - index->table->space->id, + index->table->space_id, page_cursor->block->page.id.page_no()); mem_heap_free(heap); @@ -1267,7 +1267,7 @@ after_insert: /* Check any predicate locks need to be moved/copied to the new page */ lock_prdt_update_split(new_block, &prdt, &new_prdt, - cursor->index->table->space->id, page_no); + cursor->index->table->space_id, page_no); /* Adjust the upper level. */ rtr_adjust_upper_level(cursor, flags, block, new_block, @@ -1884,7 +1884,7 @@ rtr_estimate_n_rows_in_range( mtr_s_lock(&index->lock, &mtr); buf_block_t* block = btr_block_get( - page_id_t(index->table->space->id, index->page), + page_id_t(index->table->space_id, index->page), page_size_t(index->table->space->flags), RW_S_LATCH, index, &mtr); const page_t* page = buf_block_get_frame(block); diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index 093c1570200..a8242b31af5 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -268,7 +268,7 @@ rtr_pcur_getnext_from_path( dberr_t err = DB_SUCCESS; block = buf_page_get_gen( - page_id_t(index->table->space->id, + page_id_t(index->table->space_id, next_rec.page_no), page_size, rw_latch, NULL, BUF_GET, __FILE__, __LINE__, mtr, &err); @@ -298,7 +298,7 @@ rtr_pcur_getnext_from_path( && mode != PAGE_CUR_RTREE_LOCATE) { ut_ad(rtr_info->thr); lock_place_prdt_page_lock( - index->table->space->id, + index->table->space_id, next_page_no, index, rtr_info->thr); } @@ -422,7 +422,7 @@ rtr_pcur_getnext_from_path( btr_cur_latch_leaves( block, - page_id_t(index->table->space->id, + page_id_t(index->table->space_id, block->page.id.page_no()), page_size, BTR_MODIFY_TREE, btr_cur, mtr); @@ -1367,7 +1367,7 @@ search_again: dberr_t err = DB_SUCCESS; block = buf_page_get_gen( - page_id_t(index->table->space->id, page_no), + page_id_t(index->table->space_id, page_no), page_size, RW_X_LATCH, NULL, BUF_GET, __FILE__, __LINE__, mtr, &err); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 1afe451d4a8..c5dbaa52f77 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -145,8 +145,8 @@ void close_thread_tables(THD* thd); #ifdef WITH_WSREP #include "dict0priv.h" -#include "ut0byte.h" #include <mysql/service_md5.h> +#include "wsrep_sst.h" extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log; @@ -3731,6 +3731,15 @@ static int innodb_init_params() ib::info() << "For Galera, using innodb_lock_schedule_algorithm=fcfs"; innodb_lock_schedule_algorithm = INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS; } + + /* Print deprecation info if xtrabackup is used for SST method */ + if (global_system_variables.wsrep_on + && wsrep_sst_method + && (!strcmp(wsrep_sst_method, "xtrabackup") + || !strcmp(wsrep_sst_method, "xtrabackup-v2"))) { + ib::info() << "Galera SST method xtrabackup is deprecated and the " + " support for it may be removed in future releases."; + } #endif /* WITH_WSREP */ #ifndef HAVE_LZ4 @@ -10791,6 +10800,7 @@ create_table_info_t::create_table_def() DBUG_PRINT("enter", ("table_name: %s", m_table_name)); DBUG_ASSERT(m_trx->mysql_thd == m_thd); + DBUG_ASSERT(!m_drop_before_rollback); /* MySQL does the name length check. But we do additional check on the name length here */ @@ -11052,6 +11062,7 @@ err_col: table, m_trx, (fil_encryption_t)options->encryption, (uint32_t)options->encryption_key_id); + m_drop_before_rollback = (err == DB_SUCCESS); } DBUG_EXECUTE_IF("ib_crash_during_create_for_encryption", @@ -12278,6 +12289,9 @@ int create_table_info_t::create_table(bool create_fk) DBUG_RETURN(error); } + DBUG_ASSERT(m_drop_before_rollback + == !(m_flags2 & DICT_TF2_TEMPORARY)); + /* Create the keys */ if (m_form->s->keys == 0 || primary_key_no == -1) { @@ -12336,6 +12350,7 @@ int create_table_info_t::create_table(bool create_fk) my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), FTS_DOC_ID_INDEX_NAME); + m_drop_before_rollback = false; error = -1; DBUG_RETURN(error); case FTS_EXIST_DOC_ID_INDEX: @@ -12350,10 +12365,6 @@ int create_table_info_t::create_table(bool create_fk) error = convert_error_code_to_mysql(err, 0, NULL); if (error) { - row_drop_table_for_mysql(m_table_name, m_trx, - SQLCOM_DROP_DB); - trx_rollback_to_savepoint(m_trx, NULL); - m_trx->error_state = DB_SUCCESS; DBUG_RETURN(error); } } @@ -12419,6 +12430,9 @@ int create_table_info_t::create_table(bool create_fk) error = convert_error_code_to_mysql(err, m_flags, NULL); if (error) { + /* row_table_add_foreign_constraints() dropped + the table */ + m_drop_before_rollback = false; DBUG_RETURN(error); } } @@ -12577,14 +12591,20 @@ ha_innobase::create( } if ((error = info.create_table(own_trx))) { - row_drop_table_for_mysql(norm_name, trx, SQLCOM_DROP_TABLE, - true); + /* Drop the being-created table before rollback, + so that rollback can possibly rename back a table + that could have been renamed before the failed creation. */ + if (info.drop_before_rollback()) { + trx->error_state = DB_SUCCESS; + row_drop_table_for_mysql(info.table_name(), + trx, SQLCOM_TRUNCATE, true); + } trx_rollback_for_mysql(trx); row_mysql_unlock_data_dictionary(trx); if (own_trx) { trx_free(trx); - DBUG_RETURN(error); } + DBUG_RETURN(error); } innobase_commit_low(trx); diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 7bec858b5af..ed7d380db8b 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -656,7 +656,7 @@ public: m_trx(trx), m_form(form), m_create_info(create_info), - m_table_name(table_name), m_table(NULL), + m_table_name(table_name), m_table(NULL), m_drop_before_rollback(false), m_remote_path(remote_path), m_innodb_file_per_table(file_per_table) {} @@ -729,6 +729,9 @@ public: const char* table_name() const { return(m_table_name); } + /** @return whether the table needs to be dropped on rollback */ + bool drop_before_rollback() const { return m_drop_before_rollback; } + THD* thd() const { return(m_thd); } @@ -772,6 +775,8 @@ private: char* m_table_name; /** Table */ dict_table_t* m_table; + /** Whether the table needs to be dropped before rollback */ + bool m_drop_before_rollback; /** Remote path (DATA DIRECTORY) or zero length-string */ char* m_remote_path; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 959205e75bd..04354a2cea5 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -244,9 +244,12 @@ inline void dict_table_t::prepare_instant(const dict_table_t& old, DBUG_ASSERT(n_dropped() == 0); DBUG_ASSERT(old.n_cols == old.n_def); DBUG_ASSERT(n_cols == n_def); - DBUG_ASSERT(old.not_redundant() == not_redundant()); DBUG_ASSERT(old.supports_instant()); - DBUG_ASSERT(supports_instant()); + /* supports_instant() does not necessarily hold here, + in case ROW_FORMAT=COMPRESSED according to the + MariaDB data dictionary, and ALTER_OPTIONS was not set. + If that is the case, the instant ALTER TABLE would keep + the InnoDB table in its current format. */ dict_index_t& oindex = *old.indexes.start; dict_index_t& index = *indexes.start; diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 1e441b893ac..e9abde032fa 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -3371,7 +3371,7 @@ ibuf_insert_low( ut_ad(!dict_index_is_spatial(index)); ut_ad(dtuple_check_typed(entry)); ut_ad(!no_counter || op == IBUF_OP_INSERT); - ut_ad(page_id.space() == index->table->space->id); + ut_ad(page_id.space() == index->table->space_id); ut_a(op < IBUF_OP_COUNT); do_merge = FALSE; diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 7ddb1c58c5e..cf09fad27d1 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1304,21 +1304,6 @@ dict_index_build_node_ptr( ulint level) /*!< in: level of rec in tree: 0 means leaf level */ MY_ATTRIBUTE((nonnull, warn_unused_result)); -/**********************************************************************//** -Copies an initial segment of a physical record, long enough to specify an -index entry uniquely. -@return pointer to the prefix record */ -rec_t* -dict_index_copy_rec_order_prefix( -/*=============================*/ - const dict_index_t* index, /*!< in: index */ - const rec_t* rec, /*!< in: record for which to - copy prefix */ - ulint* n_fields,/*!< out: number of fields copied */ - byte** buf, /*!< in/out: memory buffer for the - copied prefix, or NULL */ - ulint* buf_size)/*!< in/out: buffer size */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); /** Convert a physical record into a search tuple. @param[in] rec index record (not necessarily in an index page) @param[in] index index diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index e0af39bdee8..94e758b52ef 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -187,6 +187,19 @@ struct fil_space_t { && srv_use_doublewrite_buf && buf_dblwr; } + /** Append a file to the chain of files of a space. + @param[in] name file name of a file that is not open + @param[in] handle file handle, or OS_FILE_CLOSED + @param[in] size file size in entire database pages + @param[in] is_raw whether this is a raw device + @param[in] atomic_write true if atomic write could be enabled + @param[in] max_pages maximum number of pages in file, + or ULINT_MAX for unlimited + @return file object */ + fil_node_t* add(const char* name, pfs_os_file_t handle, + ulint size, bool is_raw, bool atomic_write, + ulint max_pages = ULINT_MAX); + /** Try to reserve free extents. @param[in] n_free_now current number of free extents @param[in] n_to_reserve number of extents to reserve @@ -322,6 +335,11 @@ struct fil_node_t { return(handle != OS_FILE_CLOSED); } + /** Read the first page of a data file. + @param[in] first whether this is the very first read + @return whether the page was found valid */ + bool read_page0(bool first); + /** Close the file handle. */ void close(); }; @@ -519,9 +537,6 @@ extern ulint fil_n_pending_log_flushes; /** Number of pending tablespace flushes */ extern ulint fil_n_pending_tablespace_flushes; -/** Number of files currently open */ -extern ulint fil_n_file_opened; - #ifndef UNIV_INNOCHECKSUM /** Look up a tablespace. @@ -636,26 +651,6 @@ fil_space_get_latch( ulint id, ulint* flags); -/** Append a file to the chain of files of a space. -@param[in] name file name of a file that is not open -@param[in] size file size in entire database blocks -@param[in,out] space tablespace from fil_space_create() -@param[in] is_raw whether this is a raw device or partition -@param[in] atomic_write true if atomic write could be enabled -@param[in] max_pages maximum number of pages in file, -ULINT_MAX means the file size is unlimited. -@return pointer to the file name -@retval NULL if error */ -char* -fil_node_create( - const char* name, - ulint size, - fil_space_t* space, - bool is_raw, - bool atomic_write, - ulint max_pages = ULINT_MAX) - MY_ATTRIBUTE((warn_unused_result)); - /** Create a space memory object and put it to the fil_system hash table. Error messages are issued to the server log. @param[in] name tablespace name @@ -664,7 +659,7 @@ Error messages are issued to the server log. @param[in] purpose tablespace purpose @param[in,out] crypt_data encryption information @param[in] mode encryption mode -@return pointer to created tablespace, to be filled in with fil_node_create() +@return pointer to created tablespace, to be filled in with fil_space_t::add() @retval NULL on failure (such as when the same tablespace exists) */ fil_space_t* fil_space_create( diff --git a/storage/innobase/include/mem0mem.h b/storage/innobase/include/mem0mem.h index 2cdb307ea96..f299fc84b5e 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -418,104 +418,4 @@ struct mem_block_info_t { UNIV_MEM_ALIGNMENT) #include "mem0mem.ic" - -/** A C++ wrapper class to the mem_heap_t routines, so that it can be used -as an STL allocator */ -template<typename T> -class mem_heap_allocator -{ -public: - typedef T value_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - - mem_heap_allocator(mem_heap_t* heap) : m_heap(heap) { } - - mem_heap_allocator(const mem_heap_allocator& other) - : - m_heap(other.m_heap) - { - // Do nothing - } - - template <typename U> - mem_heap_allocator (const mem_heap_allocator<U>& other) - : - m_heap(other.m_heap) - { - // Do nothing - } - - ~mem_heap_allocator() { m_heap = 0; } - - size_type max_size() const - { - return(ULONG_MAX / sizeof(T)); - } - - /** This function returns a pointer to the first element of a newly - allocated array large enough to contain n objects of type T; only the - memory is allocated, and the objects are not constructed. Moreover, - an optional pointer argument (that points to an object already - allocated by mem_heap_allocator) can be used as a hint to the - implementation about where the new memory should be allocated in - order to improve locality. */ - pointer allocate(size_type n) - { - return(reinterpret_cast<pointer>( - mem_heap_alloc(m_heap, n * sizeof(T)))); - } - pointer allocate(size_type n, const_pointer) { return allocate(n); } - - void deallocate(pointer, size_type) {} - - pointer address (reference r) const { return(&r); } - - const_pointer address (const_reference r) const { return(&r); } - - void construct(pointer p, const_reference t) - { - new (reinterpret_cast<void*>(p)) T(t); - } - - void destroy(pointer p) - { - (reinterpret_cast<T*>(p))->~T(); - } - - /** Allocators are required to supply the below template class member - which enables the possibility of obtaining a related allocator, - parametrized in terms of a different type. For example, given an - allocator type IntAllocator for objects of type int, a related - allocator type for objects of type long could be obtained using - IntAllocator::rebind<long>::other */ - template <typename U> - struct rebind - { - typedef mem_heap_allocator<U> other; - }; - -private: - mem_heap_t* m_heap; - template <typename U> friend class mem_heap_allocator; -}; - -template <class T> -bool operator== (const mem_heap_allocator<T>& left, - const mem_heap_allocator<T>& right) -{ - return(left.heap == right.heap); -} - -template <class T> -bool operator!= (const mem_heap_allocator<T>& left, - const mem_heap_allocator<T>& right) -{ - return(left.heap != right.heap); -} - #endif diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 1accfd858be..8130f733806 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -372,9 +372,8 @@ row_create_table_for_mysql( MY_ATTRIBUTE((warn_unused_result)); /*********************************************************************//** -Does an index creation operation for MySQL. TODO: currently failure -to create an index results in dropping the whole table! This is no problem -currently as all indexes must be created at the same time as the table. +Create an index when creating a table. +On failure, the caller must drop the table! @return error number or DB_SUCCESS */ dberr_t row_create_index_for_mysql( diff --git a/storage/innobase/include/row0row.h b/storage/innobase/include/row0row.h index b46ca6eb3bc..8b3db8a1b64 100644 --- a/storage/innobase/include/row0row.h +++ b/storage/innobase/include/row0row.h @@ -418,7 +418,7 @@ row_mtr_start(mtr_t* mtr, dict_index_t* index, bool pessimistic) { mtr->start(); - switch (index->table->space->id) { + switch (index->table->space_id) { case IBUF_SPACE_ID: if (pessimistic && !(index->type & (DICT_UNIQUE | DICT_SPATIAL))) { diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 4fe79a1c9d0..be448696b1b 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -972,7 +972,7 @@ struct export_var_t{ ulint innodb_system_rows_inserted; /*!< srv_n_system_rows_inserted */ ulint innodb_system_rows_updated; /*!< srv_n_system_rows_updated */ ulint innodb_system_rows_deleted; /*!< srv_n_system_rows_deleted*/ - ulint innodb_num_open_files; /*!< fil_n_file_opened */ + ulint innodb_num_open_files; /*!< fil_system_t::n_open */ ulint innodb_truncated_status_writes; /*!< srv_truncated_status_writes */ ulint innodb_available_undo_logs; /*!< srv_available_undo_logs */ diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 8ace3d2df4a..4b9aaf6ae92 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -4923,6 +4923,8 @@ lock_rec_queue_validate( goto func_exit; } + ut_ad(page_rec_is_leaf(rec)); + if (index == NULL) { /* Nothing we can do */ @@ -5091,10 +5093,13 @@ loop: ? REC_FMT_LEAF : REC_FMT_LEAF_FLEXIBLE; i < lock_rec_get_n_bits(lock); i++) { - if (i == 1 || lock_rec_get_nth_bit(lock, i)) { + if (i == PAGE_HEAP_NO_SUPREMUM + || lock_rec_get_nth_bit(lock, i)) { rec = page_find_rec_with_heap_no(block->frame, i); ut_a(rec); + ut_ad(!lock_rec_get_nth_bit(lock, i) + || page_rec_is_leaf(rec)); offsets = rec_get_offsets(rec, lock->index, offsets, format, ULINT_UNDEFINED, &heap); @@ -5313,7 +5318,7 @@ lock_rec_insert_check_and_lock( { ut_ad(block->frame == page_align(rec)); ut_ad(!dict_index_is_online_ddl(index) - || dict_index_is_clust(index) + || index->is_primary() || (flags & BTR_CREATE_FLAG)); ut_ad(mtr->is_named_space(index->table->space)); ut_ad(page_rec_is_leaf(rec)); @@ -5324,6 +5329,7 @@ lock_rec_insert_check_and_lock( } ut_ad(!index->table->is_temporary()); + ut_ad(page_is_leaf(block->frame)); dberr_t err; lock_t* lock; diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index 7e85c422d51..57d7854e3e3 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -235,7 +235,7 @@ page_set_autoinc( mtr, block, MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); ut_ad(index->is_primary()); ut_ad(index->page == block->page.id.page_no()); - ut_ad(index->table->space->id == block->page.id.space()); + ut_ad(index->table->space_id == block->page.id.space()); byte* field = PAGE_HEADER + PAGE_ROOT_AUTO_INC + buf_block_get_frame(block); diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 893eeb56c18..f46c381fbf7 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -900,7 +900,7 @@ loop: merge_file[t_ctx.buf_used]->offset++, block[t_ctx.buf_used], crypt_block[t_ctx.buf_used], - table->space->id)) { + table->space_id)) { error = DB_TEMP_FILE_WRITE_FAIL; goto func_exit; } @@ -994,7 +994,7 @@ exit: merge_file[i]->offset++, block[i], crypt_block[i], - table->space->id)) { + table->space_id)) { error = DB_TEMP_FILE_WRITE_FAIL; goto func_exit; } @@ -1032,7 +1032,7 @@ exit: psort_info->psort_common->dup, merge_file[i], block[i], &tmpfd[i], false, 0.0/* pct_progress */, 0.0/* pct_cost */, - crypt_block[i], table->space->id); + crypt_block[i], table->space_id); if (error != DB_SUCCESS) { os_file_close(tmpfd[i]); @@ -1702,7 +1702,7 @@ row_fts_merge_insert( #ifdef UNIV_DEBUG ins_ctx.aux_index_id = id; #endif - const ulint space = table->space->id; + const ulint space = table->space_id; for (i = 0; i < fts_sort_pll_degree; i++) { if (psort_info[i].merge_file[id]->n_rec == 0) { diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index c2d443a5c28..038f4cc31bd 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -2056,7 +2056,7 @@ row_import_discard_changes( table->file_unreadable = true; if (table->space) { - fil_close_tablespace(trx, table->space->id); + fil_close_tablespace(trx, table->space_id); table->space = NULL; } } diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 54b2b7ce2a6..0675217a391 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -435,7 +435,7 @@ row_log_online_op( if (!log_tmp_block_encrypt( buf, srv_sort_buf_size, log->crypt_tail, byte_offset, - index->table->space->id)) { + index->table->space_id)) { log->error = DB_DECRYPTION_FAILED; goto write_failed; } @@ -573,7 +573,7 @@ row_log_table_close_func( if (!log_tmp_block_encrypt( log->tail.block, srv_sort_buf_size, log->crypt_tail, byte_offset, - index->table->space->id)) { + index->table->space_id)) { log->error = DB_DECRYPTION_FAILED; goto err_exit; } @@ -2878,7 +2878,7 @@ all_done: if (!log_tmp_block_decrypt( buf, srv_sort_buf_size, index->online_log->crypt_head, - ofs, index->table->space->id)) { + ofs, index->table->space_id)) { error = DB_DECRYPTION_FAILED; goto func_exit; } @@ -3782,7 +3782,7 @@ all_done: if (!log_tmp_block_decrypt( buf, srv_sort_buf_size, index->online_log->crypt_head, - ofs, index->table->space->id)) { + ofs, index->table->space_id)) { error = DB_DECRYPTION_FAILED; goto func_exit; } diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 47ea1d34dc2..79619e805ca 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -2542,7 +2542,7 @@ write_buffers: curr_progress, pct_cost, crypt_block, - new_table->space->id); + new_table->space_id); if (row == NULL) { err = clust_btr_bulk->finish( @@ -2653,7 +2653,7 @@ write_buffers: curr_progress, pct_cost, crypt_block, - new_table->space->id); + new_table->space_id); err = btr_bulk.finish(err); @@ -2687,7 +2687,7 @@ write_buffers: if (!row_merge_write( file->fd, file->offset++, block, crypt_block, - new_table->space->id)) { + new_table->space_id)) { err = DB_TEMP_FILE_WRITE_FAIL; trx->error_key_num = i; break; @@ -4307,7 +4307,7 @@ row_make_new_pathname( dict_table_t* table, /*!< in: table to be renamed */ const char* new_name) /*!< in: new name */ { - ut_ad(!is_system_tablespace(table->space->id)); + ut_ad(!is_system_tablespace(table->space_id)); return os_file_make_new_pathname(table->space->chain.start->name, new_name); } @@ -4542,7 +4542,7 @@ row_merge_write_redo( log_ptr = mlog_open(&mtr, 11 + 8); log_ptr = mlog_write_initial_log_record_low( MLOG_INDEX_LOAD, - index->table->space->id, index->page, log_ptr, &mtr); + index->table->space_id, index->page, log_ptr, &mtr); mach_write_to_8(log_ptr, index->id); mlog_close(&mtr, log_ptr + 8); mtr.commit(); @@ -4900,7 +4900,7 @@ wait_again: trx, &dup, &merge_files[i], block, &tmpfd, true, pct_progress, pct_cost, - crypt_block, new_table->space->id, + crypt_block, new_table->space_id, stage); pct_progress += pct_cost; @@ -4943,7 +4943,7 @@ wait_again: merge_files[i].fd, block, NULL, &btr_bulk, merge_files[i].n_rec, pct_progress, pct_cost, - crypt_block, new_table->space->id, + crypt_block, new_table->space_id, stage); error = btr_bulk.finish(error); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 371aca1f772..7bf5963068a 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2466,7 +2466,7 @@ err_exit: /* We already have .ibd file here. it should be deleted. */ if (dict_table_is_file_per_table(table) - && fil_delete_tablespace(table->space->id) != DB_SUCCESS) { + && fil_delete_tablespace(table->space_id) != DB_SUCCESS) { ib::error() << "Cannot delete the file of table " << table->name; } @@ -2489,9 +2489,8 @@ err_exit: } /*********************************************************************//** -Does an index creation operation for MySQL. TODO: currently failure -to create an index results in dropping the whole table! This is no problem -currently as all indexes must be created at the same time as the table. +Create an index when creating a table. +On failure, the caller must drop the table! @return error number or DB_SUCCESS */ dberr_t row_create_index_for_mysql( @@ -2514,16 +2513,9 @@ row_create_index_for_mysql( ulint len; dict_table_t* table = index->table; - trx->op_info = "creating index"; - ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X)); ut_ad(mutex_own(&dict_sys->mutex)); - - if (!table->is_temporary()) { - trx_start_if_not_started_xa(trx, true); - } - for (i = 0; i < index->n_def; i++) { /* Check that prefix_len and actual length < DICT_MAX_INDEX_COL_LEN */ @@ -2541,19 +2533,19 @@ row_create_index_for_mysql( /* Column or prefix length exceeds maximum column length */ if (len > (ulint) DICT_MAX_FIELD_LEN_BY_FORMAT(table)) { - err = DB_TOO_BIG_INDEX_COL; - dict_mem_index_free(index); - goto error_handling; + return DB_TOO_BIG_INDEX_COL; } } - trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); + trx->op_info = "creating index"; /* For temp-table we avoid insertion into SYSTEM TABLES to maintain performance and so we have separate path that directly just updates dictonary cache. */ if (!table->is_temporary()) { + trx_start_if_not_started_xa(trx, true); + trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); /* Note that the space id where we store the index is inherited from the table in dict_build_index_def_step() in dict0crea.cc. */ @@ -2600,22 +2592,6 @@ row_create_index_for_mysql( } } - if (err != DB_SUCCESS) { -error_handling: - /* We have special error handling here */ - - trx->error_state = DB_SUCCESS; - - if (trx_is_started(trx)) { - row_drop_table_for_mysql(table->name.m_name, trx, - SQLCOM_DROP_TABLE, true); - trx_rollback_to_savepoint(trx, NULL); - ut_ad(!trx_is_started(trx)); - } - - trx->error_state = DB_SUCCESS; - } - trx->op_info = ""; return(err); @@ -3801,7 +3777,7 @@ do_drop: && dict_table_get_low("SYS_DATAFILES")) { info = pars_info_create(); pars_info_add_int4_literal(info, "id", - lint(table->space->id)); + lint(table->space_id)); err = que_eval_sql( info, "PROCEDURE DROP_SPACE_PROC () IS\n" diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc index d9b52484a94..d77cc1e33dc 100644 --- a/storage/innobase/row/row0quiesce.cc +++ b/storage/innobase/row/row0quiesce.cc @@ -141,7 +141,7 @@ row_quiesce_write_indexes( mach_write_to_8(ptr, index->id); ptr += sizeof(index_id_t); - mach_write_to_4(ptr, table->space->id); + mach_write_to_4(ptr, table->space_id); ptr += sizeof(ib_uint32_t); mach_write_to_4(ptr, index->page); @@ -525,7 +525,7 @@ row_quiesce_table_start( } for (ulint count = 0; - ibuf_merge_space(table->space->id) != 0 + ibuf_merge_space(table->space_id) != 0 && !trx_is_interrupted(trx); ++count) { if (!(count % 20)) { @@ -537,7 +537,7 @@ row_quiesce_table_start( if (!trx_is_interrupted(trx)) { { FlushObserver observer(table->space, trx, NULL); - buf_LRU_flush_or_remove_pages(table->space->id, + buf_LRU_flush_or_remove_pages(table->space_id, &observer); } @@ -637,7 +637,7 @@ row_quiesce_set_state( ER_CANNOT_DISCARD_TEMPORARY_TABLE); return(DB_UNSUPPORTED); - } else if (table->space->id == TRX_SYS_SPACE) { + } else if (table->space_id == TRX_SYS_SPACE) { char table_name[MAX_FULL_NAME_LEN + 1]; diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 929fd675135..0804c1bede2 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -1133,7 +1133,7 @@ re_scan: btr_pcur_get_page(pcur)); cur_block = buf_page_get_gen( - page_id_t(index->table->space->id, page_no), + page_id_t(index->table->space_id, page_no), page_size_t(index->table->space->flags), RW_X_LATCH, NULL, BUF_GET, __FILE__, __LINE__, mtr, &err); diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index 164bcb46d68..5b39862c6fb 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -412,7 +412,7 @@ static bool row_undo_ins_parse_undo_rec(undo_node_t* node, bool dict_locked) dict_table_t* table = node->table; ut_ad(!table->is_temporary()); ut_ad(dict_table_is_file_per_table(table) - == !is_system_tablespace(table->space->id)); + == !is_system_tablespace(table->space_id)); size_t len = mach_read_from_2(node->undo_rec) + size_t(node->undo_rec - ptr) - 2; ptr[len] = 0; diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 5291290c643..0e59c09c693 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2307,7 +2307,7 @@ row_upd_sec_index_entry( mtr.start(); - switch (index->table->space->id) { + switch (index->table->space_id) { case SRV_TMP_SPACE_ID: mtr.set_log_mode(MTR_LOG_NO_REDO); flags = BTR_NO_LOCKING_FLAG; diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index 25fc3522f94..8fa71689caf 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -1944,7 +1944,7 @@ srv_mon_process_existing_counter( break; case MONITOR_OVLD_N_FILE_OPENED: - value = fil_n_file_opened; + value = fil_system.n_open; break; case MONITOR_OVLD_IBUF_MERGE_INSERT: diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 86899eb5162..8db656cd561 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1578,7 +1578,7 @@ srv_export_innodb_status(void) export_vars.innodb_system_rows_deleted = srv_stats.n_system_rows_deleted; - export_vars.innodb_num_open_files = fil_n_file_opened; + export_vars.innodb_num_open_files = fil_system.n_open; export_vars.innodb_truncated_status_writes = srv_truncated_status_writes; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index ffcec1b7eb0..fa38741fb5d 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -462,23 +462,16 @@ create_log_files( const ulint size = ulint(srv_log_file_size >> srv_page_size_shift); - logfile0 = fil_node_create( - logfilename, size, log_space, false, false); + logfile0 = log_space->add(logfilename, OS_FILE_CLOSED, size, + false, false)->name; ut_a(logfile0); for (unsigned i = 1; i < srv_n_log_files; i++) { sprintf(logfilename + dirnamelen, "ib_logfile%u", i); - if (!fil_node_create(logfilename, size, - log_space, false, false)) { - - ib::error() - << "Cannot create file node for log file " - << logfilename; - - return(DB_ERROR); - } + log_space->add(logfilename, OS_FILE_CLOSED, size, + false, false); } log_sys.log.create(srv_n_log_files); @@ -626,83 +619,68 @@ srv_undo_tablespace_create( return(err); } -/*********************************************************************//** -Open an undo tablespace. -@return DB_SUCCESS or error code */ -static -dberr_t -srv_undo_tablespace_open( -/*=====================*/ - const char* name, /*!< in: tablespace file name */ - ulint space_id) /*!< in: tablespace id */ + +/** Open an undo tablespace. +@param[in] name tablespace file name +@param[in] space_id tablespace ID +@param[in] create_new_db whether undo tablespaces are being created +@return whether the tablespace was opened */ +static bool srv_undo_tablespace_open(const char* name, ulint space_id, + bool create_new_db) { pfs_os_file_t fh; - bool ret; - dberr_t err = DB_ERROR; + bool success; char undo_name[sizeof "innodb_undo000"]; snprintf(undo_name, sizeof(undo_name), "innodb_undo%03u", static_cast<unsigned>(space_id)); - if (!srv_file_check_mode(name)) { - ib::error() << "UNDO tablespaces must be " << - (srv_read_only_mode ? "writable" : "readable") << "!"; - - return(DB_ERROR); - } - fh = os_file_create( - innodb_data_file_key, name, - OS_FILE_OPEN_RETRY - | OS_FILE_ON_ERROR_NO_EXIT - | OS_FILE_ON_ERROR_SILENT, - OS_FILE_NORMAL, - OS_DATA_FILE, - srv_read_only_mode, - &ret); - - /* If the file open was successful then load the tablespace. */ - - if (ret) { - os_offset_t size; - fil_space_t* space; - - size = os_file_get_size(fh); - ut_a(size != (os_offset_t) -1); + innodb_data_file_key, name, OS_FILE_OPEN + | OS_FILE_ON_ERROR_NO_EXIT | OS_FILE_ON_ERROR_SILENT, + OS_FILE_AIO, OS_DATA_FILE, srv_read_only_mode, &success); + if (!success) { + return false; + } - ret = os_file_close(fh); - ut_a(ret); + os_offset_t size = os_file_get_size(fh); + ut_a(size != os_offset_t(-1)); - /* Load the tablespace into InnoDB's internal - data structures. */ + /* Load the tablespace into InnoDB's internal data structures. */ - /* We set the biggest space id to the undo tablespace - because InnoDB hasn't opened any other tablespace apart - from the system tablespace. */ + /* We set the biggest space id to the undo tablespace + because InnoDB hasn't opened any other tablespace apart + from the system tablespace. */ - fil_set_max_space_id_if_bigger(space_id); + fil_set_max_space_id_if_bigger(space_id); - space = fil_space_create( - undo_name, space_id, FSP_FLAGS_PAGE_SSIZE(), - FIL_TYPE_TABLESPACE, NULL); + fil_space_t* space = fil_space_create( + undo_name, space_id, FSP_FLAGS_PAGE_SSIZE(), + FIL_TYPE_TABLESPACE, NULL); - ut_a(fil_validate()); - ut_a(space); + ut_a(fil_validate()); + ut_a(space); - os_offset_t n_pages = size >> srv_page_size_shift; + fil_node_t* file = space->add(name, fh, 0, false, true); - /* On 32-bit platforms, ulint is 32 bits and os_offset_t - is 64 bits. It is OK to cast the n_pages to ulint because - the unit has been scaled to pages and page number is always - 32 bits. */ - if (fil_node_create( - name, (ulint) n_pages, space, false, TRUE)) { + mutex_enter(&fil_system.mutex); - err = DB_SUCCESS; + if (create_new_db) { + space->size = file->size = ulint(size >> srv_page_size_shift); + space->size_in_header = SRV_UNDO_TABLESPACE_SIZE_IN_PAGES; + } else { + success = file->read_page0(true); + if (!success) { + os_file_close(file->handle); + file->handle = OS_FILE_CLOSED; + ut_a(fil_system.n_open > 0); + fil_system.n_open--; } } - return(err); + mutex_exit(&fil_system.mutex); + + return success; } /** Check if undo tablespaces and redo log files exist before creating a @@ -888,12 +866,11 @@ srv_undo_tablespaces_init(bool create_new_db) ut_a(undo_tablespace_ids[i] != 0); ut_a(undo_tablespace_ids[i] != ULINT_UNDEFINED); - err = srv_undo_tablespace_open(name, undo_tablespace_ids[i]); - - if (err != DB_SUCCESS) { + if (!srv_undo_tablespace_open(name, undo_tablespace_ids[i], + create_new_db)) { ib::error() << "Unable to open undo tablespace '" << name << "'."; - return(err); + return DB_ERROR; } prev_space_id = undo_tablespace_ids[i]; @@ -918,9 +895,8 @@ srv_undo_tablespaces_init(bool create_new_db) name, sizeof(name), "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, i); - err = srv_undo_tablespace_open(name, i); - - if (err != DB_SUCCESS) { + if (!srv_undo_tablespace_open(name, i, create_new_db)) { + err = DB_ERROR; break; } @@ -1759,10 +1735,8 @@ dberr_t srv_start(bool create_new_db) for (unsigned j = 0; j < srv_n_log_files_found; j++) { sprintf(logfilename + dirnamelen, "ib_logfile%u", j); - if (!fil_node_create(logfilename, size, - log_space, false, false)) { - return(srv_init_abort(DB_ERROR)); - } + log_space->add(logfilename, OS_FILE_CLOSED, size, + false, false); } log_sys.log.create(srv_n_log_files_found); diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index d4f2d0b1b00..a0ceb44b8d1 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -784,9 +784,7 @@ trx_lists_init_at_db_start() evenly distributed between 0 and innodb_undo_logs-1 @return persistent rollback segment @retval NULL if innodb_read_only */ -static -trx_rseg_t* -trx_assign_rseg_low() +static trx_rseg_t* trx_assign_rseg_low() { if (srv_read_only_mode) { ut_ad(srv_undo_logs == ULONG_UNDEFINED); @@ -837,8 +835,8 @@ trx_assign_rseg_low() ut_ad(rseg->is_persistent()); if (rseg->space != fil_system.sys_space) { - ut_ad(srv_undo_tablespaces > 1); - if (rseg->skip_allocation) { + if (rseg->skip_allocation + || !srv_undo_tablespaces) { continue; } } else if (trx_rseg_t* next diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp index 4af8811800e..7a41442d4ba 100644 --- a/storage/mroonga/ha_mroonga.cpp +++ b/storage/mroonga/ha_mroonga.cpp @@ -10576,7 +10576,7 @@ int ha_mroonga::generic_store_bulk_time(Field *field, grn_obj *buf) bool truncated = false; Field_time *time_field = (Field_time *)field; MYSQL_TIME mysql_time; - time_field->get_time(&mysql_time); + time_field->get_date(&mysql_time, Time::Options(current_thd)); mrn::TimeConverter time_converter; long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); @@ -10596,7 +10596,7 @@ int ha_mroonga::generic_store_bulk_datetime(Field *field, grn_obj *buf) bool truncated = false; Field_datetime *datetime_field = (Field_datetime *)field; MYSQL_TIME mysql_time; - datetime_field->get_time(&mysql_time); + datetime_field->get_date(&mysql_time, Time::Options(current_thd)); mrn::TimeConverter time_converter; long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); @@ -10657,7 +10657,7 @@ int ha_mroonga::generic_store_bulk_datetime2(Field *field, grn_obj *buf) bool truncated = false; Field_datetimef *datetimef_field = (Field_datetimef *)field; MYSQL_TIME mysql_time; - datetimef_field->get_time(&mysql_time); + datetimef_field->get_date(&mysql_time, Time::Options(current_thd)); mrn::TimeConverter time_converter; long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); @@ -10682,7 +10682,7 @@ int ha_mroonga::generic_store_bulk_time2(Field *field, grn_obj *buf) int error = 0; bool truncated = false; MYSQL_TIME mysql_time; - field->get_time(&mysql_time); + field->get_date(&mysql_time, Time::Options(current_thd)); mrn::TimeConverter time_converter; long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); @@ -10707,7 +10707,7 @@ int ha_mroonga::generic_store_bulk_new_date(Field *field, grn_obj *buf) bool truncated = false; Field_newdate *newdate_field = (Field_newdate *)field; MYSQL_TIME mysql_date; - newdate_field->get_time(&mysql_date); + newdate_field->get_date(&mysql_date, Time::Options(current_thd)); mrn::TimeConverter time_converter; long long int time = time_converter.mysql_time_to_grn_time(&mysql_date, &truncated); @@ -11617,14 +11617,14 @@ int ha_mroonga::storage_encode_key_timestamp(Field *field, const uchar *key, } else { Field_timestamp_hires *timestamp_hires_field = (Field_timestamp_hires *)field; - uint fuzzy_date = 0; uchar *ptr_backup = field->ptr; uchar *null_ptr_backup = field->null_ptr; TABLE *table_backup = field->table; field->ptr = (uchar *)key; field->null_ptr = (uchar *)(key - 1); field->table = table; - timestamp_hires_field->get_date(&mysql_time, date_mode_t(fuzzy_date)); + Temporal::Options opt(TIME_CONV_NONE, current_thd); + timestamp_hires_field->get_date(&mysql_time, opt); field->ptr = ptr_backup; field->null_ptr = null_ptr_backup; field->table = table_backup; @@ -11675,12 +11675,12 @@ int ha_mroonga::storage_encode_key_time(Field *field, const uchar *key, mysql_time.time_type = MYSQL_TIMESTAMP_TIME; } else { Field_time_hires *time_hires_field = (Field_time_hires *)field; - uint fuzzy_date = 0; uchar *ptr_backup = field->ptr; uchar *null_ptr_backup = field->null_ptr; field->ptr = (uchar *)key; field->null_ptr = (uchar *)(key - 1); - time_hires_field->get_date(&mysql_time, date_mode_t(fuzzy_date)); + Temporal::Options opt(TIME_CONV_NONE, current_thd); + time_hires_field->get_date(&mysql_time, opt); field->ptr = ptr_backup; field->null_ptr = null_ptr_backup; } @@ -11749,12 +11749,12 @@ int ha_mroonga::storage_encode_key_datetime(Field *field, const uchar *key, if (field->decimals() > 0) { Field_datetime_hires *datetime_hires_field = (Field_datetime_hires *)field; MYSQL_TIME mysql_time; - uint fuzzy_date = 0; uchar *ptr_backup = field->ptr; uchar *null_ptr_backup = field->null_ptr; field->ptr = (uchar *)key; field->null_ptr = (uchar *)(key - 1); - datetime_hires_field->get_date(&mysql_time, date_mode_t(fuzzy_date)); + Temporal::Options opt(TIME_CONV_NONE, current_thd); + datetime_hires_field->get_date(&mysql_time, opt); field->ptr = ptr_backup; field->null_ptr = null_ptr_backup; mrn::TimeConverter time_converter; diff --git a/storage/mroonga/lib/mrn_condition_converter.cpp b/storage/mroonga/lib/mrn_condition_converter.cpp index 49f8e10753a..68ffa073f4f 100644 --- a/storage/mroonga/lib/mrn_condition_converter.cpp +++ b/storage/mroonga/lib/mrn_condition_converter.cpp @@ -258,8 +258,11 @@ namespace mrn { Item *real_value_item = value_item->real_item(); switch (field_item->field->type()) { case MYSQL_TYPE_TIME: - error = real_value_item->get_time(current_thd, mysql_time); + { + THD *thd= current_thd; + error= real_value_item->get_date(thd, mysql_time, Time::Options(thd)); break; + } case MYSQL_TYPE_YEAR: mysql_time->year = static_cast<int>(value_item->val_int()); mysql_time->month = 1; @@ -273,9 +276,13 @@ namespace mrn { error = false; break; default: - error = real_value_item->get_date(current_thd, mysql_time, TIME_FUZZY_DATES); + { + THD *thd= current_thd; + Datetime::Options opt(TIME_FUZZY_DATES, thd); + error = real_value_item->get_date(thd, mysql_time, opt); break; } + } DBUG_RETURN(error); } diff --git a/storage/rocksdb/mysql-test/rocksdb/r/xa.result b/storage/rocksdb/mysql-test/rocksdb/r/xa.result new file mode 100644 index 00000000000..30cfe94e0b7 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/r/xa.result @@ -0,0 +1,32 @@ +# +# MDEV-13155: XA recovery not supported for RocksDB (Just a testcase) +# +call mtr.add_suppression("Found .* prepared XA transactions"); +connect con1,localhost,root,,test; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a INT) ENGINE=RocksDB; +XA START 'xa1'; +INSERT INTO t1 (a) VALUES (1),(2); +XA END 'xa1'; +XA PREPARE 'xa1'; +connect con2,localhost,root,,test; +XA START 'xa2'; +INSERT INTO t1 (a) VALUES (3); +INSERT INTO t1 (a) VALUES (4); +XA END 'xa2'; +XA PREPARE 'xa2'; +connection default; +SELECT * FROM t1; +a +connect con3,localhost,root,,test; +XA RECOVER; +formatID gtrid_length bqual_length data +1 3 0 xa1 +1 3 0 xa2 +XA ROLLBACK 'xa1'; +XA COMMIT 'xa2'; +SELECT a FROM t1; +a +3 +4 +DROP TABLE t1; diff --git a/storage/rocksdb/mysql-test/rocksdb/t/xa-master.opt b/storage/rocksdb/mysql-test/rocksdb/t/xa-master.opt new file mode 100644 index 00000000000..70c120604f6 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/t/xa-master.opt @@ -0,0 +1 @@ +--rocksdb_flush_log_at_trx_commit=1 diff --git a/storage/rocksdb/mysql-test/rocksdb/t/xa.test b/storage/rocksdb/mysql-test/rocksdb/t/xa.test new file mode 100644 index 00000000000..f8f381f0580 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/t/xa.test @@ -0,0 +1,38 @@ +--echo # +--echo # MDEV-13155: XA recovery not supported for RocksDB (Just a testcase) +--echo # + +call mtr.add_suppression("Found .* prepared XA transactions"); + +--connect (con1,localhost,root,,test) +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (a INT) ENGINE=RocksDB; + +XA START 'xa1'; +INSERT INTO t1 (a) VALUES (1),(2); +XA END 'xa1'; +XA PREPARE 'xa1'; + +--connect (con2,localhost,root,,test) +XA START 'xa2'; +INSERT INTO t1 (a) VALUES (3); +INSERT INTO t1 (a) VALUES (4); +XA END 'xa2'; +XA PREPARE 'xa2'; + +--connection default +SELECT * FROM t1; + +--let $shutdown_timeout= 0 +--source include/restart_mysqld.inc + +--connect (con3,localhost,root,,test) +--disable_abort_on_error +XA RECOVER; +XA ROLLBACK 'xa1'; +XA COMMIT 'xa2'; +SELECT a FROM t1; +DROP TABLE t1; |