From 275f434392d6e04ece74ddec70abde75c6d86603 Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Tue, 12 Sep 2023 22:17:13 +0300 Subject: [PATCH 001/158] MDEV-25163 Rowid filter does not process storage engine error correctly. The fix is to return 3-state value from Range_rowid_filter::build() call: 1. The filter was built successfully; 2. The filter was not built, but the error was not fatal, i.e. there is no need to rollback transaction. For example, if the size of container to storevrow ids is not enough; 3. The filter was not built because of fatal error, for example, deadlock or lock wait timeout from storage engine. In this case we should stop query plan execution and roll back transaction. Reviewed by: Sergey Petrunya --- mysql-test/main/rowid_filter_innodb.result | 29 ++++++++++++ mysql-test/main/rowid_filter_innodb.test | 35 +++++++++++++++ sql/rowid_filter.cc | 52 +++++++++++++++------- sql/rowid_filter.h | 11 +++-- sql/sql_join_cache.cc | 6 ++- sql/sql_select.cc | 26 ++++++++--- sql/sql_select.h | 2 +- 7 files changed, 132 insertions(+), 29 deletions(-) diff --git a/mysql-test/main/rowid_filter_innodb.result b/mysql-test/main/rowid_filter_innodb.result index 1bf63d9a378..6bc00da6f4c 100644 --- a/mysql-test/main/rowid_filter_innodb.result +++ b/mysql-test/main/rowid_filter_innodb.result @@ -2717,6 +2717,35 @@ SELECT a FROM t1 WHERE c < 'k' AND b > 't' ORDER BY a; a 1 5 +# +# MDEV-25163 Rowid filter does not process storage engine error correctly. +# +CREATE TABLE two(tw int) Engine=MyISAM; +INSERT INTO two VALUES (1),(2); +SET GLOBAL innodb_stats_persistent= OFF; +EXPLAIN EXTENDED +SELECT a FROM t1 WHERE c < 'k' AND b > 't' ORDER BY a FOR UPDATE; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range|filter b,c b|c 13|1027 NULL 5 (42%) 41.67 Using index condition; Using where; Using filesort; Using rowid filter +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`c` < 'k' and `test`.`t1`.`b` > 't' order by `test`.`t1`.`a` for update +EXPLAIN EXTENDED +SELECT a FROM t1,two WHERE c < 'k' AND b > 't' ORDER BY a FOR UPDATE; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE two ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort +1 SIMPLE t1 range|filter b,c b|c 13|1027 NULL 5 (42%) 41.67 Using index condition; Using where; Using join buffer (flat, BNL join); Using rowid filter +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`two` where `test`.`t1`.`c` < 'k' and `test`.`t1`.`b` > 't' order by `test`.`t1`.`a` for update +SET @saved_dbug = @@SESSION.debug_dbug; +SET debug_dbug = '+d,innodb_report_deadlock'; +SELECT a FROM t1 WHERE c < 'k' AND b > 't' ORDER BY a FOR UPDATE; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET debug_dbug = @saved_dbug; +SET debug_dbug = '+d,innodb_report_deadlock'; +SELECT a FROM t1,two WHERE c < 'k' AND b > 't' ORDER BY a FOR UPDATE; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET debug_dbug = @saved_dbug; +DROP TABLE two; DROP TABLE t1; SET GLOBAL innodb_stats_persistent= @stats.save; # diff --git a/mysql-test/main/rowid_filter_innodb.test b/mysql-test/main/rowid_filter_innodb.test index f4d0b241d11..d5f3e4d4a6b 100644 --- a/mysql-test/main/rowid_filter_innodb.test +++ b/mysql-test/main/rowid_filter_innodb.test @@ -1,5 +1,6 @@ --source include/no_valgrind_without_big.inc --source include/have_innodb.inc +--source include/have_debug.inc SET SESSION STORAGE_ENGINE='InnoDB'; @@ -132,6 +133,40 @@ SELECT a FROM t1 WHERE c < 'k' AND b > 't' ORDER BY a; SELECT a FROM t1 WHERE c < 'k' AND b > 't' ORDER BY a; +--echo # +--echo # MDEV-25163 Rowid filter does not process storage engine error correctly. +--echo # + +CREATE TABLE two(tw int) Engine=MyISAM; +INSERT INTO two VALUES (1),(2); + +# Switch off statistics update to catch correct create lock function call +SET GLOBAL innodb_stats_persistent= OFF; + +# Make sure it's still rowid filter + filesort +EXPLAIN EXTENDED +SELECT a FROM t1 WHERE c < 'k' AND b > 't' ORDER BY a FOR UPDATE; + +EXPLAIN EXTENDED +SELECT a FROM t1,two WHERE c < 'k' AND b > 't' ORDER BY a FOR UPDATE; + +SET @saved_dbug = @@SESSION.debug_dbug; +# Deadlock error should be returned from InnoDB during rowid filter container +# filling. If MDEV-25163 is not fixed, there will be assertion failure in +# InnoDB, as allready rolled back trx_t object will be used in filesort +# operation. +SET debug_dbug = '+d,innodb_report_deadlock'; +--error ER_LOCK_DEADLOCK +SELECT a FROM t1 WHERE c < 'k' AND b > 't' ORDER BY a FOR UPDATE; +SET debug_dbug = @saved_dbug; + +# Same as above for the join query: +SET debug_dbug = '+d,innodb_report_deadlock'; +--error ER_LOCK_DEADLOCK +SELECT a FROM t1,two WHERE c < 'k' AND b > 't' ORDER BY a FOR UPDATE; +SET debug_dbug = @saved_dbug; + +DROP TABLE two; DROP TABLE t1; SET GLOBAL innodb_stats_persistent= @stats.save; diff --git a/sql/rowid_filter.cc b/sql/rowid_filter.cc index 75f2ab71ecd..9ca2d3849f3 100644 --- a/sql/rowid_filter.cc +++ b/sql/rowid_filter.cc @@ -536,8 +536,11 @@ TABLE::best_range_rowid_filter_for_partial_join(uint access_key_no, range filter and place into the filter the rowids / primary keys read from key tuples when doing this scan. @retval - false on success - true otherwise + Rowid_filter::SUCCESS on success + Rowid_filter::NON_FATAL_ERROR the error which does not require transaction + rollback + Rowid_filter::FATAL_ERROR the error which does require transaction + rollback @note The function assumes that the quick select object to perform @@ -550,9 +553,9 @@ TABLE::best_range_rowid_filter_for_partial_join(uint access_key_no, purposes to facilitate a lazy building of the filter. */ -bool Range_rowid_filter::fill() +Rowid_filter::build_return_code Range_rowid_filter::build() { - int rc= 0; + build_return_code rc= SUCCESS; handler *file= table->file; THD *thd= table->in_use; QUICK_RANGE_SELECT* quick= (QUICK_RANGE_SELECT*) select->quick; @@ -573,18 +576,34 @@ bool Range_rowid_filter::fill() table->file->ha_start_keyread(quick->index); if (quick->init() || quick->reset()) - rc= 1; - - while (!rc) + rc= FATAL_ERROR; + else { - rc= quick->get_next(); - if (thd->killed) - rc= 1; - if (!rc) + for (;;) { + int quick_get_next_result= quick->get_next(); + if (thd->killed) + { + rc= FATAL_ERROR; + break; + } + if (quick_get_next_result != 0) + { + rc= (quick_get_next_result == HA_ERR_END_OF_FILE ? SUCCESS + : FATAL_ERROR); + /* + The error state has been set by file->print_error(res, MYF(0)) call + inside quick->get_next() call, in Mrr_simple_index_reader::get_next() + */ + DBUG_ASSERT(rc == SUCCESS || thd->is_error()); + break; + } file->position(quick->record); - if (container->add(NULL, (char*) file->ref)) - rc= 1; + if (container->add(NULL, (char *) file->ref)) + { + rc= NON_FATAL_ERROR; + break; + } else tracker->increment_container_elements_count(); } @@ -599,10 +618,9 @@ bool Range_rowid_filter::fill() file->in_range_check_pushed_down= in_range_check_pushed_down_save; tracker->report_container_buff_size(table->file->ref_length); - if (rc != HA_ERR_END_OF_FILE) - return 1; - table->file->rowid_filter_is_active= true; - return 0; + if (rc == SUCCESS) + table->file->rowid_filter_is_active= true; + return rc; } diff --git a/sql/rowid_filter.h b/sql/rowid_filter.h index eabf1f05fec..1e9b2eb5971 100644 --- a/sql/rowid_filter.h +++ b/sql/rowid_filter.h @@ -217,6 +217,11 @@ protected: Rowid_filter_tracker *tracker; public: + enum build_return_code { + SUCCESS, + NON_FATAL_ERROR, + FATAL_ERROR, + }; Rowid_filter(Rowid_filter_container *container_arg) : container(container_arg) {} @@ -224,7 +229,7 @@ public: Build the filter : fill it with info on the set of elements placed there */ - virtual bool build() = 0; + virtual build_return_code build() = 0; /* Check whether an element is in the filter. @@ -269,7 +274,7 @@ public: ~Range_rowid_filter(); - bool build() { return fill(); } + build_return_code build(); bool check(char *elem) { @@ -280,8 +285,6 @@ public: return was_checked; } - bool fill(); - SQL_SELECT *get_select() { return select; } }; diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index f1dd23d9618..e7b096b420b 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -2338,7 +2338,11 @@ enum_nested_loop_state JOIN_CACHE::join_matching_records(bool skip_last) if ((rc= join_tab_execution_startup(join_tab)) < 0) goto finish2; - join_tab->build_range_rowid_filter_if_needed(); + if (join_tab->build_range_rowid_filter_if_needed()) + { + rc= NESTED_LOOP_ERROR; + goto finish2; + } /* Prepare to retrieve all records of the joined table */ if (unlikely((error= join_tab_scan->open()))) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 805ba19f0bc..d7badbc59a5 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13626,8 +13626,18 @@ bool error_if_full_join(JOIN *join) } -void JOIN_TAB::build_range_rowid_filter_if_needed() +/** + Build rowid filter. + + @retval + 0 ok + @retval + 1 Error, transaction should be rolled back +*/ + +bool JOIN_TAB::build_range_rowid_filter_if_needed() { + bool result= false; if (rowid_filter && !is_rowid_filter_built) { /** @@ -13642,10 +13652,9 @@ void JOIN_TAB::build_range_rowid_filter_if_needed() Rowid_filter_tracker *rowid_tracker= rowid_filter->get_tracker(); table->file->set_time_tracker(rowid_tracker->get_time_tracker()); rowid_tracker->start_tracking(); - if (!rowid_filter->build()) - { + Rowid_filter::build_return_code build_rc= rowid_filter->build(); + if (build_rc == Rowid_filter::SUCCESS) is_rowid_filter_built= true; - } else { delete rowid_filter; @@ -13653,7 +13662,9 @@ void JOIN_TAB::build_range_rowid_filter_if_needed() } rowid_tracker->stop_tracking(); table->file->set_time_tracker(table_tracker); + result= (build_rc == Rowid_filter::FATAL_ERROR); } + return result; } @@ -20853,7 +20864,9 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) if (!join_tab->preread_init_done && join_tab->preread_init()) DBUG_RETURN(NESTED_LOOP_ERROR); - join_tab->build_range_rowid_filter_if_needed(); + if (join_tab->build_range_rowid_filter_if_needed()) + DBUG_RETURN(NESTED_LOOP_ERROR); + if (join_tab->rowid_filter && join_tab->rowid_filter->is_empty()) rc= NESTED_LOOP_NO_MORE_ROWS; @@ -21810,7 +21823,8 @@ int join_init_read_record(JOIN_TAB *tab) if (tab->distinct && tab->remove_duplicates()) // Remove duplicates. return 1; - tab->build_range_rowid_filter_if_needed(); + if (tab->build_range_rowid_filter_if_needed()) + return 1; if (tab->filesort && tab->sort_table()) // Sort table. return 1; diff --git a/sql/sql_select.h b/sql/sql_select.h index 5c00a77638a..b0fa0b66b62 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -541,7 +541,7 @@ typedef struct st_join_table { /* Becomes true just after the used range filter has been built / filled */ bool is_rowid_filter_built; - void build_range_rowid_filter_if_needed(); + bool build_range_rowid_filter_if_needed(); void cleanup(); inline bool is_using_loose_index_scan() From ca66a2cbfa5f0c47b6f0af196c968fa356cfdabf Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 19 Sep 2023 11:33:51 +1000 Subject: [PATCH 002/158] MDEV-18200 MariaBackup full backup failed with InnoDB: Failing assertion: success There are many filesystem related errors that can occur with MariaBackup. These already outputed to stderr with a good description of the error. Many of these are permission or resource (file descriptor) limits where the assertion and resulting core crash doesn't offer developers anything more than the log message. To the user, assertions and core crashes come across as poor error handling. As such we return an error and handle this all the way up the stack. --- extra/mariabackup/xtrabackup.cc | 27 +++++++++++++------ .../suite/mariabackup/data_directory.result | 6 +++++ .../suite/mariabackup/data_directory.test | 15 +++++++++++ plugin/cracklib_password_check/CMakeLists.txt | 6 +++++ storage/innobase/fil/fil0fil.cc | 18 ++++++++----- storage/innobase/include/log0log.h | 5 ++-- storage/innobase/log/log0log.cc | 21 ++++++++------- storage/innobase/log/log0recv.cc | 14 +++++++--- 8 files changed, 82 insertions(+), 30 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 96c90b5afad..64a0f44e183 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -4503,14 +4503,21 @@ bool Backup_datasinks::backup_low() if (recv_find_max_checkpoint(&max_cp_field) == DB_SUCCESS && log_sys.log.format != 0) { - if (max_cp_field == LOG_CHECKPOINT_1) { - log_header_read(max_cp_field); + switch (max_cp_field) { + case LOG_CHECKPOINT_1: + if (log_header_read(max_cp_field)) { + /* metadata_to_lsn still 0 so error returns below */ + msg("Error: recv_find_max_checkpoint() failed."); + break; + } + /* fallthrough */ + default: + metadata_to_lsn = mach_read_from_8( + log_sys.checkpoint_buf + LOG_CHECKPOINT_LSN); + msg("mariabackup: The latest check point" + " (for incremental): '" LSN_PF "'", + metadata_to_lsn); } - metadata_to_lsn = mach_read_from_8( - log_sys.checkpoint_buf + LOG_CHECKPOINT_LSN); - msg("mariabackup: The latest check point" - " (for incremental): '" LSN_PF "'", - metadata_to_lsn); } else { msg("Error: recv_find_max_checkpoint() failed."); } @@ -4721,7 +4728,11 @@ reread_log_header: checkpoint_lsn_start = log_sys.log.get_lsn(); checkpoint_no_start = log_sys.next_checkpoint_no; - log_header_read(max_cp_field); + if (log_header_read(max_cp_field)) { + log_mutex_exit(); + goto fail; + } + if (checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO) || checkpoint_lsn_start diff --git a/mysql-test/suite/mariabackup/data_directory.result b/mysql-test/suite/mariabackup/data_directory.result index 4e45127bd6a..8692c35239e 100644 --- a/mysql-test/suite/mariabackup/data_directory.result +++ b/mysql-test/suite/mariabackup/data_directory.result @@ -11,3 +11,9 @@ SELECT * FROM t; a 1 DROP TABLE t; +# +# MDEV-18200 MariaBackup full backup failed with InnoDB: Failing assertion: success +# +# +# End of 10.4 tests +# diff --git a/mysql-test/suite/mariabackup/data_directory.test b/mysql-test/suite/mariabackup/data_directory.test index a89b7bdccc4..ffb3ab3073c 100644 --- a/mysql-test/suite/mariabackup/data_directory.test +++ b/mysql-test/suite/mariabackup/data_directory.test @@ -21,4 +21,19 @@ rmdir $table_data_dir; SELECT * FROM t; DROP TABLE t; rmdir $targetdir; + +--echo # +--echo # MDEV-18200 MariaBackup full backup failed with InnoDB: Failing assertion: success +--echo # +let $DATADIR= `select @@datadir`; +chmod 0000 $DATADIR/ibdata1; +--disable_result_log +--error 1 +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +chmod 0755 $DATADIR/ibdata1; rmdir $table_data_dir; +rmdir $targetdir; +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/plugin/cracklib_password_check/CMakeLists.txt b/plugin/cracklib_password_check/CMakeLists.txt index 4a6337310f9..79b3b80fbef 100644 --- a/plugin/cracklib_password_check/CMakeLists.txt +++ b/plugin/cracklib_password_check/CMakeLists.txt @@ -1,3 +1,9 @@ + +IF(PLUGIN_CRACKLIB_PASSWORD_CHECK STREQUAL "NO") + ADD_FEATURE_INFO(CRACKLIB_PASSWORD_CHECK "OFF" "CrackLib Password Validation Plugin") + RETURN() +ENDIF() + INCLUDE (CheckIncludeFiles) INCLUDE (CheckLibraryExists) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index ebeb1f66101..45f8c341ee2 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -557,7 +557,9 @@ fail: &success); } - ut_a(success); + if (!success) + return false; + ut_a(node->is_open()); fil_system.n_open++; @@ -4062,8 +4064,10 @@ inline void IORequest::set_fil_node(fil_node_t* node) @param[in] message message for aio handler if non-sync aio used, else ignored @param[in] ignore_missing_space true=ignore missing space duging read -@return DB_SUCCESS, or DB_TABLESPACE_DELETED - if we are trying to do i/o on a tablespace which does not exist */ +@retval DB_SUCCESS, if successful; or +@retval DB_IO_ERROR, if unable to open file or the purpose==FIL_TYPE_IMPORT; or +@retval DB_TABLESPACE_DELETED, if we are trying to do i/o on a tablespace which + does not exist */ dberr_t fil_io( const IORequest& type, @@ -4232,11 +4236,13 @@ fil_io( return(DB_TABLESPACE_DELETED); } - /* The tablespace is for log. Currently, we just assert here + /* The tablespace is for log. We used to asssert here to prevent handling errors along the way fil_io returns. Also, if the log files are missing, it would be hard to - promise the server can continue running. */ - ut_a(0); + promise the server can continue running. However this + is also used by MariaDB-backup, so we need to handle it. */ + mutex_exit(&fil_system.mutex); + return(DB_IO_ERROR); } /* Check that at least the start offset is within the bounds of a diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 477bb0a1d05..7079479754f 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -209,8 +209,9 @@ void logs_empty_and_mark_files_at_shutdown(void); /*=======================================*/ /** Read a log group header page to log_sys.checkpoint_buf. -@param[in] header 0 or LOG_CHECKPOINT_1 or LOG_CHECKPOINT2 */ -void log_header_read(ulint header); +@param[in] header 0 or LOG_CHECKPOINT_1 or LOG_CHECKPOINT2 +@return error code (from fil_io) or DB_SUCCESS */ +dberr_t log_header_read(ulint header); /** Write checkpoint info to the log header and invoke log_mutex_exit(). @param[in] sync whether to wait for the write to complete @param[in] end_lsn start LSN of the MLOG_CHECKPOINT mini-transaction */ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index bf75b3b7c86..433483b662e 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -1355,20 +1355,21 @@ log_group_checkpoint(lsn_t end_lsn) } /** Read a log group header page to log_sys.checkpoint_buf. -@param[in] header 0 or LOG_CHECKPOINT_1 or LOG_CHECKPOINT2 */ -void log_header_read(ulint header) +@param[in] header 0 or LOG_CHECKPOINT_1 or LOG_CHECKPOINT2 +@return DB_SUCCESS or error. */ +dberr_t log_header_read(ulint header) { - ut_ad(log_mutex_own()); + ut_ad(log_mutex_own()); - log_sys.n_log_ios++; + log_sys.n_log_ios++; - MONITOR_INC(MONITOR_LOG_IO); + MONITOR_INC(MONITOR_LOG_IO); - fil_io(IORequestLogRead, true, - page_id_t(SRV_LOG_SPACE_FIRST_ID, - header >> srv_page_size_shift), - 0, header & (srv_page_size - 1), - OS_FILE_LOG_BLOCK_SIZE, log_sys.checkpoint_buf, NULL); + return fil_io(IORequestLogRead, true, + page_id_t(SRV_LOG_SPACE_FIRST_ID, + header >> srv_page_size_shift), + 0, header & (srv_page_size - 1), + OS_FILE_LOG_BLOCK_SIZE, log_sys.checkpoint_buf, NULL); } /** Write checkpoint info to the log header and invoke log_mutex_exit(). diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index eb4cb910679..5645e56903d 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1068,6 +1068,7 @@ recv_find_max_checkpoint_0(ulint* max_field) { ib_uint64_t max_no = 0; ib_uint64_t checkpoint_no; + dberr_t err; byte* buf = log_sys.checkpoint_buf; ut_ad(log_sys.log.format == 0); @@ -1085,7 +1086,8 @@ recv_find_max_checkpoint_0(ulint* max_field) for (ulint field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { - log_header_read(field); + if ((err= log_header_read(field))) + return err; if (static_cast(ut_fold_binary(buf, CHECKSUM_1)) != mach_read_from_4(buf + CHECKSUM_1) @@ -1208,13 +1210,15 @@ recv_find_max_checkpoint(ulint* max_field) ib_uint64_t checkpoint_no; ulint field; byte* buf; + dberr_t err; max_no = 0; *max_field = 0; buf = log_sys.checkpoint_buf; - log_header_read(0); + if ((err= log_header_read(0))) + return err; /* Check the header page checksum. There was no checksum in the first redo log format (version 0). */ log_sys.log.format = mach_read_from_4(buf + LOG_HEADER_FORMAT); @@ -1252,7 +1256,8 @@ recv_find_max_checkpoint(ulint* max_field) for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { - log_header_read(field); + if ((err= log_header_read(field))) + return err; const ulint crc32 = log_block_calc_checksum_crc32(buf); const ulint cksum = log_block_get_checksum(buf); @@ -3630,7 +3635,8 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) return(err); } - log_header_read(max_cp_field); + if ((err= log_header_read(max_cp_field))) + return err; buf = log_sys.checkpoint_buf; From 952f06aa8bcfad6c62d4c2bbc15ffe6e05f01008 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 20 Sep 2023 19:45:24 +0530 Subject: [PATCH 003/158] MDEV-29989 binlog_do_db option breaks versioning table Problem: ========= During commit, server calls prepare_commit_versioned to determine the transaction modified system-versioned data. Due to binlog_do_db option, we disable the binlog for the statement. But prepare_commit_versioned() is being called only when binlog is enabled for the statement. Fix: === prepare_commit_versioned() should happen irrespective of binlog state. So if the server has any read-write operation then we should call prepare_commit_versioned(). --- mysql-test/suite/versioning/t/trx_id.opt | 2 ++ sql/handler.cc | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/versioning/t/trx_id.opt diff --git a/mysql-test/suite/versioning/t/trx_id.opt b/mysql-test/suite/versioning/t/trx_id.opt new file mode 100644 index 00000000000..f900254f5d0 --- /dev/null +++ b/mysql-test/suite/versioning/t/trx_id.opt @@ -0,0 +1,2 @@ +--log_bin +--binlog_do_db=foo diff --git a/sql/handler.cc b/sql/handler.cc index ca5a3e28c28..45721d6cfbb 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1510,8 +1510,7 @@ int ha_commit_trans(THD *thd, bool all) uint rw_ha_count= ha_check_and_coalesce_trx_read_only(thd, ha_info, all); /* rw_trans is TRUE when we in a transaction changing data */ - bool rw_trans= is_real_trans && - (rw_ha_count > (thd->is_current_stmt_binlog_disabled()?0U:1U)); + bool rw_trans= is_real_trans && rw_ha_count > 0; MDL_request mdl_backup; DBUG_PRINT("info", ("is_real_trans: %d rw_trans: %d rw_ha_count: %d", is_real_trans, rw_trans, rw_ha_count)); From 8a5a07f09a7059b03a1421af21332d4d1fb633a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 8 Aug 2023 07:43:37 +0300 Subject: [PATCH 004/158] MDEV-24912 : Assertion `state() == s_executing || state() == s_prepared || state() == s_committing || state() == s_must_abort || state() == s_replaying' failed. CACHE INDEX and LOAD INDEX INTO CACHE are local operations. Therefore, do not replicate them with Galera. Signed-off-by: Julius Goryavsky --- .../suite/galera/r/galera_cache_index.result | 49 +++++++++++++++++++ .../suite/galera/t/galera_cache_index.test | 29 +++++++++++ sql/sql_admin.cc | 43 +++++++++++++++- sql/wsrep_trans_observer.h | 5 ++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera/r/galera_cache_index.result create mode 100644 mysql-test/suite/galera/t/galera_cache_index.test diff --git a/mysql-test/suite/galera/r/galera_cache_index.result b/mysql-test/suite/galera/r/galera_cache_index.result new file mode 100644 index 00000000000..d8172e6bd0d --- /dev/null +++ b/mysql-test/suite/galera/r/galera_cache_index.result @@ -0,0 +1,49 @@ +connection node_2; +connection node_1; +CREATE TABLE t1 (c1 int, UNIQUE INDEX (c1)) engine=innodb; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +CREATE TABLE t2 (c1 int); +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +CREATE TEMPORARY TABLE t1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1,t2) INSERT_METHOD=LAST; +CACHE INDEX t1,t2 IN default; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache Error Table 't1' is differently defined or of non-MyISAM type or doesn't exist +test.t1 assign_to_keycache error Corrupt +test.t2 assign_to_keycache note The storage engine for the table doesn't support assign_to_keycache +LOAD INDEX INTO CACHE t1,t2; +Table Op Msg_type Msg_text +test.t1 preload_keys Error Table 't1' is differently defined or of non-MyISAM type or doesn't exist +test.t1 preload_keys error Corrupt +test.t2 preload_keys note The storage engine for the table doesn't support preload_keys +DROP TEMPORARY TABLE t1; +DROP TABLE t1,t2; +CREATE TABLE t1 (c1 int, UNIQUE INDEX (c1)) engine=MyISAM; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +CREATE TABLE t2 (c1 int, UNIQUE INDEX (c1)) engine=MyISAM; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +CREATE TEMPORARY TABLE t1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1,t2) INSERT_METHOD=LAST; +CACHE INDEX t1,t2 IN default; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache Error Table 't1' is differently defined or of non-MyISAM type or doesn't exist +test.t1 assign_to_keycache error Corrupt +test.t2 assign_to_keycache status OK +LOAD INDEX INTO CACHE t1,t2; +Table Op Msg_type Msg_text +test.t1 preload_keys Error Table 't1' is differently defined or of non-MyISAM type or doesn't exist +test.t1 preload_keys error Corrupt +test.t2 preload_keys status OK +DROP TEMPORARY TABLE t1; +DROP TABLE t1,t2; +CREATE TABLE t1 (c1 int, UNIQUE INDEX (c1)) engine=MyISAM; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +CREATE TABLE t2 (c1 int, UNIQUE INDEX (c1)) engine=MyISAM; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +CACHE INDEX t1,t2 IN default; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +test.t2 assign_to_keycache status OK +LOAD INDEX INTO CACHE t1,t2; +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +test.t2 preload_keys status OK +DROP TABLE t1,t2; diff --git a/mysql-test/suite/galera/t/galera_cache_index.test b/mysql-test/suite/galera/t/galera_cache_index.test new file mode 100644 index 00000000000..b373a173894 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_cache_index.test @@ -0,0 +1,29 @@ +--source include/galera_cluster.inc + +CREATE TABLE t1 (c1 int, UNIQUE INDEX (c1)) engine=innodb; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +CREATE TABLE t2 (c1 int); +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +CREATE TEMPORARY TABLE t1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1,t2) INSERT_METHOD=LAST; +CACHE INDEX t1,t2 IN default; +LOAD INDEX INTO CACHE t1,t2; +DROP TEMPORARY TABLE t1; +DROP TABLE t1,t2; + +CREATE TABLE t1 (c1 int, UNIQUE INDEX (c1)) engine=MyISAM; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +CREATE TABLE t2 (c1 int, UNIQUE INDEX (c1)) engine=MyISAM; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +CREATE TEMPORARY TABLE t1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1,t2) INSERT_METHOD=LAST; +CACHE INDEX t1,t2 IN default; +LOAD INDEX INTO CACHE t1,t2; +DROP TEMPORARY TABLE t1; +DROP TABLE t1,t2; + +CREATE TABLE t1 (c1 int, UNIQUE INDEX (c1)) engine=MyISAM; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +CREATE TABLE t2 (c1 int, UNIQUE INDEX (c1)) engine=MyISAM; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +CACHE INDEX t1,t2 IN default; +LOAD INDEX INTO CACHE t1,t2; +DROP TABLE t1,t2; diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index ce472697d40..66dfc93f45d 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -33,6 +33,10 @@ #include "sql_admin.h" #include "sql_statistics.h" #include "wsrep_mysqld.h" +#ifdef WITH_WSREP +#include "wsrep_trans_observer.h" +#endif + /* Prepare, run and cleanup for mysql_recreate_table() */ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list, @@ -437,6 +441,32 @@ dbug_err: return open_error; } +#ifdef WITH_WSREP +/** RAII class for temporarily disable wsrep_on in the connection. */ +class Disable_wsrep_on_guard +{ + public: + /** + @param thd - pointer to the context of connection in which + wsrep_on mode needs to be disabled. + @param disable - true if wsrep_on should be disabled + */ + explicit Disable_wsrep_on_guard(THD *thd, bool disable) + : m_thd(thd), m_orig_wsrep_on(thd->variables.wsrep_on) + { + if (disable) + thd->variables.wsrep_on= false; + } + + ~Disable_wsrep_on_guard() + { + m_thd->variables.wsrep_on= m_orig_wsrep_on; + } + private: + THD* m_thd; + bool m_orig_wsrep_on; +}; +#endif /* WITH_WSREP */ /* RETURN VALUES @@ -473,6 +503,18 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, DBUG_ENTER("mysql_admin_table"); DBUG_PRINT("enter", ("extra_open_options: %u", extra_open_options)); +#ifdef WITH_WSREP + /* + CACHE INDEX and LOAD INDEX INTO CACHE statements are + local operations. Do not replicate them with Galera + */ + const bool disable_wsrep_on= (WSREP(thd) && + (lex->sql_command == SQLCOM_ASSIGN_TO_KEYCACHE || + lex->sql_command == SQLCOM_PRELOAD_KEYS)); + + Disable_wsrep_on_guard wsrep_on_guard(thd, disable_wsrep_on); +#endif /* WITH_WSREP */ + field_list.push_back(item= new (thd->mem_root) Item_empty_string(thd, "Table", NAME_CHAR_LEN * 2), thd->mem_root); @@ -535,7 +577,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, ? MDL_SHARED_NO_READ_WRITE : lock_type >= TL_WRITE_ALLOW_WRITE ? MDL_SHARED_WRITE : MDL_SHARED_READ); - if (thd->check_killed()) { open_error= false; diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h index 4c9346739fe..cf5063df04d 100644 --- a/sql/wsrep_trans_observer.h +++ b/sql/wsrep_trans_observer.h @@ -193,6 +193,11 @@ static inline bool wsrep_run_commit_hook(THD* thd, bool all) wsrep_is_active(thd), wsrep_is_real(thd, all), wsrep_has_changes(thd), wsrep_thd_is_applying(thd), wsrep_is_ordered(thd))); + + /* skipping non-wsrep threads */ + if (!WSREP(thd)) + DBUG_RETURN(false); + /* Is MST commit or autocommit? */ bool ret= wsrep_is_active(thd) && wsrep_is_real(thd, all); /* Do not commit if we are aborting */ From f5c3e736f2cfa02df69e7a57465835a63573813f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 10 Jul 2023 13:18:48 +0300 Subject: [PATCH 005/158] MDEV-31651 : Assertion wsrep_thd_is_applying(thd) && !wsrep_thd_is_local_toi(thd) in wsrep_ignored_error_code Problem was that with BINLOG-statement you can execute binlog events on master also (not only in applier). Fix removes too strict part wsrep_thd_is_applying from assertion. Note that actual event in test is intentionally corrupted to test should this error being ignored. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/mdev-31651.result | 11 +++++++++++ mysql-test/suite/galera/t/mdev-31651.test | 11 +++++++++++ sql/wsrep_mysqld.cc | 5 +++-- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/galera/r/mdev-31651.result create mode 100644 mysql-test/suite/galera/t/mdev-31651.test diff --git a/mysql-test/suite/galera/r/mdev-31651.result b/mysql-test/suite/galera/r/mdev-31651.result new file mode 100644 index 00000000000..f715aa895f8 --- /dev/null +++ b/mysql-test/suite/galera/r/mdev-31651.result @@ -0,0 +1,11 @@ +connection node_2; +connection node_1; +call mtr.add_suppression("BINLOG_BASE64_EVENT: Could not read field.*"); +call mtr.add_suppression("BINLOG_BASE64_EVENT: Could not execute Write_rows_v1 event on table.*"); +CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b INT, KEY(b)) engine=innodb; +BINLOG 'AMqaOw8BAAAAdAAAAHgAAAAAAAQANS42LjM0LTc5LjEtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAXAAEGggAAAAICAgCAAAACgoKGRkAAYVx w2w='; +BINLOG 'wlZOTxMBAAAAKgAAADwCAAAAACkAAAAAAAEABHRlc3QAAnQxAAIDAwAC wlZOTxcBAAAAJgAAAGICAAAAACkAAAAAAAEAAv/8AgAAAAgAAAA='; +ERROR HY000: Got error 171 "The event was corrupt, leading to illegal data being read" from storage engine InnoDB +SELECT * FROM t1; +a b +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/mdev-31651.test b/mysql-test/suite/galera/t/mdev-31651.test new file mode 100644 index 00000000000..3598057a53f --- /dev/null +++ b/mysql-test/suite/galera/t/mdev-31651.test @@ -0,0 +1,11 @@ +--source include/galera_cluster.inc + + +call mtr.add_suppression("BINLOG_BASE64_EVENT: Could not read field.*"); +call mtr.add_suppression("BINLOG_BASE64_EVENT: Could not execute Write_rows_v1 event on table.*"); +CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b INT, KEY(b)) engine=innodb; +BINLOG 'AMqaOw8BAAAAdAAAAHgAAAAAAAQANS42LjM0LTc5LjEtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAXAAEGggAAAAICAgCAAAACgoKGRkAAYVx w2w='; +--error ER_GET_ERRNO +BINLOG 'wlZOTxMBAAAAKgAAADwCAAAAACkAAAAAAAEABHRlc3QAAnQxAAIDAwAC wlZOTxcBAAAAJgAAAGICAAAAACkAAAAAAAEAAv/8AgAAAAgAAAA='; +SELECT * FROM t1; +DROP TABLE t1; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index a345f8c6b35..06991c7f44d 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2799,8 +2799,9 @@ int wsrep_ignored_error_code(Log_event* ev, int error) const THD* thd= ev->thd; DBUG_ASSERT(error); - DBUG_ASSERT(wsrep_thd_is_applying(thd) && - !wsrep_thd_is_local_toi(thd)); + /* Note that binlog events can be executed on master also with + BINLOG '....'; */ + DBUG_ASSERT(!wsrep_thd_is_local_toi(thd)); if ((wsrep_ignore_apply_errors & WSREP_IGNORE_ERRORS_ON_RECONCILING_DML)) { From 9b5275b8f5343bf8f00c1a75fff3b2343afa89c2 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 18 Jul 2023 17:04:05 +1000 Subject: [PATCH 006/158] MDEV-31332: Galera rsync sst to ignore .snapshot/ files .snapshot exists as a directory on NetApp storage and should not be copied during the sst process. Thanks Daniel Czadek for the bug report. Signed-off-by: Julius Goryavsky --- scripts/wsrep_sst_rsync.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 5279929c5b0..8d53405eeb8 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -564,6 +564,7 @@ FILTER="-f '- /lost+found' -f '- /.Trashes' -f '- /.pid' -f '- /.conf' + -f '- /.snapshot/' -f '+ /wsrep_sst_binlog.tar' -f '- $ib_home_dir/ib_lru_dump' -f '- $ib_home_dir/ibdata*' @@ -673,7 +674,8 @@ FILTER="-f '- /lost+found' cd "$DATA" find . -maxdepth 1 -mindepth 1 -type d -not -name 'lost+found' \ - -not -name '.zfs' -print0 | xargs -I{} -0 -P $backup_threads \ + -not -name '.zfs' -not -name .snapshot -print0 \ + | xargs -I{} -0 -P $backup_threads \ rsync ${STUNNEL:+--rsh="$STUNNEL"} \ --owner --group --perms --links --specials --ignore-times \ --inplace --recursive --delete --quiet $WHOLE_FILE_OPT \ From 50a2e8b1892b6b8a276d4bd75a1a02148f9e6ff2 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 25 Sep 2023 17:14:36 +0200 Subject: [PATCH 007/158] MDEV-32140: Valgrind/MSAN warnings in dynamic_column_update_move_left Do not manipulate empty dynamic column, just better return empty dynamic column from the begining. (it is also optimisation) --- mysql-test/main/dyncol.result | 12 ++++++++++++ mysql-test/main/dyncol.test | 10 ++++++++++ mysys/ma_dyncol.c | 7 +++++++ 3 files changed, 29 insertions(+) diff --git a/mysql-test/main/dyncol.result b/mysql-test/main/dyncol.result index 4275bf1ce43..0febe6057f0 100644 --- a/mysql-test/main/dyncol.result +++ b/mysql-test/main/dyncol.result @@ -1956,3 +1956,15 @@ DROP TABLE t1; # # End of 10.2 tests # +# +# MDEV-32140: Valgrind/MSAN warnings in dynamic_column_update_move_left +# +SELECT COLUMN_GET(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL),3 AS INTEGER); +COLUMN_GET(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL),3 AS INTEGER) +NULL +SELECT HEX(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL)); +HEX(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL)) +000000 +# +# End of 10.4 tests +# diff --git a/mysql-test/main/dyncol.test b/mysql-test/main/dyncol.test index 286cc6216a6..f3594442009 100644 --- a/mysql-test/main/dyncol.test +++ b/mysql-test/main/dyncol.test @@ -986,3 +986,13 @@ DROP TABLE t1; --echo # --echo # End of 10.2 tests --echo # + +--echo # +--echo # MDEV-32140: Valgrind/MSAN warnings in dynamic_column_update_move_left +--echo # +SELECT COLUMN_GET(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL),3 AS INTEGER); +SELECT HEX(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL)); + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index b438d910157..d3017212fc2 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -2872,6 +2872,13 @@ dynamic_column_update_move_left(DYNAMIC_COLUMN *str, PLAN *plan, write= (uchar *)str->str + FIXED_HEADER_SIZE; set_fixed_header(str, (uint)new_offset_size, new_column_count); + if (!new_column_count) + { + // No records left + DBUG_ASSERT(new_header_size == 0); + str->length= FIXED_HEADER_SIZE; + return ER_DYNCOL_OK; + } /* Move headers first. From 47f0135d7aba57d160d1d95ff7f1f6b7bb07c2fb Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 26 Sep 2023 08:54:34 -0700 Subject: [PATCH 008/158] MDEV-32245 Test from subselect.test fails with statement memory protection With this patch st_select_lex::ref_pointer_array is never re-allocated. Approved by Oleksandr Byelkin --- sql/sql_lex.cc | 55 +++++++++++++++++++++++--------------------------- sql/sql_lex.h | 3 +++ 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 019377061a0..dfb9580721a 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2413,6 +2413,7 @@ void st_select_lex::init_query() max_equal_elems= 0; ref_pointer_array.reset(); select_n_where_fields= 0; + order_group_num= 0; select_n_reserved= 0; select_n_having_items= 0; n_sum_items= 0; @@ -2978,46 +2979,40 @@ ulong st_select_lex::get_table_join_options() } -bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) +uint st_select_lex::get_cardinality_of_ref_ptrs_slice(uint order_group_num_arg) { - if (!((options & SELECT_DISTINCT) && !group_list.elements)) hidden_bit_fields= 0; - // find_order_in_list() may need some extra space, so multiply by two. - order_group_num*= 2; + if (!order_group_num) + order_group_num= order_group_num_arg; /* - We have to create array in prepared statement memory if it is a - prepared statement + find_order_in_list() may need some extra space, + so multiply order_group_num by 2 */ - Query_arena *arena= thd->stmt_arena; - const size_t n_elems= (n_sum_items + - n_child_sum_items + - item_list.elements + - select_n_reserved + - select_n_having_items + - select_n_where_fields + - order_group_num + - hidden_bit_fields + - fields_in_window_functions) * (size_t) 5; - DBUG_ASSERT(n_elems % 5 == 0); + uint n= n_sum_items + + n_child_sum_items + + item_list.elements + + select_n_reserved + + select_n_having_items + + select_n_where_fields + + order_group_num * 2 + + hidden_bit_fields + + fields_in_window_functions; + return n; +} + + +bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) +{ + uint n_elems= get_cardinality_of_ref_ptrs_slice(order_group_num) * 5; if (!ref_pointer_array.is_null()) - { - /* - We need to take 'n_sum_items' into account when allocating the array, - and this may actually increase during the optimization phase due to - MIN/MAX rewrite in Item_in_subselect::single_value_transformer. - In the usual case we can reuse the array from the prepare phase. - If we need a bigger array, we must allocate a new one. - */ - if (ref_pointer_array.size() >= n_elems) - return false; - } - Item **array= static_cast(arena->alloc(sizeof(Item*) * n_elems)); + return false; + Item **array= static_cast(thd->stmt_arena->alloc(sizeof(Item*) * + n_elems)); if (likely(array != NULL)) ref_pointer_array= Ref_ptr_array(array, n_elems); - return array == NULL; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a2c5fec03e5..d47f196d679 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1176,6 +1176,8 @@ public: and all inner subselects. */ uint select_n_where_fields; + /* Total number of elements in group by and order by lists */ + uint order_group_num; /* reserved for exists 2 in */ uint select_n_reserved; /* @@ -1416,6 +1418,7 @@ public: init_select(); } bool setup_ref_array(THD *thd, uint order_group_num); + uint get_cardinality_of_ref_ptrs_slice(uint order_group_num_arg); void print(THD *thd, String *str, enum_query_type query_type); void print_item_list(THD *thd, String *str, enum_query_type query_type); void print_set_clause(THD *thd, String *str, enum_query_type query_type); From fec93e7155393f8807a8006934b774e4166a7290 Mon Sep 17 00:00:00 2001 From: Lena Startseva Date: Fri, 11 Aug 2023 11:25:36 +0700 Subject: [PATCH 009/158] MDEV-31465: main.sum_distinct-big and main.merge-big fail with timeout with view-protocol MDEV-31455: main.events_stress or events.events_stress fails with view-protocol MDEV-31457: main.delete_use_source fails (hangs) with view-protocol Fixed tests: main.sum_distinct-big, main.delete_use_source - disabled view-protocol for some cases because they use transactions without autocommit main.events_stress, main.merge-big - disabled service connection for some queries since it is necessary that the query SELECT pass in the same session --- mysql-test/main/delete_use_source.test | 2 ++ mysql-test/main/events_stress.test | 2 ++ mysql-test/main/merge-big.test | 2 ++ mysql-test/main/sum_distinct-big.test | 2 ++ 4 files changed, 8 insertions(+) diff --git a/mysql-test/main/delete_use_source.test b/mysql-test/main/delete_use_source.test index 4aed00da375..2df1e009fac 100644 --- a/mysql-test/main/delete_use_source.test +++ b/mysql-test/main/delete_use_source.test @@ -16,6 +16,7 @@ analyze table t1; --echo # Delete with limit (quick select - range acces) --echo # +--disable_view_protocol start transaction; --enable_info delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1; @@ -111,6 +112,7 @@ rollback; start transaction; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 order by c2 desc limit 10 returning c1,c2; rollback; +--enable_view_protocol drop view v1; drop table t1; diff --git a/mysql-test/main/events_stress.test b/mysql-test/main/events_stress.test index 080707f029f..92b084a35b4 100644 --- a/mysql-test/main/events_stress.test +++ b/mysql-test/main/events_stress.test @@ -45,10 +45,12 @@ CREATE EVENT ev_drop1 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1; CREATE EVENT ev_drop2 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1; CREATE EVENT ev_drop3 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1; USE events_test; +--disable_service_connection SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS; SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2'; DROP DATABASE events_conn1_test2; SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2'; +--enable_service_connection --echo "Now testing stability - dropping db -> events while they are running" CREATE DATABASE events_conn1_test2; diff --git a/mysql-test/main/merge-big.test b/mysql-test/main/merge-big.test index 5873d2eb233..873161a3e1d 100644 --- a/mysql-test/main/merge-big.test +++ b/mysql-test/main/merge-big.test @@ -66,8 +66,10 @@ let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST --echo # Unlock and close table and wait for con1 to close too. FLUSH TABLES; #SELECT NOW(); +--disable_service_connection --echo # This should give no result. SELECT * FROM t1; +--enable_service_connection #SELECT NOW(); UNLOCK TABLES; connection con1; diff --git a/mysql-test/main/sum_distinct-big.test b/mysql-test/main/sum_distinct-big.test index d87569f8668..4af0fafd354 100644 --- a/mysql-test/main/sum_distinct-big.test +++ b/mysql-test/main/sum_distinct-big.test @@ -79,6 +79,7 @@ SET @@max_heap_table_size=@save_max_heap_table_size; --echo # CREATE TABLE t2 (id INTEGER) ENGINE=InnoDB; +--disable_view_protocol BEGIN; INSERT INTO t2 SELECT b.seq FROM seq_1_to_128 a, seq_1_to_16384 b ORDER BY b.seq*rand(); @@ -103,5 +104,6 @@ SET @@max_heap_table_size=@save_max_heap_table_size; --echo # Back to default tmp_table_size / max_heap_table_size SELECT SQL_NO_CACHE count(DISTINCT id) sm FROM t2; COMMIT; +--enable_view_protocol DROP TABLE t2; From 554aa1e2b4ef1011555a2bde83668a61cb67b646 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 27 Sep 2023 07:51:47 +0200 Subject: [PATCH 010/158] Disable view protocol for the MDEV-31742 test because it make statistics differ or wrong (without service connection) --- mysql-test/main/log_slow.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/main/log_slow.test b/mysql-test/main/log_slow.test index 6120ac77756..7c1725897de 100644 --- a/mysql-test/main/log_slow.test +++ b/mysql-test/main/log_slow.test @@ -141,6 +141,7 @@ CREATE TABLE `tab_MDEV_30820` ( ); --disable_ps2_protocol +--disable_view_protocol --delimiter // CREATE FUNCTION `get_zero`() RETURNS int(11) @@ -181,6 +182,7 @@ SET SESSION slow_query_log=default; drop table tab_MDEV_30820, tab2; drop function get_zero; +--enable_view_protocol --enable_ps2_protocol --echo # From 2d29ccda1a4206b5cd0bc492dbcb9621f141a700 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Tue, 26 Sep 2023 18:17:04 +0200 Subject: [PATCH 011/158] MDEV-29771 Server crashes in check_sequence_fields upon CREATE TABLE .. SEQUENCE=1 AS SELECT .. Pass name separately for sequence check because sequence can be created with CREATE TABLE (see https://mariadb.com/kb/en/create-table/#sequence ) --- mysql-test/suite/sql_sequence/create.result | 8 ++++++++ mysql-test/suite/sql_sequence/create.test | 10 ++++++++++ sql/sql_sequence.cc | 6 +++--- sql/sql_sequence.h | 4 +++- sql/sql_table.cc | 3 ++- 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/sql_sequence/create.result b/mysql-test/suite/sql_sequence/create.result index 073cb1ac390..1b02a9a2c11 100644 --- a/mysql-test/suite/sql_sequence/create.result +++ b/mysql-test/suite/sql_sequence/create.result @@ -716,4 +716,12 @@ CREATE SEQUENCE seq1 START WITH 2; CREATE TRIGGER s1 BEFORE UPDATE ON seq1 FOR EACH ROW SET @a= 5; ERROR HY000: Trigger's 'seq1' is view, temporary table or sequence DROP SEQUENCE seq1; +# +# MDEV-29771: Server crashes in check_sequence_fields upon +# CREATE TABLE .. SEQUENCE=1 AS SELECT .. +# +create table s sequence=1 as select 1; +ERROR HY000: Sequence 'test.s' table structure is invalid (Wrong number of columns) +# # End of 10.4 test +# diff --git a/mysql-test/suite/sql_sequence/create.test b/mysql-test/suite/sql_sequence/create.test index fa85c0a8f0a..aa09a899d76 100644 --- a/mysql-test/suite/sql_sequence/create.test +++ b/mysql-test/suite/sql_sequence/create.test @@ -554,4 +554,14 @@ CREATE SEQUENCE seq1 START WITH 2; CREATE TRIGGER s1 BEFORE UPDATE ON seq1 FOR EACH ROW SET @a= 5; DROP SEQUENCE seq1; +--echo # +--echo # MDEV-29771: Server crashes in check_sequence_fields upon +--echo # CREATE TABLE .. SEQUENCE=1 AS SELECT .. +--echo # + +--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE +create table s sequence=1 as select 1; + +--echo # --echo # End of 10.4 test +--echo # diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index 4ba1e6092bd..9387d2527fe 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -186,7 +186,8 @@ void sequence_definition::store_fields(TABLE *table) true Failure */ -bool check_sequence_fields(LEX *lex, List *fields) +bool check_sequence_fields(LEX *lex, List *fields, + const LEX_CSTRING db, const LEX_CSTRING table_name) { Create_field *field; List_iterator_fast it(*fields); @@ -234,8 +235,7 @@ bool check_sequence_fields(LEX *lex, List *fields) err: my_error(ER_SEQUENCE_INVALID_TABLE_STRUCTURE, MYF(0), - lex->first_select_lex()->table_list.first->db.str, - lex->first_select_lex()->table_list.first->table_name.str, reason); + db.str, table_name.str, reason); DBUG_RETURN(TRUE); } diff --git a/sql/sql_sequence.h b/sql/sql_sequence.h index 29c589e67cd..fba04686d69 100644 --- a/sql/sql_sequence.h +++ b/sql/sql_sequence.h @@ -162,6 +162,8 @@ public: class Create_field; extern bool prepare_sequence_fields(THD *thd, List *fields); -extern bool check_sequence_fields(LEX *lex, List *fields); +extern bool check_sequence_fields(LEX *lex, List *fields, + const LEX_CSTRING db, + const LEX_CSTRING table_name); extern bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list); #endif /* SQL_SEQUENCE_INCLUDED */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6f41b70c69f..218bf1cfcaa 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3471,7 +3471,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, } /* The user specified fields: check that structure is ok */ - if (check_sequence_fields(thd->lex, &alter_info->create_list)) + if (check_sequence_fields(thd->lex, &alter_info->create_list, + db, table_name)) DBUG_RETURN(TRUE); } From b0763f509a3f120e882cee2810495d169ff344a4 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 27 Sep 2023 09:59:24 +0200 Subject: [PATCH 012/158] fix check_galera_version.inc to work and make it print both version it compares to be able to see if it starts misbehaving again --- mysql-test/suite/wsrep/include/check_galera_version.inc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/wsrep/include/check_galera_version.inc b/mysql-test/suite/wsrep/include/check_galera_version.inc index 7a58e657f40..40cd157ca80 100644 --- a/mysql-test/suite/wsrep/include/check_galera_version.inc +++ b/mysql-test/suite/wsrep/include/check_galera_version.inc @@ -34,13 +34,13 @@ SELECT CAST(REGEXP_REPLACE(@ACTUAL_GALERA_VERSION,'^[\\d\\.]*\\.(\\d+).*','\\1') #SELECT @ACTUAL_GALERA_MINOR_VERSION; #SELECT @ACTUAL_GALERA_RELEASE_VERSION; -if (!`SELECT (@ACTUAL_GALERA_MAJOR_VERSION >= @GALERA_MAJOR_VERSION AND @ACTUAL_GALERA_MINOR_VERSION > @GALERA_MINOR_VERSION) OR - (@ACTUAL_GALERA_MAJOR_VERSION = @GALERA_MAJOR_VERSION AND - @ACTUAL_GALERA_MINOR_VERSION = @GALERA_MINOR_VERSION AND +if (!`SELECT (@ACTUAL_GALERA_MINOR_VERSION > @GALERA_MINOR_VERSION) OR + (@ACTUAL_GALERA_MINOR_VERSION = @GALERA_MINOR_VERSION AND @ACTUAL_GALERA_RELEASE_VERSION >= @GALERA_RELEASE_VERSION) `) { - skip Test requires Galera library version >= $galera_version; + let actual_galera_version=`select @ACTUAL_GALERA_VERSION`; + skip needs galera >= $galera_version, got $actual_galera_version; } --echo # Correct Galera library found From 4e2594768d658194220ae5678a686ed680aa3217 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 26 Sep 2023 19:36:38 -0700 Subject: [PATCH 013/158] MDEV-32259 Test from win.test fails with statement memory protection The function setup_windows() called at the prepare phase of processing a select builds a list of all window specifications used in the select. This list is built on the statement memory and it must be done only once. Approved by Oleksandr Byelkin --- sql/sql_lex.cc | 1 + sql/sql_lex.h | 1 + sql/sql_window.cc | 44 +++++++++++++++++++++++++------------------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index dfb9580721a..c0f639b55ec 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2441,6 +2441,7 @@ void st_select_lex::init_query() m_custom_agg_func_used= false; window_specs.empty(); window_funcs.empty(); + is_win_spec_list_built= false; tvc= 0; in_tvc= false; versioned_tables= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index d47f196d679..2e0b3604244 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1530,6 +1530,7 @@ public: bool no_to_clones); List window_specs; + bool is_win_spec_list_built; void prepare_add_window_spec(THD *thd); bool add_window_def(THD *thd, LEX_CSTRING *win_name, LEX_CSTRING *win_ref, SQL_I_List win_partition_list, diff --git a/sql/sql_window.cc b/sql/sql_window.cc index df43efe18a4..7677c3e9113 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -207,27 +207,33 @@ setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, DBUG_ENTER("setup_windows"); List_iterator it(win_specs); - /* - Move all unnamed specifications after the named ones. - We could have avoided it if we had built two separate lists for - named and unnamed specifications. - */ - Query_arena *arena, backup; - arena= thd->activate_stmt_arena_if_needed(&backup); - uint i = 0; - uint elems= win_specs.elements; - while ((win_spec= it++) && i++ < elems) + if (!thd->lex->current_select->is_win_spec_list_built) { - if (win_spec->name() == NULL) - { - it.remove(); - win_specs.push_back(win_spec); - } - } - if (arena) - thd->restore_active_arena(arena, &backup); - it.rewind(); + /* + Move all unnamed specifications after the named ones. + We could have avoided it if we had built two separate lists for + named and unnamed specifications. + */ + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); + uint i = 0; + uint elems= win_specs.elements; + while ((win_spec= it++) && i++ < elems) + { + if (win_spec->name() == NULL) + { + it.remove(); + win_specs.push_back(win_spec); + } + } + if (arena) + thd->restore_active_arena(arena, &backup); + + it.rewind(); + + thd->lex->current_select->is_win_spec_list_built= true; + } List_iterator_fast itp(win_specs); From 23a229706ecaf722f0c35f3ac0723ab35fbf98db Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 21 Sep 2023 13:01:48 +0200 Subject: [PATCH 014/158] MDEV-32223 Memory leak showed in MDEV-6146 test suite Fix Item_func_match to avoid removing Item_direct_ref_to_item from item tree via real_item() call. --- sql/item_func.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sql/item_func.cc b/sql/item_func.cc index a632ab825e0..56bc2e9b29c 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -6098,7 +6098,8 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref) table= 0; for (uint i=1 ; i < arg_count ; i++) { - item= args[i]= args[i]->real_item(); + + item= args[i]->real_item(); /* When running in PS mode, some Item_field's can already be replaced to Item_func_conv_charset during PREPARE time. This is possible @@ -6187,9 +6188,10 @@ bool Item_func_match::fix_index() for (i=1; i < arg_count; i++) { - if (args[i]->type() != FIELD_ITEM) + Item *real_item= args[i]->real_item(); + if (real_item->type() != FIELD_ITEM) goto err; - item=(Item_field*)args[i]; + item=(Item_field*)real_item; for (keynr=0 ; keynr < fts ; keynr++) { KEY *ft_key=&table->key_info[ft_to_key[keynr]]; From c1bc05605c90ef127659603225bd4ee0b1417f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 15 Aug 2023 10:12:34 +0300 Subject: [PATCH 015/158] MDEV-24912: post-fix for test regression Problem is that mysql.galera_slave_pos table is replicated, thus it should be InnoDB to allow rolling back in case of replay. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/galera_as_slave_replay.result | 1 + mysql-test/suite/galera/r/galera_slave_replay.result | 1 + mysql-test/suite/galera/t/galera_as_slave_replay.test | 2 ++ mysql-test/suite/galera/t/galera_slave_replay.test | 2 ++ 4 files changed, 6 insertions(+) diff --git a/mysql-test/suite/galera/r/galera_as_slave_replay.result b/mysql-test/suite/galera/r/galera_as_slave_replay.result index 05bfeed8f01..0425bd2b97a 100644 --- a/mysql-test/suite/galera/r/galera_as_slave_replay.result +++ b/mysql-test/suite/galera/r/galera_as_slave_replay.result @@ -2,6 +2,7 @@ connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2a; connection node_2; connection node_1; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; connection node_3; RESET MASTER; diff --git a/mysql-test/suite/galera/r/galera_slave_replay.result b/mysql-test/suite/galera/r/galera_slave_replay.result index 0b0199c4a02..8fb7e1ab099 100644 --- a/mysql-test/suite/galera/r/galera_slave_replay.result +++ b/mysql-test/suite/galera/r/galera_slave_replay.result @@ -2,6 +2,7 @@ connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2a; connection node_2; connection node_1; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; connection node_3; RESET MASTER; diff --git a/mysql-test/suite/galera/t/galera_as_slave_replay.test b/mysql-test/suite/galera/t/galera_as_slave_replay.test index 725d72c4144..73fd7b3ff29 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_replay.test +++ b/mysql-test/suite/galera/t/galera_as_slave_replay.test @@ -17,6 +17,8 @@ --source include/galera_cluster.inc #--source suite/galera/include/galera_have_debug_sync.inc +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; + # # node 3 is native MariaDB server operating as async replication master # diff --git a/mysql-test/suite/galera/t/galera_slave_replay.test b/mysql-test/suite/galera/t/galera_slave_replay.test index f1500eeaeaa..6680e66ffa1 100644 --- a/mysql-test/suite/galera/t/galera_slave_replay.test +++ b/mysql-test/suite/galera/t/galera_slave_replay.test @@ -17,6 +17,8 @@ --connection node_2a --source include/galera_cluster.inc +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; + # # node 3 is native MariaDB server operating as async replication master # From 3c65434b789be9b06235bbecec08a7e97301bb52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 16 May 2023 15:21:43 +0300 Subject: [PATCH 016/158] MDEV-31285 : Assertion `state() == s_executing || state() == s_preparing || state() == s_prepared || state() == s_must_abort || state() == s_aborting || state() == s_cert_failed || state() == s_must_replay' failed When applier tries to execute write rows event it find out in table_def::compatible_with that value is not compatible and sets error and thd->is_slave_error but thd->is_error() is false. Later in rpl_group_info::slave_close_thread_tables we commit stmt. This is bad for Galera because later in apply_write_set we notice that event apply was not successful and try to rollback transaction, but wsrep transaction is already in s_committed state. This is fixed on rpl_group_info::slave_close_thread_tables so that in Galera case we rollback stmt if thd->is_slave_error or thd->is_error() is set. Then later we can rollback wsrep transaction. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/mdev-31285.result | 23 ++++++++++++++ mysql-test/suite/galera/t/mdev-31285.test | 34 +++++++++++++++++++++ sql/rpl_rli.cc | 12 +++++++- 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera/r/mdev-31285.result create mode 100644 mysql-test/suite/galera/t/mdev-31285.test diff --git a/mysql-test/suite/galera/r/mdev-31285.result b/mysql-test/suite/galera/r/mdev-31285.result new file mode 100644 index 00000000000..228f62fa305 --- /dev/null +++ b/mysql-test/suite/galera/r/mdev-31285.result @@ -0,0 +1,23 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +connection node_1; +CREATE TABLE t ENGINE=InnoDB WITH SYSTEM VERSIONING AS SELECT 1 AS i; +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `i` int(1) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci WITH SYSTEM VERSIONING +SELECT * from t; +i +1 +DROP TABLE IF EXISTS t; +COMMIT; +connection node_2; +SET SESSION wsrep_sync_wait=0; +Killing server ... +Starting server ... +connection node_2; +call mtr.add_suppression("WSREP: Event .*Write_rows_v1 apply failed:.*"); +call mtr.add_suppression("SREP: Failed to apply write set: gtid:.*"); diff --git a/mysql-test/suite/galera/t/mdev-31285.test b/mysql-test/suite/galera/t/mdev-31285.test new file mode 100644 index 00000000000..d2749165ef7 --- /dev/null +++ b/mysql-test/suite/galera/t/mdev-31285.test @@ -0,0 +1,34 @@ +--source include/galera_cluster.inc + +--let $node_1 = node_1 +--let $node_2 = node_2 +--source include/auto_increment_offset_save.inc + +--connection node_1 +CREATE TABLE t ENGINE=InnoDB WITH SYSTEM VERSIONING AS SELECT 1 AS i; +SHOW CREATE TABLE t; +SELECT * from t; +DROP TABLE IF EXISTS t; +COMMIT; + +# +# Restart node_2, force SST because database is inconsistent compared to node_1 +# +--connection node_2 +SET SESSION wsrep_sync_wait=0; +--source include/kill_galera.inc +--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat +--echo Starting server ... +let $restart_noprint=2; +--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 + +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc + +--connection node_2 +call mtr.add_suppression("WSREP: Event .*Write_rows_v1 apply failed:.*"); +call mtr.add_suppression("SREP: Failed to apply write set: gtid:.*"); + +--source include/auto_increment_offset_restore.inc diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 214650f1e29..95566b2f6c7 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -2377,7 +2377,17 @@ void rpl_group_info::slave_close_thread_tables(THD *thd) { DBUG_ENTER("rpl_group_info::slave_close_thread_tables(THD *thd)"); thd->get_stmt_da()->set_overwrite_status(true); - thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd); +#ifdef WITH_WSREP + // This can happen e.g. when table_def::compatible_with fails and sets a error + // but thd->is_error() is false then. However, we do not want to commit + // statement on Galera instead we want to rollback it as later in + // apply_write_set we rollback transaction and that can't be done + // after wsrep transaction state is s_committed. + if (WSREP(thd)) + (thd->is_error() || thd->is_slave_error) ? trans_rollback_stmt(thd) : trans_commit_stmt(thd); + else +#endif + thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd); thd->get_stmt_da()->set_overwrite_status(false); close_thread_tables(thd); From 87d1ab9ad98d3336f3ee4265cc0f30fea6d6607b Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 27 Sep 2023 17:57:24 +0200 Subject: [PATCH 017/158] MDEV-28561 Assertion failed: !pfs->m_idle || (state == PSI_SOCKET_STATE_ACTIVE) The error was specific to threadpool/compressed protocol. set_thd_idle() set socket state to idle twice, causing assert failure. This happens if unread compressed data on connection,after query was finished. On a protocol level, this means a single compression packet contains multiple command packets. --- sql/threadpool_common.cc | 11 +++++++---- tests/mysql_client_test.c | 26 ++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index 38848f3c237..108144d6cce 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -124,12 +124,17 @@ static void re_init_net_server_extension(THD *thd) #endif /* HAVE_PSI_INTERFACE */ +static inline bool has_unread_compressed_data(const NET *net) +{ + return net->compress && net->remain_in_buf; +} static inline void set_thd_idle(THD *thd) { thd->net.reading_or_writing= 1; #ifdef HAVE_PSI_INTERFACE - net_before_header_psi(&thd->net, thd, 0); + if (!has_unread_compressed_data(&thd->net)) + net_before_header_psi(&thd->net, thd, 0); #endif } @@ -326,10 +331,8 @@ static void handle_wait_timeout(THD *thd) static bool has_unread_data(THD* thd) { NET *net= &thd->net; - if (net->compress && net->remain_in_buf) - return true; Vio *vio= net->vio; - return vio->has_data(vio); + return vio->has_data(vio) || has_unread_compressed_data(net); } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 4df31bda302..a5178837f97 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -20040,8 +20040,10 @@ static void test_bug17512527() static void test_compressed_protocol() { MYSQL *mysql_local; + MYSQL_STMT *stmt; char query[4096], *end; int i; + int rc; myheader("test_compressed_protocol"); if (!(mysql_local= mysql_client_init(NULL))) @@ -20064,14 +20066,34 @@ static void test_compressed_protocol() for (i=0 ; i < 2 ; i++) { MYSQL_RES *res; - - int rc= mysql_real_query(mysql, query, (int) (end-query)); + rc= mysql_real_query(mysql, query, (int) (end-query)); myquery(rc); res= mysql_store_result(mysql); DBUG_ASSERT(res != 0); mysql_free_result(res); } + /* + Special compression protocol feature - it can pack + multiple protocol commands inside the same compression packet. + + mariadbclient does it when MYSQL_STMT is reused in multiple + mysql_stmt_prepare() calls. It sends then COM_STMT_CLOSE and + COM_STMT_PREPARE together in a single compression packet. + + Let's test, how server can handle that. There can be bugs + (MDEV-28561) + */ + stmt= mysql_stmt_init(mysql_local); + check_stmt(stmt); + for (i= 0; i < 2; i++) + { + rc= mysql_stmt_prepare(stmt, "DO 1", -1); + myquery(rc); + } + rc= mysql_stmt_close(stmt); + myquery(rc); + mysql_close(mysql_local); } From 04b7b3a0ca88cda43fd384decbc8d5f53cb4b7da Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 29 Sep 2023 00:18:19 +0200 Subject: [PATCH 018/158] mtr bug: even if the test is skipped, process combinations otherwise, e.g. ./mtr main.mysql_install_db_win_admin,innodb results in sporadic mysql-test-run: *** ERROR: Could not run main.mysql_install_db_win_admin with 'innodb' combination(s) depending on whether it'll process the skip (not windows admin) or the innodb.combinations first (if skip is processed first, innodb combination wasn't, making the further code think that the test doesn't have innodb combination) --- mysql-test/lib/mtr_cases.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index d289eb0a888..20baf24c9d6 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -614,7 +614,7 @@ sub make_combinations($$@) { my ($test, $test_combs, @combinations) = @_; - return ($test) if $test->{'skip'} or not @combinations; + return ($test) unless @combinations; if ($combinations[0]->{skip}) { $test->{skip} = 1; $test->{comment} = $combinations[0]->{skip} unless $test->{comment}; @@ -647,6 +647,8 @@ sub make_combinations($$@) } } + return ($test) if $test->{'skip'}; + my @cases; foreach my $comb (@combinations) { From f57deb314f743ad8197e5dde755f71b6e6a3f534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 4 Aug 2023 07:59:37 +0300 Subject: [PATCH 019/158] MDEV-31660 : Assertion `client_state.transaction().active() in wsrep_append_key At the moment we cannot support wsrep_forced_binlog_format=[MIXED|STATEMENT] during CREATE TABLE AS SELECT. Statement will use ROW instead and give a warning. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/create.result | 2 + .../r/galera_forced_binlog_format_ctas.result | 273 ++++++++++++++++++ .../t/galera_forced_binlog_ctas_test.inc | 50 ++++ .../t/galera_forced_binlog_format_ctas.test | 19 ++ sql/log.cc | 12 +- sql/sql_base.cc | 3 +- sql/sql_class.cc | 42 ++- sql/sql_class.h | 22 +- sql/sql_error.cc | 12 + sql/sql_error.h | 13 + sql/sql_insert.cc | 2 +- sql/sql_table.cc | 60 +++- sql/wsrep_on.h | 5 - 13 files changed, 476 insertions(+), 39 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_forced_binlog_format_ctas.result create mode 100644 mysql-test/suite/galera/t/galera_forced_binlog_ctas_test.inc create mode 100644 mysql-test/suite/galera/t/galera_forced_binlog_format_ctas.test diff --git a/mysql-test/suite/galera/r/create.result b/mysql-test/suite/galera/r/create.result index cd0380b206d..16ae684a1f2 100644 --- a/mysql-test/suite/galera/r/create.result +++ b/mysql-test/suite/galera/r/create.result @@ -18,6 +18,8 @@ USE test; CREATE TABLE t1(i INT) ENGINE=INNODB; INSERT INTO t1 VALUES(1); CREATE TEMPORARY TABLE `t1_temp` AS SELECT * FROM `t1` WHERE i = 1; +Warnings: +Warning 1105 Galera does not support wsrep_forced_binlog_format = STMT in CREATE TABLE AS SELECT SELECT * FROM t1; i 1 diff --git a/mysql-test/suite/galera/r/galera_forced_binlog_format_ctas.result b/mysql-test/suite/galera/r/galera_forced_binlog_format_ctas.result new file mode 100644 index 00000000000..cae5f723c51 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_forced_binlog_format_ctas.result @@ -0,0 +1,273 @@ +connection node_2; +connection node_1; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since.*"); +SET GLOBAL wsrep_forced_binlog_format=ROW; +connection node_1; +CREATE TABLE t1(a int not null primary key auto_increment, b int) ENGINE=InnoDB; +CREATE TABLE t2(a int not null primary key, b int) ENGINE=InnoDB; +INSERT INTO t1 VALUES (NULL,1),(NULL,2); +INSERT INTO t1(b) SELECT b+1 from t1; +INSERT INTO t1(b) SELECT b+1 from t1; +INSERT INTO t1(b) SELECT b+1 from t1; +INSERT INTO t1(b) SELECT b+1 from t1; +CREATE TABLE t3 AS SELECT * FROM t1; +CREATE TABLE t4 AS SELECT * FROM t2; +CREATE TABLE t5 (a INT UNIQUE) AS SELECT 1 AS a; +CREATE TABLE t6 (a INT UNIQUE) REPLACE SELECT 1 AS a; +CREATE TABLE t7 (a INT UNIQUE) REPLACE SELECT 1 AS a,2 AS b UNION SELECT 1 AS a, +3 AS c; +SELECT COUNT(*) AS EXPECT_32 FROM t1; +EXPECT_32 +32 +SELECT COUNT(*) AS EXPECT_0 FROM t2; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_32 FROM t3; +EXPECT_32 +32 +SELECT * FROM t4; +a b +SELECT * FROM t5; +a +1 +SELECT * FROM t6; +a +1 +SELECT * FROM t7; +a b +1 3 +connection node_2; +# Veryfy CTAS replication +SELECT COUNT(*) AS EXPECT_32 FROM t1; +EXPECT_32 +32 +SELECT COUNT(*) AS EXPECT_0 FROM t2; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_32 FROM t3; +EXPECT_32 +32 +SELECT * FROM t4; +a b +SELECT * FROM t5; +a +1 +SELECT * FROM t6; +a +1 +SELECT * FROM t7; +a b +1 3 +connection node_1; +DROP TABLE t1,t2,t3,t4,t5,t6,t7; +SET GLOBAL wsrep_forced_binlog_format=STATEMENT; +connection node_1; +CREATE TABLE t1(a int not null primary key auto_increment, b int) ENGINE=InnoDB; +CREATE TABLE t2(a int not null primary key, b int) ENGINE=InnoDB; +INSERT INTO t1 VALUES (NULL,1),(NULL,2); +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave +INSERT INTO t1(b) SELECT b+1 from t1; +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave +INSERT INTO t1(b) SELECT b+1 from t1; +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave +INSERT INTO t1(b) SELECT b+1 from t1; +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave +INSERT INTO t1(b) SELECT b+1 from t1; +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave +CREATE TABLE t3 AS SELECT * FROM t1; +Warnings: +Warning 1105 Galera does not support wsrep_forced_binlog_format = STMT in CREATE TABLE AS SELECT +CREATE TABLE t4 AS SELECT * FROM t2; +Warnings: +Warning 1105 Galera does not support wsrep_forced_binlog_format = STMT in CREATE TABLE AS SELECT +CREATE TABLE t5 (a INT UNIQUE) AS SELECT 1 AS a; +Warnings: +Warning 1105 Galera does not support wsrep_forced_binlog_format = STMT in CREATE TABLE AS SELECT +CREATE TABLE t6 (a INT UNIQUE) REPLACE SELECT 1 AS a; +Warnings: +Warning 1105 Galera does not support wsrep_forced_binlog_format = STMT in CREATE TABLE AS SELECT +CREATE TABLE t7 (a INT UNIQUE) REPLACE SELECT 1 AS a,2 AS b UNION SELECT 1 AS a, +3 AS c; +Warnings: +Warning 1105 Galera does not support wsrep_forced_binlog_format = STMT in CREATE TABLE AS SELECT +SELECT COUNT(*) AS EXPECT_32 FROM t1; +EXPECT_32 +32 +SELECT COUNT(*) AS EXPECT_0 FROM t2; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_32 FROM t3; +EXPECT_32 +32 +SELECT * FROM t4; +a b +SELECT * FROM t5; +a +1 +SELECT * FROM t6; +a +1 +SELECT * FROM t7; +a b +1 3 +connection node_2; +# Veryfy CTAS replication +SELECT COUNT(*) AS EXPECT_32 FROM t1; +EXPECT_32 +32 +SELECT COUNT(*) AS EXPECT_0 FROM t2; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_32 FROM t3; +EXPECT_32 +32 +SELECT * FROM t4; +a b +SELECT * FROM t5; +a +1 +SELECT * FROM t6; +a +1 +SELECT * FROM t7; +a b +1 3 +connection node_1; +DROP TABLE t1,t2,t3,t4,t5,t6,t7; +SET GLOBAL wsrep_forced_binlog_format=MIXED; +connection node_1; +CREATE TABLE t1(a int not null primary key auto_increment, b int) ENGINE=InnoDB; +CREATE TABLE t2(a int not null primary key, b int) ENGINE=InnoDB; +INSERT INTO t1 VALUES (NULL,1),(NULL,2); +INSERT INTO t1(b) SELECT b+1 from t1; +INSERT INTO t1(b) SELECT b+1 from t1; +INSERT INTO t1(b) SELECT b+1 from t1; +INSERT INTO t1(b) SELECT b+1 from t1; +CREATE TABLE t3 AS SELECT * FROM t1; +Warnings: +Warning 1105 Galera does not support wsrep_forced_binlog_format = MIXED in CREATE TABLE AS SELECT +CREATE TABLE t4 AS SELECT * FROM t2; +Warnings: +Warning 1105 Galera does not support wsrep_forced_binlog_format = MIXED in CREATE TABLE AS SELECT +CREATE TABLE t5 (a INT UNIQUE) AS SELECT 1 AS a; +Warnings: +Warning 1105 Galera does not support wsrep_forced_binlog_format = MIXED in CREATE TABLE AS SELECT +CREATE TABLE t6 (a INT UNIQUE) REPLACE SELECT 1 AS a; +Warnings: +Warning 1105 Galera does not support wsrep_forced_binlog_format = MIXED in CREATE TABLE AS SELECT +CREATE TABLE t7 (a INT UNIQUE) REPLACE SELECT 1 AS a,2 AS b UNION SELECT 1 AS a, +3 AS c; +Warnings: +Warning 1105 Galera does not support wsrep_forced_binlog_format = MIXED in CREATE TABLE AS SELECT +SELECT COUNT(*) AS EXPECT_32 FROM t1; +EXPECT_32 +32 +SELECT COUNT(*) AS EXPECT_0 FROM t2; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_32 FROM t3; +EXPECT_32 +32 +SELECT * FROM t4; +a b +SELECT * FROM t5; +a +1 +SELECT * FROM t6; +a +1 +SELECT * FROM t7; +a b +1 3 +connection node_2; +# Veryfy CTAS replication +SELECT COUNT(*) AS EXPECT_32 FROM t1; +EXPECT_32 +32 +SELECT COUNT(*) AS EXPECT_0 FROM t2; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_32 FROM t3; +EXPECT_32 +32 +SELECT * FROM t4; +a b +SELECT * FROM t5; +a +1 +SELECT * FROM t6; +a +1 +SELECT * FROM t7; +a b +1 3 +connection node_1; +DROP TABLE t1,t2,t3,t4,t5,t6,t7; +SET GLOBAL wsrep_forced_binlog_format=NONE; +connection node_1; +CREATE TABLE t1(a int not null primary key auto_increment, b int) ENGINE=InnoDB; +CREATE TABLE t2(a int not null primary key, b int) ENGINE=InnoDB; +INSERT INTO t1 VALUES (NULL,1),(NULL,2); +INSERT INTO t1(b) SELECT b+1 from t1; +INSERT INTO t1(b) SELECT b+1 from t1; +INSERT INTO t1(b) SELECT b+1 from t1; +INSERT INTO t1(b) SELECT b+1 from t1; +CREATE TABLE t3 AS SELECT * FROM t1; +CREATE TABLE t4 AS SELECT * FROM t2; +CREATE TABLE t5 (a INT UNIQUE) AS SELECT 1 AS a; +CREATE TABLE t6 (a INT UNIQUE) REPLACE SELECT 1 AS a; +CREATE TABLE t7 (a INT UNIQUE) REPLACE SELECT 1 AS a,2 AS b UNION SELECT 1 AS a, +3 AS c; +SELECT COUNT(*) AS EXPECT_32 FROM t1; +EXPECT_32 +32 +SELECT COUNT(*) AS EXPECT_0 FROM t2; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_32 FROM t3; +EXPECT_32 +32 +SELECT * FROM t4; +a b +SELECT * FROM t5; +a +1 +SELECT * FROM t6; +a +1 +SELECT * FROM t7; +a b +1 3 +connection node_2; +# Veryfy CTAS replication +SELECT COUNT(*) AS EXPECT_32 FROM t1; +EXPECT_32 +32 +SELECT COUNT(*) AS EXPECT_0 FROM t2; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_32 FROM t3; +EXPECT_32 +32 +SELECT * FROM t4; +a b +SELECT * FROM t5; +a +1 +SELECT * FROM t6; +a +1 +SELECT * FROM t7; +a b +1 3 +connection node_1; +DROP TABLE t1,t2,t3,t4,t5,t6,t7; diff --git a/mysql-test/suite/galera/t/galera_forced_binlog_ctas_test.inc b/mysql-test/suite/galera/t/galera_forced_binlog_ctas_test.inc new file mode 100644 index 00000000000..f6d8f451d13 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_forced_binlog_ctas_test.inc @@ -0,0 +1,50 @@ +--connection node_1 +CREATE TABLE t1(a int not null primary key auto_increment, b int) ENGINE=InnoDB; +CREATE TABLE t2(a int not null primary key, b int) ENGINE=InnoDB; +INSERT INTO t1 VALUES (NULL,1),(NULL,2); +INSERT INTO t1(b) SELECT b+1 from t1; +INSERT INTO t1(b) SELECT b+1 from t1; +INSERT INTO t1(b) SELECT b+1 from t1; +INSERT INTO t1(b) SELECT b+1 from t1; +CREATE TABLE t3 AS SELECT * FROM t1; +CREATE TABLE t4 AS SELECT * FROM t2; +CREATE TABLE t5 (a INT UNIQUE) AS SELECT 1 AS a; +CREATE TABLE t6 (a INT UNIQUE) REPLACE SELECT 1 AS a; +CREATE TABLE t7 (a INT UNIQUE) REPLACE SELECT 1 AS a,2 AS b UNION SELECT 1 AS a, +3 AS c; + +SELECT COUNT(*) AS EXPECT_32 FROM t1; +SELECT COUNT(*) AS EXPECT_0 FROM t2; +SELECT COUNT(*) AS EXPECT_32 FROM t3; +SELECT * FROM t4; +SELECT * FROM t5; +SELECT * FROM t6; +SELECT * FROM t7; + +--connection node_2 +--echo # Veryfy CTAS replication +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't3' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't4' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't5' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't6' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't7' +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_32 FROM t1; +SELECT COUNT(*) AS EXPECT_0 FROM t2; +SELECT COUNT(*) AS EXPECT_32 FROM t3; +SELECT * FROM t4; +SELECT * FROM t5; +SELECT * FROM t6; +SELECT * FROM t7; + +--connection node_1 +DROP TABLE t1,t2,t3,t4,t5,t6,t7; diff --git a/mysql-test/suite/galera/t/galera_forced_binlog_format_ctas.test b/mysql-test/suite/galera/t/galera_forced_binlog_format_ctas.test new file mode 100644 index 00000000000..bb9cb6a9403 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_forced_binlog_format_ctas.test @@ -0,0 +1,19 @@ +--source include/galera_cluster.inc + +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since.*"); + +SET GLOBAL wsrep_forced_binlog_format=ROW; + +--source suite/galera/t/galera_forced_binlog_ctas_test.inc + +SET GLOBAL wsrep_forced_binlog_format=STATEMENT; + +--source suite/galera/t/galera_forced_binlog_ctas_test.inc + +SET GLOBAL wsrep_forced_binlog_format=MIXED; + +--source suite/galera/t/galera_forced_binlog_ctas_test.inc + +SET GLOBAL wsrep_forced_binlog_format=NONE; + +--source suite/galera/t/galera_forced_binlog_ctas_test.inc diff --git a/sql/log.cc b/sql/log.cc index 726598affe3..e7292064747 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1960,15 +1960,16 @@ static int binlog_prepare(handlerton *hton, THD *thd, bool all) static bool trans_cannot_safely_rollback(THD *thd, bool all) { DBUG_ASSERT(ending_trans(thd, all)); + ulong binlog_format= thd->wsrep_binlog_format(thd->variables.binlog_format); return ((thd->variables.option_bits & OPTION_KEEP_LOG) || (trans_has_updated_non_trans_table(thd) && - thd->wsrep_binlog_format() == BINLOG_FORMAT_STMT) || + binlog_format == BINLOG_FORMAT_STMT) || (thd->transaction.all.has_modified_non_trans_temp_table() && - thd->wsrep_binlog_format() == BINLOG_FORMAT_MIXED) || + binlog_format == BINLOG_FORMAT_MIXED) || (trans_has_updated_non_trans_table(thd) && ending_single_stmt_trans(thd,all) && - thd->wsrep_binlog_format() == BINLOG_FORMAT_MIXED)); + binlog_format == BINLOG_FORMAT_MIXED)); } @@ -2117,6 +2118,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) } else if (likely(!error)) { + ulong binlog_format= thd->wsrep_binlog_format(thd->variables.binlog_format); if (ending_trans(thd, all) && trans_cannot_safely_rollback(thd, all)) error= binlog_rollback_flush_trx_cache(thd, all, cache_mngr); /* @@ -2133,9 +2135,9 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) (!(thd->transaction.stmt.has_created_dropped_temp_table() && !thd->is_current_stmt_binlog_format_row()) && (!stmt_has_updated_non_trans_table(thd) || - thd->wsrep_binlog_format() != BINLOG_FORMAT_STMT) && + binlog_format != BINLOG_FORMAT_STMT) && (!thd->transaction.stmt.has_modified_non_trans_temp_table() || - thd->wsrep_binlog_format() != BINLOG_FORMAT_MIXED))) + binlog_format != BINLOG_FORMAT_MIXED))) error= binlog_truncate_trx_cache(thd, cache_mngr, all); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 97d214e1f17..91dd8cb12cd 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3433,7 +3433,8 @@ thr_lock_type read_lock_type_for_table(THD *thd, at THD::variables::sql_log_bin member. */ bool log_on= mysql_bin_log.is_open() && thd->variables.sql_log_bin; - if ((log_on == FALSE) || (thd->wsrep_binlog_format() == BINLOG_FORMAT_ROW) || + if ((log_on == FALSE) || + (thd->wsrep_binlog_format(thd->variables.binlog_format) == BINLOG_FORMAT_ROW) || (table_list->table->s->table_category == TABLE_CATEGORY_LOG) || (table_list->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) || !(is_update_query(prelocking_ctx->sql_command) || diff --git a/sql/sql_class.cc b/sql/sql_class.cc index bd40f3c05f5..46177837827 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -667,6 +667,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) wsrep_ignore_table(false), wsrep_aborter(0), wsrep_delayed_BF_abort(false), + wsrep_ctas(false), /* wsrep-lib */ m_wsrep_next_trx_id(WSREP_UNDEFINED_TRX_ID), @@ -5323,7 +5324,7 @@ extern "C" int thd_binlog_format(const MYSQL_THD thd) if (WSREP(thd)) { /* for wsrep binlog format is meaningful also when binlogging is off */ - return (int) WSREP_BINLOG_FORMAT(thd->variables.binlog_format); + return (int) thd->wsrep_binlog_format(thd->variables.binlog_format); } if (mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG)) @@ -5997,6 +5998,8 @@ int THD::decide_logging_format(TABLE_LIST *tables) reset_binlog_local_stmt_filter(); + // Used binlog format + ulong binlog_format= wsrep_binlog_format(variables.binlog_format); /* We should not decide logging format if the binlog is closed or binlogging is off, or if the statement is filtered out from the @@ -6017,20 +6020,41 @@ int THD::decide_logging_format(TABLE_LIST *tables) } } + /* + If user has configured wsrep_forced_binlog_format to + STMT OR MIXED and used binlog_format would be same + and this is CREATE TABLE AS SELECT we will fall back + to ROW. + */ + if (wsrep_forced_binlog_format < BINLOG_FORMAT_ROW && + wsrep_ctas) + { + if (!get_stmt_da()->has_sql_condition(ER_UNKNOWN_ERROR)) + { + push_warning_printf(this, Sql_condition::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, + "Galera does not support wsrep_forced_binlog_format = %s " + "in CREATE TABLE AS SELECT", + wsrep_forced_binlog_format == BINLOG_FORMAT_STMT ? + "STMT" : "MIXED"); + } + set_current_stmt_binlog_format_row(); + } + if ((WSREP_EMULATE_BINLOG_NNULL(this) || (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG))) && - !(wsrep_binlog_format() == BINLOG_FORMAT_STMT && + !(binlog_format == BINLOG_FORMAT_STMT && !binlog_filter->db_ok(db.str))) #else if (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG) && - !(wsrep_binlog_format() == BINLOG_FORMAT_STMT && + !(binlog_format == BINLOG_FORMAT_STMT && !binlog_filter->db_ok(db.str))) #endif /* WITH_WSREP */ { if (is_bulk_op()) { - if (wsrep_binlog_format() == BINLOG_FORMAT_STMT) + if (binlog_format == BINLOG_FORMAT_STMT) { my_error(ER_BINLOG_NON_SUPPORTED_BULK, MYF(0)); DBUG_PRINT("info", @@ -6243,7 +6267,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) prev_access_table= table; } - if (wsrep_binlog_format() != BINLOG_FORMAT_ROW) + if (binlog_format != BINLOG_FORMAT_ROW) { /* DML statements that modify a table with an auto_increment @@ -6327,7 +6351,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) */ my_error((error= ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE), MYF(0)); } - else if ((wsrep_binlog_format() == BINLOG_FORMAT_ROW || is_bulk_op()) && + else if ((binlog_format == BINLOG_FORMAT_ROW || is_bulk_op()) && sqlcom_can_generate_row_events(this)) { /* @@ -6357,7 +6381,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) else { /* binlog_format = STATEMENT */ - if (wsrep_binlog_format() == BINLOG_FORMAT_STMT) + if (binlog_format == BINLOG_FORMAT_STMT) { if (lex->is_stmt_row_injection()) { @@ -6497,7 +6521,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) "and binlog_filter->db_ok(db) = %d", mysql_bin_log.is_open(), (variables.option_bits & OPTION_BIN_LOG), - (uint) wsrep_binlog_format(), + (uint) binlog_format, binlog_filter->db_ok(db.str))); #endif @@ -6533,7 +6557,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) void THD::reconsider_logging_format_for_iodup(TABLE *table) { DBUG_ENTER("reconsider_logging_format_for_iodup"); - enum_binlog_format bf= (enum_binlog_format) wsrep_binlog_format(); + enum_binlog_format bf= (enum_binlog_format) wsrep_binlog_format(variables.binlog_format); DBUG_ASSERT(lex->duplicates == DUP_UPDATE); diff --git a/sql/sql_class.h b/sql/sql_class.h index e96fe300eba..b40acd084ca 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4255,7 +4255,7 @@ public: tests fail and so force them to propagate the lex->binlog_row_based_if_mixed upwards to the caller. */ - if ((wsrep_binlog_format() == BINLOG_FORMAT_MIXED) && (in_sub_stmt == 0)) + if ((wsrep_binlog_format(variables.binlog_format) == BINLOG_FORMAT_MIXED) && (in_sub_stmt == 0)) set_current_stmt_binlog_format_row(); DBUG_VOID_RETURN; @@ -4311,7 +4311,7 @@ public: show_system_thread(system_thread))); if (in_sub_stmt == 0) { - if (wsrep_binlog_format() == BINLOG_FORMAT_ROW) + if (wsrep_binlog_format(variables.binlog_format) == BINLOG_FORMAT_ROW) set_current_stmt_binlog_format_row(); else if (!has_temporary_tables()) set_current_stmt_binlog_format_stmt(); @@ -4958,9 +4958,18 @@ public: */ bool is_awaiting_semisync_ack; - inline ulong wsrep_binlog_format() const + inline ulong wsrep_binlog_format(ulong binlog_format) const { - return WSREP_BINLOG_FORMAT(variables.binlog_format); +#ifdef WITH_WSREP + // During CTAS we force ROW format + if (wsrep_ctas) + return BINLOG_FORMAT_ROW; + else + return ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? + wsrep_forced_binlog_format : binlog_format); +#else + return (binlog_format); +#endif } #ifdef WITH_WSREP @@ -5003,11 +5012,9 @@ public: void *wsrep_apply_format; uchar* wsrep_rbr_buf; wsrep_gtid_t wsrep_sync_wait_gtid; - // wsrep_gtid_t wsrep_last_written_gtid; ulong wsrep_affected_rows; bool wsrep_has_ignored_error; bool wsrep_replicate_GTID; - /* When enabled, do not replicate/binlog updates from the current table that's being processed. At the moment, it is used to keep mysql.gtid_slave_pos @@ -5027,7 +5034,8 @@ public: /* true if BF abort is observed in do_command() right after reading client's packet, and if the client has sent PS execute command. */ bool wsrep_delayed_BF_abort; - + // true if this transaction is CREATE TABLE AS SELECT (CTAS) + bool wsrep_ctas; /* Transaction id: * m_wsrep_next_trx_id is assigned on the first query after diff --git a/sql/sql_error.cc b/sql/sql_error.cc index a11a0f454a2..2975d86579e 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -537,6 +537,18 @@ bool Warning_info::has_sql_condition(const char *message_str, size_t message_len return false; } +bool Warning_info::has_sql_condition(uint sql_errno) const +{ + Diagnostics_area::Sql_condition_iterator it(m_warn_list); + const Sql_condition *err; + + while ((err = it++)) + { + if (err->get_sql_errno() == sql_errno) + return true; + } + return false; +} void Warning_info::clear(ulonglong new_id) { diff --git a/sql/sql_error.h b/sql/sql_error.h index 5f52aea7dd6..1e3e2dacd50 100644 --- a/sql/sql_error.h +++ b/sql/sql_error.h @@ -591,6 +591,16 @@ private: */ bool has_sql_condition(const char *message_str, size_t message_length) const; + /** + Checks if Warning_info contains SQL-condition with the given error id + + @param sql_errno SQL-condition error number + + @return true if the Warning_info contains an SQL-condition with the given + error id. + */ + bool has_sql_condition(uint sql_errno) const; + /** Reset the warning information. Clear all warnings, the number of warnings, reset current row counter @@ -1126,6 +1136,9 @@ public: bool has_sql_condition(const char *message_str, size_t message_length) const { return get_warning_info()->has_sql_condition(message_str, message_length); } + bool has_sql_condition(uint sql_errno) const + { return get_warning_info()->has_sql_condition(sql_errno); } + void reset_for_next_command() { get_warning_info()->reset_for_next_command(); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 659db7b01fb..c3acce2f4a5 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -475,7 +475,7 @@ void upgrade_lock_type(THD *thd, thr_lock_type *lock_type, } bool log_on= (thd->variables.option_bits & OPTION_BIN_LOG); - if (WSREP_BINLOG_FORMAT(global_system_variables.binlog_format) == BINLOG_FORMAT_STMT && + if (thd->wsrep_binlog_format(global_system_variables.binlog_format) == BINLOG_FORMAT_STMT && log_on && mysql_bin_log.is_open()) { /* diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 218bf1cfcaa..99839e61ba8 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -57,7 +57,33 @@ #include #ifdef WITH_WSREP #include "wsrep_mysqld.h" -#endif + +/** RAII class for temporarily enabling wsrep_ctas in the connection. */ +class Enable_wsrep_ctas_guard +{ + public: + /** + @param thd - pointer to the context of connection in which + wsrep_ctas mode needs to be enabled. + @param ctas - true if this is CREATE TABLE AS SELECT and + wsrep_on + */ + explicit Enable_wsrep_ctas_guard(THD *thd, const bool ctas) + : m_thd(thd) + { + if (ctas) + thd->wsrep_ctas= true; + } + + ~Enable_wsrep_ctas_guard() + { + m_thd->wsrep_ctas= false; + } + private: + THD* m_thd; +}; + +#endif /* WITH_WSREP */ #include "sql_debug.h" #ifdef __WIN__ @@ -11519,6 +11545,7 @@ bool Sql_cmd_create_table_like::execute(THD *thd) int res= 0; const bool used_engine= lex->create_info.used_fields & HA_CREATE_USED_ENGINE; + ulong binlog_format= thd->wsrep_binlog_format(thd->variables.binlog_format); DBUG_ASSERT((m_storage_engine_name.str != NULL) == used_engine); if (used_engine) { @@ -11558,6 +11585,14 @@ bool Sql_cmd_create_table_like::execute(THD *thd) */ Alter_info alter_info(lex->alter_info, thd->mem_root); +#ifdef WITH_WSREP + // If CREATE TABLE AS SELECT and wsrep_on + const bool wsrep_ctas= (select_lex->item_list.elements && WSREP(thd)); + + // This will be used in THD::decide_logging_format if CTAS + Enable_wsrep_ctas_guard wsrep_ctas_guard(thd, wsrep_ctas); +#endif + if (unlikely(thd->is_fatal_error)) { /* If out of memory when creating a copy of alter_info. */ @@ -11627,15 +11662,17 @@ bool Sql_cmd_create_table_like::execute(THD *thd) #endif #ifdef WITH_WSREP - if (select_lex->item_list.elements && // With SELECT - WSREP(thd) && thd->variables.wsrep_trx_fragment_size > 0) + if (wsrep_ctas) { - my_message( + if (thd->variables.wsrep_trx_fragment_size > 0) + { + my_message( ER_NOT_ALLOWED_COMMAND, "CREATE TABLE AS SELECT is not supported with streaming replication", MYF(0)); - res= 1; - goto end_with_restore_list; + res= 1; + goto end_with_restore_list; + } } #endif /* WITH_WSREP */ @@ -11665,7 +11702,7 @@ bool Sql_cmd_create_table_like::execute(THD *thd) (see 'NAME_CONST issues' in 'Binary Logging of Stored Programs') */ if (thd->query_name_consts && mysql_bin_log.is_open() && - thd->wsrep_binlog_format() == BINLOG_FORMAT_STMT && + binlog_format == BINLOG_FORMAT_STMT && !mysql_bin_log.is_query_in_union(thd, thd->query_id)) { List_iterator_fast it(select_lex->item_list); @@ -11802,10 +11839,11 @@ bool Sql_cmd_create_table_like::execute(THD *thd) #ifdef WITH_WSREP WSREP_TO_ISOLATION_BEGIN_ALTER(create_table->db.str, create_table->table_name.str, first_table, &alter_info, NULL) - { - WSREP_WARN("CREATE TABLE isolation failure"); - DBUG_RETURN(true); - } + { + WSREP_WARN("CREATE TABLE isolation failure"); + res= true; + goto end_with_restore_list; + } #endif /* WITH_WSREP */ } // check_engine will set db_type to NULL if e.g. TEMPORARY is diff --git a/sql/wsrep_on.h b/sql/wsrep_on.h index f85fe3d5d0d..a3ef834523c 100644 --- a/sql/wsrep_on.h +++ b/sql/wsrep_on.h @@ -46,10 +46,6 @@ extern ulong wsrep_forced_binlog_format; #define WSREP_EMULATE_BINLOG(thd) \ (WSREP(thd) && wsrep_emulate_bin_log) -#define WSREP_BINLOG_FORMAT(my_format) \ - ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \ - wsrep_forced_binlog_format : my_format) - #else #define WSREP_ON false @@ -57,7 +53,6 @@ extern ulong wsrep_forced_binlog_format; #define WSREP_NNULL(T) (0) #define WSREP_EMULATE_BINLOG(thd) (0) #define WSREP_EMULATE_BINLOG_NNULL(thd) (0) -#define WSREP_BINLOG_FORMAT(my_format) ((ulong)my_format) #endif #endif From 3626379d42e8cf28f9470d5f2213736d78ab5180 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Tue, 3 Oct 2023 16:20:34 +0300 Subject: [PATCH 020/158] MDEV-20168: main.innodb_icp fails in BB with various wrong execution plans Add FORCE INDEX and ANALYZE TABLE PERSISTENT FOR ALL to make the plans stable. --- mysql-test/include/icp_tests.inc | 6 ++++-- mysql-test/main/innodb_icp.result | 16 ++++++++++++++-- mysql-test/main/myisam_icp.result | 16 ++++++++++++++-- mysql-test/suite/maria/icp.result | 16 ++++++++++++++-- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/mysql-test/include/icp_tests.inc b/mysql-test/include/icp_tests.inc index 965a4a5f5d2..f1873c09e50 100644 --- a/mysql-test/include/icp_tests.inc +++ b/mysql-test/include/icp_tests.inc @@ -160,7 +160,7 @@ INSERT INTO t1 VALUES --echo --echo # Execute select with invalid timestamp, desc ordering SELECT * -FROM t1 +FROM t1 FORCE INDEX(PRIMARY) WHERE ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00' ORDER BY ts DESC LIMIT 2; @@ -169,7 +169,7 @@ LIMIT 2; --echo # Should use index condition EXPLAIN SELECT * -FROM t1 +FROM t1 FORCE INDEX(PRIMARY) WHERE ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00' ORDER BY ts DESC LIMIT 2; @@ -456,6 +456,7 @@ INSERT INTO t2 VALUES (11,1); INSERT INTO t2 VALUES (12,2); INSERT INTO t2 VALUES (15,4); +analyze table t1,t2 persistent for all; set @save_optimizer_switch= @@optimizer_switch; set optimizer_switch='semijoin=off'; @@ -725,6 +726,7 @@ CREATE TABLE t2 (a varchar(1024), KEY (a(512))); INSERT INTO t2 VALUES ('Ill'), ('eckqzsflbzaffti'), ('w'), ('she'), ('gxbwypqtjzwywwer'), ('w'); +analyze table t1,t2 persistent for all; SET SESSION optimizer_switch='index_condition_pushdown=off'; EXPLAIN SELECT t1.b, t1.c FROM t1, t2 WHERE t1.a = t2.a AND (t1.b<0 OR t1.b>0) diff --git a/mysql-test/main/innodb_icp.result b/mysql-test/main/innodb_icp.result index 96ff1964ac1..4b303027201 100644 --- a/mysql-test/main/innodb_icp.result +++ b/mysql-test/main/innodb_icp.result @@ -156,7 +156,7 @@ INSERT INTO t1 VALUES # Execute select with invalid timestamp, desc ordering SELECT * -FROM t1 +FROM t1 FORCE INDEX(PRIMARY) WHERE ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00' ORDER BY ts DESC LIMIT 2; @@ -167,7 +167,7 @@ ts c # Should use index condition EXPLAIN SELECT * -FROM t1 +FROM t1 FORCE INDEX(PRIMARY) WHERE ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00' ORDER BY ts DESC LIMIT 2; @@ -429,6 +429,12 @@ CREATE TABLE t2 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); INSERT INTO t2 VALUES (11,1); INSERT INTO t2 VALUES (12,2); INSERT INTO t2 VALUES (15,4); +analyze table t1,t2 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK set @save_optimizer_switch= @@optimizer_switch; set optimizer_switch='semijoin=off'; EXPLAIN @@ -685,6 +691,12 @@ INSERT INTO t1 VALUES (1,4,'Ill'); CREATE TABLE t2 (a varchar(1024), KEY (a(512))); INSERT INTO t2 VALUES ('Ill'), ('eckqzsflbzaffti'), ('w'), ('she'), ('gxbwypqtjzwywwer'), ('w'); +analyze table t1,t2 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK SET SESSION optimizer_switch='index_condition_pushdown=off'; EXPLAIN SELECT t1.b, t1.c FROM t1, t2 WHERE t1.a = t2.a AND (t1.b<0 OR t1.b>0) diff --git a/mysql-test/main/myisam_icp.result b/mysql-test/main/myisam_icp.result index 7f0e1d1b516..f7a51d60d2b 100644 --- a/mysql-test/main/myisam_icp.result +++ b/mysql-test/main/myisam_icp.result @@ -149,7 +149,7 @@ INSERT INTO t1 VALUES # Execute select with invalid timestamp, desc ordering SELECT * -FROM t1 +FROM t1 FORCE INDEX(PRIMARY) WHERE ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00' ORDER BY ts DESC LIMIT 2; @@ -160,7 +160,7 @@ ts c # Should use index condition EXPLAIN SELECT * -FROM t1 +FROM t1 FORCE INDEX(PRIMARY) WHERE ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00' ORDER BY ts DESC LIMIT 2; @@ -422,6 +422,12 @@ CREATE TABLE t2 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); INSERT INTO t2 VALUES (11,1); INSERT INTO t2 VALUES (12,2); INSERT INTO t2 VALUES (15,4); +analyze table t1,t2 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK set @save_optimizer_switch= @@optimizer_switch; set optimizer_switch='semijoin=off'; EXPLAIN @@ -678,6 +684,12 @@ INSERT INTO t1 VALUES (1,4,'Ill'); CREATE TABLE t2 (a varchar(1024), KEY (a(512))); INSERT INTO t2 VALUES ('Ill'), ('eckqzsflbzaffti'), ('w'), ('she'), ('gxbwypqtjzwywwer'), ('w'); +analyze table t1,t2 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK SET SESSION optimizer_switch='index_condition_pushdown=off'; EXPLAIN SELECT t1.b, t1.c FROM t1, t2 WHERE t1.a = t2.a AND (t1.b<0 OR t1.b>0) diff --git a/mysql-test/suite/maria/icp.result b/mysql-test/suite/maria/icp.result index 975c280d467..4f5697e097e 100644 --- a/mysql-test/suite/maria/icp.result +++ b/mysql-test/suite/maria/icp.result @@ -151,7 +151,7 @@ INSERT INTO t1 VALUES # Execute select with invalid timestamp, desc ordering SELECT * -FROM t1 +FROM t1 FORCE INDEX(PRIMARY) WHERE ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00' ORDER BY ts DESC LIMIT 2; @@ -162,7 +162,7 @@ ts c # Should use index condition EXPLAIN SELECT * -FROM t1 +FROM t1 FORCE INDEX(PRIMARY) WHERE ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00' ORDER BY ts DESC LIMIT 2; @@ -424,6 +424,12 @@ CREATE TABLE t2 (pk INTEGER PRIMARY KEY, i INTEGER NOT NULL); INSERT INTO t2 VALUES (11,1); INSERT INTO t2 VALUES (12,2); INSERT INTO t2 VALUES (15,4); +analyze table t1,t2 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK set @save_optimizer_switch= @@optimizer_switch; set optimizer_switch='semijoin=off'; EXPLAIN @@ -680,6 +686,12 @@ INSERT INTO t1 VALUES (1,4,'Ill'); CREATE TABLE t2 (a varchar(1024), KEY (a(512))); INSERT INTO t2 VALUES ('Ill'), ('eckqzsflbzaffti'), ('w'), ('she'), ('gxbwypqtjzwywwer'), ('w'); +analyze table t1,t2 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK SET SESSION optimizer_switch='index_condition_pushdown=off'; EXPLAIN SELECT t1.b, t1.c FROM t1, t2 WHERE t1.a = t2.a AND (t1.b<0 OR t1.b>0) From e2da748c29f2cedd5125aa5e48e22b934164efb7 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 19 Jul 2023 15:10:47 +0400 Subject: [PATCH 021/158] MDEV-28835 Assertion `(length % 4) == 0' failed in my_lengthsp_utf32 on INSERT Problem: Item_func_date_format::val_str() and make_date_time() did not take into account that the format string and the result string (separately or at the same time) can be of a tricky character set like UCS2, UTF16, UTF32. As a result, DATE_FORMAT() could generate an ill-formed result which crashed on DBUG_ASSERTs testing well-formedness in other parts of the code. Fix: 1. class String changes Removing String::append_with_prefill(). It was not compatible with tricky character sets. Also it was inconvenient to use and required too much duplicate code on the caller side. Adding String::append_zerofill() instead. It's compatible with tricky character sets and is easier to use. Adding helper methods Static_binary_string::q_append_wc() and String::append_wc(), to append a single wide character (a Unicode code point in my_wc_t). 2. storage/spider changes Removing spider_string::append_with_prefill(). It used String::append_with_prefix() inside, but it was unused itself. 3. Changing tricky charset incompatible code pieces in make_date_time() to compatible replacements: - Fixing the loop scanning the format string to iterate in terms of Unicode code points (using mb_wc()) rather than in terms of "char" items. - Using append_wc(my_wc_t) instead of append(char) to append a single character to the result string. - Using append_zerofill() instead of append_with_prefill() to append date/time numeric components to the result string. --- mysql-test/main/ctype_binary.result | 44 +++++++++ mysql-test/main/ctype_binary.test | 25 +++++ mysql-test/main/ctype_utf32.result | 64 +++++++++++++ mysql-test/main/ctype_utf32.test | 42 +++++++++ sql/item_timefunc.cc | 137 ++++++++++++++-------------- sql/sql_string.cc | 18 ---- sql/sql_string.h | 40 +++++++- storage/spider/spd_db_include.h | 6 -- storage/spider/spd_malloc.cc | 17 ---- 9 files changed, 280 insertions(+), 113 deletions(-) diff --git a/mysql-test/main/ctype_binary.result b/mysql-test/main/ctype_binary.result index b43f2136e30..d2e22e1a9cb 100644 --- a/mysql-test/main/ctype_binary.result +++ b/mysql-test/main/ctype_binary.result @@ -3394,5 +3394,49 @@ INSERT INTO t VALUES (0,0); DELETE FROM t WHERE c2length(0); if (l_time->neg) - str->append('-'); + str->append_wc('-'); - end= (ptr= format.str) + format.length; - for (; ptr != end ; ptr++) + end= (ptr= (const uchar *) format.str) + format.length; + + for ( ; ; ) { - if (*ptr != '%' || ptr+1 == end) - str->append(*ptr); + my_wc_t wc; + int mblen= format_charset->cset->mb_wc(format_charset, &wc, ptr, end); + if (mblen < 1) + return false; + ptr+= mblen; + + if (wc != '%' || ptr >= end) + str->append_wc(wc); else { - switch (*++ptr) { + mblen= format_charset->cset->mb_wc(format_charset, &wc, ptr, end); + if (mblen < 1) + return false; + ptr+= mblen; + + switch (wc) { case 'M': if (type == MYSQL_TIMESTAMP_TIME || !l_time->month) return 1; @@ -536,8 +550,7 @@ static bool make_date_time(const LEX_CSTRING &format, MYSQL_TIME *l_time, case 'D': if (type == MYSQL_TIMESTAMP_TIME) return 1; - length= (uint) (int10_to_str(l_time->day, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 1, '0'); + str->append_zerofill(l_time->day, 1); if (l_time->day >= 10 && l_time->day <= 19) str->append(STRING_WITH_LEN("th")); else @@ -561,73 +574,62 @@ static bool make_date_time(const LEX_CSTRING &format, MYSQL_TIME *l_time, case 'Y': if (type == MYSQL_TIMESTAMP_TIME) return 1; - length= (uint) (int10_to_str(l_time->year, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 4, '0'); + str->append_zerofill(l_time->year, 4); break; case 'y': if (type == MYSQL_TIMESTAMP_TIME) return 1; - length= (uint) (int10_to_str(l_time->year%100, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 2, '0'); + str->append_zerofill(l_time->year % 100, 2); break; case 'm': if (type == MYSQL_TIMESTAMP_TIME) return 1; - length= (uint) (int10_to_str(l_time->month, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 2, '0'); + str->append_zerofill(l_time->month, 2); break; case 'c': if (type == MYSQL_TIMESTAMP_TIME) return 1; - length= (uint) (int10_to_str(l_time->month, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 1, '0'); + str->append_zerofill(l_time->month, 1); break; case 'd': if (type == MYSQL_TIMESTAMP_TIME) return 1; - length= (uint) (int10_to_str(l_time->day, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 2, '0'); + str->append_zerofill(l_time->day, 2); break; case 'e': if (type == MYSQL_TIMESTAMP_TIME) return 1; - length= (uint) (int10_to_str(l_time->day, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 1, '0'); + str->append_zerofill(l_time->day, 1); break; case 'f': - length= (uint) (int10_to_str(l_time->second_part, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 6, '0'); + str->append_zerofill((uint) l_time->second_part, 6); break; case 'H': - length= (uint) (int10_to_str(l_time->hour, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 2, '0'); + str->append_zerofill(l_time->hour, 2); break; case 'h': case 'I': hours_i= (l_time->hour%24 + 11)%12+1; - length= (uint) (int10_to_str(hours_i, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 2, '0'); + str->append_zerofill(hours_i, 2); break; case 'i': /* minutes */ - length= (uint) (int10_to_str(l_time->minute, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 2, '0'); + str->append_zerofill(l_time->minute, 2); break; case 'j': + { if (type == MYSQL_TIMESTAMP_TIME || !l_time->month || !l_time->year) return 1; - length= (uint) (int10_to_str(calc_daynr(l_time->year,l_time->month, - l_time->day) - - calc_daynr(l_time->year,1,1) + 1, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 3, '0'); + long value= calc_daynr(l_time->year,l_time->month, l_time->day) - + calc_daynr(l_time->year,1,1) + 1; + str->append_zerofill((uint) value, 3); break; + } case 'k': - length= (uint) (int10_to_str(l_time->hour, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 1, '0'); + str->append_zerofill(l_time->hour, 1); break; case 'l': hours_i= (l_time->hour%24 + 11)%12+1; - length= (uint) (int10_to_str(hours_i, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 1, '0'); + str->append_zerofill(hours_i, 1); break; case 'p': hours_i= l_time->hour%24; @@ -643,8 +645,7 @@ static bool make_date_time(const LEX_CSTRING &format, MYSQL_TIME *l_time, break; case 'S': case 's': - length= (uint) (int10_to_str(l_time->second, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 2, '0'); + str->append_zerofill(l_time->second, 2); break; case 'T': length= sprintf(intbuff, "%02d:%02d:%02d", @@ -657,42 +658,39 @@ static bool make_date_time(const LEX_CSTRING &format, MYSQL_TIME *l_time, uint year; if (type == MYSQL_TIMESTAMP_TIME) return 1; - length= (uint) (int10_to_str(calc_week(l_time, - (*ptr) == 'U' ? - WEEK_FIRST_WEEKDAY : WEEK_MONDAY_FIRST, - &year), - intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 2, '0'); + + uint value= calc_week(l_time, + wc == 'U' ? WEEK_FIRST_WEEKDAY : + WEEK_MONDAY_FIRST, + &year); + str->append_zerofill(value, 2); } break; case 'v': case 'V': { - uint year; - if (type == MYSQL_TIMESTAMP_TIME) - return 1; - length= (uint) (int10_to_str(calc_week(l_time, - ((*ptr) == 'V' ? - (WEEK_YEAR | WEEK_FIRST_WEEKDAY) : - (WEEK_YEAR | WEEK_MONDAY_FIRST)), - &year), - intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 2, '0'); + uint year; + if (type == MYSQL_TIMESTAMP_TIME) + return 1; + uint value= calc_week(l_time, wc == 'V' ? + (WEEK_YEAR | WEEK_FIRST_WEEKDAY) : + (WEEK_YEAR | WEEK_MONDAY_FIRST), + &year); + str->append_zerofill(value, 2); } break; case 'x': case 'X': { - uint year; - if (type == MYSQL_TIMESTAMP_TIME) - return 1; - (void) calc_week(l_time, - ((*ptr) == 'X' ? - WEEK_YEAR | WEEK_FIRST_WEEKDAY : - WEEK_YEAR | WEEK_MONDAY_FIRST), - &year); - length= (uint) (int10_to_str(year, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 4, '0'); + uint year; + if (type == MYSQL_TIMESTAMP_TIME) + return 1; + (void) calc_week(l_time, + (wc == 'X' ? + WEEK_YEAR | WEEK_FIRST_WEEKDAY : + WEEK_YEAR | WEEK_MONDAY_FIRST), + &year); + str->append_zerofill(year, 4); } break; case 'w': @@ -700,12 +698,11 @@ static bool make_date_time(const LEX_CSTRING &format, MYSQL_TIME *l_time, return 1; weekday=calc_weekday(calc_daynr(l_time->year,l_time->month, l_time->day),1); - length= (uint) (int10_to_str(weekday, intbuff, 10) - intbuff); - str->append_with_prefill(intbuff, length, 1, '0'); + str->append_zerofill(weekday, 1); break; default: - str->append(*ptr); + str->append_wc(wc); break; } } @@ -1919,7 +1916,7 @@ String *Item_func_date_format::val_str(String *str) /* Create the result string */ str->set_charset(collation.collation); - if (!make_date_time(format->lex_cstring(), &l_time, + if (!make_date_time(format->lex_cstring(), format->charset(), &l_time, is_time_format ? MYSQL_TIMESTAMP_TIME : MYSQL_TIMESTAMP_DATE, lc, str)) diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 6de1207db95..2f49d842783 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -649,24 +649,6 @@ bool String::append_parenthesized(long nr, int radix) } -bool String::append_with_prefill(const char *s,uint32 arg_length, - uint32 full_length, char fill_char) -{ - int t_length= arg_length > full_length ? arg_length : full_length; - - if (realloc_with_extra_if_needed(str_length + t_length)) - return TRUE; - t_length= full_length - arg_length; - if (t_length > 0) - { - bfill(Ptr+str_length, t_length, fill_char); - str_length=str_length + t_length; - } - append(s, arg_length); - return FALSE; -} - - int Static_binary_string::strstr(const Static_binary_string &s, uint32 offset) { if (s.length()+offset <= str_length) diff --git a/sql/sql_string.h b/sql/sql_string.h index 491e2766643..883b7a28b69 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -392,6 +392,19 @@ public: float8store(Ptr + str_length, *d); str_length += 8; } + /* + Append a wide character. + The caller must have allocated at least cs->mbmaxlen bytes. + */ + int q_append_wc(my_wc_t wc, CHARSET_INFO *cs) + { + int mblen; + if ((mblen= cs->cset->wc_mb(cs, wc, + (uchar *) end(), + (uchar *) end() + cs->mbmaxlen)) > 0) + str_length+= (uint32) mblen; + return mblen; + } void q_append(const char *data, size_t data_len) { if (data_len) @@ -1009,8 +1022,6 @@ public: (quot && append(quot)); } bool append(const char *s, size_t size); - bool append_with_prefill(const char *s, uint32 arg_length, - uint32 full_length, char fill_char); bool append_parenthesized(long nr, int radix= 10); // Append with optional character set conversion from cs to charset() @@ -1020,6 +1031,31 @@ public: return append(s.str, s.length, cs); } + // Append a wide character + bool append_wc(my_wc_t wc) + { + if (reserve(mbmaxlen())) + return true; + int mblen= q_append_wc(wc, charset()); + if (mblen > 0) + return false; + else if (mblen == MY_CS_ILUNI && wc != '?') + return q_append_wc('?', charset()) <= 0; + return true; + } + + // Append a number with zero prefilling + bool append_zerofill(uint num, uint width) + { + static const char zeros[15]= "00000000000000"; + char intbuff[15]; + uint length= (uint) (int10_to_str(num, intbuff, 10) - intbuff); + if (length < width && + append(zeros, width - length, &my_charset_latin1)) + return true; + return append(intbuff, length, &my_charset_latin1); + } + /* Append a bitmask in an uint32 with a translation into a C-style human readable representation, e.g.: diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index 307c6638c3a..74b1a186355 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -445,12 +445,6 @@ public: IO_CACHE *file, uint32 arg_length ); - bool append_with_prefill( - const char *s, - uint32 arg_length, - uint32 full_length, - char fill_char - ); int strstr( const String &search, uint32 offset = 0 diff --git a/storage/spider/spd_malloc.cc b/storage/spider/spd_malloc.cc index 40b37ff4377..f43131d630d 100644 --- a/storage/spider/spd_malloc.cc +++ b/storage/spider/spd_malloc.cc @@ -941,23 +941,6 @@ bool spider_string::append( DBUG_RETURN(res); } -bool spider_string::append_with_prefill( - const char *s, - uint32 arg_length, - uint32 full_length, - char fill_char -) { - DBUG_ENTER("spider_string::append_with_prefill"); - DBUG_PRINT("info",("spider this=%p", this)); - DBUG_ASSERT(mem_calc_inited); - DBUG_ASSERT((!current_alloc_mem && !str.is_alloced()) || - current_alloc_mem == str.alloced_length()); - bool res = str.append_with_prefill(s, arg_length, full_length, - fill_char); - SPIDER_STRING_CALC_MEM; - DBUG_RETURN(res); -} - int spider_string::strstr( const String &search, uint32 offset From 534a2bf1c65c04d2a624df9a9afe481752ad0f0f Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 4 Oct 2023 14:22:02 +0400 Subject: [PATCH 022/158] MDEV-32275 getting error 'Illegal parameter data types row and bigint for operation '+' ' when using ITERATE in a FOR..DO An "ITERATE innerLoop" did not work properly inside a WHILE loop, which itself is inside an outer FOR loop: outerLoop: FOR ... innerLoop: WHILE ... ITERATE innerLoop; ... END WHILE; ... END FOR; It erroneously generated an integer increment code for the outer FOR loop. There were two problems: 1. "ITERATE innerLoop" worked like "ITERATE outerLoop" 2. It was always integer increment, even in case of FOR cursor loops. Background: - A FOR loop automatically creates a dedicated sp_pcontext stack entry, to put the iteration and bound variables on it. - Other loop types (LOOP, WHILE, REPEAT), do not generate a dedicated slack entry. The old code erroneously assumed that sp_pcontext::m_for_loop either describes the most inner loop (in case the inner loop is FOR), or is empty (in case the inner loop is not FOR). But in fact, sp_pcontext::m_for_loop is never empty inside a FOR loop: it describes the closest FOR loop, even if this FOR loop has nested non-FOR loops inside. So when we're near the ITERATE statement in the above script, sp_pcontext::m_for_loop is not empty - it stores information about the FOR loop labeled as "outrLoop:". Fix: - Adding a new member sp_pcontext::Lex_for_loop::m_start_label, to remember the explicit or the auto-generated label correspoding to the start of the FOR body. It's used during generation of "ITERATE loop_label" code to check if "loop_label" belongs to the current FOR loop pointed by sp_pcontext::m_for_loop, or belongs to a non-FOR nested loop. - Adding LEX methods sp_for_loop_intrange_iterate() and sp_for_loop_cursor_iterate() to reuse the code between methods handling: * ITERATE * END FOR - Adding a test for Lex_for_loop::is_for_loop_cursor() and generate a code either a cursor fetch, or for an integer increment. Before this change, it always erroneously generated an integer increment version. - Cleanup: Initialize Lex_for_loop_st::m_cursor_offset inside Lex_for_loop_st::init(), to avoid not initialized members. - Cleanup: Removing a redundant method: Lex_for_loop_st::init(const Lex_for_loop_st &other) Using Lex_for_loop_st::operator(const Lex_for_loop_st &other) instead. --- mysql-test/main/sp-code.result | 327 +++++++++++++++++++++++++++++ mysql-test/main/sp-code.test | 224 ++++++++++++++++++++ mysql-test/main/sp-for-loop.result | 30 +++ mysql-test/main/sp-for-loop.test | 38 ++++ sql/sp_pcontext.h | 27 ++- sql/sql_lex.cc | 32 +-- sql/sql_lex.h | 13 +- sql/structs.h | 5 +- 8 files changed, 672 insertions(+), 24 deletions(-) diff --git a/mysql-test/main/sp-code.result b/mysql-test/main/sp-code.result index 2b5f7374ce6..a4e3f00ba04 100644 --- a/mysql-test/main/sp-code.result +++ b/mysql-test/main/sp-code.result @@ -1356,3 +1356,330 @@ drop function f1; # # End of 10.3 tests # +# +# Start of 10.4 tests +# +# +# MDEV-32275 getting error 'Illegal parameter data types row and bigint for operation '+' ' when using ITERATE in a FOR..DO +# +# +# Unlabeled FOR/cursor with a nested labeled LOOP inside +# +CREATE OR REPLACE PROCEDURE p1() +BEGIN +DECLARE loopDone TINYINT DEFAULT FALSE; +FOR _row IN (SELECT '' AS a) DO +SELECT 'start of outerLoop'; +innerLoop: LOOP +SELECT 'start of innerLoop'; +IF loopDone THEN +LEAVE innerLoop; +END IF; +SET loopDone = TRUE; +IF _row.a = 'v1' + THEN +SELECT 'start of THEN block'; +ITERATE innerLoop; +END IF; +SELECT 'end of innerLoop'; +END LOOP; +SELECT 'end of outerLoop'; +END FOR; +END +$$ +SHOW PROCEDURE CODE p1; +Pos Instruction +0 set loopDone@0 0 +1 cpush [implicit_cursor]@0 +2 cursor_copy_struct [implicit_cursor] _row@1 +3 copen [implicit_cursor]@0 +4 cfetch [implicit_cursor]@0 _row@1 +5 jump_if_not 19(19) `[implicit_cursor]`%FOUND +6 stmt 0 "SELECT 'start of outerLoop'" +7 stmt 0 "SELECT 'start of innerLoop'" +8 jump_if_not 10(10) loopDone@0 +9 jump 16 +10 set loopDone@0 1 +11 jump_if_not 14(14) _row.a@1["a"] = 'v1' +12 stmt 0 "SELECT 'start of THEN block'" +13 jump 7 +14 stmt 0 "SELECT 'end of innerLoop'" +15 jump 7 +16 stmt 0 "SELECT 'end of outerLoop'" +17 cfetch [implicit_cursor]@0 _row@1 +18 jump 5 +19 cpop 1 +DROP PROCEDURE p1; +# +# Labeled FOR/cursor with a nested labeled LOOP +# +CREATE OR REPLACE PROCEDURE p1() +BEGIN +DECLARE loopDone TINYINT DEFAULT FALSE; +outerLoop: +FOR _row IN (SELECT '' AS a) DO +SELECT 'start of outerLoop'; +innerLoop: LOOP +SELECT 'start of innerLoop'; +IF loopDone THEN +LEAVE innerLoop; +END IF; +SET loopDone = TRUE; +IF _row.a = 'v1' + THEN +SELECT 'start of IF/v1/THEN block'; +ITERATE innerLoop; +END IF; +IF _row.a = 'v2' + THEN +SELECT 'start of IF/v2/THEN block'; +ITERATE outerLoop; +END IF; +SELECT 'end of innerLoop'; +END LOOP; +SELECT 'end of outerLoop'; +END FOR; +END +$$ +SHOW PROCEDURE CODE p1; +Pos Instruction +0 set loopDone@0 0 +1 cpush [implicit_cursor]@0 +2 cursor_copy_struct [implicit_cursor] _row@1 +3 copen [implicit_cursor]@0 +4 cfetch [implicit_cursor]@0 _row@1 +5 jump_if_not 23(23) `[implicit_cursor]`%FOUND +6 stmt 0 "SELECT 'start of outerLoop'" +7 stmt 0 "SELECT 'start of innerLoop'" +8 jump_if_not 10(10) loopDone@0 +9 jump 20 +10 set loopDone@0 1 +11 jump_if_not 14(14) _row.a@1["a"] = 'v1' +12 stmt 0 "SELECT 'start of IF/v1/THEN block'" +13 jump 7 +14 jump_if_not 18(18) _row.a@1["a"] = 'v2' +15 stmt 0 "SELECT 'start of IF/v2/THEN block'" +16 cfetch [implicit_cursor]@0 _row@1 +17 jump 5 +18 stmt 0 "SELECT 'end of innerLoop'" +19 jump 7 +20 stmt 0 "SELECT 'end of outerLoop'" +21 cfetch [implicit_cursor]@0 _row@1 +22 jump 5 +23 cpop 1 +DROP PROCEDURE p1; +# +# Unlabeled FOR/integer with a labeled LOOP inside +# +CREATE OR REPLACE PROCEDURE p1() +BEGIN +DECLARE loopDone TINYINT DEFAULT FALSE; +FOR _index IN 1..10 DO +SELECT 'start of outerLoop'; +innerLoop: LOOP +SELECT 'start of innerLoop'; +IF loopDone THEN +LEAVE innerLoop; +END IF; +SET loopDone = TRUE; +IF _index = 1 +THEN +SELECT 'start of THEN block'; +ITERATE innerLoop; +END IF; +SELECT 'end of innerLoop'; +END LOOP; +SELECT 'end of outerLoop'; +END FOR; +END +$$ +SHOW PROCEDURE CODE p1; +Pos Instruction +0 set loopDone@0 0 +1 set _index@1 1 +2 set [target_bound]@2 10 +3 jump_if_not 19(19) _index@1 <= [target_bound]@2 +4 stmt 0 "SELECT 'start of outerLoop'" +5 stmt 0 "SELECT 'start of innerLoop'" +6 jump_if_not 8(8) loopDone@0 +7 jump 14 +8 set loopDone@0 1 +9 jump_if_not 12(12) _index@1 = 1 +10 stmt 0 "SELECT 'start of THEN block'" +11 jump 5 +12 stmt 0 "SELECT 'end of innerLoop'" +13 jump 5 +14 stmt 0 "SELECT 'end of outerLoop'" +15 set _index@1 _index@1 + 1 +16 jump 3 +DROP PROCEDURE p1; +# +# Labeled FOR/integer with a labeled LOOP inside +# +CREATE OR REPLACE PROCEDURE p1() +BEGIN +DECLARE loopDone TINYINT DEFAULT FALSE; +outerLoop: +FOR _index IN 1..10 DO +SELECT 'start of outerLoop'; +innerLoop: LOOP +SELECT 'start of innerLoop'; +IF loopDone THEN +LEAVE innerLoop; +END IF; +SET loopDone = TRUE; +IF _index = 1 +THEN +SELECT 'start of IF/1/THEN block'; +ITERATE innerLoop; +END IF; +IF _index = 2 +THEN +SELECT 'start of IF/2/THEN block'; +ITERATE outerLoop; +END IF; +SELECT 'end of innerLoop'; +END LOOP; +SELECT 'end of outerLoop'; +END FOR; +END +$$ +SHOW PROCEDURE CODE p1; +Pos Instruction +0 set loopDone@0 0 +1 set _index@1 1 +2 set [target_bound]@2 10 +3 jump_if_not 24(24) _index@1 <= [target_bound]@2 +4 stmt 0 "SELECT 'start of outerLoop'" +5 stmt 0 "SELECT 'start of innerLoop'" +6 jump_if_not 8(8) loopDone@0 +7 jump 18 +8 set loopDone@0 1 +9 jump_if_not 12(12) _index@1 = 1 +10 stmt 0 "SELECT 'start of IF/1/THEN block'" +11 jump 5 +12 jump_if_not 16(16) _index@1 = 2 +13 stmt 0 "SELECT 'start of IF/2/THEN block'" +14 set _index@1 _index@1 + 1 +15 jump 3 +16 stmt 0 "SELECT 'end of innerLoop'" +17 jump 5 +18 stmt 0 "SELECT 'end of outerLoop'" +19 set _index@1 _index@1 + 1 +20 jump 3 +DROP PROCEDURE p1; +# +# Unlabeled FOR/integer with a labeled FOR inside +# +CREATE OR REPLACE PROCEDURE p1() +BEGIN +DECLARE loopDone TINYINT DEFAULT FALSE; +FOR _index_outer IN 1..10 DO +SELECT 'start of outerLoop'; +innerLoop: +FOR _index_inner IN 1..10 DO +SELECT 'start of innerLoop'; +IF loopDone THEN +LEAVE innerLoop; +END IF; +SET loopDone = TRUE; +IF _index_inner = 1 +THEN +SELECT 'start of IF/1/THEN block'; +ITERATE innerLoop; +END IF; +SELECT 'end of innerLoop'; +END FOR; +SELECT 'end of outerLoop'; +END FOR; +END +$$ +SHOW PROCEDURE CODE p1; +Pos Instruction +0 set loopDone@0 0 +1 set _index_outer@1 1 +2 set [target_bound]@2 10 +3 jump_if_not 24(24) _index_outer@1 <= [target_bound]@2 +4 stmt 0 "SELECT 'start of outerLoop'" +5 set _index_inner@3 1 +6 set [target_bound]@4 10 +7 jump_if_not 19(19) _index_inner@3 <= [target_bound]@4 +8 stmt 0 "SELECT 'start of innerLoop'" +9 jump_if_not 11(11) loopDone@0 +10 jump 19 +11 set loopDone@0 1 +12 jump_if_not 16(16) _index_inner@3 = 1 +13 stmt 0 "SELECT 'start of IF/1/THEN block'" +14 set _index_inner@3 _index_inner@3 + 1 +15 jump 7 +16 stmt 0 "SELECT 'end of innerLoop'" +17 set _index_inner@3 _index_inner@3 + 1 +18 jump 7 +19 stmt 0 "SELECT 'end of outerLoop'" +20 set _index_outer@1 _index_outer@1 + 1 +21 jump 3 +DROP PROCEDURE p1; +# +# Labeled FOR/integer with a labeled FOR inside +# +CREATE OR REPLACE PROCEDURE p1() +BEGIN +DECLARE loopDone TINYINT DEFAULT FALSE; +outerLoop: +FOR _index_outer IN 1..10 DO +SELECT 'start of outerLoop'; +innerLoop: +FOR _index_inner IN 1..10 DO +SELECT 'start of innerLoop'; +IF loopDone THEN +LEAVE innerLoop; +END IF; +SET loopDone = TRUE; +IF _index_inner = 1 +THEN +SELECT 'start of IF/1/THEN block'; +ITERATE innerLoop; +END IF; +IF _index_inner = 2 +THEN +SELECT 'start of IF/2/THEN block'; +ITERATE outerLoop; +END IF; +SELECT 'end of innerLoop'; +END FOR; +SELECT 'end of outerLoop'; +END FOR; +END +$$ +SHOW PROCEDURE CODE p1; +Pos Instruction +0 set loopDone@0 0 +1 set _index_outer@1 1 +2 set [target_bound]@2 10 +3 jump_if_not 29(29) _index_outer@1 <= [target_bound]@2 +4 stmt 0 "SELECT 'start of outerLoop'" +5 set _index_inner@3 1 +6 set [target_bound]@4 10 +7 jump_if_not 23(23) _index_inner@3 <= [target_bound]@4 +8 stmt 0 "SELECT 'start of innerLoop'" +9 jump_if_not 11(11) loopDone@0 +10 jump 23 +11 set loopDone@0 1 +12 jump_if_not 16(16) _index_inner@3 = 1 +13 stmt 0 "SELECT 'start of IF/1/THEN block'" +14 set _index_inner@3 _index_inner@3 + 1 +15 jump 7 +16 jump_if_not 20(20) _index_inner@3 = 2 +17 stmt 0 "SELECT 'start of IF/2/THEN block'" +18 set _index_outer@1 _index_outer@1 + 1 +19 jump 3 +20 stmt 0 "SELECT 'end of innerLoop'" +21 set _index_inner@3 _index_inner@3 + 1 +22 jump 7 +23 stmt 0 "SELECT 'end of outerLoop'" +24 set _index_outer@1 _index_outer@1 + 1 +25 jump 3 +DROP PROCEDURE p1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/sp-code.test b/mysql-test/main/sp-code.test index 35c9d4b9da1..1563e1e373a 100644 --- a/mysql-test/main/sp-code.test +++ b/mysql-test/main/sp-code.test @@ -975,3 +975,227 @@ drop function f1; --echo # --echo # End of 10.3 tests --echo # + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-32275 getting error 'Illegal parameter data types row and bigint for operation '+' ' when using ITERATE in a FOR..DO +--echo # + +--echo # +--echo # Unlabeled FOR/cursor with a nested labeled LOOP inside +--echo # + +DELIMITER $$; +CREATE OR REPLACE PROCEDURE p1() +BEGIN + DECLARE loopDone TINYINT DEFAULT FALSE; + FOR _row IN (SELECT '' AS a) DO + SELECT 'start of outerLoop'; + innerLoop: LOOP + SELECT 'start of innerLoop'; + IF loopDone THEN + LEAVE innerLoop; + END IF; + SET loopDone = TRUE; + IF _row.a = 'v1' + THEN + SELECT 'start of THEN block'; + ITERATE innerLoop; + END IF; + SELECT 'end of innerLoop'; + END LOOP; + SELECT 'end of outerLoop'; + END FOR; +END +$$ +DELIMITER ;$$ +SHOW PROCEDURE CODE p1; +DROP PROCEDURE p1; + + +--echo # +--echo # Labeled FOR/cursor with a nested labeled LOOP +--echo # + +DELIMITER $$; +CREATE OR REPLACE PROCEDURE p1() +BEGIN + DECLARE loopDone TINYINT DEFAULT FALSE; +outerLoop: + FOR _row IN (SELECT '' AS a) DO + SELECT 'start of outerLoop'; + innerLoop: LOOP + SELECT 'start of innerLoop'; + IF loopDone THEN + LEAVE innerLoop; + END IF; + SET loopDone = TRUE; + IF _row.a = 'v1' + THEN + SELECT 'start of IF/v1/THEN block'; + ITERATE innerLoop; + END IF; + IF _row.a = 'v2' + THEN + SELECT 'start of IF/v2/THEN block'; + ITERATE outerLoop; + END IF; + SELECT 'end of innerLoop'; + END LOOP; + SELECT 'end of outerLoop'; + END FOR; +END +$$ +DELIMITER ;$$ +SHOW PROCEDURE CODE p1; +DROP PROCEDURE p1; + + +--echo # +--echo # Unlabeled FOR/integer with a labeled LOOP inside +--echo # + +DELIMITER $$; +CREATE OR REPLACE PROCEDURE p1() +BEGIN + DECLARE loopDone TINYINT DEFAULT FALSE; + FOR _index IN 1..10 DO + SELECT 'start of outerLoop'; + innerLoop: LOOP + SELECT 'start of innerLoop'; + IF loopDone THEN + LEAVE innerLoop; + END IF; + SET loopDone = TRUE; + IF _index = 1 + THEN + SELECT 'start of THEN block'; + ITERATE innerLoop; + END IF; + SELECT 'end of innerLoop'; + END LOOP; + SELECT 'end of outerLoop'; + END FOR; +END +$$ +DELIMITER ;$$ +SHOW PROCEDURE CODE p1; +DROP PROCEDURE p1; + + +--echo # +--echo # Labeled FOR/integer with a labeled LOOP inside +--echo # + +DELIMITER $$; +CREATE OR REPLACE PROCEDURE p1() +BEGIN + DECLARE loopDone TINYINT DEFAULT FALSE; +outerLoop: + FOR _index IN 1..10 DO + SELECT 'start of outerLoop'; + innerLoop: LOOP + SELECT 'start of innerLoop'; + IF loopDone THEN + LEAVE innerLoop; + END IF; + SET loopDone = TRUE; + IF _index = 1 + THEN + SELECT 'start of IF/1/THEN block'; + ITERATE innerLoop; + END IF; + IF _index = 2 + THEN + SELECT 'start of IF/2/THEN block'; + ITERATE outerLoop; + END IF; + SELECT 'end of innerLoop'; + END LOOP; + SELECT 'end of outerLoop'; + END FOR; +END +$$ +DELIMITER ;$$ +SHOW PROCEDURE CODE p1; +DROP PROCEDURE p1; + + +--echo # +--echo # Unlabeled FOR/integer with a labeled FOR inside +--echo # + +DELIMITER $$; +CREATE OR REPLACE PROCEDURE p1() +BEGIN + DECLARE loopDone TINYINT DEFAULT FALSE; + FOR _index_outer IN 1..10 DO + SELECT 'start of outerLoop'; + innerLoop: + FOR _index_inner IN 1..10 DO + SELECT 'start of innerLoop'; + IF loopDone THEN + LEAVE innerLoop; + END IF; + SET loopDone = TRUE; + IF _index_inner = 1 + THEN + SELECT 'start of IF/1/THEN block'; + ITERATE innerLoop; + END IF; + SELECT 'end of innerLoop'; + END FOR; + SELECT 'end of outerLoop'; + END FOR; +END +$$ +DELIMITER ;$$ +SHOW PROCEDURE CODE p1; +DROP PROCEDURE p1; + + + +--echo # +--echo # Labeled FOR/integer with a labeled FOR inside +--echo # + +DELIMITER $$; +CREATE OR REPLACE PROCEDURE p1() +BEGIN + DECLARE loopDone TINYINT DEFAULT FALSE; +outerLoop: + FOR _index_outer IN 1..10 DO + SELECT 'start of outerLoop'; + innerLoop: + FOR _index_inner IN 1..10 DO + SELECT 'start of innerLoop'; + IF loopDone THEN + LEAVE innerLoop; + END IF; + SET loopDone = TRUE; + IF _index_inner = 1 + THEN + SELECT 'start of IF/1/THEN block'; + ITERATE innerLoop; + END IF; + IF _index_inner = 2 + THEN + SELECT 'start of IF/2/THEN block'; + ITERATE outerLoop; + END IF; + SELECT 'end of innerLoop'; + END FOR; + SELECT 'end of outerLoop'; + END FOR; +END +$$ +DELIMITER ;$$ +SHOW PROCEDURE CODE p1; +DROP PROCEDURE p1; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/sp-for-loop.result b/mysql-test/main/sp-for-loop.result index d62d6ae3612..72fad0643b1 100644 --- a/mysql-test/main/sp-for-loop.result +++ b/mysql-test/main/sp-for-loop.result @@ -206,3 +206,33 @@ SELECT f1(3), f1(4), f1(5) FROM DUAL; f1(3) f1(4) f1(5) 6 8 8 DROP FUNCTION f1; +# +# End of 10.3 tests +# +# +# Start of 10.4 tests +# +# +# MDEV-32275 getting error 'Illegal parameter data types row and bigint for operation '+' ' when using ITERATE in a FOR..DO +# +CREATE OR REPLACE PROCEDURE forIterateBug() +BEGIN +DECLARE loopDone TINYINT DEFAULT FALSE; +FOR _unused IN (SELECT '') DO +innerLoop: LOOP +IF loopDone THEN +LEAVE innerLoop; +END IF; +SET loopDone = TRUE; +BEGIN +ITERATE innerLoop; +END; +END LOOP; +END FOR; +END; +$$ +CALL forIterateBug; +DROP PROCEDURE forIterateBug; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/sp-for-loop.test b/mysql-test/main/sp-for-loop.test index 420ab58aaa7..d6b30b0e99f 100644 --- a/mysql-test/main/sp-for-loop.test +++ b/mysql-test/main/sp-for-loop.test @@ -210,3 +210,41 @@ END; DELIMITER ;/ SELECT f1(3), f1(4), f1(5) FROM DUAL; DROP FUNCTION f1; + +--echo # +--echo # End of 10.3 tests +--echo # + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-32275 getting error 'Illegal parameter data types row and bigint for operation '+' ' when using ITERATE in a FOR..DO +--echo # + +DELIMITER $$; +CREATE OR REPLACE PROCEDURE forIterateBug() +BEGIN + DECLARE loopDone TINYINT DEFAULT FALSE; + FOR _unused IN (SELECT '') DO + innerLoop: LOOP + IF loopDone THEN + LEAVE innerLoop; + END IF; + SET loopDone = TRUE; + BEGIN + ITERATE innerLoop; + END; + END LOOP; + END FOR; +END; +$$ +DELIMITER ;$$ +CALL forIterateBug; +DROP PROCEDURE forIterateBug; + + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index b1d77234f54..b44a1cd3b7d 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -371,7 +371,28 @@ public: class Lex_for_loop: public Lex_for_loop_st { public: - Lex_for_loop() { init(); } + /* + The label poiting to the body start, + either explicit or automatically generated. + Used during generation of "ITERATE loop_label" + to check if "loop_label" is a FOR loop label. + - In case of a FOR loop, some additional code + (cursor fetch or iteger increment) is generated before + the backward jump to the beginning of the loop body. + - In case of other loop types (WHILE, REPEAT) + only the jump is generated. + */ + const sp_label *m_start_label; + + Lex_for_loop() + :m_start_label(NULL) + { Lex_for_loop_st::init(); } + + Lex_for_loop(const Lex_for_loop_st &for_loop, const sp_label *start) + :m_start_label(start) + { + Lex_for_loop_st::operator=(for_loop); + } }; public: @@ -679,9 +700,9 @@ public: void set_for_loop(const Lex_for_loop_st &for_loop) { - m_for_loop.init(for_loop); + m_for_loop= Lex_for_loop(for_loop, last_label()); } - const Lex_for_loop_st &for_loop() + const Lex_for_loop &for_loop() { return m_for_loop; } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index c0f639b55ec..8b9e8183b48 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -6362,7 +6362,7 @@ bool LEX::sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop) } -bool LEX::sp_for_loop_intrange_finalize(THD *thd, const Lex_for_loop_st &loop) +bool LEX::sp_for_loop_intrange_iterate(THD *thd, const Lex_for_loop_st &loop) { sphead->reset_lex(thd); @@ -6372,13 +6372,12 @@ bool LEX::sp_for_loop_intrange_finalize(THD *thd, const Lex_for_loop_st &loop) thd->lex->sphead->restore_lex(thd))) return true; - // Generate a jump to the beginning of the loop DBUG_ASSERT(this == thd->lex); - return sp_while_loop_finalize(thd); + return false; } -bool LEX::sp_for_loop_cursor_finalize(THD *thd, const Lex_for_loop_st &loop) +bool LEX::sp_for_loop_cursor_iterate(THD *thd, const Lex_for_loop_st &loop) { sp_instr_cfetch *instr= new (thd->mem_root) sp_instr_cfetch(sphead->instructions(), @@ -6386,10 +6385,10 @@ bool LEX::sp_for_loop_cursor_finalize(THD *thd, const Lex_for_loop_st &loop) if (unlikely(instr == NULL) || unlikely(sphead->add_instr(instr))) return true; instr->add_to_varlist(loop.m_index); - // Generate a jump to the beginning of the loop - return sp_while_loop_finalize(thd); + return false; } + bool LEX::sp_for_loop_outer_block_finalize(THD *thd, const Lex_for_loop_st &loop) { @@ -6970,13 +6969,22 @@ bool LEX::sp_iterate_statement(THD *thd, const LEX_CSTRING *label_name) bool LEX::sp_continue_loop(THD *thd, sp_label *lab) { - if (lab->ctx->for_loop().m_index) + const sp_pcontext::Lex_for_loop &for_loop= lab->ctx->for_loop(); + /* + FOR loops need some additional instructions (e.g. an integer increment or + a cursor fetch) before the "jump to the start of the body" instruction. + We need to check two things here: + - If we're in a FOR loop at all. + - If the label pointed by "lab" belongs exactly to the nearest FOR loop, + rather than to a nested LOOP/WHILE/REPEAT inside the FOR. + */ + if (for_loop.m_index /* we're in some FOR loop */ && + for_loop.m_start_label == lab /* lab belongs to the FOR loop */) { - // We're in a FOR loop, increment the index variable before backward jump - sphead->reset_lex(thd); - DBUG_ASSERT(this != thd->lex); - if (thd->lex->sp_for_loop_increment(thd, lab->ctx->for_loop()) || - thd->lex->sphead->restore_lex(thd)) + // We're in a FOR loop, and "ITERATE loop_label" belongs to this FOR loop. + if (for_loop.is_for_loop_cursor() ? + sp_for_loop_cursor_iterate(thd, for_loop) : + sp_for_loop_intrange_iterate(thd, for_loop)) return true; } return sp_change_context(thd, lab->ctx, false) || diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 2e0b3604244..1208d63d7f0 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -4158,7 +4158,7 @@ public: const LEX_CSTRING *index, const Lex_for_loop_bounds_st &bounds); bool sp_for_loop_intrange_condition_test(THD *thd, const Lex_for_loop_st &loop); - bool sp_for_loop_intrange_finalize(THD *thd, const Lex_for_loop_st &loop); + bool sp_for_loop_intrange_iterate(THD *thd, const Lex_for_loop_st &loop); /* Cursor FOR LOOP methods */ bool sp_for_loop_cursor_declarations(THD *thd, Lex_for_loop_st *loop, @@ -4174,7 +4174,7 @@ public: Lex_for_loop_bounds_st *bounds, sp_lex_cursor *cur); bool sp_for_loop_cursor_condition_test(THD *thd, const Lex_for_loop_st &loop); - bool sp_for_loop_cursor_finalize(THD *thd, const Lex_for_loop_st &); + bool sp_for_loop_cursor_iterate(THD *thd, const Lex_for_loop_st &); /* Generic FOR LOOP methods*/ @@ -4232,9 +4232,12 @@ public: */ bool sp_for_loop_finalize(THD *thd, const Lex_for_loop_st &loop) { - return loop.is_for_loop_cursor() ? - sp_for_loop_cursor_finalize(thd, loop) : - sp_for_loop_intrange_finalize(thd, loop); + if (loop.is_for_loop_cursor() ? + sp_for_loop_cursor_iterate(thd, loop) : + sp_for_loop_intrange_iterate(thd, loop)) + return true; + // Generate a jump to the beginning of the loop + return sp_while_loop_finalize(thd); } bool sp_for_loop_outer_block_finalize(THD *thd, const Lex_for_loop_st &loop); diff --git a/sql/structs.h b/sql/structs.h index 2e6683ec706..7d8aed43786 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -744,13 +744,10 @@ public: { m_index= 0; m_target_bound= 0; + m_cursor_offset= 0; m_direction= 0; m_implicit_cursor= false; } - void init(const Lex_for_loop_st &other) - { - *this= other; - } bool is_for_loop_cursor() const { return m_target_bound == NULL; } bool is_for_loop_explicit_cursor() const { From e4ce61ac0f319a64c1991124c3dfbc9cda2a7873 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 5 Oct 2023 09:49:25 +0400 Subject: [PATCH 023/158] MDEV-32226 UBSAN shift exponent X is too large for 64-bit type 'long long int' in sql/field.cc --- mysql-test/main/type_set.result | 64 +++++++++++++++++++++++++++++++++ mysql-test/main/type_set.test | 9 +++++ sql/field.cc | 8 ++--- 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/mysql-test/main/type_set.result b/mysql-test/main/type_set.result index ea057157569..2e53eb8768e 100644 --- a/mysql-test/main/type_set.result +++ b/mysql-test/main/type_set.result @@ -379,3 +379,67 @@ a FLOOR(a) CEILING(a) TRUNCATE(a,0) ROUND(a) 999999999999999999999999999999999999999999999999999999999999 1 1 1 1 DROP TABLE t2; DROP TABLE t1; +# +# MDEV-32226 UBSAN shift exponent X is too large for 64-bit type 'long long int' in sql/field.cc +# +SET sql_mode=''; +CREATE TABLE t (f SET('1','2','3','4','5','6','7','8','9','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1')); +Warnings: +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +Note 1291 Column 'f' has duplicated value '1' in SET +INSERT INTO t VALUES ('0'); +DROP TABLE t; diff --git a/mysql-test/main/type_set.test b/mysql-test/main/type_set.test index 2d0c81340ae..9608b3385f8 100644 --- a/mysql-test/main/type_set.test +++ b/mysql-test/main/type_set.test @@ -261,3 +261,12 @@ SHOW CREATE TABLE t2; SELECT * FROM t2; DROP TABLE t2; DROP TABLE t1; + +--echo # +--echo # MDEV-32226 UBSAN shift exponent X is too large for 64-bit type 'long long int' in sql/field.cc +--echo # + +SET sql_mode=''; +CREATE TABLE t (f SET('1','2','3','4','5','6','7','8','9','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1')); +INSERT INTO t VALUES ('0'); +DROP TABLE t; diff --git a/sql/field.cc b/sql/field.cc index ff45b6c5de9..3e30fbadccc 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -9568,13 +9568,13 @@ int Field_set::store(const char *from,size_t length,CHARSET_INFO *cs) /* This is for reading numbers with LOAD DATA INFILE */ char *end; tmp=my_strntoull(cs,from,length,10,&end,&err); - if (err || end != from+length || - tmp > (ulonglong) (((longlong) 1 << typelib->count) - (longlong) 1)) + if (err || end != from + length) { - tmp=0; set_warning(WARN_DATA_TRUNCATED, 1); - err= 1; + store_type(0); + return 1; } + return Field_set::store((longlong) tmp, true/*unsigned*/); } else if (got_warning) set_warning(WARN_DATA_TRUNCATED, 1); From 422774b40a3574b8e2342dcb5add097b68b80a04 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Thu, 5 Oct 2023 16:57:52 +0300 Subject: [PATCH 024/158] MDEV-10683: main.order_by_optimizer_innodb fails in buildbot Fix order_by_optimizer_innodb and order_by_innodb tests. The problem was that the query could be ran before InnoDB was ready to provide a realistic statistic for #records in the table. It provided a number that was too low, which caused the optimizer to decide that range access plan wasn't advantageous and discard it. --- mysql-test/main/order_by_innodb.result | 10 ++++++++++ mysql-test/main/order_by_innodb.test | 2 ++ mysql-test/main/order_by_optimizer_innodb.result | 4 ++++ mysql-test/main/order_by_optimizer_innodb.test | 1 + 4 files changed, 17 insertions(+) diff --git a/mysql-test/main/order_by_innodb.result b/mysql-test/main/order_by_innodb.result index 17d39eb12e6..12390e2979c 100644 --- a/mysql-test/main/order_by_innodb.result +++ b/mysql-test/main/order_by_innodb.result @@ -159,6 +159,12 @@ insert into t2 values (1,2,'2019-03-05 00:00:00','2019-03-06 00:00:00'), (2,3,'2019-03-05 00:00:00','2019-03-06 00:00:00'), (3,3,'2019-03-06 00:00:00','2019-03-05 00:00:00'); +analyze table t1,t2 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK select t1.id,t2.id from @@ -177,6 +183,10 @@ id id 2 1 3 3 create index for_latest_sort on t2 (d1 desc, d2 desc, id desc); +analyze table t2 persistent for all; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK select t1.id,t2.id from diff --git a/mysql-test/main/order_by_innodb.test b/mysql-test/main/order_by_innodb.test index 29b796f67bc..aa8c16a126c 100644 --- a/mysql-test/main/order_by_innodb.test +++ b/mysql-test/main/order_by_innodb.test @@ -148,6 +148,7 @@ insert into t2 values (2,3,'2019-03-05 00:00:00','2019-03-06 00:00:00'), (3,3,'2019-03-06 00:00:00','2019-03-05 00:00:00'); +analyze table t1,t2 persistent for all; select t1.id,t2.id from @@ -163,6 +164,7 @@ from ); create index for_latest_sort on t2 (d1 desc, d2 desc, id desc); +analyze table t2 persistent for all; select t1.id,t2.id diff --git a/mysql-test/main/order_by_optimizer_innodb.result b/mysql-test/main/order_by_optimizer_innodb.result index 0b62ba997d8..17d5d82e1c9 100644 --- a/mysql-test/main/order_by_optimizer_innodb.result +++ b/mysql-test/main/order_by_optimizer_innodb.result @@ -24,6 +24,10 @@ REPEAT('filler-data-', 10), REPEAT('filler-data-', 10) from t1; +analyze table t2 persistent for all; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK select pk1, count(*) from t2 group by pk1; pk1 count(*) 0 1 diff --git a/mysql-test/main/order_by_optimizer_innodb.test b/mysql-test/main/order_by_optimizer_innodb.test index 90430d11549..4726b8f6fad 100644 --- a/mysql-test/main/order_by_optimizer_innodb.test +++ b/mysql-test/main/order_by_optimizer_innodb.test @@ -33,6 +33,7 @@ select from t1; +analyze table t2 persistent for all; select pk1, count(*) from t2 group by pk1; --echo # The following should use range(ux_pk1_fd5), two key parts (key_len=5+8=13) From 96ae37abc51a622e271d23875970a2e86c7a1883 Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Tue, 3 Oct 2023 20:07:39 +0300 Subject: [PATCH 025/158] MDEV-30658 lock_row_lock_current_waits counter in information_schema.innodb_metrics may become negative MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MONITOR_OVLD_ROW_LOCK_CURRENT_WAIT monitor should has MONITOR_DISPLAY_CURRENT flag set in its definition, as it shows the current state and does not accumulate anything. Reviewed by: Marko Mäkelä --- .../r/innodb_skip_innodb_is_tables.result | 2 +- .../r/mon_lock_wait_current_count.result | 54 +++++++++++++ .../innodb/t/mon_lock_wait_current_count.test | 76 +++++++++++++++++++ storage/innobase/lock/lock0wait.cc | 1 + storage/innobase/srv/srv0mon.cc | 2 +- 5 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/innodb/r/mon_lock_wait_current_count.result create mode 100644 mysql-test/suite/innodb/t/mon_lock_wait_current_count.test diff --git a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result index 26f3267440e..486a9fd7c8f 100644 --- a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result +++ b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result @@ -50,7 +50,7 @@ lock_rec_locks lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabl lock_table_lock_created lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of table locks created lock_table_lock_removed lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of table locks removed from the lock queue lock_table_locks lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Current number of table locks on tables -lock_row_lock_current_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of row locks currently being waited for (innodb_row_lock_current_waits) +lock_row_lock_current_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled value Number of row locks currently being waited for (innodb_row_lock_current_waits) lock_row_lock_time lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Time spent in acquiring row locks, in milliseconds (innodb_row_lock_time) lock_row_lock_time_max lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled value The maximum time to acquire a row lock, in milliseconds (innodb_row_lock_time_max) lock_row_lock_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of times a row lock had to be waited for (innodb_row_lock_waits) diff --git a/mysql-test/suite/innodb/r/mon_lock_wait_current_count.result b/mysql-test/suite/innodb/r/mon_lock_wait_current_count.result new file mode 100644 index 00000000000..d30bf863001 --- /dev/null +++ b/mysql-test/suite/innodb/r/mon_lock_wait_current_count.result @@ -0,0 +1,54 @@ +connect prevent_purge,localhost,root,,; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +SET GLOBAL innodb_monitor_disable='all'; +SET GLOBAL innodb_monitor_enable='lock_row_lock_current_waits'; +CREATE TABLE `t` (a INT PRIMARY KEY) engine=InnoDB STATS_PERSISTENT=0; +INSERT INTO t VALUES (5); +SELECT name, count FROM information_schema.innodb_metrics +WHERE name ='lock_row_lock_current_waits'; +name count +lock_row_lock_current_waits 0 +connect con1,localhost,root,,; +BEGIN; +SELECT * FROM t FOR UPDATE; +a +5 +connect con2,localhost,root,,; +SET DEBUG_SYNC="lock_wait_before_suspend SIGNAL blocked WAIT_FOR cont"; +BEGIN; +SELECT * FROM t FOR UPDATE; +connection default; +SET DEBUG_SYNC="now WAIT_FOR blocked"; +SELECT name, count FROM information_schema.innodb_metrics +WHERE name ='lock_row_lock_current_waits'; +name count +lock_row_lock_current_waits 1 +SET GLOBAL innodb_monitor_disable='lock_row_lock_current_waits'; +SET GLOBAL innodb_monitor_reset_all='lock_row_lock_current_waits'; +SET GLOBAL innodb_monitor_enable='lock_row_lock_current_waits'; +SELECT name, count FROM information_schema.innodb_metrics +WHERE name ='lock_row_lock_current_waits'; +name count +lock_row_lock_current_waits 1 +SET DEBUG_SYNC="now SIGNAL cont"; +disconnect con1; +connection con2; +a +5 +COMMIT; +disconnect con2; +connection default; +SET DEBUG_SYNC="reset"; +SELECT name, count FROM information_schema.innodb_metrics +WHERE name ='lock_row_lock_current_waits'; +name count +lock_row_lock_current_waits 0 +DROP TABLE `t`; +SET GLOBAL innodb_monitor_disable='lock_row_lock_current_waits'; +SET GLOBAL innodb_monitor_reset_all='lock_row_lock_current_waits'; +SET GLOBAL innodb_monitor_enable='lock_row_lock_current_waits'; +SET GLOBAL innodb_monitor_disable=default; +SET GLOBAL innodb_monitor_reset_all=default; +SET GLOBAL innodb_monitor_enable=default; +disconnect prevent_purge; diff --git a/mysql-test/suite/innodb/t/mon_lock_wait_current_count.test b/mysql-test/suite/innodb/t/mon_lock_wait_current_count.test new file mode 100644 index 00000000000..5bceb1ec881 --- /dev/null +++ b/mysql-test/suite/innodb/t/mon_lock_wait_current_count.test @@ -0,0 +1,76 @@ +# Check if lock_row_lock_current_waits counter in +# information_schema.innodb_metrics does not become negative after disabling, +# resetting and enabling. + +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/count_sessions.inc + +--connect (prevent_purge,localhost,root,,) +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +--connection default +SET GLOBAL innodb_monitor_disable='all'; +SET GLOBAL innodb_monitor_enable='lock_row_lock_current_waits'; +CREATE TABLE `t` (a INT PRIMARY KEY) engine=InnoDB STATS_PERSISTENT=0; +INSERT INTO t VALUES (5); +SELECT name, count FROM information_schema.innodb_metrics + WHERE name ='lock_row_lock_current_waits'; + +--connect (con1,localhost,root,,) +BEGIN; +SELECT * FROM t FOR UPDATE; + +--connect (con2,localhost,root,,) +SET DEBUG_SYNC="lock_wait_before_suspend SIGNAL blocked WAIT_FOR cont"; +BEGIN; +--send SELECT * FROM t FOR UPDATE + +--connection default +SET DEBUG_SYNC="now WAIT_FOR blocked"; +SELECT name, count FROM information_schema.innodb_metrics + WHERE name ='lock_row_lock_current_waits'; +SET GLOBAL innodb_monitor_disable='lock_row_lock_current_waits'; +SET GLOBAL innodb_monitor_reset_all='lock_row_lock_current_waits'; +SET GLOBAL innodb_monitor_enable='lock_row_lock_current_waits'; +###################################### +# Equals to zero if the bug is not fixed, as MONITOR_DISPLAY_CURRENT is not +# set for this counter and its value is reset during previous +# "SET GLOBAL innodb_monitor_reset_all='lock_row_lock_current_waits'" execution. +##### +SELECT name, count FROM information_schema.innodb_metrics + WHERE name ='lock_row_lock_current_waits'; +SET DEBUG_SYNC="now SIGNAL cont"; + +--disconnect con1 + +--connection con2 +--reap +COMMIT; +--disconnect con2 + +--connection default +SET DEBUG_SYNC="reset"; +###################################### +# Equals to -1 if the bug is not fixed. I.e. +# innodb_counter_value[MONITOR_OVLD_ROW_LOCK_CURRENT_WAIT].mon_start_value is +# set to 1 during +# "set global innodb_monitor_disable='lock_row_lock_current_waits'" execution, +# and the value is counted as +# (value = 0) - (mon_value_reset = 0) - (mon_start_value = 1) + +# (mon_last_value = 0) = -1. See MONITOR_SET_DIFF() macro in +# srv_mon_process_existing_counter() for details. +##### +SELECT name, count FROM information_schema.innodb_metrics + WHERE name ='lock_row_lock_current_waits'; +DROP TABLE `t`; +SET GLOBAL innodb_monitor_disable='lock_row_lock_current_waits'; +SET GLOBAL innodb_monitor_reset_all='lock_row_lock_current_waits'; +SET GLOBAL innodb_monitor_enable='lock_row_lock_current_waits'; +--disable_warnings +SET GLOBAL innodb_monitor_disable=default; +SET GLOBAL innodb_monitor_reset_all=default; +SET GLOBAL innodb_monitor_enable=default; +--enable_warnings +--disconnect prevent_purge +--source include/wait_until_count_sessions.inc diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc index a26b3a6efaa..18d5eba6b48 100644 --- a/storage/innobase/lock/lock0wait.cc +++ b/storage/innobase/lock/lock0wait.cc @@ -340,6 +340,7 @@ lock_wait_suspend_thread( thd_wait_begin(trx->mysql_thd, THD_WAIT_TABLE_LOCK); } + DEBUG_SYNC_C("lock_wait_before_suspend"); os_event_wait(slot->event); DBUG_EXECUTE_IF("small_sleep_after_lock_wait", { diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index 97ea562140c..2c46a41b122 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -145,7 +145,7 @@ static monitor_info_t innodb_counter_info[] = "Number of row locks currently being waited for" " (innodb_row_lock_current_waits)", static_cast( - MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_EXISTING | MONITOR_DISPLAY_CURRENT | MONITOR_DEFAULT_ON), MONITOR_DEFAULT_START, MONITOR_OVLD_ROW_LOCK_CURRENT_WAIT}, {"lock_row_lock_time", "lock", From a34b989f0c0ae8a968ac5b881a41a9143c9dcdeb Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 13 Sep 2023 17:42:54 +1000 Subject: [PATCH 026/158] MDEV-22418 mysqladmin wrong error with simple_password_check mysqladmin's presumption about the cause of an error by looking at the error code was presumptious. Server knows best, so pass the error along. Avoid returning -1 as a exit code, Linux makes this 255 and Windows keeps this as -1. --- client/mysqladmin.cc | 21 +++---------------- .../plugins/r/simple_password_check.result | 10 +++++++++ .../plugins/t/simple_password_check.test | 18 ++++++++++++++++ 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 0b31ca3a5ce..05abec9fe61 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -431,6 +431,7 @@ int main(int argc,char *argv[]) if (error > 0) break; + error= -error; /* don't exit with negative error codes */ /* Command was well-formed, but failed on the server. Might succeed on retry (if conditions on server change etc.), but needs --force @@ -1204,24 +1205,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) else if (mysql_query(mysql,buff)) { - if (mysql_errno(mysql)!=1290) - { - my_printf_error(0,"unable to change password; error: '%s'", - error_flags, mysql_error(mysql)); - } - else - { - /* - We don't try to execute 'update mysql.user set..' - because we can't perfectly find out the host - */ - my_printf_error(0,"\n" - "You cannot use 'password' command as mysqld runs\n" - " with grant tables disabled (was started with" - " --skip-grant-tables).\n" - "Use: \"mysqladmin flush-privileges password '*'\"" - " instead", error_flags); - } + my_printf_error(0,"unable to change password; error: '%s'", + error_flags, mysql_error(mysql)); ret = -1; } password_done: diff --git a/mysql-test/suite/plugins/r/simple_password_check.result b/mysql-test/suite/plugins/r/simple_password_check.result index c4f8d15fc51..3790bb8f8d8 100644 --- a/mysql-test/suite/plugins/r/simple_password_check.result +++ b/mysql-test/suite/plugins/r/simple_password_check.result @@ -250,3 +250,13 @@ Grants for foo1@localhost GRANT USAGE ON *.* TO `foo1`@`localhost` IDENTIFIED BY PASSWORD '*1D62FA326F98258451ED56A404F15452423DCC1D' drop user foo1@localhost; uninstall plugin simple_password_check; +# +# MDEV-22418 mysqladmin wrong error with simple_password_check +# +install soname "simple_password_check"; +MARIADB-ADMIN: unable to change password; error: 'The MariaDB server is running with the --strict-password-validation option so it cannot execute this statement' +# All done +uninstall plugin simple_password_check; +# +# End of 10.4 tests +# diff --git a/mysql-test/suite/plugins/t/simple_password_check.test b/mysql-test/suite/plugins/t/simple_password_check.test index 3ce2d86cd68..442585e89d4 100644 --- a/mysql-test/suite/plugins/t/simple_password_check.test +++ b/mysql-test/suite/plugins/t/simple_password_check.test @@ -150,3 +150,21 @@ flush privileges; show grants for foo1@localhost; drop user foo1@localhost; uninstall plugin simple_password_check; + + +--echo # +--echo # MDEV-22418 mysqladmin wrong error with simple_password_check +--echo # + +install soname "simple_password_check"; + +--replace_regex /.*[\/\\]// /(mysqladmin|mariadb-admin)(\.exe)?/MARIADB-ADMIN/ +--error 1 +--exec $MYSQLADMIN -uroot password foo 2>&1 + +--echo # All done +uninstall plugin simple_password_check; + +--echo # +--echo # End of 10.4 tests +--echo # From ebf364925998273d5a3d522980c512c8093a1c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 6 Oct 2023 12:30:43 +0300 Subject: [PATCH 027/158] MDEV-32361 mariadb-backup --move-back leaves out ib_logfile0 copy_back(): Also copy the dummy empty ib_logfile0 so that MariaDB Server 10.8 or later can be started after --copy-back or --move-back. Thanks to Daniel Black for reporting this. --- extra/mariabackup/backup_copy.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index 05acc1e6765..e8f2e7c7d56 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -1984,8 +1984,10 @@ copy_back() dst_dir, i); unlink(filename); } - } else if (!(ret = copy_or_move_file(ds_tmp, "ib_logfile0", "ib_logfile0", - dst_dir, 1))) { + } + + if (!(ret = copy_or_move_file(ds_tmp, "ib_logfile0", "ib_logfile0", + dst_dir, 1))) { goto cleanup; } ds_destroy(ds_tmp); From 424a7a262072f3cd171f33f4193aed23465059fc Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 6 Oct 2023 18:18:37 +0300 Subject: [PATCH 028/158] Fixed randomly failing test main.order_by_optimizer_innodb The problem was that sometimes InnoDB returned sligtly wrong record count for table, which causes the optimizer to disregard the result from the range optimizer. The end result was that the optimizer choosed a ref access instead of a range access which caused errors in buildbot. Fixed by adding more rows to the table to ensure that table scan is more costly than range scan of the given interval. --- .../main/order_by_optimizer_innodb.result | 17 +++++++---------- mysql-test/main/order_by_optimizer_innodb.test | 16 ++++++---------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/mysql-test/main/order_by_optimizer_innodb.result b/mysql-test/main/order_by_optimizer_innodb.result index 0b62ba997d8..18a62414cab 100644 --- a/mysql-test/main/order_by_optimizer_innodb.result +++ b/mysql-test/main/order_by_optimizer_innodb.result @@ -2,10 +2,6 @@ drop table if exists t0,t1,t2,t3; # # MDEV-6402: Optimizer doesn't choose best execution plan when composite key is used # -create table t0(a int); -insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); -create table t1(a int); -insert into t1 select A.a + B.a* 10 + C.a * 100 from t0 A, t0 B, t0 C; CREATE TABLE t2 ( pk1 int(11) NOT NULL, pk2 int(11) NOT NULL, @@ -17,13 +13,13 @@ UNIQUE KEY ux_pk1_fd5 (pk1,fd5) ) ENGINE=InnoDB; insert into t2 select -round(log(2,t1.a+1)), -t1.a, -t1.a, +round(log(2,seq+1)), +seq, +seq, REPEAT('filler-data-', 10), REPEAT('filler-data-', 10) from -t1; +seq_0_to_1999; select pk1, count(*) from t2 group by pk1; pk1 count(*) 0 1 @@ -36,7 +32,8 @@ pk1 count(*) 7 91 8 181 9 362 -10 276 +10 724 +11 552 # The following should use range(ux_pk1_fd5), two key parts (key_len=5+8=13) EXPLAIN SELECT * FROM t2 USE INDEX(ux_pk1_fd5) WHERE pk1=9 AND fd5 < 500 ORDER BY fd5 DESC LIMIT 10; id select_type table type possible_keys key key_len ref rows Extra @@ -45,7 +42,7 @@ id select_type table type possible_keys key key_len ref rows Extra EXPLAIN SELECT * FROM t2 WHERE pk1=9 AND fd5 < 500 ORDER BY fd5 DESC LIMIT 10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range PRIMARY,ux_pk1_fd5 ux_pk1_fd5 13 NULL 138 Using where -drop table t0,t1, t2; +drop table t2; # # MDEV-6814: Server crashes in calculate_key_len on query with ORDER BY # diff --git a/mysql-test/main/order_by_optimizer_innodb.test b/mysql-test/main/order_by_optimizer_innodb.test index 90430d11549..ef6e9aac450 100644 --- a/mysql-test/main/order_by_optimizer_innodb.test +++ b/mysql-test/main/order_by_optimizer_innodb.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/have_sequence.inc --disable_warnings drop table if exists t0,t1,t2,t3; @@ -7,11 +8,6 @@ drop table if exists t0,t1,t2,t3; --echo # --echo # MDEV-6402: Optimizer doesn't choose best execution plan when composite key is used --echo # -create table t0(a int); -insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); - -create table t1(a int); -insert into t1 select A.a + B.a* 10 + C.a * 100 from t0 A, t0 B, t0 C; CREATE TABLE t2 ( pk1 int(11) NOT NULL, @@ -25,13 +21,13 @@ CREATE TABLE t2 ( insert into t2 select - round(log(2,t1.a+1)), - t1.a, - t1.a, + round(log(2,seq+1)), + seq, + seq, REPEAT('filler-data-', 10), REPEAT('filler-data-', 10) from - t1; + seq_0_to_1999; select pk1, count(*) from t2 group by pk1; @@ -40,7 +36,7 @@ EXPLAIN SELECT * FROM t2 USE INDEX(ux_pk1_fd5) WHERE pk1=9 AND fd5 < 500 ORDER B --echo # This also must use range, not ref. key_len must be 13 EXPLAIN SELECT * FROM t2 WHERE pk1=9 AND fd5 < 500 ORDER BY fd5 DESC LIMIT 10; -drop table t0,t1, t2; +drop table t2; --echo # --echo # MDEV-6814: Server crashes in calculate_key_len on query with ORDER BY From 185591c1c0dfd16bc6f74999a23d5aa5d7cfb12b Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 8 Oct 2023 18:00:51 +0300 Subject: [PATCH 029/158] MDEV-31349 test maria.maria-purge failed on 'aria_log.00000002 not found' The bug was in the test case. The problem was that maria_empty_logs.inc deleted aria log files before the server was properly shutdown. Fixed by waiting for pid file to disappear before starting to delete log files. Other things: - Fixed that translog_purge_at_flush() will not stop deleting files even if one file could not be deleted. --- mysql-test/include/maria_empty_logs.inc | 2 + mysql-test/include/wait_until_no_pidfile.inc | 30 +++++++++++++++ storage/maria/ma_loghandler.c | 40 ++++++++++++-------- 3 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 mysql-test/include/wait_until_no_pidfile.inc diff --git a/mysql-test/include/maria_empty_logs.inc b/mysql-test/include/maria_empty_logs.inc index f1835c0d2c3..bdbe3ff3ac7 100644 --- a/mysql-test/include/maria_empty_logs.inc +++ b/mysql-test/include/maria_empty_logs.inc @@ -11,6 +11,7 @@ connection default; let $default_db=`select database()`; let $MYSQLD_DATADIR= `SELECT @@datadir`; +let $pid_file=`select @@pid_file`; #it will used at end of test for wait_for_status_var.inc primitive #let $status_var= Threads_connected; @@ -23,6 +24,7 @@ wait-maria_empty_logs.inc EOF --source include/mysqladmin_shutdown.inc +--source include/wait_until_no_pidfile.inc --disable_warnings if (!$mel_keep_control_file) diff --git a/mysql-test/include/wait_until_no_pidfile.inc b/mysql-test/include/wait_until_no_pidfile.inc new file mode 100644 index 00000000000..9448400522b --- /dev/null +++ b/mysql-test/include/wait_until_no_pidfile.inc @@ -0,0 +1,30 @@ +# Include this script after a shutdown to wait until the pid file, +# stored in $pid_file, has disappered. + +#--echo $pid_file + +--disable_result_log +--disable_query_log +# Wait one minute +let $counter= 600; +while ($counter) +{ +--error 0,1 +--file_exists $pid_file + if (!$errno) + { + dec $counter; + --real_sleep 0.1 + } + if ($errno) + { + let $counter= 0; + } +} +if (!$errno) +{ + --die Pid file "$pid_file" failed to disappear +} + +--enable_query_log +--enable_result_log diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 0b403fd456d..857bb59d851 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -8427,34 +8427,41 @@ my_bool translog_is_file(uint file_no) static uint32 translog_first_file(TRANSLOG_ADDRESS horizon, int is_protected) { - uint min_file= 0, max_file; + uint min_file= 1, max_file; DBUG_ENTER("translog_first_file"); if (!is_protected) mysql_mutex_lock(&log_descriptor.purger_lock); - if (log_descriptor.min_file_number && - translog_is_file(log_descriptor.min_file_number)) + if (log_descriptor.min_file_number) { - DBUG_PRINT("info", ("cached %lu", - (ulong) log_descriptor.min_file_number)); - if (!is_protected) - mysql_mutex_unlock(&log_descriptor.purger_lock); - DBUG_RETURN(log_descriptor.min_file_number); + min_file= log_descriptor.min_file_number; + if (translog_is_file(log_descriptor.min_file_number)) + { + DBUG_PRINT("info", ("cached %lu", + (ulong) log_descriptor.min_file_number)); + if (!is_protected) + mysql_mutex_unlock(&log_descriptor.purger_lock); + DBUG_RETURN(log_descriptor.min_file_number); + } } max_file= LSN_FILE_NO(horizon); + if (!translog_is_file(max_file)) + { + if (!is_protected) + mysql_mutex_unlock(&log_descriptor.purger_lock); + DBUG_RETURN(max_file); /* For compatibility */ + } /* binary search for last file */ - while (min_file != max_file && min_file != (max_file - 1)) + while (min_file < max_file) { uint test= (min_file + max_file) / 2; DBUG_PRINT("info", ("min_file: %u test: %u max_file: %u", min_file, test, max_file)); - if (test == max_file) - test--; if (translog_is_file(test)) max_file= test; else - min_file= test; + min_file= test+1; } log_descriptor.min_file_number= max_file; if (!is_protected) @@ -8723,9 +8730,9 @@ my_bool translog_purge(TRANSLOG_ADDRESS low) /** @brief Purges files by stored min need file in case of - "ondemend" purge type + "one demand" purge type - @note This function do real work only if it is "ondemend" purge type + @note This function do real work only if it is "one demand" purge type and translog_purge() was called at least once and last time without errors @@ -8764,13 +8771,14 @@ my_bool translog_purge_at_flush() min_file= translog_first_file(translog_get_horizon(), 1); DBUG_ASSERT(min_file != 0); /* log is already started */ - for(i= min_file; i < log_descriptor.min_need_file && rc == 0; i++) + for(i= min_file; i < log_descriptor.min_need_file ; i++) { char path[FN_REFLEN], *file_name; DBUG_PRINT("info", ("purge file %lu\n", (ulong) i)); file_name= translog_filename_by_fileno(i, path); - rc= MY_TEST(mysql_file_delete(key_file_translog, + rc|= MY_TEST(mysql_file_delete(key_file_translog, file_name, MYF(MY_WME))); + DBUG_ASSERT(rc == 0); } mysql_mutex_unlock(&log_descriptor.purger_lock); From 9d19b6526917c94ca03ef1b4c57152882b192cfe Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 8 Oct 2023 18:04:15 +0300 Subject: [PATCH 030/158] MDEV-22243 type_test.type_test_double fails with 'NUMERIC_SCALE NULL' There where several reasons why the test failed: - Constructors for Field_double and Field_float changed an argument to the constructor instead of a the correct class variable. - gcc 7.5.0 produced wrong code when inlining Field_double constructor into Field_test_double constructor. Fixed by changing the correct class variable and make the constructors not inline to go around the gcc bug. --- .../type_test/type_test_double.result | 2 +- sql/field.cc | 54 +++++++++++++++++++ sql/field.h | 43 ++------------- 3 files changed, 60 insertions(+), 39 deletions(-) diff --git a/plugin/type_test/mysql-test/type_test/type_test_double.result b/plugin/type_test/mysql-test/type_test/type_test_double.result index 6241ff95b8a..edcfdc0eff8 100644 --- a/plugin/type_test/mysql-test/type_test/type_test_double.result +++ b/plugin/type_test/mysql-test/type_test/type_test_double.result @@ -290,7 +290,7 @@ DATA_TYPE test_double CHARACTER_MAXIMUM_LENGTH NULL CHARACTER_OCTET_LENGTH NULL NUMERIC_PRECISION 22 -NUMERIC_SCALE 31 +NUMERIC_SCALE NULL DATETIME_PRECISION NULL CHARACTER_SET_NAME NULL COLLATION_NAME NULL diff --git a/sql/field.cc b/sql/field.cc index 6b4466db87e..f40a2b4cc28 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4645,6 +4645,28 @@ bool Field_longlong::is_max() single precision float ****************************************************************************/ +Field_float::Field_float(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + uchar null_bit_arg, + enum utype unireg_check_arg, + const LEX_CSTRING *field_name_arg, + uint8 dec_arg,bool zero_arg,bool unsigned_arg) + :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, + unireg_check_arg, field_name_arg, + (dec_arg >= FLOATING_POINT_DECIMALS ? NOT_FIXED_DEC : dec_arg), + zero_arg, unsigned_arg) +{ +} + +Field_float::Field_float(uint32 len_arg, bool maybe_null_arg, + const LEX_CSTRING *field_name_arg, uint8 dec_arg) + :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, + NONE, field_name_arg, + (dec_arg >= FLOATING_POINT_DECIMALS ? NOT_FIXED_DEC : dec_arg), + 0, 0) +{ +} + + int Field_float::store(const char *from,size_t len,CHARSET_INFO *cs) { int error; @@ -4793,6 +4815,38 @@ Binlog_type_info Field_float::binlog_type_info() const double precision floating point numbers ****************************************************************************/ +Field_double::Field_double(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + uchar null_bit_arg, + enum utype unireg_check_arg, + const LEX_CSTRING *field_name_arg, + uint8 dec_arg,bool zero_arg,bool unsigned_arg) + :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, + unireg_check_arg, field_name_arg, + (dec_arg >= FLOATING_POINT_DECIMALS ? NOT_FIXED_DEC : dec_arg), + zero_arg, unsigned_arg) +{ +} + +Field_double::Field_double(uint32 len_arg, bool maybe_null_arg, + const LEX_CSTRING *field_name_arg, uint8 dec_arg) + :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, + NONE, field_name_arg, + (dec_arg >= FLOATING_POINT_DECIMALS ? NOT_FIXED_DEC : dec_arg), + 0, 0) +{ +} + +Field_double::Field_double(uint32 len_arg, bool maybe_null_arg, + const LEX_CSTRING *field_name_arg, + uint8 dec_arg, bool not_fixed_arg) + :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, + NONE, field_name_arg, + (dec_arg >= FLOATING_POINT_DECIMALS ? NOT_FIXED_DEC : dec_arg), + 0, 0) +{ + not_fixed= not_fixed_arg; +} + int Field_double::store(const char *from,size_t len,CHARSET_INFO *cs) { int error; diff --git a/sql/field.h b/sql/field.h index 804394c58a6..057bd8453c5 100644 --- a/sql/field.h +++ b/sql/field.h @@ -2842,22 +2842,9 @@ public: Field_float(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, - uint8 dec_arg,bool zero_arg,bool unsigned_arg) - :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, - dec_arg, zero_arg, unsigned_arg) - { - if (dec_arg >= FLOATING_POINT_DECIMALS) - dec_arg= NOT_FIXED_DEC; - } + uint8 dec_arg,bool zero_arg,bool unsigned_arg); Field_float(uint32 len_arg, bool maybe_null_arg, - const LEX_CSTRING *field_name_arg, uint8 dec_arg) - :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0, - NONE, field_name_arg, dec_arg, 0, 0) - { - if (dec_arg >= FLOATING_POINT_DECIMALS) - dec_arg= NOT_FIXED_DEC; - } + const LEX_CSTRING *field_name_arg, uint8 dec_arg); const Type_handler *type_handler() const override { return &type_handler_float; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_FLOAT; } @@ -2890,32 +2877,12 @@ public: Field_double(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg, - uint8 dec_arg,bool zero_arg,bool unsigned_arg) - :Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, - dec_arg, zero_arg, unsigned_arg) - { - if (dec_arg >= FLOATING_POINT_DECIMALS) - dec_arg= NOT_FIXED_DEC; - } + uint8 dec_arg,bool zero_arg,bool unsigned_arg); Field_double(uint32 len_arg, bool maybe_null_arg, - const LEX_CSTRING *field_name_arg, uint8 dec_arg) - :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, - NONE, field_name_arg, dec_arg, 0, 0) - { - if (dec_arg >= FLOATING_POINT_DECIMALS) - dec_arg= NOT_FIXED_DEC; - } + const LEX_CSTRING *field_name_arg, uint8 dec_arg); Field_double(uint32 len_arg, bool maybe_null_arg, const LEX_CSTRING *field_name_arg, - uint8 dec_arg, bool not_fixed_arg) - :Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0, - NONE, field_name_arg, dec_arg, 0, 0) - { - not_fixed= not_fixed_arg; - if (dec_arg >= FLOATING_POINT_DECIMALS) - dec_arg= NOT_FIXED_DEC; - } + uint8 dec_arg, bool not_fixed_arg); void init_for_tmp_table(Field *org_field, TABLE *new_table) override { Field::init_for_tmp_table(org_field, new_table); From 1dd6d9a0bfb2dd99a9cfcad39e7ec0a77b393780 Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 8 Oct 2023 20:17:52 +0300 Subject: [PATCH 031/158] Fixed compiler warnings in connect/odbconn.cpp --- storage/connect/odbconn.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index 18bb77a9d00..b022319b49a 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -125,18 +125,21 @@ int TranslateSQLType(int stp, int prec, int& len, char& v, bool& w) switch (stp) { case SQL_WVARCHAR: // (-9) w = true; + // Fall through case SQL_VARCHAR: // 12 v = 'V'; type = TYPE_STRING; break; case SQL_WCHAR: // (-8) w = true; + // Fall through case SQL_CHAR: // 1 type = TYPE_STRING; break; case SQL_WLONGVARCHAR: // (-10) w = true; - case SQL_LONGVARCHAR: // (-1) + // Fall through + case SQL_LONGVARCHAR: // (-1) if (GetTypeConv() == TPC_YES || GetTypeConv() == TPC_FORCE) { v = 'V'; type = TYPE_STRING; @@ -2355,6 +2358,7 @@ int ODBConn::GetCatInfo(CATPARM *cap) break; case CAT_SPC: ThrowDBX("SQLSpecialColumns not available yet"); + break; default: ThrowDBX("Invalid SQL function id"); } // endswitch infotype From b04af64882f233e3937f729aac321de504db3f63 Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 8 Oct 2023 22:36:16 +0300 Subject: [PATCH 032/158] Fixed that log_slow.test works with view_protocol Part of the test did not work with view_protocol as the query written to the slow_log table is changed because of view_protocol. --- mysql-test/main/log_slow.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/main/log_slow.test b/mysql-test/main/log_slow.test index 6120ac77756..a5f6ac9baba 100644 --- a/mysql-test/main/log_slow.test +++ b/mysql-test/main/log_slow.test @@ -141,6 +141,7 @@ CREATE TABLE `tab_MDEV_30820` ( ); --disable_ps2_protocol +--disable_view_protocol --delimiter // CREATE FUNCTION `get_zero`() RETURNS int(11) @@ -182,6 +183,7 @@ drop table tab_MDEV_30820, tab2; drop function get_zero; --enable_ps2_protocol +--enable_view_protocol --echo # --echo # End of 10.4 tests From 0c7af6a2a19343cb9d4fedbd7165b8f73bc4cf96 Mon Sep 17 00:00:00 2001 From: Lena Startseva Date: Mon, 28 Aug 2023 09:58:28 +0700 Subject: [PATCH 033/158] MDEV-32023 main.secure_file_priv_win fails with 2nd execution PS protocol Fixed tests: main.secure_file_priv_win - disabled ps2-protocol for queries like "SELECT ... INTO OUTFILE ..." --- mysql-test/main/secure_file_priv_win.test | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql-test/main/secure_file_priv_win.test b/mysql-test/main/secure_file_priv_win.test index a12510974ce..60fc8e29b6e 100644 --- a/mysql-test/main/secure_file_priv_win.test +++ b/mysql-test/main/secure_file_priv_win.test @@ -12,6 +12,8 @@ INSERT INTO t1 values ('a'); LET $MYSQL_TMP_DIR_UCASE= `SELECT upper('$MYSQL_TMP_DIR')`; LET $MYSQL_TMP_DIR_LCASE= `SELECT lower('$MYSQL_TMP_DIR')`; +--disable_ps2_protocol + #create the file --replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR/B11764517.tmp'; @@ -77,3 +79,4 @@ eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR_LCASE/B11764517-5.tmp'; --error 0,1 --remove_file $MYSQL_TMP_DIR/B11764517-5.tmp; DROP TABLE t1; +--enable_ps2_protocol From cbe61bf87f1539ced0a93af6d7e1b1a8c4e185f0 Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Fri, 7 Jul 2023 14:42:31 +0700 Subject: [PATCH 034/158] MDEV-30664 mysqldump output is truncated on Windows Flush stdout on finalizing of mysqldump/mysqlbinlog output to avoid truncation. The same patch has been applied to the mysqltest.cc code with commit 34ff714b0d5456901e979e280399579d3ab3338c Author: Magnus Svensson Date: Fri Nov 14 11:06:56 2008 +0100 WL#4189 Make mysqltest flush log file at close if logfile is stdout but not to mysqldump.c/mysqlbinlog.cc --- client/mysqlbinlog.cc | 9 +++++++-- client/mysqldump.c | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 8d03e0680b8..8ef11da85d4 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -3224,8 +3224,13 @@ int main(int argc, char** argv) if (tmpdir.list) free_tmpdir(&tmpdir); - if (result_file && result_file != stdout) - my_fclose(result_file, MYF(0)); + if (result_file) + { + if (result_file != stdout) + my_fclose(result_file, MYF(0)); + else + fflush(result_file); + } cleanup(); /* We cannot free DBUG, it is used in global destructors after exit(). */ my_end(my_end_arg | MY_DONT_FREE_DBUG); diff --git a/client/mysqldump.c b/client/mysqldump.c index d0797c2721b..2f1665b4137 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1794,8 +1794,13 @@ static FILE* open_sql_file_for_table(const char* table, int flags) static void free_resources() { - if (md_result_file && md_result_file != stdout) - my_fclose(md_result_file, MYF(0)); + if (md_result_file) + { + if (md_result_file != stdout) + my_fclose(md_result_file, MYF(0)); + else + fflush(md_result_file); + } if (get_table_name_result) mysql_free_result(get_table_name_result); if (routine_res) From 194236367cad965767763722ddb89c5ffd0bb720 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 9 Oct 2023 22:57:33 +0200 Subject: [PATCH 035/158] MDEV-32387 Windows - mtr output on is messed up with large MTR_PARALLEL. Windows C runtime does not implement line buffering mode for stdio. This sometimes makes output from different tests interleaved in MTR MTR relies on this buffering (lines won't output until "\n") to correctly workin parallel scenarios. Implement do-it-yourself line buffering on Windows, to workaround. --- mysql-test/lib/mtr_report.pm | 41 +++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index 7d944ade71a..97c48c19112 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -76,6 +76,30 @@ if (-t STDOUT) { } } +# On Windows, stdio does not support line buffering +# This can make MTR output from multiple forked processes interleaved, messed up. +# Below is DYI stdout line buffering. +my $out_line=""; + +# Flush buffered line +sub flush_out { + print $out_line; + $out_line = ""; +} + +# Print to stdout +sub print_out { + if(IS_WIN32PERL) { + $out_line .= $_[0]; + # Flush buffered output on new lines. + if (rindex($_[0], "\n") != -1) { + flush_out(); + } + } else { + print($_[0]); + } +} + sub titlebar_stat($) { sub time_format($) { @@ -116,10 +140,10 @@ sub _mtr_report_test_name ($) { return unless defined $verbose; - print _name(). _timestamp(); - printf "%-40s ", $tname; + print_out _name(). _timestamp(); + print_out (sprintf "%-40s ", $tname); my $worker = $tinfo->{worker}; - print "w$worker " if defined $worker; + print_out "w$worker " if defined $worker; return $tname; } @@ -661,14 +685,14 @@ sub mtr_report (@) { { my @s = split /\[ (\S+) \]/, _name() . "@_\n"; if (@s > 1) { - print $s[0]; + print_out $s[0]; &$set_color($s[1]); - print "[ $s[1] ]"; + print_out "[ $s[1] ]"; &$set_color('reset'); - print $s[2]; + print_out $s[2]; titlebar_stat($s[1]) if $set_titlebar; } else { - print $s[0]; + print_out $s[0]; } } } @@ -676,6 +700,7 @@ sub mtr_report (@) { # Print warning to screen sub mtr_warning (@) { + flush_out(); print STDERR _name(). _timestamp(). "mysql-test-run: WARNING: ". join(" ", @_). "\n"; } @@ -683,7 +708,7 @@ sub mtr_warning (@) { # Print error to screen and then exit sub mtr_error (@) { - IO::Handle::flush(\*STDOUT) if IS_WINDOWS; + flush_out(); print STDERR _name(). _timestamp(). "mysql-test-run: *** ERROR: ". join(" ", @_). "\n"; if (IS_WINDOWS) From f197f9a5273054f6c68b20fb429a73b353ff2cf2 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 9 Oct 2023 22:57:33 +0200 Subject: [PATCH 036/158] MDEV-32387 Windows - mtr output on is messed up with large MTR_PARALLEL. Windows C runtime does not implement line buffering mode for stdio. This sometimes makes output from different tests interleaved in MTR MTR relies on this buffering (lines won't output until "\n") to correctly work in parallel scenarios. Implement do-it-yourself line buffering on Windows, to workaround. --- mysql-test/lib/mtr_report.pm | 41 +++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index 7d944ade71a..97c48c19112 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -76,6 +76,30 @@ if (-t STDOUT) { } } +# On Windows, stdio does not support line buffering +# This can make MTR output from multiple forked processes interleaved, messed up. +# Below is DYI stdout line buffering. +my $out_line=""; + +# Flush buffered line +sub flush_out { + print $out_line; + $out_line = ""; +} + +# Print to stdout +sub print_out { + if(IS_WIN32PERL) { + $out_line .= $_[0]; + # Flush buffered output on new lines. + if (rindex($_[0], "\n") != -1) { + flush_out(); + } + } else { + print($_[0]); + } +} + sub titlebar_stat($) { sub time_format($) { @@ -116,10 +140,10 @@ sub _mtr_report_test_name ($) { return unless defined $verbose; - print _name(). _timestamp(); - printf "%-40s ", $tname; + print_out _name(). _timestamp(); + print_out (sprintf "%-40s ", $tname); my $worker = $tinfo->{worker}; - print "w$worker " if defined $worker; + print_out "w$worker " if defined $worker; return $tname; } @@ -661,14 +685,14 @@ sub mtr_report (@) { { my @s = split /\[ (\S+) \]/, _name() . "@_\n"; if (@s > 1) { - print $s[0]; + print_out $s[0]; &$set_color($s[1]); - print "[ $s[1] ]"; + print_out "[ $s[1] ]"; &$set_color('reset'); - print $s[2]; + print_out $s[2]; titlebar_stat($s[1]) if $set_titlebar; } else { - print $s[0]; + print_out $s[0]; } } } @@ -676,6 +700,7 @@ sub mtr_report (@) { # Print warning to screen sub mtr_warning (@) { + flush_out(); print STDERR _name(). _timestamp(). "mysql-test-run: WARNING: ". join(" ", @_). "\n"; } @@ -683,7 +708,7 @@ sub mtr_warning (@) { # Print error to screen and then exit sub mtr_error (@) { - IO::Handle::flush(\*STDOUT) if IS_WINDOWS; + flush_out(); print STDERR _name(). _timestamp(). "mysql-test-run: *** ERROR: ". join(" ", @_). "\n"; if (IS_WINDOWS) From 2556fe1ab13af114e217f0580d75b114903fe8de Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 11 Oct 2023 16:29:51 +1100 Subject: [PATCH 037/158] MDEV-31996 Create connection on demand in spider_db_delete_all_rows When spider_db_delete_all_rows() is called, the supplied spider->conns may have already been freed. The existing mechanism has spider_trx own the connections in trx_conn_hash and it may free a conn during the cleanup after a query. When running a delete query and if the table is in the table cache, ha_spider::open() would not be called which would recreate the conn. So we recreate the conn when necessary during delete by calling spider_check_trx_and_get_conn(). We also reduce code duplication as delete_all_rows() and truncate() has almost identical code, and there's no need to assign wide_handler->sql_command in these functions because it has already been correctly assigned. --- storage/spider/ha_spider.cc | 32 +----------- .../spider/bugfix/r/mdev_31996.result | 47 +++++++++++++++++ .../spider/bugfix/t/mdev_31996.test | 50 +++++++++++++++++++ 3 files changed, 98 insertions(+), 31 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 8b4cb85730c..ac586479d8c 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -11223,41 +11223,11 @@ int ha_spider::pre_direct_delete_rows() int ha_spider::delete_all_rows() { - int error_num, roop_count; THD *thd = ha_thd(); - backup_error_status(); DBUG_ENTER("ha_spider::delete_all_rows"); - DBUG_PRINT("info",("spider this=%p", this)); if (spider_param_delete_all_rows_type(thd, share->delete_all_rows_type)) DBUG_RETURN(HA_ERR_WRONG_COMMAND); - if (spider_param_read_only_mode(thd, share->read_only_mode)) - { - my_printf_error(ER_SPIDER_READ_ONLY_NUM, ER_SPIDER_READ_ONLY_STR, MYF(0), - table_share->db.str, table_share->table_name.str); - DBUG_RETURN(ER_SPIDER_READ_ONLY_NUM); - } -#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS - do_direct_update = FALSE; -#endif - sql_kinds = SPIDER_SQL_KIND_SQL; - for (roop_count = 0; roop_count < (int) share->link_count; roop_count++) - sql_kind[roop_count] = SPIDER_SQL_KIND_SQL; - if ((error_num = spider_db_delete_all_rows(this))) - DBUG_RETURN(check_error_mode(error_num)); - if (sql_command == SQLCOM_TRUNCATE && table->found_next_number_field) - { - DBUG_PRINT("info",("spider reset auto increment")); - pthread_mutex_lock(&share->lgtm_tblhnd_share->auto_increment_mutex); - share->lgtm_tblhnd_share->auto_increment_lclval = 1; - share->lgtm_tblhnd_share->auto_increment_init = FALSE; - share->lgtm_tblhnd_share->auto_increment_value = 1; - DBUG_PRINT("info",("spider init auto_increment_lclval=%llu", - share->lgtm_tblhnd_share->auto_increment_lclval)); - DBUG_PRINT("info",("spider auto_increment_value=%llu", - share->lgtm_tblhnd_share->auto_increment_value)); - pthread_mutex_unlock(&share->lgtm_tblhnd_share->auto_increment_mutex); - } - DBUG_RETURN(0); + DBUG_RETURN(truncate()); } int ha_spider::truncate() diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result new file mode 100644 index 00000000000..04d7e884676 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result @@ -0,0 +1,47 @@ +for master_1 +for child2 +for child3 +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +set session spider_delete_all_rows_type=0; +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2", delete_all_rows_type "0"'; +delete from t1; +drop table t1, t2; +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2", delete_all_rows_type "0"'; +insert ignore into t1 values (42), (378); +select * from t1; +c +42 +378 +delete from t1; +select * from t1; +c +drop table t1, t2; +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2", delete_all_rows_type "0"'; +truncate t1; +drop table t1, t2; +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2", delete_all_rows_type "0"'; +insert ignore into t1 values (42), (378); +select * from t1; +c +42 +378 +truncate t1; +select * from t1; +c +drop table t1, t2; +drop server srv; +for master_1 +for child2 +for child3 +# +# end of test tmp +# diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test new file mode 100644 index 00000000000..3e823790c82 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test @@ -0,0 +1,50 @@ +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); + +set session spider_delete_all_rows_type=0; + +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2", delete_all_rows_type "0"'; +delete from t1; +drop table t1, t2; + +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2", delete_all_rows_type "0"'; +insert ignore into t1 values (42), (378); +select * from t1; +delete from t1; +select * from t1; +drop table t1, t2; + +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2", delete_all_rows_type "0"'; +truncate t1; +drop table t1, t2; + +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2", delete_all_rows_type "0"'; +insert ignore into t1 values (42), (378); +select * from t1; +truncate t1; +select * from t1; +drop table t1, t2; + +drop server srv; +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log +--echo # +--echo # end of test tmp +--echo # From 69089c715c1f3c4ffe23895054ce9634b89ecf76 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 8 Oct 2023 12:50:14 +0200 Subject: [PATCH 038/158] fix groonga to compile with -Werror=enum-int-mismatch gcc 13.2.1 --- storage/mroonga/vendor/groonga/include/groonga/groonga.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/mroonga/vendor/groonga/include/groonga/groonga.h b/storage/mroonga/vendor/groonga/include/groonga/groonga.h index b08403676c0..c5bbfe09f6d 100644 --- a/storage/mroonga/vendor/groonga/include/groonga/groonga.h +++ b/storage/mroonga/vendor/groonga/include/groonga/groonga.h @@ -1640,7 +1640,7 @@ GRN_API int grn_charlen(grn_ctx *ctx, const char *str, const char *end); GRN_API grn_rc grn_ctx_push(grn_ctx *ctx, grn_obj *obj); GRN_API grn_obj *grn_ctx_pop(grn_ctx *ctx); -GRN_API int grn_obj_columns(grn_ctx *ctx, grn_obj *table, +GRN_API grn_rc grn_obj_columns(grn_ctx *ctx, grn_obj *table, const char *str, unsigned int str_size, grn_obj *res); GRN_API grn_rc grn_load(grn_ctx *ctx, grn_content_type input_type, From 3e2b1295bd58e5d2bfff0319bb838c56415c592b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 11 Oct 2023 12:01:54 +0200 Subject: [PATCH 039/158] MDEV-30658 fix failing test followup for 96ae37abc51 --- .../mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result b/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result index 769c600cdaf..531f72e8eb0 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result @@ -32,7 +32,7 @@ lock_rec_locks lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabl lock_table_lock_created lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of table locks created lock_table_lock_removed lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of table locks removed from the lock queue lock_table_locks lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Current number of table locks on tables -lock_row_lock_current_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of row locks currently being waited for (innodb_row_lock_current_waits) +lock_row_lock_current_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled value Number of row locks currently being waited for (innodb_row_lock_current_waits) lock_row_lock_time lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Time spent in acquiring row locks, in milliseconds (innodb_row_lock_time) lock_row_lock_time_max lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled value The maximum time to acquire a row lock, in milliseconds (innodb_row_lock_time_max) lock_row_lock_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of times a row lock had to be waited for (innodb_row_lock_waits) From 702dc2ec78de8a4b209bd6b22e16dcc2893f3992 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 11 Oct 2023 12:03:21 +0200 Subject: [PATCH 040/158] MDEV-32024 disable failing test --- mysql-test/suite/galera/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index b70ab461aaa..348f8948bbd 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -16,3 +16,4 @@ galera_sst_encrypted : MDEV-29876 Galera test failure on galera_sst_encrypted galera_var_node_address : MDEV-20485 Galera test failure MDEV-26575 : MDEV-29878 Galera test failure on MDEV-26575 galera_bf_abort_group_commit : MDEV-30855 PR to remove the test exists +galera.galera_sequences : MDEV-32024 From 3f1a256234138aa07e755f84df1727b9d73bee1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 11 Oct 2023 15:59:56 +0300 Subject: [PATCH 041/158] MDEV-31890: Remove COMPILE_FLAGS The cmake configuration step is single-threaded and already consuming too much time. We should not make it worse by adding invocations like MY_CHECK_CXX_COMPILER_FLAG(). Let us prefer something that works on any supported version of GCC (4.8.5 or later) or clang, as well as recent versions of the Intel C compiler. This replaces commit 1fde785315ec6d575d0cd5c3e33d53a5d83e3e00 --- storage/innobase/CMakeLists.txt | 6 ------ storage/innobase/fts/fts0pars.cc | 10 +++++----- storage/innobase/fts/fts0pars.y | 10 +++++----- storage/innobase/pars/pars0grm.cc | 10 +++++----- storage/innobase/pars/pars0grm.y | 10 +++++----- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 514c14557c2..f63eddd38ac 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -359,12 +359,6 @@ IF(MSVC) TARGET_COMPILE_OPTIONS(innobase PRIVATE "/wd4065") ENDIF() -MY_CHECK_CXX_COMPILER_FLAG(-Wno-unused-but-set-variable) -IF(have_CXX__Wno_unused_but_set_variable) - ADD_COMPILE_FLAGS(pars/pars0grm.cc fts/fts0pars.cc - COMPILE_FLAGS "-Wno-unused-but-set-variable") -ENDIF() - IF(NOT (PLUGIN_INNOBASE STREQUAL DYNAMIC)) ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/extra/mariabackup ${CMAKE_BINARY_DIR}/extra/mariabackup) ENDIF() diff --git a/storage/innobase/fts/fts0pars.cc b/storage/innobase/fts/fts0pars.cc index 56cc8d6052c..cb51784a7f1 100644 --- a/storage/innobase/fts/fts0pars.cc +++ b/storage/innobase/fts/fts0pars.cc @@ -83,15 +83,15 @@ #include "fts0tlex.h" #include "fts0pars.h" #include - extern int fts_lexer(YYSTYPE*, fts_lexer_t*); extern int fts_blexer(YYSTYPE*, yyscan_t); extern int fts_tlexer(YYSTYPE*, yyscan_t); - - - +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wpragmas" +# pragma GCC diagnostic ignored "-Wunknown-warning-option" +# pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#endif extern int ftserror(const char* p); - /* Required for reentrant parser */ #define ftslex fts_lexer diff --git a/storage/innobase/fts/fts0pars.y b/storage/innobase/fts/fts0pars.y index deebc79e4c4..903c72800f9 100644 --- a/storage/innobase/fts/fts0pars.y +++ b/storage/innobase/fts/fts0pars.y @@ -31,15 +31,15 @@ this program; if not, write to the Free Software Foundation, Inc., #include "fts0tlex.h" #include "fts0pars.h" #include - extern int fts_lexer(YYSTYPE*, fts_lexer_t*); extern int fts_blexer(YYSTYPE*, yyscan_t); extern int fts_tlexer(YYSTYPE*, yyscan_t); - - - +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wpragmas" +# pragma GCC diagnostic ignored "-Wunknown-warning-option" +# pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#endif extern int ftserror(const char* p); - /* Required for reentrant parser */ #define ftslex fts_lexer diff --git a/storage/innobase/pars/pars0grm.cc b/storage/innobase/pars/pars0grm.cc index 1e10a61f5ad..1eacc32c3de 100644 --- a/storage/innobase/pars/pars0grm.cc +++ b/storage/innobase/pars/pars0grm.cc @@ -78,13 +78,13 @@ que_node_t */ #include "que0types.h" #include "que0que.h" #include "row0sel.h" - -#if defined __GNUC__ && (!defined __clang_major__ || __clang_major__ > 11) -#pragma GCC diagnostic ignored "-Wfree-nonheap-object" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wpragmas" +# pragma GCC diagnostic ignored "-Wunknown-warning-option" +# pragma GCC diagnostic ignored "-Wfree-nonheap-object" +# pragma GCC diagnostic ignored "-Wunused-but-set-variable" #endif - #define YYSTYPE que_node_t* - /* #define __STDC__ */ int yylex(void); diff --git a/storage/innobase/pars/pars0grm.y b/storage/innobase/pars/pars0grm.y index ed2b9bc09b0..1d31d2ffff9 100644 --- a/storage/innobase/pars/pars0grm.y +++ b/storage/innobase/pars/pars0grm.y @@ -37,13 +37,13 @@ que_node_t */ #include "que0types.h" #include "que0que.h" #include "row0sel.h" - -#if defined __GNUC__ && (!defined __clang_major__ || __clang_major__ > 11) -#pragma GCC diagnostic ignored "-Wfree-nonheap-object" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wpragmas" +# pragma GCC diagnostic ignored "-Wunknown-warning-option" +# pragma GCC diagnostic ignored "-Wfree-nonheap-object" +# pragma GCC diagnostic ignored "-Wunused-but-set-variable" #endif - #define YYSTYPE que_node_t* - /* #define __STDC__ */ int yylex(void); From 6400b199acdaabf50b99cbd5ae70caac783f7e15 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 27 Sep 2023 10:54:30 +0400 Subject: [PATCH 042/158] MDEV-32249 strings/ctype-ucs2.c:2336: my_vsnprintf_utf32: Assertion `(n % 4) == 0' failed in my_vsnprintf_utf32 on INSERT The crash inside my_vsnprintf_utf32() happened correctly, because the caller methods: Field_string::sql_rpl_type() Field_varstring::sql_rpl_type() mis-used the charset library and sent pure ASCII data to the virtual function snprintf() of a utf32 CHARSET_INFO. It was wrong to use Field::charset() in sql_rpl_type(). We're printing the metadata (the data type) here, not the column data. The string contraining the data type of a CHAR/VARCHAR column is a pure ASCII string. Fixing to use res->charset() to print, like all virtual implementations of sql_type() do. Review was done by Andrei Elkin. Thanks to Andrei for proposing MTR test improvents. --- mysql-test/suite/rpl/r/rpl_row_utf32.result | 58 ++++++++++++++++++ mysql-test/suite/rpl/t/rpl_row_utf32.test | 68 +++++++++++++++++++++ sql/field.cc | 6 +- 3 files changed, 130 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_row_utf32.result b/mysql-test/suite/rpl/r/rpl_row_utf32.result index 6d177b7cda0..d167b0c747f 100644 --- a/mysql-test/suite/rpl/r/rpl_row_utf32.result +++ b/mysql-test/suite/rpl/r/rpl_row_utf32.result @@ -19,6 +19,64 @@ connection master; INSERT INTO t1(c1) VALUES ('insert into t1'); DROP TABLE t1; connection slave; +# +# MDEV-32249 strings/ctype-ucs2.c:2336: my_vsnprintf_utf32: Assertion `(n +# +# +# Testing with VARCHAR +# +connection slave; +include/stop_slave.inc +SET GLOBAL SLAVE_TYPE_CONVERSIONS= ''; +include/start_slave.inc +connection master; +CREATE TABLE t1 (a INT); +connection slave; +ALTER TABLE t1 MODIFY a VARCHAR(1) CHARACTER SET utf32; +connection master; +INSERT INTO t1 VALUES (1); +connection slave; +include/wait_for_slave_sql_error.inc [errno=1677] +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(1) CHARACTER SET utf32 COLLATE utf32_general_ci DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT * FROM t1 ORDER BY a; +a +SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; +START SLAVE; +connection master; +DROP TABLE t1; +connection slave; +# +# Testing with CHAR +# +connection slave; +include/stop_slave.inc +SET GLOBAL SLAVE_TYPE_CONVERSIONS= ''; +include/start_slave.inc +connection master; +CREATE TABLE t1 (a INT); +connection slave; +ALTER TABLE t1 MODIFY a CHAR(1) CHARACTER SET utf32; +connection master; +INSERT INTO t1 VALUES (1); +connection slave; +include/wait_for_slave_sql_error.inc [errno=1677] +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(1) CHARACTER SET utf32 COLLATE utf32_general_ci DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT * FROM t1 ORDER BY a; +a +SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; +START SLAVE; +connection master; +DROP TABLE t1; +connection slave; +connection slave; SET GLOBAL SLAVE_TYPE_CONVERSIONS= @saved_slave_type_conversions; include/stop_slave.inc include/start_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_utf32.test b/mysql-test/suite/rpl/t/rpl_row_utf32.test index c82cd4e5c2f..546cf07adfd 100644 --- a/mysql-test/suite/rpl/t/rpl_row_utf32.test +++ b/mysql-test/suite/rpl/t/rpl_row_utf32.test @@ -34,10 +34,78 @@ DROP TABLE t1; --sync_slave_with_master +--echo # +--echo # MDEV-32249 strings/ctype-ucs2.c:2336: my_vsnprintf_utf32: Assertion `(n +--echo # + +--echo # +--echo # Testing with VARCHAR +--echo # + +-- connection slave +-- source include/stop_slave.inc +SET GLOBAL SLAVE_TYPE_CONVERSIONS= ''; +-- source include/start_slave.inc + +--connection master +CREATE TABLE t1 (a INT); + +--sync_slave_with_master +ALTER TABLE t1 MODIFY a VARCHAR(1) CHARACTER SET utf32; + +--connection master +INSERT INTO t1 VALUES (1); + +--connection slave +# ER_SLAVE_CONVERSION_FAILED +--let $slave_sql_errno= 1677 +--source include/wait_for_slave_sql_error.inc +SHOW CREATE TABLE t1; +SELECT * FROM t1 ORDER BY a; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; +START SLAVE; + +--connection master +DROP TABLE t1; +--sync_slave_with_master + +--echo # +--echo # Testing with CHAR +--echo # + +-- connection slave +-- source include/stop_slave.inc +SET GLOBAL SLAVE_TYPE_CONVERSIONS= ''; +-- source include/start_slave.inc + +--connection master +CREATE TABLE t1 (a INT); + +--sync_slave_with_master +ALTER TABLE t1 MODIFY a CHAR(1) CHARACTER SET utf32; + +--connection master +INSERT INTO t1 VALUES (1); + +--connection slave +# ER_SLAVE_CONVERSION_FAILED +--let $slave_sql_errno= 1677 +--source include/wait_for_slave_sql_error.inc +SHOW CREATE TABLE t1; +SELECT * FROM t1 ORDER BY a; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; +START SLAVE; + +--connection master +DROP TABLE t1; +--sync_slave_with_master + + # assertion: the slave woul hit an/several assertions: # before and during slave conversion procedure # Now that is fixed, it wont. +-- connection slave SET GLOBAL SLAVE_TYPE_CONVERSIONS= @saved_slave_type_conversions; -- source include/stop_slave.inc -- source include/start_slave.inc diff --git a/sql/field.cc b/sql/field.cc index 3e30fbadccc..e37b4801f6b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7487,9 +7487,10 @@ void Field_string::sql_type(String &res) const */ void Field_string::sql_rpl_type(String *res) const { - CHARSET_INFO *cs=charset(); if (Field_string::has_charset()) { + CHARSET_INFO *cs= res->charset(); + DBUG_ASSERT(cs->mbminlen == 1); size_t length= cs->cset->snprintf(cs, (char*) res->ptr(), res->alloced_length(), "char(%u octets) character set %s", @@ -7978,9 +7979,10 @@ void Field_varstring::sql_type(String &res) const */ void Field_varstring::sql_rpl_type(String *res) const { - CHARSET_INFO *cs=charset(); if (Field_varstring::has_charset()) { + CHARSET_INFO *cs= res->charset(); + DBUG_ASSERT(cs->mbminlen == 1); size_t length= cs->cset->snprintf(cs, (char*) res->ptr(), res->alloced_length(), "varchar(%u octets) character set %s", From f9d471e2d5dc752917262a467ce83d080a5c6c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 12 Oct 2023 09:48:54 +0300 Subject: [PATCH 043/158] Cleanup: Remove innobase_init_vc_templ() This fixes up a merge of commit 4fb8f7d07a23b1ac1249dd1f60195ff946450c79 with respect to commit ea37b144094a0c2ebfc6774047fd473c1b2a8658. --- storage/innobase/handler/ha_innodb.cc | 24 ------------------------ storage/innobase/include/row0mysql.h | 5 ----- 2 files changed, 29 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 30a24107a21..291568c6e2a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -20364,30 +20364,6 @@ static TABLE* innodb_find_table_for_vc(THD* thd, dict_table_t* table) return mysql_table; } -/** Only used by the purge thread -@param[in,out] table table whose virtual column template to be built */ -TABLE* innobase_init_vc_templ(dict_table_t* table) -{ - DBUG_ENTER("innobase_init_vc_templ"); - - ut_ad(table->vc_templ == NULL); - - TABLE *mysql_table= innodb_find_table_for_vc(current_thd, table); - - ut_ad(mysql_table); - if (!mysql_table) { - DBUG_RETURN(NULL); - } - - dict_vcol_templ_t* vc_templ = UT_NEW_NOKEY(dict_vcol_templ_t()); - - mutex_enter(&dict_sys.mutex); - table->vc_templ = vc_templ; - innobase_build_v_templ(mysql_table, table, vc_templ, nullptr, true); - mutex_exit(&dict_sys.mutex); - DBUG_RETURN(mysql_table); -} - /** Change dbname and table name in table->vc_templ. @param[in,out] table the table whose virtual column template dbname and tbname to be renamed. */ diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index eb90ec0f04c..7605a1904e3 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -940,11 +940,6 @@ innobase_get_computed_value( const upd_t* update=NULL, bool ignore_warnings=false); -/** Get the computed value by supplying the base column values. -@param[in,out] table the table whose virtual column - template to be built */ -TABLE* innobase_init_vc_templ(dict_table_t* table); - /** Change dbname and table name in table->vc_templ. @param[in,out] table the table whose virtual column template dbname and tbname to be renamed. */ From 156bf5298f0f12560466ef1f5371dd8dce0e5944 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 11 Oct 2023 20:20:55 +0200 Subject: [PATCH 044/158] fix SRPM builds on SLES 12.5, cmake 3.5.2 the bug with %attr(700,%{mysqld_user},-) was fixed not right after 2.8.12, but only in 3.10.0 https://gitlab.kitware.com/cmake/cmake/-/commit/a351edd245 --- plugin/auth_pam/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/auth_pam/CMakeLists.txt b/plugin/auth_pam/CMakeLists.txt index 49e02b339c7..f2cce80f800 100644 --- a/plugin/auth_pam/CMakeLists.txt +++ b/plugin/auth_pam/CMakeLists.txt @@ -42,8 +42,8 @@ IF(HAVE_PAM_APPL_H AND HAVE_GETGROUPLIST) IF (TARGET auth_pam) MYSQL_ADD_EXECUTABLE(auth_pam_tool auth_pam_tool.c DESTINATION ${INSTALL_PLUGINDIR}/auth_pam_tool_dir COMPONENT Server) TARGET_LINK_LIBRARIES(auth_pam_tool pam) - IF (CMAKE_MAJOR_VERSION EQUAL 2) - # 2.8.12 bug (in CentOS 7) + IF (CMAKE_VERSION VERSION_LESS 3.10.0) + # cmake bug #14362 SET(user mysql) ELSE() SET(user "%{mysqld_user}") From a2312b6fb2aa72c0eb14f96d1103135d21df08bc Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Thu, 12 Oct 2023 14:48:43 +0530 Subject: [PATCH 045/158] MDEV-32017 Auto-increment no longer works for explicit FTS_DOC_ID - InnoDB should avoid the sync commit operation when there is nothing in fulltext cache. This is caused by commit 1248fe727784bb6be73f70163353cf8457cfde69 (MDEV-27582) --- .../suite/innodb_fts/r/innodb-fts-ddl.result | 13 +++++++++++++ mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test | 14 ++++++++++++++ storage/innobase/fts/fts0fts.cc | 5 +++++ storage/innobase/row/row0merge.cc | 2 +- 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result index d831477c2af..15f5b2958cd 100644 --- a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result +++ b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result @@ -318,3 +318,16 @@ DROP TABLE t1; disconnect con1; SET GLOBAL innodb_optimize_fulltext_only=OFF; SET GLOBAL innodb_ft_aux_table = default; +# +# MDEV-32017 Auto-increment no longer works for +# explicit FTS_DOC_ID +# +CREATE TABLE t ( +FTS_DOC_ID BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, +f1 char(255), f2 char(255), f3 char(255), fulltext key (f3) +) ENGINE=InnoDB; +INSERT INTO t (f1,f2,f3) VALUES ('foo','bar','baz'); +ALTER TABLE t ADD FULLTEXT INDEX ft1(f1); +ALTER TABLE t ADD FULLTEXT INDEX ft2(f2); +INSERT INTO t (f1,f2,f3) VALUES ('bar','baz','qux'); +DROP TABLE t; diff --git a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test index 31f10399bc2..cef8df2d113 100644 --- a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test +++ b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test @@ -397,3 +397,17 @@ DROP TABLE t1; disconnect con1; SET GLOBAL innodb_optimize_fulltext_only=OFF; SET GLOBAL innodb_ft_aux_table = default; + +--echo # +--echo # MDEV-32017 Auto-increment no longer works for +--echo # explicit FTS_DOC_ID +--echo # +CREATE TABLE t ( + FTS_DOC_ID BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + f1 char(255), f2 char(255), f3 char(255), fulltext key (f3) +) ENGINE=InnoDB; +INSERT INTO t (f1,f2,f3) VALUES ('foo','bar','baz'); +ALTER TABLE t ADD FULLTEXT INDEX ft1(f1); +ALTER TABLE t ADD FULLTEXT INDEX ft2(f2); +INSERT INTO t (f1,f2,f3) VALUES ('bar','baz','qux'); +DROP TABLE t; diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 8ce6fee0b76..499f826cea0 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -4304,6 +4304,11 @@ fts_sync( size_t fts_cache_size= 0; rw_lock_x_lock(&cache->lock); + if (cache->total_size == 0) { + rw_lock_x_unlock(&cache->lock); + return DB_SUCCESS; + } + /* Check if cache is being synced. Note: we release cache lock in fts_sync_write_words() to avoid long wait for the lock by other threads. */ diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index f0aed489f22..a85a6d8becb 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -2828,7 +2828,7 @@ wait_again: if (err == DB_SUCCESS) { new_table->fts->cache->synced_doc_id = max_doc_id; - /* Update the max value as next FTS_DOC_ID */ + /* Update the max value as next FTS_DOC_ID */ if (max_doc_id >= new_table->fts->cache->next_doc_id) { new_table->fts->cache->next_doc_id = max_doc_id + 1; From 4045ead9db6f591bc4b971162d943ca2dc799d38 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Thu, 12 Oct 2023 14:49:27 +0530 Subject: [PATCH 046/158] MDEV-32337 Assertion `pos < table->n_def' failed in dict_table_get_nth_col While checking for altered column in foreign key constraints, InnoDB fails to ignore virtual columns. This issue caused by commit 5f09b53bdb4e973e7c7ec2c53a24c98321223f98(MDEV-31086). --- mysql-test/suite/innodb/r/fk_col_alter.result | 11 +++++++++++ mysql-test/suite/innodb/t/fk_col_alter.test | 13 +++++++++++++ storage/innobase/handler/handler0alter.cc | 13 +++++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/fk_col_alter.result b/mysql-test/suite/innodb/r/fk_col_alter.result index a220402db94..21a8f5da334 100644 --- a/mysql-test/suite/innodb/r/fk_col_alter.result +++ b/mysql-test/suite/innodb/r/fk_col_alter.result @@ -94,4 +94,15 @@ ALTER TABLE t2 MODIFY b VARCHAR(16), ADD KEY(b); ERROR 42S02: Table 'test.t2' doesn't exist DROP TABLE t2, t1; ERROR 42S02: Unknown table 'test.t2' +# +# MDEV-32337 Assertion `pos < table->n_def' failed +# in dict_table_get_nth_col +# +CREATE TABLE t (a INT, va INT AS (a), b INT, vb INT AS (b), +c INT, vc INT AS (c), vf VARCHAR(16) AS (f), +f VARCHAR(4)) ENGINE=InnoDB; +ALTER TABLE t MODIFY f VARCHAR(8); +ALTER TABLE t MODIFY vf VARCHAR(18); +ERROR HY000: This is not yet supported for generated columns +DROP TABLE t; # End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/fk_col_alter.test b/mysql-test/suite/innodb/t/fk_col_alter.test index 87ccde5652a..afcea6093b4 100644 --- a/mysql-test/suite/innodb/t/fk_col_alter.test +++ b/mysql-test/suite/innodb/t/fk_col_alter.test @@ -126,4 +126,17 @@ SET SESSION FOREIGN_KEY_CHECKS = ON; ALTER TABLE t2 MODIFY b VARCHAR(16), ADD KEY(b); --error ER_BAD_TABLE_ERROR DROP TABLE t2, t1; + +--echo # +--echo # MDEV-32337 Assertion `pos < table->n_def' failed +--echo # in dict_table_get_nth_col +--echo # +CREATE TABLE t (a INT, va INT AS (a), b INT, vb INT AS (b), + c INT, vc INT AS (c), vf VARCHAR(16) AS (f), + f VARCHAR(4)) ENGINE=InnoDB; +ALTER TABLE t MODIFY f VARCHAR(8); +# Altering the virtual column is not supported +--error ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN +ALTER TABLE t MODIFY vf VARCHAR(18); +DROP TABLE t; --echo # End of 10.4 tests diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index bde3c1fb05e..eb484281bf2 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -8333,8 +8333,17 @@ err_exit: if (ha_alter_info->handler_flags & ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) { - for (uint i= 0; i < table->s->fields; i++) { + for (uint i= 0, n_v_col= 0; i < table->s->fields; + i++) { Field* field = table->field[i]; + + /* Altering the virtual column is not + supported for inplace alter algorithm */ + if (field->vcol_info) { + n_v_col++; + continue; + } + for (const Create_field& new_field : ha_alter_info->alter_info->create_list) { if (new_field.field == field) { @@ -8349,7 +8358,7 @@ err_exit: field_changed: const char* col_name= field->field_name.str; dict_col_t *col= dict_table_get_nth_col( - m_prebuilt->table, i); + m_prebuilt->table, i - n_v_col); if (check_col_is_in_fk_indexes( m_prebuilt->table, col, col_name, span( From c79ca7c7add86ffa49cd1bebaea29bbc0dec592a Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 19 Sep 2023 11:33:51 +1000 Subject: [PATCH 047/158] MDEV-18200 MariaBackup full backup failed with InnoDB: Failing assertion: success There are many filesystem related errors that can occur with MariaBackup. These already outputed to stderr with a good description of the error. Many of these are permission or resource (file descriptor) limits where the assertion and resulting core crash doesn't offer developers anything more than the log message. To the user, assertions and core crashes come across as poor error handling. As such we return an error and handle this all the way up the stack. --- extra/mariabackup/xtrabackup.cc | 32 +++++++++++------- .../suite/mariabackup/data_directory.result | 6 ++++ .../suite/mariabackup/data_directory.test | 15 +++++++++ storage/innobase/fil/fil0fil.cc | 5 +-- storage/innobase/include/log0log.h | 3 +- storage/innobase/include/log0recv.h | 3 +- storage/innobase/log/log0log.cc | 10 ++++-- storage/innobase/log/log0recv.cc | 33 ++++++++++++------- 8 files changed, 77 insertions(+), 30 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 5c122ad04f2..513f469e699 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -4436,16 +4436,24 @@ bool Backup_datasinks::backup_low() if (recv_find_max_checkpoint(&max_cp_field) == DB_SUCCESS && log_sys.log.format != 0) { - if (max_cp_field == LOG_CHECKPOINT_1) { - log_sys.log.read(max_cp_field, - {log_sys.checkpoint_buf, - OS_FILE_LOG_BLOCK_SIZE}); + switch (max_cp_field) { + case LOG_CHECKPOINT_1: + if (log_sys.log.read(max_cp_field, + {log_sys.checkpoint_buf, + OS_FILE_LOG_BLOCK_SIZE})) + { + /* metadata_to_lsn still 0 so error returns below */ + msg("Error: recv_find_max_checkpoint() failed."); + break; + } + /* fallthrough */ + default: + metadata_to_lsn = mach_read_from_8( + log_sys.checkpoint_buf + LOG_CHECKPOINT_LSN); + msg("mariabackup: The latest check point" + " (for incremental): '" LSN_PF "'", + metadata_to_lsn); } - metadata_to_lsn = mach_read_from_8( - log_sys.checkpoint_buf + LOG_CHECKPOINT_LSN); - msg("mariabackup: The latest check point" - " (for incremental): '" LSN_PF "'", - metadata_to_lsn); } else { msg("Error: recv_find_max_checkpoint() failed."); } @@ -4661,14 +4669,14 @@ reread_log_header: checkpoint_lsn_start = log_sys.log.get_lsn(); checkpoint_no_start = log_sys.next_checkpoint_no; - log_sys.log.read(max_cp_field, {buf, OS_FILE_LOG_BLOCK_SIZE}); + err = log_sys.log.read(max_cp_field, {buf, OS_FILE_LOG_BLOCK_SIZE}); - if (checkpoint_no_start + if (err == DB_SUCCESS && (checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO) || checkpoint_lsn_start != mach_read_from_8(buf + LOG_CHECKPOINT_LSN) || log_sys.log.get_lsn_offset() - != mach_read_from_8(buf + LOG_CHECKPOINT_OFFSET)) + != mach_read_from_8(buf + LOG_CHECKPOINT_OFFSET))) goto reread_log_header; } mysql_mutex_unlock(&log_sys.mutex); diff --git a/mysql-test/suite/mariabackup/data_directory.result b/mysql-test/suite/mariabackup/data_directory.result index 4e45127bd6a..8692c35239e 100644 --- a/mysql-test/suite/mariabackup/data_directory.result +++ b/mysql-test/suite/mariabackup/data_directory.result @@ -11,3 +11,9 @@ SELECT * FROM t; a 1 DROP TABLE t; +# +# MDEV-18200 MariaBackup full backup failed with InnoDB: Failing assertion: success +# +# +# End of 10.4 tests +# diff --git a/mysql-test/suite/mariabackup/data_directory.test b/mysql-test/suite/mariabackup/data_directory.test index a89b7bdccc4..ffb3ab3073c 100644 --- a/mysql-test/suite/mariabackup/data_directory.test +++ b/mysql-test/suite/mariabackup/data_directory.test @@ -21,4 +21,19 @@ rmdir $table_data_dir; SELECT * FROM t; DROP TABLE t; rmdir $targetdir; + +--echo # +--echo # MDEV-18200 MariaBackup full backup failed with InnoDB: Failing assertion: success +--echo # +let $DATADIR= `select @@datadir`; +chmod 0000 $DATADIR/ibdata1; +--disable_result_log +--error 1 +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +chmod 0755 $DATADIR/ibdata1; rmdir $table_data_dir; +rmdir $targetdir; +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 725345957ee..ea7c496b86b 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -363,6 +363,7 @@ fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle, return node; } +__attribute__((warn_unused_result, nonnull)) /** Open a tablespace file. @param node data file @return whether the file was successfully opened */ @@ -391,9 +392,9 @@ static bool fil_node_open_file_low(fil_node_t *node) : OS_FILE_OPEN | OS_FILE_ON_ERROR_NO_EXIT, OS_FILE_AIO, type, srv_read_only_mode, &success); - if (node->is_open()) + + if (success && node->is_open()) { - ut_ad(success); #ifndef _WIN32 if (!node->space->id && !srv_read_only_mode && my_disable_locking && os_file_lock(node->handle, node->name)) diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index e8399ba4c96..16ff4ced5b2 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -506,7 +506,8 @@ public: /** reads buffer from log file @param[in] offset offset in log file @param[in] buf buffer where to read */ - void read(os_offset_t offset, span buf); + dberr_t MY_ATTRIBUTE((warn_unused_result)) read(os_offset_t offset, + span buf); /** Tells whether writes require calling flush() */ bool writes_are_durable() const noexcept; /** writes buffer to log file diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index e4a8f0d25a2..263996a78d3 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -283,7 +283,8 @@ public: /** Last added LSN to pages. */ lsn_t last_stored_lsn= 0; - void read(os_offset_t offset, span buf); + __attribute__((warn_unused_result)) + dberr_t read(os_offset_t offset, span buf); inline size_t files_size(); void close_files() { files.clear(); files.shrink_to_fit(); } diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 58d7689894d..279e2806b23 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -280,6 +280,7 @@ dberr_t file_os_io::close() noexcept return DB_SUCCESS; } +__attribute__((warn_unused_result)) dberr_t file_os_io::read(os_offset_t offset, span buf) noexcept { return os_file_read(IORequestRead, m_fd, buf.data(), offset, buf.size()); @@ -382,6 +383,7 @@ public: : DB_ERROR; } dberr_t close() noexcept final { return m_file.unmap(); } + __attribute__((warn_unused_result)) dberr_t read(os_offset_t offset, span buf) noexcept final { memcpy(buf.data(), m_file.data() + offset, buf.size()); @@ -448,6 +450,8 @@ dberr_t log_file_t::close() noexcept return DB_SUCCESS; } + +__attribute__((warn_unused_result)) dberr_t log_file_t::read(os_offset_t offset, span buf) noexcept { ut_ad(is_opened()); @@ -510,10 +514,10 @@ void log_t::file::write_header_durable(lsn_t lsn) log_sys.log.flush(); } -void log_t::file::read(os_offset_t offset, span buf) +__attribute__((warn_unused_result)) +dberr_t log_t::file::read(os_offset_t offset, span buf) { - if (const dberr_t err= fd.read(offset, buf)) - ib::fatal() << "read(" << fd.get_path() << ") returned "<< err; + return fd.read(offset, buf); } bool log_t::file::writes_are_durable() const noexcept diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 1b62b1fe111..a34f00e16c1 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -762,14 +762,15 @@ void recv_sys_t::open_log_files_if_needed() } } -void recv_sys_t::read(os_offset_t total_offset, span buf) +MY_ATTRIBUTE((warn_unused_result)) +dberr_t +recv_sys_t::read(os_offset_t total_offset, span buf) { open_log_files_if_needed(); size_t file_idx= static_cast(total_offset / log_sys.log.file_size); os_offset_t offset= total_offset % log_sys.log.file_size; - dberr_t err= recv_sys.files[file_idx].read(offset, buf); - ut_a(err == DB_SUCCESS); + return recv_sys.files[file_idx].read(offset, buf); } inline size_t recv_sys_t::files_size() @@ -1107,7 +1108,8 @@ loop: ut_a((source_offset >> srv_page_size_shift) <= ULINT_MAX); - recv_sys.read(source_offset, {buf, len}); + if (recv_sys.read(source_offset, {buf, len})) + return false; for (ulint l = 0; l < len; l += OS_FILE_LOG_BLOCK_SIZE, buf += OS_FILE_LOG_BLOCK_SIZE, @@ -1272,6 +1274,7 @@ inline uint32_t log_block_calc_checksum_format_0(const byte *b) ATTRIBUTE_COLD static dberr_t recv_log_recover_pre_10_2() { uint64_t max_no= 0; + dberr_t err; byte *buf= log_sys.buf; ut_ad(log_sys.log.format == 0); @@ -1295,7 +1298,8 @@ ATTRIBUTE_COLD static dberr_t recv_log_recover_pre_10_2() for (ulint field= LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { - log_sys.log.read(field, {buf, OS_FILE_LOG_BLOCK_SIZE}); + if ((err= log_sys.log.read(field, {buf, OS_FILE_LOG_BLOCK_SIZE}))) + return err; if (static_cast(ut_fold_binary(buf, CHECKSUM_1)) != mach_read_from_4(buf + CHECKSUM_1) || @@ -1347,7 +1351,8 @@ ATTRIBUTE_COLD static dberr_t recv_log_recover_pre_10_2() "InnoDB: Upgrade after a crash is not supported." " This redo log was created before MariaDB 10.2.2"; - recv_sys.read(source_offset & ~511, {buf, 512}); + if ((err= recv_sys.read(source_offset & ~511, {buf, 512}))) + return err; if (log_block_calc_checksum_format_0(buf) != log_block_get_checksum(buf) && !log_crypt_101_read_block(buf, lsn)) @@ -1414,8 +1419,9 @@ static dberr_t recv_log_recover_10_4() return DB_CORRUPTION; } - recv_sys.read(source_offset & ~lsn_t(OS_FILE_LOG_BLOCK_SIZE - 1), - {buf, OS_FILE_LOG_BLOCK_SIZE}); + if (dberr_t err= recv_sys.read(source_offset & ~lsn_t(OS_FILE_LOG_BLOCK_SIZE - 1), + {buf, OS_FILE_LOG_BLOCK_SIZE})) + return err; ulint crc = log_block_calc_checksum_crc32(buf); ulint cksum = log_block_get_checksum(buf); @@ -1473,7 +1479,8 @@ recv_find_max_checkpoint(ulint* max_field) buf = log_sys.checkpoint_buf; - log_sys.log.read(0, {buf, OS_FILE_LOG_BLOCK_SIZE}); + if (dberr_t err= log_sys.log.read(0, {buf, OS_FILE_LOG_BLOCK_SIZE})) + return err; /* Check the header page checksum. There was no checksum in the first redo log format (version 0). */ log_sys.log.format = mach_read_from_4(buf + LOG_HEADER_FORMAT); @@ -1512,7 +1519,8 @@ recv_find_max_checkpoint(ulint* max_field) for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { - log_sys.log.read(field, {buf, OS_FILE_LOG_BLOCK_SIZE}); + if (dberr_t err= log_sys.log.read(field, {buf, OS_FILE_LOG_BLOCK_SIZE})) + return err; const ulint crc32 = log_block_calc_checksum_crc32(buf); const ulint cksum = log_block_get_checksum(buf); @@ -3452,7 +3460,10 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) } buf = log_sys.checkpoint_buf; - log_sys.log.read(max_cp_field, {buf, OS_FILE_LOG_BLOCK_SIZE}); + if ((err= log_sys.log.read(max_cp_field, {buf, OS_FILE_LOG_BLOCK_SIZE}))) { + mysql_mutex_unlock(&log_sys.mutex); + return(err); + } checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO); From fbd11d5f299a1e399ee5b46f141d6f56db0f7f58 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Fri, 13 Oct 2023 09:12:01 +1100 Subject: [PATCH 048/158] MDEV-18200 MariaBackup full backup failed with InnoDB: Failing assertion: success Review cleanups. --- storage/innobase/include/log0log.h | 9 ++++++--- storage/innobase/log/log0log.cc | 11 ----------- storage/innobase/log/log0recv.cc | 11 +++++------ 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 16ff4ced5b2..26385bb4494 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -503,13 +503,16 @@ public: void write_header_durable(lsn_t lsn); /** opens log file which must be closed prior this call */ dberr_t rename(std::string path) { return fd.rename(path); } + + MY_ATTRIBUTE((warn_unused_result)) /** reads buffer from log file @param[in] offset offset in log file @param[in] buf buffer where to read */ - dberr_t MY_ATTRIBUTE((warn_unused_result)) read(os_offset_t offset, - span buf); + dberr_t read(os_offset_t offset, span buf) + { return fd.read(offset, buf); } /** Tells whether writes require calling flush() */ - bool writes_are_durable() const noexcept; + bool writes_are_durable() const noexcept + { return fd.writes_are_durable(); } /** writes buffer to log file @param[in] offset offset in log file @param[in] buf buffer from which to write */ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 279e2806b23..a9029a3df82 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -514,17 +514,6 @@ void log_t::file::write_header_durable(lsn_t lsn) log_sys.log.flush(); } -__attribute__((warn_unused_result)) -dberr_t log_t::file::read(os_offset_t offset, span buf) -{ - return fd.read(offset, buf); -} - -bool log_t::file::writes_are_durable() const noexcept -{ - return fd.writes_are_durable(); -} - void log_t::file::write(os_offset_t offset, span buf) { srv_stats.os_log_pending_writes.inc(); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index a34f00e16c1..e452267d2e8 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -763,8 +763,7 @@ void recv_sys_t::open_log_files_if_needed() } MY_ATTRIBUTE((warn_unused_result)) -dberr_t -recv_sys_t::read(os_offset_t total_offset, span buf) +dberr_t recv_sys_t::read(os_offset_t total_offset, span buf) { open_log_files_if_needed(); @@ -1274,7 +1273,6 @@ inline uint32_t log_block_calc_checksum_format_0(const byte *b) ATTRIBUTE_COLD static dberr_t recv_log_recover_pre_10_2() { uint64_t max_no= 0; - dberr_t err; byte *buf= log_sys.buf; ut_ad(log_sys.log.format == 0); @@ -1298,7 +1296,7 @@ ATTRIBUTE_COLD static dberr_t recv_log_recover_pre_10_2() for (ulint field= LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { - if ((err= log_sys.log.read(field, {buf, OS_FILE_LOG_BLOCK_SIZE}))) + if (dberr_t err= log_sys.log.read(field, {buf, OS_FILE_LOG_BLOCK_SIZE})) return err; if (static_cast(ut_fold_binary(buf, CHECKSUM_1)) != @@ -1351,7 +1349,7 @@ ATTRIBUTE_COLD static dberr_t recv_log_recover_pre_10_2() "InnoDB: Upgrade after a crash is not supported." " This redo log was created before MariaDB 10.2.2"; - if ((err= recv_sys.read(source_offset & ~511, {buf, 512}))) + if (dberr_t err= recv_sys.read(source_offset & ~511, {buf, 512})) return err; if (log_block_calc_checksum_format_0(buf) != log_block_get_checksum(buf) && @@ -1419,7 +1417,8 @@ static dberr_t recv_log_recover_10_4() return DB_CORRUPTION; } - if (dberr_t err= recv_sys.read(source_offset & ~lsn_t(OS_FILE_LOG_BLOCK_SIZE - 1), + if (dberr_t err= + recv_sys.read(source_offset & ~lsn_t(OS_FILE_LOG_BLOCK_SIZE - 1), {buf, OS_FILE_LOG_BLOCK_SIZE})) return err; From 358209dab4e21c1d00cca48021ee17884f61ec91 Mon Sep 17 00:00:00 2001 From: Ian Gilfillan Date: Thu, 12 Oct 2023 14:42:35 +0200 Subject: [PATCH 049/158] Update innochecksum man page --- man/innochecksum.1 | 92 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 7 deletions(-) diff --git a/man/innochecksum.1 b/man/innochecksum.1 index 8c63237c1e1..38dd3db7759 100644 --- a/man/innochecksum.1 +++ b/man/innochecksum.1 @@ -34,7 +34,7 @@ CHECK TABLE to check tables within the tablespace\&. .PP If checksum mismatches are found, you would normally restore the tablespace from backup or start the server and attempt to use -\fBmysqldump\fR +\fBmariadb-dump\fR to make a backup of the tables within the tablespace\&. .PP Invoke @@ -75,9 +75,9 @@ Displays help and exits\&. .sp -1 .IP \(bu 2.3 .\} -\fB\-c, --count\fR +\fB\-a \fR\fB\fInum\fB, --allow-mismatches=#\fR .sp -Print a count of the number of pages in the file\&. +Maximum checksum mismatch allowed before innochecksum terminates. Defaults to 0, which terminates on the first mismatch\&. .RE .sp .RS 4 @@ -88,9 +88,9 @@ Print a count of the number of pages in the file\&. .sp -1 .IP \(bu 2.3 .\} -\fB\-d, --debug\fR +\fB\-c, --count\fR .sp -Debug mode; prints checksums for each page\&. +Print a count of the number of pages in the file\&. .RE .sp .RS 4 @@ -140,7 +140,7 @@ Synonym for \fB--help\fR\&. .sp -1 .IP \(bu 2.3 .\} -\fB\-l, --leaf\fR +\fB\-f, --leaf\fR .sp Examine leaf index pages\&. .RE @@ -153,6 +153,19 @@ Examine leaf index pages\&. .sp -1 .IP \(bu 2.3 .\} +\fB\-l \fR\fB\fIfn\fB, --log=fn\fR\fR +.sp +Log output to the specified filename, fn\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} \fB\-m \fR\fB\fInum\fB, --merge=#\fR\fR .sp Leaf page count if merge given number of consecutive pages\&. @@ -166,6 +179,19 @@ Leaf page count if merge given number of consecutive pages\&. .sp -1 .IP \(bu 2.3 .\} +\fB\-n, --no-check\fR\fR +.sp +Ignore the checksum verification. Until MariaDB 10.6, must be used with the --write option\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} \fB\-p \fR\fB\fInum\fB, --page-num=#\fR\fR .sp Check only this page number\&. @@ -179,6 +205,32 @@ Check only this page number\&. .sp -1 .IP \(bu 2.3 .\} +\fB\-D \fR\fB\fIname\fB, --page-type-dump=name\fR\fR +.sp +Dump the page type info for each page in a tablespace\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +\fB\-S, --page-type-summary\fR\fR +.sp +Display a count of each page type in a tablespace\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} \fB\-s \fR\fB\fInum\fB, --start-page\fR\fR .sp Start at this page number\&. @@ -205,6 +257,32 @@ Skip corrupt pages\&. .sp -1 .IP \(bu 2.3 .\} +\fB\-C \fR\fB\fIname\fB, --strict-check=name\fR\fR +.sp +Specify the strict checksum algorithm. One of: crc32, innodb, none. If not specified, validates against innodb, crc32 and none. Removed in MariaDB 10.6\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +\fB\-w \fR\fB\fIname\fB, --write=name\fR\fR +.sp +Rewrite the checksum algorithm. One of crc32, innodb, none. An exclusive lock is obtained during use. Use in conjunction with the -no-check option to rewrite an invalid checksum. Removed in MariaDB 10.6\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} \fB\-v, --verbose\fR .sp Verbose mode; print a progress indicator every five seconds\&. @@ -225,7 +303,7 @@ Displays version information and exits\&. .SH "COPYRIGHT" .br .PP -Copyright 2007-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc., 2010-2015 MariaDB Foundation +Copyright 2007-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc., 2010-2023 MariaDB Foundation .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP From 8660e2de0ec8876464370681caceda70dde33a65 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 10 Oct 2023 11:56:19 +0200 Subject: [PATCH 050/158] MDEV-29893: SST fails when having datadir set to a symlink SST for mariabackup may not destroy old files if datadir or other working directory is declared as a symlink due to the lack of the "-L" option among the find utility options, similarly SST for rsync in some cases may not transfer data directories if they are created as symlinks. This fix adds the missing option and generally unifies the work with find utility options to avoid failures in the interpretation of directories and regular expressions. --- scripts/wsrep_sst_mariabackup.sh | 35 ++++++++++++++------------------ scripts/wsrep_sst_rsync.sh | 7 +++++-- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index b46e64a9e8b..981a042d506 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -439,7 +439,7 @@ get_transfer() get_footprint() { cd "$DATA_DIR" - local payload_data=$(find . \ + local payload_data=$(find $findopt . \ -regex '.*undo[0-9]+$\|.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' \ -type f -print0 | du --files0-from=- --block-size=1 -c -s | \ awk 'END { print $1 }') @@ -1035,6 +1035,9 @@ setup_commands() get_stream get_transfer +findopt='-L' +[ "$OS" = 'FreeBSD' ] && findopt="$findopt -E" + if [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then trap cleanup_at_exit EXIT @@ -1428,21 +1431,13 @@ else # joiner wsrep_log_info \ "Cleaning the existing datadir and innodb-data/log directories" - if [ "$OS" = 'FreeBSD' ]; then - find -E ${ib_home_dir:+"$ib_home_dir"} \ - ${ib_undo_dir:+"$ib_undo_dir"} \ - ${ib_log_dir:+"$ib_log_dir"} \ - ${ar_log_dir:+"$ar_log_dir"} \ - "$DATA" -mindepth 1 -prune -regex "$cpat" \ - -o -exec rm -rf {} >&2 \+ - else - find ${ib_home_dir:+"$ib_home_dir"} \ - ${ib_undo_dir:+"$ib_undo_dir"} \ - ${ib_log_dir:+"$ib_log_dir"} \ - ${ar_log_dir:+"$ar_log_dir"} \ - "$DATA" -mindepth 1 -prune -regex "$cpat" \ - -o -exec rm -rf {} >&2 \+ - fi + + find $findopt ${ib_home_dir:+"$ib_home_dir"} \ + ${ib_undo_dir:+"$ib_undo_dir"} \ + ${ib_log_dir:+"$ib_log_dir"} \ + ${ar_log_dir:+"$ar_log_dir"} \ + "$DATA" -mindepth 1 -prune -regex "$cpat" \ + -o -exec rm -rf {} >&2 \+ TDATA="$DATA" DATA="$DATA/.sst" @@ -1464,7 +1459,7 @@ else # joiner exit 2 fi - qpfiles=$(find "$DATA" -maxdepth 1 -type f -name '*.qp' -print -quit) + qpfiles=$(find $findopt "$DATA" -maxdepth 1 -type f -name '*.qp' -print -quit) if [ -n "$qpfiles" ]; then wsrep_log_info "Compressed qpress files found" @@ -1480,7 +1475,7 @@ else # joiner if [ -n "$progress" -a "$progress" != 'none' ] && \ pv --help | grep -qw -F -- '--line-mode' then - count=$(find "$DATA" -maxdepth 1 -type f -name '*.qp' | wc -l) + count=$(find $findopt "$DATA" -maxdepth 1 -type f -name '*.qp' | wc -l) count=$(( count*2 )) pvopts='-f -l -N Decompression' pvformat="-F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'" @@ -1492,13 +1487,13 @@ else # joiner # Decompress the qpress files wsrep_log_info "Decompression with $nproc threads" timeit 'Joiner-Decompression' \ - "find '$DATA' -type f -name '*.qp' -printf '%p\n%h\n' | \ + "find $findopt '$DATA' -type f -name '*.qp' -printf '%p\n%h\n' | \ $dcmd" extcode=$? if [ $extcode -eq 0 ]; then wsrep_log_info "Removing qpress files after decompression" - find "$DATA" -type f -name '*.qp' -delete + find $findopt "$DATA" -type f -name '*.qp' -delete if [ $? -ne 0 ]; then wsrep_log_error \ "Something went wrong with deletion of qpress files." \ diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 8d53405eeb8..3e63596bcbe 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -673,9 +673,12 @@ FILTER="-f '- /lost+found' cd "$DATA" - find . -maxdepth 1 -mindepth 1 -type d -not -name 'lost+found' \ + findopt='-L' + [ "$OS" = 'FreeBSD' ] && findopt="$findopt -E" + + find $findopt . -maxdepth 1 -mindepth 1 -type d -not -name 'lost+found' \ -not -name '.zfs' -not -name .snapshot -print0 \ - | xargs -I{} -0 -P $backup_threads \ + | xargs -I{} -0 -P $backup_threads \ rsync ${STUNNEL:+--rsh="$STUNNEL"} \ --owner --group --perms --links --specials --ignore-times \ --inplace --recursive --delete --quiet $WHOLE_FILE_OPT \ From 5c6fceec769296a52b52fcd6d34394029950094c Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 13 Oct 2023 15:17:54 +1100 Subject: [PATCH 051/158] MDEV-28998 remove a known reference to a SPIDER_CONN when it is freed --- .../spider/bugfix/r/mdev_28998.result | 23 ++++++++++++ .../spider/bugfix/t/mdev_28998.test | 35 +++++++++++++++++++ storage/spider/spd_conn.cc | 2 ++ storage/spider/spd_group_by_handler.cc | 3 +- 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result new file mode 100644 index 00000000000..edac80d9761 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result @@ -0,0 +1,23 @@ +# +# MDEV-28998 ASAN errors in spider_fields::free_conn_holder or spider_create_group_by_handler +# +for master_1 +for child2 +for child3 +CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t1_SPIDER (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't1'"; +CREATE TABLE t2 AS SELECT a FROM t1_SPIDER; +SELECT * FROM t2; +a +1 +2 +DROP TABLE t2, t1_SPIDER, t1; +drop server s; +for master_1 +for child2 +for child3 +# +# end of test mdev_28998 +# diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test new file mode 100644 index 00000000000..e1735706341 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test @@ -0,0 +1,35 @@ +--echo # +--echo # MDEV-28998 ASAN errors in spider_fields::free_conn_holder or spider_create_group_by_handler +--echo # + +if (`select not(count(*)) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "%ASAN%"`) +{ +--skip test needs to be run with ASAN +} + +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log +evalp CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t1_SPIDER (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't1'"; + +CREATE TABLE t2 AS SELECT a FROM t1_SPIDER; +SELECT * FROM t2; + +# Cleanup +DROP TABLE t2, t1_SPIDER, t1; +drop server s; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log +--echo # +--echo # end of test mdev_28998 +--echo # diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index 8c2a9d81e2b..40fb155ac8e 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -1255,6 +1255,8 @@ int spider_free_conn( ip_port_conn->ip_port_count--; pthread_mutex_unlock(&ip_port_conn->mutex); } + if (conn->conn_holder_for_direct_join) + conn->conn_holder_for_direct_join->conn= NULL; spider_free_conn_alloc(conn); spider_free(spider_current_trx, conn, MYF(0)); DBUG_RETURN(0); diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index 5a0c30bd790..dd39c5e48d4 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -859,7 +859,8 @@ void spider_fields::free_conn_holder( } } } - conn_holder_arg->conn->conn_holder_for_direct_join = NULL; + if (conn_holder_arg->conn) + conn_holder_arg->conn->conn_holder_for_direct_join = NULL; DBUG_PRINT("info",("spider free conn_holder=%p", conn_holder_arg)); spider_free(spider_current_trx, conn_holder_arg, MYF(0)); DBUG_VOID_RETURN; From c03cb73ab93dcad4384f164873b5d2116c7b4aed Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 13 Oct 2023 12:33:32 +0300 Subject: [PATCH 052/158] Safemalloc did not give list of not freed THD memory --- sql/sql_class.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 46177837827..1d278a01947 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1730,7 +1730,7 @@ THD::~THD() if (status_var.local_memory_used != 0) { DBUG_PRINT("error", ("memory_used: %lld", status_var.local_memory_used)); - SAFEMALLOC_REPORT_MEMORY(thread_id); + SAFEMALLOC_REPORT_MEMORY(sf_malloc_dbug_id()); DBUG_ASSERT(status_var.local_memory_used == 0 || !debug_assert_on_not_freed_memory); } From d594f1e53191765b382c4bd696b95295bc6065b1 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 13 Oct 2023 11:15:14 +0200 Subject: [PATCH 053/158] Removing MDEV-27871 because it is not a bug Part 1 --- mysql-test/main/alias.test | 6 +- mysql-test/main/case.result | 90 +- mysql-test/main/case.test | 50 +- mysql-test/main/cast.result | 116 +- mysql-test/main/cast.test | 80 +- mysql-test/main/ctype_collate.result | 13 +- mysql-test/main/ctype_collate.test | 8 +- mysql-test/main/ctype_eucjpms.test | 2 - mysql-test/main/ctype_gbk.result | 8 +- mysql-test/main/ctype_gbk.test | 4 +- mysql-test/main/ctype_sjis.test | 5 - mysql-test/main/ctype_uca.result | 4 +- mysql-test/main/ctype_uca.test | 5 +- mysql-test/main/dyncol.result | 1405 ++++++++--------- mysql-test/main/dyncol.test | 695 ++++---- mysql-test/main/fulltext.result | 5 +- mysql-test/main/fulltext.test | 7 +- mysql-test/main/func_concat.result | 5 +- mysql-test/main/func_concat.test | 7 +- mysql-test/main/func_debug.result | 196 +-- mysql-test/main/func_debug.test | 127 +- mysql-test/main/func_hybrid_type.result | 4 +- mysql-test/main/func_hybrid_type.test | 5 +- mysql-test/main/func_if.result | 14 +- mysql-test/main/func_if.test | 5 +- mysql-test/main/func_json.result | 392 ++--- mysql-test/main/func_json.test | 238 +-- mysql-test/main/func_math.result | 4 +- mysql-test/main/func_math.test | 5 +- mysql-test/main/func_misc.result | 12 +- mysql-test/main/func_misc.test | 12 +- mysql-test/main/func_sapdb.result | 100 +- mysql-test/main/func_sapdb.test | 62 +- mysql-test/main/func_set.result | 17 +- mysql-test/main/func_set.test | 12 +- mysql-test/main/func_time.result | 165 +- mysql-test/main/func_time.test | 128 +- mysql-test/main/gis-json.result | 94 +- mysql-test/main/gis-json.test | 60 +- mysql-test/main/gis.result | 87 +- mysql-test/main/gis.test | 86 +- mysql-test/main/loaddata.result | 25 +- mysql-test/main/loaddata.test | 40 +- mysql-test/main/null.result | 4 +- mysql-test/main/null.test | 7 +- mysql-test/main/opt_trace.test | 3 - mysql-test/main/outfile_loaddata.result | 28 +- mysql-test/main/outfile_loaddata.test | 17 +- mysql-test/main/second_frac-9175.result | 12 +- mysql-test/main/second_frac-9175.test | 11 +- mysql-test/main/select.result | 115 +- mysql-test/main/select.test | 62 +- mysql-test/main/select_jcl6.result | 115 +- mysql-test/main/select_pkeycache.result | 115 +- mysql-test/main/subselect4.result | 54 +- mysql-test/main/subselect4.test | 20 +- mysql-test/main/subselect_exists2in.result | 24 +- mysql-test/main/subselect_exists2in.test | 16 +- .../main/subselect_mat_cost_bugs.result | 10 +- mysql-test/main/subselect_mat_cost_bugs.test | 9 +- mysql-test/main/type_date.result | 14 +- mysql-test/main/type_date.test | 14 +- mysql-test/main/type_time.result | 8 +- mysql-test/main/type_time.test | 10 +- mysql-test/main/win_big-mdev-10092.result | 16 +- mysql-test/main/win_big-mdev-10092.test | 13 +- mysql-test/main/win_big-mdev-11697.result | 4 +- mysql-test/main/win_big-mdev-11697.test | 5 +- mysql-test/main/win_orderby.result | 20 +- mysql-test/main/win_orderby.test | 7 +- mysql-test/main/win_std.result | 117 +- mysql-test/main/win_std.test | 65 +- 72 files changed, 2517 insertions(+), 2803 deletions(-) diff --git a/mysql-test/main/alias.test b/mysql-test/main/alias.test index bc429656b7e..f75fdafea1e 100644 --- a/mysql-test/main/alias.test +++ b/mysql-test/main/alias.test @@ -1,5 +1,3 @@ -#remove this include after fix MDEV-27871 ---source include/no_view_protocol.inc --disable_warnings DROP TABLE IF EXISTS t1; @@ -248,7 +246,9 @@ SET sql_mode=DEFAULT; --echo # in Item::print_item_w_name on SELECT w/ optimizer_trace enabled --echo # +--disable_view_protocol SELECT '' LIMIT 0; +--enable_view_protocol --error ER_WRONG_COLUMN_NAME CREATE TABLE t1 AS SELECT ''; @@ -320,7 +320,9 @@ create or replace table t2 (b int); insert into t1 values(111111111),(-2147483648); insert into t2 values(1),(2); --enable_metadata +--disable_view_protocol select t1.a as a1 from t1 as t1,t2 order by t2.b,t1.a; +--enable_view_protocol --disable_metadata drop table t1,t2; diff --git a/mysql-test/main/case.result b/mysql-test/main/case.result index 139267a103c..fcabbc1a968 100644 --- a/mysql-test/main/case.result +++ b/mysql-test/main/case.result @@ -1,67 +1,67 @@ drop table if exists t1, t2; -select CASE "b" when "a" then 1 when "b" then 2 END; -CASE "b" when "a" then 1 when "b" then 2 END +select CASE "b" when "a" then 1 when "b" then 2 END as exp; +exp 2 -select CASE "c" when "a" then 1 when "b" then 2 END; -CASE "c" when "a" then 1 when "b" then 2 END +select CASE "c" when "a" then 1 when "b" then 2 END as exp; +exp NULL -select CASE "c" when "a" then 1 when "b" then 2 ELSE 3 END; -CASE "c" when "a" then 1 when "b" then 2 ELSE 3 END +select CASE "c" when "a" then 1 when "b" then 2 ELSE 3 END as exp; +exp 3 -select CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END; -CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END +select CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END as exp; +exp ok -select CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END; -CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END +select CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END as exp; +exp ok -select CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end; -CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end +select CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end as exp; +exp a -select CASE when 1=0 then "true" else "false" END; -CASE when 1=0 then "true" else "false" END +select CASE when 1=0 then "true" else "false" END as exp; +exp false -select CASE 1 when 1 then "one" WHEN 2 then "two" ELSE "more" END; -CASE 1 when 1 then "one" WHEN 2 then "two" ELSE "more" END +select CASE 1 when 1 then "one" WHEN 2 then "two" ELSE "more" END as exp; +exp one -explain extended select CASE 1 when 1 then "one" WHEN 2 then "two" ELSE "more" END; +explain extended select CASE 1 when 1 then "one" WHEN 2 then "two" ELSE "more" END as exp; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select case 1 when 1 then 'one' when 2 then 'two' else 'more' end AS `CASE 1 when 1 then "one" WHEN 2 then "two" ELSE "more" END` -select CASE 2.0 when 1 then "one" WHEN 2.0 then "two" ELSE "more" END; -CASE 2.0 when 1 then "one" WHEN 2.0 then "two" ELSE "more" END +Note 1003 select case 1 when 1 then 'one' when 2 then 'two' else 'more' end AS `exp` +select CASE 2.0 when 1 then "one" WHEN 2.0 then "two" ELSE "more" END as exp; +exp two -select (CASE "two" when "one" then "1" WHEN "two" then "2" END) | 0; -(CASE "two" when "one" then "1" WHEN "two" then "2" END) | 0 +select (CASE "two" when "one" then "1" WHEN "two" then "2" END) | 0 as exp; +exp 2 -select (CASE "two" when "one" then 1.00 WHEN "two" then 2.00 END) +0.0; -(CASE "two" when "one" then 1.00 WHEN "two" then 2.00 END) +0.0 +select (CASE "two" when "one" then 1.00 WHEN "two" then 2.00 END) +0.0 as exp; +exp 2.00 -select case 1/0 when "a" then "true" else "false" END; -case 1/0 when "a" then "true" else "false" END +select case 1/0 when "a" then "true" else "false" END as exp; +exp false Warnings: Warning 1365 Division by 0 -select case 1/0 when "a" then "true" END; -case 1/0 when "a" then "true" END +select case 1/0 when "a" then "true" END as exp; +exp NULL Warnings: Warning 1365 Division by 0 -select (case 1/0 when "a" then "true" END) | 0; -(case 1/0 when "a" then "true" END) | 0 +select (case 1/0 when "a" then "true" END) | 0 as exp; +exp NULL Warnings: Warning 1365 Division by 0 -select (case 1/0 when "a" then "true" END) + 0.0; -(case 1/0 when "a" then "true" END) + 0.0 +select (case 1/0 when "a" then "true" END) + 0.0 as exp; +exp NULL Warnings: Warning 1365 Division by 0 -select case when 1>0 then "TRUE" else "FALSE" END; -case when 1>0 then "TRUE" else "FALSE" END +select case when 1>0 then "TRUE" else "FALSE" END as exp; +exp TRUE -select case when 1<0 then "TRUE" else "FALSE" END; -case when 1<0 then "TRUE" else "FALSE" END +select case when 1<0 then "TRUE" else "FALSE" END as exp; +exp FALSE create table t1 (a int); insert into t1 values(1),(2),(3),(4); @@ -133,12 +133,12 @@ WHEN _latin1'a' COLLATE latin1_swedish_ci THEN 2 END; ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_danish_ci,EXPLICIT), (latin1_swedish_ci,EXPLICIT) for operation 'case' SELECT -CASE _latin1'a' COLLATE latin1_general_ci WHEN _latin1'A' THEN '1' ELSE 2 END, -CASE _latin1'a' COLLATE latin1_bin WHEN _latin1'A' THEN '1' ELSE 2 END, -CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_swedish_ci THEN '1' ELSE 2 END, -CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_bin THEN '1' ELSE 2 END +CASE _latin1'a' COLLATE latin1_general_ci WHEN _latin1'A' THEN '1' ELSE 2 END as e1, +CASE _latin1'a' COLLATE latin1_bin WHEN _latin1'A' THEN '1' ELSE 2 END as e2, +CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_swedish_ci THEN '1' ELSE 2 END as e3, +CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_bin THEN '1' ELSE 2 END as e4 ; -CASE _latin1'a' COLLATE latin1_general_ci WHEN _latin1'A' THEN '1' ELSE 2 END CASE _latin1'a' COLLATE latin1_bin WHEN _latin1'A' THEN '1' ELSE 2 END CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_swedish_ci THEN '1' ELSE 2 END CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_bin THEN '1' ELSE 2 END +e1 e2 e3 e4 1 2 1 2 CREATE TABLE t1 SELECT COALESCE(_latin1'a',_latin2'a'); ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'coalesce' @@ -403,8 +403,8 @@ DROP TABLE t1; # # End of 10.1 test # -select case 'foo' when time'10:00:00' then 'never' when '0' then 'bug' else 'ok' end; -case 'foo' when time'10:00:00' then 'never' when '0' then 'bug' else 'ok' end +select case 'foo' when time'10:00:00' then 'never' when '0' then 'bug' else 'ok' end as exp; +exp ok Warnings: Warning 1292 Truncated incorrect time value: 'foo' @@ -434,8 +434,8 @@ Warning 1292 Truncated incorrect time value: 'foo' Warning 1292 Truncated incorrect time value: 'foo' Warning 1292 Truncated incorrect time value: 'foo' drop table t1; -select case '20:10:05' when date'2020-10-10' then 'never' when time'20:10:5' then 'ok' else 'bug' end; -case '20:10:05' when date'2020-10-10' then 'never' when time'20:10:5' then 'ok' else 'bug' end +select case '20:10:05' when date'2020-10-10' then 'never' when time'20:10:5' then 'ok' else 'bug' end as exp; +exp ok # # End of 10.2 test diff --git a/mysql-test/main/case.test b/mysql-test/main/case.test index b80408f44d6..10d8aa18db6 100644 --- a/mysql-test/main/case.test +++ b/mysql-test/main/case.test @@ -2,31 +2,29 @@ # Testing of CASE # -#remove this include after fix MDEV-27871 ---source include/no_view_protocol.inc --disable_warnings drop table if exists t1, t2; --enable_warnings -select CASE "b" when "a" then 1 when "b" then 2 END; -select CASE "c" when "a" then 1 when "b" then 2 END; -select CASE "c" when "a" then 1 when "b" then 2 ELSE 3 END; -select CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END; -select CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END; -select CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end; -select CASE when 1=0 then "true" else "false" END; -select CASE 1 when 1 then "one" WHEN 2 then "two" ELSE "more" END; -explain extended select CASE 1 when 1 then "one" WHEN 2 then "two" ELSE "more" END; -select CASE 2.0 when 1 then "one" WHEN 2.0 then "two" ELSE "more" END; -select (CASE "two" when "one" then "1" WHEN "two" then "2" END) | 0; -select (CASE "two" when "one" then 1.00 WHEN "two" then 2.00 END) +0.0; -select case 1/0 when "a" then "true" else "false" END; -select case 1/0 when "a" then "true" END; -select (case 1/0 when "a" then "true" END) | 0; -select (case 1/0 when "a" then "true" END) + 0.0; -select case when 1>0 then "TRUE" else "FALSE" END; -select case when 1<0 then "TRUE" else "FALSE" END; +select CASE "b" when "a" then 1 when "b" then 2 END as exp; +select CASE "c" when "a" then 1 when "b" then 2 END as exp; +select CASE "c" when "a" then 1 when "b" then 2 ELSE 3 END as exp; +select CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END as exp; +select CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END as exp; +select CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end as exp; +select CASE when 1=0 then "true" else "false" END as exp; +select CASE 1 when 1 then "one" WHEN 2 then "two" ELSE "more" END as exp; +explain extended select CASE 1 when 1 then "one" WHEN 2 then "two" ELSE "more" END as exp; +select CASE 2.0 when 1 then "one" WHEN 2.0 then "two" ELSE "more" END as exp; +select (CASE "two" when "one" then "1" WHEN "two" then "2" END) | 0 as exp; +select (CASE "two" when "one" then 1.00 WHEN "two" then 2.00 END) +0.0 as exp; +select case 1/0 when "a" then "true" else "false" END as exp; +select case 1/0 when "a" then "true" END as exp; +select (case 1/0 when "a" then "true" END) | 0 as exp; +select (case 1/0 when "a" then "true" END) + 0.0 as exp; +select case when 1>0 then "TRUE" else "FALSE" END as exp; +select case when 1<0 then "TRUE" else "FALSE" END as exp; # # Test bug when using GROUP BY on CASE @@ -83,10 +81,10 @@ SELECT CASE _latin1'a' COLLATE latin1_general_ci END; SELECT -CASE _latin1'a' COLLATE latin1_general_ci WHEN _latin1'A' THEN '1' ELSE 2 END, -CASE _latin1'a' COLLATE latin1_bin WHEN _latin1'A' THEN '1' ELSE 2 END, -CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_swedish_ci THEN '1' ELSE 2 END, -CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_bin THEN '1' ELSE 2 END +CASE _latin1'a' COLLATE latin1_general_ci WHEN _latin1'A' THEN '1' ELSE 2 END as e1, +CASE _latin1'a' COLLATE latin1_bin WHEN _latin1'A' THEN '1' ELSE 2 END as e2, +CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_swedish_ci THEN '1' ELSE 2 END as e3, +CASE _latin1'a' WHEN _latin1'A' COLLATE latin1_bin THEN '1' ELSE 2 END as e4 ; # @@ -297,7 +295,7 @@ DROP TABLE t1; # # should not convert all values to time -select case 'foo' when time'10:00:00' then 'never' when '0' then 'bug' else 'ok' end; +select case 'foo' when time'10:00:00' then 'never' when '0' then 'bug' else 'ok' end as exp; select 'foo' in (time'10:00:00','0'); create table t1 (a time); @@ -308,7 +306,7 @@ select 'foo' in (a,'0') from t1; drop table t1; # first comparison should be as date, second as time -select case '20:10:05' when date'2020-10-10' then 'never' when time'20:10:5' then 'ok' else 'bug' end; +select case '20:10:05' when date'2020-10-10' then 'never' when time'20:10:5' then 'ok' else 'bug' end as exp; --echo # --echo # End of 10.2 test diff --git a/mysql-test/main/cast.result b/mysql-test/main/cast.result index 2276e73aac6..f154db15bcc 100644 --- a/mysql-test/main/cast.result +++ b/mysql-test/main/cast.result @@ -69,95 +69,95 @@ cast(cast("20:01:01" as time) as datetime) select cast(cast("8:46:06.23434" AS time) as decimal(32,10)); cast(cast("8:46:06.23434" AS time) as decimal(32,10)) 84606.0000000000 -select cast(cast("2011-04-05 8:46:06.23434" AS datetime) as decimal(32,6)); -cast(cast("2011-04-05 8:46:06.23434" AS datetime) as decimal(32,6)) +select cast(cast("2011-04-05 8:46:06.23434" AS datetime) as decimal(32,6)) as exp; +exp 20110405084606.000000 # # Check handling of cast with microseconds # -select cast(cast(20010203101112.121314 as double) as datetime); -cast(cast(20010203101112.121314 as double) as datetime) +select cast(cast(20010203101112.121314 as double) as datetime) as exp; +exp 2001-02-03 10:11:12 -select cast(cast(010203101112.12 as double) as datetime); -cast(cast(010203101112.12 as double) as datetime) +select cast(cast(010203101112.12 as double) as datetime) as exp; +exp 2001-02-03 10:11:12 -select cast(cast(20010203101112.121314 as decimal(32,6)) as datetime); -cast(cast(20010203101112.121314 as decimal(32,6)) as datetime) +select cast(cast(20010203101112.121314 as decimal(32,6)) as datetime) as exp; +exp 2001-02-03 10:11:12 -select cast(20010203101112.121314 as datetime); -cast(20010203101112.121314 as datetime) +select cast(20010203101112.121314 as datetime) as exp; +exp 2001-02-03 10:11:12 -select cast(110203101112.121314 as datetime); -cast(110203101112.121314 as datetime) +select cast(110203101112.121314 as datetime) as exp; +exp 2011-02-03 10:11:12 -select cast(cast(010203101112.12 as double) as datetime); -cast(cast(010203101112.12 as double) as datetime) +select cast(cast(010203101112.12 as double) as datetime) as exp; +exp 2001-02-03 10:11:12 -select cast("2011-02-03 10:11:12.123456" as datetime); -cast("2011-02-03 10:11:12.123456" as datetime) +select cast("2011-02-03 10:11:12.123456" as datetime) as exp; +exp 2011-02-03 10:11:12 -select cast("2011-02-03 10:11:12.123456" as datetime(0)); -cast("2011-02-03 10:11:12.123456" as datetime(0)) +select cast("2011-02-03 10:11:12.123456" as datetime(0)) as exp; +exp 2011-02-03 10:11:12 -select cast("2011-02-03 10:11:12.123456" as datetime(5)); -cast("2011-02-03 10:11:12.123456" as datetime(5)) +select cast("2011-02-03 10:11:12.123456" as datetime(5)) as exp; +exp 2011-02-03 10:11:12.12345 -select cast("2011-02-03 10:11:12.123456" as datetime(6)); -cast("2011-02-03 10:11:12.123456" as datetime(6)) +select cast("2011-02-03 10:11:12.123456" as datetime(6)) as exp; +exp 2011-02-03 10:11:12.123456 -select cast("2011-02-03 10:11:12" as datetime(6)); -cast("2011-02-03 10:11:12" as datetime(6)) +select cast("2011-02-03 10:11:12" as datetime(6)) as exp; +exp 2011-02-03 10:11:12.000000 -select cast(cast(20010203101112.5 as double) as datetime(1)); -cast(cast(20010203101112.5 as double) as datetime(1)) +select cast(cast(20010203101112.5 as double) as datetime(1)) as exp; +exp 2001-02-03 10:11:12.5 -select cast(cast(010203101112.12 as double) as datetime(2)); -cast(cast(010203101112.12 as double) as datetime(2)) +select cast(cast(010203101112.12 as double) as datetime(2)) as exp; +exp 2001-02-03 10:11:12.12 -select cast(cast(20010203101112.121314 as decimal(32,6)) as datetime(6)); -cast(cast(20010203101112.121314 as decimal(32,6)) as datetime(6)) +select cast(cast(20010203101112.121314 as decimal(32,6)) as datetime(6)) as exp; +exp 2001-02-03 10:11:12.121314 -select cast(20010203101112.121314 as datetime(6)); -cast(20010203101112.121314 as datetime(6)) +select cast(20010203101112.121314 as datetime(6)) as exp; +exp 2001-02-03 10:11:12.121314 -select cast(110203101112.121314 as datetime(6)); -cast(110203101112.121314 as datetime(6)) +select cast(110203101112.121314 as datetime(6)) as exp; +exp 2011-02-03 10:11:12.121314 -select cast(cast(010203101112.12 as double) as datetime(6)); -cast(cast(010203101112.12 as double) as datetime(6)) +select cast(cast(010203101112.12 as double) as datetime(6)) as exp; +exp 2001-02-03 10:11:12.120000 -select cast("2011-02-03 10:11:12.123456" as time); -cast("2011-02-03 10:11:12.123456" as time) +select cast("2011-02-03 10:11:12.123456" as time) as exp; +exp 10:11:12 -select cast("2011-02-03 10:11:12.123456" as time(6)); -cast("2011-02-03 10:11:12.123456" as time(6)) +select cast("2011-02-03 10:11:12.123456" as time(6)) as exp; +exp 10:11:12.123456 -select cast("10:11:12.123456" as time); -cast("10:11:12.123456" as time) +select cast("10:11:12.123456" as time) as exp; +exp 10:11:12 -select cast("10:11:12.123456" as time(0)); -cast("10:11:12.123456" as time(0)) +select cast("10:11:12.123456" as time(0)) as exp; +exp 10:11:12 -select cast("10:11:12.123456" as time(5)); -cast("10:11:12.123456" as time(5)) +select cast("10:11:12.123456" as time(5)) as exp; +exp 10:11:12.12345 -select cast("10:11:12.123456" as time(6)); -cast("10:11:12.123456" as time(6)) +select cast("10:11:12.123456" as time(6)) as exp; +exp 10:11:12.123456 -select cast("10:11:12" as time(6)); -cast("10:11:12" as time(6)) +select cast("10:11:12" as time(6)) as exp; +exp 10:11:12.000000 -select cast(cast("2011-04-05 8:46:06.123456" AS datetime) as time); -cast(cast("2011-04-05 8:46:06.123456" AS datetime) as time) +select cast(cast("2011-04-05 8:46:06.123456" AS datetime) as time) as exp; +exp 08:46:06 -select cast(cast("2011-04-05 8:46:06.123456" AS datetime) as time(6)); -cast(cast("2011-04-05 8:46:06.123456" AS datetime) as time(6)) +select cast(cast("2011-04-05 8:46:06.123456" AS datetime) as time(6)) as exp; +exp 08:46:06.000000 -select cast(cast("2011-04-05 8:46:06.123456" AS datetime(6)) as time); -cast(cast("2011-04-05 8:46:06.123456" AS datetime(6)) as time) +select cast(cast("2011-04-05 8:46:06.123456" AS datetime(6)) as time) as exp; +exp 08:46:06 -select cast(cast("2011-04-05 8:46:06.123456" AS datetime(6)) as time(6)); -cast(cast("2011-04-05 8:46:06.123456" AS datetime(6)) as time(6)) +select cast(cast("2011-04-05 8:46:06.123456" AS datetime(6)) as time(6)) as exp; +exp 08:46:06.123456 select cast(NULL as unsigned), cast(1/0 as unsigned); cast(NULL as unsigned) cast(1/0 as unsigned) diff --git a/mysql-test/main/cast.test b/mysql-test/main/cast.test index 073b5fe0be5..478c59a58f7 100644 --- a/mysql-test/main/cast.test +++ b/mysql-test/main/cast.test @@ -2,10 +2,6 @@ # Test of cast function # -#remove this include after fix MDEV-27871 -# discuss what to do with "set names binary" ---source include/no_view_protocol.inc - # For TIME->DATETIME conversion SET timestamp=unix_timestamp('2001-02-03 10:20:30'); @@ -27,41 +23,41 @@ select cast(null as double(5,2)); select cast(12.444 as double); select cast(cast("20:01:01" as time) as datetime); select cast(cast("8:46:06.23434" AS time) as decimal(32,10)); -select cast(cast("2011-04-05 8:46:06.23434" AS datetime) as decimal(32,6)); +select cast(cast("2011-04-05 8:46:06.23434" AS datetime) as decimal(32,6)) as exp; --echo # --echo # Check handling of cast with microseconds --echo # -select cast(cast(20010203101112.121314 as double) as datetime); -select cast(cast(010203101112.12 as double) as datetime); -select cast(cast(20010203101112.121314 as decimal(32,6)) as datetime); -select cast(20010203101112.121314 as datetime); -select cast(110203101112.121314 as datetime); -select cast(cast(010203101112.12 as double) as datetime); +select cast(cast(20010203101112.121314 as double) as datetime) as exp; +select cast(cast(010203101112.12 as double) as datetime) as exp; +select cast(cast(20010203101112.121314 as decimal(32,6)) as datetime) as exp; +select cast(20010203101112.121314 as datetime) as exp; +select cast(110203101112.121314 as datetime) as exp; +select cast(cast(010203101112.12 as double) as datetime) as exp; -select cast("2011-02-03 10:11:12.123456" as datetime); -select cast("2011-02-03 10:11:12.123456" as datetime(0)); -select cast("2011-02-03 10:11:12.123456" as datetime(5)); -select cast("2011-02-03 10:11:12.123456" as datetime(6)); -select cast("2011-02-03 10:11:12" as datetime(6)); -select cast(cast(20010203101112.5 as double) as datetime(1)); -select cast(cast(010203101112.12 as double) as datetime(2)); -select cast(cast(20010203101112.121314 as decimal(32,6)) as datetime(6)); -select cast(20010203101112.121314 as datetime(6)); -select cast(110203101112.121314 as datetime(6)); -select cast(cast(010203101112.12 as double) as datetime(6)); +select cast("2011-02-03 10:11:12.123456" as datetime) as exp; +select cast("2011-02-03 10:11:12.123456" as datetime(0)) as exp; +select cast("2011-02-03 10:11:12.123456" as datetime(5)) as exp; +select cast("2011-02-03 10:11:12.123456" as datetime(6)) as exp; +select cast("2011-02-03 10:11:12" as datetime(6)) as exp; +select cast(cast(20010203101112.5 as double) as datetime(1)) as exp; +select cast(cast(010203101112.12 as double) as datetime(2)) as exp; +select cast(cast(20010203101112.121314 as decimal(32,6)) as datetime(6)) as exp; +select cast(20010203101112.121314 as datetime(6)) as exp; +select cast(110203101112.121314 as datetime(6)) as exp; +select cast(cast(010203101112.12 as double) as datetime(6)) as exp; -select cast("2011-02-03 10:11:12.123456" as time); -select cast("2011-02-03 10:11:12.123456" as time(6)); -select cast("10:11:12.123456" as time); -select cast("10:11:12.123456" as time(0)); -select cast("10:11:12.123456" as time(5)); -select cast("10:11:12.123456" as time(6)); -select cast("10:11:12" as time(6)); -select cast(cast("2011-04-05 8:46:06.123456" AS datetime) as time); -select cast(cast("2011-04-05 8:46:06.123456" AS datetime) as time(6)); -select cast(cast("2011-04-05 8:46:06.123456" AS datetime(6)) as time); -select cast(cast("2011-04-05 8:46:06.123456" AS datetime(6)) as time(6)); +select cast("2011-02-03 10:11:12.123456" as time) as exp; +select cast("2011-02-03 10:11:12.123456" as time(6)) as exp; +select cast("10:11:12.123456" as time) as exp; +select cast("10:11:12.123456" as time(0)) as exp; +select cast("10:11:12.123456" as time(5)) as exp; +select cast("10:11:12.123456" as time(6)) as exp; +select cast("10:11:12" as time(6)) as exp; +select cast(cast("2011-04-05 8:46:06.123456" AS datetime) as time) as exp; +select cast(cast("2011-04-05 8:46:06.123456" AS datetime) as time(6)) as exp; +select cast(cast("2011-04-05 8:46:06.123456" AS datetime(6)) as time) as exp; +select cast(cast("2011-04-05 8:46:06.123456" AS datetime(6)) as time(6)) as exp; # # Bug #28250: Run-Time Check Failure #3 - The variable 'value' is being used @@ -162,7 +158,10 @@ select cast(1 as double(64,63)); # set names binary; select cast(_latin1'test' as char character set latin2); +#enable after MDEV-32461 fix +--disable_view_protocol select cast(_koi8r'ÔÅÓÔ' as char character set cp1251); +--enable_view_protocol create table t1 select cast(_koi8r'ÔÅÓÔ' as char character set cp1251) as t; show create table t1; drop table t1; @@ -170,6 +169,8 @@ drop table t1; # # CAST to CHAR with/without length # +#enable after MDEV-32461 fix +--disable_view_protocol select cast(_latin1'ab' AS char) as c1, cast(_latin1'a ' AS char) as c2, @@ -177,6 +178,7 @@ select cast(_latin1'a ' AS char(2)) as c4, hex(cast(_latin1'a' AS char(2))) as c5; select cast(1000 as CHAR(3)); +--enable_view_protocol SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR create table t1 select @@ -237,12 +239,15 @@ select cast("1:2:3" as TIME) = "1:02:03"; # CREATE TABLE t1 (a enum ('aac','aab','aaa') not null); INSERT INTO t1 VALUES ('aaa'),('aab'),('aac'); +#enable after MDEV-32461 fix +--disable_view_protocol # these two should be in enum order SELECT a, CAST(a AS CHAR) FROM t1 ORDER BY CAST(a AS UNSIGNED) ; SELECT a, CAST(a AS CHAR(3)) FROM t1 ORDER BY CAST(a AS CHAR(2)), a; # these two should be in alphabetic order SELECT a, CAST(a AS UNSIGNED) FROM t1 ORDER BY CAST(a AS CHAR) ; SELECT a, CAST(a AS CHAR(2)) FROM t1 ORDER BY CAST(a AS CHAR(3)), a; +--enable_view_protocol DROP TABLE t1; # @@ -344,9 +349,12 @@ select cast(NULL as decimal(6)) as t1; # Bug #17903: cast to char results in binary # set names latin1; +#enable after MDEV-32461 fix +--disable_view_protocol select hex(cast('a' as char(2) binary)); select hex(cast('a' as binary(2))); select hex(cast('a' as char(2) binary)); +--enable_view_protocol # # Bug#29898: Item_date_typecast::val_int doesn't reset the null_value flag. @@ -476,11 +484,14 @@ drop table t1; # # CAST (... BINARY) # +#enable after MDEV-32461 fix +--disable_view_protocol select collation(cast("a" as char(10) binary)); select collation(cast("a" as char(10) charset utf8 binary)); select collation(cast("a" as char(10) ascii binary)); select collation(cast("a" as char(10) binary charset utf8)); select collation(cast("a" as char(10) binary ascii)); +--enable_view_protocol --echo # --echo # MDEV-11030 Assertion `precision > 0' failed in decimal_bin_size @@ -762,7 +773,10 @@ INSERT INTO t1 VALUES (-1.0); SELECT * FROM t1; DROP TABLE t1; +#enable after MDEV-32461 fix +--disable_view_protocol SELECT CAST(-1e0 AS UNSIGNED); +--enable_view_protocol CREATE TABLE t1 (a BIGINT UNSIGNED); INSERT INTO t1 VALUES (-1e0); SELECT * FROM t1; diff --git a/mysql-test/main/ctype_collate.result b/mysql-test/main/ctype_collate.result index 1ae9f295042..ea9e3e96b46 100644 --- a/mysql-test/main/ctype_collate.result +++ b/mysql-test/main/ctype_collate.result @@ -641,8 +641,8 @@ check table t1 extended; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; -select least(_latin1'a',_latin2'b',_latin5'c' collate latin5_turkish_ci); -least(_latin1'a',_latin2'b',_latin5'c' collate latin5_turkish_ci) +select least(_latin1'a',_latin2'b',_latin5'c' collate latin5_turkish_ci) as f1; +f1 a create table t1 select least(_latin1'a',_latin2'b',_latin5'c' collate latin5_turkish_ci) as f1; @@ -653,12 +653,11 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; select case _latin1'a' when _latin2'b' then 1 when _latin5'c' collate -latin5_turkish_ci then 2 else 3 end; -case _latin1'a' when _latin2'b' then 1 when _latin5'c' collate -latin5_turkish_ci then 2 else 3 end +latin5_turkish_ci then 2 else 3 end as exp; +exp 3 -select concat(_latin1'a',_latin2'b',_latin5'c' collate latin5_turkish_ci); -concat(_latin1'a',_latin2'b',_latin5'c' collate latin5_turkish_ci) +select concat(_latin1'a',_latin2'b',_latin5'c' collate latin5_turkish_ci) as exp; +exp abc # # Bug#11765016 57926: ILLEGAL MIX OF COLLATIONS FOR OPERATION 'UNION' .. USING CONCAT/FUNCTION/ diff --git a/mysql-test/main/ctype_collate.test b/mysql-test/main/ctype_collate.test index ab79a6cd51a..2366b130e7c 100644 --- a/mysql-test/main/ctype_collate.test +++ b/mysql-test/main/ctype_collate.test @@ -1,5 +1,3 @@ -#remove this include after fix MDEV-27871 ---source include/no_view_protocol.inc --disable_warnings DROP TABLE IF EXISTS t1; @@ -248,16 +246,16 @@ drop table t1; # # Bug#41627 Illegal mix of collations in LEAST / GREATEST / CASE # -select least(_latin1'a',_latin2'b',_latin5'c' collate latin5_turkish_ci); +select least(_latin1'a',_latin2'b',_latin5'c' collate latin5_turkish_ci) as f1; create table t1 select least(_latin1'a',_latin2'b',_latin5'c' collate latin5_turkish_ci) as f1; show create table t1; drop table t1; select case _latin1'a' when _latin2'b' then 1 when _latin5'c' collate -latin5_turkish_ci then 2 else 3 end; +latin5_turkish_ci then 2 else 3 end as exp; -select concat(_latin1'a',_latin2'b',_latin5'c' collate latin5_turkish_ci); +select concat(_latin1'a',_latin2'b',_latin5'c' collate latin5_turkish_ci) as exp; --echo # diff --git a/mysql-test/main/ctype_eucjpms.test b/mysql-test/main/ctype_eucjpms.test index f144f5566f3..2d669bb0fc0 100644 --- a/mysql-test/main/ctype_eucjpms.test +++ b/mysql-test/main/ctype_eucjpms.test @@ -1,6 +1,4 @@ # remove this include in 10.6 version, -# if MDEV-27871 will be fix ---source include/no_view_protocol.inc -- source include/have_eucjpms.inc diff --git a/mysql-test/main/ctype_gbk.result b/mysql-test/main/ctype_gbk.result index c16be59ae99..b5ea45a5070 100644 --- a/mysql-test/main/ctype_gbk.result +++ b/mysql-test/main/ctype_gbk.result @@ -5954,13 +5954,13 @@ DROP TABLE t1; # MDEV-7661 Unexpected result for: CAST(0xHHHH AS CHAR CHARACTER SET xxx) for incorrect byte sequences # set sql_mode=''; -SELECT HEX(CAST(0xA341 AS CHAR CHARACTER SET gb2312)); -HEX(CAST(0xA341 AS CHAR CHARACTER SET gb2312)) +SELECT HEX(CAST(0xA341 AS CHAR CHARACTER SET gb2312)) as exp; +exp 3F41 Warnings: Warning 1300 Invalid gb2312 character string: '\xA3A' -SELECT HEX(CONVERT(CAST(0xA341 AS CHAR CHARACTER SET gb2312) USING utf8)); -HEX(CONVERT(CAST(0xA341 AS CHAR CHARACTER SET gb2312) USING utf8)) +SELECT HEX(CONVERT(CAST(0xA341 AS CHAR CHARACTER SET gb2312) USING utf8)) as exp; +exp 3F41 Warnings: Warning 1300 Invalid gb2312 character string: '\xA3A' diff --git a/mysql-test/main/ctype_gbk.test b/mysql-test/main/ctype_gbk.test index 1c672a89e41..9e93be1f5ba 100644 --- a/mysql-test/main/ctype_gbk.test +++ b/mysql-test/main/ctype_gbk.test @@ -449,8 +449,8 @@ DROP TABLE t1; #enable after fix MDEV-27871 --disable_view_protocol set sql_mode=''; -SELECT HEX(CAST(0xA341 AS CHAR CHARACTER SET gb2312)); -SELECT HEX(CONVERT(CAST(0xA341 AS CHAR CHARACTER SET gb2312) USING utf8)); +SELECT HEX(CAST(0xA341 AS CHAR CHARACTER SET gb2312)) as exp; +SELECT HEX(CONVERT(CAST(0xA341 AS CHAR CHARACTER SET gb2312) USING utf8)) as exp; set sql_mode=default; --enable_view_protocol diff --git a/mysql-test/main/ctype_sjis.test b/mysql-test/main/ctype_sjis.test index 1bb1e423687..c1fcb0a870a 100644 --- a/mysql-test/main/ctype_sjis.test +++ b/mysql-test/main/ctype_sjis.test @@ -209,9 +209,6 @@ DROP TABLE t1; --echo # WL#3664 WEIGHT_STRING --echo # -# enable view-protocol after fix MDEV-27871 ---disable_view_protocol - set names sjis; --source include/weight_string.inc --source include/weight_string_l1.inc @@ -223,8 +220,6 @@ set collation_connection=sjis_bin; --source include/weight_string_l1.inc --source include/weight_string_8140.inc ---enable_view_protocol - --echo # --echo # End of 5.6 tests --echo # diff --git a/mysql-test/main/ctype_uca.result b/mysql-test/main/ctype_uca.result index 2298733851d..0ab995993ac 100644 --- a/mysql-test/main/ctype_uca.result +++ b/mysql-test/main/ctype_uca.result @@ -7964,8 +7964,8 @@ hex(weight_string(cast(_latin1 0xDF6368 as char),25, 4,0xC0)) # # Bug#33077 weight of supplementary characters is not 0xfffd # -select hex(weight_string(_utf8mb4 0xF0908080 /* U+10000 */ collate utf8mb4_unicode_ci)); -hex(weight_string(_utf8mb4 0xF0908080 /* U+10000 */ collate utf8mb4_unicode_ci)) +select hex(weight_string(_utf8mb4 0xF0908080 /* U+10000 */ collate utf8mb4_unicode_ci)) as exp; +exp FFFD # # Bug#53064 garbled data when using utf8_german2_ci collation diff --git a/mysql-test/main/ctype_uca.test b/mysql-test/main/ctype_uca.test index 1b7474428c1..6ac86e9942e 100644 --- a/mysql-test/main/ctype_uca.test +++ b/mysql-test/main/ctype_uca.test @@ -552,10 +552,7 @@ set @@collation_connection=ucs2_czech_ci; --echo # --echo # Bug#33077 weight of supplementary characters is not 0xfffd --echo # -#enable_after_fix MDEV-27871 ---disable_view_protocol -select hex(weight_string(_utf8mb4 0xF0908080 /* U+10000 */ collate utf8mb4_unicode_ci)); ---enable_view_protocol +select hex(weight_string(_utf8mb4 0xF0908080 /* U+10000 */ collate utf8mb4_unicode_ci)) as exp; --echo # --echo # Bug#53064 garbled data when using utf8_german2_ci collation diff --git a/mysql-test/main/dyncol.result b/mysql-test/main/dyncol.result index 0febe6057f0..6135be649b2 100644 --- a/mysql-test/main/dyncol.result +++ b/mysql-test/main/dyncol.result @@ -1,20 +1,20 @@ # # column create # -select hex(COLUMN_CREATE(1, NULL AS char character set utf8)); -hex(COLUMN_CREATE(1, NULL AS char character set utf8)) +select hex(COLUMN_CREATE(1, NULL AS char character set utf8)) as exp; +exp 000000 -select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8)); -hex(COLUMN_CREATE(1, "afaf" AS char character set utf8)) +select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8)) as ex; +ex 0001000100032161666166 -select hex(COLUMN_CREATE(1, 1212 AS char character set utf8)); -hex(COLUMN_CREATE(1, 1212 AS char character set utf8)) +select hex(COLUMN_CREATE(1, 1212 AS char character set utf8)) as ex; +ex 0001000100032131323132 -select hex(COLUMN_CREATE(1, 12.12 AS char character set utf8)); -hex(COLUMN_CREATE(1, 12.12 AS char character set utf8)) +select hex(COLUMN_CREATE(1, 12.12 AS char character set utf8)) as ex; +ex 0001000100032131322E3132 -select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS char character set utf8)); -hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS char character set utf8)) +select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS char character set utf8)) as ex; +ex 000100010003213939393939393939393939393939393939393939393939393939393939 select hex(COLUMN_CREATE(1, NULL AS unsigned int)); hex(COLUMN_CREATE(1, NULL AS unsigned int)) @@ -43,8 +43,8 @@ hex(COLUMN_CREATE(1, ~0)) select hex(COLUMN_CREATE(1, -1)); hex(COLUMN_CREATE(1, -1)) 00010001000001 -select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS unsigned int)); -hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS unsigned int)) +select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS unsigned int)) as ex; +ex 000100010001FFFFFFFFFFFFFF7F Warnings: Warning 1916 Got overflow when converting '99999999999999999999999999999' to INT. Value truncated @@ -69,8 +69,8 @@ hex(COLUMN_CREATE(1, 128 AS int)) select hex(COLUMN_CREATE(1, 12.12 AS int)); hex(COLUMN_CREATE(1, 12.12 AS int)) 00010001000018 -select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS int)); -hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS int)) +select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS int)) as ex; +ex 000100010000FEFFFFFFFFFFFFFF Warnings: Warning 1916 Got overflow when converting '99999999999999999999999999999' to INT. Value truncated @@ -83,8 +83,8 @@ hex(COLUMN_CREATE(1, 1212 AS double)) select hex(COLUMN_CREATE(1, 12.12 AS double)); hex(COLUMN_CREATE(1, 12.12 AS double)) 0001000100023D0AD7A3703D2840 -select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS double)); -hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS double)) +select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS double)) as ex; +ex 00010001000221D7E6FAE031F445 select hex(COLUMN_CREATE(1, NULL AS decimal)); hex(COLUMN_CREATE(1, NULL AS decimal)) @@ -107,8 +107,8 @@ hex(COLUMN_CREATE(1, 128 AS decimal)) select hex(COLUMN_CREATE(1, 12.12 AS decimal)); hex(COLUMN_CREATE(1, 12.12 AS decimal)) 00010001000402028C0C -select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS decimal)); -hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS decimal)) +select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS decimal)) as ex; +ex 0001000100041D00E33B9AC9FF3B9AC9FF3B9AC9FF select hex(COLUMN_CREATE(1, NULL AS date)); hex(COLUMN_CREATE(1, NULL AS date)) @@ -125,8 +125,8 @@ hex(COLUMN_CREATE(1, "0:45:49.000001" AS time)) select hex(COLUMN_CREATE(1, NULL AS datetime)); hex(COLUMN_CREATE(1, NULL AS datetime)) 000000 -select hex(COLUMN_CREATE(1, "2011-04-05 0:45:49.000001" AS datetime)); -hex(COLUMN_CREATE(1, "2011-04-05 0:45:49.000001" AS datetime)) +select hex(COLUMN_CREATE(1, "2011-04-05 0:45:49.000001" AS datetime)) as ex; +ex 00010001000585B60F010010B70000 select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8, 2, 1212 AS unsigned int, @@ -135,15 +135,8 @@ select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8, 4+1, 12.12 AS decimal, 6, "2011-04-05" AS date, 7, "- 0:45:49.000001" AS time, -8, "2011-04-05 0:45:49.000001" AS datetime)); -hex(COLUMN_CREATE(1, "afaf" AS char character set utf8, -2, 1212 AS unsigned int, -3, 1212 AS int, -4, 12.12 AS double, -4+1, 12.12 AS decimal, -6, "2011-04-05" AS date, -7, "- 0:45:49.000001" AS time, -8, "2011-04-05 0:45:49.000001" AS datetime)) +8, "2011-04-05 0:45:49.000001" AS datetime)) as ex; +ex 01080001000300020029000300380004004A0005008C000600AE000700C7000800F5002161666166BC0478093D0AD7A3703D284002028C0C85B60F010010B7000485B60F010010B70000 explain extended select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8, @@ -153,18 +146,11 @@ select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8, 4+1, 12.12 AS decimal, 6, "2011-04-05" AS date, 7, "- 0:45:49.000001" AS time, -8, "2011-04-05 0:45:49.000001" AS datetime)); +8, "2011-04-05 0:45:49.000001" AS datetime)) as ex; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select hex(column_create(1,'afaf' AS char charset utf8 ,2,1212 AS unsigned int,3,1212 AS int,4,12.12 AS double,4 + 1,12.12 AS decimal,6,'2011-04-05' AS date,7,'- 0:45:49.000001' AS time,8,'2011-04-05 0:45:49.000001' AS datetime)) AS `hex(COLUMN_CREATE(1, "afaf" AS char character set utf8, -2, 1212 AS unsigned int, -3, 1212 AS int, -4, 12.12 AS double, -4+1, 12.12 AS decimal, -6, "2011-04-05" AS date, -7, "- 0:45:49.000001" AS time, -8, "2011-04-05 0:45:49.000001" AS datetime))` +Note 1003 select hex(column_create(1,'afaf' AS char charset utf8 ,2,1212 AS unsigned int,3,1212 AS int,4,12.12 AS double,4 + 1,12.12 AS decimal,6,'2011-04-05' AS date,7,'- 0:45:49.000001' AS time,8,'2011-04-05 0:45:49.000001' AS datetime)) AS `ex` select hex(column_create(1, 0.0 AS decimal)); hex(column_create(1, 0.0 AS decimal)) 000100010004 @@ -174,969 +160,969 @@ hex(column_create(1, 1.0 AS decimal)) # # column get uint # -select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int); -column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int) +select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int) as ex; +ex 1212 explain extended -select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int); +select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int) as ex; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select column_get(column_create(1,1212 AS unsigned int),1 as unsigned) AS `column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int)` +Note 1003 select column_get(column_create(1,1212 AS unsigned int),1 as unsigned) AS `ex` explain extended -select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned); +select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned) as ex; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select column_get(column_create(1,1212 AS unsigned int),1 as unsigned) AS `column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned)` -select column_get(column_create(1, 1212 AS decimal), 1 as unsigned int); -column_get(column_create(1, 1212 AS decimal), 1 as unsigned int) +Note 1003 select column_get(column_create(1,1212 AS unsigned int),1 as unsigned) AS `ex` +select column_get(column_create(1, 1212 AS decimal), 1 as unsigned int) as ex; +ex 1212 -select column_get(column_create(1, 1212 AS double), 1 as unsigned int); -column_get(column_create(1, 1212 AS double), 1 as unsigned int) +select column_get(column_create(1, 1212 AS double), 1 as unsigned int) as ex; +ex 1212 -select column_get(column_create(1, 1212 AS int), 1 as unsigned int); -column_get(column_create(1, 1212 AS int), 1 as unsigned int) +select column_get(column_create(1, 1212 AS int), 1 as unsigned int) as ex; +ex 1212 -select column_get(column_create(1, "1212" AS char), 1 as unsigned int); -column_get(column_create(1, "1212" AS char), 1 as unsigned int) +select column_get(column_create(1, "1212" AS char), 1 as unsigned int) as ex; +ex 1212 -select column_get(column_create(1, "2011-04-05" AS date), 1 as unsigned int); -column_get(column_create(1, "2011-04-05" AS date), 1 as unsigned int) +select column_get(column_create(1, "2011-04-05" AS date), 1 as unsigned int) as ex; +ex 20110405 -select column_get(column_create(1, "8:46:06.23434" AS time), 1 as unsigned int); -column_get(column_create(1, "8:46:06.23434" AS time), 1 as unsigned int) +select column_get(column_create(1, "8:46:06.23434" AS time), 1 as unsigned int) as ex; +ex 84606 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as unsigned int); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as unsigned int) +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as unsigned int) as ex; +ex 20110405084606 -select column_get(column_create(1, NULL AS unsigned int), 1 as unsigned int); -column_get(column_create(1, NULL AS unsigned int), 1 as unsigned int) +select column_get(column_create(1, NULL AS unsigned int), 1 as unsigned int) as ex; +ex NULL # column geint truncation & warnings -select column_get(column_create(1, -1212 AS int), 1 as unsigned int); -column_get(column_create(1, -1212 AS int), 1 as unsigned int) +select column_get(column_create(1, -1212 AS int), 1 as unsigned int) as ex; +ex 18446744073709550404 Warnings: Note 1105 Cast to unsigned converted negative integer to it's positive complement -select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as unsigned int); -column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as unsigned int) +select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as unsigned int) as ex; +ex 18446744073709551615 Warnings: Warning 1916 Got overflow when converting '99999999999999999999999999999' to UNSIGNED INT. Value truncated -select column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as unsigned int); -column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as unsigned int) +select column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as unsigned int) as ex; +ex 1000 -select column_get(column_create(1, -1 AS decimal), 1 as unsigned int); -column_get(column_create(1, -1 AS decimal), 1 as unsigned int) +select column_get(column_create(1, -1 AS decimal), 1 as unsigned int) as ex; +ex 0 Warnings: Warning 1916 Got overflow when converting '-1' to UNSIGNED INT. Value truncated -select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as unsigned int); -column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as unsigned int) +select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as unsigned int) as ex; +ex 18446744073709551615 Warnings: Warning 1916 Got overflow when converting '1e29' to UNSIGNED INT. Value truncated -select column_get(column_create(1, 999.9 AS double), 1 as unsigned int); -column_get(column_create(1, 999.9 AS double), 1 as unsigned int) +select column_get(column_create(1, 999.9 AS double), 1 as unsigned int) as ex; +ex 1000 -select column_get(column_create(1, -1 AS double), 1 as unsigned int); -column_get(column_create(1, -1 AS double), 1 as unsigned int) +select column_get(column_create(1, -1 AS double), 1 as unsigned int) as ex; +ex 0 Warnings: Warning 1916 Got overflow when converting '-1' to UNSIGNED INT. Value truncated -select column_get(column_create(1, "1212III" AS char), 1 as unsigned int); -column_get(column_create(1, "1212III" AS char), 1 as unsigned int) +select column_get(column_create(1, "1212III" AS char), 1 as unsigned int) as ex; +ex 1212 Warnings: Warning 1918 Encountered illegal value '1212III' when converting to UNSIGNED INT # # column get int # -select column_get(column_create(1, 1212 AS int), 1 as int); -column_get(column_create(1, 1212 AS int), 1 as int) +select column_get(column_create(1, 1212 AS int), 1 as int) as ex; +ex 1212 explain extended -select column_get(column_create(1, 1212 AS int), 1 as int); +select column_get(column_create(1, 1212 AS int), 1 as int) as ex; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select column_get(column_create(1,1212 AS int),1 as signed) AS `column_get(column_create(1, 1212 AS int), 1 as int)` +Note 1003 select column_get(column_create(1,1212 AS int),1 as signed) AS `ex` explain extended -select column_get(column_create(1, 1212 AS int), 1 as signed int); +select column_get(column_create(1, 1212 AS int), 1 as signed int) as ex; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select column_get(column_create(1,1212 AS int),1 as signed) AS `column_get(column_create(1, 1212 AS int), 1 as signed int)` -select column_get(column_create(1, -1212 AS int), 1 as int); -column_get(column_create(1, -1212 AS int), 1 as int) +Note 1003 select column_get(column_create(1,1212 AS int),1 as signed) AS `ex` +select column_get(column_create(1, -1212 AS int), 1 as int) as ex; +ex -1212 -select column_get(column_create(1, 1212 AS decimal), 1 as int); -column_get(column_create(1, 1212 AS decimal), 1 as int) +select column_get(column_create(1, 1212 AS decimal), 1 as int) as ex; +ex 1212 -select column_get(column_create(1, 1212 AS double), 1 as int); -column_get(column_create(1, 1212 AS double), 1 as int) +select column_get(column_create(1, 1212 AS double), 1 as int) as ex; +ex 1212 -select column_get(column_create(1, 1212 AS unsigned int), 1 as int); -column_get(column_create(1, 1212 AS unsigned int), 1 as int) +select column_get(column_create(1, 1212 AS unsigned int), 1 as int) as ex; +ex 1212 -select column_get(column_create(1, "1212" AS char), 1 as int); -column_get(column_create(1, "1212" AS char), 1 as int) +select column_get(column_create(1, "1212" AS char), 1 as int) as ex; +ex 1212 -select column_get(column_create(1, "-1212" AS char), 1 as int); -column_get(column_create(1, "-1212" AS char), 1 as int) +select column_get(column_create(1, "-1212" AS char), 1 as int) as ex; +ex -1212 -select column_get(column_create(1, "2011-04-05" AS date), 1 as int); -column_get(column_create(1, "2011-04-05" AS date), 1 as int) +select column_get(column_create(1, "2011-04-05" AS date), 1 as int) as ex; +ex 20110405 -select column_get(column_create(1, "8:46:06.23434" AS time), 1 as int); -column_get(column_create(1, "8:46:06.23434" AS time), 1 as int) +select column_get(column_create(1, "8:46:06.23434" AS time), 1 as int) as ex; +ex 84606 -select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as int); -column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as int) +select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as int) as ex; +ex 84606 -select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as int); -column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as int) +select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as int) as ex; +ex -8084606 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as int); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as int) +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as int) as ex; +ex 20110405084606 -select column_get(column_create(1, NULL AS int), 1 as int); -column_get(column_create(1, NULL AS int), 1 as int) +select column_get(column_create(1, NULL AS int), 1 as int) as ex; +ex NULL #column gett truncation & warnings -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as int); -column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as int) +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as int) as ex; +ex -1 Warnings: Note 1105 Cast to signed converted positive out-of-range integer to it's negative complement -select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as int); -column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as int) +select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as int) as ex; +ex 9223372036854775807 Warnings: Warning 1916 Got overflow when converting '99999999999999999999999999999' to INT. Value truncated -select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as int); -column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as int) +select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as int) as ex; +ex -9223372036854775808 Warnings: Warning 1916 Got overflow when converting '-99999999999999999999999999999' to INT. Value truncated -select column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as int); -column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as int) +select column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as int) as ex; +ex 1000 -select column_get(column_create(1, 999.9 AS double), 1 as int); -column_get(column_create(1, 999.9 AS double), 1 as int) +select column_get(column_create(1, 999.9 AS double), 1 as int) as ex; +ex 1000 -select column_get(column_create(1, -99999999999999999999999999999 AS double), 1 as int); -column_get(column_create(1, -99999999999999999999999999999 AS double), 1 as int) +select column_get(column_create(1, -99999999999999999999999999999 AS double), 1 as int) as ex; +ex -9223372036854775808 Warnings: Warning 1916 Got overflow when converting '-1e29' to INT. Value truncated -select column_get(column_create(1, "-1212III" AS char), 1 as int); -column_get(column_create(1, "-1212III" AS char), 1 as int) +select column_get(column_create(1, "-1212III" AS char), 1 as int) as ex; +ex -1212 Warnings: Warning 1918 Encountered illegal value '-1212III' when converting to INT -select column_get(column_create(1, "1212III" AS char), 1 as int); -column_get(column_create(1, "1212III" AS char), 1 as int) +select column_get(column_create(1, "1212III" AS char), 1 as int) as ex; +ex 1212 Warnings: Warning 1918 Encountered illegal value '1212III' when converting to INT -select column_get(COLUMN_CREATE(1, ~0), 1 as signed); -column_get(COLUMN_CREATE(1, ~0), 1 as signed) +select column_get(COLUMN_CREATE(1, ~0), 1 as signed) as ex; +ex -1 Warnings: Note 1105 Cast to signed converted positive out-of-range integer to it's negative complement -select column_get(COLUMN_CREATE(1, ~0), 1 as unsigned); -column_get(COLUMN_CREATE(1, ~0), 1 as unsigned) +select column_get(COLUMN_CREATE(1, ~0), 1 as unsigned) as ex; +ex 18446744073709551615 -select column_get(COLUMN_CREATE(1, -1), 1 as signed); -column_get(COLUMN_CREATE(1, -1), 1 as signed) +select column_get(COLUMN_CREATE(1, -1), 1 as signed) as ex; +ex -1 -select column_get(COLUMN_CREATE(1, -1), 1 as unsigned); -column_get(COLUMN_CREATE(1, -1), 1 as unsigned) +select column_get(COLUMN_CREATE(1, -1), 1 as unsigned) as ex; +ex 18446744073709551615 Warnings: Note 1105 Cast to unsigned converted negative integer to it's positive complement # #column get char # -select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8); -column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8) +select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8) as ex; +ex 1212 explain extended -select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8); +select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8) as ex; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select column_get(column_create(1,'1212' AS char charset utf8 ),1 as char charset utf8) AS `column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8)` -select column_get(column_create(1, 1212 AS unsigned int), 1 as char charset utf8); -column_get(column_create(1, 1212 AS unsigned int), 1 as char charset utf8) +Note 1003 select column_get(column_create(1,'1212' AS char charset utf8 ),1 as char charset utf8) AS `ex` +select column_get(column_create(1, 1212 AS unsigned int), 1 as char charset utf8) as ex; +ex 1212 -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as char charset utf8); -column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as char charset utf8) +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as char charset utf8) as ex; +ex 18446744073709551615 -select column_get(column_create(1, 1212 AS int), 1 as char charset utf8); -column_get(column_create(1, 1212 AS int), 1 as char charset utf8) +select column_get(column_create(1, 1212 AS int), 1 as char charset utf8) as ex; +ex 1212 -select column_get(column_create(1, -1212 AS int), 1 as char charset utf8); -column_get(column_create(1, -1212 AS int), 1 as char charset utf8) +select column_get(column_create(1, -1212 AS int), 1 as char charset utf8) as ex; +ex -1212 -select column_get(column_create(1, 9223372036854775807 AS int), 1 as char charset utf8); -column_get(column_create(1, 9223372036854775807 AS int), 1 as char charset utf8) +select column_get(column_create(1, 9223372036854775807 AS int), 1 as char charset utf8) as ex; +ex 9223372036854775807 -select column_get(column_create(1, -9223372036854775808 AS int), 1 as char charset utf8); -column_get(column_create(1, -9223372036854775808 AS int), 1 as char charset utf8) +select column_get(column_create(1, -9223372036854775808 AS int), 1 as char charset utf8) as ex; +ex -9223372036854775808 -select column_get(column_create(1, 1212.12 AS decimal), 1 as char charset utf8); -column_get(column_create(1, 1212.12 AS decimal), 1 as char charset utf8) +select column_get(column_create(1, 1212.12 AS decimal), 1 as char charset utf8) as ex; +ex 1212.12 -select column_get(column_create(1, 1212.12 AS double), 1 as char charset utf8); -column_get(column_create(1, 1212.12 AS double), 1 as char charset utf8) +select column_get(column_create(1, 1212.12 AS double), 1 as char charset utf8) as ex; +ex 1212.12 -select column_get(column_create(1, "2011-04-05" AS date), 1 as char charset utf8); -column_get(column_create(1, "2011-04-05" AS date), 1 as char charset utf8) +select column_get(column_create(1, "2011-04-05" AS date), 1 as char charset utf8) as ex; +ex 2011-04-05 -select column_get(column_create(1, "8:46:06.23434" AS time), 1 as char charset utf8); -column_get(column_create(1, "8:46:06.23434" AS time), 1 as char charset utf8) +select column_get(column_create(1, "8:46:06.23434" AS time), 1 as char charset utf8) as ex; +ex 08:46:06.234340 -select column_get(column_create(1, "8:46:06.23434" AS time(0)), 1 as char charset utf8); -column_get(column_create(1, "8:46:06.23434" AS time(0)), 1 as char charset utf8) +select column_get(column_create(1, "8:46:06.23434" AS time(0)), 1 as char charset utf8) as ex; +ex 08:46:06.234340 -select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as char charset utf8); -column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as char charset utf8) +select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as char charset utf8) as ex; +ex 08:46:06.234340 -select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as char charset utf8); -column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as char charset utf8) +select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as char charset utf8) as ex; +ex -808:46:06.234340 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as char charset utf8); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as char charset utf8) +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as char charset utf8) as ex; +ex 2011-04-05 08:46:06.234340 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(0)), 1 as char charset utf8); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(0)), 1 as char charset utf8) +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(0)), 1 as char charset utf8) as ex; +ex 2011-04-05 08:46:06.234340 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as char charset utf8); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as char charset utf8) +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as char charset utf8) as ex; +ex 2011-04-05 08:46:06.234340 -select column_get(column_create(1, NULL AS char charset utf8), 1 as char charset utf8); -column_get(column_create(1, NULL AS char charset utf8), 1 as char charset utf8) +select column_get(column_create(1, NULL AS char charset utf8), 1 as char charset utf8) as ex; +ex NULL -select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary); -column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary) +select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary) as ex; +ex 1212 explain extended -select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary); +select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary) as ex; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select column_get(column_create(1,'1212' AS char charset utf8 ),1 as char charset binary) AS `column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary)` +Note 1003 select column_get(column_create(1,'1212' AS char charset utf8 ),1 as char charset binary) AS `ex` # # column get real # -select column_get(column_create(1, 1212.12 AS double), 1 as double); -column_get(column_create(1, 1212.12 AS double), 1 as double) +select column_get(column_create(1, 1212.12 AS double), 1 as double) as ex; +ex 1212.12 explain extended -select column_get(column_create(1, 1212.12 AS double), 1 as double); +select column_get(column_create(1, 1212.12 AS double), 1 as double) as ex; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select column_get(column_create(1,1212.12 AS double),1 as double) AS `column_get(column_create(1, 1212.12 AS double), 1 as double)` +Note 1003 select column_get(column_create(1,1212.12 AS double),1 as double) AS `ex` explain extended -select column_get(column_create(1, 1212.12 AS double), 1 as double(6,2)); +select column_get(column_create(1, 1212.12 AS double), 1 as double(6,2)) as ex; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select column_get(column_create(1,1212.12 AS double),1 as double(6,2)) AS `column_get(column_create(1, 1212.12 AS double), 1 as double(6,2))` -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as double); -column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as double) +Note 1003 select column_get(column_create(1,1212.12 AS double),1 as double(6,2)) AS `ex` +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as double) as ex; +ex 1.8446744073709552e19 -select column_get(column_create(1, 9223372036854775807 AS int), 1 as double); -column_get(column_create(1, 9223372036854775807 AS int), 1 as double) +select column_get(column_create(1, 9223372036854775807 AS int), 1 as double) as ex; +ex 9.223372036854776e18 -select column_get(column_create(1, -9223372036854775808 AS int), 1 as double); -column_get(column_create(1, -9223372036854775808 AS int), 1 as double) +select column_get(column_create(1, -9223372036854775808 AS int), 1 as double) as ex; +ex -9.223372036854776e18 -select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as double); -column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as double) +select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as double) as ex; +ex 1e29 -select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as double); -column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as double) +select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as double) as ex; +ex -1e29 -select column_get(column_create(1, "2011-04-05" AS date), 1 as double); -column_get(column_create(1, "2011-04-05" AS date), 1 as double) +select column_get(column_create(1, "2011-04-05" AS date), 1 as double) as ex; +ex 20110405 -select column_get(column_create(1, "8:46:06.23434" AS time), 1 as double); -column_get(column_create(1, "8:46:06.23434" AS time), 1 as double) +select column_get(column_create(1, "8:46:06.23434" AS time), 1 as double) as ex; +ex 84606.23434 -select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as double); -column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as double) +select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as double) as ex; +ex 84606.23434 -select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as double); -column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as double) +select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as double) as ex; +ex -8084606.23434 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double) +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double) as ex; +ex 20110405084606.234 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as double); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as double) +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as double) as ex; +ex 20110405084606.234 -select round(column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double(20,6)),3); -round(column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double(20,6)),3) +select round(column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double(20,6)),3) as ex; +ex 20110405084606.234 -select column_get(column_create(1, NULL AS double), 1 as double); -column_get(column_create(1, NULL AS double), 1 as double) +select column_get(column_create(1, NULL AS double), 1 as double) as ex; +ex NULL # column get real truncation & warnings -select column_get(column_create(1, "1223.5aa" AS char), 1 as double); -column_get(column_create(1, "1223.5aa" AS char), 1 as double) +select column_get(column_create(1, "1223.5aa" AS char), 1 as double) as ex; +ex 1223.5 Warnings: Warning 1918 Encountered illegal value '1223.5aa' when converting to DOUBLE -select column_get(column_create(1, "aa" AS char), 1 as double); -column_get(column_create(1, "aa" AS char), 1 as double) +select column_get(column_create(1, "aa" AS char), 1 as double) as ex; +ex 0 Warnings: Warning 1918 Encountered illegal value 'aa' when converting to DOUBLE -select column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2)); -column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2)) +select column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2)) as ex; +ex 999.99 Warnings: -Note 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2))' at row 1 -select column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2)); -column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2)) +Note 1264 Out of range value for column 'ex' at row 1 +select column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2)) as ex; +ex 9.99 Warnings: -Note 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2))' at row 1 +Note 1264 Out of range value for column 'ex' at row 1 # # column get decimal # -select column_get(column_create(1, 1212.12 AS double), 1 as decimal); -column_get(column_create(1, 1212.12 AS double), 1 as decimal) +select column_get(column_create(1, 1212.12 AS double), 1 as decimal) as ex; +ex 1212 -select column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2)); -column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2)) +select column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2)) as ex; +ex 1212.12 explain extended -select column_get(column_create(1, 1212.12 AS double), 1 as decimal); +select column_get(column_create(1, 1212.12 AS double), 1 as decimal) as ex; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select column_get(column_create(1,1212.12 AS double),1 as decimal(10,0)) AS `column_get(column_create(1, 1212.12 AS double), 1 as decimal)` +Note 1003 select column_get(column_create(1,1212.12 AS double),1 as decimal(10,0)) AS `ex` explain extended -select column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2)); +select column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2)) as ex; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select column_get(column_create(1,1212.12 AS double),1 as decimal(6,2)) AS `column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2))` -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal(20,0)); -column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal(20,0)) +Note 1003 select column_get(column_create(1,1212.12 AS double),1 as decimal(6,2)) AS `ex` +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal(20,0)) as ex; +ex 18446744073709551615 -select column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal(32,0)); -column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal(32,0)) +select column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal(32,0)) as ex; +ex 9223372036854775807 -select column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal(32,0)); -column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal(32,0)) +select column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal(32,0)) as ex; +ex -9223372036854775808 -select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as decimal(40,10)); -column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as decimal(40,10)) +select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as decimal(40,10)) as ex; +ex -99999999999999999999999999999.0000000000 -select column_get(column_create(1, "2011-04-05" AS date), 1 as decimal(32,6)); -column_get(column_create(1, "2011-04-05" AS date), 1 as decimal(32,6)) +select column_get(column_create(1, "2011-04-05" AS date), 1 as decimal(32,6)) as ex; +ex 20110405.000000 -select column_get(column_create(1, "8:46:06.23434" AS time), 1 as decimal(32,6)); -column_get(column_create(1, "8:46:06.23434" AS time), 1 as decimal(32,6)) +select column_get(column_create(1, "8:46:06.23434" AS time), 1 as decimal(32,6)) as ex; +ex 84606.234340 -select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as decimal(32,6)); -column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as decimal(32,6)) +select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as decimal(32,6)) as ex; +ex 84606.234340 -select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as decimal(32,6)); -column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as decimal(32,6)) +select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as decimal(32,6)) as ex; +ex -8084606.234340 -select column_get(column_create(1, "2011-04-05 8:46:06.123456" AS datetime), 1 as decimal(32,6)); -column_get(column_create(1, "2011-04-05 8:46:06.123456" AS datetime), 1 as decimal(32,6)) +select column_get(column_create(1, "2011-04-05 8:46:06.123456" AS datetime), 1 as decimal(32,6)) as ex; +ex 20110405084606.123456 -select column_get(column_create(1, "2011-04-05 8:46:06.123456" AS datetime(6)), 1 as decimal(32,6)); -column_get(column_create(1, "2011-04-05 8:46:06.123456" AS datetime(6)), 1 as decimal(32,6)) +select column_get(column_create(1, "2011-04-05 8:46:06.123456" AS datetime(6)), 1 as decimal(32,6)) as ex; +ex 20110405084606.123456 -select column_get(column_create(1, "2011-04-05 8:46:06.12345678" AS datetime(6)), 1 as decimal(32,8)); -column_get(column_create(1, "2011-04-05 8:46:06.12345678" AS datetime(6)), 1 as decimal(32,8)) +select column_get(column_create(1, "2011-04-05 8:46:06.12345678" AS datetime(6)), 1 as decimal(32,8)) as ex; +ex 20110405084606.12345600 Warnings: Note 1292 Truncated incorrect datetime value: '2011-04-05 8:46:06.12345678' -select column_get(column_create(1, NULL as decimal), 1 as decimal(32,10)); -column_get(column_create(1, NULL as decimal), 1 as decimal(32,10)) +select column_get(column_create(1, NULL as decimal), 1 as decimal(32,10)) as ex; +ex NULL -select column_get(column_create(1, "1223.5555" as decimal(10,5)), 1 as decimal(6,2)); -column_get(column_create(1, "1223.5555" as decimal(10,5)), 1 as decimal(6,2)) +select column_get(column_create(1, "1223.5555" as decimal(10,5)), 1 as decimal(6,2)) as ex; +ex 1223.56 # column get decimal truncation & warnings -select column_get(column_create(1, "1223.5aa" AS char), 1 as decimal(32,10)); -column_get(column_create(1, "1223.5aa" AS char), 1 as decimal(32,10)) +select column_get(column_create(1, "1223.5aa" AS char), 1 as decimal(32,10)) as ex; +ex 1223.5000000000 Warnings: Warning 1918 Encountered illegal value '1223.5aa' when converting to DECIMAL -select column_get(column_create(1, "aa" AS char), 1 as decimal(32,10)); -column_get(column_create(1, "aa" AS char), 1 as decimal(32,10)) +select column_get(column_create(1, "aa" AS char), 1 as decimal(32,10)) as ex; +ex 0.0000000000 Warnings: Warning 1918 Encountered illegal value 'aa' when converting to DECIMAL -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal); -column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal) +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal) as ex; +ex 9999999999 Warnings: -Warning 1264 Out of range value for column 'column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal)' at row 1 -select column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal); -column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal) +Warning 1264 Out of range value for column 'ex' at row 1 +select column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal) as ex; +ex 9999999999 Warnings: -Warning 1264 Out of range value for column 'column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal)' at row 1 -select column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal); -column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal) +Warning 1264 Out of range value for column 'ex' at row 1 +select column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal) as ex; +ex -9999999999 Warnings: -Warning 1264 Out of range value for column 'column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal)' at row 1 -select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as decimal); -column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as decimal) +Warning 1264 Out of range value for column 'ex' at row 1 +select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as decimal) as ex; +ex 9999999999 Warnings: -Warning 1264 Out of range value for column 'column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as decimal)' at row 1 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal) +Warning 1264 Out of range value for column 'ex' at row 1 +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal) as ex; +ex 9999999999 Warnings: -Warning 1264 Out of range value for column 'column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal)' at row 1 -select column_get(column_create(1, "1223.5555" as double), 1 as decimal(5,2)); -column_get(column_create(1, "1223.5555" as double), 1 as decimal(5,2)) +Warning 1264 Out of range value for column 'ex' at row 1 +select column_get(column_create(1, "1223.5555" as double), 1 as decimal(5,2)) as ex; +ex 999.99 Warnings: -Warning 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" as double), 1 as decimal(5,2))' at row 1 -select column_get(column_create(1, "-1223.5555" as double), 1 as decimal(5,2)); -column_get(column_create(1, "-1223.5555" as double), 1 as decimal(5,2)) +Warning 1264 Out of range value for column 'ex' at row 1 +select column_get(column_create(1, "-1223.5555" as double), 1 as decimal(5,2)) as ex; +ex -999.99 Warnings: -Warning 1264 Out of range value for column 'column_get(column_create(1, "-1223.5555" as double), 1 as decimal(5,2))' at row 1 -select column_get(column_create(1, "1223.5555" AS double), 1 as decimal(3,2)); -column_get(column_create(1, "1223.5555" AS double), 1 as decimal(3,2)) +Warning 1264 Out of range value for column 'ex' at row 1 +select column_get(column_create(1, "1223.5555" AS double), 1 as decimal(3,2)) as ex; +ex 9.99 Warnings: -Warning 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" AS double), 1 as decimal(3,2))' at row 1 -select column_get(column_create(1, "1223.5555" AS decimal(10,5)), 1 as decimal(3,2)); -column_get(column_create(1, "1223.5555" AS decimal(10,5)), 1 as decimal(3,2)) +Warning 1264 Out of range value for column 'ex' at row 1 +select column_get(column_create(1, "1223.5555" AS decimal(10,5)), 1 as decimal(3,2)) as ex; +ex 9.99 Warnings: -Warning 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" AS decimal(10,5)), 1 as decimal(3,2))' at row 1 -select column_get(column_create(1, 0.0 AS decimal,2, 0.0 as decimal), 1 as decimal); -column_get(column_create(1, 0.0 AS decimal,2, 0.0 as decimal), 1 as decimal) +Warning 1264 Out of range value for column 'ex' at row 1 +select column_get(column_create(1, 0.0 AS decimal,2, 0.0 as decimal), 1 as decimal) as ex; +ex 0 # # column get datetime # -select column_get(column_create(1, 20010203101112.121314 as double), 1 as datetime); -column_get(column_create(1, 20010203101112.121314 as double), 1 as datetime) +select column_get(column_create(1, 20010203101112.121314 as double), 1 as datetime) as ex; +ex 2001-02-03 10:11:12 -select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as datetime); -column_get(column_create(1, 20010203101112.121314 as decimal), 1 as datetime) +select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as datetime) as ex; +ex 2001-02-03 10:11:12 -select column_get(column_create(1, 20010203101112 as unsigned int), 1 as datetime); -column_get(column_create(1, 20010203101112 as unsigned int), 1 as datetime) +select column_get(column_create(1, 20010203101112 as unsigned int), 1 as datetime) as ex; +ex 2001-02-03 10:11:12 -select column_get(column_create(1, 20010203101112 as int), 1 as datetime); -column_get(column_create(1, 20010203101112 as int), 1 as datetime) +select column_get(column_create(1, 20010203101112 as int), 1 as datetime) as ex; +ex 2001-02-03 10:11:12 -select column_get(column_create(1, "20010203101112" as char), 1 as datetime); -column_get(column_create(1, "20010203101112" as char), 1 as datetime) +select column_get(column_create(1, "20010203101112" as char), 1 as datetime) as ex; +ex 2001-02-03 10:11:12 -select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as datetime); -column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as datetime) +select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as datetime) as ex; +ex 2001-02-03 10:11:12 -select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as datetime); -column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as datetime) +select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as datetime) as ex; +ex 2001-02-03 10:11:12 -select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as datetime); -column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as datetime) +select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as datetime) as ex; +ex 2001-02-03 10:11:12 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime) +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime) as ex; +ex 2011-04-05 08:46:06 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime(0)); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime(0)) +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime(0)) as ex; +ex 2011-04-05 08:46:06 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime(6)); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime(6)) +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime(6)) as ex; +ex 2011-04-05 08:46:06.234340 -select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as datetime); -column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as datetime) +select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as datetime) as ex; +ex 2011-00-00 08:46:06 -select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as datetime); -column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as datetime) +select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as datetime) as ex; +ex 2011-00-01 08:46:06 -select column_get(column_create(1, 20010203 as unsigned int), 1 as datetime); -column_get(column_create(1, 20010203 as unsigned int), 1 as datetime) +select column_get(column_create(1, 20010203 as unsigned int), 1 as datetime) as ex; +ex 2001-02-03 00:00:00 -select column_get(column_create(1, 20010203 as int), 1 as datetime); -column_get(column_create(1, 20010203 as int), 1 as datetime) +select column_get(column_create(1, 20010203 as int), 1 as datetime) as ex; +ex 2001-02-03 00:00:00 -select column_get(column_create(1, 20010203), 1 as datetime); -column_get(column_create(1, 20010203), 1 as datetime) +select column_get(column_create(1, 20010203), 1 as datetime) as ex; +ex 2001-02-03 00:00:00 -select column_get(column_create(1, 20010203.0), 1 as datetime); -column_get(column_create(1, 20010203.0), 1 as datetime) +select column_get(column_create(1, 20010203.0), 1 as datetime) as ex; +ex 2001-02-03 00:00:00 -select column_get(column_create(1, 20010203.0 as double), 1 as datetime); -column_get(column_create(1, 20010203.0 as double), 1 as datetime) +select column_get(column_create(1, 20010203.0 as double), 1 as datetime) as ex; +ex 2001-02-03 00:00:00 -select column_get(column_create(1, "2001-02-03"), 1 as datetime); -column_get(column_create(1, "2001-02-03"), 1 as datetime) +select column_get(column_create(1, "2001-02-03"), 1 as datetime) as ex; +ex 2001-02-03 00:00:00 -select column_get(column_create(1, "20010203"), 1 as datetime); -column_get(column_create(1, "20010203"), 1 as datetime) +select column_get(column_create(1, "20010203"), 1 as datetime) as ex; +ex 2001-02-03 00:00:00 -select column_get(column_create(1, 0), 1 as datetime); -column_get(column_create(1, 0), 1 as datetime) +select column_get(column_create(1, 0), 1 as datetime) as ex; +ex 0000-00-00 00:00:00 -select column_get(column_create(1, "2001021"), 1 as datetime); -column_get(column_create(1, "2001021"), 1 as datetime) +select column_get(column_create(1, "2001021"), 1 as datetime) as ex; +ex 2020-01-02 01:00:00 SET timestamp=unix_timestamp('2001-02-03 10:20:30'); -select column_get(column_create(1, "8:46:06.23434" AS time), 1 as datetime); -column_get(column_create(1, "8:46:06.23434" AS time), 1 as datetime) +select column_get(column_create(1, "8:46:06.23434" AS time), 1 as datetime) as ex; +ex 2001-02-03 08:46:06 -select column_get(column_create(1, "-808:46:06.23434" AS time), 1 as datetime); -column_get(column_create(1, "-808:46:06.23434" AS time), 1 as datetime) +select column_get(column_create(1, "-808:46:06.23434" AS time), 1 as datetime) as ex; +ex 2000-12-31 07:13:53 SET timestamp=DEFAULT; set @@sql_mode="allow_invalid_dates"; -select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as datetime); -column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as datetime) +select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as datetime) as ex; +ex 2011-02-30 18:46:06 -select column_get(column_create(1, "0000-00-000" AS CHAR), 1 as datetime); -column_get(column_create(1, "0000-00-000" AS CHAR), 1 as datetime) +select column_get(column_create(1, "0000-00-000" AS CHAR), 1 as datetime) as ex; +ex 0000-00-00 00:00:00 -select column_get(column_create(1, "2001-00-02" AS CHAR), 1 as datetime); -column_get(column_create(1, "2001-00-02" AS CHAR), 1 as datetime) +select column_get(column_create(1, "2001-00-02" AS CHAR), 1 as datetime) as ex; +ex 2001-00-02 00:00:00 set @@sql_mode=""; # column get datetime truncation & warnings -select column_get(column_create(1, "1223.5aa" AS char), 1 as datetime); -column_get(column_create(1, "1223.5aa" AS char), 1 as datetime) +select column_get(column_create(1, "1223.5aa" AS char), 1 as datetime) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '1223.5aa' -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as datetime); -column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as datetime) +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as datetime) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '1.8446744073709552e19' -select column_get(column_create(1, 9223372036854775807 AS int), 1 as datetime); -column_get(column_create(1, 9223372036854775807 AS int), 1 as datetime) +select column_get(column_create(1, 9223372036854775807 AS int), 1 as datetime) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '9223372036854775807' -select column_get(column_create(1, -9223372036854775808 AS int), 1 as datetime); -column_get(column_create(1, -9223372036854775808 AS int), 1 as datetime) +select column_get(column_create(1, -9223372036854775808 AS int), 1 as datetime) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '-9223372036854775808' -select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as datetime); -column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as datetime) +select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as datetime) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '99999999999999999999999999999' -select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as datetime); -column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as datetime) +select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as datetime) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '1e29' -select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as datetime); -column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as datetime) +select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as datetime) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '2011-02-32 8:46:06.23434' -select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as datetime); -column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as datetime) +select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as datetime) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '2011-13-01 8:46:06.23434' -select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as datetime); -column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as datetime) +select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as datetime) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '2011-02-30 8:46:06.23434' -select column_get(column_create(1, "20010231"), 1 as datetime); -column_get(column_create(1, "20010231"), 1 as datetime) +select column_get(column_create(1, "20010231"), 1 as datetime) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '20010231' -select column_get(column_create(1, "0" AS CHAR), 1 as datetime); -column_get(column_create(1, "0" AS CHAR), 1 as datetime) +select column_get(column_create(1, "0" AS CHAR), 1 as datetime) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '0' # # column get date # -select column_get(column_create(1, 20010203101112.121314 as double), 1 as date); -column_get(column_create(1, 20010203101112.121314 as double), 1 as date) +select column_get(column_create(1, 20010203101112.121314 as double), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as date); -column_get(column_create(1, 20010203101112.121314 as decimal), 1 as date) +select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, 20010203101112 as unsigned int), 1 as date); -column_get(column_create(1, 20010203101112 as unsigned int), 1 as date) +select column_get(column_create(1, 20010203101112 as unsigned int), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, 20010203101112 as int), 1 as date); -column_get(column_create(1, 20010203101112 as int), 1 as date) +select column_get(column_create(1, 20010203101112 as int), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, "20010203101112" as char), 1 as date); -column_get(column_create(1, "20010203101112" as char), 1 as date) +select column_get(column_create(1, "20010203101112" as char), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as date); -column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as date) +select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as date); -column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as date) +select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as date); -column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as date) +select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as date); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as date) +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as date) as ex; +ex 2011-04-05 -select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as date); -column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as date) +select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as date) as ex; +ex 2011-00-00 -select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as date); -column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as date) +select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as date) as ex; +ex 2011-00-01 -select column_get(column_create(1, 20010203 as unsigned int), 1 as date); -column_get(column_create(1, 20010203 as unsigned int), 1 as date) +select column_get(column_create(1, 20010203 as unsigned int), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, 20010203 as int), 1 as date); -column_get(column_create(1, 20010203 as int), 1 as date) +select column_get(column_create(1, 20010203 as int), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, 20010203), 1 as date); -column_get(column_create(1, 20010203), 1 as date) +select column_get(column_create(1, 20010203), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, 20010203.0), 1 as date); -column_get(column_create(1, 20010203.0), 1 as date) +select column_get(column_create(1, 20010203.0), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, 20010203.0 as double), 1 as date); -column_get(column_create(1, 20010203.0 as double), 1 as date) +select column_get(column_create(1, 20010203.0 as double), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, "2001-02-03"), 1 as date); -column_get(column_create(1, "2001-02-03"), 1 as date) +select column_get(column_create(1, "2001-02-03"), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, "20010203"), 1 as date); -column_get(column_create(1, "20010203"), 1 as date) +select column_get(column_create(1, "20010203"), 1 as date) as ex; +ex 2001-02-03 -select column_get(column_create(1, 0), 1 as date); -column_get(column_create(1, 0), 1 as date) +select column_get(column_create(1, 0), 1 as date) as ex; +ex 0000-00-00 -select column_get(column_create(1, "2001021"), 1 as date); -column_get(column_create(1, "2001021"), 1 as date) +select column_get(column_create(1, "2001021"), 1 as date) as ex; +ex 2020-01-02 set @@sql_mode="allow_invalid_dates"; -select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as date); -column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as date) +select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as date) as ex; +ex 2011-02-30 -select column_get(column_create(1, "0000-00-000" AS CHAR), 1 as date); -column_get(column_create(1, "0000-00-000" AS CHAR), 1 as date) +select column_get(column_create(1, "0000-00-000" AS CHAR), 1 as date) as ex; +ex 0000-00-00 -select column_get(column_create(1, "2001-00-02" AS CHAR), 1 as date); -column_get(column_create(1, "2001-00-02" AS CHAR), 1 as date) +select column_get(column_create(1, "2001-00-02" AS CHAR), 1 as date) as ex; +ex 2001-00-02 set @@sql_mode=""; # column get date truncation & warnings -select column_get(column_create(1, "1223.5aa" AS char), 1 as date); -column_get(column_create(1, "1223.5aa" AS char), 1 as date) +select column_get(column_create(1, "1223.5aa" AS char), 1 as date) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '1223.5aa' -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as date); -column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as date) +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as date) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '1.8446744073709552e19' -select column_get(column_create(1, 9223372036854775807 AS int), 1 as date); -column_get(column_create(1, 9223372036854775807 AS int), 1 as date) +select column_get(column_create(1, 9223372036854775807 AS int), 1 as date) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '9223372036854775807' -select column_get(column_create(1, -9223372036854775808 AS int), 1 as date); -column_get(column_create(1, -9223372036854775808 AS int), 1 as date) +select column_get(column_create(1, -9223372036854775808 AS int), 1 as date) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '-9223372036854775808' -select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as date); -column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as date) +select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as date) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '99999999999999999999999999999' -select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as date); -column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as date) +select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as date) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '1e29' -select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as date); -column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as date) +select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as date) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '2011-02-32 8:46:06.23434' -select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as date); -column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as date) +select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as date) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '2011-13-01 8:46:06.23434' -select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as date); -column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as date) +select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as date) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '2011-02-30 8:46:06.23434' -select column_get(column_create(1, "20010231"), 1 as date); -column_get(column_create(1, "20010231"), 1 as date) +select column_get(column_create(1, "20010231"), 1 as date) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '20010231' -select column_get(column_create(1, "0" AS CHAR), 1 as date); -column_get(column_create(1, "0" AS CHAR), 1 as date) +select column_get(column_create(1, "0" AS CHAR), 1 as date) as ex; +ex NULL Warnings: Warning 1292 Incorrect datetime value: '0' # # column get time # -select column_get(column_create(1, 20010203101112.121314 as double), 1 as time); -column_get(column_create(1, 20010203101112.121314 as double), 1 as time) +select column_get(column_create(1, 20010203101112.121314 as double), 1 as time) as ex; +ex 10:11:12 -select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as time); -column_get(column_create(1, 20010203101112.121314 as decimal), 1 as time) +select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as time) as ex; +ex 10:11:12 -select column_get(column_create(1, 20010203101112 as unsigned int), 1 as time); -column_get(column_create(1, 20010203101112 as unsigned int), 1 as time) +select column_get(column_create(1, 20010203101112 as unsigned int), 1 as time) as ex; +ex 10:11:12 -select column_get(column_create(1, 8080102 as unsigned int), 1 as time); -column_get(column_create(1, 8080102 as unsigned int), 1 as time) +select column_get(column_create(1, 8080102 as unsigned int), 1 as time) as ex; +ex 808:01:02 -select column_get(column_create(1, 20010203101112 as int), 1 as time); -column_get(column_create(1, 20010203101112 as int), 1 as time) +select column_get(column_create(1, 20010203101112 as int), 1 as time) as ex; +ex 10:11:12 -select column_get(column_create(1, -8080102 as int), 1 as time); -column_get(column_create(1, -8080102 as int), 1 as time) +select column_get(column_create(1, -8080102 as int), 1 as time) as ex; +ex -808:01:02 -select column_get(column_create(1, "20010203101112" as char), 1 as time); -column_get(column_create(1, "20010203101112" as char), 1 as time) +select column_get(column_create(1, "20010203101112" as char), 1 as time) as ex; +ex 10:11:12 -select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as time); -column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as time) +select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as time) as ex; +ex 10:11:12 -select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time); -column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time) +select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time) as ex; +ex 10:11:12 -select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time(6)); -column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time(6)) +select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time(6)) as ex; +ex 10:11:12.121314 -select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as time); -column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as time) +select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as time) as ex; +ex 10:11:12 -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as time(6)); -column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as time(6)) +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as time(6)) as ex; +ex 08:46:06.234340 -select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as time(6)); -column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as time(6)) +select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as time(6)) as ex; +ex 08:46:06.234340 -select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as time(6)); -column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as time(6)) +select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as time(6)) as ex; +ex 08:46:06.234340 -select column_get(column_create(1, "830:46:06.23434" AS CHAR), 1 as time(6)); -column_get(column_create(1, "830:46:06.23434" AS CHAR), 1 as time(6)) +select column_get(column_create(1, "830:46:06.23434" AS CHAR), 1 as time(6)) as ex; +ex 830:46:06.234340 -select column_get(column_create(1, "830:46:06" AS CHAR), 1 as time(6)); -column_get(column_create(1, "830:46:06" AS CHAR), 1 as time(6)) +select column_get(column_create(1, "830:46:06" AS CHAR), 1 as time(6)) as ex; +ex 830:46:06.000000 -select cast("-830:46:06.23434" AS time(6)); -cast("-830:46:06.23434" AS time(6)) +select cast("-830:46:06.23434" AS time(6)) as ex; +ex -830:46:06.234340 -select 1,cast("-830:46:06.23434" AS time(6)); -1 cast("-830:46:06.23434" AS time(6)) +select 1,cast("-830:46:06.23434" AS time(6)) as ex; +1 ex 1 -830:46:06.234340 -select hex(column_create(1, "-830:46:06.23434" AS CHAR)); -hex(column_create(1, "-830:46:06.23434" AS CHAR)) +select hex(column_create(1, "-830:46:06.23434" AS CHAR)) as ex; +ex 000100010003082D3833303A34363A30362E3233343334 -select column_get(column_create(1, "-830:46:06.23434" AS CHAR), 1 as time(6)); -column_get(column_create(1, "-830:46:06.23434" AS CHAR), 1 as time(6)) +select column_get(column_create(1, "-830:46:06.23434" AS CHAR), 1 as time(6)) as ex; +ex -830:46:06.234340 -select column_get(column_create(1, "0" AS CHAR), 1 as time); -column_get(column_create(1, "0" AS CHAR), 1 as time) +select column_get(column_create(1, "0" AS CHAR), 1 as time) as ex; +ex 00:00:00 -select column_get(column_create(1, "6" AS CHAR), 1 as time); -column_get(column_create(1, "6" AS CHAR), 1 as time) +select column_get(column_create(1, "6" AS CHAR), 1 as time) as ex; +ex 00:00:06 -select column_get(column_create(1, "1:6" AS CHAR), 1 as time); -column_get(column_create(1, "1:6" AS CHAR), 1 as time) +select column_get(column_create(1, "1:6" AS CHAR), 1 as time) as ex; +ex 01:06:00 -select column_get(column_create(1, "2:1:6" AS CHAR), 1 as time); -column_get(column_create(1, "2:1:6" AS CHAR), 1 as time) +select column_get(column_create(1, "2:1:6" AS CHAR), 1 as time) as ex; +ex 02:01:06 -select column_get(column_create(1, 0), 1 as time); -column_get(column_create(1, 0), 1 as time) +select column_get(column_create(1, 0), 1 as time) as ex; +ex 00:00:00 -select column_get(column_create(1, "2001021"), 1 as time); -column_get(column_create(1, "2001021"), 1 as time) +select column_get(column_create(1, "2001021"), 1 as time) as ex; +ex 200:10:21 set @@sql_mode="allow_invalid_dates"; -select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as time); -column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as time) +select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as time) as ex; +ex 18:46:06 set @@sql_mode=""; # column get date truncation & warnings -select column_get(column_create(1, "1223.5aa" AS char), 1 as time); -column_get(column_create(1, "1223.5aa" AS char), 1 as time) +select column_get(column_create(1, "1223.5aa" AS char), 1 as time) as ex; +ex 00:12:23 Warnings: Warning 1292 Truncated incorrect time value: '1223.5aa' -select column_get(column_create(1, "1223.5aa" AS char), 1 as time(3)); -column_get(column_create(1, "1223.5aa" AS char), 1 as time(3)) +select column_get(column_create(1, "1223.5aa" AS char), 1 as time(3)) as ex; +ex 00:12:23.500 Warnings: Warning 1292 Truncated incorrect time value: '1223.5aa' -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as time); -column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as time) +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as time) as ex; +ex 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '1.8446744073709552e19' -select column_get(column_create(1, 9223372036854775807 AS int), 1 as time); -column_get(column_create(1, 9223372036854775807 AS int), 1 as time) +select column_get(column_create(1, 9223372036854775807 AS int), 1 as time) as ex; +ex 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '9223372036854775807' -select column_get(column_create(1, -9223372036854775808 AS int), 1 as time); -column_get(column_create(1, -9223372036854775808 AS int), 1 as time) +select column_get(column_create(1, -9223372036854775808 AS int), 1 as time) as ex; +ex -838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '-9223372036854775808' -select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as time); -column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as time) +select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as time) as ex; +ex 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '99999999999999999999999999999' -select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as time); -column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as time) +select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as time) as ex; +ex 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '1e29' -select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as time); -column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as time) +select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as time) as ex; +ex NULL Warnings: Warning 1292 Incorrect time value: '2011-02-32 8:46:06.23434' -select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as time); -column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as time) +select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as time) as ex; +ex NULL Warnings: Warning 1292 Incorrect time value: '2011-13-01 8:46:06.23434' -select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as time); -column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as time) +select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as time) as ex; +ex 08:46:06 -select column_get(column_create(1, "2001-02-03"), 1 as time); -column_get(column_create(1, "2001-02-03"), 1 as time) +select column_get(column_create(1, "2001-02-03"), 1 as time) as ex; +ex 00:20:01 Warnings: Warning 1292 Truncated incorrect time value: '2001-02-03' -select column_get(column_create(1, "20010203"), 1 as time); -column_get(column_create(1, "20010203"), 1 as time) +select column_get(column_create(1, "20010203"), 1 as time) as ex; +ex 838:59:59 Warnings: Warning 1292 Truncated incorrect time value: '20010203' # column add -select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer)); -hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer)) +select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer)) as ex; +ex 00020001000002001078097809 -select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer)); -hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer)) +select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer)) as ex; +ex 0001000100007809 -select hex(column_add(column_create(1, 1212 as integer), 1, NULL as integer)); -hex(column_add(column_create(1, 1212 as integer), 1, NULL as integer)) +select hex(column_add(column_create(1, 1212 as integer), 1, NULL as integer)) as ex; +ex 000000 -select hex(column_add(column_create(1, 1212 as integer), 2, NULL as integer)); -hex(column_add(column_create(1, 1212 as integer), 2, NULL as integer)) +select hex(column_add(column_create(1, 1212 as integer), 2, NULL as integer)) as ex; +ex 0001000100007809 -select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer)); -hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer)) +select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer)) as ex; +ex 000200010000020008167809 -select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 1 as integer); -column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 1 as integer) +select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 1 as integer) as ex; +ex 11 -select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 2 as integer); -column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 2 as integer) +select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 2 as integer) as ex; +ex 1212 -select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer, 2, 11 as integer)); -hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer, 2, 11 as integer)) +select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer, 2, 11 as integer)) as ex; +ex 000200010000020010780916 -select hex(column_add(column_create(1, NULL as integer), 1, 1212 as integer, 2, 11 as integer)); -hex(column_add(column_create(1, NULL as integer), 1, 1212 as integer, 2, 11 as integer)) +select hex(column_add(column_create(1, NULL as integer), 1, 1212 as integer, 2, 11 as integer)) as ex; +ex 000200010000020010780916 -select hex(column_add(column_create(1, 1212 as integer, 2, 1212 as integer), 1, 11 as integer)); -hex(column_add(column_create(1, 1212 as integer, 2, 1212 as integer), 1, 11 as integer)) +select hex(column_add(column_create(1, 1212 as integer, 2, 1212 as integer), 1, 11 as integer)) as ex; +ex 000200010000020008167809 -select hex(column_add(column_create(1, 1), 1, null)); -hex(column_add(column_create(1, 1), 1, null)) +select hex(column_add(column_create(1, 1), 1, null)) as ex; +ex 000000 -select column_list(column_add(column_create(1, 1), 1, null)); -column_list(column_add(column_create(1, 1), 1, null)) +select column_list(column_add(column_create(1, 1), 1, null)) as ex; +ex -select column_list(column_add(column_create(1, 1), 1, "")); -column_list(column_add(column_create(1, 1), 1, "")) +select column_list(column_add(column_create(1, 1), 1, "")) as ex; +ex `1` -select hex(column_add("", 1, 1)); -hex(column_add("", 1, 1)) +select hex(column_add("", 1, 1)) as ex; +ex 00010001000002 # column delete -select hex(column_delete(column_create(1, 1212 as integer, 2, 1212 as integer), 1)); -hex(column_delete(column_create(1, 1212 as integer, 2, 1212 as integer), 1)) +select hex(column_delete(column_create(1, 1212 as integer, 2, 1212 as integer), 1)) as ex; +ex 0001000200007809 -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2)); -hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2)) +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2)) as ex; +ex 0002000100000300080206 -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 3)); -hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 3)) +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 3)) as ex; +ex 0002000100000200080204 -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 4)); -hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 4)) +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 4)) as ex; +ex 000300010000020008030010020406 -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 1)); -hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 1)) +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 1)) as ex; +ex 00010003000006 -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 3)); -hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 3)) +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 3)) as ex; +ex 00010001000002 -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3)); -hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3)) +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3)) as ex; +ex 000000 -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3, 10)); -hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3, 10)) +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3, 10)) as ex; +ex 000000 -select hex(column_delete(column_create(1, 1), 1)); -hex(column_delete(column_create(1, 1), 1)) +select hex(column_delete(column_create(1, 1), 1)) as ex; +ex 000000 -select hex(column_delete("", 1)); -hex(column_delete("", 1)) +select hex(column_delete("", 1)) as ex; +ex # column exists -select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 1); -column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 1) +select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 1) as ex; +ex 1 -select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4); -column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4) +select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4) as ex; +ex 0 # column list -select column_list(column_create(1, 1212 as integer, 2, 1212 as integer)); -column_list(column_create(1, 1212 as integer, 2, 1212 as integer)) +select column_list(column_create(1, 1212 as integer, 2, 1212 as integer)) as ex; +ex `1`,`2` -select column_list(column_create(1, 1212 as integer)); -column_list(column_create(1, 1212 as integer)) +select column_list(column_create(1, 1212 as integer)) as ex; +ex `1` -select column_list(column_create(1, NULL as integer)); -column_list(column_create(1, NULL as integer)) +select column_list(column_create(1, NULL as integer)) as ex; +ex # # check error handling @@ -1321,17 +1307,17 @@ set @a=0x00020008000009000C2C010080; select COLUMN_GET(@a, 9 AS DECIMAL); COLUMN_GET(@a, 9 AS DECIMAL) 0 -select hex(COLUMN_CREATE(0, COLUMN_GET(@a, 9 AS DECIMAL))); -hex(COLUMN_CREATE(0, COLUMN_GET(@a, 9 AS DECIMAL))) +select hex(COLUMN_CREATE(0, COLUMN_GET(@a, 9 AS DECIMAL))) as ex; +ex 000100000004 -select hex(COLUMN_CREATE(0, COLUMN_GET(@a, 9 AS DECIMAL(19,0)))); -hex(COLUMN_CREATE(0, COLUMN_GET(@a, 9 AS DECIMAL(19,0)))) +select hex(COLUMN_CREATE(0, COLUMN_GET(@a, 9 AS DECIMAL(19,0)))) as ex; +ex 000100000004 -select hex(COLUMN_CREATE(0, COLUMN_GET(COLUMN_CREATE(0, 0.0 as decimal), 0 as decimal))); -hex(COLUMN_CREATE(0, COLUMN_GET(COLUMN_CREATE(0, 0.0 as decimal), 0 as decimal))) +select hex(COLUMN_CREATE(0, COLUMN_GET(COLUMN_CREATE(0, 0.0 as decimal), 0 as decimal))) as ex; +ex 000100000004 -select hex(COLUMN_CREATE(0, 0.0 as decimal)); -hex(COLUMN_CREATE(0, 0.0 as decimal)) +select hex(COLUMN_CREATE(0, 0.0 as decimal)) as ex; +ex 000100000004 # # MDEV-4292: parse error when selecting on views using dynamic column @@ -1427,12 +1413,12 @@ CREATE TABLE t1 (dyncol TINYBLOB) ENGINE=MyISAM; INSERT INTO t1 SET dyncol = COLUMN_CREATE( 7, REPEAT('k',487), 209, REPEAT('x',464) ); Warnings: Warning 1265 Data truncated for column 'dyncol' at row 1 -SELECT COLUMN_ADD( dyncol, 7, '22:22:22', 8, REPEAT('x',270) AS CHAR ) FROM t1; +SELECT COLUMN_ADD( dyncol, 7, '22:22:22', 8, REPEAT('x',270) AS CHAR ) as ex FROM t1; delete from t1; INSERT INTO t1 SET dyncol = COLUMN_CREATE( 'a', REPEAT('k',487), 'b', REPEAT('x',464) ); Warnings: Warning 1265 Data truncated for column 'dyncol' at row 1 -SELECT COLUMN_ADD( dyncol, 'a', '22:22:22', 'c', REPEAT('x',270) AS CHAR ) FROM t1; +SELECT COLUMN_ADD( dyncol, 'a', '22:22:22', 'c', REPEAT('x',270) AS CHAR ) as ex FROM t1; DROP table t1; # # MDEV-4858 Wrong results for a huge unsigned value inserted into a TIME column @@ -1448,8 +1434,8 @@ Warning 1292 Truncated incorrect time value: '-9223372036854775808' # # end of 5.3 tests # -select column_get(column_create(1, "18446744073709552001" as char), 1 as int); -column_get(column_create(1, "18446744073709552001" as char), 1 as int) +select column_get(column_create(1, "18446744073709552001" as char), 1 as int) as ex; +ex -1 Warnings: Warning 1918 Encountered illegal value '18446744073709552001' when converting to INT @@ -1486,149 +1472,149 @@ hex(column_create("1212", 2, "адын", 1, 3, 3)) set names latin1; # fetching column test (names) set names utf8; -select column_get(column_create("адын", 1212), "адын" as int); -column_get(column_create("адын", 1212), "адын" as int) +select column_get(column_create("адын", 1212), "адын" as int) as ex; +ex 1212 -select column_get(column_create("1212", 2, "адын", 1, 3, 3), "адын" as int); -column_get(column_create("1212", 2, "адын", 1, 3, 3), "адын" as int) +select column_get(column_create("1212", 2, "адын", 1, 3, 3), "адын" as int) as ex; +ex 1 -select column_get(column_create("1212", 2, "адын", 1, 3, 3), 1212 as int); -column_get(column_create("1212", 2, "адын", 1, 3, 3), 1212 as int) +select column_get(column_create("1212", 2, "адын", 1, 3, 3), 1212 as int) as ex; +ex 2 -select column_get(column_create("1212", 2, "адын", 1, 3, 3), "3" as int); -column_get(column_create("1212", 2, "адын", 1, 3, 3), "3" as int) +select column_get(column_create("1212", 2, "адын", 1, 3, 3), "3" as int) as ex; +ex 3 -select column_get(column_create("1212", 2, "адын", 1, 3, 3), 3 as int); -column_get(column_create("1212", 2, "адын", 1, 3, 3), 3 as int) +select column_get(column_create("1212", 2, "адын", 1, 3, 3), 3 as int) as ex; +ex 3 -select column_get(column_create("1212", 2, "адын", 1, 3, 3), 4 as int); -column_get(column_create("1212", 2, "адын", 1, 3, 3), 4 as int) +select column_get(column_create("1212", 2, "адын", 1, 3, 3), 4 as int) as ex; +ex NULL -select column_get(column_create("1212", 2, "адын", 1, 3, 3), "4" as int); -column_get(column_create("1212", 2, "адын", 1, 3, 3), "4" as int) +select column_get(column_create("1212", 2, "адын", 1, 3, 3), "4" as int) as ex; +ex NULL set names latin1; # column existance test (names) set names utf8; -select column_exists(column_create("адын", 1212), "адын"); -column_exists(column_create("адын", 1212), "адын") +select column_exists(column_create("адын", 1212), "адын") as ex; +ex 1 -select column_exists(column_create("адын", 1212), "aады"); -column_exists(column_create("адын", 1212), "aады") +select column_exists(column_create("адын", 1212), "aады") as ex; +ex 0 -select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "адын"); -column_exists(column_create("1212", 2, "адын", 1, 3, 3), "адын") +select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "адын") as ex; +ex 1 -select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 1212); -column_exists(column_create("1212", 2, "адын", 1, 3, 3), 1212) +select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 1212) as ex; +ex 1 -select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "3"); -column_exists(column_create("1212", 2, "адын", 1, 3, 3), "3") +select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "3") as ex; +ex 1 -select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 3); -column_exists(column_create("1212", 2, "адын", 1, 3, 3), 3) +select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 3) as ex; +ex 1 -select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 4); -column_exists(column_create("1212", 2, "адын", 1, 3, 3), 4) +select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 4) as ex; +ex 0 -select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "4"); -column_exists(column_create("1212", 2, "адын", 1, 3, 3), "4") +select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "4") as ex; +ex 0 set names latin1; # column changing test (names) -select hex(column_add(column_create(1, "AAA"), "b", "BBB")); -hex(column_add(column_create(1, "AAA"), "b", "BBB")) +select hex(column_add(column_create(1, "AAA"), "b", "BBB")) as ex; +ex 0402000200000003000100430031620841414108424242 -select hex(column_add(column_create("1", "AAA"), "b", "BBB")); -hex(column_add(column_create("1", "AAA"), "b", "BBB")) +select hex(column_add(column_create("1", "AAA"), "b", "BBB")) as ex; +ex 0402000200000003000100430031620841414108424242 -select column_get(column_add(column_create(1, "AAA"), "b", "BBB"), 1 as char); -column_get(column_add(column_create(1, "AAA"), "b", "BBB"), 1 as char) +select column_get(column_add(column_create(1, "AAA"), "b", "BBB"), 1 as char) as ex; +ex AAA -select column_get(column_add(column_create(1, "AAA"), "b", "BBB"), "b" as char); -column_get(column_add(column_create(1, "AAA"), "b", "BBB"), "b" as char) +select column_get(column_add(column_create(1, "AAA"), "b", "BBB"), "b" as char) as ex; +ex BBB -select hex(column_add(column_create("a", "AAA"), 1, "BBB")); -hex(column_add(column_create("a", "AAA"), 1, "BBB")) +select hex(column_add(column_create("a", "AAA"), 1, "BBB")) as ex; +ex 0402000200000003000100430031610842424208414141 -select hex(column_add(column_create("a", "AAA"), "1", "BBB")); -hex(column_add(column_create("a", "AAA"), "1", "BBB")) +select hex(column_add(column_create("a", "AAA"), "1", "BBB")) as ex; +ex 0402000200000003000100430031610842424208414141 -select hex(column_add(column_create("a", 1212 as integer), "b", "1212" as integer)); -hex(column_add(column_create("a", 1212 as integer), "b", "1212" as integer)) +select hex(column_add(column_create("a", 1212 as integer), "b", "1212" as integer)) as ex; +ex 04020002000000000001002000616278097809 -select hex(column_add(column_create("a", 1212 as integer), "a", "1212" as integer)); -hex(column_add(column_create("a", 1212 as integer), "a", "1212" as integer)) +select hex(column_add(column_create("a", 1212 as integer), "a", "1212" as integer)) as ex; +ex 040100010000000000617809 -select hex(column_add(column_create("a", 1212 as integer), "a", NULL as integer)); -hex(column_add(column_create("a", 1212 as integer), "a", NULL as integer)) +select hex(column_add(column_create("a", 1212 as integer), "a", NULL as integer)) as ex; +ex 0400000000 -select hex(column_add(column_create("a", 1212 as integer), "b", NULL as integer)); -hex(column_add(column_create("a", 1212 as integer), "b", NULL as integer)) +select hex(column_add(column_create("a", 1212 as integer), "b", NULL as integer)) as ex; +ex 040100010000000000617809 -select hex(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer)); -hex(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer)) +select hex(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer)) as ex; +ex 040200020000000000010010006162167809 -select column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "a" as integer); -column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "a" as integer) +select column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "a" as integer) as ex; +ex 11 -select column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "b" as integer); -column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "b" as integer) +select column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "b" as integer) as ex; +ex 1212 -select hex(column_add(column_create("a", 1212 as integer), "a", 1212 as integer, "b", 11 as integer)); -hex(column_add(column_create("a", 1212 as integer), "a", 1212 as integer, "b", 11 as integer)) +select hex(column_add(column_create("a", 1212 as integer), "a", 1212 as integer, "b", 11 as integer)) as ex; +ex 040200020000000000010020006162780916 -select hex(column_add(column_create("a", NULL as integer), "a", 1212 as integer, "b", 11 as integer)); -hex(column_add(column_create("a", NULL as integer), "a", 1212 as integer, "b", 11 as integer)) +select hex(column_add(column_create("a", NULL as integer), "a", 1212 as integer, "b", 11 as integer)) as ex; +ex 040200020000000000010020006162780916 -select hex(column_add(column_create("a", 1212 as integer, "b", 1212 as integer), "a", 11 as integer)); -hex(column_add(column_create("a", 1212 as integer, "b", 1212 as integer), "a", 11 as integer)) +select hex(column_add(column_create("a", 1212 as integer, "b", 1212 as integer), "a", 11 as integer)) as ex; +ex 040200020000000000010010006162167809 -select hex(column_add(column_create("a", 1), "a", null)); -hex(column_add(column_create("a", 1), "a", null)) +select hex(column_add(column_create("a", 1), "a", null)) as ex; +ex 0400000000 -select column_list(column_add(column_create("a", 1), "a", null)); -column_list(column_add(column_create("a", 1), "a", null)) +select column_list(column_add(column_create("a", 1), "a", null)) as ex; +ex -select column_list(column_add(column_create("a", 1), "a", "")); -column_list(column_add(column_create("a", 1), "a", "")) +select column_list(column_add(column_create("a", 1), "a", "")) as ex; +ex `a` -select hex(column_add("", "a", 1)); -hex(column_add("", "a", 1)) +select hex(column_add("", "a", 1)) as ex; +ex 0401000100000000006102 # column delete (names) -select hex(column_delete(column_create("a", 1212 as integer, "b", 1212 as integer), "a")); -hex(column_delete(column_create("a", 1212 as integer, "b", 1212 as integer), "a")) +select hex(column_delete(column_create("a", 1212 as integer, "b", 1212 as integer), "a")) as ex; +ex 040100010000000000627809 -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b")); -hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b")) +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b")) as ex; +ex 0402000200000000000100100061630206 -select hex(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer)); -hex(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer)) +select hex(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer)) as ex; +ex 0403000300000000000100100002002000616263020406 -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "c")); -hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "c")) +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "c")) as ex; +ex 0402000200000000000100100061620204 -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "d")); -hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "d")) +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "d")) as ex; +ex 0403000300000000000100100002002000616263020406 -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "a")); -hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "a")) +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "a")) as ex; +ex 0401000100000000006306 -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "c")); -hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "c")) +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "c")) as ex; +ex 0401000100000000006102 -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c")); -hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c")) +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c")) as ex; +ex 0400000000 -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c", "e")); -hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c", "e")) +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c", "e")) as ex; +ex 0400000000 -select hex(column_delete(column_create("a", 1), "a")); -hex(column_delete(column_create("a", 1), "a")) +select hex(column_delete(column_create("a", 1), "a")) as ex; +ex 0400000000 -select hex(column_delete("", "a")); -hex(column_delete("", "a")) +select hex(column_delete("", "a")) as ex; +ex # # MDEV-458 DNAMES: Server crashes on using an unquoted string @@ -1661,23 +1647,23 @@ drop table t1; # # MDEV-490/MDEV-491 null as arguments # -SELECT COLUMN_GET( COLUMN_CREATE( 'col', 'val' ), NULL AS CHAR ); -COLUMN_GET( COLUMN_CREATE( 'col', 'val' ), NULL AS CHAR ) +SELECT COLUMN_GET( COLUMN_CREATE( 'col', 'val' ), NULL AS CHAR ) as ex; +ex NULL -SELECT COLUMN_GET( NULL, 'col' as char ); -COLUMN_GET( NULL, 'col' as char ) +SELECT COLUMN_GET( NULL, 'col' as char ) as ex; +ex NULL -SELECT COLUMN_EXISTS( COLUMN_CREATE( 'col', 'val' ), NULL); -COLUMN_EXISTS( COLUMN_CREATE( 'col', 'val' ), NULL) +SELECT COLUMN_EXISTS( COLUMN_CREATE( 'col', 'val' ), NULL) as ex; +ex NULL -SELECT COLUMN_EXISTS( NULL, 'col'); -COLUMN_EXISTS( NULL, 'col') +SELECT COLUMN_EXISTS( NULL, 'col') as ex; +ex NULL -SELECT COLUMN_CREATE( NULL, 'val' ); -COLUMN_CREATE( NULL, 'val' ) +SELECT COLUMN_CREATE( NULL, 'val' ) as ex; +ex NULL -SELECT COLUMN_ADD( NULL, 'val', 'col'); -COLUMN_ADD( NULL, 'val', 'col') +SELECT COLUMN_ADD( NULL, 'val', 'col') as ex; +ex NULL # # MDEV-488: Assertion `column_name->length < 255' failed on a @@ -1691,11 +1677,11 @@ ERROR 22007: Illegal value used as argument of dynamic column function # # JSON conversion # -select column_json(column_create("int", -1212 as int, "uint", 12334 as unsigned int, "decimal", "23.344" as decimal, "double", 1.23444e50 as double, "string", 'gdgd\\dhdjh"dhdhd' as char, "time", "0:45:49.000001" AS time, "datetime", "2011-04-05 0:45:49.000001" AS datetime, "date", "2011-04-05" AS date)); -column_json(column_create("int", -1212 as int, "uint", 12334 as unsigned int, "decimal", "23.344" as decimal, "double", 1.23444e50 as double, "string", 'gdgd\\dhdjh"dhdhd' as char, "time", "0:45:49.000001" AS time, "datetime", "2011-04-05 0:45:49.000001" +select column_json(column_create("int", -1212 as int, "uint", 12334 as unsigned int, "decimal", "23.344" as decimal, "double", 1.23444e50 as double, "string", 'gdgd\\dhdjh"dhdhd' as char, "time", "0:45:49.000001" AS time, "datetime", "2011-04-05 0:45:49.000001" AS datetime, "date", "2011-04-05" AS date)) as ex; +ex {"int":-1212,"date":"2011-04-05","time":"00:45:49.000001","uint":12334,"double":1.23444e50,"string":"gdgd\\dhdjh\"dhdhd","decimal":23.344,"datetime":"2011-04-05 00:45:49.000001"} -select column_json(column_create(1, -1212 as int, 2, 12334 as unsigned int, 3, "23.344" as decimal, 4, 1.23444e50 as double, 5, 'gdgd\\dhdjh"dhdhd' as char, 6, "0:45:49.000001" AS time, 7, "2011-04-05 0:45:49.000001" AS datetime, 8, "2011-04-05" AS date)); -column_json(column_create(1, -1212 as int, 2, 12334 as unsigned int, 3, "23.344" as decimal, 4, 1.23444e50 as double, 5, 'gdgd\\dhdjh"dhdhd' as char, 6, "0:45:49.000001" AS time, 7, "2011-04-05 0:45:49.000001" AS datetime, 8, "2011-04-05" AS date)) +select column_json(column_create(1, -1212 as int, 2, 12334 as unsigned int, 3, "23.344" as decimal, 4, 1.23444e50 as double, 5, 'gdgd\\dhdjh"dhdhd' as char, 6, "0:45:49.000001" AS time, 7, "2011-04-05 0:45:49.000001" AS datetime, 8, "2011-04-05" AS date)) as ex; +ex {"1":-1212,"2":12334,"3":23.344,"4":1.23444e50,"5":"gdgd\\dhdjh\"dhdhd","6":"00:45:49.000001","7":"2011-04-05 00:45:49.000001","8":"2011-04-05"} # # CHECK test @@ -1721,11 +1707,11 @@ column_json(column_create("string", "'\"/\\`.,whatever")) hex(column_create("str # # embedding test # -select column_json(column_create("val", "val", "emb", column_create("val2", "val2"))); -column_json(column_create("val", "val", "emb", column_create("val2", "val2"))) +select column_json(column_create("val", "val", "emb", column_create("val2", "val2"))) as ex; +ex {"emb":{"val2":"val2"},"val":"val"} -select column_json(column_create(1, "val", 2, column_create(3, "val2"))); -column_json(column_create(1, "val", 2, column_create(3, "val2"))) +select column_json(column_create(1, "val", 2, column_create(3, "val2"))) as ex; +ex {"1":"val","2":{"3":"val2"}} # # Time encoding @@ -1778,8 +1764,8 @@ DROP TABLE t1; # create table t1 (dyn blob); insert into t1 values (column_create('name1','value1','name2','value2')); -select group_concat(cast(column_json(dyn) as char)) from t1; -group_concat(cast(column_json(dyn) as char)) +select group_concat(cast(column_json(dyn) as char)) as ex from t1; +ex {"name1":"value1","name2":"value2"} drop table t1; # @@ -1827,25 +1813,20 @@ COLUMN_CREATE( 'one', 123.456, 'two', 123.456 as DOUBLE ) -); -COLUMN_JSON( -COLUMN_CREATE( -'one', 123.456, -'two', 123.456 as DOUBLE -) -) +) as ex; +ex {"one":123.456,"two":123.456} # # MDEV-8521: Drastic loss of precision in COLUMN_JSON() on DOUBLEs # -select column_get(column_create('float', 1.23456789012345E+100 as double), 'float' as double); -column_get(column_create('float', 1.23456789012345E+100 as double), 'float' as double) +select column_get(column_create('float', 1.23456789012345E+100 as double), 'float' as double) as ex; +ex 1.23456789012345e100 -select column_json(column_create('float', 1.23456789012345E+100 as double)); -column_json(column_create('float', 1.23456789012345E+100 as double)) +select column_json(column_create('float', 1.23456789012345E+100 as double)) as ex; +ex {"float":1.23456789012345e100} -select column_json(column_create('float', 1.23456789012345E+10 as double)); -column_json(column_create('float', 1.23456789012345E+10 as double)) +select column_json(column_create('float', 1.23456789012345E+10 as double)) as ex; +ex {"float":12345678901.2345} # # MDEV-9147: Character set is ignored in Dynamic Column for saved string @@ -1860,17 +1841,17 @@ a # # MDEV-9167: COLUMN_CHECK fails on valid decimal data # -SELECT COLUMN_CHECK(COLUMN_CREATE('a',0 AS DECIMAL,'b',1 AS DECIMAL)); -COLUMN_CHECK(COLUMN_CREATE('a',0 AS DECIMAL,'b',1 AS DECIMAL)) +SELECT COLUMN_CHECK(COLUMN_CREATE('a',0 AS DECIMAL,'b',1 AS DECIMAL)) as ex; +ex 1 -SELECT COLUMN_CHECK(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)); -COLUMN_CHECK(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)) +SELECT COLUMN_CHECK(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)) as ex; +ex 1 -SELECT COLUMN_JSON(COLUMN_CREATE('a',0 AS DECIMAL,'b',1 AS DECIMAL)); -COLUMN_JSON(COLUMN_CREATE('a',0 AS DECIMAL,'b',1 AS DECIMAL)) +SELECT COLUMN_JSON(COLUMN_CREATE('a',0 AS DECIMAL,'b',1 AS DECIMAL)) as ex; +ex {"a":0,"b":1} -SELECT COLUMN_JSON(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)); -COLUMN_JSON(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)) +SELECT COLUMN_JSON(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)) as ex; +ex {"a":1,"b":1} # # MDEV-7533: COLUMN_JSON() doesn't escape control characters @@ -1959,11 +1940,11 @@ DROP TABLE t1; # # MDEV-32140: Valgrind/MSAN warnings in dynamic_column_update_move_left # -SELECT COLUMN_GET(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL),3 AS INTEGER); -COLUMN_GET(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL),3 AS INTEGER) +SELECT COLUMN_GET(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL),3 AS INTEGER) as ex; +ex NULL -SELECT HEX(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL)); -HEX(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL)) +SELECT HEX(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL)) as ex; +ex 000000 # # End of 10.4 tests diff --git a/mysql-test/main/dyncol.test b/mysql-test/main/dyncol.test index f3594442009..70f4d0f0c6d 100644 --- a/mysql-test/main/dyncol.test +++ b/mysql-test/main/dyncol.test @@ -1,19 +1,17 @@ # # Dynamic column function test # -# enable view-protocol after fix MDEV-27871 --- source include/no_view_protocol.inc --source include/default_charset.inc --echo # --echo # column create --echo # -select hex(COLUMN_CREATE(1, NULL AS char character set utf8)); -select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8)); -select hex(COLUMN_CREATE(1, 1212 AS char character set utf8)); -select hex(COLUMN_CREATE(1, 12.12 AS char character set utf8)); -select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS char character set utf8)); +select hex(COLUMN_CREATE(1, NULL AS char character set utf8)) as exp; +select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8)) as ex; +select hex(COLUMN_CREATE(1, 1212 AS char character set utf8)) as ex; +select hex(COLUMN_CREATE(1, 12.12 AS char character set utf8)) as ex; +select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS char character set utf8)) as ex; select hex(COLUMN_CREATE(1, NULL AS unsigned int)); select hex(COLUMN_CREATE(1, 1212 AS unsigned int)); select hex(COLUMN_CREATE(1, 7 AS unsigned int)); @@ -23,7 +21,7 @@ select hex(COLUMN_CREATE(1, 128 AS unsigned int)); select hex(COLUMN_CREATE(1, 12.12 AS unsigned int)); select hex(COLUMN_CREATE(1, ~0)); select hex(COLUMN_CREATE(1, -1)); -select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS unsigned int)); +select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS unsigned int)) as ex; select hex(COLUMN_CREATE(1, NULL AS int)); select hex(COLUMN_CREATE(1, 1212 AS int)); select hex(COLUMN_CREATE(1, 7 AS int)); @@ -31,11 +29,11 @@ select hex(COLUMN_CREATE(1, 8 AS int)); select hex(COLUMN_CREATE(1, 127 AS int)); select hex(COLUMN_CREATE(1, 128 AS int)); select hex(COLUMN_CREATE(1, 12.12 AS int)); -select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS int)); +select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS int)) as ex; select hex(COLUMN_CREATE(1, NULL AS double)); select hex(COLUMN_CREATE(1, 1212 AS double)); select hex(COLUMN_CREATE(1, 12.12 AS double)); -select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS double)); +select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS double)) as ex; select hex(COLUMN_CREATE(1, NULL AS decimal)); select hex(COLUMN_CREATE(1, 1212 AS decimal)); select hex(COLUMN_CREATE(1, 7 AS decimal)); @@ -43,13 +41,13 @@ select hex(COLUMN_CREATE(1, 8 AS decimal)); select hex(COLUMN_CREATE(1, 127 AS decimal)); select hex(COLUMN_CREATE(1, 128 AS decimal)); select hex(COLUMN_CREATE(1, 12.12 AS decimal)); -select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS decimal)); +select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS decimal)) as ex; select hex(COLUMN_CREATE(1, NULL AS date)); select hex(COLUMN_CREATE(1, "2011-04-05" AS date)); select hex(COLUMN_CREATE(1, NULL AS time)); select hex(COLUMN_CREATE(1, "0:45:49.000001" AS time)); select hex(COLUMN_CREATE(1, NULL AS datetime)); -select hex(COLUMN_CREATE(1, "2011-04-05 0:45:49.000001" AS datetime)); +select hex(COLUMN_CREATE(1, "2011-04-05 0:45:49.000001" AS datetime)) as ex; select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8, 2, 1212 AS unsigned int, 3, 1212 AS int, @@ -57,7 +55,7 @@ select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8, 4+1, 12.12 AS decimal, 6, "2011-04-05" AS date, 7, "- 0:45:49.000001" AS time, - 8, "2011-04-05 0:45:49.000001" AS datetime)); + 8, "2011-04-05 0:45:49.000001" AS datetime)) as ex; explain extended select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8, 2, 1212 AS unsigned int, @@ -66,353 +64,353 @@ select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8, 4+1, 12.12 AS decimal, 6, "2011-04-05" AS date, 7, "- 0:45:49.000001" AS time, - 8, "2011-04-05 0:45:49.000001" AS datetime)); + 8, "2011-04-05 0:45:49.000001" AS datetime)) as ex; select hex(column_create(1, 0.0 AS decimal)); select hex(column_create(1, 1.0 AS decimal)); --echo # --echo # column get uint --echo # -select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int); +select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int) as ex; explain extended -select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int); +select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int) as ex; explain extended -select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned); -select column_get(column_create(1, 1212 AS decimal), 1 as unsigned int); -select column_get(column_create(1, 1212 AS double), 1 as unsigned int); -select column_get(column_create(1, 1212 AS int), 1 as unsigned int); -select column_get(column_create(1, "1212" AS char), 1 as unsigned int); -select column_get(column_create(1, "2011-04-05" AS date), 1 as unsigned int); -select column_get(column_create(1, "8:46:06.23434" AS time), 1 as unsigned int); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as unsigned int); -select column_get(column_create(1, NULL AS unsigned int), 1 as unsigned int); +select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned) as ex; +select column_get(column_create(1, 1212 AS decimal), 1 as unsigned int) as ex; +select column_get(column_create(1, 1212 AS double), 1 as unsigned int) as ex; +select column_get(column_create(1, 1212 AS int), 1 as unsigned int) as ex; +select column_get(column_create(1, "1212" AS char), 1 as unsigned int) as ex; +select column_get(column_create(1, "2011-04-05" AS date), 1 as unsigned int) as ex; +select column_get(column_create(1, "8:46:06.23434" AS time), 1 as unsigned int) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as unsigned int) as ex; +select column_get(column_create(1, NULL AS unsigned int), 1 as unsigned int) as ex; --echo # column geint truncation & warnings -select column_get(column_create(1, -1212 AS int), 1 as unsigned int); -select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as unsigned int); -select column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as unsigned int); -select column_get(column_create(1, -1 AS decimal), 1 as unsigned int); +select column_get(column_create(1, -1212 AS int), 1 as unsigned int) as ex; +select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as unsigned int) as ex; +select column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as unsigned int) as ex; +select column_get(column_create(1, -1 AS decimal), 1 as unsigned int) as ex; --replace_result e+029 e+29 -select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as unsigned int); -select column_get(column_create(1, 999.9 AS double), 1 as unsigned int); -select column_get(column_create(1, -1 AS double), 1 as unsigned int); -select column_get(column_create(1, "1212III" AS char), 1 as unsigned int); +select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as unsigned int) as ex; +select column_get(column_create(1, 999.9 AS double), 1 as unsigned int) as ex; +select column_get(column_create(1, -1 AS double), 1 as unsigned int) as ex; +select column_get(column_create(1, "1212III" AS char), 1 as unsigned int) as ex; --echo # --echo # column get int --echo # -select column_get(column_create(1, 1212 AS int), 1 as int); +select column_get(column_create(1, 1212 AS int), 1 as int) as ex; explain extended -select column_get(column_create(1, 1212 AS int), 1 as int); +select column_get(column_create(1, 1212 AS int), 1 as int) as ex; explain extended -select column_get(column_create(1, 1212 AS int), 1 as signed int); -select column_get(column_create(1, -1212 AS int), 1 as int); -select column_get(column_create(1, 1212 AS decimal), 1 as int); -select column_get(column_create(1, 1212 AS double), 1 as int); -select column_get(column_create(1, 1212 AS unsigned int), 1 as int); -select column_get(column_create(1, "1212" AS char), 1 as int); -select column_get(column_create(1, "-1212" AS char), 1 as int); -select column_get(column_create(1, "2011-04-05" AS date), 1 as int); -select column_get(column_create(1, "8:46:06.23434" AS time), 1 as int); -select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as int); -select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as int); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as int); -select column_get(column_create(1, NULL AS int), 1 as int); +select column_get(column_create(1, 1212 AS int), 1 as signed int) as ex; +select column_get(column_create(1, -1212 AS int), 1 as int) as ex; +select column_get(column_create(1, 1212 AS decimal), 1 as int) as ex; +select column_get(column_create(1, 1212 AS double), 1 as int) as ex; +select column_get(column_create(1, 1212 AS unsigned int), 1 as int) as ex; +select column_get(column_create(1, "1212" AS char), 1 as int) as ex; +select column_get(column_create(1, "-1212" AS char), 1 as int) as ex; +select column_get(column_create(1, "2011-04-05" AS date), 1 as int) as ex; +select column_get(column_create(1, "8:46:06.23434" AS time), 1 as int) as ex; +select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as int) as ex; +select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as int) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as int) as ex; +select column_get(column_create(1, NULL AS int), 1 as int) as ex; --echo #column gett truncation & warnings -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as int); -select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as int); -select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as int); -select column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as int); -select column_get(column_create(1, 999.9 AS double), 1 as int); +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as int) as ex; +select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as int) as ex; +select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as int) as ex; +select column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as int) as ex; +select column_get(column_create(1, 999.9 AS double), 1 as int) as ex; --replace_result e+029 e+29 -select column_get(column_create(1, -99999999999999999999999999999 AS double), 1 as int); -select column_get(column_create(1, "-1212III" AS char), 1 as int); -select column_get(column_create(1, "1212III" AS char), 1 as int); -select column_get(COLUMN_CREATE(1, ~0), 1 as signed); -select column_get(COLUMN_CREATE(1, ~0), 1 as unsigned); -select column_get(COLUMN_CREATE(1, -1), 1 as signed); -select column_get(COLUMN_CREATE(1, -1), 1 as unsigned); +select column_get(column_create(1, -99999999999999999999999999999 AS double), 1 as int) as ex; +select column_get(column_create(1, "-1212III" AS char), 1 as int) as ex; +select column_get(column_create(1, "1212III" AS char), 1 as int) as ex; +select column_get(COLUMN_CREATE(1, ~0), 1 as signed) as ex; +select column_get(COLUMN_CREATE(1, ~0), 1 as unsigned) as ex; +select column_get(COLUMN_CREATE(1, -1), 1 as signed) as ex; +select column_get(COLUMN_CREATE(1, -1), 1 as unsigned) as ex; --echo # --echo #column get char --echo # -select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8); +select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8) as ex; explain extended -select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8); -select column_get(column_create(1, 1212 AS unsigned int), 1 as char charset utf8); -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as char charset utf8); -select column_get(column_create(1, 1212 AS int), 1 as char charset utf8); -select column_get(column_create(1, -1212 AS int), 1 as char charset utf8); -select column_get(column_create(1, 9223372036854775807 AS int), 1 as char charset utf8); -select column_get(column_create(1, -9223372036854775808 AS int), 1 as char charset utf8); -select column_get(column_create(1, 1212.12 AS decimal), 1 as char charset utf8); -select column_get(column_create(1, 1212.12 AS double), 1 as char charset utf8); -select column_get(column_create(1, "2011-04-05" AS date), 1 as char charset utf8); -select column_get(column_create(1, "8:46:06.23434" AS time), 1 as char charset utf8); -select column_get(column_create(1, "8:46:06.23434" AS time(0)), 1 as char charset utf8); -select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as char charset utf8); -select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as char charset utf8); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as char charset utf8); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(0)), 1 as char charset utf8); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as char charset utf8); -select column_get(column_create(1, NULL AS char charset utf8), 1 as char charset utf8); -select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary); +select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8) as ex; +select column_get(column_create(1, 1212 AS unsigned int), 1 as char charset utf8) as ex; +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as char charset utf8) as ex; +select column_get(column_create(1, 1212 AS int), 1 as char charset utf8) as ex; +select column_get(column_create(1, -1212 AS int), 1 as char charset utf8) as ex; +select column_get(column_create(1, 9223372036854775807 AS int), 1 as char charset utf8) as ex; +select column_get(column_create(1, -9223372036854775808 AS int), 1 as char charset utf8) as ex; +select column_get(column_create(1, 1212.12 AS decimal), 1 as char charset utf8) as ex; +select column_get(column_create(1, 1212.12 AS double), 1 as char charset utf8) as ex; +select column_get(column_create(1, "2011-04-05" AS date), 1 as char charset utf8) as ex; +select column_get(column_create(1, "8:46:06.23434" AS time), 1 as char charset utf8) as ex; +select column_get(column_create(1, "8:46:06.23434" AS time(0)), 1 as char charset utf8) as ex; +select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as char charset utf8) as ex; +select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as char charset utf8) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as char charset utf8) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(0)), 1 as char charset utf8) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as char charset utf8) as ex; +select column_get(column_create(1, NULL AS char charset utf8), 1 as char charset utf8) as ex; +select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary) as ex; explain extended -select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary); +select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary) as ex; --echo # --echo # column get real --echo # -select column_get(column_create(1, 1212.12 AS double), 1 as double); +select column_get(column_create(1, 1212.12 AS double), 1 as double) as ex; explain extended -select column_get(column_create(1, 1212.12 AS double), 1 as double); +select column_get(column_create(1, 1212.12 AS double), 1 as double) as ex; explain extended -select column_get(column_create(1, 1212.12 AS double), 1 as double(6,2)); -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as double); -select column_get(column_create(1, 9223372036854775807 AS int), 1 as double); -select column_get(column_create(1, -9223372036854775808 AS int), 1 as double); -select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as double); -select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as double); -select column_get(column_create(1, "2011-04-05" AS date), 1 as double); -select column_get(column_create(1, "8:46:06.23434" AS time), 1 as double); -select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as double); -select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as double); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as double); +select column_get(column_create(1, 1212.12 AS double), 1 as double(6,2)) as ex; +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as double) as ex; +select column_get(column_create(1, 9223372036854775807 AS int), 1 as double) as ex; +select column_get(column_create(1, -9223372036854775808 AS int), 1 as double) as ex; +select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as double) as ex; +select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as double) as ex; +select column_get(column_create(1, "2011-04-05" AS date), 1 as double) as ex; +select column_get(column_create(1, "8:46:06.23434" AS time), 1 as double) as ex; +select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as double) as ex; +select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as double) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime(6)), 1 as double) as ex; # The replace result is needed for windows. -select round(column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double(20,6)),3); -select column_get(column_create(1, NULL AS double), 1 as double); +select round(column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double(20,6)),3) as ex; +select column_get(column_create(1, NULL AS double), 1 as double) as ex; -- echo # column get real truncation & warnings -select column_get(column_create(1, "1223.5aa" AS char), 1 as double); -select column_get(column_create(1, "aa" AS char), 1 as double); -select column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2)); -select column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2)); +select column_get(column_create(1, "1223.5aa" AS char), 1 as double) as ex; +select column_get(column_create(1, "aa" AS char), 1 as double) as ex; +select column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2)) as ex; +select column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2)) as ex; --echo # --echo # column get decimal --echo # -select column_get(column_create(1, 1212.12 AS double), 1 as decimal); -select column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2)); +select column_get(column_create(1, 1212.12 AS double), 1 as decimal) as ex; +select column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2)) as ex; explain extended -select column_get(column_create(1, 1212.12 AS double), 1 as decimal); +select column_get(column_create(1, 1212.12 AS double), 1 as decimal) as ex; explain extended -select column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2)); -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal(20,0)); -select column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal(32,0)); -select column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal(32,0)); -select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as decimal(40,10)); -select column_get(column_create(1, "2011-04-05" AS date), 1 as decimal(32,6)); -select column_get(column_create(1, "8:46:06.23434" AS time), 1 as decimal(32,6)); -select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as decimal(32,6)); -select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as decimal(32,6)); -select column_get(column_create(1, "2011-04-05 8:46:06.123456" AS datetime), 1 as decimal(32,6)); -select column_get(column_create(1, "2011-04-05 8:46:06.123456" AS datetime(6)), 1 as decimal(32,6)); -select column_get(column_create(1, "2011-04-05 8:46:06.12345678" AS datetime(6)), 1 as decimal(32,8)); -select column_get(column_create(1, NULL as decimal), 1 as decimal(32,10)); -select column_get(column_create(1, "1223.5555" as decimal(10,5)), 1 as decimal(6,2)); +select column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2)) as ex; +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal(20,0)) as ex; +select column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal(32,0)) as ex; +select column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal(32,0)) as ex; +select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as decimal(40,10)) as ex; +select column_get(column_create(1, "2011-04-05" AS date), 1 as decimal(32,6)) as ex; +select column_get(column_create(1, "8:46:06.23434" AS time), 1 as decimal(32,6)) as ex; +select column_get(column_create(1, "8:46:06.23434" AS time(6)), 1 as decimal(32,6)) as ex; +select column_get(column_create(1, "-808:46:06.23434" AS time(6)), 1 as decimal(32,6)) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.123456" AS datetime), 1 as decimal(32,6)) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.123456" AS datetime(6)), 1 as decimal(32,6)) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.12345678" AS datetime(6)), 1 as decimal(32,8)) as ex; +select column_get(column_create(1, NULL as decimal), 1 as decimal(32,10)) as ex; +select column_get(column_create(1, "1223.5555" as decimal(10,5)), 1 as decimal(6,2)) as ex; -- echo # column get decimal truncation & warnings -select column_get(column_create(1, "1223.5aa" AS char), 1 as decimal(32,10)); -select column_get(column_create(1, "aa" AS char), 1 as decimal(32,10)); -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal); -select column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal); -select column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal); -select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as decimal); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal); -select column_get(column_create(1, "1223.5555" as double), 1 as decimal(5,2)); -select column_get(column_create(1, "-1223.5555" as double), 1 as decimal(5,2)); -select column_get(column_create(1, "1223.5555" AS double), 1 as decimal(3,2)); -select column_get(column_create(1, "1223.5555" AS decimal(10,5)), 1 as decimal(3,2)); -select column_get(column_create(1, 0.0 AS decimal,2, 0.0 as decimal), 1 as decimal); +select column_get(column_create(1, "1223.5aa" AS char), 1 as decimal(32,10)) as ex; +select column_get(column_create(1, "aa" AS char), 1 as decimal(32,10)) as ex; +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal) as ex; +select column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal) as ex; +select column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal) as ex; +select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as decimal) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal) as ex; +select column_get(column_create(1, "1223.5555" as double), 1 as decimal(5,2)) as ex; +select column_get(column_create(1, "-1223.5555" as double), 1 as decimal(5,2)) as ex; +select column_get(column_create(1, "1223.5555" AS double), 1 as decimal(3,2)) as ex; +select column_get(column_create(1, "1223.5555" AS decimal(10,5)), 1 as decimal(3,2)) as ex; +select column_get(column_create(1, 0.0 AS decimal,2, 0.0 as decimal), 1 as decimal) as ex; --echo # --echo # column get datetime --echo # -select column_get(column_create(1, 20010203101112.121314 as double), 1 as datetime); -select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as datetime); -select column_get(column_create(1, 20010203101112 as unsigned int), 1 as datetime); -select column_get(column_create(1, 20010203101112 as int), 1 as datetime); -select column_get(column_create(1, "20010203101112" as char), 1 as datetime); -select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as datetime); -select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as datetime); -select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as datetime); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime(0)); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime(6)); -select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as datetime); -select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as datetime); +select column_get(column_create(1, 20010203101112.121314 as double), 1 as datetime) as ex; +select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as datetime) as ex; +select column_get(column_create(1, 20010203101112 as unsigned int), 1 as datetime) as ex; +select column_get(column_create(1, 20010203101112 as int), 1 as datetime) as ex; +select column_get(column_create(1, "20010203101112" as char), 1 as datetime) as ex; +select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as datetime) as ex; +select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as datetime) as ex; +select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as datetime) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime(0)) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime(6)) as ex; +select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as datetime) as ex; +select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as datetime) as ex; -select column_get(column_create(1, 20010203 as unsigned int), 1 as datetime); -select column_get(column_create(1, 20010203 as int), 1 as datetime); -select column_get(column_create(1, 20010203), 1 as datetime); -select column_get(column_create(1, 20010203.0), 1 as datetime); -select column_get(column_create(1, 20010203.0 as double), 1 as datetime); -select column_get(column_create(1, "2001-02-03"), 1 as datetime); -select column_get(column_create(1, "20010203"), 1 as datetime); -select column_get(column_create(1, 0), 1 as datetime); -select column_get(column_create(1, "2001021"), 1 as datetime); +select column_get(column_create(1, 20010203 as unsigned int), 1 as datetime) as ex; +select column_get(column_create(1, 20010203 as int), 1 as datetime) as ex; +select column_get(column_create(1, 20010203), 1 as datetime) as ex; +select column_get(column_create(1, 20010203.0), 1 as datetime) as ex; +select column_get(column_create(1, 20010203.0 as double), 1 as datetime) as ex; +select column_get(column_create(1, "2001-02-03"), 1 as datetime) as ex; +select column_get(column_create(1, "20010203"), 1 as datetime) as ex; +select column_get(column_create(1, 0), 1 as datetime) as ex; +select column_get(column_create(1, "2001021"), 1 as datetime) as ex; SET timestamp=unix_timestamp('2001-02-03 10:20:30'); -select column_get(column_create(1, "8:46:06.23434" AS time), 1 as datetime); -select column_get(column_create(1, "-808:46:06.23434" AS time), 1 as datetime); +select column_get(column_create(1, "8:46:06.23434" AS time), 1 as datetime) as ex; +select column_get(column_create(1, "-808:46:06.23434" AS time), 1 as datetime) as ex; SET timestamp=DEFAULT; set @@sql_mode="allow_invalid_dates"; -select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as datetime); -select column_get(column_create(1, "0000-00-000" AS CHAR), 1 as datetime); -select column_get(column_create(1, "2001-00-02" AS CHAR), 1 as datetime); +select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as datetime) as ex; +select column_get(column_create(1, "0000-00-000" AS CHAR), 1 as datetime) as ex; +select column_get(column_create(1, "2001-00-02" AS CHAR), 1 as datetime) as ex; set @@sql_mode=""; -- echo # column get datetime truncation & warnings -select column_get(column_create(1, "1223.5aa" AS char), 1 as datetime); +select column_get(column_create(1, "1223.5aa" AS char), 1 as datetime) as ex; --replace_result e+019 e+19 -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as datetime); -select column_get(column_create(1, 9223372036854775807 AS int), 1 as datetime); -select column_get(column_create(1, -9223372036854775808 AS int), 1 as datetime); -select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as datetime); +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as datetime) as ex; +select column_get(column_create(1, 9223372036854775807 AS int), 1 as datetime) as ex; +select column_get(column_create(1, -9223372036854775808 AS int), 1 as datetime) as ex; +select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as datetime) as ex; --replace_result e+029 e+29 -select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as datetime); -select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as datetime); -select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as datetime); -select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as datetime); -select column_get(column_create(1, "20010231"), 1 as datetime); -select column_get(column_create(1, "0" AS CHAR), 1 as datetime); +select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as datetime) as ex; +select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as datetime) as ex; +select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as datetime) as ex; +select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as datetime) as ex; +select column_get(column_create(1, "20010231"), 1 as datetime) as ex; +select column_get(column_create(1, "0" AS CHAR), 1 as datetime) as ex; --echo # --echo # column get date --echo # -select column_get(column_create(1, 20010203101112.121314 as double), 1 as date); -select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as date); -select column_get(column_create(1, 20010203101112 as unsigned int), 1 as date); -select column_get(column_create(1, 20010203101112 as int), 1 as date); -select column_get(column_create(1, "20010203101112" as char), 1 as date); -select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as date); -select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as date); -select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as date); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as date); -select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as date); -select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as date); +select column_get(column_create(1, 20010203101112.121314 as double), 1 as date) as ex; +select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as date) as ex; +select column_get(column_create(1, 20010203101112 as unsigned int), 1 as date) as ex; +select column_get(column_create(1, 20010203101112 as int), 1 as date) as ex; +select column_get(column_create(1, "20010203101112" as char), 1 as date) as ex; +select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as date) as ex; +select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as date) as ex; +select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as date) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as date) as ex; +select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as date) as ex; +select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as date) as ex; -select column_get(column_create(1, 20010203 as unsigned int), 1 as date); -select column_get(column_create(1, 20010203 as int), 1 as date); -select column_get(column_create(1, 20010203), 1 as date); -select column_get(column_create(1, 20010203.0), 1 as date); -select column_get(column_create(1, 20010203.0 as double), 1 as date); -select column_get(column_create(1, "2001-02-03"), 1 as date); -select column_get(column_create(1, "20010203"), 1 as date); -select column_get(column_create(1, 0), 1 as date); -select column_get(column_create(1, "2001021"), 1 as date); +select column_get(column_create(1, 20010203 as unsigned int), 1 as date) as ex; +select column_get(column_create(1, 20010203 as int), 1 as date) as ex; +select column_get(column_create(1, 20010203), 1 as date) as ex; +select column_get(column_create(1, 20010203.0), 1 as date) as ex; +select column_get(column_create(1, 20010203.0 as double), 1 as date) as ex; +select column_get(column_create(1, "2001-02-03"), 1 as date) as ex; +select column_get(column_create(1, "20010203"), 1 as date) as ex; +select column_get(column_create(1, 0), 1 as date) as ex; +select column_get(column_create(1, "2001021"), 1 as date) as ex; set @@sql_mode="allow_invalid_dates"; -select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as date); -select column_get(column_create(1, "0000-00-000" AS CHAR), 1 as date); -select column_get(column_create(1, "2001-00-02" AS CHAR), 1 as date); +select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as date) as ex; +select column_get(column_create(1, "0000-00-000" AS CHAR), 1 as date) as ex; +select column_get(column_create(1, "2001-00-02" AS CHAR), 1 as date) as ex; set @@sql_mode=""; -- echo # column get date truncation & warnings -select column_get(column_create(1, "1223.5aa" AS char), 1 as date); +select column_get(column_create(1, "1223.5aa" AS char), 1 as date) as ex; --replace_result e+019 e+19 -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as date); -select column_get(column_create(1, 9223372036854775807 AS int), 1 as date); -select column_get(column_create(1, -9223372036854775808 AS int), 1 as date); -select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as date); +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as date) as ex; +select column_get(column_create(1, 9223372036854775807 AS int), 1 as date) as ex; +select column_get(column_create(1, -9223372036854775808 AS int), 1 as date) as ex; +select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as date) as ex; --replace_result e+029 e+29 -select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as date); -select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as date); -select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as date); -select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as date); -select column_get(column_create(1, "20010231"), 1 as date); -select column_get(column_create(1, "0" AS CHAR), 1 as date); +select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as date) as ex; +select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as date) as ex; +select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as date) as ex; +select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as date) as ex; +select column_get(column_create(1, "20010231"), 1 as date) as ex; +select column_get(column_create(1, "0" AS CHAR), 1 as date) as ex; --echo # --echo # column get time --echo # -select column_get(column_create(1, 20010203101112.121314 as double), 1 as time); -select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as time); -select column_get(column_create(1, 20010203101112 as unsigned int), 1 as time); -select column_get(column_create(1, 8080102 as unsigned int), 1 as time); -select column_get(column_create(1, 20010203101112 as int), 1 as time); -select column_get(column_create(1, -8080102 as int), 1 as time); -select column_get(column_create(1, "20010203101112" as char), 1 as time); -select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as time); -select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time); -select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time(6)); -select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as time); -select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as time(6)); -select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as time(6)); -select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as time(6)); -select column_get(column_create(1, "830:46:06.23434" AS CHAR), 1 as time(6)); -select column_get(column_create(1, "830:46:06" AS CHAR), 1 as time(6)); -select cast("-830:46:06.23434" AS time(6)); -select 1,cast("-830:46:06.23434" AS time(6)); -select hex(column_create(1, "-830:46:06.23434" AS CHAR)); -select column_get(column_create(1, "-830:46:06.23434" AS CHAR), 1 as time(6)); -select column_get(column_create(1, "0" AS CHAR), 1 as time); -select column_get(column_create(1, "6" AS CHAR), 1 as time); -select column_get(column_create(1, "1:6" AS CHAR), 1 as time); -select column_get(column_create(1, "2:1:6" AS CHAR), 1 as time); +select column_get(column_create(1, 20010203101112.121314 as double), 1 as time) as ex; +select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as time) as ex; +select column_get(column_create(1, 20010203101112 as unsigned int), 1 as time) as ex; +select column_get(column_create(1, 8080102 as unsigned int), 1 as time) as ex; +select column_get(column_create(1, 20010203101112 as int), 1 as time) as ex; +select column_get(column_create(1, -8080102 as int), 1 as time) as ex; +select column_get(column_create(1, "20010203101112" as char), 1 as time) as ex; +select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as time) as ex; +select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time) as ex; +select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time(6)) as ex; +select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as time) as ex; +select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as time(6)) as ex; +select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as time(6)) as ex; +select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as time(6)) as ex; +select column_get(column_create(1, "830:46:06.23434" AS CHAR), 1 as time(6)) as ex; +select column_get(column_create(1, "830:46:06" AS CHAR), 1 as time(6)) as ex; +select cast("-830:46:06.23434" AS time(6)) as ex; +select 1,cast("-830:46:06.23434" AS time(6)) as ex; +select hex(column_create(1, "-830:46:06.23434" AS CHAR)) as ex; +select column_get(column_create(1, "-830:46:06.23434" AS CHAR), 1 as time(6)) as ex; +select column_get(column_create(1, "0" AS CHAR), 1 as time) as ex; +select column_get(column_create(1, "6" AS CHAR), 1 as time) as ex; +select column_get(column_create(1, "1:6" AS CHAR), 1 as time) as ex; +select column_get(column_create(1, "2:1:6" AS CHAR), 1 as time) as ex; -select column_get(column_create(1, 0), 1 as time); -select column_get(column_create(1, "2001021"), 1 as time); +select column_get(column_create(1, 0), 1 as time) as ex; +select column_get(column_create(1, "2001021"), 1 as time) as ex; set @@sql_mode="allow_invalid_dates"; -select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as time); +select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as time) as ex; set @@sql_mode=""; -- echo # column get date truncation & warnings -select column_get(column_create(1, "1223.5aa" AS char), 1 as time); -select column_get(column_create(1, "1223.5aa" AS char), 1 as time(3)); +select column_get(column_create(1, "1223.5aa" AS char), 1 as time) as ex; +select column_get(column_create(1, "1223.5aa" AS char), 1 as time(3)) as ex; --replace_result e+019 e+19 -select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as time); -select column_get(column_create(1, 9223372036854775807 AS int), 1 as time); -select column_get(column_create(1, -9223372036854775808 AS int), 1 as time); -select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as time); +select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as time) as ex; +select column_get(column_create(1, 9223372036854775807 AS int), 1 as time) as ex; +select column_get(column_create(1, -9223372036854775808 AS int), 1 as time) as ex; +select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as time) as ex; --replace_result e+029 e+29 -select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as time); -select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as time); -select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as time); -select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as time); -select column_get(column_create(1, "2001-02-03"), 1 as time); -select column_get(column_create(1, "20010203"), 1 as time); +select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as time) as ex; +select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as time) as ex; +select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as time) as ex; +select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as time) as ex; +select column_get(column_create(1, "2001-02-03"), 1 as time) as ex; +select column_get(column_create(1, "20010203"), 1 as time) as ex; -- echo # column add -select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer)); -select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer)); -select hex(column_add(column_create(1, 1212 as integer), 1, NULL as integer)); -select hex(column_add(column_create(1, 1212 as integer), 2, NULL as integer)); -select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer)); -select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 1 as integer); -select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 2 as integer); -select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer, 2, 11 as integer)); -select hex(column_add(column_create(1, NULL as integer), 1, 1212 as integer, 2, 11 as integer)); -select hex(column_add(column_create(1, 1212 as integer, 2, 1212 as integer), 1, 11 as integer)); -select hex(column_add(column_create(1, 1), 1, null)); -select column_list(column_add(column_create(1, 1), 1, null)); -select column_list(column_add(column_create(1, 1), 1, "")); -select hex(column_add("", 1, 1)); +select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer)) as ex; +select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer)) as ex; +select hex(column_add(column_create(1, 1212 as integer), 1, NULL as integer)) as ex; +select hex(column_add(column_create(1, 1212 as integer), 2, NULL as integer)) as ex; +select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer)) as ex; +select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 1 as integer) as ex; +select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 2 as integer) as ex; +select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer, 2, 11 as integer)) as ex; +select hex(column_add(column_create(1, NULL as integer), 1, 1212 as integer, 2, 11 as integer)) as ex; +select hex(column_add(column_create(1, 1212 as integer, 2, 1212 as integer), 1, 11 as integer)) as ex; +select hex(column_add(column_create(1, 1), 1, null)) as ex; +select column_list(column_add(column_create(1, 1), 1, null)) as ex; +select column_list(column_add(column_create(1, 1), 1, "")) as ex; +select hex(column_add("", 1, 1)) as ex; -- echo # column delete -select hex(column_delete(column_create(1, 1212 as integer, 2, 1212 as integer), 1)); -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2)); -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 3)); -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 4)); -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 1)); -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 3)); -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3)); -select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3, 10)); -select hex(column_delete(column_create(1, 1), 1)); -select hex(column_delete("", 1)); +select hex(column_delete(column_create(1, 1212 as integer, 2, 1212 as integer), 1)) as ex; +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2)) as ex; +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 3)) as ex; +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 4)) as ex; +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 1)) as ex; +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 3)) as ex; +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3)) as ex; +select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3, 10)) as ex; +select hex(column_delete(column_create(1, 1), 1)) as ex; +select hex(column_delete("", 1)) as ex; -- echo # column exists -select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 1); -select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4); +select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 1) as ex; +select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4) as ex; -- echo # column list -select column_list(column_create(1, 1212 as integer, 2, 1212 as integer)); -select column_list(column_create(1, 1212 as integer)); -select column_list(column_create(1, NULL as integer)); +select column_list(column_create(1, 1212 as integer, 2, 1212 as integer)) as ex; +select column_list(column_create(1, 1212 as integer)) as ex; +select column_list(column_create(1, NULL as integer)) as ex; --echo # --echo # check error handling @@ -551,11 +549,11 @@ select column_add(@a, 3, "a"); set @a=0x00020008000009000C2C010080; select COLUMN_GET(@a, 9 AS DECIMAL); -select hex(COLUMN_CREATE(0, COLUMN_GET(@a, 9 AS DECIMAL))); -select hex(COLUMN_CREATE(0, COLUMN_GET(@a, 9 AS DECIMAL(19,0)))); +select hex(COLUMN_CREATE(0, COLUMN_GET(@a, 9 AS DECIMAL))) as ex; +select hex(COLUMN_CREATE(0, COLUMN_GET(@a, 9 AS DECIMAL(19,0)))) as ex; -select hex(COLUMN_CREATE(0, COLUMN_GET(COLUMN_CREATE(0, 0.0 as decimal), 0 as decimal))); -select hex(COLUMN_CREATE(0, 0.0 as decimal)); +select hex(COLUMN_CREATE(0, COLUMN_GET(COLUMN_CREATE(0, 0.0 as decimal), 0 as decimal))) as ex; +select hex(COLUMN_CREATE(0, 0.0 as decimal)) as ex; --echo # --echo # MDEV-4292: parse error when selecting on views using dynamic column @@ -635,11 +633,11 @@ CREATE TABLE t1 (dyncol TINYBLOB) ENGINE=MyISAM; INSERT INTO t1 SET dyncol = COLUMN_CREATE( 7, REPEAT('k',487), 209, REPEAT('x',464) ); --error 0,ER_DYN_COL_WRONG_FORMAT -SELECT COLUMN_ADD( dyncol, 7, '22:22:22', 8, REPEAT('x',270) AS CHAR ) FROM t1; +SELECT COLUMN_ADD( dyncol, 7, '22:22:22', 8, REPEAT('x',270) AS CHAR ) as ex FROM t1; delete from t1; INSERT INTO t1 SET dyncol = COLUMN_CREATE( 'a', REPEAT('k',487), 'b', REPEAT('x',464) ); --error 0,ER_DYN_COL_WRONG_FORMAT -SELECT COLUMN_ADD( dyncol, 'a', '22:22:22', 'c', REPEAT('x',270) AS CHAR ) FROM t1; +SELECT COLUMN_ADD( dyncol, 'a', '22:22:22', 'c', REPEAT('x',270) AS CHAR ) as ex FROM t1; DROP table t1; @@ -658,7 +656,7 @@ SELECT # MySQL Bug#16997513 MY_STRTOLL10 ACCEPTING OVERFLOWED UNSIGNED LONG LONG VALUES AS NORMAL ONES # (incorrect overflow check in my_strtoll10()) # -select column_get(column_create(1, "18446744073709552001" as char), 1 as int); +select column_get(column_create(1, "18446744073709552001" as char), 1 as int) as ex; --echo # --echo # MDEV-7505 - Too large scale in DECIMAL dynamic column getter crashes @@ -672,71 +670,80 @@ SELECT COLUMN_GET(`x`, 'y' AS DECIMAL(5,50)); --echo # --echo # creation test (names) set names utf8; +#enable after MDEV-32465 fix +--disable_view_protocol select hex(column_create("адын", 1212)); +--enable_view_protocol select hex(column_create("1212", 1212)); select hex(column_create(1212, 2, "www", 3)); select hex(column_create("1212", 2, "www", 3)); select hex(column_create("1212", 2, 3, 3)); +#enable after MDEV-32465 fix +--disable_view_protocol select hex(column_create("1212", 2, "адын", 1, 3, 3)); +--enable_view_protocol set names latin1; --echo # fetching column test (names) set names utf8; -select column_get(column_create("адын", 1212), "адын" as int); -select column_get(column_create("1212", 2, "адын", 1, 3, 3), "адын" as int); -select column_get(column_create("1212", 2, "адын", 1, 3, 3), 1212 as int); -select column_get(column_create("1212", 2, "адын", 1, 3, 3), "3" as int); -select column_get(column_create("1212", 2, "адын", 1, 3, 3), 3 as int); -select column_get(column_create("1212", 2, "адын", 1, 3, 3), 4 as int); -select column_get(column_create("1212", 2, "адын", 1, 3, 3), "4" as int); +select column_get(column_create("адын", 1212), "адын" as int) as ex; +select column_get(column_create("1212", 2, "адын", 1, 3, 3), "адын" as int) as ex; +select column_get(column_create("1212", 2, "адын", 1, 3, 3), 1212 as int) as ex; +select column_get(column_create("1212", 2, "адын", 1, 3, 3), "3" as int) as ex; +select column_get(column_create("1212", 2, "адын", 1, 3, 3), 3 as int) as ex; +select column_get(column_create("1212", 2, "адын", 1, 3, 3), 4 as int) as ex; +select column_get(column_create("1212", 2, "адын", 1, 3, 3), "4" as int) as ex; set names latin1; --echo # column existance test (names) set names utf8; -select column_exists(column_create("адын", 1212), "адын"); -select column_exists(column_create("адын", 1212), "aады"); -select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "адын"); -select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 1212); -select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "3"); -select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 3); -select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 4); -select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "4"); +select column_exists(column_create("адын", 1212), "адын") as ex; +select column_exists(column_create("адын", 1212), "aады") as ex; +select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "адын") as ex; +select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 1212) as ex; +select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "3") as ex; +select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 3) as ex; +select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 4) as ex; +select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "4") as ex; set names latin1; --echo # column changing test (names) -select hex(column_add(column_create(1, "AAA"), "b", "BBB")); -select hex(column_add(column_create("1", "AAA"), "b", "BBB")); -select column_get(column_add(column_create(1, "AAA"), "b", "BBB"), 1 as char); -select column_get(column_add(column_create(1, "AAA"), "b", "BBB"), "b" as char); -select hex(column_add(column_create("a", "AAA"), 1, "BBB")); -select hex(column_add(column_create("a", "AAA"), "1", "BBB")); -select hex(column_add(column_create("a", 1212 as integer), "b", "1212" as integer)); -select hex(column_add(column_create("a", 1212 as integer), "a", "1212" as integer)); -select hex(column_add(column_create("a", 1212 as integer), "a", NULL as integer)); -select hex(column_add(column_create("a", 1212 as integer), "b", NULL as integer)); -select hex(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer)); -select column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "a" as integer); -select column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "b" as integer); -select hex(column_add(column_create("a", 1212 as integer), "a", 1212 as integer, "b", 11 as integer)); -select hex(column_add(column_create("a", NULL as integer), "a", 1212 as integer, "b", 11 as integer)); -select hex(column_add(column_create("a", 1212 as integer, "b", 1212 as integer), "a", 11 as integer)); -select hex(column_add(column_create("a", 1), "a", null)); -select column_list(column_add(column_create("a", 1), "a", null)); -select column_list(column_add(column_create("a", 1), "a", "")); -select hex(column_add("", "a", 1)); +#enable after MDEV-32465 fix +--disable_view_protocol +select hex(column_add(column_create(1, "AAA"), "b", "BBB")) as ex; +select hex(column_add(column_create("1", "AAA"), "b", "BBB")) as ex; +select column_get(column_add(column_create(1, "AAA"), "b", "BBB"), 1 as char) as ex; +select column_get(column_add(column_create(1, "AAA"), "b", "BBB"), "b" as char) as ex; +select hex(column_add(column_create("a", "AAA"), 1, "BBB")) as ex; +select hex(column_add(column_create("a", "AAA"), "1", "BBB")) as ex; +--enable_view_protocol +select hex(column_add(column_create("a", 1212 as integer), "b", "1212" as integer)) as ex; +select hex(column_add(column_create("a", 1212 as integer), "a", "1212" as integer)) as ex; +select hex(column_add(column_create("a", 1212 as integer), "a", NULL as integer)) as ex; +select hex(column_add(column_create("a", 1212 as integer), "b", NULL as integer)) as ex; +select hex(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer)) as ex; +select column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "a" as integer) as ex; +select column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "b" as integer) as ex; +select hex(column_add(column_create("a", 1212 as integer), "a", 1212 as integer, "b", 11 as integer)) as ex; +select hex(column_add(column_create("a", NULL as integer), "a", 1212 as integer, "b", 11 as integer)) as ex; +select hex(column_add(column_create("a", 1212 as integer, "b", 1212 as integer), "a", 11 as integer)) as ex; +select hex(column_add(column_create("a", 1), "a", null)) as ex; +select column_list(column_add(column_create("a", 1), "a", null)) as ex; +select column_list(column_add(column_create("a", 1), "a", "")) as ex; +select hex(column_add("", "a", 1)) as ex; -- echo # column delete (names) -select hex(column_delete(column_create("a", 1212 as integer, "b", 1212 as integer), "a")); -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b")); -select hex(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer)); -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "c")); -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "d")); -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "a")); -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "c")); -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c")); -select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c", "e")); -select hex(column_delete(column_create("a", 1), "a")); -select hex(column_delete("", "a")); +select hex(column_delete(column_create("a", 1212 as integer, "b", 1212 as integer), "a")) as ex; +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b")) as ex; +select hex(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer)) as ex; +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "c")) as ex; +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "d")) as ex; +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "a")) as ex; +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "c")) as ex; +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c")) as ex; +select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c", "e")) as ex; +select hex(column_delete(column_create("a", 1), "a")) as ex; +select hex(column_delete("", "a")) as ex; --echo # --echo # MDEV-458 DNAMES: Server crashes on using an unquoted string @@ -765,12 +772,12 @@ drop table t1; --echo # --echo # MDEV-490/MDEV-491 null as arguments --echo # -SELECT COLUMN_GET( COLUMN_CREATE( 'col', 'val' ), NULL AS CHAR ); -SELECT COLUMN_GET( NULL, 'col' as char ); -SELECT COLUMN_EXISTS( COLUMN_CREATE( 'col', 'val' ), NULL); -SELECT COLUMN_EXISTS( NULL, 'col'); -SELECT COLUMN_CREATE( NULL, 'val' ); -SELECT COLUMN_ADD( NULL, 'val', 'col'); +SELECT COLUMN_GET( COLUMN_CREATE( 'col', 'val' ), NULL AS CHAR ) as ex; +SELECT COLUMN_GET( NULL, 'col' as char ) as ex; +SELECT COLUMN_EXISTS( COLUMN_CREATE( 'col', 'val' ), NULL) as ex; +SELECT COLUMN_EXISTS( NULL, 'col') as ex; +SELECT COLUMN_CREATE( NULL, 'val' ) as ex; +SELECT COLUMN_ADD( NULL, 'val', 'col') as ex; --echo # --echo # MDEV-488: Assertion `column_name->length < 255' failed on a @@ -783,8 +790,8 @@ SELECT hex(COLUMN_CREATE(REPEAT('a',65536),1)); --echo # --echo # JSON conversion --echo # -select column_json(column_create("int", -1212 as int, "uint", 12334 as unsigned int, "decimal", "23.344" as decimal, "double", 1.23444e50 as double, "string", 'gdgd\\dhdjh"dhdhd' as char, "time", "0:45:49.000001" AS time, "datetime", "2011-04-05 0:45:49.000001" AS datetime, "date", "2011-04-05" AS date)); -select column_json(column_create(1, -1212 as int, 2, 12334 as unsigned int, 3, "23.344" as decimal, 4, 1.23444e50 as double, 5, 'gdgd\\dhdjh"dhdhd' as char, 6, "0:45:49.000001" AS time, 7, "2011-04-05 0:45:49.000001" AS datetime, 8, "2011-04-05" AS date)); +select column_json(column_create("int", -1212 as int, "uint", 12334 as unsigned int, "decimal", "23.344" as decimal, "double", 1.23444e50 as double, "string", 'gdgd\\dhdjh"dhdhd' as char, "time", "0:45:49.000001" AS time, "datetime", "2011-04-05 0:45:49.000001" AS datetime, "date", "2011-04-05" AS date)) as ex; +select column_json(column_create(1, -1212 as int, 2, 12334 as unsigned int, 3, "23.344" as decimal, 4, 1.23444e50 as double, 5, 'gdgd\\dhdjh"dhdhd' as char, 6, "0:45:49.000001" AS time, 7, "2011-04-05 0:45:49.000001" AS datetime, 8, "2011-04-05" AS date)) as ex; --echo # --echo # CHECK test @@ -802,8 +809,8 @@ select column_json(column_create("string", "'\"/\\`.,whatever")),hex(column_crea --echo # --echo # embedding test --echo # -select column_json(column_create("val", "val", "emb", column_create("val2", "val2"))); -select column_json(column_create(1, "val", 2, column_create(3, "val2"))); +select column_json(column_create("val", "val", "emb", column_create("val2", "val2"))) as ex; +select column_json(column_create(1, "val", 2, column_create(3, "val2"))) as ex; --echo # --echo # Time encoding @@ -845,7 +852,7 @@ DROP TABLE t1; --echo # create table t1 (dyn blob); insert into t1 values (column_create('name1','value1','name2','value2')); -select group_concat(cast(column_json(dyn) as char)) from t1; +select group_concat(cast(column_json(dyn) as char)) as ex from t1; drop table t1; @@ -895,15 +902,15 @@ SELECT COLUMN_JSON( 'one', 123.456, 'two', 123.456 as DOUBLE ) -); +) as ex; --echo # --echo # MDEV-8521: Drastic loss of precision in COLUMN_JSON() on DOUBLEs --echo # -select column_get(column_create('float', 1.23456789012345E+100 as double), 'float' as double); -select column_json(column_create('float', 1.23456789012345E+100 as double)); -select column_json(column_create('float', 1.23456789012345E+10 as double)); +select column_get(column_create('float', 1.23456789012345E+100 as double), 'float' as double) as ex; +select column_json(column_create('float', 1.23456789012345E+100 as double)) as ex; +select column_json(column_create('float', 1.23456789012345E+10 as double)) as ex; --echo # --echo # MDEV-9147: Character set is ignored in Dynamic Column for saved string @@ -916,13 +923,13 @@ SELECT COLUMN_GET(COLUMN_CREATE(1, 0xC2A2 AS CHAR CHARACTER SET utf8), 1 AS CHAR --echo # MDEV-9167: COLUMN_CHECK fails on valid decimal data --echo # -SELECT COLUMN_CHECK(COLUMN_CREATE('a',0 AS DECIMAL,'b',1 AS DECIMAL)); +SELECT COLUMN_CHECK(COLUMN_CREATE('a',0 AS DECIMAL,'b',1 AS DECIMAL)) as ex; -SELECT COLUMN_CHECK(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)); +SELECT COLUMN_CHECK(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)) as ex; -SELECT COLUMN_JSON(COLUMN_CREATE('a',0 AS DECIMAL,'b',1 AS DECIMAL)); +SELECT COLUMN_JSON(COLUMN_CREATE('a',0 AS DECIMAL,'b',1 AS DECIMAL)) as ex; -SELECT COLUMN_JSON(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)); +SELECT COLUMN_JSON(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)) as ex; --echo # @@ -990,8 +997,8 @@ DROP TABLE t1; --echo # --echo # MDEV-32140: Valgrind/MSAN warnings in dynamic_column_update_move_left --echo # -SELECT COLUMN_GET(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL),3 AS INTEGER); -SELECT HEX(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL)); +SELECT COLUMN_GET(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL),3 AS INTEGER) as ex; +SELECT HEX(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL)) as ex; --echo # --echo # End of 10.4 tests diff --git a/mysql-test/main/fulltext.result b/mysql-test/main/fulltext.result index dba1789dd4d..fcf7efbd157 100644 --- a/mysql-test/main/fulltext.result +++ b/mysql-test/main/fulltext.result @@ -747,8 +747,9 @@ DROP TABLE t1; # CREATE TABLE t1 (f VARCHAR(8)); INSERT INTO t1 VALUES ('foo'),('bar'); -SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) ); -'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) ) +SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN +BOOLEAN MODE ) ) as exp; +exp 1 SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE )) as f1, MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) as f2 from t1 ; f1 f2 diff --git a/mysql-test/main/fulltext.test b/mysql-test/main/fulltext.test index 7f27a883004..a9db469a114 100644 --- a/mysql-test/main/fulltext.test +++ b/mysql-test/main/fulltext.test @@ -693,11 +693,10 @@ DROP TABLE t1; CREATE TABLE t1 (f VARCHAR(8)); INSERT INTO t1 VALUES ('foo'),('bar'); -#enable after fix MDEV-27871 ---disable_view_protocol -SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) ); ---enable_view_protocol +SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN +BOOLEAN MODE ) ) as exp; SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE )) as f1, MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) as f2 from t1 ; + explain extended SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE )) as f1, MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) as f2 from t1 ; diff --git a/mysql-test/main/func_concat.result b/mysql-test/main/func_concat.result index acde1be051b..4303c97d35c 100644 --- a/mysql-test/main/func_concat.result +++ b/mysql-test/main/func_concat.result @@ -70,10 +70,9 @@ a a a0.0000 select concat((select x from (select 'a' as x) as t1 ), -(select y from (select 'b' as y) as t2 )) from (select 1 union select 2 ) +(select y from (select 'b' as y) as t2 )) as exp from (select 1 union select 2 ) as t3; -concat((select x from (select 'a' as x) as t1 ), -(select y from (select 'b' as y) as t2 )) +exp ab ab create table t1(f1 varchar(6)) charset=utf8; diff --git a/mysql-test/main/func_concat.test b/mysql-test/main/func_concat.test index 070d341cb2d..44dea7e35b1 100644 --- a/mysql-test/main/func_concat.test +++ b/mysql-test/main/func_concat.test @@ -57,15 +57,10 @@ select 'a' union select concat('a', -0.0000); # Bug#16716: subselect in concat() may lead to a wrong result # -#enable after fix MDEV-27871 ---disable_view_protocol - select concat((select x from (select 'a' as x) as t1 ), - (select y from (select 'b' as y) as t2 )) from (select 1 union select 2 ) + (select y from (select 'b' as y) as t2 )) as exp from (select 1 union select 2 ) as t3; ---enable_view_protocol - # End of 4.1 tests # diff --git a/mysql-test/main/func_debug.result b/mysql-test/main/func_debug.result index a120411d4b5..a5bda1c2b86 100644 --- a/mysql-test/main/func_debug.result +++ b/mysql-test/main/func_debug.result @@ -113,29 +113,29 @@ Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (longblob) Note 1105 DBUG: [1] arg=2 handler=0 (longblob) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30'); -TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30') +SELECT TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30') as exp; +exp 1 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (datetime) Note 1105 DBUG: [1] arg=2 handler=0 (datetime) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL); -TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL) +SELECT TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL) as exp; +exp 1 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (datetime) Note 1105 DBUG: [1] arg=2 handler=0 (datetime) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30'); -TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30') +SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30') as exp; +exp 0 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (datetime) Note 1105 DBUG: [1] arg=2 handler=0 (datetime) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL); -TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL) +SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL) as exp; +exp 0 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (datetime) @@ -351,8 +351,8 @@ Note 1105 DBUG: [2] arg=3 handler=0 (longblob) Note 1105 DBUG: types_compatible=yes bisect=yes DROP TABLE t1; CREATE TABLE t1 (a DATE); -SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) FROM t1; -a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) +SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (date) Note 1105 DBUG: [1] arg=2 handler=0 (date) @@ -360,8 +360,8 @@ Note 1105 DBUG: [2] arg=3 handler=0 (date) Note 1105 DBUG: [3] arg=4 handler=0 (date) Note 1105 DBUG: [4] arg=5 handler=0 (date) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) FROM t1; -a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) +SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (date) Note 1105 DBUG: [1] arg=2 handler=0 (date) @@ -369,8 +369,8 @@ Note 1105 DBUG: [2] arg=3 handler=0 (date) Note 1105 DBUG: [3] arg=4 handler=0 (date) Note 1105 DBUG: [4] arg=5 handler=0 (date) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) FROM t1; -a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) +SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (date) Note 1105 DBUG: [1] arg=2 handler=0 (date) @@ -378,8 +378,8 @@ Note 1105 DBUG: [2] arg=3 handler=0 (date) Note 1105 DBUG: [3] arg=4 handler=0 (date) Note 1105 DBUG: [4] arg=5 handler=0 (date) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) FROM t1; -a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) +SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (date) Note 1105 DBUG: [1] arg=2 handler=0 (date) @@ -389,8 +389,8 @@ Note 1105 DBUG: [4] arg=5 handler=0 (date) Note 1105 DBUG: types_compatible=yes bisect=yes DROP TABLE t1; CREATE TABLE t1 (a TIME); -SELECT a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) FROM t1; -a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) +SELECT a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) @@ -398,8 +398,8 @@ Note 1105 DBUG: [2] arg=3 handler=0 (time) Note 1105 DBUG: [3] arg=4 handler=0 (time) Note 1105 DBUG: [4] arg=5 handler=0 (time) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) FROM t1; -a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) +SELECT a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) @@ -407,8 +407,8 @@ Note 1105 DBUG: [2] arg=3 handler=0 (time) Note 1105 DBUG: [3] arg=4 handler=0 (time) Note 1105 DBUG: [4] arg=5 handler=0 (time) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) FROM t1; -a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) +SELECT a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) @@ -416,8 +416,8 @@ Note 1105 DBUG: [2] arg=3 handler=0 (time) Note 1105 DBUG: [3] arg=4 handler=0 (time) Note 1105 DBUG: [4] arg=5 handler=0 (time) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) FROM t1; -a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) +SELECT a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) @@ -427,8 +427,8 @@ Note 1105 DBUG: [4] arg=5 handler=0 (time) Note 1105 DBUG: types_compatible=yes bisect=yes DROP TABLE t1; CREATE TABLE t1 (a DATETIME); -SELECT a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) FROM t1; -a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) +SELECT a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (datetime) Note 1105 DBUG: [1] arg=2 handler=0 (datetime) @@ -438,8 +438,8 @@ Note 1105 DBUG: [4] arg=5 handler=0 (datetime) Note 1105 DBUG: [5] arg=6 handler=0 (datetime) Note 1105 DBUG: [6] arg=7 handler=0 (datetime) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) FROM t1; -a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) +SELECT a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (datetime) Note 1105 DBUG: [1] arg=2 handler=0 (datetime) @@ -449,8 +449,8 @@ Note 1105 DBUG: [4] arg=5 handler=0 (datetime) Note 1105 DBUG: [5] arg=6 handler=0 (datetime) Note 1105 DBUG: [6] arg=7 handler=0 (datetime) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) FROM t1; -a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) +SELECT a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (datetime) Note 1105 DBUG: [1] arg=2 handler=0 (datetime) @@ -460,8 +460,8 @@ Note 1105 DBUG: [4] arg=5 handler=0 (datetime) Note 1105 DBUG: [5] arg=6 handler=0 (datetime) Note 1105 DBUG: [6] arg=7 handler=0 (datetime) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) FROM t1; -a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) +SELECT a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (datetime) Note 1105 DBUG: [1] arg=2 handler=0 (datetime) @@ -659,26 +659,26 @@ Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: types_compatible=yes bisect=no DROP TABLE t1; CREATE TABLE t1 (a DATETIME); -SELECT TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30') FROM t1; -TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30') +SELECT TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30') as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (datetime) Note 1105 DBUG: [1] arg=2 handler=0 (datetime) Note 1105 DBUG: types_compatible=yes bisect=no -SELECT TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) FROM t1; -TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) +SELECT TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (datetime) Note 1105 DBUG: [1] arg=2 handler=0 (datetime) Note 1105 DBUG: types_compatible=yes bisect=no -SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30') FROM t1; -TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30') +SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30') as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (datetime) Note 1105 DBUG: [1] arg=2 handler=0 (datetime) Note 1105 DBUG: types_compatible=yes bisect=no -SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) FROM t1; -TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) +SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (datetime) Note 1105 DBUG: [1] arg=2 handler=0 (datetime) @@ -797,38 +797,38 @@ Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (longblob) Note 1105 DBUG: [1] arg=2 handler=1 (decimal) Note 1105 DBUG: types_compatible=no bisect=no -SELECT TIME'10:20:30' IN (1,TIME'10:20:30'); -TIME'10:20:30' IN (1,TIME'10:20:30') +SELECT TIME'10:20:30' IN (1,TIME'10:20:30') as exp; +exp 1 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT TIME'10:20:30' IN (1,TIME'10:20:30',NULL); -TIME'10:20:30' IN (1,TIME'10:20:30',NULL) +SELECT TIME'10:20:30' IN (1,TIME'10:20:30',NULL) as exp; +exp 1 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32'); -TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') +SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp; +exp 1 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=2 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL); -TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) +SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp; +exp 1 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=2 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32'); -TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') +SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp; +exp 1 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) @@ -836,8 +836,8 @@ Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=0 (time) Note 1105 DBUG: [3] arg=4 handler=3 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL); -TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) +SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp; +exp 1 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) @@ -845,38 +845,38 @@ Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=0 (time) Note 1105 DBUG: [3] arg=4 handler=3 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30'); -TIME'10:20:30' NOT IN (1,TIME'10:20:30') +SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30') as exp; +exp 0 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30',NULL); -TIME'10:20:30' NOT IN (1,TIME'10:20:30',NULL) +SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30',NULL) as exp; +exp 0 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: types_compatible=yes bisect=yes -SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32'); -TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') +SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp; +exp 0 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=2 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL); -TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) +SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp; +exp 0 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=2 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32'); -TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') +SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp; +exp 0 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) @@ -884,8 +884,8 @@ Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=0 (time) Note 1105 DBUG: [3] arg=4 handler=3 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL); -TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) +SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp; +exp 0 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) @@ -907,27 +907,27 @@ Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (bigint) Note 1105 DBUG: [1] arg=2 handler=1 (double) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1; -a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) +SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (bigint) Note 1105 DBUG: [1] arg=2 handler=1 (decimal) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1; -a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) +SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (bigint) Note 1105 DBUG: [1] arg=2 handler=1 (decimal) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1; -a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) +SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (decimal) Note 1105 DBUG: [1] arg=2 handler=1 (bigint) Note 1105 DBUG: [2] arg=3 handler=0 (decimal) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1; -a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) +SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (decimal) Note 1105 DBUG: [1] arg=2 handler=1 (bigint) @@ -945,27 +945,27 @@ Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (bigint) Note 1105 DBUG: [1] arg=2 handler=1 (double) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1; -a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) +SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (bigint) Note 1105 DBUG: [1] arg=2 handler=1 (decimal) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1; -a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) +SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (bigint) Note 1105 DBUG: [1] arg=2 handler=1 (decimal) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1; -a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) +SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (decimal) Note 1105 DBUG: [1] arg=2 handler=1 (bigint) Note 1105 DBUG: [2] arg=3 handler=0 (decimal) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1; -a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) +SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (decimal) Note 1105 DBUG: [1] arg=2 handler=1 (bigint) @@ -1219,60 +1219,60 @@ Note 1105 DBUG: [1] arg=2 handler=1 (time) Note 1105 DBUG: types_compatible=no bisect=no DROP TABLE t1; CREATE TABLE t1 (a TIME); -SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1; -a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') +SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=2 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1; -a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) +SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=2 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1; -a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') +SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=0 (time) Note 1105 DBUG: [3] arg=4 handler=3 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1; -a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) +SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=0 (time) Note 1105 DBUG: [3] arg=4 handler=3 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1; -a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') +SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=2 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1; -a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) +SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=2 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1; -a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') +SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=0 (time) Note 1105 DBUG: [3] arg=4 handler=3 (datetime) Note 1105 DBUG: types_compatible=no bisect=no -SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1; -a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) +SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp FROM t1; +exp Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) Note 1105 DBUG: [1] arg=2 handler=0 (time) @@ -1511,8 +1511,8 @@ DROP TABLE t1; # # MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result # -SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32'); -TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32') +SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32') as exp; +exp 1 Warnings: Note 1105 DBUG: [0] arg=1 handler=0 (time) diff --git a/mysql-test/main/func_debug.test b/mysql-test/main/func_debug.test index 1fbc652bb48..b65676dec97 100644 --- a/mysql-test/main/func_debug.test +++ b/mysql-test/main/func_debug.test @@ -24,15 +24,10 @@ SELECT 'a' IN ('a','b',NULL); SELECT 'a' NOT IN ('a','b'); SELECT 'a' NOT IN ('a','b',NULL); -#enable after fix MDEV-27871 ---disable_view_protocol - -SELECT TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30'); -SELECT TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL); -SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30'); -SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL); - ---enable_view_protocol +SELECT TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30') as exp; +SELECT TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL) as exp; +SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30') as exp; +SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL) as exp; SELECT TIME'10:20:30' IN ('10:20:30','10:20:30'); SELECT TIME'10:20:30' IN ('10:20:30','10:20:30',NULL); @@ -86,32 +81,27 @@ SELECT a NOT IN ('a','b','c') FROM t1; SELECT a NOT IN ('a','b','c',NULL) FROM t1; DROP TABLE t1; -#enable after fix MDEV-27871 ---disable_view_protocol - CREATE TABLE t1 (a DATE); -SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) FROM t1; -SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) FROM t1; -SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) FROM t1; -SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) FROM t1; +SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) as exp FROM t1; +SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) as exp FROM t1; +SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) as exp FROM t1; +SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) as exp FROM t1; DROP TABLE t1; CREATE TABLE t1 (a TIME); -SELECT a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) FROM t1; -SELECT a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) FROM t1; -SELECT a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) FROM t1; -SELECT a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) FROM t1; +SELECT a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) as exp FROM t1; +SELECT a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) as exp FROM t1; +SELECT a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) as exp FROM t1; +SELECT a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) as exp FROM t1; DROP TABLE t1; CREATE TABLE t1 (a DATETIME); -SELECT a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) FROM t1; -SELECT a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) FROM t1; -SELECT a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) FROM t1; -SELECT a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) FROM t1; +SELECT a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) as exp FROM t1; +SELECT a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) as exp FROM t1; +SELECT a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) as exp FROM t1; +SELECT a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) as exp FROM t1; DROP TABLE t1; ---enable_view_protocol - --echo # Constant predicant, compatible types, no bisect --echo # Bisect is not used because of non-constant expressions in the list CREATE TABLE t1 (a INT); @@ -156,18 +146,13 @@ SELECT TIME'10:20:30' NOT IN (a,'10:20:30') FROM t1; SELECT TIME'10:20:30' NOT IN (a,'10:20:30',NULL) FROM t1; DROP TABLE t1; -#enable after fix MDEV-27871 ---disable_view_protocol - CREATE TABLE t1 (a DATETIME); -SELECT TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30') FROM t1; -SELECT TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) FROM t1; -SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30') FROM t1; -SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) FROM t1; +SELECT TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30') as exp FROM t1; +SELECT TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) as exp FROM t1; +SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30') as exp FROM t1; +SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) as exp FROM t1; DROP TABLE t1; ---enable_view_protocol - --echo # Constant predicant, incompatible types, no bisect SELECT 1 IN (1,2e0); SELECT 1 IN (1,2e0,NULL); @@ -189,38 +174,33 @@ SELECT 'a' IN ('a',2,NULL); SELECT 'a' NOT IN ('a',2); SELECT 'a' NOT IN ('a',2,NULL); -#enable after fix MDEV-27871 ---disable_view_protocol - -SELECT TIME'10:20:30' IN (1,TIME'10:20:30'); -SELECT TIME'10:20:30' IN (1,TIME'10:20:30',NULL); -SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32'); -SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL); -SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32'); -SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL); -SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30'); -SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30',NULL); -SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32'); -SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL); -SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32'); -SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL); +SELECT TIME'10:20:30' IN (1,TIME'10:20:30') as exp; +SELECT TIME'10:20:30' IN (1,TIME'10:20:30',NULL) as exp; +SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp; +SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp; +SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp; +SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp; +SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30') as exp; +SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30',NULL) as exp; +SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp; +SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp; +SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp; +SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp; --echo # Column predicant, incompatible types, no bisect CREATE TABLE t1 (a INT); SELECT a IN (1,1e0) FROM t1; SELECT a IN (1,1e0,NULL) FROM t1; -SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1; -SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1; -SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1; -SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1; +SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) as exp FROM t1; +SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) as exp FROM t1; +SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) as exp FROM t1; +SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) as exp FROM t1; SELECT a NOT IN (1,1e0) FROM t1; SELECT a NOT IN (1,1e0,NULL) FROM t1; -SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1; -SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1; -SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1; -SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1; - ---enable_view_protocol +SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) as exp FROM t1; +SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) as exp FROM t1; +SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) as exp FROM t1; +SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) as exp FROM t1; SELECT a IN (1,1.0) FROM t1; SELECT a IN (1,1.0,NULL) FROM t1; @@ -279,22 +259,17 @@ SELECT a NOT IN ('a',1) FROM t1; SELECT a NOT IN ('a',TIME'10:20:30') FROM t1; DROP TABLE t1; -#enable after fix MDEV-27871 ---disable_view_protocol - CREATE TABLE t1 (a TIME); -SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1; -SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1; -SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1; -SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1; -SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1; -SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1; -SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1; -SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1; +SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp FROM t1; +SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp FROM t1; +SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp FROM t1; +SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp FROM t1; +SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp FROM t1; +SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp FROM t1; +SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') as exp FROM t1; +SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) as exp FROM t1; DROP TABLE t1; ---enable_view_protocol - # # ROW tests # @@ -437,12 +412,8 @@ DROP TABLE t1; --echo # --echo # MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result --echo # -#enable after fix MDEV-27871 ---disable_view_protocol -SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32'); - ---enable_view_protocol +SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32') as exp; PREPARE stmt FROM "SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')"; diff --git a/mysql-test/main/func_hybrid_type.result b/mysql-test/main/func_hybrid_type.result index 8416532211d..70d08a5fcc2 100644 --- a/mysql-test/main/func_hybrid_type.result +++ b/mysql-test/main/func_hybrid_type.result @@ -3419,8 +3419,8 @@ DROP TABLE t1; # # MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool) # -SELECT CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END; -CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END +SELECT CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END as exp; +exp NULL SELECT CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END; CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END diff --git a/mysql-test/main/func_hybrid_type.test b/mysql-test/main/func_hybrid_type.test index 2cb53c0cd53..89c6568b9f1 100644 --- a/mysql-test/main/func_hybrid_type.test +++ b/mysql-test/main/func_hybrid_type.test @@ -470,10 +470,7 @@ DROP TABLE t1; --echo # --echo # MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool) --echo # -#enable after fix MDEV-27871 ---disable_view_protocol -SELECT CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END; ---enable_view_protocol +SELECT CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END as exp; SELECT CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END; SELECT CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END; diff --git a/mysql-test/main/func_if.result b/mysql-test/main/func_if.result index 6a8e578767e..069d9bf2e3c 100644 --- a/mysql-test/main/func_if.result +++ b/mysql-test/main/func_if.result @@ -162,19 +162,9 @@ IF((ROUND(t1.a,2)=1), 2, IF((ROUND(t1.a,2)=1), 2, IF((ROUND(t1.a,2)=1), 2, IF((ROUND(t1.a,2)=1), 2, -IF((ROUND(t1.a,2)=1), 2,0)))))))))))))))))))))))))))))) + 1 +IF((ROUND(t1.a,2)=1), 2,0)))))))))))))))))))))))))))))) + 1 as exp FROM t1; -a IF((ROUND(t1.a,2)=1), 2, -IF((ROUND(t1.a,2)=1), 2, -IF((ROUND(t1.a,2)=1), 2, -IF((ROUND(t1.a,2)=1), 2, -IF((ROUND(t1.a,2)=1), 2, -IF((ROUND(t1.a,2)=1), 2, -IF((ROUND(t1.a,2)=1), 2, -IF((ROUND(t1.a,2)=1), 2, -IF((ROUND(t1.a,2)=1), 2, -IF((ROUND(t1.a,2)=1), 2, -IF((R +a exp DROP TABLE t1; CREATE TABLE t1 (c LONGTEXT); INSERT INTO t1 VALUES(1), (2), (3), (4), ('1234567890123456789'); diff --git a/mysql-test/main/func_if.test b/mysql-test/main/func_if.test index d18bdc3070e..35bf5bde529 100644 --- a/mysql-test/main/func_if.test +++ b/mysql-test/main/func_if.test @@ -119,8 +119,6 @@ select if(0, 18446744073709551610, 18446744073709551610); CREATE TABLE t1(a DECIMAL(10,3)); -#enable after fix MDEV-27871 ---disable_view_protocol # check : should be fast. more than few secs means failure. SELECT t1.a, IF((ROUND(t1.a,2)=1), 2, @@ -152,9 +150,8 @@ SELECT t1.a, IF((ROUND(t1.a,2)=1), 2, IF((ROUND(t1.a,2)=1), 2, IF((ROUND(t1.a,2)=1), 2, - IF((ROUND(t1.a,2)=1), 2,0)))))))))))))))))))))))))))))) + 1 + IF((ROUND(t1.a,2)=1), 2,0)))))))))))))))))))))))))))))) + 1 as exp FROM t1; ---enable_view_protocol DROP TABLE t1; # diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index a6a8f39bd2d..4b42c1def16 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -28,8 +28,8 @@ NULL select json_value('{"key1": [1,2,3], "key1":123}', '$.key1'); json_value('{"key1": [1,2,3], "key1":123}', '$.key1') 123 -select JSON_VALUE('{ "x": [0,1], "y": "[0,1]", "z": "Mon\\\"t\\\"y" }','$.z'); -JSON_VALUE('{ "x": [0,1], "y": "[0,1]", "z": "Mon\\\"t\\\"y" }','$.z') +select JSON_VALUE('{ "x": [0,1], "y": "[0,1]", "z": "Mon\\\"t\\\"y" }','$.z') as exp; +exp Mon"t"y select json_query('{"key1":{"a":1, "b":[1,2]}}', '$.key2'); json_query('{"key1":{"a":1, "b":[1,2]}}', '$.key2') @@ -43,8 +43,8 @@ NULL select json_query('{"key1":123, "key1": [1,2,3]}', '$.key1'); json_query('{"key1":123, "key1": [1,2,3]}', '$.key1') [1,2,3] -select json_query('{"key1":123, "key1": [1,2,3]}', concat('$', repeat('.k', 1000))); -json_query('{"key1":123, "key1": [1,2,3]}', concat('$', repeat('.k', 1000))) +select json_query('{"key1":123, "key1": [1,2,3]}', concat('$', repeat('.k', 1000))) as exp; +exp NULL select json_array(); json_array() @@ -76,14 +76,14 @@ json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[3]', 'x') select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[4]', 'x'); json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[4]', 'x') ["a", {"b": [1, 2]}, [3, 4], "x"] -select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[1].b[0]', 'x'); -json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[1].b[0]', 'x') +select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[1].b[0]', 'x') as exp; +exp ["a", {"b": ["x", 1, 2]}, [3, 4]] select json_array_insert('true', '$', 1); json_array_insert('true', '$', 1) NULL -select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[2][1]', 'y'); -json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[2][1]', 'y') +select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[2][1]', 'y') as exp; +exp ["a", {"b": [1, 2]}, [3, "y", 4]] select json_contains('{"k1":123, "k2":345}', '123', '$.k1'); json_contains('{"k1":123, "k2":345}', '123', '$.k1') @@ -152,98 +152,98 @@ json_contains('[1, {"a":1}]', '{"a":1}') select json_contains('[{"abc":"def", "def":"abc"}]', '["foo","bar"]'); json_contains('[{"abc":"def", "def":"abc"}]', '["foo","bar"]') 0 -select json_contains('[{"abc":"def", "def":"abc"}, "bar"]', '["bar", {}]'); -json_contains('[{"abc":"def", "def":"abc"}, "bar"]', '["bar", {}]') +select json_contains('[{"abc":"def", "def":"abc"}, "bar"]', '["bar", {}]') as exp; +exp 1 select json_contains('[{"a":"b"},{"c":"d"}]','{"c":"d"}'); json_contains('[{"a":"b"},{"c":"d"}]','{"c":"d"}') 1 -select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]"); -json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]") +select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]") as exp; +exp 1 -select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[10]"); -json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[10]") +select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[10]") as exp; +exp 0 -select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.ma"); -json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.ma") +select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.ma") as exp; +exp 0 -select json_contains_path('{"key1":1, "key2":[2,3]}', "one", "$.key1"); -json_contains_path('{"key1":1, "key2":[2,3]}', "one", "$.key1") +select json_contains_path('{"key1":1, "key2":[2,3]}', "one", "$.key1") as exp; +exp 1 -select json_contains_path('{"key1":1, "key2":[2,3]}', "one", "$.key1", "$.ma"); -json_contains_path('{"key1":1, "key2":[2,3]}', "one", "$.key1", "$.ma") +select json_contains_path('{"key1":1, "key2":[2,3]}', "one", "$.key1", "$.ma") as exp; +exp 1 -select json_contains_path('{"key1":1, "key2":[2,3]}', "aLl", "$.key1", "$.ma"); -json_contains_path('{"key1":1, "key2":[2,3]}', "aLl", "$.key1", "$.ma") +select json_contains_path('{"key1":1, "key2":[2,3]}', "aLl", "$.key1", "$.ma") as exp; +exp 0 -select json_contains_path('{"key1":1, "key2":[2,3]}', "aLl", "$.key1", "$.key2"); -json_contains_path('{"key1":1, "key2":[2,3]}', "aLl", "$.key1", "$.key2") +select json_contains_path('{"key1":1, "key2":[2,3]}', "aLl", "$.key1", "$.key2") as exp; +exp 1 -select json_contains_path('{ "a": true }', NULL, '$.a' ); -json_contains_path('{ "a": true }', NULL, '$.a' ) +select json_contains_path('{ "a": true }', NULL, '$.a' ) as exp; +exp NULL -select json_contains_path('{ "a": true }', 'all', NULL ); -json_contains_path('{ "a": true }', 'all', NULL ) +select json_contains_path('{ "a": true }', 'all', NULL ) as exp; +exp NULL -select json_contains_path('{"a":{"b":"c"}}', 'one', '$.a.*'); -json_contains_path('{"a":{"b":"c"}}', 'one', '$.a.*') +select json_contains_path('{"a":{"b":"c"}}', 'one', '$.a.*') as exp; +exp 1 -select json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1"); -json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1") +select json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1") as exp; +exp "asd" -select json_extract('{"key1":"asd", "key2":[2,3]}', "$.keyX", "$.keyY"); -json_extract('{"key1":"asd", "key2":[2,3]}', "$.keyX", "$.keyY") +select json_extract('{"key1":"asd", "key2":[2,3]}', "$.keyX", "$.keyY") as exp; +exp NULL -select json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1", "$.key2"); -json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1", "$.key2") +select json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1", "$.key2") as exp; +exp ["asd", [2, 3]] -select json_extract('{"key1":5, "key2":[2,3]}', "$.key1", "$.key2"); -json_extract('{"key1":5, "key2":[2,3]}', "$.key1", "$.key2") +select json_extract('{"key1":5, "key2":[2,3]}', "$.key1", "$.key2") as exp; +exp [5, [2, 3]] -select json_extract('{"key0":true, "key1":"qwe"}', "$.key1"); -json_extract('{"key0":true, "key1":"qwe"}', "$.key1") +select json_extract('{"key0":true, "key1":"qwe"}', "$.key1") as exp; +exp "qwe" -select json_extract(json_object('foo', 'foobar'),'$'); -json_extract(json_object('foo', 'foobar'),'$') +select json_extract(json_object('foo', 'foobar'),'$') as exp; +exp {"foo": "foobar"} -select json_extract('[10, 20, [30, 40]]', '$[2][*]'); -json_extract('[10, 20, [30, 40]]', '$[2][*]') +select json_extract('[10, 20, [30, 40]]', '$[2][*]') as exp; +exp [30, 40] -select json_extract('[10, 20, [{"a":3}, 30, 40]]', '$[2][*]'); -json_extract('[10, 20, [{"a":3}, 30, 40]]', '$[2][*]') +select json_extract('[10, 20, [{"a":3}, 30, 40]]', '$[2][*]') as exp; +exp [{"a": 3}, 30, 40] -select json_extract('1', '$'); -json_extract('1', '$') +select json_extract('1', '$') as exp; +exp 1 -select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]'); -json_extract('[10, 20, [30, 40], 1, 10]', '$[1]') +select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]') as exp; +exp 20 -select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]', '$[25]'); -json_extract('[10, 20, [30, 40], 1, 10]', '$[1]', '$[25]') +select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]', '$[25]') as exp; +exp [20] -select json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a'); -json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a') +select json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a') as exp; +exp [[3, 4]] -select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word'); -json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word') +select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word') as exp; +exp {"a": 1, "b": {"c": 1, "k1": "word"}, "d": [1, 2]} -select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.d[3]', 3); -json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.d[3]', 3) +select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.d[3]', 3) as exp; +exp {"a": 1, "b": {"c": 1}, "d": [1, 2, 3]} -select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.a[2]', 2); -json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.a[2]', 2) +select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.a[2]', 2) as exp; +exp {"a": [1, 2], "b": {"c": 1}, "d": [1, 2]} -select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.c', 'word'); -json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.c', 'word') +select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.c', 'word') as exp; +exp {"a": 1, "b": {"c": 1}, "d": [1, 2]} -select json_set('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]'); -json_set('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]') +select json_set('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]') as exp; +exp {"a": 10, "b": [2, 3], "c": "[true, false]"} -select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]'); -json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]') +select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]') as exp; +exp {"a": 10, "b": [2, 3]} -select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.b', '[true, false]'); -json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.b', '[true, false]') +select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.b', '[true, false]') as exp; +exp {"a": 10, "b": "[true, false]"} set @j = '["a", ["b", "c"], "d"]'; select json_remove(@j, '$[0]'); @@ -278,14 +278,14 @@ select * from t1; f {"id": 87, "name": "carrot"} drop table t1; -select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2"); -json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2") +select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2") as ex; +ex 1 -select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2[1]"); -json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2[1]") +select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2[1]") as ex; +ex 1 -select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2[10]"); -json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2[10]") +select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2[10]") as ex; +ex 0 select json_quote('"string"'); json_quote('"string"') @@ -362,43 +362,43 @@ json_keys('foo') NULL Warnings: Warning 4038 Syntax error in JSON text in argument 1 to function 'json_keys' at position 1 -select json_keys('{"a":{"c":1, "d":2}, "b":2, "c":1, "a":3, "b":1, "c":2}'); -json_keys('{"a":{"c":1, "d":2}, "b":2, "c":1, "a":3, "b":1, "c":2}') +select json_keys('{"a":{"c":1, "d":2}, "b":2, "c":1, "a":3, "b":1, "c":2}') as ex; +ex ["a", "b", "c"] -select json_keys('{"c1": "value 1", "c1": "value 2"}'); -json_keys('{"c1": "value 1", "c1": "value 2"}') +select json_keys('{"c1": "value 1", "c1": "value 2"}') as ex; +ex ["c1"] SET @j = '["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]'; -select json_search(@j, 'one', 'abc'); -json_search(@j, 'one', 'abc') +select json_search(@j, 'one', 'abc') as ex; +ex "$[0]" -select json_search(@j, 'all', 'abc'); -json_search(@j, 'all', 'abc') +select json_search(@j, 'all', 'abc') as ex; +ex ["$[0]", "$[2].x"] -select json_search(@j, 'all', 'abc', NULL, '$[2]'); -json_search(@j, 'all', 'abc', NULL, '$[2]') +select json_search(@j, 'all', 'abc', NULL, '$[2]') as ex; +ex "$[2].x" -select json_search(@j, 'all', 'abc', NULL, '$'); -json_search(@j, 'all', 'abc', NULL, '$') +select json_search(@j, 'all', 'abc', NULL, '$') as ex; +ex ["$[0]", "$[2].x"] -select json_search(@j, 'all', '10', NULL, '$'); -json_search(@j, 'all', '10', NULL, '$') +select json_search(@j, 'all', '10', NULL, '$') as ex; +ex "$[1][0].k" -select json_search(@j, 'all', '10', NULL, '$[*]'); -json_search(@j, 'all', '10', NULL, '$[*]') +select json_search(@j, 'all', '10', NULL, '$[*]') as ex; +ex "$[1][0].k" -select json_search(@j, 'all', '10', NULL, '$[*][0].k'); -json_search(@j, 'all', '10', NULL, '$[*][0].k') +select json_search(@j, 'all', '10', NULL, '$[*][0].k') as ex; +ex "$[1][0].k" -select json_search(@j, 'all', '10', NULL, '$**.k'); -json_search(@j, 'all', '10', NULL, '$**.k') +select json_search(@j, 'all', '10', NULL, '$**.k') as ex; +ex "$[1][0].k" create table t1( json_col text ); insert into t1 values ('{ "a": "foobar" }'), ('{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }'); -select json_search( json_col, 'all', 'foot' ) from t1; -json_search( json_col, 'all', 'foot' ) +select json_search( json_col, 'all', 'foot' ) as ex from t1; +ex NULL "$.c[1]" drop table t1; @@ -468,32 +468,32 @@ json CREATE TABLE `json` ( `j` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table json; -select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ); -json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ) +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ) as ex; +ex 1 -select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ); -json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ) +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ) as ex; +ex 1 -select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' ); -json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' ) +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' ) as ex; +ex 1 -select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' ); -json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' ) +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' ) as ex; +ex 1 -select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' ); -json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' ) +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' ) as ex; +ex 2 -select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' ); -json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' ) +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' ) as ex; +ex 2 -select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' ); -json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' ) +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' ) as ex; +ex 2 -select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' ); -json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' ) +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' ) as ex; +ex 2 -select json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' ); -json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' ) +select json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' ) as ex; +ex 2 select json_set('1', '$[0]', 100); json_set('1', '$[0]', 100) @@ -516,20 +516,20 @@ json_set('{"a":12}', '$[0][0].a', 100) select json_set('{"a":12}', '$[0][1].a', 100); json_set('{"a":12}', '$[0][1].a', 100) {"a": 12} -select json_value('{"\\"key1":123}', '$."\\"key1"'); -json_value('{"\\"key1":123}', '$."\\"key1"') +select json_value('{"\\"key1":123}', '$."\\"key1"') as ex; +ex 123 -select json_value('{"\\"key1\\"":123}', '$."\\"key1\\""'); -json_value('{"\\"key1\\"":123}', '$."\\"key1\\""') +select json_value('{"\\"key1\\"":123}', '$."\\"key1\\""') as ex; +ex 123 -select json_value('{"key 1":123}', '$."key 1"'); -json_value('{"key 1":123}', '$."key 1"') +select json_value('{"key 1":123}', '$."key 1"') as ex; +ex 123 -select json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[2]"); -json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[2]") +select json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[2]") as ex; +ex 1 -select json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[3]"); -json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[3]") +select json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[3]") as ex; +ex 0 select json_extract( '[1]', '$[0][0]' ); json_extract( '[1]', '$[0][0]' ) @@ -579,26 +579,26 @@ json_set('[]', '$[0][0][0]', 100) SELECT JSON_search( '{"": "a"}', "one", 'a'); JSON_search( '{"": "a"}', "one", 'a') "$." -select json_merge('{"a":"b"}', '{"a":"c"}') ; -json_merge('{"a":"b"}', '{"a":"c"}') +select json_merge('{"a":"b"}', '{"a":"c"}') as ex ; +ex {"a": ["b", "c"]} -select json_merge('{"a":{"x":"b"}}', '{"a":"c"}') ; -json_merge('{"a":{"x":"b"}}', '{"a":"c"}') +select json_merge('{"a":{"x":"b"}}', '{"a":"c"}') as ex ; +ex {"a": [{"x": "b"}, "c"]} -select json_merge('{"a":{"u":12, "x":"b"}}', '{"a":{"x":"c"}}') ; -json_merge('{"a":{"u":12, "x":"b"}}', '{"a":{"x":"c"}}') +select json_merge('{"a":{"u":12, "x":"b"}}', '{"a":{"x":"c"}}') as ex ; +ex {"a": {"u": 12, "x": ["b", "c"]}} -select json_merge('{"a":{"u":12, "x":"b", "r":1}}', '{"a":{"x":"c", "r":2}}') ; -json_merge('{"a":{"u":12, "x":"b", "r":1}}', '{"a":{"x":"c", "r":2}}') +select json_merge('{"a":{"u":12, "x":"b", "r":1}}', '{"a":{"x":"c", "r":2}}') as ex ; +ex {"a": {"u": 12, "x": ["b", "c"], "r": [1, 2]}} -select json_compact('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}'); -json_compact('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') +select json_compact('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') as ex; +ex {"a":1,"b":[1,2,3],"c":{"aa":"v1","bb":"v2"}} -select json_loose('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}'); -json_loose('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') +select json_loose('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') as ex; +ex {"a": 1, "b": [1, 2, 3], "c": {"aa": "v1", "bb": "v2"}} -select json_detailed('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}'); -json_detailed('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') +select json_detailed('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') as ex; +ex { "a": 1, "b": @@ -613,11 +613,11 @@ json_detailed('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') "bb": "v2" } } -SELECT JSON_search( '{"x": "\\""}', "one", '"'); -JSON_search( '{"x": "\\""}', "one", '"') +SELECT JSON_search( '{"x": "\\""}', "one", '"') as ex; +ex "$.x" -SELECT JSON_search( '{"x": "\\""}', "one", '\\"'); -JSON_search( '{"x": "\\""}', "one", '\\"') +SELECT JSON_search( '{"x": "\\""}', "one", '\\"') as ex; +ex "$.x" set @save_max_allowed_packet=@@max_allowed_packet; set @save_net_buffer_length=@@net_buffer_length; @@ -630,13 +630,13 @@ net_buffer_length 1024 show variables like 'max_allowed_packet'; Variable_name Value max_allowed_packet 2048 -select json_array(repeat('a',1024),repeat('a',1024)); -json_array(repeat('a',1024),repeat('a',1024)) +select json_array(repeat('a',1024),repeat('a',1024)) as ex; +ex NULL Warnings: Warning 1301 Result of json_array() was larger than max_allowed_packet (2048) - truncated -select json_object("a", repeat('a',1024),"b", repeat('a',1024)); -json_object("a", repeat('a',1024),"b", repeat('a',1024)) +select json_object("a", repeat('a',1024),"b", repeat('a',1024)) as ex; +ex NULL Warnings: Warning 1301 Result of json_object() was larger than max_allowed_packet (2048) - truncated @@ -674,31 +674,31 @@ NULL SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*]' ); JSON_EXTRACT( '{"foo":"bar"}', '$[*]' ) NULL -select JSON_EXTRACT('{"name":"value"}', '$.name') = 'value'; -JSON_EXTRACT('{"name":"value"}', '$.name') = 'value' +select JSON_EXTRACT('{"name":"value"}', '$.name') = 'value' as ex; +ex 1 -select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = true; -JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = true +select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = true as ex; +ex 1 -select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = false; -JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = false +select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = false as ex; +ex 0 -select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1; -JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1 +select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1 as ex; +ex 1 -select JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"'); -JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"') +select JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"') as ex; +ex "\u00f6" -select JSON_EXTRACT('{"foo": "bar" foobar foo invalid ', '$.foo'); -JSON_EXTRACT('{"foo": "bar" foobar foo invalid ', '$.foo') +select JSON_EXTRACT('{"foo": "bar" foobar foo invalid ', '$.foo') as ex; +ex NULL Warnings: Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 15 -SELECT JSON_OBJECT('foo', '`'); -JSON_OBJECT('foo', '`') +SELECT JSON_OBJECT('foo', '`') as ex; +ex {"foo": "`"} -SELECT JSON_OBJECT("foo", "bar`bar"); -JSON_OBJECT("foo", "bar`bar") +SELECT JSON_OBJECT("foo", "bar`bar") as ex; +ex {"foo": "bar`bar"} SELECT JSON_SET('{}', '$.age', 87); JSON_SET('{}', '$.age', 87) @@ -776,21 +776,21 @@ insert into t1 values (_latin1 X'7B226B657931223A2253EC227D'); select JSON_VALUE(json_col, '$.key1')= _latin1 X'53EC' from t1; JSON_VALUE(json_col, '$.key1')= _latin1 X'53EC' 1 -select REPLACE(JSON_VALUE(json_col, '$.key1'), 'null', '') = _latin1 X'53EC' from t1; -REPLACE(JSON_VALUE(json_col, '$.key1'), 'null', '') = _latin1 X'53EC' +select REPLACE(JSON_VALUE(json_col, '$.key1'), 'null', '') = _latin1 X'53EC' as exp from t1; +exp 1 drop table t1; # # MDEV-16750 JSON_SET mishandles unicode every second pair of arguments. # -SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6); -JSON_SET('{}', '$.a', _utf8 0xC3B6) +SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6) as exp; +exp {"a": "ö"} -SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6, '$.b', _utf8 0xC3B6); -JSON_SET('{}', '$.a', _utf8 0xC3B6, '$.b', _utf8 0xC3B6) +SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6, '$.b', _utf8 0xC3B6) as exp; +exp {"a": "ö", "b": "ö"} -SELECT JSON_SET('{}', '$.a', _utf8 X'C3B6', '$.x', 1, '$.b', _utf8 X'C3B6'); -JSON_SET('{}', '$.a', _utf8 X'C3B6', '$.x', 1, '$.b', _utf8 X'C3B6') +SELECT JSON_SET('{}', '$.a', _utf8 X'C3B6', '$.x', 1, '$.b', _utf8 X'C3B6') as exp; +exp {"a": "ö", "x": 1, "b": "ö"} # # MDEV-17121 JSON_ARRAY_APPEND @@ -835,14 +835,14 @@ JSON_VALID( '{"a":1]' ) # # MDEV-18886 JSON_ARRAY() does not recognise JSON argument. # -SELECT JSON_ARRAY(_UTF8 'str', JSON_OBJECT(_LATIN1 'plugin', _LATIN1'unix_socket')); -JSON_ARRAY(_UTF8 'str', JSON_OBJECT(_LATIN1 'plugin', _LATIN1'unix_socket')) +SELECT JSON_ARRAY(_UTF8 'str', JSON_OBJECT(_LATIN1 'plugin', _LATIN1'unix_socket')) as exp; +exp ["str", {"plugin": "unix_socket"}] -SELECT CHARSET(JSON_ARRAY()); -CHARSET(JSON_ARRAY()) +SELECT CHARSET(JSON_ARRAY()) as exp; +exp latin1 -SELECT CHARSET(JSON_OBJECT()); -CHARSET(JSON_OBJECT()) +SELECT CHARSET(JSON_OBJECT()) as exp; +exp latin1 # # MDEV-13992 Implement JSON_MERGE_PATCH @@ -892,31 +892,31 @@ id target patch merged a 16 NULL {} NULL NULL 17 {} NULL NULL NULL DROP TABLE merge_t; -SELECT JSON_MERGE_PATCH('{"a":"b"}', NULL, '{"c":"d"}'); -JSON_MERGE_PATCH('{"a":"b"}', NULL, '{"c":"d"}') +SELECT JSON_MERGE_PATCH('{"a":"b"}', NULL, '{"c":"d"}') as exp; +exp NULL -SELECT JSON_MERGE_PATCH(NULL, '[1,2,3]'); -JSON_MERGE_PATCH(NULL, '[1,2,3]') +SELECT JSON_MERGE_PATCH(NULL, '[1,2,3]') as exp; +exp [1, 2, 3] -SELECT JSON_MERGE_PATCH(NULL, 'a'); -JSON_MERGE_PATCH(NULL, 'a') +SELECT JSON_MERGE_PATCH(NULL, 'a') as exp; +exp NULL Warnings: Warning 4038 Syntax error in JSON text in argument 2 to function 'json_merge_patch' at position 1 -SELECT JSON_MERGE_PATCH('{"a":"b"}', NULL, '[1,2,3]', '{"c":null,"d":"e"}'); -JSON_MERGE_PATCH('{"a":"b"}', NULL, '[1,2,3]', '{"c":null,"d":"e"}') +SELECT JSON_MERGE_PATCH('{"a":"b"}', NULL, '[1,2,3]', '{"c":null,"d":"e"}') as exp; +exp {"d": "e"} -SELECT JSON_MERGE_PATCH(); +SELECT JSON_MERGE_PATCH() as exp; ERROR 42000: Incorrect parameter count in the call to native function 'JSON_MERGE_PATCH' -SELECT JSON_MERGE_PATCH('{}'); +SELECT JSON_MERGE_PATCH('{}') as exp; ERROR 42000: Incorrect parameter count in the call to native function 'JSON_MERGE_PATCH' -SELECT JSON_MERGE_PATCH('{', '[1,2,3]'); -JSON_MERGE_PATCH('{', '[1,2,3]') +SELECT JSON_MERGE_PATCH('{', '[1,2,3]') as exp; +exp NULL Warnings: Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_merge_patch' -SELECT JSON_MERGE_PATCH('{"a":"b"}', '[1,'); -JSON_MERGE_PATCH('{"a":"b"}', '[1,') +SELECT JSON_MERGE_PATCH('{"a":"b"}', '[1,') as exp; +exp NULL Warnings: Warning 4037 Unexpected end of JSON text in argument 2 to function 'json_merge_patch' @@ -1219,8 +1219,8 @@ insert into t200 values } ] }'); -select JSON_DETAILED(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) from t200; -JSON_DETAILED(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) +select JSON_DETAILED(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) as exp from t200; +exp [ { "range_scan_alternatives": @@ -1250,8 +1250,8 @@ JSON_DETAILED(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) ["123"] } ] -select JSON_PRETTY(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) from t200; -JSON_PRETTY(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) +select JSON_PRETTY(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) as exp from t200; +exp [ { "range_scan_alternatives": @@ -1281,8 +1281,8 @@ JSON_PRETTY(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) ["123"] } ] -select JSON_LOOSE(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) from t200; -JSON_LOOSE(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) +select JSON_LOOSE(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) as exp from t200; +exp [{"range_scan_alternatives": [{"index": "a_b", "ranges": ["2 <= a <= 2 AND 4 <= b <= 4", "123"], "rowid_ordered": true, "using_mrr": false, "index_only": true, "rows": 1, "cost": 1.1752, "chosen": true}], "analyzing_roworder_intersect": {"cause": "too few roworder scans"}, "analyzing_index_merge_union": [], "test_one_line_array": ["123"]}] drop table t200; # diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index ef747efb79d..eed433aa118 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -10,19 +10,13 @@ select json_value('{"key1":123}', '$.key1'); select json_value('{"key1":[1,2,3]}', '$.key1'); select json_value('{"key1": [1,2,3], "key1":123}', '$.key1'); -#enable after fix MDEV-27871 ---disable_view_protocol -select JSON_VALUE('{ "x": [0,1], "y": "[0,1]", "z": "Mon\\\"t\\\"y" }','$.z'); ---enable_view_protocol +select JSON_VALUE('{ "x": [0,1], "y": "[0,1]", "z": "Mon\\\"t\\\"y" }','$.z') as exp; select json_query('{"key1":{"a":1, "b":[1,2]}}', '$.key2'); select json_query('{"key1":{"a":1, "b":[1,2]}}', '$.key1'); select json_query('{"key1": 1}', '$.key1'); select json_query('{"key1":123, "key1": [1,2,3]}', '$.key1'); -#enable after fix MDEV-27871 ---disable_view_protocol -select json_query('{"key1":123, "key1": [1,2,3]}', concat('$', repeat('.k', 1000))); ---enable_view_protocol +select json_query('{"key1":123, "key1": [1,2,3]}', concat('$', repeat('.k', 1000))) as exp; select json_array(); select json_array(1); @@ -39,15 +33,9 @@ select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[1]', 'x'); select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[2]', 'x'); select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[3]', 'x'); select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[4]', 'x'); -#enable after fix MDEV-27871 ---disable_view_protocol -select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[1].b[0]', 'x'); ---enable_view_protocol +select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[1].b[0]', 'x') as exp; select json_array_insert('true', '$', 1); -#enable after fix MDEV-27871 ---disable_view_protocol -select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[2][1]', 'y'); ---enable_view_protocol +select json_array_insert('["a", {"b": [1, 2]}, [3, 4]]', '$[2][1]', 'y') as exp; select json_contains('{"k1":123, "k2":345}', '123', '$.k1'); select json_contains('"you"', '"you"'); @@ -72,45 +60,45 @@ select json_contains('{"a":1}', '{}'); select json_contains('[1, {"a":1}]', '{}'); select json_contains('[1, {"a":1}]', '{"a":1}'); select json_contains('[{"abc":"def", "def":"abc"}]', '["foo","bar"]'); -#enable after fix MDEV-27871 ---disable_view_protocol -select json_contains('[{"abc":"def", "def":"abc"}, "bar"]', '["bar", {}]'); ---disable_view_protocol +select json_contains('[{"abc":"def", "def":"abc"}, "bar"]', '["bar", {}]') as exp; select json_contains('[{"a":"b"},{"c":"d"}]','{"c":"d"}'); -select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]"); -select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[10]"); -select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.ma"); -select json_contains_path('{"key1":1, "key2":[2,3]}', "one", "$.key1"); -select json_contains_path('{"key1":1, "key2":[2,3]}', "one", "$.key1", "$.ma"); -select json_contains_path('{"key1":1, "key2":[2,3]}', "aLl", "$.key1", "$.ma"); -select json_contains_path('{"key1":1, "key2":[2,3]}', "aLl", "$.key1", "$.key2"); -select json_contains_path('{ "a": true }', NULL, '$.a' ); -select json_contains_path('{ "a": true }', 'all', NULL ); -select json_contains_path('{"a":{"b":"c"}}', 'one', '$.a.*'); +select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[1]") as exp; +select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.key2[10]") as exp; +select json_contains_path('{"key1":1, "key2":[2,3]}', "oNE", "$.ma") as exp; +select json_contains_path('{"key1":1, "key2":[2,3]}', "one", "$.key1") as exp; +select json_contains_path('{"key1":1, "key2":[2,3]}', "one", "$.key1", "$.ma") as exp; +select json_contains_path('{"key1":1, "key2":[2,3]}', "aLl", "$.key1", "$.ma") as exp; +select json_contains_path('{"key1":1, "key2":[2,3]}', "aLl", "$.key1", "$.key2") as exp; +select json_contains_path('{ "a": true }', NULL, '$.a' ) as exp; +select json_contains_path('{ "a": true }', 'all', NULL ) as exp; +select json_contains_path('{"a":{"b":"c"}}', 'one', '$.a.*') as exp; -select json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1"); -select json_extract('{"key1":"asd", "key2":[2,3]}', "$.keyX", "$.keyY"); -select json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1", "$.key2"); -select json_extract('{"key1":5, "key2":[2,3]}', "$.key1", "$.key2"); -select json_extract('{"key0":true, "key1":"qwe"}', "$.key1"); -select json_extract(json_object('foo', 'foobar'),'$'); -select json_extract('[10, 20, [30, 40]]', '$[2][*]'); -select json_extract('[10, 20, [{"a":3}, 30, 40]]', '$[2][*]'); -select json_extract('1', '$'); -select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]'); -select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]', '$[25]'); -select json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a'); +select json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1") as exp; +select json_extract('{"key1":"asd", "key2":[2,3]}', "$.keyX", "$.keyY") as exp; +select json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1", "$.key2") as exp; +select json_extract('{"key1":5, "key2":[2,3]}', "$.key1", "$.key2") as exp; +select json_extract('{"key0":true, "key1":"qwe"}', "$.key1") as exp; +select json_extract(json_object('foo', 'foobar'),'$') as exp; +select json_extract('[10, 20, [30, 40]]', '$[2][*]') as exp; +select json_extract('[10, 20, [{"a":3}, 30, 40]]', '$[2][*]') as exp; +select json_extract('1', '$') as exp; +select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]') as exp; +select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]', '$[25]') as exp; +select json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a') as exp; -select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word'); -select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.d[3]', 3); -select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.a[2]', 2); -select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.c', 'word'); +#enable after MDEV-32454 fix +--disable_view_protocol +select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word') as exp; +select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.d[3]', 3) as exp; +select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.a[2]', 2) as exp; +select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.c', 'word') as exp; -select json_set('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]'); +select json_set('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]') as exp; +--enable_view_protocol -select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]'); -select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.b', '[true, false]'); +select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]') as exp; +select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.b', '[true, false]') as exp; set @j = '["a", ["b", "c"], "d"]'; select json_remove(@j, '$[0]'); @@ -127,9 +115,9 @@ show create table t1; select * from t1; drop table t1; -select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2"); -select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2[1]"); -select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2[10]"); +select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2") as ex; +select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2[1]") as ex; +select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2[10]") as ex; select json_quote('"string"'); create table t1 as select json_quote('foo'); @@ -149,11 +137,14 @@ select json_merge('a','b'); select json_merge('{"a":"b"}','{"c":"d"}'); SELECT JSON_MERGE('[1, 2]', '{"id": 47}'); +#enable after MDEV-32454 fix +--disable_view_protocol select json_type('{"k1":123, "k2":345}'); select json_type('[123, "k2", 345]'); select json_type("true"); select json_type('123'); select json_type('123.12'); +--enable_view_protocol select json_keys('{"a":{"c":1, "d":2}, "b":2}'); select json_keys('{"a":{"c":1, "d":2}, "b":2}', "$.a"); @@ -162,28 +153,31 @@ select json_keys('foo'); # # mdev-12789 JSON_KEYS returns duplicate keys twice # -select json_keys('{"a":{"c":1, "d":2}, "b":2, "c":1, "a":3, "b":1, "c":2}'); -select json_keys('{"c1": "value 1", "c1": "value 2"}'); +select json_keys('{"a":{"c":1, "d":2}, "b":2, "c":1, "a":3, "b":1, "c":2}') as ex; +select json_keys('{"c1": "value 1", "c1": "value 2"}') as ex; SET @j = '["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]'; -select json_search(@j, 'one', 'abc'); -select json_search(@j, 'all', 'abc'); -select json_search(@j, 'all', 'abc', NULL, '$[2]'); -select json_search(@j, 'all', 'abc', NULL, '$'); -select json_search(@j, 'all', '10', NULL, '$'); -select json_search(@j, 'all', '10', NULL, '$[*]'); -select json_search(@j, 'all', '10', NULL, '$[*][0].k'); -select json_search(@j, 'all', '10', NULL, '$**.k'); +select json_search(@j, 'one', 'abc') as ex; +select json_search(@j, 'all', 'abc') as ex; +select json_search(@j, 'all', 'abc', NULL, '$[2]') as ex; +select json_search(@j, 'all', 'abc', NULL, '$') as ex; +select json_search(@j, 'all', '10', NULL, '$') as ex; +select json_search(@j, 'all', '10', NULL, '$[*]') as ex; +select json_search(@j, 'all', '10', NULL, '$[*][0].k') as ex; +select json_search(@j, 'all', '10', NULL, '$**.k') as ex; create table t1( json_col text ); insert into t1 values ('{ "a": "foobar" }'), ('{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }'); -select json_search( json_col, 'all', 'foot' ) from t1; +select json_search( json_col, 'all', 'foot' ) as ex from t1; drop table t1; +#enable after MDEV-32454 fix +--disable_view_protocol select json_unquote('"abc"'); select json_unquote('abc'); +--enable_view_protocol # # MDEV-13703 Illegal mix of collations for operation 'json_object' on using JSON_UNQUOTE as an argument. # @@ -193,9 +187,14 @@ insert into t1 values ('abc'),('def'); select json_object('foo', json_unquote(json_object('bar', c)),'qux', c) as fld from t1; drop table t1; + +#enable after MDEV-32454 fix +--disable_view_protocol select json_object("a", json_object("b", "abcd")); select json_object("a", '{"b": "abcd"}'); select json_object("a", json_compact('{"b": "abcd"}')); +--enable_view_protocol + select json_compact(NULL); select json_depth(json_compact(NULL)); @@ -214,15 +213,15 @@ create table json (j INT); show create table json; drop table json; -select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ); -select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ); -select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' ); -select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' ); -select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' ); -select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' ); -select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' ); -select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' ); -select json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' ); +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ) as ex; +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ) as ex; +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' ) as ex; +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' ) as ex; +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' ) as ex; +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' ) as ex; +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' ) as ex; +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' ) as ex; +select json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' ) as ex; select json_set('1', '$[0]', 100); select json_set('1', '$[0][0]', 100); @@ -232,12 +231,12 @@ select json_set('{"a":12}', '$[0].a', 100); select json_set('{"a":12}', '$[0][0].a', 100); select json_set('{"a":12}', '$[0][1].a', 100); -select json_value('{"\\"key1":123}', '$."\\"key1"'); -select json_value('{"\\"key1\\"":123}', '$."\\"key1\\""'); -select json_value('{"key 1":123}', '$."key 1"'); +select json_value('{"\\"key1":123}', '$."\\"key1"') as ex; +select json_value('{"\\"key1\\"":123}', '$."\\"key1\\""') as ex; +select json_value('{"key 1":123}', '$."key 1"') as ex; -select json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[2]"); -select json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[3]"); +select json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[2]") as ex; +select json_contains_path('{"a":[{"c":[1,{"a":[0,1,2]},3]}], "b":[1,2,3]}', 'one', "$**.a[3]") as ex; select json_extract( '[1]', '$[0][0]' ); select json_extract( '[1]', '$[1][0]' ); @@ -265,21 +264,24 @@ SELECT JSON_search( '{"": "a"}', "one", 'a'); # MDEV-11858 json_merge() concatenates instead of merging. # -select json_merge('{"a":"b"}', '{"a":"c"}') ; -select json_merge('{"a":{"x":"b"}}', '{"a":"c"}') ; -select json_merge('{"a":{"u":12, "x":"b"}}', '{"a":{"x":"c"}}') ; -select json_merge('{"a":{"u":12, "x":"b", "r":1}}', '{"a":{"x":"c", "r":2}}') ; +select json_merge('{"a":"b"}', '{"a":"c"}') as ex ; +select json_merge('{"a":{"x":"b"}}', '{"a":"c"}') as ex ; +select json_merge('{"a":{"u":12, "x":"b"}}', '{"a":{"x":"c"}}') as ex ; +select json_merge('{"a":{"u":12, "x":"b", "r":1}}', '{"a":{"x":"c", "r":2}}') as ex ; -select json_compact('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}'); -select json_loose('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}'); -select json_detailed('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}'); +select json_compact('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') as ex; +#enable after MDEV-32454 fix +--disable_view_protocol +select json_loose('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') as ex; +select json_detailed('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') as ex; +--enable_view_protocol # # MDEV-11856 json_search doesn't search for values with double quotes character (") # -SELECT JSON_search( '{"x": "\\""}', "one", '"'); -SELECT JSON_search( '{"x": "\\""}', "one", '\\"'); +SELECT JSON_search( '{"x": "\\""}', "one", '"') as ex; +SELECT JSON_search( '{"x": "\\""}', "one", '\\"') as ex; # # MDEV-11833 JSON functions don't seem to respect max_allowed_packet. @@ -293,8 +295,8 @@ set @@global.max_allowed_packet=2048; show variables like 'net_buffer_length'; show variables like 'max_allowed_packet'; -select json_array(repeat('a',1024),repeat('a',1024)); -select json_object("a", repeat('a',1024),"b", repeat('a',1024)); +select json_array(repeat('a',1024),repeat('a',1024)) as ex; +select json_object("a", repeat('a',1024),"b", repeat('a',1024)) as ex; --connection default set @@global.max_allowed_packet = @save_max_allowed_packet; @@ -344,22 +346,22 @@ SELECT JSON_EXTRACT( '{"foo":"bar"}', '$[*]' ); # MDEV-12604 Comparison of JSON_EXTRACT result differs with Mysql. # -select JSON_EXTRACT('{"name":"value"}', '$.name') = 'value'; -select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = true; -select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = false; -select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1; -select JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"'); +select JSON_EXTRACT('{"name":"value"}', '$.name') = 'value' as ex; +select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = true as ex; +select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = false as ex; +select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1 as ex; +select JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"') as ex; # # MDEV-129892 JSON_EXTRACT returns data for invalid JSON # -select JSON_EXTRACT('{"foo": "bar" foobar foo invalid ', '$.foo'); +select JSON_EXTRACT('{"foo": "bar" foobar foo invalid ', '$.foo') as ex; # # MDEV-13138 JSON_OBJECT returns null with strings containing backticks. # -SELECT JSON_OBJECT('foo', '`'); -SELECT JSON_OBJECT("foo", "bar`bar"); +SELECT JSON_OBJECT('foo', '`') as ex; +SELECT JSON_OBJECT("foo", "bar`bar") as ex; # # MDEV-13324 JSON_SET returns NULL instead of object. @@ -457,16 +459,19 @@ select json_array(1,user(),compress(5.140264e+307)); create table t1(json_col TEXT) DEFAULT CHARSET=latin1; insert into t1 values (_latin1 X'7B226B657931223A2253EC227D'); select JSON_VALUE(json_col, '$.key1')= _latin1 X'53EC' from t1; -select REPLACE(JSON_VALUE(json_col, '$.key1'), 'null', '') = _latin1 X'53EC' from t1; +select REPLACE(JSON_VALUE(json_col, '$.key1'), 'null', '') = _latin1 X'53EC' as exp from t1; drop table t1; --echo # --echo # MDEV-16750 JSON_SET mishandles unicode every second pair of arguments. --echo # -SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6); -SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6, '$.b', _utf8 0xC3B6); -SELECT JSON_SET('{}', '$.a', _utf8 X'C3B6', '$.x', 1, '$.b', _utf8 X'C3B6'); +#enable after MDEV-32454 fix +--disable_view_protocol +SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6) as exp; +SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6, '$.b', _utf8 0xC3B6) as exp; +SELECT JSON_SET('{}', '$.a', _utf8 X'C3B6', '$.x', 1, '$.b', _utf8 X'C3B6') as exp; +--enable_view_protocol --echo # --echo # MDEV-17121 JSON_ARRAY_APPEND @@ -509,9 +514,9 @@ select JSON_VALID( '{"a":1]' ); --echo # --echo # MDEV-18886 JSON_ARRAY() does not recognise JSON argument. --echo # -SELECT JSON_ARRAY(_UTF8 'str', JSON_OBJECT(_LATIN1 'plugin', _LATIN1'unix_socket')); -SELECT CHARSET(JSON_ARRAY()); -SELECT CHARSET(JSON_OBJECT()); +SELECT JSON_ARRAY(_UTF8 'str', JSON_OBJECT(_LATIN1 'plugin', _LATIN1'unix_socket')) as exp; +SELECT CHARSET(JSON_ARRAY()) as exp; +SELECT CHARSET(JSON_OBJECT()) as exp; --echo # --echo # MDEV-13992 Implement JSON_MERGE_PATCH @@ -545,17 +550,17 @@ SELECT id, target, patch, FROM merge_t ORDER BY id; DROP TABLE merge_t; -SELECT JSON_MERGE_PATCH('{"a":"b"}', NULL, '{"c":"d"}'); -SELECT JSON_MERGE_PATCH(NULL, '[1,2,3]'); -SELECT JSON_MERGE_PATCH(NULL, 'a'); -SELECT JSON_MERGE_PATCH('{"a":"b"}', NULL, '[1,2,3]', '{"c":null,"d":"e"}'); +SELECT JSON_MERGE_PATCH('{"a":"b"}', NULL, '{"c":"d"}') as exp; +SELECT JSON_MERGE_PATCH(NULL, '[1,2,3]') as exp; +SELECT JSON_MERGE_PATCH(NULL, 'a') as exp; +SELECT JSON_MERGE_PATCH('{"a":"b"}', NULL, '[1,2,3]', '{"c":null,"d":"e"}') as exp; --error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT -SELECT JSON_MERGE_PATCH(); +SELECT JSON_MERGE_PATCH() as exp; --error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT -SELECT JSON_MERGE_PATCH('{}'); -SELECT JSON_MERGE_PATCH('{', '[1,2,3]'); -SELECT JSON_MERGE_PATCH('{"a":"b"}', '[1,'); +SELECT JSON_MERGE_PATCH('{}') as exp; +SELECT JSON_MERGE_PATCH('{', '[1,2,3]') as exp; +SELECT JSON_MERGE_PATCH('{"a":"b"}', '[1,') as exp; --echo # --echo # MDEV-22976 CAST(JSON_EXTRACT() AS DECIMAL) does not handle boolean values @@ -601,6 +606,7 @@ DROP TABLE json_test; --enable_metadata --disable_ps_protocol +--disable_view_protocol SELECT JSON_VALID('{"id": 1, "name": "Monty"}') AS json_valid, @@ -612,6 +618,7 @@ SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}') AS json_length, JSON_DEPTH('[10, {"a": 20}]') AS json_depnth; +--enable_view_protocol --enable_ps_protocol --disable_metadata @@ -674,10 +681,13 @@ SELECT JSON_EXTRACT('{"a":null, "b":10, "c":"null"}', '$.a'); --echo # --vertical_results +#enable after fix MDEV-28649 +--disable_view_protocol SELECT JSON_OBJECT("cond", true) AS j1, JSON_OBJECT("cond", COALESCE(true, false)) j2, JSON_OBJECT("cond", COALESCE(COALESCE(true, false))) j3; +--enable_view_protocol --horizontal_results CREATE TABLE t1 (a INT); @@ -807,9 +817,9 @@ insert into t200 values }'); -select JSON_DETAILED(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) from t200; -select JSON_PRETTY(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) from t200; -select JSON_LOOSE(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) from t200; +select JSON_DETAILED(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) as exp from t200; +select JSON_PRETTY(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) as exp from t200; +select JSON_LOOSE(JSON_EXTRACT(a, '$**.analyzing_range_alternatives')) as exp from t200; drop table t200; --echo # diff --git a/mysql-test/main/func_math.result b/mysql-test/main/func_math.result index 81d0395fe69..e3191281ea4 100644 --- a/mysql-test/main/func_math.result +++ b/mysql-test/main/func_math.result @@ -931,8 +931,8 @@ STDDEV_POP(ROUND(0,@A:=2009)) # CREATE TABLE t1 ( pk int NOT NULL, i1 int NOT NULL, d1 date NOT NULL, t1 time); INSERT INTO t1 VALUES (7,9,'2007-08-15','03:55:02'),(8,7,'1993-06-05','04:17:51'),(9,7,'2034-07-01','17:31:12'),(10,0,'1998-08-24','08:09:27'); -SELECT DISTINCT STDDEV_SAMP(EXPORT_SET(t1, -1379790335835635712, (i1 + 'o'), (MD5(d1)))) FROM t1; -STDDEV_SAMP(EXPORT_SET(t1, -1379790335835635712, (i1 + 'o'), (MD5(d1)))) +SELECT DISTINCT STDDEV_SAMP(EXPORT_SET(t1, -1379790335835635712, (i1 + 'o'), (MD5(d1)))) as exp FROM t1; +exp NULL Warnings: Warning 1292 Truncated incorrect DOUBLE value: 'o' diff --git a/mysql-test/main/func_math.test b/mysql-test/main/func_math.test index 96867b530d0..19d2e72ca55 100644 --- a/mysql-test/main/func_math.test +++ b/mysql-test/main/func_math.test @@ -685,10 +685,7 @@ SELECT STDDEV_POP(ROUND(0,@A:=2009)) FROM (SELECT 1 UNION SELECT 2) fake_table; CREATE TABLE t1 ( pk int NOT NULL, i1 int NOT NULL, d1 date NOT NULL, t1 time); INSERT INTO t1 VALUES (7,9,'2007-08-15','03:55:02'),(8,7,'1993-06-05','04:17:51'),(9,7,'2034-07-01','17:31:12'),(10,0,'1998-08-24','08:09:27'); -#enable after fix MDEV-27871 ---disable_view_protocol -SELECT DISTINCT STDDEV_SAMP(EXPORT_SET(t1, -1379790335835635712, (i1 + 'o'), (MD5(d1)))) FROM t1; ---enable_view_protocol +SELECT DISTINCT STDDEV_SAMP(EXPORT_SET(t1, -1379790335835635712, (i1 + 'o'), (MD5(d1)))) as exp FROM t1; DROP TABLE t1; CREATE TABLE t1 (a VARCHAR(128)); diff --git a/mysql-test/main/func_misc.result b/mysql-test/main/func_misc.result index ed3e8eef91e..adbb9f33caf 100644 --- a/mysql-test/main/func_misc.result +++ b/mysql-test/main/func_misc.result @@ -149,8 +149,8 @@ select @invoked; @invoked 10 set @invoked := 0; -select benchmark(100, (select avg(func_26093_b(a, rand())) from table_26093)); -benchmark(100, (select avg(func_26093_b(a, rand())) from table_26093)) +select benchmark(100, (select avg(func_26093_b(a, rand())) from table_26093)) as exp; +exp 0 select @invoked; @invoked @@ -1170,11 +1170,11 @@ INET6_NTOA(INET6_ATON('1:2:3:4:5:6:7::')) SELECT INET6_NTOA(INET6_ATON('0000:0000::0000:0001')); INET6_NTOA(INET6_ATON('0000:0000::0000:0001')) ::1 -SELECT INET6_NTOA(INET6_ATON('1234:5678:9abc:def0:4321:8765:cba9:0fed')); -INET6_NTOA(INET6_ATON('1234:5678:9abc:def0:4321:8765:cba9:0fed')) +SELECT INET6_NTOA(INET6_ATON('1234:5678:9abc:def0:4321:8765:cba9:0fed')) as exp; +exp 1234:5678:9abc:def0:4321:8765:cba9:fed -SELECT INET6_NTOA(INET6_ATON('0000:0000:0000:0000:0000:0000:0000:0001')); -INET6_NTOA(INET6_ATON('0000:0000:0000:0000:0000:0000:0000:0001')) +SELECT INET6_NTOA(INET6_ATON('0000:0000:0000:0000:0000:0000:0000:0001')) as exp; +exp ::1 SELECT INET6_NTOA(INET6_ATON('::C0A8:0102')); INET6_NTOA(INET6_ATON('::C0A8:0102')) diff --git a/mysql-test/main/func_misc.test b/mysql-test/main/func_misc.test index 935f33350d9..58bcd2f498a 100644 --- a/mysql-test/main/func_misc.test +++ b/mysql-test/main/func_misc.test @@ -158,10 +158,7 @@ select @invoked; set @invoked := 0; --disable_ps2_protocol -#enable after fix MDEV-27871 ---disable_view_protocol -select benchmark(100, (select avg(func_26093_b(a, rand())) from table_26093)); ---enable_view_protocol +select benchmark(100, (select avg(func_26093_b(a, rand())) from table_26093)) as exp; --enable_ps2_protocol # Returns 1000, due to rand() preventing caching. select @invoked; @@ -952,11 +949,8 @@ SELECT INET6_NTOA(INET6_ATON('1:2:3:4:5::7:8')); SELECT INET6_NTOA(INET6_ATON('1:2:3:4:5:6::8')); SELECT INET6_NTOA(INET6_ATON('1:2:3:4:5:6:7::')); SELECT INET6_NTOA(INET6_ATON('0000:0000::0000:0001')); -#enable after fix MDEV-27871 ---disable_view_protocol -SELECT INET6_NTOA(INET6_ATON('1234:5678:9abc:def0:4321:8765:cba9:0fed')); -SELECT INET6_NTOA(INET6_ATON('0000:0000:0000:0000:0000:0000:0000:0001')); ---enable_view_protocol +SELECT INET6_NTOA(INET6_ATON('1234:5678:9abc:def0:4321:8765:cba9:0fed')) as exp; +SELECT INET6_NTOA(INET6_ATON('0000:0000:0000:0000:0000:0000:0000:0001')) as exp; SELECT INET6_NTOA(INET6_ATON('::C0A8:0102')); SELECT INET6_NTOA(INET6_ATON('::c0a8:0102')); SELECT INET6_NTOA(INET6_ATON('::192.168.1.2')); diff --git a/mysql-test/main/func_sapdb.result b/mysql-test/main/func_sapdb.result index 27f1d74bc41..5098752a433 100644 --- a/mysql-test/main/func_sapdb.result +++ b/mysql-test/main/func_sapdb.result @@ -17,35 +17,35 @@ extract(MICROSECOND FROM "1999-01-02 10:11:12.000123") select date_format("1997-12-31 23:59:59.000002", "%f"); date_format("1997-12-31 23:59:59.000002", "%f") 000002 -select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000 99:99:99.999999" DAY_MICROSECOND); -date_add("1997-12-31 23:59:59.000002",INTERVAL "10000 99:99:99.999999" DAY_MICROSECOND) +select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000 99:99:99.999999" DAY_MICROSECOND) as exp; +exp 2025-05-23 04:40:39.000001 -select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99:99.999999" HOUR_MICROSECOND); -date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99:99.999999" HOUR_MICROSECOND) +select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99:99.999999" HOUR_MICROSECOND) as exp; +exp 1999-02-21 17:40:39.000001 -select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99.999999" MINUTE_MICROSECOND); -date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99.999999" MINUTE_MICROSECOND) +select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000:99.999999" MINUTE_MICROSECOND) as exp; +exp 1998-01-07 22:41:39.000001 -select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000.999999" SECOND_MICROSECOND); -date_add("1997-12-31 23:59:59.000002",INTERVAL "10000.999999" SECOND_MICROSECOND) +select date_add("1997-12-31 23:59:59.000002",INTERVAL "10000.999999" SECOND_MICROSECOND) as exp; +exp 1998-01-01 02:46:40.000001 -select date_add("1997-12-31 23:59:59.000002",INTERVAL "999999" MICROSECOND); -date_add("1997-12-31 23:59:59.000002",INTERVAL "999999" MICROSECOND) +select date_add("1997-12-31 23:59:59.000002",INTERVAL "999999" MICROSECOND) as exp; +exp 1998-01-01 00:00:00.000001 -select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1 1:1:1.000002" DAY_MICROSECOND); -date_sub("1998-01-01 00:00:00.000001",INTERVAL "1 1:1:1.000002" DAY_MICROSECOND) +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1 1:1:1.000002" DAY_MICROSECOND) as exp; +exp 1997-12-30 22:58:58.999999 -select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1:1.000002" HOUR_MICROSECOND); -date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1:1.000002" HOUR_MICROSECOND) +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1:1.000002" HOUR_MICROSECOND) as exp; +exp 1997-12-31 22:58:58.999999 -select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1.000002" MINUTE_MICROSECOND); -date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1.000002" MINUTE_MICROSECOND) +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1:1.000002" MINUTE_MICROSECOND) as exp; +exp 1997-12-31 23:58:58.999999 -select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1.000002" SECOND_MICROSECOND); -date_sub("1998-01-01 00:00:00.000001",INTERVAL "1.000002" SECOND_MICROSECOND) +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "1.000002" SECOND_MICROSECOND) as exp; +exp 1997-12-31 23:59:58.999999 -select date_sub("1998-01-01 00:00:00.000001",INTERVAL "000002" MICROSECOND); -date_sub("1998-01-01 00:00:00.000001",INTERVAL "000002" MICROSECOND) +select date_sub("1998-01-01 00:00:00.000001",INTERVAL "000002" MICROSECOND) as exp; +exp 1997-12-31 23:59:59.999999 select adddate("1997-12-31 23:59:59.000001", 10); adddate("1997-12-31 23:59:59.000001", 10) @@ -98,47 +98,47 @@ NULL select makedate(100,1); makedate(100,1) 0100-01-01 -select addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002"); -addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002") +select addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002") as exp; +exp 1998-01-02 01:01:01.000001 -select subtime("1997-12-31 23:59:59.000001", "1 1:1:1.000002"); -subtime("1997-12-31 23:59:59.000001", "1 1:1:1.000002") +select subtime("1997-12-31 23:59:59.000001", "1 1:1:1.000002") as exp; +exp 1997-12-30 22:58:57.999999 -select addtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999"); -addtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999") +select addtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999") as exp; +exp NULL Warnings: Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '1998-01-01 01:01:01.999999' -select subtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999"); -subtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999") +select subtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999") as exp; +exp NULL Warnings: Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '1998-01-01 01:01:01.999999' -select subtime("01:00:00.999999", "02:00:00.999998"); -subtime("01:00:00.999999", "02:00:00.999998") +select subtime("01:00:00.999999", "02:00:00.999998") as exp; +exp -00:59:59.999999 -select subtime("02:01:01.999999", "01:01:01.999999"); -subtime("02:01:01.999999", "01:01:01.999999") +select subtime("02:01:01.999999", "01:01:01.999999") as exp; +exp 01:00:00 -select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002"); -timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002") +select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002") as exp; +exp 838:59:59.999999 Warnings: Warning 1292 Truncated incorrect time value: '8807:59:59.999999' -select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002"); -timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") +select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") as exp; +exp 46:58:57.999999 -select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002"); -timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002") +select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002") as exp; +exp -24:00:00.000001 -select timediff("1997-12-31 23:59:59.000001","23:59:59.000001"); -timediff("1997-12-31 23:59:59.000001","23:59:59.000001") +select timediff("1997-12-31 23:59:59.000001","23:59:59.000001") as exp; +exp NULL -select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001"); -timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001") +select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001") as exp; +exp -00:00:00.000001 -select timediff("2005-01-11 15:48:49.999999", "2005-01-11 15:48:50"); -timediff("2005-01-11 15:48:49.999999", "2005-01-11 15:48:50") +select timediff("2005-01-11 15:48:49.999999", "2005-01-11 15:48:50") as exp; +exp -00:00:00.000001 select maketime(10,11,12); maketime(10,11,12) @@ -262,14 +262,14 @@ a select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f"); str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f") 2003-01-02 10:11:12.001200 -select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10'),time('00:00:00'); -timediff('2008-09-29 20:10:10','2008-09-30 20:10:10') time('00:00:00') +select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10'),time('00:00:00') as exp; +timediff('2008-09-29 20:10:10','2008-09-30 20:10:10') exp -24:00:00 00:00:00 -select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')>time('00:00:00'); -timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')>time('00:00:00') +select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')>time('00:00:00') as exp; +exp 0 -select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')time('00:00:00'); -select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')time('00:00:00') as exp; +select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')neg == 0' failed in void date_to_datetime(MYSQL_TIME*) --echo # -#enable after fix MDEV-27871 ---disable_view_protocol CREATE TABLE t1 (d DATE); INSERT INTO t1 VALUES ('2005-07-20'),('2012-12-21'); -SELECT REPLACE( ADDDATE( d, INTERVAL 0.6732771076944444 HOUR_SECOND ), '2', 'x' ) FROM t1; -SELECT REPLACE( ADDDATE( d, INTERVAL '0.6732771076944444' HOUR_SECOND ), '2', 'x' ) FROM t1; -SELECT CAST(ADDDATE( d, INTERVAL 6732771076944444 SECOND) AS CHAR) FROM t1; -SELECT CAST(ADDDATE( d, INTERVAL '67327710769444:44' HOUR_SECOND) AS CHAR) FROM t1; -SELECT CAST(ADDDATE( d, INTERVAL '673277107694:44:44' HOUR_SECOND) AS CHAR) FROM t1; +SELECT REPLACE( ADDDATE( d, INTERVAL 0.6732771076944444 HOUR_SECOND ), '2', 'x' ) as exp FROM t1; +SELECT REPLACE( ADDDATE( d, INTERVAL '0.6732771076944444' HOUR_SECOND ), '2', 'x' ) as exp FROM t1; +SELECT CAST(ADDDATE( d, INTERVAL 6732771076944444 SECOND) AS CHAR) as exp FROM t1; +SELECT CAST(ADDDATE( d, INTERVAL '67327710769444:44' HOUR_SECOND) AS CHAR) as exp FROM t1; +SELECT CAST(ADDDATE( d, INTERVAL '673277107694:44:44' HOUR_SECOND) AS CHAR) as exp FROM t1; DROP TABLE t1; # Maximum possible DAY_SECOND values in various formats -SELECT ADDDATE(DATE'0000-01-01', INTERVAL '3652423:23:59:59' DAY_SECOND); -SELECT ADDDATE(DATE'0000-01-01', INTERVAL '0:87658175:59:59' DAY_SECOND); -SELECT ADDDATE(DATE'0000-01-01', INTERVAL '0:0:5259490559:59' DAY_SECOND); -SELECT ADDDATE(DATE'0000-01-01', INTERVAL '0:0:0:315569433599' DAY_SECOND); +SELECT ADDDATE(DATE'0000-01-01', INTERVAL '3652423:23:59:59' DAY_SECOND) as exp; +SELECT ADDDATE(DATE'0000-01-01', INTERVAL '0:87658175:59:59' DAY_SECOND) as exp; +SELECT ADDDATE(DATE'0000-01-01', INTERVAL '0:0:5259490559:59' DAY_SECOND) as exp; +SELECT ADDDATE(DATE'0000-01-01', INTERVAL '0:0:0:315569433599' DAY_SECOND) as exp; # Out-of-range INTERVAL DAY_SECOND values -SELECT ADDDATE(DATE'0000-01-01', INTERVAL '3652423:0:0:315569433559' DAY_SECOND); -SELECT ADDDATE(DATE'0000-01-01', INTERVAL '0:87658175:0:315569433559' DAY_SECOND); -SELECT ADDDATE(DATE'0000-01-01', INTERVAL '0:0:5259490559:315569433599' DAY_SECOND); ---disable_view_protocol +SELECT ADDDATE(DATE'0000-01-01', INTERVAL '3652423:0:0:315569433559' DAY_SECOND) as exp; +SELECT ADDDATE(DATE'0000-01-01', INTERVAL '0:87658175:0:315569433559' DAY_SECOND) as exp; +SELECT ADDDATE(DATE'0000-01-01', INTERVAL '0:0:5259490559:315569433599' DAY_SECOND) as exp; --echo # --echo # MDEV-13202 Assertion `ltime->neg == 0' failed in date_to_datetime @@ -1889,7 +1845,7 @@ INSERT INTO t1 VALUES (1, '1970-01-01'); SELECT CONCAT(DATE_SUB(d, INTERVAL 17300000 HOUR)) FROM t1; DROP TABLE t1; -SELECT CONCAT(DATE_SUB(TIMESTAMP'1970-01-01 00:00:00', INTERVAL 17300000 HOUR)); +SELECT CONCAT(DATE_SUB(TIMESTAMP'1970-01-01 00:00:00', INTERVAL 17300000 HOUR)) as exp; --echo # diff --git a/mysql-test/main/gis-json.result b/mysql-test/main/gis-json.result index 644684f5a73..4ea2fec7674 100644 --- a/mysql-test/main/gis-json.result +++ b/mysql-test/main/gis-json.result @@ -1,44 +1,44 @@ -select st_asgeojson(geomfromtext('POINT(1 1)')); -st_asgeojson(geomfromtext('POINT(1 1)')) +select st_asgeojson(geomfromtext('POINT(1 1)')) as exp; +exp {"type": "Point", "coordinates": [1, 1]} -select st_asgeojson(geomfromtext('LINESTRING(10 10,20 10,20 20,10 20,10 10)')); -st_asgeojson(geomfromtext('LINESTRING(10 10,20 10,20 20,10 20,10 10)')) +select st_asgeojson(geomfromtext('LINESTRING(10 10,20 10,20 20,10 20,10 10)')) as exp; +exp {"type": "LineString", "coordinates": [[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]} -select st_asgeojson(geomfromtext('POLYGON((10 10,20 10,20 20,10 20,10 10))')); -st_asgeojson(geomfromtext('POLYGON((10 10,20 10,20 20,10 20,10 10))')) +select st_asgeojson(geomfromtext('POLYGON((10 10,20 10,20 20,10 20,10 10))')) as exp; +exp {"type": "Polygon", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]} -select st_asgeojson(geomfromtext('MULTIPOLYGON(((10 10,20 10,20 20,10 20,10 10)))')); -st_asgeojson(geomfromtext('MULTIPOLYGON(((10 10,20 10,20 20,10 20,10 10)))')) +select st_asgeojson(geomfromtext('MULTIPOLYGON(((10 10,20 10,20 20,10 20,10 10)))')) as exp; +exp {"type": "MultiPolygon", "coordinates": [[[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]]} -select st_asgeojson(geomfromtext('multilinestring((10 10,20 10,20 20,10 20,10 10))')); -st_asgeojson(geomfromtext('multilinestring((10 10,20 10,20 20,10 20,10 10))')) +select st_asgeojson(geomfromtext('multilinestring((10 10,20 10,20 20,10 20,10 10))')) as exp; +exp {"type": "MultiLineString", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]} -select st_asgeojson(geomfromtext('multipoint(10 10,20 10,20 20,10 20,10 10)')); -st_asgeojson(geomfromtext('multipoint(10 10,20 10,20 20,10 20,10 10)')) +select st_asgeojson(geomfromtext('multipoint(10 10,20 10,20 20,10 20,10 10)')) as exp; +exp {"type": "MultiPoint", "coordinates": [[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]} -select st_asgeojson(st_geomfromtext('GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))')); -st_asgeojson(st_geomfromtext('GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))')) +select st_asgeojson(st_geomfromtext('GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))')) as exp; +exp {"type": "GeometryCollection", "geometries": [{"type": "Point", "coordinates": [100, 0]}, {"type": "LineString", "coordinates": [[101, 0], [102, 1]]}]} -SELECT st_astext(st_geomfromgeojson('{"type":"point","coordinates":[1,2]}')); -st_astext(st_geomfromgeojson('{"type":"point","coordinates":[1,2]}')) +SELECT st_astext(st_geomfromgeojson('{"type":"point","coordinates":[1,2]}')) as exp; +exp POINT(1 2) -SELECT st_astext(st_geomfromgeojson('{"type":"LineString","coordinates":[[1,2],[4,5],[7,8]]}')); -st_astext(st_geomfromgeojson('{"type":"LineString","coordinates":[[1,2],[4,5],[7,8]]}')) +SELECT st_astext(st_geomfromgeojson('{"type":"LineString","coordinates":[[1,2],[4,5],[7,8]]}')) as exp; +exp LINESTRING(1 2,4 5,7 8) -SELECT st_astext(st_geomfromgeojson('{"type": "polygon", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')); -st_astext(st_geomfromgeojson('{"type": "polygon", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')) +SELECT st_astext(st_geomfromgeojson('{"type": "polygon", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')) as exp; +exp POLYGON((10 10,20 10,20 20,10 20,10 10)) -SELECT st_astext(st_geomfromgeojson('{"type":"multipoint","coordinates":[[1,2],[4,5],[7,8]]}')); -st_astext(st_geomfromgeojson('{"type":"multipoint","coordinates":[[1,2],[4,5],[7,8]]}')) +SELECT st_astext(st_geomfromgeojson('{"type":"multipoint","coordinates":[[1,2],[4,5],[7,8]]}')) as exp; +exp MULTIPOINT(1 2,4 5,7 8) -SELECT st_astext(st_geomfromgeojson('{"type": "multilinestring", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')); -st_astext(st_geomfromgeojson('{"type": "multilinestring", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')) +SELECT st_astext(st_geomfromgeojson('{"type": "multilinestring", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')) as exp; +exp MULTILINESTRING((10 10,20 10,20 20,10 20,10 10)) -SELECT st_astext(st_geomfromgeojson('{"type": "multipolygon", "coordinates": [[[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]]}')); -st_astext(st_geomfromgeojson('{"type": "multipolygon", "coordinates": [[[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]]}')) +SELECT st_astext(st_geomfromgeojson('{"type": "multipolygon", "coordinates": [[[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]]}')) as exp; +exp MULTIPOLYGON(((10 10,20 10,20 20,10 20,10 10))) -SELECT st_astext(st_geomfromgeojson('{"type": "GeometryCollection", "geometries": [{"type": "Point","coordinates": [100.0, 0.0]}, {"type": "LineString","coordinates": [[101.0, 0.0],[102.0, 1.0]]}]}')); -st_astext(st_geomfromgeojson('{"type": "GeometryCollection", "geometries": [{"type": "Point","coordinates": [100.0, 0.0]}, {"type": "LineString","coordinates": [[101.0, 0.0],[102.0, 1.0]]}]}')) +SELECT st_astext(st_geomfromgeojson('{"type": "GeometryCollection", "geometries": [{"type": "Point","coordinates": [100.0, 0.0]}, {"type": "LineString","coordinates": [[101.0, 0.0],[102.0, 1.0]]}]}')) as exp; +exp GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1)) SELECT st_astext(st_geomfromgeojson('{"type":"point"}')); st_astext(st_geomfromgeojson('{"type":"point"}')) @@ -55,27 +55,27 @@ st_astext(st_geomfromgeojson('{"type""point"}')) NULL Warnings: Warning 4038 Syntax error in JSON text in argument 1 to function 'st_geomfromgeojson' at position 7 -SELECT st_astext(st_geomfromgeojson('{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] } }')); -st_astext(st_geomfromgeojson('{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] } }')) +SELECT st_astext(st_geomfromgeojson('{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] } }')) as exp; +exp POINT(102 0.5) -SELECT st_astext(st_geomfromgeojson('{ "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "type": "Feature" }')); -st_astext(st_geomfromgeojson('{ "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "type": "Feature" }')) +SELECT st_astext(st_geomfromgeojson('{ "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "type": "Feature" }')) as exp; +exp POINT(102 0.5) -SELECT st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }]}')); -st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }]}')) +SELECT st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }]}')) as exp; +exp GEOMETRYCOLLECTION(POINT(102 0.5)) SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',5)); ERROR HY000: Incorrect option value: '5' for function ST_GeomFromGeoJSON -SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',1)); +SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',1)) as exp; ERROR 22023: Invalid GIS data provided to function ST_GeomFromGeoJSON. -SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',2)); -ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',2)) +SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',2)) as exp; +exp POINT(5.3 15) -SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',3)); -ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',3)) +SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',3)) as exp; +exp POINT(5.3 15) -SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',4)); -ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',4)) +SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',4)) as exp; +exp POINT(5.3 15) SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),2); ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),2) @@ -107,16 +107,16 @@ a NULL Warnings: Warning 4076 Incorrect GeoJSON format - empty 'coordinates' array. -SELECT ST_GEOMFROMGEOJSON("{ \"type\": \"Feature\", \"geometry\": [10, 20] }"); -ST_GEOMFROMGEOJSON("{ \"type\": \"Feature\", \"geometry\": [10, 20] }") +SELECT ST_GEOMFROMGEOJSON("{ \"type\": \"Feature\", \"geometry\": [10, 20] }") as exp; +exp NULL -SELECT ST_ASTEXT (ST_GEOMFROMGEOJSON ('{ "type": "GEOMETRYCOLLECTION", "coordinates": [102.0, 0.0]}')); -ST_ASTEXT (ST_GEOMFROMGEOJSON ('{ "type": "GEOMETRYCOLLECTION", "coordinates": [102.0, 0.0]}')) +SELECT ST_ASTEXT (ST_GEOMFROMGEOJSON ('{ "type": "GEOMETRYCOLLECTION", "coordinates": [102.0, 0.0]}')) as exp; +exp NULL Warnings: Warning 4048 Incorrect GeoJSON format specified for st_geomfromgeojson function. -SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"type": ["POINT"], "coINates": [0,0] }')); -ST_ASTEXT(ST_GEOMFROMGEOJSON('{"type": ["POINT"], "coINates": [0,0] }')) +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"type": ["POINT"], "coINates": [0,0] }')) as exp; +exp NULL Warnings: Warning 4048 Incorrect GeoJSON format specified for st_geomfromgeojson function. diff --git a/mysql-test/main/gis-json.test b/mysql-test/main/gis-json.test index cda395acab5..766a036609c 100644 --- a/mysql-test/main/gis-json.test +++ b/mysql-test/main/gis-json.test @@ -1,46 +1,39 @@ -- source include/have_geometry.inc -#enable after fix MDEV-27871 ---disable_view_protocol -select st_asgeojson(geomfromtext('POINT(1 1)')); -select st_asgeojson(geomfromtext('LINESTRING(10 10,20 10,20 20,10 20,10 10)')); -select st_asgeojson(geomfromtext('POLYGON((10 10,20 10,20 20,10 20,10 10))')); -select st_asgeojson(geomfromtext('MULTIPOLYGON(((10 10,20 10,20 20,10 20,10 10)))')); -select st_asgeojson(geomfromtext('multilinestring((10 10,20 10,20 20,10 20,10 10))')); -select st_asgeojson(geomfromtext('multipoint(10 10,20 10,20 20,10 20,10 10)')); -select st_asgeojson(st_geomfromtext('GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))')); +select st_asgeojson(geomfromtext('POINT(1 1)')) as exp; +select st_asgeojson(geomfromtext('LINESTRING(10 10,20 10,20 20,10 20,10 10)')) as exp; +select st_asgeojson(geomfromtext('POLYGON((10 10,20 10,20 20,10 20,10 10))')) as exp; +select st_asgeojson(geomfromtext('MULTIPOLYGON(((10 10,20 10,20 20,10 20,10 10)))')) as exp; +select st_asgeojson(geomfromtext('multilinestring((10 10,20 10,20 20,10 20,10 10))')) as exp; +select st_asgeojson(geomfromtext('multipoint(10 10,20 10,20 20,10 20,10 10)')) as exp; +select st_asgeojson(st_geomfromtext('GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))')) as exp; -SELECT st_astext(st_geomfromgeojson('{"type":"point","coordinates":[1,2]}')); -SELECT st_astext(st_geomfromgeojson('{"type":"LineString","coordinates":[[1,2],[4,5],[7,8]]}')); -SELECT st_astext(st_geomfromgeojson('{"type": "polygon", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')); -SELECT st_astext(st_geomfromgeojson('{"type":"multipoint","coordinates":[[1,2],[4,5],[7,8]]}')); -SELECT st_astext(st_geomfromgeojson('{"type": "multilinestring", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')); -SELECT st_astext(st_geomfromgeojson('{"type": "multipolygon", "coordinates": [[[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]]}')); -SELECT st_astext(st_geomfromgeojson('{"type": "GeometryCollection", "geometries": [{"type": "Point","coordinates": [100.0, 0.0]}, {"type": "LineString","coordinates": [[101.0, 0.0],[102.0, 1.0]]}]}')); ---enable_view_protocol +SELECT st_astext(st_geomfromgeojson('{"type":"point","coordinates":[1,2]}')) as exp; +SELECT st_astext(st_geomfromgeojson('{"type":"LineString","coordinates":[[1,2],[4,5],[7,8]]}')) as exp; +SELECT st_astext(st_geomfromgeojson('{"type": "polygon", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')) as exp; +SELECT st_astext(st_geomfromgeojson('{"type":"multipoint","coordinates":[[1,2],[4,5],[7,8]]}')) as exp; +SELECT st_astext(st_geomfromgeojson('{"type": "multilinestring", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')) as exp; +SELECT st_astext(st_geomfromgeojson('{"type": "multipolygon", "coordinates": [[[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]]}')) as exp; +SELECT st_astext(st_geomfromgeojson('{"type": "GeometryCollection", "geometries": [{"type": "Point","coordinates": [100.0, 0.0]}, {"type": "LineString","coordinates": [[101.0, 0.0],[102.0, 1.0]]}]}')) as exp; SELECT st_astext(st_geomfromgeojson('{"type":"point"}')); SELECT st_astext(st_geomfromgeojson('{"type":"point"')); SELECT st_astext(st_geomfromgeojson('{"type""point"}')); -#enable after fix MDEV-27871 ---disable_view_protocol -SELECT st_astext(st_geomfromgeojson('{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] } }')); -SELECT st_astext(st_geomfromgeojson('{ "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "type": "Feature" }')); -SELECT st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }]}')); +SELECT st_astext(st_geomfromgeojson('{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] } }')) as exp; +SELECT st_astext(st_geomfromgeojson('{ "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "type": "Feature" }')) as exp; +SELECT st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }]}')) as exp; --error ER_WRONG_VALUE_FOR_TYPE SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',5)); --error ER_GIS_INVALID_DATA -SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',1)); +SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',1)) as exp; -SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',2)); -SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',3)); -SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',4)); - ---enable_view_protocol +SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',2)) as exp; +SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',3)) as exp; +SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',4)) as exp; SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),2); SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),1); @@ -53,20 +46,15 @@ SELECT st_astext(st_geomfromgeojson('{"type": "MultiLineString","coordinates": [ SELECT st_astext(st_geomfromgeojson('{"type": "Polygon","coordinates": []}')) as a; SELECT st_astext(st_geomfromgeojson('{"type": "MultiPolygon","coordinates": []}')) as a; -#enable after fix MDEV-27871 ---disable_view_protocol -SELECT ST_GEOMFROMGEOJSON("{ \"type\": \"Feature\", \"geometry\": [10, 20] }"); +SELECT ST_GEOMFROMGEOJSON("{ \"type\": \"Feature\", \"geometry\": [10, 20] }") as exp; # # MDEV-25461 Assertion `je->state == JST_KEY' failed in Geometry::create_from_json. # -SELECT ST_ASTEXT (ST_GEOMFROMGEOJSON ('{ "type": "GEOMETRYCOLLECTION", "coordinates": [102.0, 0.0]}')); - -SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"type": ["POINT"], "coINates": [0,0] }')); - ---enable_view_protocol +SELECT ST_ASTEXT (ST_GEOMFROMGEOJSON ('{ "type": "GEOMETRYCOLLECTION", "coordinates": [102.0, 0.0]}')) as exp; +SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"type": ["POINT"], "coINates": [0,0] }')) as exp; --echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/main/gis.result b/mysql-test/main/gis.result index 057b348054b..979dcc7d4e9 100644 --- a/mysql-test/main/gis.result +++ b/mysql-test/main/gis.result @@ -463,8 +463,8 @@ gc geometrycollection YES NULL gm geometry YES NULL fid int(11) NO NULL DROP TABLE t1; -SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))); -AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))) +SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))) as exp; +exp POINT(1 4) explain extended SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))); id select_type table type possible_keys key key_len ref rows filtered Extra @@ -696,11 +696,11 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (pointfromtext('point(1,1)')); ERROR 23000: Column 'fl' cannot be null drop table t1; -select (asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))); -(asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))) +select (asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))) as exp; +exp POINT(10 10) -select (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))); -(asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))) +select (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))) as exp; +exp POINT(10 10) create table t1 (g GEOMETRY); select * from t1; @@ -1135,30 +1135,30 @@ NULL select envelope(0x0100000000030000000100000000000010); envelope(0x0100000000030000000100000000000010) NULL -select geometryn(0x0100000000070000000100000001030000000200000000000000ffff0000, 1); -geometryn(0x0100000000070000000100000001030000000200000000000000ffff0000, 1) +select geometryn(0x0100000000070000000100000001030000000200000000000000ffff0000, 1) as exp; +exp NULL -select geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1); -geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1) +select geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1) as exp; +exp NULL # # MDEV-4296 Assertion `n_linear_rings > 0' fails in Gis_polygon::centroid_xy # -SELECT Centroid( AsBinary( LineString(Point(0,0), Point(0,0), Point(0,0) ))); -Centroid( AsBinary( LineString(Point(0,0), Point(0,0), Point(0,0) ))) +SELECT Centroid( AsBinary( LineString(Point(0,0), Point(0,0), Point(0,0) ))) as exp; +exp NULL # # MDEV-4295 Server crashes in get_point on a query with Area, AsBinary, MultiPoint # -SELECT Area(AsBinary(MultiPoint(Point(0,9), Point(0,1), Point(2,2)))); -Area(AsBinary(MultiPoint(Point(0,9), Point(0,1), Point(2,2)))) +SELECT Area(AsBinary(MultiPoint(Point(0,9), Point(0,1), Point(2,2)))) as exp; +exp NULL End of 5.1 tests -select ST_AREA(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))')); -ST_AREA(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))')) +select ST_AREA(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))')) as exp; +exp 1.5 -select ST_LENGTH(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 100 30, 20 30), POINT(3 3), LINESTRING(20 20, 30 20))')); -ST_LENGTH(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 100 30, 20 30), POINT(3 3), LINESTRING(20 20, 30 20))')) +select ST_LENGTH(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 100 30, 20 30), POINT(3 3), LINESTRING(20 20, 30 20))')) as exp; +exp 160 DROP DATABASE IF EXISTS gis_ogs; CREATE DATABASE gis_ogs; @@ -1369,16 +1369,16 @@ FROM road_segments WHERE fid = 102; AsText(EndPoint(centerline)) POINT(44 31) -SELECT IsClosed(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary))) +SELECT IsClosed(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary))) as exp FROM named_places WHERE name = 'Goose Island'; -IsClosed(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary))) +exp 1 # Conformance Item T20 -SELECT IsRing(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary))) +SELECT IsRing(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary))) as exp FROM named_places WHERE name = 'Goose Island'; -IsRing(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary))) +exp 1 # Conformance Item T21 SELECT GLength(centerline) @@ -1477,11 +1477,10 @@ Area(shores) 8 # Conformance Item T37 SELECT ST_Equals(boundary, -PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1)) +PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1)) as exp FROM named_places WHERE name = 'Goose Island'; -ST_Equals(boundary, -PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1)) +exp 1 # Conformance Item T38 SELECT ST_Disjoint(centerlines, boundary) @@ -1519,11 +1518,11 @@ AND divided_routes.name = 'Route 75'; Crosses(road_segments.centerline, divided_routes.centerlines) 1 # Conformance Item T43 -SELECT ST_Intersects(road_segments.centerline, divided_routes.centerlines) +SELECT ST_Intersects(road_segments.centerline, divided_routes.centerlines) as exp FROM road_segments, divided_routes WHERE road_segments.fid = 102 AND divided_routes.name = 'Route 75'; -ST_Intersects(road_segments.centerline, divided_routes.centerlines) +exp 1 # Conformance Item T44 SELECT ST_Contains(forests.boundary, named_places.boundary) @@ -1594,21 +1593,15 @@ select st_distance(geomfromtext('LINESTRING(-95.9673005697771 36.13509598461, -95.9673057475387 36.1344478941074, -95.9673063519371 36.134484524621, -95.9673049102515 36.1343976584193)'), -geomfromtext('point(-95.96269500000000000000 36.14181833333330000000)')) ; -st_distance(geomfromtext('LINESTRING(-95.9673005697771 36.13509598461, - -95.9673057475387 36.1344478941074, - -95.9673063519371 36.134484524621, - +geomfromtext('point(-95.96269500000000000000 36.14181833333330000000)')) as exp ; +exp 0.008148695928146028 select st_distance(geomfromtext('point(-95.96269500000000000000 36.14181833333330000000)'), geomfromtext('LINESTRING(-95.9673005697771 36.13509598461, -95.9673057475387 36.1344478941074, -95.9673063519371 36.134484524621, - -95.9673049102515 36.1343976584193) ')) ; -st_distance(geomfromtext('point(-95.96269500000000000000 36.14181833333330000000)'), -geomfromtext('LINESTRING(-95.9673005697771 36.13509598461, - -95.9673057475387 36.1344478941074, - -95.9673063519371 36. + -95.9673049102515 36.1343976584193) ')) as exp ; +exp 0.008148695928146028 # # MDEV-4310 geometry function equals hangs forever. @@ -1670,13 +1663,13 @@ ENVELOPE(0x0100000000030000000100000000000010) NULL #should not crash SELECT -GEOMETRYN(0x0100000000070000000100000001030000000200000000000000ffff0000, 1); -GEOMETRYN(0x0100000000070000000100000001030000000200000000000000ffff0000, 1) +GEOMETRYN(0x0100000000070000000100000001030000000200000000000000ffff0000, 1) as exp; +exp NULL #should not crash SELECT -GEOMETRYN(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1); -GEOMETRYN(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1) +GEOMETRYN(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1) as exp; +exp NULL # # MDEV-3819 missing constraints for spatial column types @@ -1685,8 +1678,8 @@ create table t1 (pt point); insert into t1 values(Geomfromtext('POLYGON((1 1, 2 2, 2 1, 1 1))')); ERROR 22007: Incorrect POINT value: 'POLYGON((1 1,2 2,2 1,1 1))' for column `test`.`t1`.`pt` at row 1 drop table t1; -SELECT st_astext(ST_Buffer(ST_PolygonFromText('POLYGON((3 5, 2 4, 2 5, 3 5))'), -100)); -st_astext(ST_Buffer(ST_PolygonFromText('POLYGON((3 5, 2 4, 2 5, 3 5))'), -100)) +SELECT st_astext(ST_Buffer(ST_PolygonFromText('POLYGON((3 5, 2 4, 2 5, 3 5))'), -100)) as exp; +exp GEOMETRYCOLLECTION EMPTY CREATE VIEW v1 AS SELECT POINT(1,1) AS p; SHOW CREATE VIEW v1; @@ -1824,14 +1817,14 @@ drop table t1; select ST_IsRing(ST_LineFromText('LINESTRING(0 0,0 10,10 10,0 0)')); ST_IsRing(ST_LineFromText('LINESTRING(0 0,0 10,10 10,0 0)')) 1 -select ST_IsRing(ST_LineFromText('LINESTRING(0 0,0 10,10 10,-10 -10, 0 -10, 0 0)')); -ST_IsRing(ST_LineFromText('LINESTRING(0 0,0 10,10 10,-10 -10, 0 -10, 0 0)')) +select ST_IsRing(ST_LineFromText('LINESTRING(0 0,0 10,10 10,-10 -10, 0 -10, 0 0)')) as exp; +exp 0 # # MDEV-7514 GIS: PointOnSurface returns NULL instead of the point. # -SELECT ST_GEOMETRYTYPE(ST_PointOnSurface(ST_PolyFromText('POLYGON((-70.916 42.1002,-70.9468 42.0946,-70.9754 42.0875,-70.9749 42.0879,-70.9759 42.0897,-70.916 42.1002))'))); -ST_GEOMETRYTYPE(ST_PointOnSurface(ST_PolyFromText('POLYGON((-70.916 42.1002,-70.9468 42.0946,-70.9754 42.0875,-70.9749 42.0879,-70.9759 42.0897,-70.916 42.1002))'))) +SELECT ST_GEOMETRYTYPE(ST_PointOnSurface(ST_PolyFromText('POLYGON((-70.916 42.1002,-70.9468 42.0946,-70.9754 42.0875,-70.9749 42.0879,-70.9759 42.0897,-70.916 42.1002))'))) as exp; +exp NULL # # MDEV-7529 GIS: ST_Relate returns unexpected results for POINT relations diff --git a/mysql-test/main/gis.test b/mysql-test/main/gis.test index a93ee736566..e441f67e526 100644 --- a/mysql-test/main/gis.test +++ b/mysql-test/main/gis.test @@ -83,11 +83,15 @@ SELECT fid, Dimension(g) FROM gis_geometry; SELECT fid, GeometryType(g) FROM gis_geometry; SELECT fid, IsEmpty(g) FROM gis_geometry; SELECT fid, AsText(Envelope(g)) FROM gis_geometry; +--disable_view_protocol explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry; +--enable_view_protocol SELECT fid, X(g) FROM gis_point; SELECT fid, Y(g) FROM gis_point; +--disable_view_protocol explain extended select X(g),Y(g) FROM gis_point; +--enable_view_protocol SELECT fid, AsText(StartPoint(g)) FROM gis_line; SELECT fid, AsText(EndPoint(g)) FROM gis_line; @@ -95,7 +99,9 @@ SELECT fid, GLength(g) FROM gis_line; SELECT fid, NumPoints(g) FROM gis_line; SELECT fid, AsText(PointN(g, 2)) FROM gis_line; SELECT fid, IsClosed(g) FROM gis_line; +--disable_view_protocol explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM gis_line; +--enable_view_protocol SELECT fid, AsText(Centroid(g)) FROM gis_polygon; SELECT fid, Area(g) FROM gis_polygon; @@ -113,14 +119,18 @@ SELECT fid, NumGeometries(g) from gis_multi_point; SELECT fid, NumGeometries(g) from gis_multi_line; SELECT fid, NumGeometries(g) from gis_multi_polygon; SELECT fid, NumGeometries(g) from gis_geometrycollection; +--disable_view_protocol explain extended SELECT fid, NumGeometries(g) from gis_multi_point; +--enable_view_protocol SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point; SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line; SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon; SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection; SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection; +--disable_view_protocol explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point; +--enable_view_protocol #query plan for view protocol doesn't contain database name --disable_view_protocol @@ -157,13 +167,18 @@ ALTER TABLE t1 ADD fid INT NOT NULL; SHOW FIELDS FROM t1; DROP TABLE t1; -SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))); +SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))) as exp; +--disable_view_protocol explain extended SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))); explain extended SELECT AsText(GeometryFromWKB(AsWKB(PointFromText('POINT(1 4)')))); +--enable_view_protocol SELECT SRID(GeomFromText('LineString(1 1,2 2)',101)); + +--disable_view_protocol explain extended SELECT SRID(GeomFromText('LineString(1 1,2 2)',101)); #select issimple(MultiPoint(Point(3, 6), Point(4, 10))), issimple(Point(3, 6)),issimple(PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')),issimple(GeometryFromText('POINT(1 4)')), issimple(AsWKB(GeometryFromText('POINT(1 4)'))); explain extended select issimple(MultiPoint(Point(3, 6), Point(4, 10))), issimple(Point(3, 6)); +--enable_view_protocol create table t1 (a geometry not null); insert into t1 values (GeomFromText('Point(1 2)')); @@ -380,10 +395,10 @@ insert into t1 values (pointfromtext('point(1,1)')); drop table t1; -#enable after fix MDEV-27871 +#enable after MDEV-32456 --disable_view_protocol -select (asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))); -select (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))); +select (asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))) as exp; +select (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))) as exp; --enable_view_protocol --enable_metadata @@ -846,30 +861,27 @@ select astext(0x0100000000030000000100000000000010); select astext(st_centroid(0x0100000000030000000100000000000010)); select astext(st_exteriorring(0x0100000000030000000100000000000010)); select envelope(0x0100000000030000000100000000000010); -#enable after fix MDEV-27871 ---disable_view_protocol -select geometryn(0x0100000000070000000100000001030000000200000000000000ffff0000, 1); -select geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1); +select geometryn(0x0100000000070000000100000001030000000200000000000000ffff0000, 1) as exp; +select geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1) as exp; --echo # --echo # MDEV-4296 Assertion `n_linear_rings > 0' fails in Gis_polygon::centroid_xy --echo # -SELECT Centroid( AsBinary( LineString(Point(0,0), Point(0,0), Point(0,0) ))); +SELECT Centroid( AsBinary( LineString(Point(0,0), Point(0,0), Point(0,0) ))) as exp; --echo # --echo # MDEV-4295 Server crashes in get_point on a query with Area, AsBinary, MultiPoint --echo # -SELECT Area(AsBinary(MultiPoint(Point(0,9), Point(0,1), Point(2,2)))); +SELECT Area(AsBinary(MultiPoint(Point(0,9), Point(0,1), Point(2,2)))) as exp; --echo End of 5.1 tests #bug 850775 ST_AREA does not work on GEOMETRYCOLLECTIONs in maria-5.3-gis -select ST_AREA(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))')); +select ST_AREA(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))')) as exp; #bug 855336 ST_LENGTH does not work on GEOMETRYCOLLECTIONs -select ST_LENGTH(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 100 30, 20 30), POINT(3 3), LINESTRING(20 20, 30 20))')); +select ST_LENGTH(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 100 30, 20 30), POINT(3 3), LINESTRING(20 20, 30 20))')) as exp; ---enable_view_protocol # Conformance tests # @@ -1178,20 +1190,15 @@ SELECT AsText(EndPoint(centerline)) FROM road_segments WHERE fid = 102; -#enable after fix MDEV-27871 ---disable_view_protocol - -SELECT IsClosed(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary))) +SELECT IsClosed(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary))) as exp FROM named_places WHERE name = 'Goose Island'; --echo # Conformance Item T20 -SELECT IsRing(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary))) +SELECT IsRing(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary))) as exp FROM named_places WHERE name = 'Goose Island'; ---enable_view_protocol - --echo # Conformance Item T21 SELECT GLength(centerline) FROM road_segments @@ -1272,15 +1279,11 @@ SELECT Area(shores) FROM ponds WHERE fid = 120; -#enable after fix MDEV-27871 ---disable_view_protocol - --echo # Conformance Item T37 SELECT ST_Equals(boundary, -PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1)) +PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1)) as exp FROM named_places WHERE name = 'Goose Island'; ---enable_view_protocol --echo # Conformance Item T38 SELECT ST_Disjoint(centerlines, boundary) @@ -1312,17 +1315,12 @@ FROM road_segments, divided_routes WHERE road_segments.fid = 102 AND divided_routes.name = 'Route 75'; -#enable after fix MDEV-27871 ---disable_view_protocol - --echo # Conformance Item T43 -SELECT ST_Intersects(road_segments.centerline, divided_routes.centerlines) +SELECT ST_Intersects(road_segments.centerline, divided_routes.centerlines) as exp FROM road_segments, divided_routes WHERE road_segments.fid = 102 AND divided_routes.name = 'Route 75'; ---enable_view_protocol - --echo # Conformance Item T44 SELECT ST_Contains(forests.boundary, named_places.boundary) FROM forests, named_places @@ -1382,20 +1380,17 @@ USE test; --echo # BUG #1043845 st_distance() results are incorrect depending on variable order --echo # -#enable after fix MDEV-27871 ---disable_view_protocol select st_distance(geomfromtext('LINESTRING(-95.9673005697771 36.13509598461, -95.9673057475387 36.1344478941074, -95.9673063519371 36.134484524621, -95.9673049102515 36.1343976584193)'), - geomfromtext('point(-95.96269500000000000000 36.14181833333330000000)')) ; + geomfromtext('point(-95.96269500000000000000 36.14181833333330000000)')) as exp ; select st_distance(geomfromtext('point(-95.96269500000000000000 36.14181833333330000000)'), geomfromtext('LINESTRING(-95.9673005697771 36.13509598461, -95.9673057475387 36.1344478941074, -95.9673063519371 36.134484524621, - -95.9673049102515 36.1343976584193) ')) ; + -95.9673049102515 36.1343976584193) ')) as exp ; ---enable_view_protocol --echo # --echo # MDEV-4310 geometry function equals hangs forever. @@ -1457,16 +1452,13 @@ SELECT ASTEXT(0x0100000000030000000100000000000010); --echo #should not crash SELECT ENVELOPE(0x0100000000030000000100000000000010); -#enable after fix MDEV-27871 ---disable_view_protocol --echo #should not crash SELECT - GEOMETRYN(0x0100000000070000000100000001030000000200000000000000ffff0000, 1); + GEOMETRYN(0x0100000000070000000100000001030000000200000000000000ffff0000, 1) as exp; --echo #should not crash SELECT - GEOMETRYN(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1); ---enable_view_protocol + GEOMETRYN(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1) as exp; --echo # --echo # MDEV-3819 missing constraints for spatial column types @@ -1480,10 +1472,7 @@ drop table t1; # # MDEV-7516 Assertion `!cur_p->event' failed in Gcalc_scan_iterator::arrange_event(int, int) # -#enable after fix MDEV-27871 ---disable_view_protocol -SELECT st_astext(ST_Buffer(ST_PolygonFromText('POLYGON((3 5, 2 4, 2 5, 3 5))'), -100)); ---enable_view_protocol +SELECT st_astext(ST_Buffer(ST_PolygonFromText('POLYGON((3 5, 2 4, 2 5, 3 5))'), -100)) as exp; # # MDEV-7779 View definition changes upon creation @@ -1579,15 +1568,12 @@ drop table t1; --echo # MDEV-7510 GIS: IsRing returns false for a primitive triangle. --echo # select ST_IsRing(ST_LineFromText('LINESTRING(0 0,0 10,10 10,0 0)')); -#enable after fix MDEV-27871 ---disable_view_protocol -select ST_IsRing(ST_LineFromText('LINESTRING(0 0,0 10,10 10,-10 -10, 0 -10, 0 0)')); +select ST_IsRing(ST_LineFromText('LINESTRING(0 0,0 10,10 10,-10 -10, 0 -10, 0 0)')) as exp; --echo # --echo # MDEV-7514 GIS: PointOnSurface returns NULL instead of the point. --echo # -SELECT ST_GEOMETRYTYPE(ST_PointOnSurface(ST_PolyFromText('POLYGON((-70.916 42.1002,-70.9468 42.0946,-70.9754 42.0875,-70.9749 42.0879,-70.9759 42.0897,-70.916 42.1002))'))); ---enable_view_protocol +SELECT ST_GEOMETRYTYPE(ST_PointOnSurface(ST_PolyFromText('POLYGON((-70.916 42.1002,-70.9468 42.0946,-70.9754 42.0875,-70.9749 42.0879,-70.9759 42.0897,-70.916 42.1002))'))) as exp; --echo # --echo # MDEV-7529 GIS: ST_Relate returns unexpected results for POINT relations diff --git a/mysql-test/main/loaddata.result b/mysql-test/main/loaddata.result index b7d51a13c85..d00eb034505 100644 --- a/mysql-test/main/loaddata.result +++ b/mysql-test/main/loaddata.result @@ -231,8 +231,8 @@ load data infile 'MYSQL_TEST_DIR/t/loaddata.test' into table t1; Got one of the listed errors select * from t1; a b c -select load_file("MYSQL_TEST_DIR/t/loaddata.test"); -load_file("MYSQL_TEST_DIR/t/loaddata.test") +select load_file("MYSQL_TEST_DIR/t/loaddata.test") as exp; +exp NULL drop table t1, t2; create table t1(f1 int); @@ -405,8 +405,8 @@ after 4 \r 5C72 before 5 tab 09746162 after 5 tab 09746162 TRUNCATE t2; -SELECT LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt"); -LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt") +SELECT LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt") as exp; +exp 3 \tx 4 \r 5 tab @@ -424,8 +424,8 @@ after 4 \r 5C72 before 5 tab 09746162 after 5 tab 09746162 TRUNCATE t2; -SELECT LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt"); -LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt") +SELECT LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt") exp; +exp 3 \\tx 4 \\r 5 tab @@ -445,8 +445,8 @@ before 5 tab 09746162 after 5 tab 09746162 TRUNCATE t2; SET sql_mode = 'NO_BACKSLASH_ESCAPES'; -SELECT LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt"); -LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt") +SELECT LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt") as ep; +ep 3 \\tx 4 \\r 5 tab @@ -466,8 +466,8 @@ before 5 tab 09746162 after 5 tab 09746162 TRUNCATE t2; SET sql_mode = 'NO_BACKSLASH_ESCAPES'; -SELECT LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt"); -LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt") +SELECT LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt") as exp; +exp 3 \tx 4 \r 5 tab @@ -478,8 +478,9 @@ DROP TABLE t1,t2; # Bug #51893: crash with certain characters given to load_file # function on windows # -select load_file(0x0A9FB76C661B409C4BEC88098C5DD71B1072F9691F2E827D7EC8F092B299868A3CE196C04F0FB18CAB4E1557EB72331D812379DE7A75CA21C32E7C722C59E5CC33EF262EF04187B0F0EE756FA984DF2EAD37B1E4ADB064C3C5038F2E3B2D661B1C1150AAEB5425512E14D7506166D92D4533872E662F4B2D1428AAB5CCA72E75AA2EF325E196A5A02E2E8278873C64375845994B0F39BE2FF7B478332A7B0AA5E48877C47B6F513E997848AF8CCB8A899F3393AB35333CF0871E36698193862D486B4B9078B70C0A0A507B8A250F3F876F5A067632D5E65193E4445A1EC3A2C9B4C6F07AC334F0F62BC33357CB502E9B1C19D2398B6972AEC2EF21630F8C9134C4F7DD662D8AD7BDC9E19C46720F334B66C22D4BF32ED275144E20E7669FFCF6FC143667C9F02A577F32960FA9F2371BE1FA90E49CBC69C01531F140556854D588DD0E55E1307D78CA38E975CD999F9AEA604266329EE62BFB5ADDA67F549E211ECFBA906C60063696352ABB82AA782D25B17E872EA587871F450446DB1BAE0123D20404A8F2D2698B371002E986C8FCB969A99FF0E150A2709E2ED7633D02ADA87D5B3C9487D27B2BD9D21E2EC3215DCC3CDCD884371281B95A2E9987AAF82EB499C058D9C3E7DC1B66635F60DB121C72F929622DD47B6B2E69F59FF2AE6B63CC2EC60FFBA20EA50569DBAB5DAEFAEB4F03966C9637AB55662EDD28439155A82D053A5299448EDB2E7BEB0F62889E2F84E6C7F34B3212C9AAC32D521D5AB8480993F1906D5450FAB342A0FA6ED223E178BAC036B81E15783604C32A961EA1EF20BE2EBB93D34ED37BC03142B7583303E4557E48551E4BD7CBDDEA146D5485A5D212C35189F0BD6497E66912D2780A59A53B532E12C0A5ED1EC0445D96E8F2DD825221CFE4A65A87AA21DC8750481B9849DD81694C3357A0ED9B78D608D8EDDE28FAFBEC17844DE5709F41E121838DB55639D77E32A259A416D7013B2EB1259FDE1B498CBB9CAEE1D601DF3C915EA91C69B44E6B72062F5F4B3C73F06F2D5AD185E1692E2E0A01E7DD5133693681C52EE13B2BE42D03BDCF48E4E133CF06662339B778E1C3034F9939A433E157449172F7969ACCE1F5D2F65A4E09E4A5D5611EBEDDDBDB0C0C0A); -load_file(0x0A9FB76C661B409C4BEC88098C5DD71B1072F9691F2E827D7EC8F092B299868A3CE196C04F0FB18CAB4E1557EB72331D812379DE7A75CA21C32E7C722C59E5CC33EF262EF04187B0F0EE756FA984DF2EAD37B1E4ADB064C3C5038F2E3B2D661B1C1150AAEB5425512E14D7506166D92D4533872E662F4B2D142 +select +load_file(0x0A9FB76C661B409C4BEC88098C5DD71B1072F9691F2E827D7EC8F092B299868A3CE196C04F0FB18CAB4E1557EB72331D812379DE7A75CA21C32E7C722C59E5CC33EF262EF04187B0F0EE756FA984DF2EAD37B1E4ADB064C3C5038F2E3B2D661B1C1150AAEB5425512E14D7506166D92D4533872E662F4B2D1428AAB5CCA72E75AA2EF325E196A5A02E2E8278873C64375845994B0F39BE2FF7B478332A7B0AA5E48877C47B6F513E997848AF8CCB8A899F3393AB35333CF0871E36698193862D486B4B9078B70C0A0A507B8A250F3F876F5A067632D5E65193E4445A1EC3A2C9B4C6F07AC334F0F62BC33357CB502E9B1C19D2398B6972AEC2EF21630F8C9134C4F7DD662D8AD7BDC9E19C46720F334B66C22D4BF32ED275144E20E7669FFCF6FC143667C9F02A577F32960FA9F2371BE1FA90E49CBC69C01531F140556854D588DD0E55E1307D78CA38E975CD999F9AEA604266329EE62BFB5ADDA67F549E211ECFBA906C60063696352ABB82AA782D25B17E872EA587871F450446DB1BAE0123D20404A8F2D2698B371002E986C8FCB969A99FF0E150A2709E2ED7633D02ADA87D5B3C9487D27B2BD9D21E2EC3215DCC3CDCD884371281B95A2E9987AAF82EB499C058D9C3E7DC1B66635F60DB121C72F929622DD47B6B2E69F59FF2AE6B63CC2EC60FFBA20EA50569DBAB5DAEFAEB4F03966C9637AB55662EDD28439155A82D053A5299448EDB2E7BEB0F62889E2F84E6C7F34B3212C9AAC32D521D5AB8480993F1906D5450FAB342A0FA6ED223E178BAC036B81E15783604C32A961EA1EF20BE2EBB93D34ED37BC03142B7583303E4557E48551E4BD7CBDDEA146D5485A5D212C35189F0BD6497E66912D2780A59A53B532E12C0A5ED1EC0445D96E8F2DD825221CFE4A65A87AA21DC8750481B9849DD81694C3357A0ED9B78D608D8EDDE28FAFBEC17844DE5709F41E121838DB55639D77E32A259A416D7013B2EB1259FDE1B498CBB9CAEE1D601DF3C915EA91C69B44E6B72062F5F4B3C73F06F2D5AD185E1692E2E0A01E7DD5133693681C52EE13B2BE42D03BDCF48E4E133CF06662339B778E1C3034F9939A433E157449172F7969ACCE1F5D2F65A4E09E4A5D5611EBEDDDBDB0C0C0A) as exp; +exp NULL End of 5.0 tests CREATE TABLE t1 (a int); diff --git a/mysql-test/main/loaddata.test b/mysql-test/main/loaddata.test index 0a5e3c27007..9c1a583831b 100644 --- a/mysql-test/main/loaddata.test +++ b/mysql-test/main/loaddata.test @@ -159,8 +159,6 @@ select * from t1; # # It should not be possible to load from a file outside of vardir -#enable after fix MDEV-27871 ---disable_view_protocol --error 1238 set @@secure_file_priv= 0; @@ -173,11 +171,10 @@ select * from t1; # Test "load_file" returns NULL --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR -eval select load_file("$MYSQL_TEST_DIR/t/loaddata.test"); +eval select load_file("$MYSQL_TEST_DIR/t/loaddata.test") as exp; # cleanup drop table t1, t2; ---enable_view_protocol # # Bug#27586: Wrong autoinc value assigned by LOAD DATA in the @@ -447,15 +444,10 @@ SELECT 'before' AS t, id, val1, hex(val1) FROM t1 UNION TRUNCATE t2; -#enable after fix MDEV-27871 ---disable_view_protocol - --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR -eval SELECT LOAD_FILE("$file"); +eval SELECT LOAD_FILE("$file") as exp; --remove_file $file ---enable_view_protocol - --echo 1.2 NO_BACKSLASH_ESCAPES, override defaults for ESCAPED BY --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR @@ -471,14 +463,10 @@ SELECT 'before' AS t, id, val1, hex(val1) FROM t1 UNION TRUNCATE t2; -#enable after fix MDEV-27871 ---disable_view_protocol - --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR -eval SELECT LOAD_FILE("$file"); +eval SELECT LOAD_FILE("$file") exp; --remove_file $file ---enable_view_protocol # 2. with NO_BACKSLASH_ESCAPES off @@ -501,15 +489,10 @@ TRUNCATE t2; SET sql_mode = 'NO_BACKSLASH_ESCAPES'; -#enable after fix MDEV-27871 ---disable_view_protocol - --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR -eval SELECT LOAD_FILE("$file"); +eval SELECT LOAD_FILE("$file") as ep; --remove_file $file ---enable_view_protocol - SET sql_mode = ''; @@ -531,15 +514,10 @@ TRUNCATE t2; SET sql_mode = 'NO_BACKSLASH_ESCAPES'; -#enable after fix MDEV-27871 ---disable_view_protocol - --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR -eval SELECT LOAD_FILE("$file"); +eval SELECT LOAD_FILE("$file") as exp; --remove_file $file ---enable_view_protocol - # clean up set session sql_mode=@OLD_SQL_MODE; DROP TABLE t1,t2; @@ -550,12 +528,8 @@ DROP TABLE t1,t2; --echo # function on windows --echo # -#enable after fix MDEV-27871 ---disable_view_protocol - -select load_file(0x0A9FB76C661B409C4BEC88098C5DD71B1072F9691F2E827D7EC8F092B299868A3CE196C04F0FB18CAB4E1557EB72331D812379DE7A75CA21C32E7C722C59E5CC33EF262EF04187B0F0EE756FA984DF2EAD37B1E4ADB064C3C5038F2E3B2D661B1C1150AAEB5425512E14D7506166D92D4533872E662F4B2D1428AAB5CCA72E75AA2EF325E196A5A02E2E8278873C64375845994B0F39BE2FF7B478332A7B0AA5E48877C47B6F513E997848AF8CCB8A899F3393AB35333CF0871E36698193862D486B4B9078B70C0A0A507B8A250F3F876F5A067632D5E65193E4445A1EC3A2C9B4C6F07AC334F0F62BC33357CB502E9B1C19D2398B6972AEC2EF21630F8C9134C4F7DD662D8AD7BDC9E19C46720F334B66C22D4BF32ED275144E20E7669FFCF6FC143667C9F02A577F32960FA9F2371BE1FA90E49CBC69C01531F140556854D588DD0E55E1307D78CA38E975CD999F9AEA604266329EE62BFB5ADDA67F549E211ECFBA906C60063696352ABB82AA782D25B17E872EA587871F450446DB1BAE0123D20404A8F2D2698B371002E986C8FCB969A99FF0E150A2709E2ED7633D02ADA87D5B3C9487D27B2BD9D21E2EC3215DCC3CDCD884371281B95A2E9987AAF82EB499C058D9C3E7DC1B66635F60DB121C72F929622DD47B6B2E69F59FF2AE6B63CC2EC60FFBA20EA50569DBAB5DAEFAEB4F03966C9637AB55662EDD28439155A82D053A5299448EDB2E7BEB0F62889E2F84E6C7F34B3212C9AAC32D521D5AB8480993F1906D5450FAB342A0FA6ED223E178BAC036B81E15783604C32A961EA1EF20BE2EBB93D34ED37BC03142B7583303E4557E48551E4BD7CBDDEA146D5485A5D212C35189F0BD6497E66912D2780A59A53B532E12C0A5ED1EC0445D96E8F2DD825221CFE4A65A87AA21DC8750481B9849DD81694C3357A0ED9B78D608D8EDDE28FAFBEC17844DE5709F41E121838DB55639D77E32A259A416D7013B2EB1259FDE1B498CBB9CAEE1D601DF3C915EA91C69B44E6B72062F5F4B3C73F06F2D5AD185E1692E2E0A01E7DD5133693681C52EE13B2BE42D03BDCF48E4E133CF06662339B778E1C3034F9939A433E157449172F7969ACCE1F5D2F65A4E09E4A5D5611EBEDDDBDB0C0C0A); - ---enable_view_protocol +select +load_file(0x0A9FB76C661B409C4BEC88098C5DD71B1072F9691F2E827D7EC8F092B299868A3CE196C04F0FB18CAB4E1557EB72331D812379DE7A75CA21C32E7C722C59E5CC33EF262EF04187B0F0EE756FA984DF2EAD37B1E4ADB064C3C5038F2E3B2D661B1C1150AAEB5425512E14D7506166D92D4533872E662F4B2D1428AAB5CCA72E75AA2EF325E196A5A02E2E8278873C64375845994B0F39BE2FF7B478332A7B0AA5E48877C47B6F513E997848AF8CCB8A899F3393AB35333CF0871E36698193862D486B4B9078B70C0A0A507B8A250F3F876F5A067632D5E65193E4445A1EC3A2C9B4C6F07AC334F0F62BC33357CB502E9B1C19D2398B6972AEC2EF21630F8C9134C4F7DD662D8AD7BDC9E19C46720F334B66C22D4BF32ED275144E20E7669FFCF6FC143667C9F02A577F32960FA9F2371BE1FA90E49CBC69C01531F140556854D588DD0E55E1307D78CA38E975CD999F9AEA604266329EE62BFB5ADDA67F549E211ECFBA906C60063696352ABB82AA782D25B17E872EA587871F450446DB1BAE0123D20404A8F2D2698B371002E986C8FCB969A99FF0E150A2709E2ED7633D02ADA87D5B3C9487D27B2BD9D21E2EC3215DCC3CDCD884371281B95A2E9987AAF82EB499C058D9C3E7DC1B66635F60DB121C72F929622DD47B6B2E69F59FF2AE6B63CC2EC60FFBA20EA50569DBAB5DAEFAEB4F03966C9637AB55662EDD28439155A82D053A5299448EDB2E7BEB0F62889E2F84E6C7F34B3212C9AAC32D521D5AB8480993F1906D5450FAB342A0FA6ED223E178BAC036B81E15783604C32A961EA1EF20BE2EBB93D34ED37BC03142B7583303E4557E48551E4BD7CBDDEA146D5485A5D212C35189F0BD6497E66912D2780A59A53B532E12C0A5ED1EC0445D96E8F2DD825221CFE4A65A87AA21DC8750481B9849DD81694C3357A0ED9B78D608D8EDDE28FAFBEC17844DE5709F41E121838DB55639D77E32A259A416D7013B2EB1259FDE1B498CBB9CAEE1D601DF3C915EA91C69B44E6B72062F5F4B3C73F06F2D5AD185E1692E2E0A01E7DD5133693681C52EE13B2BE42D03BDCF48E4E133CF06662339B778E1C3034F9939A433E157449172F7969ACCE1F5D2F65A4E09E4A5D5611EBEDDDBDB0C0C0A) as exp; --echo End of 5.0 tests diff --git a/mysql-test/main/null.result b/mysql-test/main/null.result index 2671ee2c40c..b65f6bc0ccd 100644 --- a/mysql-test/main/null.result +++ b/mysql-test/main/null.result @@ -1735,8 +1735,8 @@ c1 c2 c3 SELECT NULLIF(COUNT(DISTINCT c1),0) FROM t1; NULLIF(COUNT(DISTINCT c1),0) 2 -SELECT CASE WHEN COUNT(DISTINCT c1)=0 THEN NULL ELSE COUNT(DISTINCT c1) END FROM t1; -CASE WHEN COUNT(DISTINCT c1)=0 THEN NULL ELSE COUNT(DISTINCT c1) END +SELECT CASE WHEN COUNT(DISTINCT c1)=0 THEN NULL ELSE COUNT(DISTINCT c1) END as exp FROM t1; +exp 2 DROP TABLE t1; CREATE TABLE t1 ( diff --git a/mysql-test/main/null.test b/mysql-test/main/null.test index 7c5a32e4307..35ffb01d3c7 100644 --- a/mysql-test/main/null.test +++ b/mysql-test/main/null.test @@ -1065,12 +1065,7 @@ SELECT CASE WHEN COUNT(c1)=0 THEN NULL ELSE COUNT(c1) END FROM t1; SELECT NULLIF(COUNT(c1)+0,0) AS c1,NULLIF(CAST(COUNT(c1) AS SIGNED),0) AS c2,NULLIF(CONCAT(COUNT(c1)),0) AS c3 FROM t1; SELECT NULLIF(COUNT(DISTINCT c1),0) FROM t1; -#enable view protocol after fix MDEV-27871 ---disable_view_protocol - -SELECT CASE WHEN COUNT(DISTINCT c1)=0 THEN NULL ELSE COUNT(DISTINCT c1) END FROM t1; - ---enable_view_protocol +SELECT CASE WHEN COUNT(DISTINCT c1)=0 THEN NULL ELSE COUNT(DISTINCT c1) END as exp FROM t1; DROP TABLE t1; diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test index 6e3ce243e9b..5ae00c8236f 100644 --- a/mysql-test/main/opt_trace.test +++ b/mysql-test/main/opt_trace.test @@ -551,7 +551,6 @@ insert into t1 values ('foo'), ('bar'); EXPLAIN SELECT * FROM t1 WHERE a= REPEAT('a', 0); SELECT * FROM t1 WHERE a= REPEAT('a', 0); -#enable after fix MDEV-27871 select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) AS JS from INFORMATION_SCHEMA.OPTIMIZER_TRACE; DROP TABLE t1; @@ -582,7 +581,6 @@ create table t1 (kp1 int, kp2 int, key(kp1, kp2)); insert into t1 values (1,1),(1,5),(5,1),(5,5); set optimizer_trace=1; select * from t1 force index(kp1) where (kp1=2 and kp2 >=4); -#enable after fix MDEV-27871 select JSON_DETAILED(JSON_EXTRACT(trace, '$**.range_scan_alternatives')) AS JS from INFORMATION_SCHEMA.OPTIMIZER_TRACE; drop table t1; @@ -595,7 +593,6 @@ INSERT INTO t1 SELECT seq, seq from seq_1_to_10; CREATE TABLE t2(a INT, b INT, key(a)); INSERT INTO t2 SELECT seq, seq from seq_1_to_100; -#enable after fix MDEV-27871 SET OPTIMIZER_TRACE=1; EXPLAIN SELECT * FROM t1, t2 WHERE t1.a=t2.a ORDER BY t2.b; select JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans')) AS JS from INFORMATION_SCHEMA.OPTIMIZER_TRACE; diff --git a/mysql-test/main/outfile_loaddata.result b/mysql-test/main/outfile_loaddata.result index 4356f8b113e..6d0133a57ea 100644 --- a/mysql-test/main/outfile_loaddata.result +++ b/mysql-test/main/outfile_loaddata.result @@ -8,8 +8,8 @@ INSERT INTO t1 VALUES (101, 202, '-r-', '=raker='); SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' FIELDS TERMINATED BY 'raker' FROM t1; Warnings: Warning 1475 First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY -SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt'); -LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') +SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') as exp; +exp 101raker202raker-r-raker=raker= CREATE TABLE t2 SELECT * FROM t1; @@ -23,8 +23,8 @@ i1 i2 c1 c2 DROP TABLE t2; # Only numeric fields, FIELDS TERMINATED BY 'r', no warnings: SELECT i1, i2 INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' FIELDS TERMINATED BY 'r' FROM t1; -SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt'); -LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') +SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') as exp; +exp 101r202 CREATE TABLE t2 SELECT i1, i2 FROM t1; @@ -38,8 +38,8 @@ DROP TABLE t2; SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' FIELDS TERMINATED BY '0' FROM t1; Warnings: Warning 1475 First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY -SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt'); -LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') +SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') as exp; +exp 10102020-r-0=raker= CREATE TABLE t2 SELECT * FROM t1; @@ -55,8 +55,8 @@ DROP TABLE t2; SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' FIELDS OPTIONALLY ENCLOSED BY '"' TERMINATED BY '0' FROM t1; Warnings: Warning 1475 First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY -SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt'); -LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') +SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') as exp; +exp 10102020"-r-"0"=raker=" CREATE TABLE t2 SELECT * FROM t1; @@ -70,8 +70,8 @@ i1 i2 c1 c2 DROP TABLE t2; # Only string fields, FIELDS OPTIONALLY ENCLOSED BY '"' TERMINATED BY '0', no warnings: SELECT c1, c2 INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' FIELDS OPTIONALLY ENCLOSED BY '"' TERMINATED BY '0' FROM t1; -SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt'); -LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') +SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') as exp; +exp "-r-"0"=raker=" CREATE TABLE t2 SELECT c1, c2 FROM t1; @@ -94,8 +94,8 @@ SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug32533.txt' FIELDS ENCLOSED BY 0xC Warnings: Warning 1638 Non-ASCII separator arguments are not fully supported TRUNCATE t1; -SELECT HEX(LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug32533.txt')); -HEX(LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug32533.txt')) +SELECT HEX(LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug32533.txt')) as exp; +exp C35CC3C30A LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug32533.txt' INTO TABLE t1 FIELDS ENCLOSED BY 0xC3; Warnings: @@ -263,8 +263,8 @@ CREATE TABLE t2 LIKE t1; INSERT INTO t1 VALUES (REPEAT('.', 800)); SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug53088.txt' CHARACTER SET latin1 FROM t1; # should be greater than 800 -SELECT LENGTH(LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug53088.txt')); -LENGTH(LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug53088.txt')) +SELECT LENGTH(LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug53088.txt')) as exp; +exp 801 LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug53088.txt' INTO TABLE t2; # should be 800 diff --git a/mysql-test/main/outfile_loaddata.test b/mysql-test/main/outfile_loaddata.test index fa2c5a47051..64a40714b5a 100644 --- a/mysql-test/main/outfile_loaddata.test +++ b/mysql-test/main/outfile_loaddata.test @@ -2,9 +2,6 @@ DROP TABLE IF EXISTS t1, t2; --enable_warnings -#enable view protocol after fix MDEV-27871 --- source include/no_view_protocol.inc - --disable_ps2_protocol --echo # --echo # Bug#31663 FIELDS TERMINATED BY special character @@ -20,7 +17,7 @@ INSERT INTO t1 VALUES (101, 202, '-r-', '=raker='); --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval SELECT $fields INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/bug31663.txt' $clauses FROM t1 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---eval SELECT LOAD_FILE('$MYSQLTEST_VARDIR/tmp/bug31663.txt') +--eval SELECT LOAD_FILE('$MYSQLTEST_VARDIR/tmp/bug31663.txt') as exp --eval CREATE TABLE t2 SELECT $fields FROM t1 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/bug31663.txt' INTO TABLE t2 $clauses @@ -35,7 +32,7 @@ DROP TABLE t2; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval SELECT $fields INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/bug31663.txt' $clauses FROM t1 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---eval SELECT LOAD_FILE('$MYSQLTEST_VARDIR/tmp/bug31663.txt') +--eval SELECT LOAD_FILE('$MYSQLTEST_VARDIR/tmp/bug31663.txt') as exp --eval CREATE TABLE t2 SELECT $fields FROM t1 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/bug31663.txt' INTO TABLE t2 $clauses @@ -50,7 +47,7 @@ DROP TABLE t2; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval SELECT $fields INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/bug31663.txt' $clauses FROM t1 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---eval SELECT LOAD_FILE('$MYSQLTEST_VARDIR/tmp/bug31663.txt') +--eval SELECT LOAD_FILE('$MYSQLTEST_VARDIR/tmp/bug31663.txt') as exp --eval CREATE TABLE t2 SELECT $fields FROM t1 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/bug31663.txt' INTO TABLE t2 $clauses @@ -65,7 +62,7 @@ DROP TABLE t2; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval SELECT $fields INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/bug31663.txt' $clauses FROM t1 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---eval SELECT LOAD_FILE('$MYSQLTEST_VARDIR/tmp/bug31663.txt') +--eval SELECT LOAD_FILE('$MYSQLTEST_VARDIR/tmp/bug31663.txt') as exp --eval CREATE TABLE t2 SELECT $fields FROM t1 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/bug31663.txt' INTO TABLE t2 $clauses @@ -80,7 +77,7 @@ DROP TABLE t2; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval SELECT $fields INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/bug31663.txt' $clauses FROM t1 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---eval SELECT LOAD_FILE('$MYSQLTEST_VARDIR/tmp/bug31663.txt') +--eval SELECT LOAD_FILE('$MYSQLTEST_VARDIR/tmp/bug31663.txt') as exp --eval CREATE TABLE t2 SELECT $fields FROM t1 --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/bug31663.txt' INTO TABLE t2 $clauses @@ -105,7 +102,7 @@ SELECT HEX(c1) FROM t1; TRUNCATE t1; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---eval SELECT HEX(LOAD_FILE('$file')) +--eval SELECT HEX(LOAD_FILE('$file')) as exp --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval LOAD DATA INFILE '$file' INTO TABLE t1 FIELDS ENCLOSED BY 0xC3 @@ -281,7 +278,7 @@ let $length= 800; --echo # should be greater than $length --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---eval SELECT LENGTH(LOAD_FILE($file)) +--eval SELECT LENGTH(LOAD_FILE($file)) as exp --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval LOAD DATA INFILE $file INTO TABLE t2 diff --git a/mysql-test/main/second_frac-9175.result b/mysql-test/main/second_frac-9175.result index dbf268b5c3b..fd99fac16cb 100644 --- a/mysql-test/main/second_frac-9175.result +++ b/mysql-test/main/second_frac-9175.result @@ -1,13 +1,13 @@ -select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456'); -timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456') +select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456') as exp; +exp 31622400123456 -explain extended select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456'); +explain extended select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456') as exp; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select timestampdiff(MICROSECOND,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456') AS `timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456')` -create view v1 as select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456'); +Note 1003 select timestampdiff(MICROSECOND,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456') AS `exp` +create view v1 as select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456') as exp; select * from v1; -Name_exp_1 +exp 31622400123456 drop view v1; diff --git a/mysql-test/main/second_frac-9175.test b/mysql-test/main/second_frac-9175.test index 4cda672b820..1c918aae24e 100644 --- a/mysql-test/main/second_frac-9175.test +++ b/mysql-test/main/second_frac-9175.test @@ -2,13 +2,8 @@ # MDEV-9175 Query parser tansforms MICROSECOND into SECOND_FRAC, which does not work # -#enable after fix MDEV-27871 ---disable_view_protocol - -select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456'); -explain extended select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456'); -create view v1 as select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456'); +select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456') as exp; +explain extended select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456') as exp; +create view v1 as select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456') as exp; select * from v1; drop view v1; - ---enable_view_protocol diff --git a/mysql-test/main/select.result b/mysql-test/main/select.result index 6652b1a6375..7b68e2b6b02 100644 --- a/mysql-test/main/select.result +++ b/mysql-test/main/select.result @@ -4134,106 +4134,103 @@ ALTER VIEW v1 AS SELECT 1 AS ` `; ERROR 42000: Incorrect column name ' ' DROP VIEW v1; select str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT' - and '2007/10/20 00:00:00 GMT'; -str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT' - and '2007/10/20 00:00:00 GMT' + and '2007/10/20 00:00:00 GMT' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007/10/01 00:00:00 GMT' Warning 1292 Truncated incorrect datetime value: '2007/10/20 00:00:00 GMT' -select str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6'; -str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6' +select str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007/10/01 00:00:00 GMT-6' -select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/20 00:00:00 GMT-6'; -str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/20 00:00:00 GMT-6' +select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/20 00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007/10/20 00:00:00 GMT-6' -select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6'; -str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6' +select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6' as exp; +exp 0 Warnings: Warning 1292 Truncated incorrect datetime value: '2007/10/2000:00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-1 00:00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect date value: '2007-10-01 x00:00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 00:00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 00:x00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect date value: '2007-10-01 x12:34:56 GMT-6' -select str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'; -str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' +select str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34x:56 GMT-6' -select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'; -str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' +select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' as exp; +exp 0 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34x:56 GMT-6' -select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56'; -str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56' +select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56' as exp; +exp 1 -select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00'; -str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00' +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00' as exp; +exp 0 -select str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00'; -str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00' +select str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00' as exp; +exp 1 -select str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00'; -str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00' +select str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34' -select str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34'; -str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34' +select str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34' as exp; +exp 1 -select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; -str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' as exp; +exp 1 select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00' - and '2007/10/20 00:00:00'; -str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00' - and '2007/10/20 00:00:00' + and '2007/10/20 00:00:00' as exp; +exp 1 set SQL_MODE=TRADITIONAL; -select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; -str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' as exp; +exp NULL Warnings: Warning 1411 Incorrect datetime value: '2007-10-00 12:34' for function str_to_date -select str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; -str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' +select str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' as exp; +exp 0 -select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34'; -str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34' +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34' as exp; +exp NULL Warnings: Warning 1411 Incorrect datetime value: '2007-10-00 12:34' for function str_to_date select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01' - and '2007/10/20'; -str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01' - and '2007/10/20' + and '2007/10/20' as exp; +exp NULL Warnings: Warning 1411 Incorrect datetime value: '2007-10-00' for function str_to_date @@ -4272,23 +4269,23 @@ str_to_date('','%Y-%m-%d') = '' 1 Warnings: Warning 1292 Truncated incorrect datetime value: '' -select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01'; -str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01' +select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01' as exp; +exp 1 -select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and NULL; -str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and NULL +select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and NULL as exp; +exp NULL -select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '2001-01-01'; -str_to_date('2000-01-01','%Y-%m-%d') between NULL and '2001-01-01' +select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '2001-01-01' as exp; +exp NULL -select str_to_date('2000-01-01','%Y-%m-%d') between '2001-01-01' and NULL; -str_to_date('2000-01-01','%Y-%m-%d') between '2001-01-01' and NULL +select str_to_date('2000-01-01','%Y-%m-%d') between '2001-01-01' and NULL as exp; +exp 0 -select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '1000-01-01'; -str_to_date('2000-01-01','%Y-%m-%d') between NULL and '1000-01-01' +select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '1000-01-01' as exp; +exp 0 -select str_to_date('2000-01-01','%Y-%m-%d') between NULL and NULL; -str_to_date('2000-01-01','%Y-%m-%d') between NULL and NULL +select str_to_date('2000-01-01','%Y-%m-%d') between NULL and NULL as exp; +exp NULL CREATE TABLE t1 (c11 INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY); CREATE TABLE t2 (c21 INT UNSIGNED NOT NULL, diff --git a/mysql-test/main/select.test b/mysql-test/main/select.test index cff0038ae4d..6ad4df1e189 100644 --- a/mysql-test/main/select.test +++ b/mysql-test/main/select.test @@ -3559,51 +3559,48 @@ DROP VIEW v1; # On DATETIME-like literals with trailing garbage, BETWEEN fudged in a # DATETIME comparator, while greater/less-than used bin-string comparisons. # Should correctly be compared as DATE or DATETIME, but throw a warning: -#enable after fix MDEV-27871 ---disable_view_protocol select str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT' - and '2007/10/20 00:00:00 GMT'; -select str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6'; -select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/20 00:00:00 GMT-6'; -select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6'; + and '2007/10/20 00:00:00 GMT' as exp; +select str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6' as exp; +select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/20 00:00:00 GMT-6' as exp; +select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6' as exp; # We have all we need -- and trailing garbage: # (leaving out a leading zero in first example to prove it's a # value-comparison, not a string-comparison!) -select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6'; -select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6'; -select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6'; -select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6'; +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6' as exp; +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6' as exp; +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6' as exp; +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6' as exp; # no time at all: -select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6'; +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6' as exp; # partial time: -select str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'; +select str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' as exp; # fail, different second part: -select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'; +select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' as exp; # correct syntax, no trailing nonsense -- this one must throw no warning: -select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56'; +select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56' as exp; # no warning, but failure (different hour parts): -select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00'; +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00' as exp; # succeed: -select str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00'; +select str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00' as exp; # succeed, but warn for "trailing garbage" (":34"): -select str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00'; +select str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00' as exp; # invalid date (Feb 30) succeeds -select str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34'; +select str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34' as exp; # 0-day for both, just works in default SQL mode. -select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' as exp; # 0-day, succeed select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00' - and '2007/10/20 00:00:00'; + and '2007/10/20 00:00:00' as exp; set SQL_MODE=TRADITIONAL; # 0-day throws warning in traditional mode, and fails -select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; -select str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' as exp; +select str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' as exp; # different code-path: get_datetime_value() with 0-day -select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34'; +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34' as exp; select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01' - and '2007/10/20'; ---enable_view_protocol + and '2007/10/20' as exp; set SQL_MODE=DEFAULT; select str_to_date('2007-10-00','%Y-%m-%d') between '' and '2007/10/20'; select str_to_date('','%Y-%m-%d') between '2007/10/01' and '2007/10/20'; @@ -3615,15 +3612,12 @@ select str_to_date('1','%Y-%m-%d') = '1'; select str_to_date('1','%Y-%m-%d') = '1'; select str_to_date('','%Y-%m-%d') = ''; -#enable after fix MDEV-27871 ---disable_view_protocol -select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01'; -select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and NULL; -select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '2001-01-01'; -select str_to_date('2000-01-01','%Y-%m-%d') between '2001-01-01' and NULL; -select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '1000-01-01'; -select str_to_date('2000-01-01','%Y-%m-%d') between NULL and NULL; ---enable_view_protocol +select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01' as exp; +select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and NULL as exp; +select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '2001-01-01' as exp; +select str_to_date('2000-01-01','%Y-%m-%d') between '2001-01-01' and NULL as exp; +select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '1000-01-01' as exp; +select str_to_date('2000-01-01','%Y-%m-%d') between NULL and NULL as exp; # # Bug #30666: Incorrect order when using range conditions on 2 tables or more diff --git a/mysql-test/main/select_jcl6.result b/mysql-test/main/select_jcl6.result index cef6e0fcf2a..205dbf799e8 100644 --- a/mysql-test/main/select_jcl6.result +++ b/mysql-test/main/select_jcl6.result @@ -4145,106 +4145,103 @@ ALTER VIEW v1 AS SELECT 1 AS ` `; ERROR 42000: Incorrect column name ' ' DROP VIEW v1; select str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT' - and '2007/10/20 00:00:00 GMT'; -str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT' - and '2007/10/20 00:00:00 GMT' + and '2007/10/20 00:00:00 GMT' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007/10/01 00:00:00 GMT' Warning 1292 Truncated incorrect datetime value: '2007/10/20 00:00:00 GMT' -select str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6'; -str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6' +select str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007/10/01 00:00:00 GMT-6' -select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/20 00:00:00 GMT-6'; -str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/20 00:00:00 GMT-6' +select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/20 00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007/10/20 00:00:00 GMT-6' -select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6'; -str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6' +select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6' as exp; +exp 0 Warnings: Warning 1292 Truncated incorrect datetime value: '2007/10/2000:00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-1 00:00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect date value: '2007-10-01 x00:00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 00:00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 00:x00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect date value: '2007-10-01 x12:34:56 GMT-6' -select str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'; -str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' +select str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34x:56 GMT-6' -select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'; -str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' +select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' as exp; +exp 0 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34x:56 GMT-6' -select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56'; -str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56' +select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56' as exp; +exp 1 -select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00'; -str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00' +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00' as exp; +exp 0 -select str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00'; -str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00' +select str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00' as exp; +exp 1 -select str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00'; -str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00' +select str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34' -select str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34'; -str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34' +select str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34' as exp; +exp 1 -select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; -str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' as exp; +exp 1 select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00' - and '2007/10/20 00:00:00'; -str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00' - and '2007/10/20 00:00:00' + and '2007/10/20 00:00:00' as exp; +exp 1 set SQL_MODE=TRADITIONAL; -select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; -str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' as exp; +exp NULL Warnings: Warning 1411 Incorrect datetime value: '2007-10-00 12:34' for function str_to_date -select str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; -str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' +select str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' as exp; +exp 0 -select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34'; -str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34' +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34' as exp; +exp NULL Warnings: Warning 1411 Incorrect datetime value: '2007-10-00 12:34' for function str_to_date select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01' - and '2007/10/20'; -str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01' - and '2007/10/20' + and '2007/10/20' as exp; +exp NULL Warnings: Warning 1411 Incorrect datetime value: '2007-10-00' for function str_to_date @@ -4283,23 +4280,23 @@ str_to_date('','%Y-%m-%d') = '' 1 Warnings: Warning 1292 Truncated incorrect datetime value: '' -select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01'; -str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01' +select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01' as exp; +exp 1 -select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and NULL; -str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and NULL +select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and NULL as exp; +exp NULL -select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '2001-01-01'; -str_to_date('2000-01-01','%Y-%m-%d') between NULL and '2001-01-01' +select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '2001-01-01' as exp; +exp NULL -select str_to_date('2000-01-01','%Y-%m-%d') between '2001-01-01' and NULL; -str_to_date('2000-01-01','%Y-%m-%d') between '2001-01-01' and NULL +select str_to_date('2000-01-01','%Y-%m-%d') between '2001-01-01' and NULL as exp; +exp 0 -select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '1000-01-01'; -str_to_date('2000-01-01','%Y-%m-%d') between NULL and '1000-01-01' +select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '1000-01-01' as exp; +exp 0 -select str_to_date('2000-01-01','%Y-%m-%d') between NULL and NULL; -str_to_date('2000-01-01','%Y-%m-%d') between NULL and NULL +select str_to_date('2000-01-01','%Y-%m-%d') between NULL and NULL as exp; +exp NULL CREATE TABLE t1 (c11 INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY); CREATE TABLE t2 (c21 INT UNSIGNED NOT NULL, diff --git a/mysql-test/main/select_pkeycache.result b/mysql-test/main/select_pkeycache.result index 6652b1a6375..7b68e2b6b02 100644 --- a/mysql-test/main/select_pkeycache.result +++ b/mysql-test/main/select_pkeycache.result @@ -4134,106 +4134,103 @@ ALTER VIEW v1 AS SELECT 1 AS ` `; ERROR 42000: Incorrect column name ' ' DROP VIEW v1; select str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT' - and '2007/10/20 00:00:00 GMT'; -str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT' - and '2007/10/20 00:00:00 GMT' + and '2007/10/20 00:00:00 GMT' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007/10/01 00:00:00 GMT' Warning 1292 Truncated incorrect datetime value: '2007/10/20 00:00:00 GMT' -select str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6'; -str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6' +select str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007/10/01 00:00:00 GMT-6' -select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/20 00:00:00 GMT-6'; -str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/20 00:00:00 GMT-6' +select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/20 00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007/10/20 00:00:00 GMT-6' -select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6'; -str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6' +select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6' as exp; +exp 0 Warnings: Warning 1292 Truncated incorrect datetime value: '2007/10/2000:00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-1 00:00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect date value: '2007-10-01 x00:00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 00:00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 00:x00:00 GMT-6' -select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6'; -str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect date value: '2007-10-01 x12:34:56 GMT-6' -select str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'; -str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' +select str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34x:56 GMT-6' -select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'; -str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' +select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' as exp; +exp 0 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34x:56 GMT-6' -select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56'; -str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56' +select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56' as exp; +exp 1 -select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00'; -str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00' +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00' as exp; +exp 0 -select str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00'; -str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00' +select str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00' as exp; +exp 1 -select str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00'; -str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00' +select str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00' as exp; +exp 1 Warnings: Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34' -select str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34'; -str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34' +select str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34' as exp; +exp 1 -select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; -str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' as exp; +exp 1 select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00' - and '2007/10/20 00:00:00'; -str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00' - and '2007/10/20 00:00:00' + and '2007/10/20 00:00:00' as exp; +exp 1 set SQL_MODE=TRADITIONAL; -select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; -str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' as exp; +exp NULL Warnings: Warning 1411 Incorrect datetime value: '2007-10-00 12:34' for function str_to_date -select str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; -str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' +select str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' as exp; +exp 0 -select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34'; -str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34' +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34' as exp; +exp NULL Warnings: Warning 1411 Incorrect datetime value: '2007-10-00 12:34' for function str_to_date select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01' - and '2007/10/20'; -str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01' - and '2007/10/20' + and '2007/10/20' as exp; +exp NULL Warnings: Warning 1411 Incorrect datetime value: '2007-10-00' for function str_to_date @@ -4272,23 +4269,23 @@ str_to_date('','%Y-%m-%d') = '' 1 Warnings: Warning 1292 Truncated incorrect datetime value: '' -select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01'; -str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01' +select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01' as exp; +exp 1 -select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and NULL; -str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and NULL +select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and NULL as exp; +exp NULL -select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '2001-01-01'; -str_to_date('2000-01-01','%Y-%m-%d') between NULL and '2001-01-01' +select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '2001-01-01' as exp; +exp NULL -select str_to_date('2000-01-01','%Y-%m-%d') between '2001-01-01' and NULL; -str_to_date('2000-01-01','%Y-%m-%d') between '2001-01-01' and NULL +select str_to_date('2000-01-01','%Y-%m-%d') between '2001-01-01' and NULL as exp; +exp 0 -select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '1000-01-01'; -str_to_date('2000-01-01','%Y-%m-%d') between NULL and '1000-01-01' +select str_to_date('2000-01-01','%Y-%m-%d') between NULL and '1000-01-01' as exp; +exp 0 -select str_to_date('2000-01-01','%Y-%m-%d') between NULL and NULL; -str_to_date('2000-01-01','%Y-%m-%d') between NULL and NULL +select str_to_date('2000-01-01','%Y-%m-%d') between NULL and NULL as exp; +exp NULL CREATE TABLE t1 (c11 INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY); CREATE TABLE t2 (c21 INT UNSIGNED NOT NULL, diff --git a/mysql-test/main/subselect4.result b/mysql-test/main/subselect4.result index 9dcf05c8565..10fe6ac1722 100644 --- a/mysql-test/main/subselect4.result +++ b/mysql-test/main/subselect4.result @@ -309,8 +309,8 @@ pk i 0 10 2 30 3 40 -SELECT (NULL, 1) NOT IN (SELECT t2a.i, t2a.pk FROM t2a WHERE t2a.pk = t1.pk) from t1; -(NULL, 1) NOT IN (SELECT t2a.i, t2a.pk FROM t2a WHERE t2a.pk = t1.pk) +SELECT (NULL, 1) NOT IN (SELECT t2a.i, t2a.pk FROM t2a WHERE t2a.pk = t1.pk) as exp from t1; +exp 1 NULL 1 @@ -325,8 +325,8 @@ pk i 0 10 2 30 3 40 -SELECT (NULL, 1) NOT IN (SELECT t2b.i, t2b.pk FROM t2b WHERE t2b.pk = t1.pk) from t1; -(NULL, 1) NOT IN (SELECT t2b.i, t2b.pk FROM t2b WHERE t2b.pk = t1.pk) +SELECT (NULL, 1) NOT IN (SELECT t2b.i, t2b.pk FROM t2b WHERE t2b.pk = t1.pk) as exp from t1; +exp 1 NULL 1 @@ -341,8 +341,8 @@ pk i 0 10 2 30 3 40 -SELECT (NULL, 1) NOT IN (SELECT t2c.i, t2c.pk FROM t2c WHERE t2c.pk = t1.pk) from t1; -(NULL, 1) NOT IN (SELECT t2c.i, t2c.pk FROM t2c WHERE t2c.pk = t1.pk) +SELECT (NULL, 1) NOT IN (SELECT t2c.i, t2c.pk FROM t2c WHERE t2c.pk = t1.pk) as exp from t1; +exp 1 NULL 1 @@ -357,8 +357,8 @@ pk i 0 10 2 30 3 40 -SELECT (NULL, 1) NOT IN (SELECT t2d.i, t2d.pk FROM t2d WHERE t2d.pk = t1.pk) from t1; -(NULL, 1) NOT IN (SELECT t2d.i, t2d.pk FROM t2d WHERE t2d.pk = t1.pk) +SELECT (NULL, 1) NOT IN (SELECT t2d.i, t2d.pk FROM t2d WHERE t2d.pk = t1.pk) as exp from t1; +exp 1 NULL 1 @@ -1759,7 +1759,7 @@ CREATE TABLE t3 ( f1 int NOT NULL , f2 int) ; INSERT INTO t3 VALUES (0,0), (0,0); EXPLAIN SELECT STRAIGHT_JOIN ( SELECT f2 FROM t1 WHERE ( f2 ) IN ( SELECT t3.f2 FROM t3 JOIN t2 ON t2.f1 = 1 ) -); +) as exp; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used 2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where @@ -1767,10 +1767,8 @@ id select_type table type possible_keys key key_len ref rows Extra 3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) SELECT STRAIGHT_JOIN ( SELECT f2 FROM t1 WHERE ( f2 ) IN ( SELECT t3.f2 FROM t3 JOIN t2 ON t2.f1 = 1 ) -); -( -SELECT f2 FROM t1 WHERE ( f2 ) IN ( SELECT t3.f2 FROM t3 JOIN t2 ON t2.f1 = 1 ) -) +) as exp; +exp NULL drop table t1, t2, t3; # @@ -2658,8 +2656,8 @@ SET @save_optimizer_switch=@@optimizer_switch; SET optimizer_switch='subquery_cache=off'; CREATE TABLE t1 (a INT,b INT); INSERT INTO t1 VALUES (0,0),(0,0); -SELECT (SELECT DISTINCT t1i.b FROM t1 t1i GROUP BY t1i.a ORDER BY MAX(t1o.b)) FROM t1 AS t1o; -(SELECT DISTINCT t1i.b FROM t1 t1i GROUP BY t1i.a ORDER BY MAX(t1o.b)) +SELECT (SELECT DISTINCT t1i.b FROM t1 t1i GROUP BY t1i.a ORDER BY MAX(t1o.b)) as exp FROM t1 AS t1o; +exp 0 SET @@optimizer_switch= @save_optimizer_switch; DROP TABLE t1; @@ -2811,17 +2809,8 @@ WHERE t1_outer.id <> id FROM t1 AS t1_outer GROUP BY f -); -1 IN ( -SELECT -(SELECT COUNT(id) -FROM t1 -WHERE t1_outer.id <> id -) AS f -FROM -t1 AS t1_outer -GROUP BY f -) +) as exp; +exp 1 SELECT 1 IN ( @@ -2833,17 +2822,8 @@ WHERE t1_outer.id <> id FROM t1 AS t1_outer GROUP BY 1 -); -1 IN ( -SELECT -(SELECT COUNT(id) -FROM t1 -WHERE t1_outer.id <> id -) AS f -FROM -t1 AS t1_outer -GROUP BY 1 -) +) as exp; +exp 1 DROP TABLE t1; # diff --git a/mysql-test/main/subselect4.test b/mysql-test/main/subselect4.test index 1db2a576612..903374461d2 100644 --- a/mysql-test/main/subselect4.test +++ b/mysql-test/main/subselect4.test @@ -1,7 +1,5 @@ # General purpose bug fix tests go here : subselect.test too large -#remove this include after fix MDEV-27871, MDEV-27957 ---source include/no_view_protocol.inc --source include/default_optimizer_switch.inc @@ -241,22 +239,22 @@ SELECT t1.pk, NULL NOT IN (SELECT t2d.i FROM t2d WHERE t2d.pk = t1.pk) FROM t1; EXPLAIN SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2a.i, t2a.pk FROM t2a WHERE t2a.pk = t1.pk); SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2a.i, t2a.pk FROM t2a WHERE t2a.pk = t1.pk); -SELECT (NULL, 1) NOT IN (SELECT t2a.i, t2a.pk FROM t2a WHERE t2a.pk = t1.pk) from t1; +SELECT (NULL, 1) NOT IN (SELECT t2a.i, t2a.pk FROM t2a WHERE t2a.pk = t1.pk) as exp from t1; EXPLAIN SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2b.i, t2b.pk FROM t2b WHERE t2b.pk = t1.pk); SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2b.i, t2b.pk FROM t2b WHERE t2b.pk = t1.pk); -SELECT (NULL, 1) NOT IN (SELECT t2b.i, t2b.pk FROM t2b WHERE t2b.pk = t1.pk) from t1; +SELECT (NULL, 1) NOT IN (SELECT t2b.i, t2b.pk FROM t2b WHERE t2b.pk = t1.pk) as exp from t1; EXPLAIN SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2c.i, t2c.pk FROM t2c WHERE t2c.pk = t1.pk); SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2c.i, t2c.pk FROM t2c WHERE t2c.pk = t1.pk); -SELECT (NULL, 1) NOT IN (SELECT t2c.i, t2c.pk FROM t2c WHERE t2c.pk = t1.pk) from t1; +SELECT (NULL, 1) NOT IN (SELECT t2c.i, t2c.pk FROM t2c WHERE t2c.pk = t1.pk) as exp from t1; EXPLAIN SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2d.i, t2d.pk FROM t2d WHERE t2d.pk = t1.pk); SELECT * FROM t1 WHERE (NULL, 1) NOT IN (SELECT t2d.i, t2d.pk FROM t2d WHERE t2d.pk = t1.pk); -SELECT (NULL, 1) NOT IN (SELECT t2d.i, t2d.pk FROM t2d WHERE t2d.pk = t1.pk) from t1; +SELECT (NULL, 1) NOT IN (SELECT t2d.i, t2d.pk FROM t2d WHERE t2d.pk = t1.pk) as exp from t1; drop table t1, t2a, t2b, t2c, t2d; @@ -1359,10 +1357,10 @@ INSERT INTO t3 VALUES (0,0), (0,0); EXPLAIN SELECT STRAIGHT_JOIN ( SELECT f2 FROM t1 WHERE ( f2 ) IN ( SELECT t3.f2 FROM t3 JOIN t2 ON t2.f1 = 1 ) -); +) as exp; SELECT STRAIGHT_JOIN ( SELECT f2 FROM t1 WHERE ( f2 ) IN ( SELECT t3.f2 FROM t3 JOIN t2 ON t2.f1 = 1 ) -); +) as exp; drop table t1, t2, t3; @@ -2183,7 +2181,7 @@ SET @save_optimizer_switch=@@optimizer_switch; SET optimizer_switch='subquery_cache=off'; CREATE TABLE t1 (a INT,b INT); INSERT INTO t1 VALUES (0,0),(0,0); -SELECT (SELECT DISTINCT t1i.b FROM t1 t1i GROUP BY t1i.a ORDER BY MAX(t1o.b)) FROM t1 AS t1o; +SELECT (SELECT DISTINCT t1i.b FROM t1 t1i GROUP BY t1i.a ORDER BY MAX(t1o.b)) as exp FROM t1 AS t1o; SET @@optimizer_switch= @save_optimizer_switch; DROP TABLE t1; @@ -2341,7 +2339,7 @@ SELECT FROM t1 AS t1_outer GROUP BY f - ); + ) as exp; SELECT 1 IN ( @@ -2353,7 +2351,7 @@ SELECT FROM t1 AS t1_outer GROUP BY 1 - ); + ) as exp; DROP TABLE t1; diff --git a/mysql-test/main/subselect_exists2in.result b/mysql-test/main/subselect_exists2in.result index 6ff518b5a29..d39218d21d3 100644 --- a/mysql-test/main/subselect_exists2in.result +++ b/mysql-test/main/subselect_exists2in.result @@ -326,44 +326,44 @@ CREATE TABLE t3 ( c INT ); INSERT INTO t3 VALUES (4),(5); SET optimizer_switch='exists_to_in=on,subquery_cache=off,materialization=on,in_to_exists=off,semijoin=off'; explain extended -SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1; +SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) as exp FROM t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 2 SUBQUERY t2 system NULL NULL NULL NULL 1 100.00 3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: Note 1276 Field or reference 'test.t2.b' of SELECT #3 was resolved in SELECT #2 -Note 1003 /* select#1 */ select (/* select#2 */ select 1 from dual where !(1 is not null and (1,1 in ((1 in on distinct_key where 1 = ``.`c`))))) AS `( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) )` from `test`.`t1` -SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1; -( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) +Note 1003 /* select#1 */ select (/* select#2 */ select 1 from dual where !(1 is not null and (1,1 in ((1 in on distinct_key where 1 = ``.`c`))))) AS `exp` from `test`.`t1` +SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) as exp FROM t1; +exp 1 1 SET optimizer_switch='exists_to_in=on,subquery_cache=off'; explain extended -SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1; +SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) as exp FROM t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 2 SUBQUERY t2 system NULL NULL NULL NULL 1 100.00 3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: Note 1276 Field or reference 'test.t2.b' of SELECT #3 was resolved in SELECT #2 -Note 1003 /* select#1 */ select (/* select#2 */ select 1 from dual where !(1 is not null and (1,1 in ((1 in on distinct_key where 1 = ``.`c`))))) AS `( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) )` from `test`.`t1` -SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1; -( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) +Note 1003 /* select#1 */ select (/* select#2 */ select 1 from dual where !(1 is not null and (1,1 in ((1 in on distinct_key where 1 = ``.`c`))))) AS `exp` from `test`.`t1` +SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) as exp FROM t1; +exp 1 1 SET optimizer_switch='exists_to_in=off,subquery_cache=off'; explain extended -SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1; +SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) as exp FROM t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 2 SUBQUERY t2 system NULL NULL NULL NULL 1 100.00 3 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: Note 1276 Field or reference 'test.t2.b' of SELECT #3 was resolved in SELECT #2 -Note 1003 /* select#1 */ select (/* select#2 */ select 1 from dual where !exists(/* select#3 */ select `test`.`t3`.`c` from `test`.`t3` where `test`.`t3`.`c` = 1 limit 1)) AS `( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) )` from `test`.`t1` -SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1; -( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) +Note 1003 /* select#1 */ select (/* select#2 */ select 1 from dual where !exists(/* select#3 */ select `test`.`t3`.`c` from `test`.`t3` where `test`.`t3`.`c` = 1 limit 1)) AS `exp` from `test`.`t1` +SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) as exp FROM t1; +exp 1 1 set optimizer_switch=default; diff --git a/mysql-test/main/subselect_exists2in.test b/mysql-test/main/subselect_exists2in.test index 8ad89be2b65..89b37cffb34 100644 --- a/mysql-test/main/subselect_exists2in.test +++ b/mysql-test/main/subselect_exists2in.test @@ -270,24 +270,22 @@ INSERT INTO t3 VALUES (4),(5); SET optimizer_switch='exists_to_in=on,subquery_cache=off,materialization=on,in_to_exists=off,semijoin=off'; -#enable after fix MDEV-27871 ---disable_view_protocol explain extended -SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1; -SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1; +SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) as exp FROM t1; +SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) as exp FROM t1; SET optimizer_switch='exists_to_in=on,subquery_cache=off'; explain extended -SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1; -SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1; +SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) as exp FROM t1; +SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) as exp FROM t1; SET optimizer_switch='exists_to_in=off,subquery_cache=off'; explain extended -SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1; -SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1; +SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) as exp FROM t1; +SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) as exp FROM t1; set optimizer_switch=default; set optimizer_switch='exists_to_in=on'; @@ -327,8 +325,6 @@ set optimizer_switch='exists_to_in=on'; drop table t1,t3; ---enable_view_protocol - --echo # --echo # MDEV-159 Assertion about not marked for read failed in --echo # String* Field_varstring::val_str(String*, String*) diff --git a/mysql-test/main/subselect_mat_cost_bugs.result b/mysql-test/main/subselect_mat_cost_bugs.result index 1b5f94c427b..baadc01c960 100644 --- a/mysql-test/main/subselect_mat_cost_bugs.result +++ b/mysql-test/main/subselect_mat_cost_bugs.result @@ -412,14 +412,14 @@ pk1 int, a1 varchar(3), b1 varchar(3), PRIMARY KEY (pk1), KEY(a1), KEY(b1) INSERT INTO t1 VALUES (1,'foo','bar'),(2,'bar','foo'); CREATE TABLE t2 (pk2 INT PRIMARY KEY, a2 VARCHAR(3), KEY(a2)) ENGINE=MyISAM; INSERT INTO t2 VALUES (1,'abc'),(2,'xyz'),(3,'foo'); -SELECT 'qux' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ); -'qux' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ) +SELECT 'qux' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ) as exp; +exp 0 -SELECT 'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ); -'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ) +SELECT 'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ) as exp; +exp 1 EXPLAIN -SELECT 'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ); +SELECT 'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ) as exp; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used 2 SUBQUERY t2 const PRIMARY,a2 PRIMARY 4 const 1 diff --git a/mysql-test/main/subselect_mat_cost_bugs.test b/mysql-test/main/subselect_mat_cost_bugs.test index 4f837efcdd8..b66c0e076ef 100644 --- a/mysql-test/main/subselect_mat_cost_bugs.test +++ b/mysql-test/main/subselect_mat_cost_bugs.test @@ -442,13 +442,10 @@ INSERT INTO t1 VALUES (1,'foo','bar'),(2,'bar','foo'); CREATE TABLE t2 (pk2 INT PRIMARY KEY, a2 VARCHAR(3), KEY(a2)) ENGINE=MyISAM; INSERT INTO t2 VALUES (1,'abc'),(2,'xyz'),(3,'foo'); -#enable after fix MDEV-27871 ---disable_view_protocol -SELECT 'qux' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ); -SELECT 'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ); +SELECT 'qux' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ) as exp; +SELECT 'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ) as exp; EXPLAIN -SELECT 'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ); ---enable_view_protocol +SELECT 'bar' IN ( SELECT a1 FROM t1 INNER JOIN t2 WHERE a2 = b1 AND pk2 = 3 ) as exp; DROP TABLE t1,t2; diff --git a/mysql-test/main/type_date.result b/mysql-test/main/type_date.result index d1ea71dae68..3bd9e96aa67 100644 --- a/mysql-test/main/type_date.result +++ b/mysql-test/main/type_date.result @@ -70,15 +70,15 @@ CREATE TABLE t1(AFIELD INT); INSERT INTO t1 VALUES(1); CREATE TABLE t2(GMT VARCHAR(32)); INSERT INTO t2 VALUES('GMT-0800'); -SELECT DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) +SELECT DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) as exp FROM t1, t2 GROUP BY t1.AFIELD; -DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) +exp Wed, 06 March 2002 10:11:12 GMT-0800 INSERT INTO t1 VALUES(1); -SELECT DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)), -DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) +SELECT DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) as e1, +DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) as e2 FROM t1,t2 GROUP BY t1.AFIELD; -DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) +e1 e2 Wed, 06 March 2002 10:11:12 GMT-0800 Wed, 06 March 2002 10:11:12 GMT-0800 drop table t1,t2; CREATE TABLE t1 (f1 time default NULL, f2 time default NULL); @@ -306,8 +306,8 @@ drop table t1; # # MDEV-4634 Crash in CONVERT_TZ # -SELECT CONVERT_TZ(GREATEST(DATE('2021-00-00'),DATE('2022-00-00')),'+00:00','+7:5'); -CONVERT_TZ(GREATEST(DATE('2021-00-00'),DATE('2022-00-00')),'+00:00','+7:5') +SELECT CONVERT_TZ(GREATEST(DATE('2021-00-00'),DATE('2022-00-00')),'+00:00','+7:5') as exp; +exp NULL Warnings: Warning 1292 Incorrect datetime value: '2022-00-00' diff --git a/mysql-test/main/type_date.test b/mysql-test/main/type_date.test index 81cad6b5af5..3566e427d50 100644 --- a/mysql-test/main/type_date.test +++ b/mysql-test/main/type_date.test @@ -74,20 +74,17 @@ drop table t1; # Test problem with DATE_FORMAT # -#enable after fix MDEV-27871 ---disable_view_protocol CREATE TABLE t1(AFIELD INT); INSERT INTO t1 VALUES(1); CREATE TABLE t2(GMT VARCHAR(32)); INSERT INTO t2 VALUES('GMT-0800'); -SELECT DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) +SELECT DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) as exp FROM t1, t2 GROUP BY t1.AFIELD; INSERT INTO t1 VALUES(1); -SELECT DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)), - DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) +SELECT DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) as e1, + DATE_FORMAT("2002-03-06 10:11:12", CONCAT('%a, %d %M %Y %H:%i:%s ', t2.GMT)) as e2 FROM t1,t2 GROUP BY t1.AFIELD; drop table t1,t2; ---enable_view_protocol # # Multiple SELECT DATE_FORMAT gave incorrect results (Bug #4036) @@ -287,10 +284,7 @@ drop table t1; --echo # --echo # MDEV-4634 Crash in CONVERT_TZ --echo # -#enable after fix MDEV-27871 ---disable_view_protocol -SELECT CONVERT_TZ(GREATEST(DATE('2021-00-00'),DATE('2022-00-00')),'+00:00','+7:5'); ---enable_view_protocol +SELECT CONVERT_TZ(GREATEST(DATE('2021-00-00'),DATE('2022-00-00')),'+00:00','+7:5') as exp; --echo # --echo # MDEV-4804 Date comparing false result diff --git a/mysql-test/main/type_time.result b/mysql-test/main/type_time.result index f23849eb0c2..9fbdc7b8d9a 100644 --- a/mysql-test/main/type_time.result +++ b/mysql-test/main/type_time.result @@ -194,8 +194,8 @@ drop table t1; # MDEV-4634 Crash in CONVERT_TZ # SET timestamp=unix_timestamp('2001-02-03 10:20:30'); -SELECT CONVERT_TZ(GREATEST(TIME('00:00:00'),TIME('00:00:00')),'+00:00','+7:5'); -CONVERT_TZ(GREATEST(TIME('00:00:00'),TIME('00:00:00')),'+00:00','+7:5') +SELECT CONVERT_TZ(GREATEST(TIME('00:00:00'),TIME('00:00:00')),'+00:00','+7:5') as exp; +exp 2001-02-03 07:05:00 SET timestamp=DEFAULT; # @@ -1404,8 +1404,8 @@ SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:00'); SELECT TIME'10:20:30' IN (102030,TIME'10:20:31'); TIME'10:20:30' IN (102030,TIME'10:20:31') 1 -SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32'); -TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32') +SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32') as exp; +exp 1 CREATE TABLE t1 (a TIME); INSERT INTO t1 VALUES ('10:20:30'),('10:20:31'),('10:20:32'); diff --git a/mysql-test/main/type_time.test b/mysql-test/main/type_time.test index a75b278b1de..78549f3aabe 100644 --- a/mysql-test/main/type_time.test +++ b/mysql-test/main/type_time.test @@ -134,12 +134,9 @@ drop table t1; --echo # --echo # MDEV-4634 Crash in CONVERT_TZ --echo # -#enable after fix MDEV-27871 ---disable_view_protocol SET timestamp=unix_timestamp('2001-02-03 10:20:30'); -SELECT CONVERT_TZ(GREATEST(TIME('00:00:00'),TIME('00:00:00')),'+00:00','+7:5'); +SELECT CONVERT_TZ(GREATEST(TIME('00:00:00'),TIME('00:00:00')),'+00:00','+7:5') as exp; SET timestamp=DEFAULT; ---enable_view_protocol --echo # --echo # MDEV-4652 Wrong result for CONCAT(GREATEST(TIME('00:00:01'),TIME('00:00:00'))) @@ -854,10 +851,7 @@ DROP TABLE t1; --echo # SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:00'); SELECT TIME'10:20:30' IN (102030,TIME'10:20:31'); -#enable after fix MDEV-27871 ---disable_view_protocol -SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32'); ---enable_view_protocol +SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32') as exp; CREATE TABLE t1 (a TIME); INSERT INTO t1 VALUES ('10:20:30'),('10:20:31'),('10:20:32'); SELECT a FROM t1 WHERE a IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32') ORDER BY a; diff --git a/mysql-test/main/win_big-mdev-10092.result b/mysql-test/main/win_big-mdev-10092.result index dc8b7b9c3bd..b65a2cfad7a 100644 --- a/mysql-test/main/win_big-mdev-10092.result +++ b/mysql-test/main/win_big-mdev-10092.result @@ -79,8 +79,8 @@ call add_data(); call add_data(); set sort_buffer_size = 1024; flush status; -select o_custkey, Avg(o_custkey) OVER ( ORDER BY o_custkey ) from orders; -o_custkey Avg(o_custkey) OVER ( ORDER BY o_custkey ) +select o_custkey, Avg(o_custkey) OVER ( ORDER BY o_custkey ) as exp from orders; +o_custkey exp 593 593 593 593 892 742.5 @@ -196,14 +196,14 @@ o_custkey Avg(o_custkey) OVER ( ORDER BY o_custkey ) 14935 7440.456140350877 14935 7440.456140350877 select variable_name, -case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end +case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end as exp from information_schema.session_status where variable_name like 'Sort_merge_passes'; -variable_name case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end +variable_name exp SORT_MERGE_PASSES WITH PASSES flush status; -select o_custkey, Avg(o_custkey) OVER ( ORDER BY o_custkey RANGE CURRENT ROW ) from orders; -o_custkey Avg(o_custkey) OVER ( ORDER BY o_custkey RANGE CURRENT ROW ) +select o_custkey, Avg(o_custkey) OVER ( ORDER BY o_custkey RANGE CURRENT ROW ) as exp from orders; +o_custkey exp 593 593 593 593 892 892 @@ -319,10 +319,10 @@ o_custkey Avg(o_custkey) OVER ( ORDER BY o_custkey RANGE CURRENT ROW ) 14935 14935 14935 14935 select variable_name, -case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end +case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end as exp from information_schema.session_status where variable_name like 'Sort_merge_passes'; -variable_name case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end +variable_name exp SORT_MERGE_PASSES WITH PASSES drop table orders; drop procedure add_data; diff --git a/mysql-test/main/win_big-mdev-10092.test b/mysql-test/main/win_big-mdev-10092.test index c4bda66018b..036e24b77a6 100644 --- a/mysql-test/main/win_big-mdev-10092.test +++ b/mysql-test/main/win_big-mdev-10092.test @@ -85,24 +85,19 @@ call add_data(); call add_data(); set sort_buffer_size = 1024; -#enable after fix MDEV-27871 ---disable_view_protocol - flush status; -select o_custkey, Avg(o_custkey) OVER ( ORDER BY o_custkey ) from orders; +select o_custkey, Avg(o_custkey) OVER ( ORDER BY o_custkey ) as exp from orders; select variable_name, - case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end + case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end as exp from information_schema.session_status where variable_name like 'Sort_merge_passes'; flush status; -select o_custkey, Avg(o_custkey) OVER ( ORDER BY o_custkey RANGE CURRENT ROW ) from orders; +select o_custkey, Avg(o_custkey) OVER ( ORDER BY o_custkey RANGE CURRENT ROW ) as exp from orders; select variable_name, - case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end + case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end as exp from information_schema.session_status where variable_name like 'Sort_merge_passes'; ---enable_view_protocol - drop table orders; drop procedure add_data; diff --git a/mysql-test/main/win_big-mdev-11697.result b/mysql-test/main/win_big-mdev-11697.result index ec9d2243c88..59c3f97ee48 100644 --- a/mysql-test/main/win_big-mdev-11697.result +++ b/mysql-test/main/win_big-mdev-11697.result @@ -65,9 +65,9 @@ id next_id 9 10 10 11 select variable_name, -case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end +case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end as exp from information_schema.session_status where variable_name like 'Sort_merge_passes'; -variable_name case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end +variable_name exp SORT_MERGE_PASSES WITH PASSES drop table test_table; diff --git a/mysql-test/main/win_big-mdev-11697.test b/mysql-test/main/win_big-mdev-11697.test index 98669a18cee..04584c625f7 100644 --- a/mysql-test/main/win_big-mdev-11697.test +++ b/mysql-test/main/win_big-mdev-11697.test @@ -41,15 +41,12 @@ commit; analyze table test_table; explain select * from (select id, lead(id) over(order by id) next_id from test_table order by id) a limit 10; -#enable after fix MDEV-27871 ---disable_view_protocol flush status; select * from (select id, lead(id) over(order by id) next_id from test_table order by id) a limit 10; select variable_name, - case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end + case when variable_value > 0 then 'WITH PASSES' else 'NO PASSES' end as exp from information_schema.session_status where variable_name like 'Sort_merge_passes'; ---enable_view_protocol drop table test_table; diff --git a/mysql-test/main/win_orderby.result b/mysql-test/main/win_orderby.result index 1a9860c1c76..f38bdd77992 100644 --- a/mysql-test/main/win_orderby.result +++ b/mysql-test/main/win_orderby.result @@ -13,12 +13,12 @@ A.a + B.a* 10 + C.a * 100, from t0 A, t0 B, t0 C; select pk, -count(a) over (order by pk rows between 2 preceding and 2 following) +count(a) over (order by pk rows between 2 preceding and 2 following) as exp from t1 where pk between 1 and 30 order by pk desc limit 4; -pk count(a) over (order by pk rows between 2 preceding and 2 following) +pk exp 30 3 29 4 28 5 @@ -65,21 +65,9 @@ WINDOW w2 AS (ORDER BY id) ) ) ) -) +) as exp FROM t1; -id IN (SELECT id -FROM t1 -WINDOW w AS (ORDER BY (SELECT 1 -FROM t1 -WHERE -EXISTS ( SELECT id -FROM t1 -GROUP BY id -WINDOW w2 AS (ORDER BY id) -) -) -) -) +exp 1 1 1 diff --git a/mysql-test/main/win_orderby.test b/mysql-test/main/win_orderby.test index 65421fc095c..d0bcddfece1 100644 --- a/mysql-test/main/win_orderby.test +++ b/mysql-test/main/win_orderby.test @@ -21,16 +21,13 @@ select 1 from t0 A, t0 B, t0 C; -#enable after fix MDEV-27871 ---disable_view_protocol select pk, - count(a) over (order by pk rows between 2 preceding and 2 following) + count(a) over (order by pk rows between 2 preceding and 2 following) as exp from t1 where pk between 1 and 30 order by pk desc limit 4; ---disable_view_protocol drop table t0,t1; @@ -80,7 +77,7 @@ SELECT ) ) ) - ) + ) as exp FROM t1; DROP TABLE t1; diff --git a/mysql-test/main/win_std.result b/mysql-test/main/win_std.result index 36d99eec425..dac8a2d58eb 100644 --- a/mysql-test/main/win_std.result +++ b/mysql-test/main/win_std.result @@ -27,90 +27,90 @@ std(c) over (order by a) 0 0 # Empty frame. -select std(b) over (order by a rows between 2 following and 1 following) +select std(b) over (order by a rows between 2 following and 1 following) as exp from t2; -std(b) over (order by a rows between 2 following and 1 following) +exp NULL NULL NULL NULL NULL NULL -select std(b) over (order by a range between 2 following and 1 following) +select std(b) over (order by a range between 2 following and 1 following) as exp from t2; -std(b) over (order by a range between 2 following and 1 following) +exp NULL NULL NULL NULL NULL NULL -select std(b) over (order by a rows between 1 preceding and 2 preceding) +select std(b) over (order by a rows between 1 preceding and 2 preceding) as exp from t2; -std(b) over (order by a rows between 1 preceding and 2 preceding) +exp NULL NULL NULL NULL NULL NULL -select std(b) over (order by a range between 1 preceding and 2 preceding) +select std(b) over (order by a range between 1 preceding and 2 preceding) as exp from t2; -std(b) over (order by a range between 1 preceding and 2 preceding) +exp NULL NULL NULL NULL NULL NULL -select std(b) over (order by a rows between 1 following and 0 following) +select std(b) over (order by a rows between 1 following and 0 following) as exp from t2; -std(b) over (order by a rows between 1 following and 0 following) +exp NULL NULL NULL NULL NULL NULL -select std(b) over (order by a range between 1 following and 0 following) +select std(b) over (order by a range between 1 following and 0 following) as exp from t2; -std(b) over (order by a range between 1 following and 0 following) +exp NULL NULL NULL NULL NULL NULL -select std(b) over (order by a rows between 1 following and 0 preceding) +select std(b) over (order by a rows between 1 following and 0 preceding) as exp from t2; -std(b) over (order by a rows between 1 following and 0 preceding) +exp NULL NULL NULL NULL NULL NULL -select std(b) over (order by a range between 1 following and 0 preceding) +select std(b) over (order by a range between 1 following and 0 preceding) as exp from t2; -std(b) over (order by a range between 1 following and 0 preceding) +exp NULL NULL NULL NULL NULL NULL -select std(b) over (order by a rows between 0 following and 1 preceding) +select std(b) over (order by a rows between 0 following and 1 preceding) as exp from t2; -std(b) over (order by a rows between 0 following and 1 preceding) +exp NULL NULL NULL NULL NULL NULL -select std(b) over (order by a range between 0 following and 1 preceding) +select std(b) over (order by a range between 0 following and 1 preceding) as exp from t2; -std(b) over (order by a range between 0 following and 1 preceding) +exp NULL NULL NULL @@ -118,57 +118,56 @@ NULL NULL NULL # 1 row frame. -select std(b) over (order by a rows between current row and current row) +select std(b) over (order by a rows between current row and current row) as exp from t2; -std(b) over (order by a rows between current row and current row) +exp 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 -select std(b) over (order by a rows between 0 preceding and current row) +select std(b) over (order by a rows between 0 preceding and current row) as exp from t2; -std(b) over (order by a rows between 0 preceding and current row) +exp 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 -select std(b) over (order by a rows between 0 preceding and 0 preceding) +select std(b) over (order by a rows between 0 preceding and 0 preceding) as exp from t2; -std(b) over (order by a rows between 0 preceding and 0 preceding) +exp 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 -select std(b) over (order by a rows between 0 preceding and 0 following) +select std(b) over (order by a rows between 0 preceding and 0 following) as exp from t2; -std(b) over (order by a rows between 0 preceding and 0 following) +exp 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 -select std(b) over (order by a rows between 0 following and 0 preceding) -from t2; -std(b) over (order by a rows between 0 following and 0 preceding) +select std(b) over (order by a rows between 0 following and 0 preceding) as exp from t2; +exp 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 -select std(b) over (order by a rows between 0 following and current row) +select std(b) over (order by a rows between 0 following and current row) as exp from t2; ERROR HY000: Unacceptable combination of window frame bound specifications -select std(b) over (order by a rows between current row and 0 following) +select std(b) over (order by a rows between current row and 0 following) as exp from t2; -std(b) over (order by a rows between current row and 0 following) +exp 0.0000 0.0000 0.0000 @@ -176,39 +175,39 @@ std(b) over (order by a rows between current row and 0 following) 0.0000 0.0000 # Only peers frame. -select a, b, std(b) over (order by a range between 0 preceding and 0 preceding) +select a, b, std(b) over (order by a range between 0 preceding and 0 preceding) as exp from t2; -a b std(b) over (order by a range between 0 preceding and 0 preceding) +a b exp 0 1 0.8165 0 2 0.8165 0 3 0.8165 1 1 0.4714 1 1 0.4714 1 2 0.4714 -select a, b, std(b) over (order by a range between 0 preceding and current row) +select a, b, std(b) over (order by a range between 0 preceding and current row) as exp from t2; -a b std(b) over (order by a range between 0 preceding and current row) +a b exp 0 1 0.8165 0 2 0.8165 0 3 0.8165 1 1 0.4714 1 1 0.4714 1 2 0.4714 -select a, b, std(b) over (order by a range between current row and 0 preceding) +select a, b, std(b) over (order by a range between current row and 0 preceding) as exp from t2; ERROR HY000: Unacceptable combination of window frame bound specifications -select a, b, std(b) over (order by a range between current row and 0 following) +select a, b, std(b) over (order by a range between current row and 0 following) as exp from t2; -a b std(b) over (order by a range between current row and 0 following) +a b exp 0 1 0.8165 0 2 0.8165 0 3 0.8165 1 1 0.4714 1 1 0.4714 1 2 0.4714 -select a, b, std(b) over (order by a range between 0 following and 0 following) +select a, b, std(b) over (order by a range between 0 following and 0 following) as exp from t2; -a b std(b) over (order by a range between 0 following and 0 following) +a b exp 0 1 0.8165 0 2 0.8165 0 3 0.8165 @@ -216,36 +215,36 @@ a b std(b) over (order by a range between 0 following and 0 following) 1 1 0.4714 1 2 0.4714 # 2 rows frame. -select pk, a, b, std(b) over (order by a, b, pk rows between 1 preceding and current row) +select pk, a, b, std(b) over (order by a, b, pk rows between 1 preceding and current row) as exp from t2; -pk a b std(b) over (order by a, b, pk rows between 1 preceding and current row) +pk a b exp 1 0 1 0.0000 2 0 2 0.5000 3 0 3 0.5000 4 1 1 1.0000 5 1 1 0.0000 6 1 2 0.5000 -select pk, a, b, std(b) over (order by a, b, pk rows between 1 preceding and 0 preceding) +select pk, a, b, std(b) over (order by a, b, pk rows between 1 preceding and 0 preceding) as exp from t2; -pk a b std(b) over (order by a, b, pk rows between 1 preceding and 0 preceding) +pk a b exp 1 0 1 0.0000 2 0 2 0.5000 3 0 3 0.5000 4 1 1 1.0000 5 1 1 0.0000 6 1 2 0.5000 -select pk, a, b, std(b) over (order by a, b, pk rows between current row and 1 following) +select pk, a, b, std(b) over (order by a, b, pk rows between current row and 1 following) as exp from t2; -pk a b std(b) over (order by a, b, pk rows between current row and 1 following) +pk a b exp 1 0 1 0.5000 2 0 2 0.5000 3 0 3 1.0000 4 1 1 0.0000 5 1 1 0.5000 6 1 2 0.0000 -select pk, a, b, std(b) over (order by a, b, pk rows between 0 following and 1 following) +select pk, a, b, std(b) over (order by a, b, pk rows between 0 following and 1 following) as exp from t2; -pk a b std(b) over (order by a, b, pk rows between 0 following and 1 following) +pk a b exp 1 0 1 0.5000 2 0 2 0.5000 3 0 3 1.0000 @@ -253,36 +252,36 @@ pk a b std(b) over (order by a, b, pk rows between 0 following and 1 following) 5 1 1 0.5000 6 1 2 0.0000 # 2 peers frame. -select pk, a, b, std(b) over (order by a range between 1 preceding and current row) +select pk, a, b, std(b) over (order by a range between 1 preceding and current row) as exp from t2; -pk a b std(b) over (order by a range between 1 preceding and current row) +pk a b exp 1 0 1 0.8165 2 0 2 0.8165 3 0 3 0.8165 4 1 1 0.7454 5 1 1 0.7454 6 1 2 0.7454 -select pk, a, b, std(b) over (order by a range between 1 preceding and 0 preceding) +select pk, a, b, std(b) over (order by a range between 1 preceding and 0 preceding) as exp from t2; -pk a b std(b) over (order by a range between 1 preceding and 0 preceding) +pk a b exp 1 0 1 0.8165 2 0 2 0.8165 3 0 3 0.8165 4 1 1 0.7454 5 1 1 0.7454 6 1 2 0.7454 -select pk, a, b, std(b) over (order by a range between current row and 1 following) +select pk, a, b, std(b) over (order by a range between current row and 1 following) as exp from t2; -pk a b std(b) over (order by a range between current row and 1 following) +pk a b exp 1 0 1 0.7454 2 0 2 0.7454 3 0 3 0.7454 4 1 1 0.4714 5 1 1 0.4714 6 1 2 0.4714 -select pk, a, b, std(b) over (order by a range between 0 following and 1 following) +select pk, a, b, std(b) over (order by a range between 0 following and 1 following) as exp from t2; -pk a b std(b) over (order by a range between 0 following and 1 following) +pk a b exp 1 0 1 0.7454 2 0 2 0.7454 3 0 3 0.7454 diff --git a/mysql-test/main/win_std.test b/mysql-test/main/win_std.test index e7986e2cf84..c2186747f42 100644 --- a/mysql-test/main/win_std.test +++ b/mysql-test/main/win_std.test @@ -25,120 +25,115 @@ select std(c) over (order by a) from t2; --enable_warnings -#enable after fix MDEV-27871 ---disable_view_protocol - --echo # Empty frame. -select std(b) over (order by a rows between 2 following and 1 following) +select std(b) over (order by a rows between 2 following and 1 following) as exp from t2; -select std(b) over (order by a range between 2 following and 1 following) +select std(b) over (order by a range between 2 following and 1 following) as exp from t2; -select std(b) over (order by a rows between 1 preceding and 2 preceding) +select std(b) over (order by a rows between 1 preceding and 2 preceding) as exp from t2; -select std(b) over (order by a range between 1 preceding and 2 preceding) +select std(b) over (order by a range between 1 preceding and 2 preceding) as exp from t2; -select std(b) over (order by a rows between 1 following and 0 following) +select std(b) over (order by a rows between 1 following and 0 following) as exp from t2; -select std(b) over (order by a range between 1 following and 0 following) +select std(b) over (order by a range between 1 following and 0 following) as exp from t2; -select std(b) over (order by a rows between 1 following and 0 preceding) +select std(b) over (order by a rows between 1 following and 0 preceding) as exp from t2; -select std(b) over (order by a range between 1 following and 0 preceding) +select std(b) over (order by a range between 1 following and 0 preceding) as exp from t2; -select std(b) over (order by a rows between 0 following and 1 preceding) +select std(b) over (order by a rows between 0 following and 1 preceding) as exp from t2; -select std(b) over (order by a range between 0 following and 1 preceding) +select std(b) over (order by a range between 0 following and 1 preceding) as exp from t2; --echo # 1 row frame. -select std(b) over (order by a rows between current row and current row) +select std(b) over (order by a rows between current row and current row) as exp from t2; -select std(b) over (order by a rows between 0 preceding and current row) +select std(b) over (order by a rows between 0 preceding and current row) as exp from t2; -select std(b) over (order by a rows between 0 preceding and 0 preceding) +select std(b) over (order by a rows between 0 preceding and 0 preceding) as exp from t2; -select std(b) over (order by a rows between 0 preceding and 0 following) +select std(b) over (order by a rows between 0 preceding and 0 following) as exp from t2; -select std(b) over (order by a rows between 0 following and 0 preceding) -from t2; +select std(b) over (order by a rows between 0 following and 0 preceding) as exp from t2; --error ER_BAD_COMBINATION_OF_WINDOW_FRAME_BOUND_SPECS -select std(b) over (order by a rows between 0 following and current row) +select std(b) over (order by a rows between 0 following and current row) as exp from t2; -select std(b) over (order by a rows between current row and 0 following) +select std(b) over (order by a rows between current row and 0 following) as exp from t2; --echo # Only peers frame. --sorted_result -select a, b, std(b) over (order by a range between 0 preceding and 0 preceding) +select a, b, std(b) over (order by a range between 0 preceding and 0 preceding) as exp from t2; --sorted_result -select a, b, std(b) over (order by a range between 0 preceding and current row) +select a, b, std(b) over (order by a range between 0 preceding and current row) as exp from t2; --error ER_BAD_COMBINATION_OF_WINDOW_FRAME_BOUND_SPECS -select a, b, std(b) over (order by a range between current row and 0 preceding) +select a, b, std(b) over (order by a range between current row and 0 preceding) as exp from t2; --sorted_result -select a, b, std(b) over (order by a range between current row and 0 following) +select a, b, std(b) over (order by a range between current row and 0 following) as exp from t2; --sorted_result -select a, b, std(b) over (order by a range between 0 following and 0 following) +select a, b, std(b) over (order by a range between 0 following and 0 following) as exp from t2; --echo # 2 rows frame. --sorted_result -select pk, a, b, std(b) over (order by a, b, pk rows between 1 preceding and current row) +select pk, a, b, std(b) over (order by a, b, pk rows between 1 preceding and current row) as exp from t2; --sorted_result -select pk, a, b, std(b) over (order by a, b, pk rows between 1 preceding and 0 preceding) +select pk, a, b, std(b) over (order by a, b, pk rows between 1 preceding and 0 preceding) as exp from t2; --sorted_result -select pk, a, b, std(b) over (order by a, b, pk rows between current row and 1 following) +select pk, a, b, std(b) over (order by a, b, pk rows between current row and 1 following) as exp from t2; --sorted_result -select pk, a, b, std(b) over (order by a, b, pk rows between 0 following and 1 following) +select pk, a, b, std(b) over (order by a, b, pk rows between 0 following and 1 following) as exp from t2; --echo # 2 peers frame. --sorted_result -select pk, a, b, std(b) over (order by a range between 1 preceding and current row) +select pk, a, b, std(b) over (order by a range between 1 preceding and current row) as exp from t2; --sorted_result -select pk, a, b, std(b) over (order by a range between 1 preceding and 0 preceding) +select pk, a, b, std(b) over (order by a range between 1 preceding and 0 preceding) as exp from t2; --sorted_result -select pk, a, b, std(b) over (order by a range between current row and 1 following) +select pk, a, b, std(b) over (order by a range between current row and 1 following) as exp from t2; --sorted_result -select pk, a, b, std(b) over (order by a range between 0 following and 1 following) +select pk, a, b, std(b) over (order by a range between 0 following and 1 following) as exp from t2; ---enable_view_protocol drop table t1; drop table t2; From e3e66a575bb9be247744d24b497e0a8cd26e7fb1 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 7 Oct 2023 10:28:05 +0200 Subject: [PATCH 054/158] make perfschema.show_aggregate test more debuggable --- .../suite/perfschema/r/show_aggregate.result | 118 +++++++++--------- .../suite/perfschema/t/show_aggregate.test | 56 ++++----- 2 files changed, 83 insertions(+), 91 deletions(-) diff --git a/mysql-test/suite/perfschema/r/show_aggregate.result b/mysql-test/suite/perfschema/r/show_aggregate.result index 69861fa42c9..b5e957f3fc8 100644 --- a/mysql-test/suite/perfschema/r/show_aggregate.result +++ b/mysql-test/suite/perfschema/r/show_aggregate.result @@ -7,6 +7,7 @@ SET @@session.sql_log_bin=OFF; # CREATE 3 CLIENTS, 3 CONNECTIONS, RESULTS TABLE connection default; USE test; +flush status; # # Create results table CREATE TABLE test.status_results @@ -204,100 +205,99 @@ USE performance_schema; # # Verify expected counts for 'handler_delete' per thread # -SELECT *, IF (variable_value = 1,'OK','ERROR') AS Expected FROM status_by_thread WHERE thread_id = @con1_id AND variable_name IN ('handler_delete', 'handler_rollback'); +SELECT *, IF (variable_value = 1,'OK1','ERROR1') AS Expected FROM status_by_thread WHERE thread_id = @con1_id AND variable_name IN ('handler_delete', 'handler_rollback'); THREAD_ID VARIABLE_NAME VARIABLE_VALUE Expected -con_1 Handler_delete 1 OK -con_1 Handler_rollback 1 OK +con_1 Handler_delete 1 OK1 +con_1 Handler_rollback 1 OK1 # -SELECT *, IF (variable_value = 2,'OK','ERROR') AS Expected FROM status_by_thread WHERE thread_id = @con2_id AND variable_name IN ('handler_delete', 'handler_rollback'); +SELECT *, IF (variable_value = 2,'OK2','ERROR2') AS Expected FROM status_by_thread WHERE thread_id = @con2_id AND variable_name IN ('handler_delete', 'handler_rollback'); THREAD_ID VARIABLE_NAME VARIABLE_VALUE Expected -con_2 Handler_delete 2 OK -con_2 Handler_rollback 2 OK +con_2 Handler_delete 2 OK2 +con_2 Handler_rollback 2 OK2 # -SELECT *, IF (variable_value = 3,'OK','ERROR') AS Expected FROM status_by_thread WHERE thread_id = @con3_id AND variable_name IN ('handler_delete', 'handler_rollback'); +SELECT *, IF (variable_value = 3,'OK3','ERROR3') AS Expected FROM status_by_thread WHERE thread_id = @con3_id AND variable_name IN ('handler_delete', 'handler_rollback'); THREAD_ID VARIABLE_NAME VARIABLE_VALUE Expected -con_3 Handler_delete 3 OK -con_3 Handler_rollback 3 OK +con_3 Handler_delete 3 OK3 +con_3 Handler_rollback 3 OK3 # # STATUS_BY_THREAD vs. GLOBAL_STATUS # -SELECT variable_name, t1, t2, t3, delta, thread, IF(thread=delta,'OK','ERROR') Expected +SELECT variable_name, t1, t2, t3, delta, thread, IF(thread=delta,'OK4','ERROR4') Expected FROM test.status_results ORDER BY variable_name; variable_name t1 t2 t3 delta thread Expected -Handler_delete 1 2 3 6 6 OK -Handler_rollback 1 2 3 6 6 OK +Handler_delete 1 2 3 6 6 OK4 +Handler_rollback 1 2 3 6 6 OK4 # # ================================================================================ # TEST 2: STATUS_BY_USER: Verify expected status counts per user (1,2,3) # ================================================================================ -SELECT *, IF (variable_value = 1,'OK','ERROR') AS Expected FROM status_by_user WHERE user IN ('user1') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 1,'OK5','ERROR5') AS Expected FROM status_by_user WHERE user IN ('user1') AND variable_name IN ('handler_delete'); USER VARIABLE_NAME VARIABLE_VALUE Expected -user1 Handler_delete 1 OK +user1 Handler_delete 1 OK5 # -SELECT *, IF (variable_value = 2,'OK','ERROR') AS Expected FROM status_by_user WHERE user IN ('user2') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 2,'OK6','ERROR6') AS Expected FROM status_by_user WHERE user IN ('user2') AND variable_name IN ('handler_delete'); USER VARIABLE_NAME VARIABLE_VALUE Expected -user2 Handler_delete 2 OK +user2 Handler_delete 2 OK6 # -SELECT *, IF (variable_value = 3,'OK','ERROR') AS Expected FROM status_by_user WHERE user IN ('user3') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 3,'OK7','ERROR7') AS Expected FROM status_by_user WHERE user IN ('user3') AND variable_name IN ('handler_delete'); USER VARIABLE_NAME VARIABLE_VALUE Expected -user3 Handler_delete 3 OK +user3 Handler_delete 3 OK7 # # STATUS_BY_USER vs. GLOBAL_STATUS # -SELECT variable_name, u1, u2, u3, delta, user, IF(user=delta,'OK','ERROR') Expected +SELECT variable_name, u1, u2, u3, delta, user, IF(user=delta,'OK8','ERROR8') Expected FROM test.status_results ORDER BY variable_name; variable_name u1 u2 u3 delta user Expected -Handler_delete 1 2 3 6 6 OK -Handler_rollback 1 2 3 6 6 OK +Handler_delete 1 2 3 6 6 OK8 +Handler_rollback 1 2 3 6 6 OK8 # # ================================================================================ # TEST 3: STATUS_BY_ACCOUNT: Verify expected status counts per user, host (1,2,3) # ================================================================================ -SELECT *, IF (variable_value = 1,'OK','ERROR') AS Expected FROM status_by_account WHERE user IN ('user1') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 1,'OK9','ERROR9') AS Expected FROM status_by_account WHERE user IN ('user1') AND variable_name IN ('handler_delete'); USER HOST VARIABLE_NAME VARIABLE_VALUE Expected -user1 localhost Handler_delete 1 OK +user1 localhost Handler_delete 1 OK9 # -SELECT *, IF (variable_value = 2,'OK','ERROR') AS Expected FROM status_by_account WHERE user IN ('user2') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 2,'OKa','ERRORa') AS Expected FROM status_by_account WHERE user IN ('user2') AND variable_name IN ('handler_delete'); USER HOST VARIABLE_NAME VARIABLE_VALUE Expected -user2 localhost Handler_delete 2 OK +user2 localhost Handler_delete 2 OKa # -SELECT *, IF (variable_value = 3,'OK','ERROR') AS Expected FROM status_by_account WHERE user IN ('user3') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 3,'OKb','ERRORb') AS Expected FROM status_by_account WHERE user IN ('user3') AND variable_name IN ('handler_delete'); USER HOST VARIABLE_NAME VARIABLE_VALUE Expected -user3 localhost Handler_delete 3 OK +user3 localhost Handler_delete 3 OKb # # STATUS_BY_ACCOUNT vs. GLOBAL_STATUS # -SELECT variable_name, a1, a2, a3, delta, acct, IF(acct=delta,'OK','ERROR') Expected +SELECT variable_name, a1, a2, a3, delta, acct, IF(acct=delta,'OKc','ERRORc') Expected FROM test.status_results ORDER BY variable_name; variable_name a1 a2 a3 delta acct Expected -Handler_delete 1 2 3 6 6 OK -Handler_rollback 1 2 3 6 6 OK +Handler_delete 1 2 3 6 6 OKc +Handler_rollback 1 2 3 6 6 OKc # ================================================================================ # TEST 4: STATUS_BY_HOST: Verify expected status counts per host (6) # ================================================================================ -SELECT *, IF (variable_value = 6,'OK','ERROR') AS Expected FROM status_by_host WHERE host IN ('localhost') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 6,'OKd','ERRORd') AS Expected FROM status_by_host WHERE host IN ('localhost') AND variable_name IN ('handler_delete'); HOST VARIABLE_NAME VARIABLE_VALUE Expected -localhost Handler_delete 6 OK +localhost Handler_delete 6 OKd # # STATUS_BY_HOST vs. GLOBAL_STATUS # # Special case: No way to isolate pre-existing 'localhost' activity, so # just check global totals = sum(status_by_host). # -SELECT variable_name, h1, h2, h3, delta, host, IF(host=delta,'OK','ERROR') Expected +SELECT variable_name, h1, h2, h3, delta, host, IF(host=delta,'OKe','ERRORe') Expected FROM test.status_results ORDER BY variable_name; variable_name h1 h2 h3 delta host Expected -Handler_delete 6 0 0 6 6 OK -Handler_rollback 6 0 0 6 6 OK +Handler_delete 6 0 0 6 6 OKe +Handler_rollback 6 0 0 6 6 OKe # # ================================================================================ # DISCONNECT ALL USERS AND RUN THE TESTS AGAIN. RESULTS SHOULD NOT CHANGE. # ================================================================================ -connection default; disconnect con1; disconnect con2; disconnect con3; @@ -429,68 +429,68 @@ USE performance_schema; # ================================================================================ # TEST 5: STATUS_BY_USER: Verify expected status counts per user (1,2,3) # ================================================================================ -SELECT *, IF (variable_value = 1,'OK','ERROR') AS Expected FROM status_by_user WHERE user IN ('user1') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 1,'OKf','ERRORf') AS Expected FROM status_by_user WHERE user IN ('user1') AND variable_name IN ('handler_delete'); USER VARIABLE_NAME VARIABLE_VALUE Expected -user1 Handler_delete 1 OK +user1 Handler_delete 1 OKf # -SELECT *, IF (variable_value = 2,'OK','ERROR') AS Expected FROM status_by_user WHERE user IN ('user2') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 2,'OKg','ERRORg') AS Expected FROM status_by_user WHERE user IN ('user2') AND variable_name IN ('handler_delete'); USER VARIABLE_NAME VARIABLE_VALUE Expected -user2 Handler_delete 2 OK +user2 Handler_delete 2 OKg # -SELECT *, IF (variable_value = 3,'OK','ERROR') AS Expected FROM status_by_user WHERE user IN ('user3') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 3,'OKh','ERRORh') AS Expected FROM status_by_user WHERE user IN ('user3') AND variable_name IN ('handler_delete'); USER VARIABLE_NAME VARIABLE_VALUE Expected -user3 Handler_delete 3 OK +user3 Handler_delete 3 OKh # # STATUS_BY_USER vs. GLOBAL_STATUS # -SELECT variable_name, u1, u2, u3, delta, user, IF(user=delta,'OK','ERROR') Expected +SELECT variable_name, u1, u2, u3, delta, user, IF(user=delta,'OKi','ERRORi') Expected FROM test.status_results ORDER BY variable_name; variable_name u1 u2 u3 delta user Expected -Handler_delete 1 2 3 6 6 OK -Handler_rollback 1 2 3 6 6 OK +Handler_delete 1 2 3 6 6 OKi +Handler_rollback 1 2 3 6 6 OKi # # ================================================================================ # TEST 6: STATUS_BY_ACCOUNT: Verify expected status counts per user:host (1,2,3) # ================================================================================ -SELECT *, IF (variable_value = 1,'OK','ERROR') AS Expected FROM status_by_account WHERE user IN ('user1') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 1,'OKj','ERRORj') AS Expected FROM status_by_account WHERE user IN ('user1') AND variable_name IN ('handler_delete'); USER HOST VARIABLE_NAME VARIABLE_VALUE Expected -user1 localhost Handler_delete 1 OK +user1 localhost Handler_delete 1 OKj # -SELECT *, IF (variable_value = 2,'OK','ERROR') AS Expected FROM status_by_account WHERE user IN ('user2') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 2,'OKk','ERRORk') AS Expected FROM status_by_account WHERE user IN ('user2') AND variable_name IN ('handler_delete'); USER HOST VARIABLE_NAME VARIABLE_VALUE Expected -user2 localhost Handler_delete 2 OK +user2 localhost Handler_delete 2 OKk # -SELECT *, IF (variable_value = 3,'OK','ERROR') AS Expected FROM status_by_account WHERE user IN ('user3') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 3,'OKl','ERRORl') AS Expected FROM status_by_account WHERE user IN ('user3') AND variable_name IN ('handler_delete'); USER HOST VARIABLE_NAME VARIABLE_VALUE Expected -user3 localhost Handler_delete 3 OK +user3 localhost Handler_delete 3 OKl # # STATUS_BY_ACCOUNT vs. GLOBAL_STATUS # -SELECT variable_name, a1, a2, a3, delta, acct, IF(acct=delta,'OK','ERROR') Expected +SELECT variable_name, a1, a2, a3, delta, acct, IF(acct=delta,'OKn','ERRORn') Expected FROM test.status_results ORDER BY variable_name; variable_name a1 a2 a3 delta acct Expected -Handler_delete 1 2 3 6 6 OK -Handler_rollback 1 2 3 6 6 OK +Handler_delete 1 2 3 6 6 OKn +Handler_rollback 1 2 3 6 6 OKn # ================================================================================ # TEST 7: STATUS_BY_HOST: Verify expected status counts per host (6) # ================================================================================ -SELECT *, IF (variable_value = 6,'OK','ERROR') AS Expected FROM status_by_host WHERE host IN ('localhost') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 6,'OKo','ERRORo') AS Expected FROM status_by_host WHERE host IN ('localhost') AND variable_name IN ('handler_delete'); HOST VARIABLE_NAME VARIABLE_VALUE Expected -localhost Handler_delete 6 OK +localhost Handler_delete 6 OKo # # STATUS_BY_HOST vs. GLOBAL_STATUS # # Special case: No way to isolate pre-existing 'localhost' activity, so # just check global totals = sum(status_by_host). # -SELECT variable_name, h1, h2, h3, delta, host, IF(host=delta,'OK','ERROR') Expected +SELECT variable_name, h1, h2, h3, delta, host, IF(host=delta,'OKp','ERRORp') Expected FROM test.status_results ORDER BY variable_name; variable_name h1 h2 h3 delta host Expected -Handler_delete 6 0 0 6 6 OK -Handler_rollback 6 0 0 6 6 OK +Handler_delete 6 0 0 6 6 OKp +Handler_rollback 6 0 0 6 6 OKp # ================================================================================ # TEST 8: FLUSH STATUS should clear account, host and user status # ================================================================================ diff --git a/mysql-test/suite/perfschema/t/show_aggregate.test b/mysql-test/suite/perfschema/t/show_aggregate.test index a15dea45268..ba1d87d1f72 100644 --- a/mysql-test/suite/perfschema/t/show_aggregate.test +++ b/mysql-test/suite/perfschema/t/show_aggregate.test @@ -14,8 +14,6 @@ --source include/no_protocol.inc --source include/maybe_pool_of_threads.inc ---enable_connect_log - --echo # --echo # ================================================================================ --echo # SETUP @@ -26,10 +24,7 @@ SET @@session.sql_log_bin=OFF; connection default; USE test; -# Clear user, host and account status accumulated from preliminary checks by mtr. ---disable_query_log flush status; ---enable_query_log --echo # --echo # Create results table @@ -135,18 +130,18 @@ USE performance_schema; --echo # Verify expected counts for 'handler_delete' per thread --echo # --replace_column 1 con_1 -SELECT *, IF (variable_value = 1,'OK','ERROR') AS Expected FROM status_by_thread WHERE thread_id = @con1_id AND variable_name IN ('handler_delete', 'handler_rollback'); +SELECT *, IF (variable_value = 1,'OK1','ERROR1') AS Expected FROM status_by_thread WHERE thread_id = @con1_id AND variable_name IN ('handler_delete', 'handler_rollback'); --echo # --replace_column 1 con_2 -SELECT *, IF (variable_value = 2,'OK','ERROR') AS Expected FROM status_by_thread WHERE thread_id = @con2_id AND variable_name IN ('handler_delete', 'handler_rollback'); +SELECT *, IF (variable_value = 2,'OK2','ERROR2') AS Expected FROM status_by_thread WHERE thread_id = @con2_id AND variable_name IN ('handler_delete', 'handler_rollback'); --echo # --replace_column 1 con_3 -SELECT *, IF (variable_value = 3,'OK','ERROR') AS Expected FROM status_by_thread WHERE thread_id = @con3_id AND variable_name IN ('handler_delete', 'handler_rollback'); +SELECT *, IF (variable_value = 3,'OK3','ERROR3') AS Expected FROM status_by_thread WHERE thread_id = @con3_id AND variable_name IN ('handler_delete', 'handler_rollback'); --echo # --echo # STATUS_BY_THREAD vs. GLOBAL_STATUS --echo # -SELECT variable_name, t1, t2, t3, delta, thread, IF(thread=delta,'OK','ERROR') Expected +SELECT variable_name, t1, t2, t3, delta, thread, IF(thread=delta,'OK4','ERROR4') Expected FROM test.status_results ORDER BY variable_name; @@ -154,16 +149,16 @@ ORDER BY variable_name; --echo # ================================================================================ --echo # TEST 2: STATUS_BY_USER: Verify expected status counts per user (1,2,3) --echo # ================================================================================ -SELECT *, IF (variable_value = 1,'OK','ERROR') AS Expected FROM status_by_user WHERE user IN ('user1') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 1,'OK5','ERROR5') AS Expected FROM status_by_user WHERE user IN ('user1') AND variable_name IN ('handler_delete'); --echo # -SELECT *, IF (variable_value = 2,'OK','ERROR') AS Expected FROM status_by_user WHERE user IN ('user2') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 2,'OK6','ERROR6') AS Expected FROM status_by_user WHERE user IN ('user2') AND variable_name IN ('handler_delete'); --echo # -SELECT *, IF (variable_value = 3,'OK','ERROR') AS Expected FROM status_by_user WHERE user IN ('user3') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 3,'OK7','ERROR7') AS Expected FROM status_by_user WHERE user IN ('user3') AND variable_name IN ('handler_delete'); --echo # --echo # STATUS_BY_USER vs. GLOBAL_STATUS --echo # -SELECT variable_name, u1, u2, u3, delta, user, IF(user=delta,'OK','ERROR') Expected +SELECT variable_name, u1, u2, u3, delta, user, IF(user=delta,'OK8','ERROR8') Expected FROM test.status_results ORDER BY variable_name; @@ -171,23 +166,23 @@ ORDER BY variable_name; --echo # ================================================================================ --echo # TEST 3: STATUS_BY_ACCOUNT: Verify expected status counts per user, host (1,2,3) --echo # ================================================================================ -SELECT *, IF (variable_value = 1,'OK','ERROR') AS Expected FROM status_by_account WHERE user IN ('user1') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 1,'OK9','ERROR9') AS Expected FROM status_by_account WHERE user IN ('user1') AND variable_name IN ('handler_delete'); --echo # -SELECT *, IF (variable_value = 2,'OK','ERROR') AS Expected FROM status_by_account WHERE user IN ('user2') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 2,'OKa','ERRORa') AS Expected FROM status_by_account WHERE user IN ('user2') AND variable_name IN ('handler_delete'); --echo # -SELECT *, IF (variable_value = 3,'OK','ERROR') AS Expected FROM status_by_account WHERE user IN ('user3') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 3,'OKb','ERRORb') AS Expected FROM status_by_account WHERE user IN ('user3') AND variable_name IN ('handler_delete'); --echo # --echo # STATUS_BY_ACCOUNT vs. GLOBAL_STATUS --echo # -SELECT variable_name, a1, a2, a3, delta, acct, IF(acct=delta,'OK','ERROR') Expected +SELECT variable_name, a1, a2, a3, delta, acct, IF(acct=delta,'OKc','ERRORc') Expected FROM test.status_results ORDER BY variable_name; --echo # ================================================================================ --echo # TEST 4: STATUS_BY_HOST: Verify expected status counts per host (6) --echo # ================================================================================ -SELECT *, IF (variable_value = 6,'OK','ERROR') AS Expected FROM status_by_host WHERE host IN ('localhost') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 6,'OKd','ERRORd') AS Expected FROM status_by_host WHERE host IN ('localhost') AND variable_name IN ('handler_delete'); --echo # --echo # STATUS_BY_HOST vs. GLOBAL_STATUS @@ -195,7 +190,7 @@ SELECT *, IF (variable_value = 6,'OK','ERROR') AS Expected FROM status_by_host W --echo # Special case: No way to isolate pre-existing 'localhost' activity, so --echo # just check global totals = sum(status_by_host). --echo # -SELECT variable_name, h1, h2, h3, delta, host, IF(host=delta,'OK','ERROR') Expected +SELECT variable_name, h1, h2, h3, delta, host, IF(host=delta,'OKe','ERRORe') Expected FROM test.status_results ORDER BY variable_name; @@ -203,7 +198,6 @@ ORDER BY variable_name; --echo # ================================================================================ --echo # DISCONNECT ALL USERS AND RUN THE TESTS AGAIN. RESULTS SHOULD NOT CHANGE. --echo # ================================================================================ -connection default; disconnect con1; disconnect con2; disconnect con3; @@ -232,16 +226,16 @@ USE performance_schema; --echo # ================================================================================ --echo # TEST 5: STATUS_BY_USER: Verify expected status counts per user (1,2,3) --echo # ================================================================================ -SELECT *, IF (variable_value = 1,'OK','ERROR') AS Expected FROM status_by_user WHERE user IN ('user1') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 1,'OKf','ERRORf') AS Expected FROM status_by_user WHERE user IN ('user1') AND variable_name IN ('handler_delete'); --echo # -SELECT *, IF (variable_value = 2,'OK','ERROR') AS Expected FROM status_by_user WHERE user IN ('user2') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 2,'OKg','ERRORg') AS Expected FROM status_by_user WHERE user IN ('user2') AND variable_name IN ('handler_delete'); --echo # -SELECT *, IF (variable_value = 3,'OK','ERROR') AS Expected FROM status_by_user WHERE user IN ('user3') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 3,'OKh','ERRORh') AS Expected FROM status_by_user WHERE user IN ('user3') AND variable_name IN ('handler_delete'); --echo # --echo # STATUS_BY_USER vs. GLOBAL_STATUS --echo # -SELECT variable_name, u1, u2, u3, delta, user, IF(user=delta,'OK','ERROR') Expected +SELECT variable_name, u1, u2, u3, delta, user, IF(user=delta,'OKi','ERRORi') Expected FROM test.status_results ORDER BY variable_name; @@ -249,23 +243,23 @@ ORDER BY variable_name; --echo # ================================================================================ --echo # TEST 6: STATUS_BY_ACCOUNT: Verify expected status counts per user:host (1,2,3) --echo # ================================================================================ -SELECT *, IF (variable_value = 1,'OK','ERROR') AS Expected FROM status_by_account WHERE user IN ('user1') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 1,'OKj','ERRORj') AS Expected FROM status_by_account WHERE user IN ('user1') AND variable_name IN ('handler_delete'); --echo # -SELECT *, IF (variable_value = 2,'OK','ERROR') AS Expected FROM status_by_account WHERE user IN ('user2') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 2,'OKk','ERRORk') AS Expected FROM status_by_account WHERE user IN ('user2') AND variable_name IN ('handler_delete'); --echo # -SELECT *, IF (variable_value = 3,'OK','ERROR') AS Expected FROM status_by_account WHERE user IN ('user3') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 3,'OKl','ERRORl') AS Expected FROM status_by_account WHERE user IN ('user3') AND variable_name IN ('handler_delete'); --echo # --echo # STATUS_BY_ACCOUNT vs. GLOBAL_STATUS --echo # -SELECT variable_name, a1, a2, a3, delta, acct, IF(acct=delta,'OK','ERROR') Expected +SELECT variable_name, a1, a2, a3, delta, acct, IF(acct=delta,'OKn','ERRORn') Expected FROM test.status_results ORDER BY variable_name; --echo # ================================================================================ --echo # TEST 7: STATUS_BY_HOST: Verify expected status counts per host (6) --echo # ================================================================================ -SELECT *, IF (variable_value = 6,'OK','ERROR') AS Expected FROM status_by_host WHERE host IN ('localhost') AND variable_name IN ('handler_delete'); +SELECT *, IF (variable_value = 6,'OKo','ERRORo') AS Expected FROM status_by_host WHERE host IN ('localhost') AND variable_name IN ('handler_delete'); --echo # --echo # STATUS_BY_HOST vs. GLOBAL_STATUS @@ -273,11 +267,10 @@ SELECT *, IF (variable_value = 6,'OK','ERROR') AS Expected FROM status_by_host W --echo # Special case: No way to isolate pre-existing 'localhost' activity, so --echo # just check global totals = sum(status_by_host). --echo # -SELECT variable_name, h1, h2, h3, delta, host, IF(host=delta,'OK','ERROR') Expected +SELECT variable_name, h1, h2, h3, delta, host, IF(host=delta,'OKp','ERRORp') Expected FROM test.status_results ORDER BY variable_name; - --echo # ================================================================================ --echo # TEST 8: FLUSH STATUS should clear account, host and user status --echo # ================================================================================ @@ -290,7 +283,6 @@ SELECT * FROM status_by_host WHERE host IN ('localhost') AND variable_name IN (' --echo # SELECT * FROM status_by_user WHERE user IN ('user1', 'user2', 'user3') AND variable_name IN ('handler_delete'); - --echo # ================================================================================ --echo # CLEANUP --echo # ================================================================================ From c378efeeb9bdd8d0f184d17493812bda83a5a0fb Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 13 Oct 2023 13:33:36 +0200 Subject: [PATCH 055/158] make perfschema.show_aggregate test more reliable --- .../include/wait_for_pfs_thread_count.inc | 13 +------------ mysql-test/suite/perfschema/r/show_aggregate.result | 6 +++--- mysql-test/suite/perfschema/t/show_aggregate.test | 11 ++++++++--- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/mysql-test/suite/perfschema/include/wait_for_pfs_thread_count.inc b/mysql-test/suite/perfschema/include/wait_for_pfs_thread_count.inc index 2375bdf1cac..49489b495e5 100644 --- a/mysql-test/suite/perfschema/include/wait_for_pfs_thread_count.inc +++ b/mysql-test/suite/perfschema/include/wait_for_pfs_thread_count.inc @@ -4,17 +4,6 @@ # Wait until there is only one session left, this one. -let $wait_condition= - select count(*) = 1 from information_schema.processlist; ---source include/wait_condition.inc - -# Threads are removed from information_schema.processlist -# very soon, but continue to execute in the server, -# before finally be removed from performance_schema.threads. -# Because instrumentation is optional, we use "<=" here. - -let $wait_condition= - select count(*) <= 2 from performance_schema.threads - where `TYPE`='FOREGROUND'; +let $wait_condition= select count(*) = 1 from performance_schema.threads where `type`='foreground'; --source include/wait_condition.inc diff --git a/mysql-test/suite/perfschema/r/show_aggregate.result b/mysql-test/suite/perfschema/r/show_aggregate.result index b5e957f3fc8..3facb3c5f04 100644 --- a/mysql-test/suite/perfschema/r/show_aggregate.result +++ b/mysql-test/suite/perfschema/r/show_aggregate.result @@ -83,9 +83,9 @@ ROLLBACK; connection default; # Get thread ids for each connection. USE performance_schema; -SELECT thread_id INTO @con1_id FROM threads WHERE processlist_user IN ('user1'); -SELECT thread_id INTO @con2_id FROM threads WHERE processlist_user IN ('user2'); -SELECT thread_id INTO @con3_id FROM threads WHERE processlist_user IN ('user3'); +SELECT thread_id INTO @con1_id FROM threads WHERE processlist_user IN ('user1') and processlist_id; +SELECT thread_id INTO @con2_id FROM threads WHERE processlist_user IN ('user2') and processlist_id; +SELECT thread_id INTO @con3_id FROM threads WHERE processlist_user IN ('user3') and processlist_id; #================= # Global results #================= diff --git a/mysql-test/suite/perfschema/t/show_aggregate.test b/mysql-test/suite/perfschema/t/show_aggregate.test index ba1d87d1f72..c84e99f6efc 100644 --- a/mysql-test/suite/perfschema/t/show_aggregate.test +++ b/mysql-test/suite/perfschema/t/show_aggregate.test @@ -13,6 +13,7 @@ --source include/not_embedded.inc --source include/no_protocol.inc --source include/maybe_pool_of_threads.inc +--source include/wait_for_pfs_thread_count.inc --echo # --echo # ================================================================================ @@ -107,9 +108,9 @@ ROLLBACK; connection default; --echo # Get thread ids for each connection. USE performance_schema; -SELECT thread_id INTO @con1_id FROM threads WHERE processlist_user IN ('user1'); -SELECT thread_id INTO @con2_id FROM threads WHERE processlist_user IN ('user2'); -SELECT thread_id INTO @con3_id FROM threads WHERE processlist_user IN ('user3'); +SELECT thread_id INTO @con1_id FROM threads WHERE processlist_user IN ('user1') and processlist_id; +SELECT thread_id INTO @con2_id FROM threads WHERE processlist_user IN ('user2') and processlist_id; +SELECT thread_id INTO @con3_id FROM threads WHERE processlist_user IN ('user3') and processlist_id; --source ../include/show_aggregate.inc @@ -201,6 +202,7 @@ ORDER BY variable_name; disconnect con1; disconnect con2; disconnect con3; + --echo # USE test; --echo # @@ -212,6 +214,9 @@ UPDATE test.status_results h1=0, h2=0, h3=0, host=0, a1=0, a2=0, a3=0, acct=0; +let $wait_condition= select count(*) = 0 from performance_schema.threads where processlist_user like 'user%' and processlist_id; +--source include/wait_condition.inc + #--echo DEBUG #SELECT * FROM test.status_results; --echo # From ea0b1ccd411dbb8c45d4ff453a401a41e68cd30e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 7 Oct 2023 10:49:36 +0200 Subject: [PATCH 056/158] Revert "MDEV-29091: Correct event_name in PFS for wait caused by FOR UPDATE" This reverts commit 03c9a4ef4a0363ba0ffd1843284332fb9c5fd692. The fix is wrong. It was doing this: if the uninitialized wait->m_class has some specific value, then don't initialize it. --- .../r/events_waits_current_MDEV-29091.result | 41 ---- .../r/table_aggregate_hist_2u_2t.result | 120 ++++++++---- .../r/table_aggregate_hist_2u_3t.result | 180 ++++++++++++------ .../r/table_aggregate_hist_4u_2t.result | 120 ++++++++---- .../r/table_aggregate_hist_4u_3t.result | 180 ++++++++++++------ .../t/events_waits_current_MDEV-29091.test | 62 ------ storage/perfschema/pfs.cc | 3 +- 7 files changed, 401 insertions(+), 305 deletions(-) delete mode 100644 mysql-test/suite/perfschema/r/events_waits_current_MDEV-29091.result delete mode 100644 mysql-test/suite/perfschema/t/events_waits_current_MDEV-29091.test diff --git a/mysql-test/suite/perfschema/r/events_waits_current_MDEV-29091.result b/mysql-test/suite/perfschema/r/events_waits_current_MDEV-29091.result deleted file mode 100644 index 8f3a17a0fc5..00000000000 --- a/mysql-test/suite/perfschema/r/events_waits_current_MDEV-29091.result +++ /dev/null @@ -1,41 +0,0 @@ -SET default_storage_engine=InnoDB; -SELECT @save_instrument_enabled := ENABLED -, @save_instrument_timed := TIMED -FROM performance_schema.setup_instruments -WHERE NAME = 'wait/lock/table/sql/handler'; -@save_instrument_enabled := ENABLED @save_instrument_timed := TIMED -YES YES -SELECT @save_consumer_enabled := ENABLED -FROM performance_schema.setup_consumers -WHERE NAME = 'events_waits_current'; -@save_consumer_enabled := ENABLED -YES -UPDATE performance_schema.setup_instruments -SET ENABLED = 'YES', TIMED = 'YES' -WHERE NAME = 'wait/lock/table/sql/handler'; -UPDATE performance_schema.setup_consumers -SET ENABLED = 'YES' -WHERE NAME = 'events_waits_current'; -CREATE TABLE t1 (id1 INT(11), col1 VARCHAR (200)); -INSERT INTO t1 VALUES (1, 'aa'); -INSERT INTO t1 VALUES (2, 'bb'); -connect con1,localhost,root,,test; -connect con2,localhost,root,,test; -connection con1; -START TRANSACTION; -connection con2; -START TRANSACTION; -SELECT id1 FROM t1 WHERE id1=1 FOR UPDATE; -connection default; -SELECT event_name FROM performance_schema.events_waits_current -WHERE event_name LIKE '%wait/lock/table/sql/handler%'; -event_name -UPDATE performance_schema.setup_instruments -SET ENABLED = @save_instrument_enabled, TIMED = @save_instrument_timed -WHERE NAME = 'wait/lock/table/sql/handler'; -UPDATE performance_schema.setup_consumers -SET ENABLED = @save_consumer_enabled -WHERE NAME = 'events_waits_current'; -disconnect con1; -disconnect con2; -DROP TABLE t1; diff --git a/mysql-test/suite/perfschema/r/table_aggregate_hist_2u_2t.result b/mysql-test/suite/perfschema/r/table_aggregate_hist_2u_2t.result index 47f4d7ba346..52ece6d289d 100644 --- a/mysql-test/suite/perfschema/r/table_aggregate_hist_2u_2t.result +++ b/mysql-test/suite/perfschema/r/table_aggregate_hist_2u_2t.result @@ -202,8 +202,10 @@ wait/io/table/sql/handler 23 wait/lock/table/sql/handler 24 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -260,8 +262,10 @@ wait/io/table/sql/handler 23 wait/lock/table/sql/handler 24 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -324,8 +328,10 @@ wait/io/table/sql/handler 23 wait/lock/table/sql/handler 24 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -423,8 +429,10 @@ wait/io/table/sql/handler 23 wait/lock/table/sql/handler 24 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -492,8 +500,10 @@ wait/io/table/sql/handler 23 wait/lock/table/sql/handler 24 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -603,8 +613,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 48 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 41 TABLE test t1 -wait/lock/table/sql/handler 78 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 20 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 28 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -677,8 +689,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 48 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 41 TABLE test t1 -wait/lock/table/sql/handler 78 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 20 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 28 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -800,8 +814,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 48 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 41 TABLE test t1 -wait/lock/table/sql/handler 78 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 20 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 28 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -875,8 +891,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 56 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -947,8 +965,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 56 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1019,8 +1039,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 56 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1088,8 +1110,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 56 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1156,8 +1180,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 56 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1223,8 +1249,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 56 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1289,8 +1317,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 56 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1357,8 +1387,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 56 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1424,8 +1456,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 56 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1491,8 +1525,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 56 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1558,8 +1594,10 @@ wait/io/table/sql/handler 71 wait/lock/table/sql/handler 56 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1625,8 +1663,10 @@ wait/io/table/sql/handler 0 wait/lock/table/sql/handler 0 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 0 0 0 0 0 0 0 diff --git a/mysql-test/suite/perfschema/r/table_aggregate_hist_2u_3t.result b/mysql-test/suite/perfschema/r/table_aggregate_hist_2u_3t.result index 9810d104ed9..b0ea06f4254 100644 --- a/mysql-test/suite/perfschema/r/table_aggregate_hist_2u_3t.result +++ b/mysql-test/suite/perfschema/r/table_aggregate_hist_2u_3t.result @@ -211,9 +211,12 @@ wait/io/table/sql/handler 33 wait/lock/table/sql/handler 36 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 22 TABLE test t2 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 10 TABLE test t2 +wait/lock/table/sql/handler 12 TABLE test t2 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -276,9 +279,12 @@ wait/io/table/sql/handler 33 wait/lock/table/sql/handler 36 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 22 TABLE test t2 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 10 TABLE test t2 +wait/lock/table/sql/handler 12 TABLE test t2 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -347,9 +353,12 @@ wait/io/table/sql/handler 33 wait/lock/table/sql/handler 36 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 22 TABLE test t2 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 10 TABLE test t2 +wait/lock/table/sql/handler 12 TABLE test t2 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -453,9 +462,12 @@ wait/io/table/sql/handler 33 wait/lock/table/sql/handler 36 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 22 TABLE test t2 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 10 TABLE test t2 +wait/lock/table/sql/handler 12 TABLE test t2 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -529,9 +541,12 @@ wait/io/table/sql/handler 33 wait/lock/table/sql/handler 36 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 22 TABLE test t2 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 10 TABLE test t2 +wait/lock/table/sql/handler 12 TABLE test t2 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -647,9 +662,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 72 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 41 TABLE test t1 -wait/lock/table/sql/handler 56 TABLE test t2 -wait/lock/table/sql/handler 78 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 20 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 24 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 28 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -728,9 +746,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 72 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 41 TABLE test t1 -wait/lock/table/sql/handler 56 TABLE test t2 -wait/lock/table/sql/handler 78 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 20 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 24 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 28 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -858,9 +879,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 72 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 41 TABLE test t1 -wait/lock/table/sql/handler 56 TABLE test t2 -wait/lock/table/sql/handler 78 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 20 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 24 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 28 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -940,9 +964,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 84 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 60 TABLE test t2 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 28 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1019,9 +1046,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 84 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 60 TABLE test t2 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 28 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1098,9 +1128,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 84 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 60 TABLE test t2 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 28 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1174,9 +1207,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 84 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 60 TABLE test t2 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 28 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1249,9 +1285,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 84 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 60 TABLE test t2 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 28 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1323,9 +1362,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 84 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 60 TABLE test t2 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 28 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1396,9 +1438,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 84 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 60 TABLE test t2 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 28 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1471,9 +1516,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 84 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 60 TABLE test t2 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 28 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1545,9 +1593,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 84 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 60 TABLE test t2 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 28 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1619,9 +1670,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 84 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 60 TABLE test t2 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 28 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1693,9 +1747,12 @@ wait/io/table/sql/handler 103 wait/lock/table/sql/handler 84 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 60 TABLE test t2 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 28 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 17 11 6 11 2 4 0 @@ -1767,9 +1824,12 @@ wait/io/table/sql/handler 0 wait/lock/table/sql/handler 0 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 45 TABLE test t1 -wait/lock/table/sql/handler 60 TABLE test t2 -wait/lock/table/sql/handler 82 TABLE test t3 +wait/io/table/sql/handler 21 TABLE test t1 +wait/lock/table/sql/handler 24 TABLE test t1 +wait/io/table/sql/handler 32 TABLE test t2 +wait/lock/table/sql/handler 28 TABLE test t2 +wait/io/table/sql/handler 50 TABLE test t3 +wait/lock/table/sql/handler 32 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 0 0 0 0 0 0 0 diff --git a/mysql-test/suite/perfschema/r/table_aggregate_hist_4u_2t.result b/mysql-test/suite/perfschema/r/table_aggregate_hist_4u_2t.result index 367a8a089eb..0a6dea739e4 100644 --- a/mysql-test/suite/perfschema/r/table_aggregate_hist_4u_2t.result +++ b/mysql-test/suite/perfschema/r/table_aggregate_hist_4u_2t.result @@ -202,8 +202,10 @@ wait/io/table/sql/handler 23 wait/lock/table/sql/handler 24 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -260,8 +262,10 @@ wait/io/table/sql/handler 23 wait/lock/table/sql/handler 24 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -324,8 +328,10 @@ wait/io/table/sql/handler 23 wait/lock/table/sql/handler 24 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -423,8 +429,10 @@ wait/io/table/sql/handler 58 wait/lock/table/sql/handler 48 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 38 TABLE test t1 -wait/lock/table/sql/handler 68 TABLE test t3 +wait/io/table/sql/handler 18 TABLE test t1 +wait/lock/table/sql/handler 20 TABLE test t1 +wait/io/table/sql/handler 40 TABLE test t3 +wait/lock/table/sql/handler 28 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 14 9 5 9 2 3 0 @@ -492,8 +500,10 @@ wait/io/table/sql/handler 58 wait/lock/table/sql/handler 48 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 38 TABLE test t1 -wait/lock/table/sql/handler 68 TABLE test t3 +wait/io/table/sql/handler 18 TABLE test t1 +wait/lock/table/sql/handler 20 TABLE test t1 +wait/io/table/sql/handler 40 TABLE test t3 +wait/lock/table/sql/handler 28 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 14 9 5 9 2 3 0 @@ -603,8 +613,10 @@ wait/io/table/sql/handler 106 wait/lock/table/sql/handler 72 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 61 TABLE test t1 -wait/lock/table/sql/handler 117 TABLE test t3 +wait/io/table/sql/handler 31 TABLE test t1 +wait/lock/table/sql/handler 30 TABLE test t1 +wait/io/table/sql/handler 75 TABLE test t3 +wait/lock/table/sql/handler 42 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 25 16 9 16 3 6 0 @@ -677,8 +689,10 @@ wait/io/table/sql/handler 106 wait/lock/table/sql/handler 72 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 61 TABLE test t1 -wait/lock/table/sql/handler 117 TABLE test t3 +wait/io/table/sql/handler 31 TABLE test t1 +wait/lock/table/sql/handler 30 TABLE test t1 +wait/io/table/sql/handler 75 TABLE test t3 +wait/lock/table/sql/handler 42 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 25 16 9 16 3 6 0 @@ -800,8 +814,10 @@ wait/io/table/sql/handler 167 wait/lock/table/sql/handler 96 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 87 TABLE test t1 -wait/lock/table/sql/handler 176 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 40 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 56 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -875,8 +891,10 @@ wait/io/table/sql/handler 167 wait/lock/table/sql/handler 104 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -947,8 +965,10 @@ wait/io/table/sql/handler 167 wait/lock/table/sql/handler 104 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1019,8 +1039,10 @@ wait/io/table/sql/handler 167 wait/lock/table/sql/handler 104 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1088,8 +1110,10 @@ wait/io/table/sql/handler 167 wait/lock/table/sql/handler 104 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1156,8 +1180,10 @@ wait/io/table/sql/handler 167 wait/lock/table/sql/handler 104 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1223,8 +1249,10 @@ wait/io/table/sql/handler 167 wait/lock/table/sql/handler 104 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1289,8 +1317,10 @@ wait/io/table/sql/handler 167 wait/lock/table/sql/handler 104 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1357,8 +1387,10 @@ wait/io/table/sql/handler 167 wait/lock/table/sql/handler 104 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1424,8 +1456,10 @@ wait/io/table/sql/handler 167 wait/lock/table/sql/handler 104 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1491,8 +1525,10 @@ wait/io/table/sql/handler 167 wait/lock/table/sql/handler 104 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1558,8 +1594,10 @@ wait/io/table/sql/handler 167 wait/lock/table/sql/handler 104 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1625,8 +1663,10 @@ wait/io/table/sql/handler 0 wait/lock/table/sql/handler 0 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 0 0 0 0 0 0 0 diff --git a/mysql-test/suite/perfschema/r/table_aggregate_hist_4u_3t.result b/mysql-test/suite/perfschema/r/table_aggregate_hist_4u_3t.result index ed1ac9d979b..c2eda2b8f23 100644 --- a/mysql-test/suite/perfschema/r/table_aggregate_hist_4u_3t.result +++ b/mysql-test/suite/perfschema/r/table_aggregate_hist_4u_3t.result @@ -211,9 +211,12 @@ wait/io/table/sql/handler 33 wait/lock/table/sql/handler 36 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 22 TABLE test t2 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 10 TABLE test t2 +wait/lock/table/sql/handler 12 TABLE test t2 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -276,9 +279,12 @@ wait/io/table/sql/handler 33 wait/lock/table/sql/handler 36 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 22 TABLE test t2 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 10 TABLE test t2 +wait/lock/table/sql/handler 12 TABLE test t2 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -347,9 +353,12 @@ wait/io/table/sql/handler 33 wait/lock/table/sql/handler 36 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 18 TABLE test t1 -wait/lock/table/sql/handler 22 TABLE test t2 -wait/lock/table/sql/handler 29 TABLE test t3 +wait/io/table/sql/handler 8 TABLE test t1 +wait/lock/table/sql/handler 10 TABLE test t1 +wait/io/table/sql/handler 10 TABLE test t2 +wait/lock/table/sql/handler 12 TABLE test t2 +wait/io/table/sql/handler 15 TABLE test t3 +wait/lock/table/sql/handler 14 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 6 4 2 4 1 1 0 @@ -453,9 +462,12 @@ wait/io/table/sql/handler 84 wait/lock/table/sql/handler 72 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 38 TABLE test t1 -wait/lock/table/sql/handler 50 TABLE test t2 -wait/lock/table/sql/handler 68 TABLE test t3 +wait/io/table/sql/handler 18 TABLE test t1 +wait/lock/table/sql/handler 20 TABLE test t1 +wait/io/table/sql/handler 26 TABLE test t2 +wait/lock/table/sql/handler 24 TABLE test t2 +wait/io/table/sql/handler 40 TABLE test t3 +wait/lock/table/sql/handler 28 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 14 9 5 9 2 3 0 @@ -529,9 +541,12 @@ wait/io/table/sql/handler 84 wait/lock/table/sql/handler 72 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 38 TABLE test t1 -wait/lock/table/sql/handler 50 TABLE test t2 -wait/lock/table/sql/handler 68 TABLE test t3 +wait/io/table/sql/handler 18 TABLE test t1 +wait/lock/table/sql/handler 20 TABLE test t1 +wait/io/table/sql/handler 26 TABLE test t2 +wait/lock/table/sql/handler 24 TABLE test t2 +wait/io/table/sql/handler 40 TABLE test t3 +wait/lock/table/sql/handler 28 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 14 9 5 9 2 3 0 @@ -647,9 +662,12 @@ wait/io/table/sql/handler 154 wait/lock/table/sql/handler 108 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 61 TABLE test t1 -wait/lock/table/sql/handler 84 TABLE test t2 -wait/lock/table/sql/handler 117 TABLE test t3 +wait/io/table/sql/handler 31 TABLE test t1 +wait/lock/table/sql/handler 30 TABLE test t1 +wait/io/table/sql/handler 48 TABLE test t2 +wait/lock/table/sql/handler 36 TABLE test t2 +wait/io/table/sql/handler 75 TABLE test t3 +wait/lock/table/sql/handler 42 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 25 16 9 16 3 6 0 @@ -728,9 +746,12 @@ wait/io/table/sql/handler 154 wait/lock/table/sql/handler 108 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 61 TABLE test t1 -wait/lock/table/sql/handler 84 TABLE test t2 -wait/lock/table/sql/handler 117 TABLE test t3 +wait/io/table/sql/handler 31 TABLE test t1 +wait/lock/table/sql/handler 30 TABLE test t1 +wait/io/table/sql/handler 48 TABLE test t2 +wait/lock/table/sql/handler 36 TABLE test t2 +wait/io/table/sql/handler 75 TABLE test t3 +wait/lock/table/sql/handler 42 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 25 16 9 16 3 6 0 @@ -858,9 +879,12 @@ wait/io/table/sql/handler 243 wait/lock/table/sql/handler 144 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 87 TABLE test t1 -wait/lock/table/sql/handler 124 TABLE test t2 -wait/lock/table/sql/handler 176 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 40 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 48 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 56 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -940,9 +964,12 @@ wait/io/table/sql/handler 243 wait/lock/table/sql/handler 156 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 128 TABLE test t2 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 52 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1019,9 +1046,12 @@ wait/io/table/sql/handler 243 wait/lock/table/sql/handler 156 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 128 TABLE test t2 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 52 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1098,9 +1128,12 @@ wait/io/table/sql/handler 243 wait/lock/table/sql/handler 156 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 128 TABLE test t2 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 52 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1174,9 +1207,12 @@ wait/io/table/sql/handler 243 wait/lock/table/sql/handler 156 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 128 TABLE test t2 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 52 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1249,9 +1285,12 @@ wait/io/table/sql/handler 243 wait/lock/table/sql/handler 156 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 128 TABLE test t2 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 52 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1323,9 +1362,12 @@ wait/io/table/sql/handler 243 wait/lock/table/sql/handler 156 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 128 TABLE test t2 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 52 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1396,9 +1438,12 @@ wait/io/table/sql/handler 243 wait/lock/table/sql/handler 156 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 128 TABLE test t2 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 52 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1471,9 +1516,12 @@ wait/io/table/sql/handler 243 wait/lock/table/sql/handler 156 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 128 TABLE test t2 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 52 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1545,9 +1593,12 @@ wait/io/table/sql/handler 243 wait/lock/table/sql/handler 156 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 128 TABLE test t2 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 52 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1619,9 +1670,12 @@ wait/io/table/sql/handler 243 wait/lock/table/sql/handler 156 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 128 TABLE test t2 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 52 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1693,9 +1747,12 @@ wait/io/table/sql/handler 243 wait/lock/table/sql/handler 156 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 128 TABLE test t2 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 52 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 39 25 14 25 4 10 0 @@ -1767,9 +1824,12 @@ wait/io/table/sql/handler 0 wait/lock/table/sql/handler 0 execute dump_waits_history; event_name count(event_name) object_type object_schema object_name -wait/lock/table/sql/handler 91 TABLE test t1 -wait/lock/table/sql/handler 128 TABLE test t2 -wait/lock/table/sql/handler 180 TABLE test t3 +wait/io/table/sql/handler 47 TABLE test t1 +wait/lock/table/sql/handler 44 TABLE test t1 +wait/io/table/sql/handler 76 TABLE test t2 +wait/lock/table/sql/handler 52 TABLE test t2 +wait/io/table/sql/handler 120 TABLE test t3 +wait/lock/table/sql/handler 60 TABLE test t3 execute dump_waits_index_io; object_type object_schema object_name index_name count_star count_read count_write count_fetch count_insert count_update count_delete TABLE test t1 NULL 0 0 0 0 0 0 0 diff --git a/mysql-test/suite/perfschema/t/events_waits_current_MDEV-29091.test b/mysql-test/suite/perfschema/t/events_waits_current_MDEV-29091.test deleted file mode 100644 index d9330ee5a9d..00000000000 --- a/mysql-test/suite/perfschema/t/events_waits_current_MDEV-29091.test +++ /dev/null @@ -1,62 +0,0 @@ -# -# proper event name wait/lock/table/sql/handler recorded in -# PERFORMANCE_SCHEMA.EVENTS_WAITS_CURRENT. Before this fix, it was -# labeled as wait/io/table/sql/handler. -# - ---source include/have_innodb.inc ---source include/have_perfschema.inc ---source include/not_embedded.inc - -SET default_storage_engine=InnoDB; - -SELECT @save_instrument_enabled := ENABLED -, @save_instrument_timed := TIMED -FROM performance_schema.setup_instruments -WHERE NAME = 'wait/lock/table/sql/handler'; - -SELECT @save_consumer_enabled := ENABLED -FROM performance_schema.setup_consumers -WHERE NAME = 'events_waits_current'; - -UPDATE performance_schema.setup_instruments -SET ENABLED = 'YES', TIMED = 'YES' -WHERE NAME = 'wait/lock/table/sql/handler'; - -UPDATE performance_schema.setup_consumers -SET ENABLED = 'YES' -WHERE NAME = 'events_waits_current'; - -CREATE TABLE t1 (id1 INT(11), col1 VARCHAR (200)); -INSERT INTO t1 VALUES (1, 'aa'); -INSERT INTO t1 VALUES (2, 'bb'); - -connect (con1,localhost,root,,test); -connect (con2,localhost,root,,test); - -connection con1; -START TRANSACTION; -let $wait_condition= - SELECT id1 FROM t1 WHERE id1=1 FOR UPDATE; ---source include/wait_condition.inc - -connection con2; -START TRANSACTION; -send SELECT id1 FROM t1 WHERE id1=1 FOR UPDATE; - -connection default; -SELECT event_name FROM performance_schema.events_waits_current -WHERE event_name LIKE '%wait/lock/table/sql/handler%'; - -# clean up -UPDATE performance_schema.setup_instruments -SET ENABLED = @save_instrument_enabled, TIMED = @save_instrument_timed -WHERE NAME = 'wait/lock/table/sql/handler'; - -UPDATE performance_schema.setup_consumers -SET ENABLED = @save_consumer_enabled -WHERE NAME = 'events_waits_current'; - -disconnect con1; -disconnect con2; -DROP TABLE t1; diff --git a/storage/perfschema/pfs.cc b/storage/perfschema/pfs.cc index 8b3a159f7a2..1373f9dd43d 100644 --- a/storage/perfschema/pfs.cc +++ b/storage/perfschema/pfs.cc @@ -3068,8 +3068,7 @@ pfs_start_table_io_wait_v1(PSI_table_locker_state *state, PFS_table_share *share= pfs_table->m_share; wait->m_thread_internal_id= pfs_thread->m_thread_internal_id; - if (wait->m_class == NULL || wait->m_class->m_type != PFS_CLASS_TABLE_LOCK) - wait->m_class= &global_table_io_class; + wait->m_class= &global_table_io_class; wait->m_timer_start= timer_start; wait->m_timer_end= 0; wait->m_object_instance_addr= pfs_table->m_identity; From c8866892610ae3441a0abecadff548bace8be97d Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Fri, 13 Oct 2023 12:17:25 +0300 Subject: [PATCH 057/158] MDEV-32320: Server crashes at TABLE::add_tmp_key The code inside Item_subselect::fix_fields() could fail to check that left expression had an Item_row, like this: (('x', 1.0) ,1) IN (SELECT 'x', 1.23 FROM ... UNION ...) In order to hit the failure, the first SELECT of the subquery had to be a degenerate no-tables select. In this case, execution will not enter into Item_in_subselect::create_row_in_to_exists_cond() and will not check if left_expr is composed of scalars. But the subquery is a UNION so as a whole it is not degenerate. We try to create an expression cache for the subquery. We create a temp.table from left_expr columns. No field is created for the Item_row. Then, we crash when trying to add an index over a non-existent field. Fixed by moving the left_expr cardinality check to a point in check_and_do_in_subquery_rewrites() which gets executed for all cases. It's better to make the check early so we don't have to care about subquery rewrite code hitting Item_row in left_expr. --- mysql-test/main/subselect4.result | 30 +++++++++++++++++++++++++++ mysql-test/main/subselect4.test | 34 +++++++++++++++++++++++++++++++ sql/item_subselect.cc | 7 ------- sql/opt_subselect.cc | 8 ++++++++ 4 files changed, 72 insertions(+), 7 deletions(-) diff --git a/mysql-test/main/subselect4.result b/mysql-test/main/subselect4.result index 10fe6ac1722..9f435146e0b 100644 --- a/mysql-test/main/subselect4.result +++ b/mysql-test/main/subselect4.result @@ -3183,4 +3183,34 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY eq_ref distinct_key distinct_key 4 func 1 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 100 drop table t0, t1, t2; +# +# MDEV-32320: Server crashes at TABLE::add_tmp_key +# +select +( ( 'x' , 1.000000 ) , 1 ) +IN +(SELECT +'x' , 'x' + WHERE ( 'x' ) +UNION +SELECT 1 , 'x' + HAVING 1 != 1 +) as T; +ERROR 21000: Operand should contain 2 column(s) +SELECT +EXISTS ( +WITH x ( x ) AS ( SELECT 1 ) +SELECT NULL +WHERE ( 1 , 1 ) = +(SELECT +1 , ( ( x , 1.000000 ) , 1 ) +IN +(SELECT 'x' , 'x' WHERE ( ( 'x' ) ) +UNION +SELECT 1 , x HAVING 1 != 1 +) +FROM x +) +); +ERROR 21000: Operand should contain 2 column(s) # End of 10.4 tests diff --git a/mysql-test/main/subselect4.test b/mysql-test/main/subselect4.test index 903374461d2..23611e4ec0d 100644 --- a/mysql-test/main/subselect4.test +++ b/mysql-test/main/subselect4.test @@ -2596,4 +2596,38 @@ select * from t1 where t1.a in (select t2.a from t2 order by t2.b); drop table t0, t1, t2; +--echo # +--echo # MDEV-32320: Server crashes at TABLE::add_tmp_key +--echo # + +--error ER_OPERAND_COLUMNS +select + ( ( 'x' , 1.000000 ) , 1 ) +IN +(SELECT + 'x' , 'x' + WHERE ( 'x' ) + UNION + SELECT 1 , 'x' + HAVING 1 != 1 +) as T; + +--error ER_OPERAND_COLUMNS +SELECT + EXISTS ( + WITH x ( x ) AS ( SELECT 1 ) + SELECT NULL + WHERE ( 1 , 1 ) = + (SELECT + 1 , ( ( x , 1.000000 ) , 1 ) + IN + (SELECT 'x' , 'x' WHERE ( ( 'x' ) ) + UNION + SELECT 1 , x HAVING 1 != 1 + ) + FROM x + ) + ); + + --echo # End of 10.4 tests diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index ae0ab27ec31..975c9922153 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2492,10 +2492,6 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, (select_lex->ref_pointer_array[i]->type() == REF_ITEM && ((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() == Item_ref::OUTER_REF)); - if (select_lex->ref_pointer_array[i]-> - check_cols(left_expr->element_index(i)->cols())) - DBUG_RETURN(true); - Item *item_eq= new (thd->mem_root) Item_func_eq(thd, new (thd->mem_root) @@ -2562,9 +2558,6 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, (select_lex->ref_pointer_array[i]->type() == REF_ITEM && ((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() == Item_ref::OUTER_REF)); - if (select_lex->ref_pointer_array[i]-> - check_cols(left_expr->element_index(i)->cols())) - DBUG_RETURN(true); item= new (thd->mem_root) Item_func_eq(thd, new (thd->mem_root) diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index db7a4c0fc14..9c2af2d8464 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -660,6 +660,14 @@ int check_and_do_in_subquery_rewrites(JOIN *join) my_error(ER_OPERAND_COLUMNS, MYF(0), in_subs->left_expr->cols()); DBUG_RETURN(-1); } + + uint cols_num= in_subs->left_expr->cols(); + for (uint i= 0; i < cols_num; i++) + { + if (select_lex->ref_pointer_array[i]-> + check_cols(in_subs->left_expr->element_index(i)->cols())) + DBUG_RETURN(-1); + } } DBUG_PRINT("info", ("Checking if subq can be converted to semi-join")); From e8c9cdc2f85d3d5c096f8af48216488fd304bc07 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 11 Oct 2023 19:02:25 +0300 Subject: [PATCH 058/158] MDEV-32301: Server crashes at Arg_comparator::compare_row In Item_bool_rowready_func2::build_clone(): if we're setting clone->cmp.comparators=0 also set const_item_cache=0 as the Item is currently in a state where one cannot compute it. --- mysql-test/main/derived_cond_pushdown.result | 11 +++++++++++ mysql-test/main/derived_cond_pushdown.test | 10 ++++++++++ sql/item_cmpfunc.h | 1 + 3 files changed, 22 insertions(+) diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 1e23b1aa3a9..def5f32b2ca 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -18442,4 +18442,15 @@ a SUBQ 4 1=11373 5 1=11612 drop table t1,t2,t3; +# +# MDEV-32301: Server crashes at Arg_comparator::compare_row +# +SELECT * FROM ( SELECT 1 x ) ss +WHERE +x AND x OR ( ( x , x , x ) <= ( x , x , x ) ) +GROUP BY +x +HAVING ( ( x = 1 ) ) ; +x +1 # End of 10.4 tests diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index 05032fb94a4..1af421e09e4 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -4013,4 +4013,14 @@ eval $q; drop table t1,t2,t3; +--echo # +--echo # MDEV-32301: Server crashes at Arg_comparator::compare_row +--echo # +SELECT * FROM ( SELECT 1 x ) ss +WHERE + x AND x OR ( ( x , x , x ) <= ( x , x , x ) ) +GROUP BY + x +HAVING ( ( x = 1 ) ) ; + --echo # End of 10.4 tests diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 6706c2edf40..37384061d9c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -559,6 +559,7 @@ public: if (clone) { clone->cmp.comparators= 0; + clone->const_item_cache= 0; } return clone; } From 208ed0d8c6c288554a3658dde1ba57317208f869 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Thu, 12 Oct 2023 14:19:08 +0300 Subject: [PATCH 059/158] MDEV-32324: Server crashes inside filesort at my_decimal::to_binary A subquery in form "(SELECT not_null_value LIMIT 1 OFFSET 1)" will produce no rows which will translate into scalar SQL NULL value. The code in Item_singlerow_subselect::fix_length_and_dec() failed to take the LIMIT/OFFSET clause into account and used to set item_subselect->maybe_null=0, despite that SQL NULL will be produced. If such subselect was used in ORDER BY, this would cause a crash in filesort() code when it would get a NULL value for a not-nullable item. also made subselect_engine::no_tables() const function. --- mysql-test/main/order_by.result | 6 +++++ mysql-test/main/order_by.test | 5 ++++ sql/item_subselect.cc | 46 +++++++++++++++++++++++---------- sql/item_subselect.h | 17 +++++++----- 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result index 19169282fc7..2aab272eca2 100644 --- a/mysql-test/main/order_by.result +++ b/mysql-test/main/order_by.result @@ -3700,4 +3700,10 @@ Note 1003 select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` A set histogram_size=@tmp_h, histogram_type=@tmp_ht, use_stat_tables=@tmp_u, optimizer_use_condition_selectivity=@tmp_o; drop table t1,t2,t3,t4; +# +# MDEV-32324: Server crashes inside filesort at my_decimal::to_binary +# +SELECT 1.000000 two UNION SELECT 1 ORDER BY ( SELECT two LIMIT 1 OFFSET 1 ) ; +two +1.000000 # End of 10.4 tests diff --git a/mysql-test/main/order_by.test b/mysql-test/main/order_by.test index 8aebc509ca7..9b63cbf64f0 100644 --- a/mysql-test/main/order_by.test +++ b/mysql-test/main/order_by.test @@ -2447,4 +2447,9 @@ set histogram_size=@tmp_h, histogram_type=@tmp_ht, use_stat_tables=@tmp_u, drop table t1,t2,t3,t4; +--echo # +--echo # MDEV-32324: Server crashes inside filesort at my_decimal::to_binary +--echo # +SELECT 1.000000 two UNION SELECT 1 ORDER BY ( SELECT two LIMIT 1 OFFSET 1 ) ; + --echo # End of 10.4 tests diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 975c9922153..6400bf518ce 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1240,18 +1240,10 @@ bool Item_singlerow_subselect::fix_length_and_dec() } unsigned_flag= value->unsigned_flag; /* - If the subquery has no tables (1) and is not a UNION (2), like: - - (SELECT subq_value) - + If the subquery always returns a row, like "(SELECT subq_value)" then its NULLability is the same as subq_value's NULLability. - - (1): A subquery that uses a table will return NULL when the table is empty. - (2): A UNION subquery will return NULL if it produces a "Subquery returns - more than one row" error. */ - if (engine->no_tables() && - engine->engine_type() != subselect_engine::UNION_ENGINE) + if (engine->always_returns_one_row()) maybe_null= engine->may_be_null(); else { @@ -1262,6 +1254,32 @@ bool Item_singlerow_subselect::fix_length_and_dec() } + +/* + @brief + Check if we can guarantee that this engine will always produce exactly one + row. + + @detail + Check if the subquery is just + + (SELECT value) + + Then we can guarantee we always return one row. + Selecting from tables may produce more than one row. + HAVING, WHERE or ORDER BY/LIMIT clauses may cause no rows to be produced. +*/ + +bool subselect_single_select_engine::always_returns_one_row() const +{ + st_select_lex *params= select_lex->master_unit()->global_parameters(); + return no_tables() && + !params->select_limit && + !params->offset_limit && + !select_lex->where && + !select_lex->having; +} + /** Add an expression cache for this subquery if it is needed @@ -4705,7 +4723,7 @@ subselect_uniquesubquery_engine::change_result(Item_subselect *si, @retval FALSE there are some tables in subquery */ -bool subselect_single_select_engine::no_tables() +bool subselect_single_select_engine::no_tables() const { return(select_lex->table_list.elements == 0); } @@ -4735,7 +4753,7 @@ bool subselect_single_select_engine::may_be_null() @retval FALSE there are some tables in subquery */ -bool subselect_union_engine::no_tables() +bool subselect_union_engine::no_tables() const { for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) { @@ -4755,7 +4773,7 @@ bool subselect_union_engine::no_tables() FALSE there are some tables in subquery */ -bool subselect_uniquesubquery_engine::no_tables() +bool subselect_uniquesubquery_engine::no_tables() const { /* returning value is correct, but this method should never be called */ DBUG_ASSERT(FALSE); @@ -5750,7 +5768,7 @@ void subselect_hash_sj_engine::exclude() DBUG_ASSERT(FALSE); } -bool subselect_hash_sj_engine::no_tables() +bool subselect_hash_sj_engine::no_tables() const { DBUG_ASSERT(FALSE); return FALSE; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 86c032dd1ce..2bdd2252dc3 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -867,7 +867,11 @@ public: virtual bool change_result(Item_subselect *si, select_result_interceptor *result, bool temp= FALSE)= 0; - virtual bool no_tables()= 0; + virtual bool no_tables() const = 0; + /* + Return true we can guarantee that the subquery will always return one row. + */ + virtual bool always_returns_one_row() const { return false; } virtual bool is_executed() const { return FALSE; } /* Check if subquery produced any rows during last query execution */ virtual bool no_rows() = 0; @@ -900,7 +904,8 @@ public: bool change_result(Item_subselect *si, select_result_interceptor *result, bool temp); - bool no_tables(); + bool no_tables() const override; + bool always_returns_one_row() const override; bool may_be_null(); bool is_executed() const { return executed; } bool no_rows(); @@ -937,7 +942,7 @@ public: bool change_result(Item_subselect *si, select_result_interceptor *result, bool temp= FALSE); - bool no_tables(); + bool no_tables() const override; bool is_executed() const; void force_reexecution(); bool no_rows(); @@ -995,7 +1000,7 @@ public: bool change_result(Item_subselect *si, select_result_interceptor *result, bool temp= FALSE); - bool no_tables(); + bool no_tables() const override; int index_lookup(); /* TIMOUR: this method needs refactoring. */ int scan_table(); bool copy_ref_key(bool skip_constants); @@ -1140,7 +1145,7 @@ public: bool change_result(Item_subselect *si, select_result_interceptor *result, bool temp= FALSE); - bool no_tables();//=>base class + bool no_tables() const override;//=>base class protected: /* The engine used to compute the IN predicate. */ @@ -1416,7 +1421,7 @@ public: select_result_interceptor*, bool temp= FALSE) { DBUG_ASSERT(FALSE); return false; } - bool no_tables() { return false; } + bool no_tables() const override { return false; } bool no_rows() { /* From 0ca699bff77ac69bb28c114e647c1ad78dffa8af Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Mon, 16 Oct 2023 18:47:24 +0300 Subject: [PATCH 060/158] Revert accidentally pushed: commit e8c9cdc2f85d3d5c096f8af48216488fd304bc07 Author: Sergei Petrunia Date: Wed Oct 11 19:02:25 2023 +0300 MDEV-32301: Server crashes at Arg_comparator::compare_row In Item_bool_rowready_func2::build_clone(): if we're setting clone->cmp.comparators=0 also set const_item_cache=0 as the Item is currently in a state where one cannot compute it. --- mysql-test/main/derived_cond_pushdown.result | 11 ----------- mysql-test/main/derived_cond_pushdown.test | 10 ---------- sql/item_cmpfunc.h | 1 - 3 files changed, 22 deletions(-) diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index def5f32b2ca..1e23b1aa3a9 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -18442,15 +18442,4 @@ a SUBQ 4 1=11373 5 1=11612 drop table t1,t2,t3; -# -# MDEV-32301: Server crashes at Arg_comparator::compare_row -# -SELECT * FROM ( SELECT 1 x ) ss -WHERE -x AND x OR ( ( x , x , x ) <= ( x , x , x ) ) -GROUP BY -x -HAVING ( ( x = 1 ) ) ; -x -1 # End of 10.4 tests diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index 1af421e09e4..05032fb94a4 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -4013,14 +4013,4 @@ eval $q; drop table t1,t2,t3; ---echo # ---echo # MDEV-32301: Server crashes at Arg_comparator::compare_row ---echo # -SELECT * FROM ( SELECT 1 x ) ss -WHERE - x AND x OR ( ( x , x , x ) <= ( x , x , x ) ) -GROUP BY - x -HAVING ( ( x = 1 ) ) ; - --echo # End of 10.4 tests diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 37384061d9c..6706c2edf40 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -559,7 +559,6 @@ public: if (clone) { clone->cmp.comparators= 0; - clone->const_item_cache= 0; } return clone; } From b1c8ea83a5b35dcdcc0c7fd940f1c977c6e59f09 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 11 Oct 2023 22:46:36 -0700 Subject: [PATCH 061/158] MDEV-32064 Crash when searching for the best split of derived table This bug could affect queries with IN subqueries in WHERE clause and using derived tables to which split optimization potentially could be applied. When looking for the best split of a splittable derived table T any key access from a semi-join materialized table used for lookups S to table T must be excluded from consideration because in the current implementation of such tables as S the values from its records cannot be used to access other tables. Approved by Oleksandr Byelkin --- mysql-test/main/derived_cond_pushdown.result | 116 +++++++++++++++++++ mysql-test/main/derived_cond_pushdown.test | 88 ++++++++++++++ sql/opt_split.cc | 3 +- 3 files changed, 206 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 1e23b1aa3a9..05137f7d492 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -18442,4 +18442,120 @@ a SUBQ 4 1=11373 5 1=11612 drop table t1,t2,t3; +# +# MDEV-32064: usage of splittable derived table in query +# with IN subquery in WHERE +# +CREATE TABLE t1 ( +id int unsigned NOT NULL, +valint1 int unsigned, +valdouble double, +valdate datetime, +PRIMARY KEY (id), +KEY (valint1), +KEY (valint1,valdate) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES +(1,3289763,1,'2021-02-09 18:31:35'),(2,3289750,1,'2021-02-09 18:31:35'), +(3,3289780,1173,'2021-02-09 18:31:35'),(4,3289762,2,'2021-02-09 18:31:36'), +(5,3289774,2334,'2021-02-09 18:31:36'),(6,3289739,1934,'2021-02-09 18:31:36'), +(7,3289761,1,'2021-02-09 18:31:37'),(8,3289763,1,'2021-02-10 11:05:19'), +(9,3289750,1,'2021-02-10 11:05:19'),(10,3289780,0,'2021-02-10 11:05:35'), +(11,3289762,2,'2021-02-10 11:05:47'),(12,3289774,429,'2021-02-10 11:05:47'), +(13,3289739,1958,'2021-02-10 11:06:00'),(14,3289761,1,'2021-02-10 11:06:08'), +(15,3289957,0,'2021-02-10 13:04:44'),(16,3289988,1993,'2021-02-10 13:04:45'), +(17,3289951,1896,'2021-02-10 13:04:59'),(18,3289957,1994,'2021-02-10 13:07:40'), +(19,3289988,5,'2021-02-10 13:07:40'),(20,3289951,1897,'2021-02-10 13:07:40'), +(21,3289594,0,'2021-02-11 14:19:38'),(22,3289642,0,'2021-02-11 14:19:38'), +(23,3289626,2150,'2021-02-11 14:19:38'),(24,3289562,0,'2021-02-11 14:19:39'), +(25,3289593,1046,'2021-02-11 14:19:39'),(26,3289496,1,'2021-02-11 14:19:45'), +(27,3289475,1074,'2021-02-11 14:19:50'),(28,3289658,1155,'2021-02-11 14:19:56'), +(29,3289595,0,'2021-02-11 14:20:01'),(30,3290334,903,'2021-02-11 16:22:44'), +(31,3290284,479,'2021-02-11 16:23:00'),(32,3290327,236,'2021-02-11 16:23:00'), +(33,3290854,0,'2021-02-15 17:29:59'),(34,3290824,0,'2021-02-15 17:30:13'), +(35,3290875,0,'2021-02-15 17:30:14'),(36,3290897,2,'2021-02-15 17:30:19'), +(37,3290800,0,'2021-02-15 17:30:24'),(38,3290822,0,'2021-02-15 17:30:25'), +(39,3290901,2667,'2021-02-15 17:30:30'),(40,3290835,0,'2021-02-15 17:30:36'), +(41,3290875,0,'2021-02-15 17:35:33'),(42,3290824,1330,'2021-02-15 17:35:39'), +(43,3290854,769,'2021-02-15 17:35:44'),(44,3290897,2,'2021-02-15 17:35:50'), +(45,3290822,748,'2021-02-15 17:35:50'),(46,3290800,1007,'2021-02-15 17:35:56'), +(47,3290901,7018,'2021-02-15 17:35:56'),(48,3290835,779,'2021-02-15 17:36:17'), +(49,3290824,1329,'2021-02-15 17:40:30'),(50,3290875,764,'2021-02-15 17:40:31'), +(51,3290854,763,'2021-02-15 17:40:36'),(52,3290897,2347,'2021-02-15 17:40:47'), +(53,3290822,1,'2021-02-15 17:41:01'),(54,3290800,1018,'2021-02-15 17:41:07'), +(55,3290901,3936,'2021-02-15 17:41:08'),(56,3290835,784,'2021-02-15 17:41:24'), +(57,3290824,1313,'2021-02-15 17:44:47'),(58,3290875,758,'2021-02-15 17:44:48'), +(59,3290854,767,'2021-02-15 17:44:48'),(60,3290897,2438,'2021-02-15 17:44:48'), +(61,3290822,738,'2021-02-15 17:44:49'),(62,3290800,1003,'2021-02-15 17:44:54'), +(63,3290901,4686,'2021-02-15 17:44:55'),(64,3290835,778,'2021-02-15 17:45:13'), +(65,3290824,1303,'2021-02-15 17:51:16'),(66,3290875,753,'2021-02-15 17:51:16'), +(67,3290854,766,'2021-02-15 17:51:22'),(68,3290897,1,'2021-02-15 17:51:22'), +(69,3290822,743,'2021-02-15 17:51:28'),(70,3290901,5718,'2021-02-15 17:51:33'), +(71,3290800,1018,'2021-02-15 17:51:34'),(72,3290835,785,'2021-02-15 17:51:48'), +(73,3290824,1310,'2021-02-15 18:21:30'),(74,3290875,754,'2021-02-15 18:21:30'), +(75,3290854,782,'2021-02-15 18:21:36'),(76,3290897,2,'2021-02-15 18:21:36'), +(77,3290822,745,'2021-02-15 18:21:53'),(78,3290800,1011,'2021-02-15 18:21:54'), +(79,3290901,8998,'2021-02-15 18:21:54'),(80,3290835,0,'2021-02-15 18:22:00'), +(81,3290936,0,'2021-02-15 18:25:28'),(82,3290895,0,'2021-02-15 18:25:28'), +(83,3290832,0,'2021-02-15 18:25:28'),(84,3290878,796,'2021-02-15 18:25:52'), +(85,3290900,730,'2021-02-15 18:25:52'),(86,3290856,0,'2021-02-15 18:26:11'), +(87,3290904,816,'2021-02-15 18:26:17'),(88,3290882,0,'2021-02-15 18:26:25'), +(89,3290883,1031,'2021-02-15 18:27:16'),(90,3290918,1749,'2021-02-15 18:27:17'), +(91,3290831,0,'2021-02-15 18:59:11'),(92,3290884,477,'2021-02-15 18:59:12'), +(93,3290899,483,'2021-02-15 18:59:12'),(94,3290848,486,'2021-02-15 18:59:35'), +(95,3290880,487,'2021-02-15 18:59:35'),(96,3290798,0,'2021-02-15 18:59:52'), +(97,3290777,983,'2021-02-15 19:00:10'),(98,3290811,488,'2021-02-15 19:00:10'), +(99,3290917,1283,'2021-02-15 19:00:36'),(100,3290858,482,'2021-02-15 19:00:42'); +CREATE TABLE t2 (a int) ENGINE=MYISAM; +INSERT INTO t2 VALUES +(3289475),(3289496),(3289562),(3289593),(3289594),(3289595),(3289626), +(3289642),(3289658),(3289739),(3289750),(3289761),(3289762),(3289763), +(3289774),(3289780),(3289951),(3289957),(3289988),(3290034),(1231562); +ANALYZE TABLE t1,t2; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +EXPLAIN SELECT t1.valdouble, t1.valint1 +FROM t1, +(SELECT max(t.valdate) AS maxdate, t.valint1 FROM t1 t GROUP BY t.valint1) +AS dt +WHERE t1.valint1 = dt.valint1 AND +t1.valdate = dt.maxdate AND +t1.valint1 IN (SELECT * FROM t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL distinct_key NULL NULL NULL 21 +1 PRIMARY t1 ref valint1,valint1_2 valint1 5 test.t2.a 2 Using index condition; Using where +1 PRIMARY ref key0 key0 11 test.t1.valdate,test.t1.valint1 10 +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 21 Using where +2 DERIVED t index valint1,valint1_2 valint1_2 11 NULL 100 Using index; Using temporary; Using filesort +SELECT t1.valdouble, t1.valint1 +FROM t1, +(SELECT max(t.valdate) AS maxdate, t.valint1 FROM t1 t GROUP BY t.valint1) +AS dt +WHERE t1.valint1 = dt.valint1 AND +t1.valdate = dt.maxdate AND +t1.valint1 IN (SELECT * FROM t2); +valdouble valint1 +1074 3289475 +1 3289496 +0 3289562 +1046 3289593 +0 3289594 +0 3289595 +2150 3289626 +0 3289642 +1155 3289658 +1958 3289739 +1 3289750 +1 3289761 +2 3289762 +1 3289763 +429 3289774 +0 3289780 +1897 3289951 +1994 3289957 +5 3289988 +DROP TABLE t1,t2; # End of 10.4 tests diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index 05032fb94a4..ce303779a41 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -4013,4 +4013,92 @@ eval $q; drop table t1,t2,t3; +--echo # +--echo # MDEV-32064: usage of splittable derived table in query +--echo # with IN subquery in WHERE +--echo # + +CREATE TABLE t1 ( + id int unsigned NOT NULL, + valint1 int unsigned, + valdouble double, + valdate datetime, + PRIMARY KEY (id), + KEY (valint1), + KEY (valint1,valdate) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES +(1,3289763,1,'2021-02-09 18:31:35'),(2,3289750,1,'2021-02-09 18:31:35'), +(3,3289780,1173,'2021-02-09 18:31:35'),(4,3289762,2,'2021-02-09 18:31:36'), +(5,3289774,2334,'2021-02-09 18:31:36'),(6,3289739,1934,'2021-02-09 18:31:36'), +(7,3289761,1,'2021-02-09 18:31:37'),(8,3289763,1,'2021-02-10 11:05:19'), +(9,3289750,1,'2021-02-10 11:05:19'),(10,3289780,0,'2021-02-10 11:05:35'), +(11,3289762,2,'2021-02-10 11:05:47'),(12,3289774,429,'2021-02-10 11:05:47'), +(13,3289739,1958,'2021-02-10 11:06:00'),(14,3289761,1,'2021-02-10 11:06:08'), +(15,3289957,0,'2021-02-10 13:04:44'),(16,3289988,1993,'2021-02-10 13:04:45'), +(17,3289951,1896,'2021-02-10 13:04:59'),(18,3289957,1994,'2021-02-10 13:07:40'), +(19,3289988,5,'2021-02-10 13:07:40'),(20,3289951,1897,'2021-02-10 13:07:40'), +(21,3289594,0,'2021-02-11 14:19:38'),(22,3289642,0,'2021-02-11 14:19:38'), +(23,3289626,2150,'2021-02-11 14:19:38'),(24,3289562,0,'2021-02-11 14:19:39'), +(25,3289593,1046,'2021-02-11 14:19:39'),(26,3289496,1,'2021-02-11 14:19:45'), +(27,3289475,1074,'2021-02-11 14:19:50'),(28,3289658,1155,'2021-02-11 14:19:56'), +(29,3289595,0,'2021-02-11 14:20:01'),(30,3290334,903,'2021-02-11 16:22:44'), +(31,3290284,479,'2021-02-11 16:23:00'),(32,3290327,236,'2021-02-11 16:23:00'), +(33,3290854,0,'2021-02-15 17:29:59'),(34,3290824,0,'2021-02-15 17:30:13'), +(35,3290875,0,'2021-02-15 17:30:14'),(36,3290897,2,'2021-02-15 17:30:19'), +(37,3290800,0,'2021-02-15 17:30:24'),(38,3290822,0,'2021-02-15 17:30:25'), +(39,3290901,2667,'2021-02-15 17:30:30'),(40,3290835,0,'2021-02-15 17:30:36'), +(41,3290875,0,'2021-02-15 17:35:33'),(42,3290824,1330,'2021-02-15 17:35:39'), +(43,3290854,769,'2021-02-15 17:35:44'),(44,3290897,2,'2021-02-15 17:35:50'), +(45,3290822,748,'2021-02-15 17:35:50'),(46,3290800,1007,'2021-02-15 17:35:56'), +(47,3290901,7018,'2021-02-15 17:35:56'),(48,3290835,779,'2021-02-15 17:36:17'), +(49,3290824,1329,'2021-02-15 17:40:30'),(50,3290875,764,'2021-02-15 17:40:31'), +(51,3290854,763,'2021-02-15 17:40:36'),(52,3290897,2347,'2021-02-15 17:40:47'), +(53,3290822,1,'2021-02-15 17:41:01'),(54,3290800,1018,'2021-02-15 17:41:07'), +(55,3290901,3936,'2021-02-15 17:41:08'),(56,3290835,784,'2021-02-15 17:41:24'), +(57,3290824,1313,'2021-02-15 17:44:47'),(58,3290875,758,'2021-02-15 17:44:48'), +(59,3290854,767,'2021-02-15 17:44:48'),(60,3290897,2438,'2021-02-15 17:44:48'), +(61,3290822,738,'2021-02-15 17:44:49'),(62,3290800,1003,'2021-02-15 17:44:54'), +(63,3290901,4686,'2021-02-15 17:44:55'),(64,3290835,778,'2021-02-15 17:45:13'), +(65,3290824,1303,'2021-02-15 17:51:16'),(66,3290875,753,'2021-02-15 17:51:16'), +(67,3290854,766,'2021-02-15 17:51:22'),(68,3290897,1,'2021-02-15 17:51:22'), +(69,3290822,743,'2021-02-15 17:51:28'),(70,3290901,5718,'2021-02-15 17:51:33'), +(71,3290800,1018,'2021-02-15 17:51:34'),(72,3290835,785,'2021-02-15 17:51:48'), +(73,3290824,1310,'2021-02-15 18:21:30'),(74,3290875,754,'2021-02-15 18:21:30'), +(75,3290854,782,'2021-02-15 18:21:36'),(76,3290897,2,'2021-02-15 18:21:36'), +(77,3290822,745,'2021-02-15 18:21:53'),(78,3290800,1011,'2021-02-15 18:21:54'), +(79,3290901,8998,'2021-02-15 18:21:54'),(80,3290835,0,'2021-02-15 18:22:00'), +(81,3290936,0,'2021-02-15 18:25:28'),(82,3290895,0,'2021-02-15 18:25:28'), +(83,3290832,0,'2021-02-15 18:25:28'),(84,3290878,796,'2021-02-15 18:25:52'), +(85,3290900,730,'2021-02-15 18:25:52'),(86,3290856,0,'2021-02-15 18:26:11'), +(87,3290904,816,'2021-02-15 18:26:17'),(88,3290882,0,'2021-02-15 18:26:25'), +(89,3290883,1031,'2021-02-15 18:27:16'),(90,3290918,1749,'2021-02-15 18:27:17'), +(91,3290831,0,'2021-02-15 18:59:11'),(92,3290884,477,'2021-02-15 18:59:12'), +(93,3290899,483,'2021-02-15 18:59:12'),(94,3290848,486,'2021-02-15 18:59:35'), +(95,3290880,487,'2021-02-15 18:59:35'),(96,3290798,0,'2021-02-15 18:59:52'), +(97,3290777,983,'2021-02-15 19:00:10'),(98,3290811,488,'2021-02-15 19:00:10'), +(99,3290917,1283,'2021-02-15 19:00:36'),(100,3290858,482,'2021-02-15 19:00:42'); + +CREATE TABLE t2 (a int) ENGINE=MYISAM; +INSERT INTO t2 VALUES +(3289475),(3289496),(3289562),(3289593),(3289594),(3289595),(3289626), +(3289642),(3289658),(3289739),(3289750),(3289761),(3289762),(3289763), +(3289774),(3289780),(3289951),(3289957),(3289988),(3290034),(1231562); + +ANALYZE TABLE t1,t2; + +let $q= +SELECT t1.valdouble, t1.valint1 +FROM t1, + (SELECT max(t.valdate) AS maxdate, t.valint1 FROM t1 t GROUP BY t.valint1) + AS dt +WHERE t1.valint1 = dt.valint1 AND + t1.valdate = dt.maxdate AND + t1.valint1 IN (SELECT * FROM t2); + +eval EXPLAIN $q; +eval $q; + +DROP TABLE t1,t2; + --echo # End of 10.4 tests diff --git a/sql/opt_split.cc b/sql/opt_split.cc index 26d0771f6f8..aba11d8c38f 100644 --- a/sql/opt_split.cc +++ b/sql/opt_split.cc @@ -987,7 +987,8 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(uint idx, table_map needed_in_prefix= 0; do { - if (keyuse_ext->needed_in_prefix & remaining_tables) + if (keyuse_ext->needed_in_prefix & + (remaining_tables | this->join->sjm_lookup_tables)) { keyuse_ext++; continue; From eb19638418906538d21a6833bb6ec33d355fdf93 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 17 Oct 2023 12:46:31 +0400 Subject: [PATCH 062/158] MDEV-32244 Wrong bit encoding using COALESCE When aggregating pairs BIT+NULL and NULL+BIT for result, e.g. in COALESCE(), preserve the BIT data type (ignore explicit NULLs). The same fix applied to YEAR. --- mysql-test/main/type_bit.result | 20 ++++++++++++++++++ mysql-test/main/type_bit.test | 16 +++++++++++++++ mysql-test/main/type_year.result | 20 ++++++++++++++++++ mysql-test/main/type_year.test | 14 +++++++++++++ sql/sql_type.cc | 35 ++++++++++++++++++++++++++++++-- sql/sql_type.h | 6 ++++++ 6 files changed, 109 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/type_bit.result b/mysql-test/main/type_bit.result index 1b5adf8c1fe..945dbfb3863 100644 --- a/mysql-test/main/type_bit.result +++ b/mysql-test/main/type_bit.result @@ -1859,5 +1859,25 @@ cc 18446744073709551615 cr 18446744073709551615 ct 18446744073709551615 # +# MDEV-32244 Wrong bit encoding using COALESCE +# +CREATE TABLE t1 (c1 BIT); +INSERT INTO t1 (c1) VALUES (0x01); +CREATE TABLE t2 AS SELECT +c1, +COALESCE(c1, c1) AS c2, +COALESCE(c1, null) AS c3, +COALESCE(null, c1) AS c4 FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `c1` bit(1) DEFAULT NULL, + `c2` bit(1) DEFAULT NULL, + `c3` bit(1) DEFAULT NULL, + `c4` bit(1) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t2; +DROP TABLE t1; +# # End of 10.4 tests # diff --git a/mysql-test/main/type_bit.test b/mysql-test/main/type_bit.test index 95a29af70f6..56ba954e728 100644 --- a/mysql-test/main/type_bit.test +++ b/mysql-test/main/type_bit.test @@ -543,6 +543,22 @@ DELIMITER ;$$ --horizontal_results +--echo # +--echo # MDEV-32244 Wrong bit encoding using COALESCE +--echo # + +CREATE TABLE t1 (c1 BIT); +INSERT INTO t1 (c1) VALUES (0x01); +CREATE TABLE t2 AS SELECT + c1, + COALESCE(c1, c1) AS c2, + COALESCE(c1, null) AS c3, + COALESCE(null, c1) AS c4 FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; +DROP TABLE t1; + + --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/type_year.result b/mysql-test/main/type_year.result index 124654cd946..6f8add9d381 100644 --- a/mysql-test/main/type_year.result +++ b/mysql-test/main/type_year.result @@ -675,5 +675,25 @@ FLOOR(a) int(4) unsigned YES NULL CEILING(a) int(4) unsigned YES NULL DROP TABLE t2,t1; # +# MDEV-32244 Wrong bit encoding using COALESCE +# +CREATE TABLE t1 (c1 YEAR); +INSERT INTO t1 (c1) VALUES (0x01); +CREATE TABLE t2 AS SELECT +c1, +COALESCE(c1, c1) AS c2, +COALESCE(c1, null) AS c3, +COALESCE(null, c1) AS c4 FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `c1` year(4) DEFAULT NULL, + `c2` year(4) DEFAULT NULL, + `c3` year(4) DEFAULT NULL, + `c4` year(4) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t2; +DROP TABLE t1; +# # End of 10.4 tests # diff --git a/mysql-test/main/type_year.test b/mysql-test/main/type_year.test index c281bdb7d97..25fe6486607 100644 --- a/mysql-test/main/type_year.test +++ b/mysql-test/main/type_year.test @@ -354,6 +354,20 @@ CREATE TABLE t2 AS SELECT a, ROUND(a), TRUNCATE(a,0), FLOOR(a), CEILING(a) FROM DESC t2; DROP TABLE t2,t1; +--echo # +--echo # MDEV-32244 Wrong bit encoding using COALESCE +--echo # + +CREATE TABLE t1 (c1 YEAR); +INSERT INTO t1 (c1) VALUES (0x01); +CREATE TABLE t2 AS SELECT + c1, + COALESCE(c1, c1) AS c2, + COALESCE(c1, null) AS c3, + COALESCE(null, c1) AS c4 FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; +DROP TABLE t1; --echo # --echo # End of 10.4 tests diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 92bf2b39f90..edffcf761c8 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -1588,6 +1588,7 @@ Type_handler::bit_and_int_mixture_handler(uint max_char_length) Note, independently from "treat_bit_as_number": - a single BIT argument gives BIT as a result - two BIT couterparts give BIT as a result + - (BIT + explicit NULL) or (explicit NULL + BIT) give BIT @details This function aggregates field types from the array of items. Found type is supposed to be used later as the result field type @@ -1620,8 +1621,11 @@ Type_handler_hybrid_field_type::aggregate_for_result(const char *funcname, { const Type_handler *cur= items[i]->type_handler(); set_if_bigger(max_display_length, items[i]->max_display_length()); - if (treat_bit_as_number && - ((type_handler() == &type_handler_bit) ^ (cur == &type_handler_bit))) + uint bit_count= (type_handler() == &type_handler_bit) + + (cur == &type_handler_bit); + uint null_count= (type_handler() == &type_handler_null) + + (cur == &type_handler_null); + if (treat_bit_as_number && bit_count == 1 && null_count == 0) { bit_and_non_bit_mixture_found= true; if (type_handler() == &type_handler_bit) @@ -4067,12 +4071,39 @@ Type_handler_timestamp_common::create_item_copy(THD *thd, Item *item) const /*************************************************************************/ +/* + This method handles YEAR and BIT data types. + It does not switch the data type to DECIAMAL on a + unsigned_flag mistmatch. This important for combinations + like YEAR+NULL, BIT+NULL. +*/ bool Type_handler_int_result:: Item_hybrid_func_fix_attributes(THD *thd, const char *func_name, Type_handler_hybrid_field_type *handler, Type_all_attributes *func, Item **items, uint nitems) const +{ + func->aggregate_attributes_int(items, nitems); + return false; +} + + +/* + This method handles general purpose integer data types + TINYINT, SHORTINT, MEDIUNINT, BIGINT. + It switches to DECIMAL in case if a mismatch in unsigned_flag found. + + Note, we should fix this to ignore all items with + type_handler()==&type_handler_null. + It's too late for 10.4. Let's do it eventually in a higher version. +*/ +bool Type_handler_general_purpose_int:: + Item_hybrid_func_fix_attributes(THD *thd, + const char *func_name, + Type_handler_hybrid_field_type *handler, + Type_all_attributes *func, + Item **items, uint nitems) const { bool unsigned_flag= items[0]->unsigned_flag; for (uint i= 1; i < nitems; i++) diff --git a/sql/sql_type.h b/sql/sql_type.h index bf76806c44a..97315faa665 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -4820,6 +4820,12 @@ public: type_limits_int_by_unsigned_flag(bool unsigned_flag) const= 0; uint32 max_display_length(const Item *item) const; uint32 Item_decimal_notation_int_digits(const Item *item) const; + bool Item_hybrid_func_fix_attributes(THD *thd, + const char *name, + Type_handler_hybrid_field_type *, + Type_all_attributes *atrr, + Item **items, + uint nitems) const; bool Vers_history_point_resolve_unit(THD *thd, Vers_history_point *p) const; }; From 073a088f3190c6da63df979a154853d4b5309e50 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 17 Oct 2023 03:27:11 +0200 Subject: [PATCH 063/158] MDEV-31467: wsrep_sst_mariabackup not working on FreeBSD Due to the different command line format of the timeout utility on FreeBSD and Linux, SST scripts for mariabackup may not work on FreeBSD. This commit fixes this problem by adding a different command to test options on FreeBSD and adding proper formatting for the utility options. --- scripts/wsrep_sst_mariabackup.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 981a042d506..84742defc16 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -798,10 +798,20 @@ recv_joiner() local ltcmd="$tcmd" if [ $tmt -gt 0 ]; then if [ -n "$(commandex timeout)" ]; then - if timeout --help | grep -qw -F -- '-k'; then + local koption=0 + if [ "$OS" = 'FreeBSD' ]; then + if timeout 2>&1 | grep -qw -F -- '-k'; then + koption=1 + fi + else + if timeout --help | grep -qw -F -- '-k'; then + koption=1 + fi + fi + if [ $koption -ne 0 ]; then ltcmd="timeout -k $(( tmt+10 )) $tmt $tcmd" else - ltcmd="timeout -s9 $tmt $tcmd" + ltcmd="timeout -s 9 $tmt $tcmd" fi fi fi From e9b38f684f9f3f5bd366bf22489b70349c121d03 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 13 Oct 2023 20:06:41 +0200 Subject: [PATCH 064/158] MDEV-25734 mbstream breaks page compression on XFS try harder to punch holes on xfs, don't rely on its heuristics to do the right thing --- extra/mariabackup/ds_local.cc | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/extra/mariabackup/ds_local.cc b/extra/mariabackup/ds_local.cc index 41a00dd9c39..0702db731f3 100644 --- a/extra/mariabackup/ds_local.cc +++ b/extra/mariabackup/ds_local.cc @@ -28,6 +28,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA #include #endif +#ifdef HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE +#include +#endif + typedef struct { File fd; my_bool init_ibd_done; @@ -160,9 +164,18 @@ static int write_compressed(File fd, uchar *data, size_t len, size_t pagesize) if (datasize < n_bytes) { /* This punches a "hole" in the file. */ size_t hole_bytes = n_bytes - datasize; - if (my_seek(fd, hole_bytes, MY_SEEK_CUR, MYF(MY_WME | MY_NABP)) - == MY_FILEPOS_ERROR) - return 1; + my_off_t off = my_seek(fd, hole_bytes, MY_SEEK_CUR, MYF(MY_WME | MY_NABP)); + if (off == MY_FILEPOS_ERROR) + return 1; +#ifdef HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE + /* punch holes harder for filesystems (like XFS) that + heuristically decide whether leave a hole after the + above or not based on the current access pattern + (which is sequential write and not at all typical for + what InnoDB will be doing with the file later */ + fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + off - hole_bytes, hole_bytes); +#endif } written += n_bytes; ptr += n_bytes; From e46ae59265036ff2653e2bba4a0e71b048db4b4f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 15 Oct 2023 23:50:30 +0200 Subject: [PATCH 065/158] MDEV-27523 main.delayed fails with wrong error code or timeout when executed after main.deadlock_ftwrl don't forget to reset mdl_context.m_deadlock_overweight when taking the THD out of the cache - the history of previous connections should not affect the weight in deadlock victim selection (small cleanup of the test to help the correct merge) --- mysql-test/main/delayed.result | 11 +---------- mysql-test/main/delayed.test | 29 +---------------------------- sql/mdl.h | 5 +++-- sql/sql_class.cc | 1 + 4 files changed, 6 insertions(+), 40 deletions(-) diff --git a/mysql-test/main/delayed.result b/mysql-test/main/delayed.result index fe284dfcdad..af486201907 100644 --- a/mysql-test/main/delayed.result +++ b/mysql-test/main/delayed.result @@ -1,4 +1,3 @@ -drop table if exists t1; create table t1 (a char(10), tmsp timestamp); insert into t1 set a = 1; insert delayed into t1 set a = 2; @@ -259,7 +258,6 @@ INSERT DELAYED INTO t1 SET b= b(); ERROR 42000: FUNCTION test.b does not exist DROP TABLE t1; End of 5.0 tests -DROP TABLE IF EXISTS t1,t2; SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'; CREATE TABLE `t1` ( `id` int(11) PRIMARY KEY auto_increment, @@ -293,7 +291,6 @@ set global low_priority_updates = 1; select @@global.low_priority_updates; @@global.low_priority_updates 1 -drop table if exists t1; create table t1 (a int, b int); insert into t1 values (1,1); lock table t1 read; @@ -322,7 +319,6 @@ set global low_priority_updates = @old_delayed_updates; # # Bug #47682 strange behaviour of INSERT DELAYED # -DROP TABLE IF EXISTS t1, t2; CREATE TABLE t1 (f1 integer); CREATE TABLE t2 (f1 integer); FLUSH TABLES WITH READ LOCK; @@ -335,8 +331,6 @@ End of 5.1 tests # # Bug #47274 assert in open_table on CREATE TABLE # -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t2; CREATE TABLE t1 ( f1 INTEGER AUTO_INCREMENT, PRIMARY KEY (f1)); # The following CREATE TABLEs before gave an assert. INSERT DELAYED t1 VALUES (4); @@ -352,14 +346,12 @@ CREATE TABLE t2 (f1 INTEGER); INSERT DELAYED t1 VALUES (7); CREATE TABLE t1 LIKE t2; ERROR 42S01: Table 't1' already exists -DROP TABLE t2; -DROP TABLE t1; +DROP TABLE t2, t1; # # Bug#54332 Deadlock with two connections doing LOCK TABLE+INSERT DELAYED # # This test is not supposed to work under --ps-protocol since # INSERT DELAYED doesn't work under LOCK TABLES with this protocol. -DROP TABLE IF EXISTS t1, t2; CREATE TABLE t1 (a INT); CREATE TABLE t2 (a INT); CREATE TABLE t3 (a INT); @@ -450,7 +442,6 @@ DROP TABLE t1, t2, t3; # connect con1,localhost,root,,; connection default; -drop table if exists t1, t2, tm; create table t1(a int); create table t2(a int); create table tm(a int) engine=merge union=(t1, t2); diff --git a/mysql-test/main/delayed.test b/mysql-test/main/delayed.test index 2cf34b5975b..2b9eb083f13 100644 --- a/mysql-test/main/delayed.test +++ b/mysql-test/main/delayed.test @@ -21,9 +21,6 @@ select @@global.storage_engine in ("memory","myisam","archive","blackhole") as `TRUE`; enable_query_log; ---disable_warnings -drop table if exists t1; ---enable_warnings create table t1 (a char(10), tmsp timestamp); insert into t1 set a = 1; insert delayed into t1 set a = 2; @@ -276,9 +273,6 @@ DROP TABLE t1; # # Bug#27358 INSERT DELAYED does not honour SQL_MODE of the client # ---disable_warnings -DROP TABLE IF EXISTS t1,t2; ---enable_warnings SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'; CREATE TABLE `t1` ( `id` int(11) PRIMARY KEY auto_increment, @@ -315,9 +309,6 @@ set @old_delayed_updates = @@global.low_priority_updates; set global low_priority_updates = 1; select @@global.low_priority_updates; ---disable_warnings -drop table if exists t1; ---enable_warnings create table t1 (a int, b int); insert into t1 values (1,1); lock table t1 read; @@ -351,10 +342,6 @@ set global low_priority_updates = @old_delayed_updates; --echo # Bug #47682 strange behaviour of INSERT DELAYED --echo # ---disable_warnings -DROP TABLE IF EXISTS t1, t2; ---enable_warnings - CREATE TABLE t1 (f1 integer); CREATE TABLE t2 (f1 integer); @@ -378,11 +365,6 @@ DROP TABLE t1, t2; --echo # Bug #47274 assert in open_table on CREATE TABLE --echo # ---disable_warnings -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t2; ---enable_warnings - CREATE TABLE t1 ( f1 INTEGER AUTO_INCREMENT, PRIMARY KEY (f1)); --echo # The following CREATE TABLEs before gave an assert. @@ -404,9 +386,7 @@ INSERT DELAYED t1 VALUES (7); --error ER_TABLE_EXISTS_ERROR CREATE TABLE t1 LIKE t2; -DROP TABLE t2; -DROP TABLE t1; - +DROP TABLE t2, t1; --echo # --echo # Bug#54332 Deadlock with two connections doing LOCK TABLE+INSERT DELAYED @@ -417,10 +397,6 @@ DROP TABLE t1; --disable_ps_protocol --disable_view_protocol ---disable_warnings -DROP TABLE IF EXISTS t1, t2; ---enable_warnings - CREATE TABLE t1 (a INT); CREATE TABLE t2 (a INT); CREATE TABLE t3 (a INT); @@ -573,9 +549,6 @@ DROP TABLE t1, t2, t3; --disable_view_protocol connect (con1,localhost,root,,); connection default; ---disable_warnings -drop table if exists t1, t2, tm; ---enable_warnings create table t1(a int); create table t2(a int); create table tm(a int) engine=merge union=(t1, t2); diff --git a/sql/mdl.h b/sql/mdl.h index 1f14188ec59..418dd6d3bd7 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -919,7 +919,8 @@ public: already has received some signal or closed signal slot. */ - void init(MDL_context_owner *arg) { m_owner= arg; } + void init(MDL_context_owner *arg) { m_owner= arg; reset(); } + void reset() { m_deadlock_overweight= 0; } void set_needs_thr_lock_abort(bool needs_thr_lock_abort) { @@ -1028,7 +1029,7 @@ private: */ MDL_wait_for_subgraph *m_waiting_for; LF_PINS *m_pins; - uint m_deadlock_overweight= 0; + uint m_deadlock_overweight; private: MDL_ticket *find_ticket(MDL_request *mdl_req, enum_mdl_duration *duration); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 1d278a01947..479ff0e68d0 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1209,6 +1209,7 @@ const Type_handler *THD::type_handler_for_datetime() const void THD::init() { DBUG_ENTER("thd::init"); + mdl_context.reset(); mysql_mutex_lock(&LOCK_global_system_variables); plugin_thdvar_init(this); /* From f293b2b21149e9085bee8ecdc5ee627233830eb0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 16 Oct 2023 14:29:12 +0200 Subject: [PATCH 066/158] cleanup --- mysql-test/main/metadata.result | 11 +++++++++-- mysql-test/main/metadata.test | 15 ++++++++++----- mysql-test/main/myisam_recover.result | 3 +-- mysql-test/main/myisam_recover.test | 16 ++++------------ mysql-test/main/schema.result | 5 ----- mysql-test/main/schema.test | 17 ----------------- mysql-test/main/sp-lock.result | 8 -------- mysql-test/main/sp-lock.test | 13 ------------- sql/mdl.cc | 7 +++++++ sql/sql_class.h | 3 +-- 10 files changed, 32 insertions(+), 66 deletions(-) diff --git a/mysql-test/main/metadata.result b/mysql-test/main/metadata.result index 175b09e5a2b..16556a030cf 100644 --- a/mysql-test/main/metadata.result +++ b/mysql-test/main/metadata.result @@ -1,4 +1,3 @@ -drop table if exists t1,t2; select 1, 1.0, -1, "hello", NULL; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def 1 3 1 1 N 32897 0 63 @@ -222,6 +221,9 @@ def v3 v3 renamed renamed 8 12 0 Y 32896 0 63 renamed drop table t1; drop view v1,v2,v3; +# +# End of 4.1 tests +# select a.* from (select 2147483648 as v_large) a; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def a v_large v_large 8 10 10 N 32769 0 63 @@ -301,7 +303,9 @@ def test va va f1 f1 3 11 0 Y 32768 0 63 f1 DROP VIEW v1; DROP TABLE t1; -End of 5.0 tests +# +# End of 5.0 tests +# create table t1( # numeric types bool_col bool, @@ -802,3 +806,6 @@ t1 CREATE TABLE `t1` ( `@b2:=111111111111` bigint(12) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci DROP TABLE t1; +# +# End of 10.3 tests +# diff --git a/mysql-test/main/metadata.test b/mysql-test/main/metadata.test index eade0e0ff01..6004ba9850d 100644 --- a/mysql-test/main/metadata.test +++ b/mysql-test/main/metadata.test @@ -4,9 +4,6 @@ #View protocol gives slightly different metadata --source include/no_view_protocol.inc ---disable_warnings -drop table if exists t1,t2; ---enable_warnings --enable_metadata # PS protocol gives slightly different metadata --disable_ps_protocol @@ -127,7 +124,9 @@ drop table t1; drop view v1,v2,v3; --disable_metadata -# End of 4.1 tests +--echo # +--echo # End of 4.1 tests +--echo # # # Bug #28492: subselect returns LONG in >5.0.24a and LONGLONG in <=5.0.24a @@ -189,7 +188,9 @@ SELECT f1 FROM v1 va; DROP VIEW v1; DROP TABLE t1; ---echo End of 5.0 tests +--echo # +--echo # End of 5.0 tests +--echo # # Verify that column metadata is correct for all possible data types. # Originally about BUG#42980 "Client doesn't set NUM_FLAG for DECIMAL" @@ -485,3 +486,7 @@ SELECT @b1:=10, @b2:=@b2:=111111111111; CREATE TABLE t1 AS SELECT @b1:=10, @b2:=111111111111; SHOW CREATE TABLE t1; DROP TABLE t1; + +--echo # +--echo # End of 10.3 tests +--echo # diff --git a/mysql-test/main/myisam_recover.result b/mysql-test/main/myisam_recover.result index da96682186c..a619f2cdd4a 100644 --- a/mysql-test/main/myisam_recover.result +++ b/mysql-test/main/myisam_recover.result @@ -22,7 +22,6 @@ call mtr.add_suppression(" '\..test.t1'"); set @save_table_open_cache=@@table_open_cache; set global table_open_cache=256; set global table_definition_cache=400; -drop procedure if exists p_create; create procedure p_create() begin declare i int default 1; @@ -44,13 +43,13 @@ end while; end| call p_create(); drop procedure p_create; +$lock; connection default; # # We have to disable the ps-protocol, to avoid # "Prepared statement needs to be re-prepared" errors # -- table def versions change all the time with full table cache. # -drop table if exists t1, t1_mrg, t1_copy; # # Prepare a MERGE engine table, that refers to a corrupted # child. diff --git a/mysql-test/main/myisam_recover.test b/mysql-test/main/myisam_recover.test index 9056b219148..f78fc38a675 100644 --- a/mysql-test/main/myisam_recover.test +++ b/mysql-test/main/myisam_recover.test @@ -28,9 +28,6 @@ call mtr.add_suppression(" '\..test.t1'"); set @save_table_open_cache=@@table_open_cache; set global table_open_cache=256; set global table_definition_cache=400; ---disable_warnings -drop procedure if exists p_create; ---enable_warnings delimiter |; create procedure p_create() begin @@ -54,10 +51,9 @@ end| delimiter ;| call p_create(); drop procedure p_create; ---disable_query_log let $lock=`select @lock_table_stmt`; -eval $lock; ---enable_query_log +evalp $lock; + connection default; --echo # --echo # We have to disable the ps-protocol, to avoid @@ -65,9 +61,6 @@ connection default; --echo # -- table def versions change all the time with full table cache. --echo # --disable_ps_protocol ---disable_warnings -drop table if exists t1, t1_mrg, t1_copy; ---enable_warnings let $MYSQLD_DATADIR=`select @@datadir`; --echo # --echo # Prepare a MERGE engine table, that refers to a corrupted @@ -151,20 +144,19 @@ select * from t2; select * from t1; connect(con2, localhost, root); ---SEND ALTER TABLE t2 ADD val INT +--send ALTER TABLE t2 ADD val INT connection default; --echo # With fix we should have alter table waiting for t2 lock here. let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "Waiting%" AND info = "ALTER TABLE t2 ADD val INT"; - --source include/wait_condition.inc ROLLBACK; SET autocommit = 1; connection con2; ---REAP +--reap connection default; disconnect con2; diff --git a/mysql-test/main/schema.result b/mysql-test/main/schema.result index 95d5535e415..bdb25a98250 100644 --- a/mysql-test/main/schema.result +++ b/mysql-test/main/schema.result @@ -1,4 +1,3 @@ -drop database if exists mysqltest1; create schema foo; show create schema foo; Database Create Database @@ -15,7 +14,6 @@ drop schema foo; # # Bug #48940 MDL deadlocks against mysql_rm_db # -DROP SCHEMA IF EXISTS schema1; connect con2, localhost, root; connection default; CREATE SCHEMA schema1; @@ -34,7 +32,6 @@ disconnect con2; # # Bug #49988 MDL deadlocks with mysql_create_db, reload_acl_and_cache # -DROP SCHEMA IF EXISTS schema1; connect con2, localhost, root; connection default; CREATE SCHEMA schema1; @@ -77,8 +74,6 @@ disconnect con2; # Tests for increased CREATE/ALTER/DROP DATABASE concurrency with # database name locks. # -DROP DATABASE IF EXISTS db1; -DROP DATABASE IF EXISTS db2; connect con2, localhost, root; connect con3, localhost, root; connection default; diff --git a/mysql-test/main/schema.test b/mysql-test/main/schema.test index e8ab4e406c0..474c9c7e9c7 100644 --- a/mysql-test/main/schema.test +++ b/mysql-test/main/schema.test @@ -8,10 +8,6 @@ --source include/count_sessions.inc --source include/default_charset.inc ---disable_warnings -drop database if exists mysqltest1; ---enable_warnings - create schema foo; show create schema foo; show schemas; @@ -22,10 +18,6 @@ drop schema foo; --echo # Bug #48940 MDL deadlocks against mysql_rm_db --echo # ---disable_warnings -DROP SCHEMA IF EXISTS schema1; ---enable_warnings - connect(con2, localhost, root); connection default; @@ -61,10 +53,6 @@ disconnect con2; --echo # Bug #49988 MDL deadlocks with mysql_create_db, reload_acl_and_cache --echo # ---disable_warnings -DROP SCHEMA IF EXISTS schema1; ---enable_warnings - connect (con2, localhost, root); connection default; @@ -134,11 +122,6 @@ disconnect con2; --echo # database name locks. --echo # ---disable_warnings -DROP DATABASE IF EXISTS db1; -DROP DATABASE IF EXISTS db2; ---enable_warnings - connect (con2, localhost, root); connect (con3, localhost, root); diff --git a/mysql-test/main/sp-lock.result b/mysql-test/main/sp-lock.result index ec8d8970ae3..4d9cbc8ad51 100644 --- a/mysql-test/main/sp-lock.result +++ b/mysql-test/main/sp-lock.result @@ -13,12 +13,6 @@ # Start a transaction, create a savepoint, # then call a DDL operation on a procedure, and then check # that the savepoint is no longer present. -drop table if exists t1; -drop procedure if exists p1; -drop procedure if exists p2; -drop procedure if exists p3; -drop procedure if exists p4; -drop function if exists f1; create table t1 (a int); # # Test 'CREATE PROCEDURE'. @@ -744,8 +738,6 @@ DROP PROCEDURE p1; # Bug#57663 Concurrent statement using stored function and DROP DATABASE # breaks SBR # -DROP DATABASE IF EXISTS db1; -DROP FUNCTION IF EXISTS f1; connect con1, localhost, root; connect con2, localhost, root; # Test 1: Check that DROP DATABASE block if a function is used diff --git a/mysql-test/main/sp-lock.test b/mysql-test/main/sp-lock.test index f31a8268231..224169a68b5 100644 --- a/mysql-test/main/sp-lock.test +++ b/mysql-test/main/sp-lock.test @@ -23,14 +23,6 @@ # Tests will be skipped for the view protocol -- source include/no_view_protocol.inc ---disable_warnings -drop table if exists t1; -drop procedure if exists p1; -drop procedure if exists p2; -drop procedure if exists p3; -drop procedure if exists p4; -drop function if exists f1; ---enable_warnings create table t1 (a int); --echo # --echo # Test 'CREATE PROCEDURE'. @@ -861,11 +853,6 @@ DROP PROCEDURE p1; --echo # breaks SBR --echo # ---disable_warnings -DROP DATABASE IF EXISTS db1; -DROP FUNCTION IF EXISTS f1; ---enable_warnings - connect(con1, localhost, root); connect(con2, localhost, root); diff --git a/sql/mdl.cc b/sql/mdl.cc index abb2d1372b8..7aae1c16022 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -245,6 +245,12 @@ const char *dbug_print_mdl(MDL_ticket *mdl_ticket) } +const char *dbug_print(MDL_ticket *mdl_ticket) +{ + return dbug_print_mdl(mdl_ticket); +} + + static int mdl_dbug_print_lock(MDL_ticket *mdl_ticket, void *arg, bool granted) { String *tmp= (String*) arg; @@ -259,6 +265,7 @@ static int mdl_dbug_print_lock(MDL_ticket *mdl_ticket, void *arg, bool granted) const char *mdl_dbug_print_locks() { thread_local String tmp; + tmp.length(0); mdl_iterate(mdl_dbug_print_lock, (void*) &tmp); return tmp.c_ptr(); } diff --git a/sql/sql_class.h b/sql/sql_class.h index b40acd084ca..066e42ca0f0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4695,8 +4695,7 @@ public: /* Relesae transactional locks if there are no active transactions */ void release_transactional_locks() { - if (!(server_status & - (SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY))) + if (!in_active_multi_stmt_transaction()) mdl_context.release_transactional_locks(this); } int decide_logging_format(TABLE_LIST *tables); From 81c88ab7cd824779d4869581b5a6b51f6cc305d4 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 16 Oct 2023 17:37:16 +0200 Subject: [PATCH 067/158] MDEV-28820 MyISAM wrong server status flags MyISAM tables no longer take transactional metadata locks unless there already is an active transaction. --- mysql-test/main/mdl.result | 44 +++++++++++++++++++++++++++ mysql-test/main/mdl.test | 43 ++++++++++++++++++++++++++ mysql-test/main/myisam_recover.result | 3 +- mysql-test/main/myisam_recover.test | 3 +- mysql-test/main/schema.result | 4 +-- mysql-test/main/schema.test | 4 +-- mysql-test/main/sp-lock.result | 4 +-- mysql-test/main/sp-lock.test | 4 +-- sql/sql_parse.cc | 2 +- 9 files changed, 98 insertions(+), 13 deletions(-) diff --git a/mysql-test/main/mdl.result b/mysql-test/main/mdl.result index 883f35674c0..c6fa2c2dbde 100644 --- a/mysql-test/main/mdl.result +++ b/mysql-test/main/mdl.result @@ -88,3 +88,47 @@ unlock tables; connection default; disconnect locker; DROP TABLE t1,t3; +# +# MDEV-28820 MyISAM wrong server status flags +# +create table t1 (a int); +set autocommit=0; +select @@in_transaction; +@@in_transaction +0 +select * from t1; +a +select @@in_transaction; +@@in_transaction +0 +connect foo,localhost,root; +drop table t1; +connection default; +set autocommit=1; +create table t1 (a int); +create table t2 (b int) engine=innodb; +set autocommit=0; +select @@in_transaction; +@@in_transaction +0 +select * from t2; +b +select @@in_transaction; +@@in_transaction +1 +select * from t1; +a +connection foo; +drop table t1; +connection default; +select * from t1; +a +commit; +connection foo; +disconnect foo; +connection default; +set autocommit=default; +drop table t2; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/mdl.test b/mysql-test/main/mdl.test index 54e23801231..b0ce408ec13 100644 --- a/mysql-test/main/mdl.test +++ b/mysql-test/main/mdl.test @@ -80,3 +80,46 @@ connection default; disconnect locker; DROP TABLE t1,t3; --enable_service_connection + +--echo # +--echo # MDEV-28820 MyISAM wrong server status flags +--echo # +# MyISAM alone doesn't start a transaction or takes transactional MDL +create table t1 (a int); +set autocommit=0; +select @@in_transaction; +select * from t1; +select @@in_transaction; +connect foo,localhost,root; +drop table t1; +connection default; +set autocommit=1; + +# MyISAM in a transaction (started by InnoDB) takes transactional MDL all right +create table t1 (a int); +create table t2 (b int) engine=innodb; +set autocommit=0; +select @@in_transaction; +select * from t2; +select @@in_transaction; +select * from t1; +connection foo; +send drop table t1; +connection default; +let $wait_condition= + select count(*) > 0 from information_schema.processlist + where state = "Waiting for table metadata lock"; +--source include/wait_condition.inc +select * from t1; +commit; + +connection foo; +reap; +disconnect foo; +connection default; +set autocommit=default; +drop table t2; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/myisam_recover.result b/mysql-test/main/myisam_recover.result index a619f2cdd4a..f42919bf186 100644 --- a/mysql-test/main/myisam_recover.result +++ b/mysql-test/main/myisam_recover.result @@ -126,7 +126,7 @@ test.t1 check error Record-count is not ok; is 2 Should be: 1 test.t1 check warning Found 2 key parts. Should be: 1 test.t1 check error Corrupt # At this point we have a corrupt t1 -set autocommit = 0; +start transaction; select * from t2; a 1 @@ -145,7 +145,6 @@ ALTER TABLE t2 ADD val INT; connection default; # With fix we should have alter table waiting for t2 lock here. ROLLBACK; -SET autocommit = 1; connection con2; connection default; disconnect con2; diff --git a/mysql-test/main/myisam_recover.test b/mysql-test/main/myisam_recover.test index f78fc38a675..00f99265464 100644 --- a/mysql-test/main/myisam_recover.test +++ b/mysql-test/main/myisam_recover.test @@ -135,7 +135,7 @@ flush table t1; check table t1; --echo # At this point we have a corrupt t1 -set autocommit = 0; +start transaction; select * from t2; --echo # Without fix select from t1 will break the transaction. After the fix --echo # transaction should be active and should hold lock on table t2. Alter @@ -153,7 +153,6 @@ let $wait_condition= LIKE "Waiting%" AND info = "ALTER TABLE t2 ADD val INT"; --source include/wait_condition.inc ROLLBACK; -SET autocommit = 1; connection con2; --reap diff --git a/mysql-test/main/schema.result b/mysql-test/main/schema.result index bdb25a98250..6fa0dbb3a96 100644 --- a/mysql-test/main/schema.result +++ b/mysql-test/main/schema.result @@ -18,14 +18,14 @@ connect con2, localhost, root; connection default; CREATE SCHEMA schema1; CREATE TABLE schema1.t1 (a INT); -SET autocommit= FALSE; +START TRANSACTION; INSERT INTO schema1.t1 VALUES (1); connection con2; DROP SCHEMA schema1; connection default; ALTER SCHEMA schema1 DEFAULT CHARACTER SET utf8; Got one of the listed errors -SET autocommit= TRUE; +COMMIT; connection con2; connection default; disconnect con2; diff --git a/mysql-test/main/schema.test b/mysql-test/main/schema.test index 474c9c7e9c7..b984ebb8639 100644 --- a/mysql-test/main/schema.test +++ b/mysql-test/main/schema.test @@ -25,7 +25,7 @@ connection default; CREATE SCHEMA schema1; CREATE TABLE schema1.t1 (a INT); -SET autocommit= FALSE; +START TRANSACTION; INSERT INTO schema1.t1 VALUES (1); connection con2; @@ -40,7 +40,7 @@ let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist # Listing the error twice to prevent result diffences based on filename. --error 1,1 ALTER SCHEMA schema1 DEFAULT CHARACTER SET utf8; -SET autocommit= TRUE; +COMMIT; connection con2; --reap diff --git a/mysql-test/main/sp-lock.result b/mysql-test/main/sp-lock.result index 4d9cbc8ad51..e7ebc3aecb8 100644 --- a/mysql-test/main/sp-lock.result +++ b/mysql-test/main/sp-lock.result @@ -463,8 +463,8 @@ drop function f1; create function f1() returns varchar(20) return "f1()"; create function f2() returns varchar(20) return "f2()"; create view v1 as select f1() as a; -set @@session.autocommit=0; lock table v1 read; +start transaction; select * from v1; a f1() @@ -486,6 +486,7 @@ connection con2; # Reaping 'drop function f2'... connection default; unlock tables; +commit; connection con1; # Reaping 'drop function f1'... connection default; @@ -494,7 +495,6 @@ ERROR 42000: FUNCTION test.f1 does not exist drop function f2; ERROR 42000: FUNCTION test.f2 does not exist drop view v1; -set @@session.autocommit=default; # # 8) Check the situation when we're preparing or executing a # prepared statement, and as part of that try to flush the diff --git a/mysql-test/main/sp-lock.test b/mysql-test/main/sp-lock.test index 224169a68b5..9ca071070ac 100644 --- a/mysql-test/main/sp-lock.test +++ b/mysql-test/main/sp-lock.test @@ -537,8 +537,8 @@ drop function f1; create function f1() returns varchar(20) return "f1()"; create function f2() returns varchar(20) return "f2()"; create view v1 as select f1() as a; -set @@session.autocommit=0; lock table v1 read; +start transaction; select * from v1; savepoint sv; select f2(); @@ -565,6 +565,7 @@ connection con2; reap; connection default; unlock tables; +commit; connection con1; --echo # Reaping 'drop function f1'... reap; @@ -574,7 +575,6 @@ drop function f1; --error ER_SP_DOES_NOT_EXIST drop function f2; drop view v1; -set @@session.autocommit=default; --echo # --echo # 8) Check the situation when we're preparing or executing a diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f5a80e9e5e5..c13637a3cfd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6319,7 +6319,7 @@ finish: thd->release_transactional_locks(); } } - else if (! thd->in_sub_stmt && ! thd->in_multi_stmt_transaction_mode()) + else if (! thd->in_sub_stmt && ! thd->in_active_multi_stmt_transaction()) { /* - If inside a multi-statement transaction, From 6f835378764772554b7570e7eaae6b4b88e5eb15 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 16 Oct 2023 23:05:26 +0200 Subject: [PATCH 068/158] MDEV-24283 Assertion `bitmap_is_set(&m_part_info->read_partitions, m_part_spec.start_part)' failed in ha_partition::handle_ordered_index_scan ha_partition should not try to search the index if all partitions were pruned away. The fix originally by Nayuta Yanagisawa --- mysql-test/main/partition_pruning.result | 14 ++++++++++++++ mysql-test/main/partition_pruning.test | 15 +++++++++++++++ sql/ha_partition.cc | 3 +++ 3 files changed, 32 insertions(+) diff --git a/mysql-test/main/partition_pruning.result b/mysql-test/main/partition_pruning.result index f8ae65fbcea..d34bc7aaef2 100644 --- a/mysql-test/main/partition_pruning.result +++ b/mysql-test/main/partition_pruning.result @@ -3529,3 +3529,17 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t3 p3 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) 1 SIMPLE t2 NULL ALL NULL NULL NULL NULL 10 Using where; Using join buffer (incremental, BNL join) drop table t0,t1,t2,t3; +# +# End of 10.3 tests +# +# +# MDEV-24283 Assertion `bitmap_is_set(&m_part_info->read_partitions, m_part_spec.start_part)' failed in ha_partition::handle_ordered_index_scan +# +create table t1 (c int key) partition by list (c) (partition p values in (0)); +select max(c) from t1 where c>0; +max(c) +NULL +drop table t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/partition_pruning.test b/mysql-test/main/partition_pruning.test index d59f52be313..5c65274adb9 100644 --- a/mysql-test/main/partition_pruning.test +++ b/mysql-test/main/partition_pruning.test @@ -1583,3 +1583,18 @@ select * from t1 left join (t3 join t2) on (t1.a=t3.a and t3.a=t2.b and t3.part_ drop table t0,t1,t2,t3; +--echo # +--echo # End of 10.3 tests +--echo # + +--echo # +--echo # MDEV-24283 Assertion `bitmap_is_set(&m_part_info->read_partitions, m_part_spec.start_part)' failed in ha_partition::handle_ordered_index_scan +--echo # + +create table t1 (c int key) partition by list (c) (partition p values in (0)); +select max(c) from t1 where c>0; +drop table t1; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 7dfbf0268b4..f0421fa4026 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5896,6 +5896,9 @@ int ha_partition::common_first_last(uchar *buf) { int error; + if (table->all_partitions_pruned_away) + return HA_ERR_END_OF_FILE; // No rows matching WHERE + if (unlikely((error= partition_scan_set_up(buf, FALSE)))) return error; if (!m_ordered_scan_ongoing && From 3da5d047b8d8c193a872c5ae6c3fb213218117bc Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 17 Oct 2023 18:37:45 +0530 Subject: [PATCH 069/158] MDEV-31851 After crash recovery, undo tablespace fails to open Problem: ======== - InnoDB fails to open undo tablespace when page0 is corrupted and fails to throw error. Solution: ========= - InnoDB throws DB_CORRUPTION error when InnoDB encounters page0 corruption of undo tablespace. - InnoDB restores the page0 of undo tablespace from doublewrite buffer if it encounters page corruption - Moved Datafile::restore_from_doublewrite() to recv_dblwr_t::restore_first_page(). So that undo tablespace and system tablespace can use this function instead of duplicating the code srv_undo_tablespace_open(): Returns 0 if file doesn't exist or ULINT_UNDEFINED if page0 is corrupted. --- .../suite/innodb/r/undo_space_dblwr.result | 21 +++++++ .../suite/innodb/t/undo_space_dblwr.opt | 2 + .../suite/innodb/t/undo_space_dblwr.test | 47 +++++++++++++++ storage/innobase/buf/buf0dblwr.cc | 2 +- storage/innobase/fsp/fsp0file.cc | 58 +------------------ storage/innobase/fsp/fsp0sysspace.cc | 4 +- storage/innobase/handler/ha_innodb.cc | 1 + storage/innobase/include/fsp0file.h | 5 -- storage/innobase/include/log0recv.h | 9 +++ storage/innobase/log/log0recv.cc | 34 +++++++++++ storage/innobase/srv/srv0start.cc | 47 ++++++++------- 11 files changed, 145 insertions(+), 85 deletions(-) create mode 100644 mysql-test/suite/innodb/r/undo_space_dblwr.result create mode 100644 mysql-test/suite/innodb/t/undo_space_dblwr.opt create mode 100644 mysql-test/suite/innodb/t/undo_space_dblwr.test diff --git a/mysql-test/suite/innodb/r/undo_space_dblwr.result b/mysql-test/suite/innodb/r/undo_space_dblwr.result new file mode 100644 index 00000000000..7954c426341 --- /dev/null +++ b/mysql-test/suite/innodb/r/undo_space_dblwr.result @@ -0,0 +1,21 @@ +call mtr.add_suppression("Checksum mismatch in the first page of file"); +show variables like 'innodb_doublewrite'; +Variable_name Value +innodb_doublewrite ON +create table t1(f1 int not null, f2 int not null)engine=innodb; +insert into t1 values (1, 1); +SET GLOBAL innodb_purge_rseg_truncate_frequency=1; +InnoDB 0 transactions not purged +set GLOBAL innodb_log_checkpoint_now=1; +# Make the first page dirty for undo tablespace +set global innodb_saved_page_number_debug = 0; +set global innodb_fil_make_page_dirty_debug = 1; +SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0; +SET GLOBAL innodb_max_dirty_pages_pct=0.0; +# Kill the server +# restart +FOUND 1 /Checksum mismatch in the first page of file/ in mysqld.1.err +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; diff --git a/mysql-test/suite/innodb/t/undo_space_dblwr.opt b/mysql-test/suite/innodb/t/undo_space_dblwr.opt new file mode 100644 index 00000000000..0b4f59176f3 --- /dev/null +++ b/mysql-test/suite/innodb/t/undo_space_dblwr.opt @@ -0,0 +1,2 @@ +--innodb_undo_tablespaces=3 +--innodb_sys_tablespaces diff --git a/mysql-test/suite/innodb/t/undo_space_dblwr.test b/mysql-test/suite/innodb/t/undo_space_dblwr.test new file mode 100644 index 00000000000..c746f37ead7 --- /dev/null +++ b/mysql-test/suite/innodb/t/undo_space_dblwr.test @@ -0,0 +1,47 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/not_embedded.inc +call mtr.add_suppression("Checksum mismatch in the first page of file"); +let INNODB_PAGE_SIZE=`select @@innodb_page_size`; +let MYSQLD_DATADIR=`select @@datadir`; + +show variables like 'innodb_doublewrite'; +create table t1(f1 int not null, f2 int not null)engine=innodb; +insert into t1 values (1, 1); + +SET GLOBAL innodb_purge_rseg_truncate_frequency=1; +--source include/wait_all_purged.inc + +set GLOBAL innodb_log_checkpoint_now=1; +--source ../include/no_checkpoint_start.inc + +--echo # Make the first page dirty for undo tablespace +set global innodb_saved_page_number_debug = 0; +set global innodb_fil_make_page_dirty_debug = 1; + +SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0; +SET GLOBAL innodb_max_dirty_pages_pct=0.0; + +sleep 1; +--let CLEANUP_IF_CHECKPOINT=drop table t1; +--source ../include/no_checkpoint_end.inc + +perl; +use IO::Handle; +my $fname= "$ENV{'MYSQLD_DATADIR'}/undo001"; +my $page_size = $ENV{INNODB_PAGE_SIZE}; +die unless open(FILE, "+<", $fname); +sysread(FILE, $page, $page_size)==$page_size||die "Unable to read $name\n"; +substr($page, 49, 4) = pack("N", 1000); +sysseek(FILE, 0, 0)||die "Unable to seek $fname\n"; +die unless syswrite(FILE, $page, $page_size) == $page_size; +close FILE; +EOF + +--source include/start_mysqld.inc +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; +let SEARCH_PATTERN= Checksum mismatch in the first page of file; +--source include/search_pattern_in_file.inc + +check table t1; +drop table t1; diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index b6b6e87b6df..57ec3553b8d 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -350,7 +350,7 @@ void buf_dblwr_t::recover() { byte *page= *i; const uint32_t page_no= page_get_page_no(page); - if (!page_no) /* recovered via Datafile::restore_from_doublewrite() */ + if (!page_no) /* recovered via recv_dblwr_t::restore_first_page() */ continue; const lsn_t lsn= mach_read_from_8(page + FIL_PAGE_LSN); diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index f131e4e90da..f0ead3b80a3 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -481,7 +481,8 @@ Datafile::validate_for_recovery() return(err); } - if (restore_from_doublewrite()) { + if (recv_sys.dblwr.restore_first_page( + m_space_id, m_filepath, m_handle)) { return(DB_CORRUPTION); } @@ -768,61 +769,6 @@ Datafile::find_space_id() return(DB_CORRUPTION); } - -/** Restore the first page of the tablespace from -the double write buffer. -@return whether the operation failed */ -bool -Datafile::restore_from_doublewrite() -{ - if (srv_operation > SRV_OPERATION_EXPORT_RESTORED) { - return true; - } - - /* Find if double write buffer contains page_no of given space id. */ - const page_id_t page_id(m_space_id, 0); - const byte* page = recv_sys.dblwr.find_page(page_id); - - if (!page) { - /* If the first page of the given user tablespace is not there - in the doublewrite buffer, then the recovery is going to fail - now. Hence this is treated as an error. */ - - ib::error() - << "Corrupted page " << page_id - << " of datafile '" << m_filepath - << "' could not be found in the doublewrite buffer."; - - return(true); - } - - ulint flags = mach_read_from_4( - FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); - - if (!fil_space_t::is_valid_flags(flags, m_space_id)) { - flags = fsp_flags_convert_from_101(flags); - /* recv_dblwr_t::validate_page() inside find_page() - checked this already. */ - ut_ad(flags != ULINT_UNDEFINED); - /* The flags on the page should be converted later. */ - } - - ulint physical_size = fil_space_t::physical_size(flags); - - ut_a(page_get_page_no(page) == page_id.page_no()); - - ib::info() << "Restoring page " << page_id - << " of datafile '" << m_filepath - << "' from the doublewrite buffer. Writing " - << physical_size << " bytes into file '" - << m_filepath << "'"; - - return(os_file_write( - IORequestWrite, - m_filepath, m_handle, page, 0, physical_size) - != DB_SUCCESS); -} - /** Create a link filename based on the contents of m_name, open that file, and read the contents into m_filepath. @retval DB_SUCCESS if remote linked tablespace file is opened and read. diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc index 07a8295a94e..a7bb417c502 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -594,7 +594,9 @@ SysTablespace::read_lsn_and_check_flags(lsn_t* flushed_lsn) if (err != DB_SUCCESS && (retry == 1 - || it->restore_from_doublewrite())) { + || recv_sys.dblwr.restore_first_page( + it->m_space_id, it->m_filepath, + it->handle()))) { it->close(); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 291568c6e2a..695f2895e4e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -18298,6 +18298,7 @@ checkpoint_now_set(THD*, st_mysql_sys_var*, void*, const void* save) while (log_sys.last_checkpoint_lsn.load( std::memory_order_acquire) + SIZE_OF_FILE_CHECKPOINT + + log_sys.framing_size() < (lsn= log_sys.get_lsn(std::memory_order_acquire))) { log_make_checkpoint(); log_sys.log.flush(); diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h index 7db85e87ed0..342b243f731 100644 --- a/storage/innobase/include/fsp0file.h +++ b/storage/innobase/include/fsp0file.h @@ -423,11 +423,6 @@ private: else DB_ERROR. */ dberr_t find_space_id(); - /** Restore the first page of the tablespace from - the double write buffer. - @return whether the operation failed */ - bool restore_from_doublewrite(); - /** Points into m_filepath to the file name with extension */ char* m_filename; diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 263996a78d3..34211392ba3 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -134,6 +134,15 @@ struct recv_dblwr_t byte* find_page(const page_id_t page_id, const fil_space_t *space= NULL, byte *tmp_buf= NULL); + /** Restore the first page of the given tablespace from + doublewrite buffer. + @param space_id tablespace identifier + @param name tablespace filepath + @param file tablespace file handle + @return whether the operation failed */ + bool restore_first_page( + ulint space_id, const char *name, os_file_t file); + typedef std::deque > list; /** Recovered doublewrite buffer page frames */ diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index e452267d2e8..3b59fb43ed3 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3819,6 +3819,11 @@ byte *recv_dblwr_t::find_page(const page_id_t page_id, if (page_get_page_no(page) != page_id.page_no() || page_get_space_id(page) != page_id.space()) continue; + uint32_t flags= mach_read_from_4( + FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); + if (!fil_space_t::is_valid_flags(flags, page_id.space())) + continue; + const lsn_t lsn= mach_read_from_8(page + FIL_PAGE_LSN); if (lsn <= max_lsn || !validate_page(page_id, page, space, tmp_buf)) @@ -3827,9 +3832,38 @@ byte *recv_dblwr_t::find_page(const page_id_t page_id, memset(page + FIL_PAGE_LSN, 0, 8); continue; } + + ut_a(page_get_page_no(page) == page_id.page_no()); max_lsn= lsn; result= page; } return result; } + +bool recv_dblwr_t::restore_first_page(ulint space_id, const char *name, + os_file_t file) +{ + const page_id_t page_id(space_id, 0); + const byte* page= find_page(page_id); + if (!page) + { + /* If the first page of the given user tablespace is not there + in the doublewrite buffer, then the recovery is going to fail + now. Hence this is treated as error. */ + ib::error() + << "Corrupted page " << page_id << " of datafile '" + << name <<"' could not be found in the doublewrite buffer."; + return true; + } + + ulint physical_size= fil_space_t::physical_size( + mach_read_from_4(page + FSP_HEADER_OFFSET + FSP_SPACE_FLAGS)); + ib::info() << "Restoring page " << page_id << " of datafile '" + << name << "' from the doublewrite buffer. Writing " + << physical_size << " bytes into file '" << name << "'"; + + return os_file_write( + IORequestWrite, name, file, page, 0, physical_size) != + DB_SUCCESS; +} diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index cc6fed7f86c..180c8a1a825 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -484,7 +484,8 @@ static ulint trx_rseg_get_n_undo_tablespaces() @param[in] name tablespace file name @param[in] i undo tablespace count @return undo tablespace identifier -@retval 0 on failure */ +@retval 0 if file doesn't exist +@retval ULINT_UNDEFINED if page0 is corrupted */ static ulint srv_undo_tablespace_open(bool create, const char* name, ulint i) { bool success; @@ -523,13 +524,13 @@ static ulint srv_undo_tablespace_open(bool create, const char* name, ulint i) { page_t *page= static_cast(aligned_malloc(srv_page_size, srv_page_size)); - dberr_t err= os_file_read(IORequestRead, fh, page, 0, srv_page_size); - if (err != DB_SUCCESS) + if (os_file_read(IORequestRead, fh, page, 0, srv_page_size) != + DB_SUCCESS) { err_exit: ib::error() << "Unable to read first page of file " << name; aligned_free(page); - return err; + return ULINT_UNDEFINED; } uint32_t id= mach_read_from_4(FIL_PAGE_SPACE_ID + page); @@ -538,19 +539,18 @@ err_exit: FSP_HEADER_OFFSET + FSP_SPACE_ID + page, 4)) { ib::error() << "Inconsistent tablespace ID in file " << name; - err= DB_CORRUPTION; - goto err_exit; - } - - fsp_flags= mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); - if (buf_page_is_corrupted(false, page, fsp_flags)) - { - ib::error() << "Checksum mismatch in the first page of file " << name; - err= DB_CORRUPTION; goto err_exit; } space_id= id; + fsp_flags= mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); + if (buf_page_is_corrupted(false, page, fsp_flags)) + { + ib::error() << "Checksum mismatch in the first page of file " << name; + if (recv_sys.dblwr.restore_first_page(space_id, name, fh)) + goto err_exit; + } + snprintf(undo_name, sizeof undo_name, "innodb_undo%03u", id); aligned_free(page); } @@ -669,17 +669,19 @@ static dberr_t srv_all_undo_tablespaces_open(bool create_new_db, ulint n_undo) snprintf(name, sizeof name, "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, i + 1); ulint space_id= srv_undo_tablespace_open(create_new_db, name, i); - if (!space_id) - { + switch (space_id) { + case ULINT_UNDEFINED: + return DB_CORRUPTION; + case 0: if (!create_new_db) - break; - ib::error() << "Unable to open create tablespace '" << name << "'."; + goto unused_undo; + sql_print_error("InnoDB: Unable to open create tablespace '%s'", name); return DB_ERROR; + default: + /* Should be no gaps in undo tablespace ids. */ + ut_a(!i || prev_id + 1 == space_id); } - /* Should be no gaps in undo tablespace ids. */ - ut_a(!i || prev_id + 1 == space_id); - prev_id= space_id; /* Note the first undo tablespace id in case of @@ -692,14 +694,15 @@ static dberr_t srv_all_undo_tablespaces_open(bool create_new_db, ulint n_undo) We stop at the first failure. These are undo tablespaces that are not in use and therefore not required by recovery. We only check that there are no gaps. */ - +unused_undo: for (ulint i= prev_id + 1; i < srv_undo_space_id_start + TRX_SYS_N_RSEGS; ++i) { char name[OS_FILE_MAX_PATH]; snprintf(name, sizeof(name), "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, i); - if (!srv_undo_tablespace_open(create_new_db, name, i)) + ulint space_id= srv_undo_tablespace_open(create_new_db, name, i); + if (!space_id || space_id == SRV_SPACE_ID_UPPER_BOUND) break; ++srv_undo_tablespaces_open; } From ac15141448e86dc6c9236e7fa45794cce60fc981 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Wed, 18 Oct 2023 11:15:16 +0700 Subject: [PATCH 070/158] MDEV-32369: Memory leak when executing PS for query with IN subquery The memory allocated for an instance of the class Item_direct_ref_to_item was leaked on second execution of a query run as a prepared statement and involving conversion of strings with different character sets. The reason of leaking the memory was caused by the fact that a statement arena could be already set by the moment the method Type_std_attributes::agg_item_set_converter() is called. --- mysql-test/main/ps_mem_leaks.result | 16 ++++++++++++++++ mysql-test/main/ps_mem_leaks.test | 27 +++++++++++++++++++++++++++ sql/item.cc | 13 ++++++++----- 3 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 mysql-test/main/ps_mem_leaks.result create mode 100644 mysql-test/main/ps_mem_leaks.test diff --git a/mysql-test/main/ps_mem_leaks.result b/mysql-test/main/ps_mem_leaks.result new file mode 100644 index 00000000000..8d66a025c1a --- /dev/null +++ b/mysql-test/main/ps_mem_leaks.result @@ -0,0 +1,16 @@ +# +# MDEV-32369: Memory leak when executing PS for query with IN subquery +# +CREATE TABLE t1 (a VARCHAR(10)) ENGINE=MYISAM; +CREATE TABLE t2 (b VARCHAR(10) CHARACTER SET utf8) ENGINE=MYISAM; +INSERT INTO t1 VALUES ('b'); +INSERT INTO t2 VALUES ('b'); +PREPARE stmt FROM "SELECT t1.a FROM t1 WHERE t1.a IN (SELECT t2.b FROM t2)"; +EXECUTE stmt; +a +b +EXECUTE stmt; +a +b +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; diff --git a/mysql-test/main/ps_mem_leaks.test b/mysql-test/main/ps_mem_leaks.test new file mode 100644 index 00000000000..2e357f9400c --- /dev/null +++ b/mysql-test/main/ps_mem_leaks.test @@ -0,0 +1,27 @@ +# This file contains test cases that use the memory leaks detection feature +# provided by the cmake build option -DWITH_PROTECT_STATEMENT_MEMROOT + +--source include/not_embedded.inc +# The cmake option -DWITH_PROTECT_STATEMENT_MEMROOT is used only +# for debug build +--source include/have_debug.inc + +--echo # +--echo # MDEV-32369: Memory leak when executing PS for query with IN subquery +--echo # + +CREATE TABLE t1 (a VARCHAR(10)) ENGINE=MYISAM; +CREATE TABLE t2 (b VARCHAR(10) CHARACTER SET utf8) ENGINE=MYISAM; + +INSERT INTO t1 VALUES ('b'); +INSERT INTO t2 VALUES ('b'); + +PREPARE stmt FROM "SELECT t1.a FROM t1 WHERE t1.a IN (SELECT t2.b FROM t2)"; + +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; + +DROP TABLE t1, t2; + diff --git a/sql/item.cc b/sql/item.cc index 500d9f73a08..f9d8ac490ae 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2584,19 +2584,22 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll, if (conv->fix_fields_if_needed(thd, arg)) return TRUE; - Query_arena *arena, backup; - arena= thd->activate_stmt_arena_if_needed(&backup); - if (arena) + if (!thd->stmt_arena->is_conventional()) { + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); + Item_direct_ref_to_item *ref= new (thd->mem_root) Item_direct_ref_to_item(thd, *arg); if ((ref == NULL) || ref->fix_fields(thd, (Item **)&ref)) { - thd->restore_active_arena(arena, &backup); + if (arena) + thd->restore_active_arena(arena, &backup); return TRUE; } *arg= ref; - thd->restore_active_arena(arena, &backup); + if (arena) + thd->restore_active_arena(arena, &backup); ref->change_item(thd, conv); } else From 5372a0f1a93757bb927f5bc5bc73a387bb3f7d14 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 18 Oct 2023 08:41:50 +0200 Subject: [PATCH 071/158] 1.3 --- zlib/CMakeLists.txt | 4 +- zlib/ChangeLog | 20 +- zlib/FAQ | 2 +- zlib/Makefile.in | 10 +- zlib/README | 19 +- zlib/adler32.c | 32 +- zlib/compress.c | 21 +- zlib/configure | 26 +- zlib/contrib/ada/readme.txt | 4 +- zlib/contrib/ada/test.adb | 4 +- zlib/contrib/ada/zlib-streams.ads | 2 +- zlib/contrib/ada/zlib.adb | 2 +- zlib/contrib/ada/zlib.ads | 2 +- zlib/contrib/delphi/ZLib.pas | 2 +- zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs | 2 +- zlib/contrib/dotzlib/DotZLib/CodecBase.cs | 4 +- zlib/contrib/dotzlib/DotZLib/GZipStream.cs | 6 +- zlib/contrib/dotzlib/DotZLib/UnitTests.cs | 2 +- zlib/contrib/dotzlib/readme.txt | 2 +- zlib/contrib/infback9/infback9.c | 24 +- zlib/contrib/infback9/infback9.h | 16 +- zlib/contrib/infback9/inftree9.c | 17 +- zlib/contrib/infback9/inftree9.h | 6 +- zlib/contrib/minizip/MiniZip64_Changes.txt | 2 +- zlib/contrib/minizip/configure.ac | 2 +- zlib/contrib/minizip/crypt.h | 12 +- zlib/contrib/minizip/ioapi.c | 62 +- zlib/contrib/minizip/ioapi.h | 36 +- zlib/contrib/minizip/iowin32.c | 65 +- zlib/contrib/minizip/iowin32.h | 8 +- zlib/contrib/minizip/miniunz.c | 70 +- zlib/contrib/minizip/minizip.c | 60 +- zlib/contrib/minizip/mztools.c | 8 +- zlib/contrib/minizip/unzip.c | 519 +++++-------- zlib/contrib/minizip/unzip.h | 134 ++-- zlib/contrib/minizip/zip.c | 315 ++++---- zlib/contrib/minizip/zip.h | 285 ++++---- zlib/contrib/pascal/zlibpas.pas | 2 +- zlib/contrib/testzlib/testzlib.c | 2 +- zlib/contrib/untgz/untgz.c | 63 +- zlib/contrib/vstudio/readme.txt | 2 +- zlib/contrib/vstudio/vc10/zlib.rc | 8 +- zlib/contrib/vstudio/vc10/zlibvc.def | 2 +- zlib/contrib/vstudio/vc11/zlib.rc | 8 +- zlib/contrib/vstudio/vc11/zlibvc.def | 2 +- zlib/contrib/vstudio/vc12/zlib.rc | 8 +- zlib/contrib/vstudio/vc12/zlibvc.def | 2 +- zlib/contrib/vstudio/vc14/zlib.rc | 8 +- zlib/contrib/vstudio/vc14/zlibvc.def | 2 +- zlib/contrib/vstudio/vc9/zlib.rc | 8 +- zlib/contrib/vstudio/vc9/zlibvc.def | 2 +- zlib/crc32.c | 248 +++---- zlib/deflate.c | 569 ++++++-------- zlib/deflate.h | 16 +- zlib/examples/fitblk.c | 2 +- zlib/examples/zlib_how.html | 26 +- zlib/examples/zran.c | 732 ++++++++++--------- zlib/examples/zran.h | 69 +- zlib/gzclose.c | 4 +- zlib/gzguts.h | 23 +- zlib/gzlib.c | 101 +-- zlib/gzread.c | 88 +-- zlib/gzwrite.c | 84 +-- zlib/infback.c | 30 +- zlib/inffast.c | 5 +- zlib/inffast.h | 2 +- zlib/inflate.c | 129 +--- zlib/inftrees.c | 17 +- zlib/inftrees.h | 6 +- zlib/os400/README400 | 2 +- zlib/os400/zlib.inc | 8 +- zlib/qnx/package.qpg | 10 +- zlib/test/example.c | 103 +-- zlib/test/infcover.c | 5 +- zlib/test/minigzip.c | 172 ++--- zlib/treebuild.xml | 4 +- zlib/trees.c | 526 ++++++------- zlib/uncompr.c | 16 +- zlib/win32/README-WIN32.txt | 4 +- zlib/zconf.h | 8 +- zlib/zconf.h.cmakein | 8 +- zlib/zconf.h.in | 8 +- zlib/zlib.3 | 6 +- zlib/zlib.3.pdf | Bin 19366 -> 19505 bytes zlib/zlib.h | 379 +++++----- zlib/zlib2ansi | 152 ---- zlib/zutil.c | 60 +- zlib/zutil.h | 20 +- 88 files changed, 2249 insertions(+), 3319 deletions(-) delete mode 100755 zlib/zlib2ansi diff --git a/zlib/CMakeLists.txt b/zlib/CMakeLists.txt index b412dc7feb7..7f1b69f4a37 100644 --- a/zlib/CMakeLists.txt +++ b/zlib/CMakeLists.txt @@ -1,9 +1,9 @@ -cmake_minimum_required(VERSION 2.4.4) +cmake_minimum_required(VERSION 2.4.4...3.15.0) set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) project(zlib C) -set(VERSION "1.2.13") +set(VERSION "1.3") set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") diff --git a/zlib/ChangeLog b/zlib/ChangeLog index 457526bc6a5..8707988ac18 100644 --- a/zlib/ChangeLog +++ b/zlib/ChangeLog @@ -1,6 +1,24 @@ ChangeLog file for zlib +Changes in 1.3 (18 Aug 2023) +- Remove K&R function definitions and zlib2ansi +- Fix bug in deflateBound() for level 0 and memLevel 9 +- Fix bug when gzungetc() is used immediately after gzopen() +- Fix bug when using gzflush() with a very small buffer +- Fix crash when gzsetparams() attempted for transparent write +- Fix test/example.c to work with FORCE_STORED +- Rewrite of zran in examples (see zran.c version history) +- Fix minizip to allow it to open an empty zip file +- Fix reading disk number start on zip64 files in minizip +- Fix logic error in minizip argument processing +- Add minizip testing to Makefile +- Read multiple bytes instead of byte-by-byte in minizip unzip.c +- Add memory sanitizer to configure (--memory) +- Various portability improvements +- Various documentation improvements +- Various spelling and typo corrections + Changes in 1.2.13 (13 Oct 2022) - Fix configure issue that discarded provided CC definition - Correct incorrect inputs provided to the CRC functions @@ -1445,7 +1463,7 @@ Changes in 0.99 (27 Jan 96) - fix typo in Make_vms.com (f$trnlnm -> f$getsyi) - in fcalloc, normalize pointer if size > 65520 bytes - don't use special fcalloc for 32 bit Borland C++ -- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc. - use Z_BINARY instead of BINARY - document that gzclose after gzdopen will close the file - allow "a" as mode in gzopen diff --git a/zlib/FAQ b/zlib/FAQ index 99b7cf92e45..55f1cdc22f6 100644 --- a/zlib/FAQ +++ b/zlib/FAQ @@ -4,7 +4,7 @@ If your question is not there, please check the zlib home page http://zlib.net/ which may have more recent information. -The lastest zlib FAQ is at http://zlib.net/zlib_faq.html +The latest zlib FAQ is at http://zlib.net/zlib_faq.html 1. Is zlib Y2K-compliant? diff --git a/zlib/Makefile.in b/zlib/Makefile.in index 7d2713f4c57..34d3cd722f8 100644 --- a/zlib/Makefile.in +++ b/zlib/Makefile.in @@ -28,7 +28,7 @@ CPP=$(CC) -E STATICLIB=libz.a SHAREDLIB=libz.so -SHAREDLIBV=libz.so.1.2.13 +SHAREDLIBV=libz.so.1.3 SHAREDLIBM=libz.so.1 LIBS=$(STATICLIB) $(SHAREDLIBV) @@ -359,8 +359,14 @@ zconf.h.cmakein: $(SRCDIR)zconf.h.in zconf: $(SRCDIR)zconf.h.in cp -p $(SRCDIR)zconf.h.in zconf.h +minizip-test: static + cd contrib/minizip && { CFLAGS="$(CFLAGS)" $(MAKE) test ; cd ../.. ; } + +minizip-clean: + cd contrib/minizip && { $(MAKE) clean ; cd ../.. ; } + mostlyclean: clean -clean: +clean: minizip-clean rm -f *.o *.lo *~ \ example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ example64$(EXE) minigzip64$(EXE) \ diff --git a/zlib/README b/zlib/README index ba34d1894a9..e02fc5aa206 100644 --- a/zlib/README +++ b/zlib/README @@ -1,6 +1,6 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.13 is a general purpose data compression library. All the code is +zlib 1.3 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and @@ -29,18 +29,17 @@ PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at -http://marknelson.us/1997/01/01/zlib-engine/ . +https://marknelson.us/posts/1997/01/01/zlib-engine.html . -The changes made in version 1.2.13 are documented in the file ChangeLog. +The changes made in version 1.3 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . -zlib is available in Java using the java.util.zip package, documented at -http://java.sun.com/developer/technicalArticles/Programming/compression/ . +zlib is available in Java using the java.util.zip package. Follow the API +Documentation link at: https://docs.oracle.com/search/?q=java.util.zip . -A Perl interface to zlib written by Paul Marquess is available -at CPAN (Comprehensive Perl Archive Network) sites, including -http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . +A Perl interface to zlib and bzip2 written by Paul Marquess +can be found at https://github.com/pmqs/IO-Compress . A Python interface to zlib written by A.M. Kuchling is available in Python 1.5 and later versions, see @@ -64,7 +63,7 @@ Notes for some targets: - zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works when compiled with cc. -- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is +- On Digital Unix 4.0D (formerly OSF/1) on AlphaServer, the cc option -std1 is necessary to get gzprintf working correctly. This is done by configure. - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with @@ -84,7 +83,7 @@ Acknowledgments: Copyright notice: - (C) 1995-2022 Jean-loup Gailly and Mark Adler + (C) 1995-2023 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/zlib/adler32.c b/zlib/adler32.c index d0be4380a39..04b81d29bad 100644 --- a/zlib/adler32.c +++ b/zlib/adler32.c @@ -7,8 +7,6 @@ #include "zutil.h" -local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); - #define BASE 65521U /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ @@ -60,11 +58,7 @@ local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); #endif /* ========================================================================= */ -uLong ZEXPORT adler32_z(adler, buf, len) - uLong adler; - const Bytef *buf; - z_size_t len; -{ +uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) { unsigned long sum2; unsigned n; @@ -131,20 +125,12 @@ uLong ZEXPORT adler32_z(adler, buf, len) } /* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) - uLong adler; - const Bytef *buf; - uInt len; -{ +uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) { return adler32_z(adler, buf, len); } /* ========================================================================= */ -local uLong adler32_combine_(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off64_t len2; -{ +local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) { unsigned long sum1; unsigned long sum2; unsigned rem; @@ -169,18 +155,10 @@ local uLong adler32_combine_(adler1, adler2, len2) } /* ========================================================================= */ -uLong ZEXPORT adler32_combine(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off_t len2; -{ +uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) { return adler32_combine_(adler1, adler2, len2); } -uLong ZEXPORT adler32_combine64(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off64_t len2; -{ +uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) { return adler32_combine_(adler1, adler2, len2); } diff --git a/zlib/compress.c b/zlib/compress.c index 2ad5326c14e..f43bacf7ab9 100644 --- a/zlib/compress.c +++ b/zlib/compress.c @@ -19,13 +19,8 @@ memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ -int ZEXPORT compress2(dest, destLen, source, sourceLen, level) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; - int level; -{ +int ZEXPORT compress2(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen, int level) { z_stream stream; int err; const uInt max = (uInt)-1; @@ -65,12 +60,8 @@ int ZEXPORT compress2(dest, destLen, source, sourceLen, level) /* =========================================================================== */ -int ZEXPORT compress(dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ +int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen) { return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); } @@ -78,9 +69,7 @@ int ZEXPORT compress(dest, destLen, source, sourceLen) If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ -uLong ZEXPORT compressBound(sourceLen) - uLong sourceLen; -{ +uLong ZEXPORT compressBound(uLong sourceLen) { return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13; } diff --git a/zlib/configure b/zlib/configure index fa4d5daaba9..cc867c94474 100755 --- a/zlib/configure +++ b/zlib/configure @@ -44,8 +44,6 @@ STATICLIB=libz.a # extract zlib version numbers from zlib.h VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h` -VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}zlib.h` -VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h` VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h` # establish commands for library building @@ -90,7 +88,8 @@ build64=0 gcc=0 warn=0 debug=0 -sanitize=0 +address=0 +memory=0 old_cc="$CC" old_cflags="$CFLAGS" OBJC='$(OBJZ) $(OBJG)' @@ -102,7 +101,7 @@ leave() if test "$*" != "0"; then echo "** $0 aborting." | tee -a configure.log fi - rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version + rm -rf $test.[co] $test $test$shared_ext $test.gcno $test.dSYM ./--version echo -------------------- >> configure.log echo >> configure.log echo >> configure.log @@ -141,7 +140,9 @@ case "$1" in -c* | --const) zconst=1; shift ;; -w* | --warn) warn=1; shift ;; -d* | --debug) debug=1; shift ;; - --sanitize) sanitize=1; shift ;; + --sanitize) address=1; shift ;; + --address) address=1; shift ;; + --memory) memory=1; shift ;; *) echo "unknown option: $1" | tee -a configure.log echo "$0 --help for help" | tee -a configure.log @@ -211,8 +212,11 @@ if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then CFLAGS="${CFLAGS} -Wall -Wextra" fi fi - if test $sanitize -eq 1; then - CFLAGS="${CFLAGS} -g -fsanitize=address" + if test $address -eq 1; then + CFLAGS="${CFLAGS} -g -fsanitize=address -fno-omit-frame-pointer" + fi + if test $memory -eq 1; then + CFLAGS="${CFLAGS} -g -fsanitize=memory -fno-omit-frame-pointer" fi if test $debug -eq 1; then CFLAGS="${CFLAGS} -DZLIB_DEBUG" @@ -259,8 +263,10 @@ if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then SHAREDLIB=libz$shared_ext SHAREDLIBV=libz.$VER$shared_ext SHAREDLIBM=libz.$VER1$shared_ext - LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"} - if libtool -V 2>&1 | grep Apple > /dev/null; then + LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER"} + if "${CROSS_PREFIX}libtool" -V 2>&1 | grep Apple > /dev/null; then + AR="${CROSS_PREFIX}libtool" + elif libtool -V 2>&1 | grep Apple > /dev/null; then AR="libtool" else AR="/usr/bin/libtool" @@ -860,7 +866,7 @@ echo prefix = $prefix >> configure.log echo sharedlibdir = $sharedlibdir >> configure.log echo uname = $uname >> configure.log -# udpate Makefile with the configure results +# update Makefile with the configure results sed < ${SRCDIR}Makefile.in " /^CC *=/s#=.*#=$CC# /^CFLAGS *=/s#=.*#=$CFLAGS# diff --git a/zlib/contrib/ada/readme.txt b/zlib/contrib/ada/readme.txt index ce4d2cadf0d..efdd639fba3 100644 --- a/zlib/contrib/ada/readme.txt +++ b/zlib/contrib/ada/readme.txt @@ -8,8 +8,8 @@ It provides Ada-style access to the ZLib C library. Here are the main changes since ZLib.Ada 1.2: -- Attension: ZLib.Read generic routine have a initialization requirement - for Read_Last parameter now. It is a bit incompartible with previous version, +- Attention: ZLib.Read generic routine have a initialization requirement + for Read_Last parameter now. It is a bit incompatible with previous version, but extends functionality, we could use new parameters Allow_Read_Some and Flush now. diff --git a/zlib/contrib/ada/test.adb b/zlib/contrib/ada/test.adb index 90773acfa18..8b350315085 100644 --- a/zlib/contrib/ada/test.adb +++ b/zlib/contrib/ada/test.adb @@ -65,12 +65,12 @@ procedure Test is Time_Stamp : Ada.Calendar.Time; procedure Generate_File; - -- Generate file of spetsified size with some random data. + -- Generate file of specified size with some random data. -- The random data is repeatable, for the good compression. procedure Compare_Streams (Left, Right : in out Root_Stream_Type'Class); - -- The procedure compearing data in 2 streams. + -- The procedure comparing data in 2 streams. -- It is for compare data before and after compression/decompression. procedure Compare_Files (Left, Right : String); diff --git a/zlib/contrib/ada/zlib-streams.ads b/zlib/contrib/ada/zlib-streams.ads index 8e26cd45083..af136933e1d 100644 --- a/zlib/contrib/ada/zlib-streams.ads +++ b/zlib/contrib/ada/zlib-streams.ads @@ -62,7 +62,7 @@ package ZLib.Streams is := Default_Buffer_Size; Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset := Default_Buffer_Size); - -- Create the Comression/Decompression stream. + -- Create the Compression/Decompression stream. -- If mode is In_Stream then Write operation is disabled. -- If mode is Out_Stream then Read operation is disabled. diff --git a/zlib/contrib/ada/zlib.adb b/zlib/contrib/ada/zlib.adb index 8b6fd686ac7..c1abe791d61 100644 --- a/zlib/contrib/ada/zlib.adb +++ b/zlib/contrib/ada/zlib.adb @@ -204,7 +204,7 @@ package body ZLib is end if; -- We allow ZLib to make header only in case of default header type. - -- Otherwise we would either do header by ourselfs, or do not do + -- Otherwise we would either do header by ourselves, or do not do -- header at all. if Header = None or else Header = GZip then diff --git a/zlib/contrib/ada/zlib.ads b/zlib/contrib/ada/zlib.ads index 79ffc4095cf..81aaf1b6ae4 100644 --- a/zlib/contrib/ada/zlib.ads +++ b/zlib/contrib/ada/zlib.ads @@ -114,7 +114,7 @@ package ZLib is -- Compression strategy constants -- ------------------------------------ - -- RLE stategy could be used only in version 1.2.0 and later. + -- RLE strategy could be used only in version 1.2.0 and later. Filtered : constant Strategy_Type; Huffman_Only : constant Strategy_Type; diff --git a/zlib/contrib/delphi/ZLib.pas b/zlib/contrib/delphi/ZLib.pas index 8be5fa22c4c..814ffa6706a 100644 --- a/zlib/contrib/delphi/ZLib.pas +++ b/zlib/contrib/delphi/ZLib.pas @@ -152,7 +152,7 @@ procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; const OutBuf: Pointer; BufSize: Integer); const - zlib_version = '1.2.13'; + zlib_version = '1.3.0'; type EZlibError = class(Exception); diff --git a/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs b/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs index 788b2fceced..c1230bf031f 100644 --- a/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs +++ b/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs @@ -61,7 +61,7 @@ namespace DotZLib /// The sum of offset and count is larger than the length of data /// data is a null reference /// Offset or count is negative. - /// All the other Update methods are implmeneted in terms of this one. + /// All the other Update methods are implemented in terms of this one. /// This is therefore the only method a derived class has to implement public abstract void Update(byte[] data, int offset, int count); diff --git a/zlib/contrib/dotzlib/DotZLib/CodecBase.cs b/zlib/contrib/dotzlib/DotZLib/CodecBase.cs index 42e6da3a565..c4bc8b8796b 100644 --- a/zlib/contrib/dotzlib/DotZLib/CodecBase.cs +++ b/zlib/contrib/dotzlib/DotZLib/CodecBase.cs @@ -139,7 +139,7 @@ namespace DotZLib /// This must be implemented by a derived class protected abstract void CleanUp(); - // performs the release of the handles and calls the dereived CleanUp() + // performs the release of the handles and calls the derived CleanUp() private void CleanUp(bool isDisposing) { if (!_isDisposed) @@ -160,7 +160,7 @@ namespace DotZLib #region Helper methods /// - /// Copies a number of bytes to the internal codec buffer - ready for proccesing + /// Copies a number of bytes to the internal codec buffer - ready for processing /// /// The byte array that contains the data to copy /// The index of the first byte to copy diff --git a/zlib/contrib/dotzlib/DotZLib/GZipStream.cs b/zlib/contrib/dotzlib/DotZLib/GZipStream.cs index b161300b185..58091d3a3e2 100644 --- a/zlib/contrib/dotzlib/DotZLib/GZipStream.cs +++ b/zlib/contrib/dotzlib/DotZLib/GZipStream.cs @@ -246,7 +246,7 @@ namespace DotZLib } /// - /// Not suppported. + /// Not supported. /// /// /// @@ -268,7 +268,7 @@ namespace DotZLib } /// - /// Gets/sets the current position in the GZipStream. Not suppported. + /// Gets/sets the current position in the GZipStream. Not supported. /// /// In this implementation this property is not supported /// Always thrown @@ -285,7 +285,7 @@ namespace DotZLib } /// - /// Gets the size of the stream. Not suppported. + /// Gets the size of the stream. Not supported. /// /// In this implementation this property is not supported /// Always thrown diff --git a/zlib/contrib/dotzlib/DotZLib/UnitTests.cs b/zlib/contrib/dotzlib/DotZLib/UnitTests.cs index 16a0ebb072d..c5fce221a36 100644 --- a/zlib/contrib/dotzlib/DotZLib/UnitTests.cs +++ b/zlib/contrib/dotzlib/DotZLib/UnitTests.cs @@ -156,7 +156,7 @@ namespace DotZLibTests public void Info_Version() { Info info = new Info(); - Assert.AreEqual("1.2.13", Info.Version); + Assert.AreEqual("1.3.0", Info.Version); Assert.AreEqual(32, info.SizeOfUInt); Assert.AreEqual(32, info.SizeOfULong); Assert.AreEqual(32, info.SizeOfPointer); diff --git a/zlib/contrib/dotzlib/readme.txt b/zlib/contrib/dotzlib/readme.txt index b2395720d4c..47454fce37d 100644 --- a/zlib/contrib/dotzlib/readme.txt +++ b/zlib/contrib/dotzlib/readme.txt @@ -36,7 +36,7 @@ Build instructions: in the same directory as the DotZLib.build file. You can define 2 properties on the nant command-line to control the build: debug={true|false} to toggle between release/debug builds (default=true). - nunit={true|false} to include or esclude unit tests (default=true). + nunit={true|false} to include or exclude unit tests (default=true). Also the target clean will remove binaries. Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on whether you are building the release diff --git a/zlib/contrib/infback9/infback9.c b/zlib/contrib/infback9/infback9.c index 05fb3e33807..742a39214ab 100644 --- a/zlib/contrib/infback9/infback9.c +++ b/zlib/contrib/infback9/infback9.c @@ -16,12 +16,8 @@ window is a user-supplied window and output buffer that is 64K bytes. */ -int ZEXPORT inflateBack9Init_(strm, window, version, stream_size) -z_stream FAR *strm; -unsigned char FAR *window; -const char *version; -int stream_size; -{ +int ZEXPORT inflateBack9Init_(z_stream FAR *strm, unsigned char FAR *window, + const char *version, int stream_size) { struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || @@ -51,8 +47,7 @@ int stream_size; #ifdef MAKEFIXED #include -void makefixed9(void) -{ +void makefixed9(void) { unsigned sym, bits, low, size; code *next, *lenfix, *distfix; struct inflate_state state; @@ -214,13 +209,8 @@ void makefixed9(void) inflateBack() can also return Z_STREAM_ERROR if the input parameters are not correct, i.e. strm is Z_NULL or the state was not initialized. */ -int ZEXPORT inflateBack9(strm, in, in_desc, out, out_desc) -z_stream FAR *strm; -in_func in; -void FAR *in_desc; -out_func out; -void FAR *out_desc; -{ +int ZEXPORT inflateBack9(z_stream FAR *strm, in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc) { struct inflate_state FAR *state; z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ @@ -603,9 +593,7 @@ void FAR *out_desc; return ret; } -int ZEXPORT inflateBack9End(strm) -z_stream FAR *strm; -{ +int ZEXPORT inflateBack9End(z_stream FAR *strm) { if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; ZFREE(strm, strm->state); diff --git a/zlib/contrib/infback9/infback9.h b/zlib/contrib/infback9/infback9.h index 1073c0a38e6..8371b4ec7d2 100644 --- a/zlib/contrib/infback9/infback9.h +++ b/zlib/contrib/infback9/infback9.h @@ -20,14 +20,14 @@ extern "C" { #endif -ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -ZEXTERN int ZEXPORT inflateBack9End OF((z_stream FAR *strm)); -ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm, - unsigned char FAR *window, - const char *version, - int stream_size)); +ZEXTERN int ZEXPORT inflateBack9(z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc); +ZEXTERN int ZEXPORT inflateBack9End(z_stream FAR *strm); +ZEXTERN int ZEXPORT inflateBack9Init_(z_stream FAR *strm, + unsigned char FAR *window, + const char *version, + int stream_size); #define inflateBack9Init(strm, window) \ inflateBack9Init_((strm), (window), \ ZLIB_VERSION, sizeof(z_stream)) diff --git a/zlib/contrib/infback9/inftree9.c b/zlib/contrib/infback9/inftree9.c index 10827a6aa01..dc38f24de96 100644 --- a/zlib/contrib/infback9/inftree9.c +++ b/zlib/contrib/infback9/inftree9.c @@ -1,5 +1,5 @@ /* inftree9.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2022 Mark Adler + * Copyright (C) 1995-2023 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate9_copyright[] = - " inflate9 1.2.13 Copyright 1995-2022 Mark Adler "; + " inflate9 1.3 Copyright 1995-2023 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -29,14 +29,9 @@ const char inflate9_copyright[] = table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ -int inflate_table9(type, lens, codes, table, bits, work) -codetype type; -unsigned short FAR *lens; -unsigned codes; -code FAR * FAR *table; -unsigned FAR *bits; -unsigned short FAR *work; -{ +int inflate_table9(codetype type, unsigned short FAR *lens, unsigned codes, + code FAR * FAR *table, unsigned FAR *bits, + unsigned short FAR *work) { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ unsigned min, max; /* minimum and maximum code lengths */ @@ -64,7 +59,7 @@ unsigned short FAR *work; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, - 133, 133, 133, 133, 144, 194, 65}; + 133, 133, 133, 133, 144, 198, 203}; static const unsigned short dbase[32] = { /* Distance codes 0..31 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, diff --git a/zlib/contrib/infback9/inftree9.h b/zlib/contrib/infback9/inftree9.h index 3b394978e3f..2c1252f57de 100644 --- a/zlib/contrib/infback9/inftree9.h +++ b/zlib/contrib/infback9/inftree9.h @@ -56,6 +56,6 @@ typedef enum { DISTS } codetype; -extern int inflate_table9 OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); +extern int inflate_table9(codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work); diff --git a/zlib/contrib/minizip/MiniZip64_Changes.txt b/zlib/contrib/minizip/MiniZip64_Changes.txt index 13a1bd91a9b..3759468113b 100644 --- a/zlib/contrib/minizip/MiniZip64_Changes.txt +++ b/zlib/contrib/minizip/MiniZip64_Changes.txt @@ -1,5 +1,5 @@ -MiniZip 1.1 was derrived from MiniZip at version 1.01f +MiniZip 1.1 was derived from MiniZip at version 1.01f Change in 1.0 (Okt 2009) - **TODO - Add history** diff --git a/zlib/contrib/minizip/configure.ac b/zlib/contrib/minizip/configure.ac index bff300b3045..df80e5b7e13 100644 --- a/zlib/contrib/minizip/configure.ac +++ b/zlib/contrib/minizip/configure.ac @@ -1,7 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. -AC_INIT([minizip], [1.2.13], [bugzilla.redhat.com]) +AC_INIT([minizip], [1.3.0], [bugzilla.redhat.com]) AC_CONFIG_SRCDIR([minizip.c]) AM_INIT_AUTOMAKE([foreign]) LT_INIT diff --git a/zlib/contrib/minizip/crypt.h b/zlib/contrib/minizip/crypt.h index 1cc41f19d78..f4b93b78dc3 100644 --- a/zlib/contrib/minizip/crypt.h +++ b/zlib/contrib/minizip/crypt.h @@ -32,8 +32,7 @@ /*********************************************************************** * Return the next byte in the pseudo-random sequence */ -static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) -{ +static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) { unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an * unpredictable manner on 16-bit systems; not a problem * with any known compiler so far, though */ @@ -46,8 +45,7 @@ static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) /*********************************************************************** * Update the encryption keys with the next byte of plain text */ -static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) -{ +static int update_keys(unsigned long* pkeys, const z_crc_t* pcrc_32_tab, int c) { (*(pkeys+0)) = CRC32((*(pkeys+0)), c); (*(pkeys+1)) += (*(pkeys+0)) & 0xff; (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; @@ -63,8 +61,7 @@ static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) * Initialize the encryption keys and the random header according to * the given password. */ -static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab) -{ +static void init_keys(const char* passwd, unsigned long* pkeys, const z_crc_t* pcrc_32_tab) { *(pkeys+0) = 305419896L; *(pkeys+1) = 591751049L; *(pkeys+2) = 878082192L; @@ -93,8 +90,7 @@ static unsigned crypthead(const char* passwd, /* password string */ int bufSize, unsigned long* pkeys, const z_crc_t* pcrc_32_tab, - unsigned long crcForCrypting) -{ + unsigned long crcForCrypting) { unsigned n; /* index in random header */ int t; /* temporary */ int c; /* random byte */ diff --git a/zlib/contrib/minizip/ioapi.c b/zlib/contrib/minizip/ioapi.c index 814a6fd38c2..782d32469ae 100644 --- a/zlib/contrib/minizip/ioapi.c +++ b/zlib/contrib/minizip/ioapi.c @@ -14,7 +14,7 @@ #define _CRT_SECURE_NO_WARNINGS #endif -#if defined(__APPLE__) || defined(IOAPI_NO_64) +#if defined(__APPLE__) || defined(IOAPI_NO_64) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64) // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions #define FOPEN_FUNC(filename, mode) fopen(filename, mode) #define FTELLO_FUNC(stream) ftello(stream) @@ -28,8 +28,7 @@ #include "ioapi.h" -voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) -{ +voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc, const void*filename, int mode) { if (pfilefunc->zfile_func64.zopen64_file != NULL) return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); else @@ -38,8 +37,7 @@ voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename } } -long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) -{ +long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) { if (pfilefunc->zfile_func64.zseek64_file != NULL) return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); else @@ -52,8 +50,7 @@ long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZP } } -ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) -{ +ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc, voidpf filestream) { if (pfilefunc->zfile_func64.zseek64_file != NULL) return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); else @@ -66,11 +63,9 @@ ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream } } -void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) -{ +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32, const zlib_filefunc_def* p_filefunc32) { p_filefunc64_32->zfile_func64.zopen64_file = NULL; p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; - p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; p_filefunc64_32->zfile_func64.ztell64_file = NULL; @@ -84,16 +79,7 @@ void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filef -static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); -static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); -static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); -static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); -static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); - -static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) -{ +static voidpf ZCALLBACK fopen_file_func(voidpf opaque, const char* filename, int mode) { FILE* file = NULL; const char* mode_fopen = NULL; (void)opaque; @@ -111,8 +97,7 @@ static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, in return file; } -static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) -{ +static voidpf ZCALLBACK fopen64_file_func(voidpf opaque, const void* filename, int mode) { FILE* file = NULL; const char* mode_fopen = NULL; (void)opaque; @@ -131,24 +116,21 @@ static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, } -static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) -{ +static uLong ZCALLBACK fread_file_func(voidpf opaque, voidpf stream, void* buf, uLong size) { uLong ret; (void)opaque; ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); return ret; } -static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) -{ +static uLong ZCALLBACK fwrite_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) { uLong ret; (void)opaque; ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); return ret; } -static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) -{ +static long ZCALLBACK ftell_file_func(voidpf opaque, voidpf stream) { long ret; (void)opaque; ret = ftell((FILE *)stream); @@ -156,16 +138,14 @@ static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) } -static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) -{ +static ZPOS64_T ZCALLBACK ftell64_file_func(voidpf opaque, voidpf stream) { ZPOS64_T ret; (void)opaque; ret = (ZPOS64_T)FTELLO_FUNC((FILE *)stream); return ret; } -static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) -{ +static long ZCALLBACK fseek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin) { int fseek_origin=0; long ret; (void)opaque; @@ -188,8 +168,7 @@ static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offs return ret; } -static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) -{ +static long ZCALLBACK fseek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) { int fseek_origin=0; long ret; (void)opaque; @@ -208,32 +187,28 @@ static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T } ret = 0; - if(FSEEKO_FUNC((FILE *)stream, (z_off_t)offset, fseek_origin) != 0) + if(FSEEKO_FUNC((FILE *)stream, (z_off64_t)offset, fseek_origin) != 0) ret = -1; return ret; } -static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) -{ +static int ZCALLBACK fclose_file_func(voidpf opaque, voidpf stream) { int ret; (void)opaque; ret = fclose((FILE *)stream); return ret; } -static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) -{ +static int ZCALLBACK ferror_file_func(voidpf opaque, voidpf stream) { int ret; (void)opaque; ret = ferror((FILE *)stream); return ret; } -void fill_fopen_filefunc (pzlib_filefunc_def) - zlib_filefunc_def* pzlib_filefunc_def; -{ +void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen_file = fopen_file_func; pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func; @@ -244,8 +219,7 @@ void fill_fopen_filefunc (pzlib_filefunc_def) pzlib_filefunc_def->opaque = NULL; } -void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) -{ +void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = fopen64_file_func; pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func; diff --git a/zlib/contrib/minizip/ioapi.h b/zlib/contrib/minizip/ioapi.h index ae9ca7e8337..c588a18d034 100644 --- a/zlib/contrib/minizip/ioapi.h +++ b/zlib/contrib/minizip/ioapi.h @@ -50,7 +50,7 @@ #define ftello64 ftell #define fseeko64 fseek #else -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64) #define fopen64 fopen #define ftello64 ftello #define fseeko64 fseeko @@ -82,7 +82,7 @@ #include "mz64conf.h" #endif -/* a type choosen by DEFINE */ +/* a type chosen by DEFINE */ #ifdef HAVE_64BIT_INT_CUSTOM typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; #else @@ -134,14 +134,14 @@ extern "C" { -typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); -typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); -typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); +typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode); +typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size); +typedef uLong (ZCALLBACK *write_file_func) (voidpf opaque, voidpf stream, const void* buf, uLong size); +typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream); +typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream); -typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); +typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream); +typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin); /* here is the "old" 32 bits structure structure */ @@ -157,9 +157,9 @@ typedef struct zlib_filefunc_def_s voidpf opaque; } zlib_filefunc_def; -typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); +typedef ZPOS64_T (ZCALLBACK *tell64_file_func) (voidpf opaque, voidpf stream); +typedef long (ZCALLBACK *seek64_file_func) (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin); +typedef voidpf (ZCALLBACK *open64_file_func) (voidpf opaque, const void* filename, int mode); typedef struct zlib_filefunc64_def_s { @@ -173,8 +173,8 @@ typedef struct zlib_filefunc64_def_s voidpf opaque; } zlib_filefunc64_def; -void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); +void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def); +void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def); /* now internal definition, only for zip.c and unzip.h */ typedef struct zlib_filefunc64_32_def_s @@ -193,11 +193,11 @@ typedef struct zlib_filefunc64_32_def_s #define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) #define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) -voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); -long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); -ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); +voidpf call_zopen64(const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode); +long call_zseek64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin); +ZPOS64_T call_ztell64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream); -void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); #define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) #define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) diff --git a/zlib/contrib/minizip/iowin32.c b/zlib/contrib/minizip/iowin32.c index 7df525172b2..08536e94b8a 100644 --- a/zlib/contrib/minizip/iowin32.c +++ b/zlib/contrib/minizip/iowin32.c @@ -38,14 +38,6 @@ #endif #endif -voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); -uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -uLong ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -ZPOS64_T ZCALLBACK win32_tell64_file_func OF((voidpf opaque, voidpf stream)); -long ZCALLBACK win32_seek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -int ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream)); -int ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream)); - typedef struct { HANDLE hf; @@ -57,8 +49,7 @@ static void win32_translate_open_mode(int mode, DWORD* lpdwDesiredAccess, DWORD* lpdwCreationDisposition, DWORD* lpdwShareMode, - DWORD* lpdwFlagsAndAttributes) -{ + DWORD* lpdwFlagsAndAttributes) { *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0; if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) @@ -79,8 +70,7 @@ static void win32_translate_open_mode(int mode, } } -static voidpf win32_build_iowin(HANDLE hFile) -{ +static voidpf win32_build_iowin(HANDLE hFile) { voidpf ret=NULL; if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) @@ -98,8 +88,7 @@ static voidpf win32_build_iowin(HANDLE hFile) return ret; } -voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode) -{ +voidpf ZCALLBACK win32_open64_file_func(voidpf opaque, const void* filename, int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; @@ -127,8 +116,7 @@ voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int } -voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode) -{ +voidpf ZCALLBACK win32_open64_file_funcA(voidpf opaque, const void* filename, int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; @@ -151,8 +139,7 @@ voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int } -voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode) -{ +voidpf ZCALLBACK win32_open64_file_funcW(voidpf opaque, const void* filename, int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; @@ -171,8 +158,7 @@ voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int } -voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode) -{ +voidpf ZCALLBACK win32_open_file_func(voidpf opaque, const char* filename, int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; @@ -200,8 +186,7 @@ voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mo } -uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size) -{ +uLong ZCALLBACK win32_read_file_func(voidpf opaque, voidpf stream, void* buf,uLong size) { uLong ret=0; HANDLE hFile = NULL; if (stream!=NULL) @@ -222,8 +207,7 @@ uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uL } -uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size) -{ +uLong ZCALLBACK win32_write_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) { uLong ret=0; HANDLE hFile = NULL; if (stream!=NULL) @@ -243,8 +227,7 @@ uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* b return ret; } -static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) -{ +static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) { #ifdef IOWIN32_USING_WINRT_API return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod); #else @@ -263,8 +246,7 @@ static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *n #endif } -long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) -{ +long ZCALLBACK win32_tell_file_func(voidpf opaque, voidpf stream) { long ret=-1; HANDLE hFile = NULL; if (stream!=NULL) @@ -286,8 +268,7 @@ long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) return ret; } -ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) -{ +ZPOS64_T ZCALLBACK win32_tell64_file_func(voidpf opaque, voidpf stream) { ZPOS64_T ret= (ZPOS64_T)-1; HANDLE hFile = NULL; if (stream!=NULL) @@ -311,8 +292,7 @@ ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) } -long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin) -{ +long ZCALLBACK win32_seek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin) { DWORD dwMoveMethod=0xFFFFFFFF; HANDLE hFile = NULL; @@ -349,8 +329,7 @@ long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,in return ret; } -long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin) -{ +long ZCALLBACK win32_seek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) { DWORD dwMoveMethod=0xFFFFFFFF; HANDLE hFile = NULL; long ret=-1; @@ -388,8 +367,7 @@ long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T off return ret; } -int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream) -{ +int ZCALLBACK win32_close_file_func(voidpf opaque, voidpf stream) { int ret=-1; if (stream!=NULL) @@ -406,8 +384,7 @@ int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream) return ret; } -int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream) -{ +int ZCALLBACK win32_error_file_func(voidpf opaque, voidpf stream) { int ret=-1; if (stream!=NULL) { @@ -416,8 +393,7 @@ int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream) return ret; } -void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def) -{ +void fill_win32_filefunc(zlib_filefunc_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen_file = win32_open_file_func; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; @@ -428,8 +404,7 @@ void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def) pzlib_filefunc_def->opaque = NULL; } -void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) -{ +void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = win32_open64_file_func; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; @@ -441,8 +416,7 @@ void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) } -void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) -{ +void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; @@ -454,8 +428,7 @@ void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) } -void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) -{ +void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; diff --git a/zlib/contrib/minizip/iowin32.h b/zlib/contrib/minizip/iowin32.h index 0ca0969a7d0..a23a65d4331 100644 --- a/zlib/contrib/minizip/iowin32.h +++ b/zlib/contrib/minizip/iowin32.h @@ -18,10 +18,10 @@ extern "C" { #endif -void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); -void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_win32_filefunc(zlib_filefunc_def* pzlib_filefunc_def); +void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def); +void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def); +void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def); #ifdef __cplusplus } diff --git a/zlib/contrib/minizip/miniunz.c b/zlib/contrib/minizip/miniunz.c index 0dc9b50815a..a12aec8bea2 100644 --- a/zlib/contrib/minizip/miniunz.c +++ b/zlib/contrib/minizip/miniunz.c @@ -27,7 +27,7 @@ #endif #endif -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64) // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions #define FOPEN_FUNC(filename, mode) fopen(filename, mode) #define FTELLO_FUNC(stream) ftello(stream) @@ -81,11 +81,7 @@ filename : the filename of the file where date/time must be modified dosdate : the new date at the MSDos format (4 bytes) tmu_date : the SAME new date at the tm_unz format */ -static void change_file_date(filename,dosdate,tmu_date) - const char *filename; - uLong dosdate; - tm_unz tmu_date; -{ +static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date) { #ifdef _WIN32 HANDLE hFile; FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; @@ -115,6 +111,10 @@ static void change_file_date(filename,dosdate,tmu_date) ut.actime=ut.modtime=mktime(&newdate); utime(filename,&ut); +#else + (void)filename; + (void)dosdate; + (void)tmu_date; #endif #endif } @@ -123,9 +123,7 @@ static void change_file_date(filename,dosdate,tmu_date) /* mymkdir and change_file_date are not 100 % portable As I don't know well Unix, I wait feedback for the unix portion */ -static int mymkdir(dirname) - const char* dirname; -{ +static int mymkdir(const char* dirname) { int ret=0; #ifdef _WIN32 ret = _mkdir(dirname); @@ -133,13 +131,13 @@ static int mymkdir(dirname) ret = mkdir (dirname,0775); #elif __APPLE__ ret = mkdir (dirname,0775); +#else + (void)dirname; #endif return ret; } -static int makedir (newdir) - const char *newdir; -{ +static int makedir(const char *newdir) { char *buffer ; char *p; size_t len = strlen(newdir); @@ -187,14 +185,12 @@ static int makedir (newdir) return 1; } -static void do_banner() -{ +static void do_banner(void) { printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); } -static void do_help() -{ +static void do_help(void) { printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ " -e Extract without pathname (junk paths)\n" \ " -x Extract with pathname\n" \ @@ -202,11 +198,10 @@ static void do_help() " -l list files\n" \ " -d directory to extract into\n" \ " -o overwrite files without prompting\n" \ - " -p extract crypted file using password\n\n"); + " -p extract encrypted file using password\n\n"); } -static void Display64BitsSize(ZPOS64_T n, int size_char) -{ +static void Display64BitsSize(ZPOS64_T n, int size_char) { /* to avoid compatibility problem , we do here the conversion */ char number[21]; int offset=19; @@ -233,9 +228,7 @@ static void Display64BitsSize(ZPOS64_T n, int size_char) printf("%s",&number[pos_string]); } -static int do_list(uf) - unzFile uf; -{ +static int do_list(unzFile uf) { uLong i; unz_global_info64 gi; int err; @@ -250,7 +243,7 @@ static int do_list(uf) char filename_inzip[256]; unz_file_info64 file_info; uLong ratio=0; - const char *string_method; + const char *string_method = ""; char charCrypt=' '; err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); if (err!=UNZ_OK) @@ -261,7 +254,7 @@ static int do_list(uf) if (file_info.uncompressed_size>0) ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size); - /* display a '*' if the file is crypted */ + /* display a '*' if the file is encrypted */ if ((file_info.flag & 1) != 0) charCrypt='*'; @@ -311,12 +304,7 @@ static int do_list(uf) } -static int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password) - unzFile uf; - const int* popt_extract_without_path; - int* popt_overwrite; - const char* password; -{ +static int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, int* popt_overwrite, const char* password) { char filename_inzip[256]; char* filename_withoutpath; char* p; @@ -473,12 +461,7 @@ static int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,pa } -static int do_extract(uf,opt_extract_without_path,opt_overwrite,password) - unzFile uf; - int opt_extract_without_path; - int opt_overwrite; - const char* password; -{ +static int do_extract(unzFile uf, int opt_extract_without_path, int opt_overwrite, const char* password) { uLong i; unz_global_info64 gi; int err; @@ -508,13 +491,7 @@ static int do_extract(uf,opt_extract_without_path,opt_overwrite,password) return 0; } -static int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite,password) - unzFile uf; - const char* filename; - int opt_extract_without_path; - int opt_overwrite; - const char* password; -{ +static int do_extract_onefile(unzFile uf, const char* filename, int opt_extract_without_path, int opt_overwrite, const char* password) { if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK) { printf("file %s not found in the zipfile\n",filename); @@ -530,10 +507,7 @@ static int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite } -int main(argc,argv) - int argc; - char *argv[]; -{ +int main(int argc, char *argv[]) { const char *zipfilename=NULL; const char *filename_to_extract=NULL; const char *password=NULL; @@ -606,7 +580,7 @@ int main(argc,argv) # endif strncpy(filename_try, zipfilename,MAXFILENAME-1); - /* strncpy doesnt append the trailing NULL, of the string is too long. */ + /* strncpy doesn't append the trailing NULL, of the string is too long. */ filename_try[ MAXFILENAME ] = '\0'; # ifdef USEWIN32IOAPI diff --git a/zlib/contrib/minizip/minizip.c b/zlib/contrib/minizip/minizip.c index e8561b15f91..26ee8d029ef 100644 --- a/zlib/contrib/minizip/minizip.c +++ b/zlib/contrib/minizip/minizip.c @@ -28,7 +28,7 @@ #endif #endif -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64) // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions #define FOPEN_FUNC(filename, mode) fopen(filename, mode) #define FTELLO_FUNC(stream) ftello(stream) @@ -71,11 +71,9 @@ #define MAXFILENAME (256) #ifdef _WIN32 -static int filetime(f, tmzip, dt) - const char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ +/* f: name of file to get info on, tmzip: return value: access, + modification and creation times, dt: dostime */ +static int filetime(const char *f, tm_zip *tmzip, uLong *dt) { int ret = 0; { FILETIME ftLocal; @@ -95,11 +93,9 @@ static int filetime(f, tmzip, dt) } #else #if defined(unix) || defined(__APPLE__) -static int filetime(f, tmzip, dt) - const char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ +/* f: name of file to get info on, tmzip: return value: access, + modification and creation times, dt: dostime */ +static int filetime(const char *f, tm_zip *tmzip, uLong *dt) { (void)dt; int ret=0; struct stat s; /* results of stat() */ @@ -114,7 +110,7 @@ static int filetime(f, tmzip, dt) len = MAXFILENAME; strncpy(name, f,MAXFILENAME-1); - /* strncpy doesnt append the trailing NULL, of the string is too long. */ + /* strncpy doesn't append the trailing NULL, of the string is too long. */ name[ MAXFILENAME ] = '\0'; if (name[len - 1] == '/') @@ -138,11 +134,12 @@ static int filetime(f, tmzip, dt) return ret; } #else -uLong filetime(f, tmzip, dt) - const char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ +/* f: name of file to get info on, tmzip: return value: access, + modification and creation times, dt: dostime */ +static int filetime(const char *f, tm_zip *tmzip, uLong *dt) { + (void)f; + (void)tmzip; + (void)dt; return 0; } #endif @@ -151,9 +148,7 @@ uLong filetime(f, tmzip, dt) -static int check_exist_file(filename) - const char* filename; -{ +static int check_exist_file(const char* filename) { FILE* ftestexist; int ret = 1; ftestexist = FOPEN_FUNC(filename,"rb"); @@ -164,14 +159,12 @@ static int check_exist_file(filename) return ret; } -static void do_banner() -{ +static void do_banner(void) { printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n"); printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n"); } -static void do_help() -{ +static void do_help(void) { printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \ " -o Overwrite existing file.zip\n" \ " -a Append to existing file.zip\n" \ @@ -183,8 +176,7 @@ static void do_help() /* calculate the CRC32 of a file, because to encrypt a file, we need known the CRC32 of the file before */ -static int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) -{ +static int getFileCrc(const char* filenameinzip, void* buf, unsigned long size_buf, unsigned long* result_crc) { unsigned long calculate_crc=0; int err=ZIP_OK; FILE * fin = FOPEN_FUNC(filenameinzip,"rb"); @@ -222,8 +214,7 @@ static int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf, return err; } -static int isLargeFile(const char* filename) -{ +static int isLargeFile(const char* filename) { int largeFile = 0; ZPOS64_T pos = 0; FILE* pFile = FOPEN_FUNC(filename, "rb"); @@ -233,7 +224,7 @@ static int isLargeFile(const char* filename) FSEEKO_FUNC(pFile, 0, SEEK_END); pos = (ZPOS64_T)FTELLO_FUNC(pFile); - printf("File : %s is %lld bytes\n", filename, pos); + printf("File : %s is %llu bytes\n", filename, pos); if(pos >= 0xffffffff) largeFile = 1; @@ -244,10 +235,7 @@ static int isLargeFile(const char* filename) return largeFile; } -int main(argc,argv) - int argc; - char *argv[]; -{ +int main(int argc, char *argv[]) { int i; int opt_overwrite=0; int opt_compress_level=Z_DEFAULT_COMPRESSION; @@ -323,7 +311,7 @@ int main(argc,argv) zipok = 1 ; strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1); - /* strncpy doesnt append the trailing NULL, of the string is too long. */ + /* strncpy doesn't append the trailing NULL, of the string is too long. */ filename_try[ MAXFILENAME ] = '\0'; len=(int)strlen(filename_try); @@ -393,10 +381,10 @@ int main(argc,argv) ((argv[i][1]=='o') || (argv[i][1]=='O') || (argv[i][1]=='a') || (argv[i][1]=='A') || (argv[i][1]=='p') || (argv[i][1]=='P') || - ((argv[i][1]>='0') || (argv[i][1]<='9'))) && + ((argv[i][1]>='0') && (argv[i][1]<='9'))) && (strlen(argv[i]) == 2))) { - FILE * fin; + FILE * fin = NULL; size_t size_read; const char* filenameinzip = argv[i]; const char *savefilenameinzip; diff --git a/zlib/contrib/minizip/mztools.c b/zlib/contrib/minizip/mztools.c index 96891c2e0b7..c8d23756155 100644 --- a/zlib/contrib/minizip/mztools.c +++ b/zlib/contrib/minizip/mztools.c @@ -27,13 +27,7 @@ WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ } while(0) -extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) -const char* file; -const char* fileOut; -const char* fileOutTmp; -uLong* nRecovered; -uLong* bytesRecovered; -{ +extern int ZEXPORT unzRepair(const char* file, const char* fileOut, const char* fileOutTmp, uLong* nRecovered, uLong* bytesRecovered) { int err = Z_OK; FILE* fpZip = fopen(file, "rb"); FILE* fpOut = fopen(fileOut, "wb"); diff --git a/zlib/contrib/minizip/unzip.c b/zlib/contrib/minizip/unzip.c index 3036b470b72..ed763f89f1f 100644 --- a/zlib/contrib/minizip/unzip.c +++ b/zlib/contrib/minizip/unzip.c @@ -49,12 +49,12 @@ Copyright (C) 2007-2008 Even Rouault - Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). + Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G should only read the compressed/uncompressed size from the Zip64 format if the size from normal header was 0xFFFFFFFF - Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant - Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) + Oct-2009 - Mathias Svensson - Applied some bug fixes from patches received from Gilles Vollant + Oct-2009 - Mathias Svensson - Applied support to unzip files with compression method BZIP2 (bzip2 lib is required) Patch created by Daniel Borca Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer @@ -77,8 +77,6 @@ #ifdef STDC # include -# include -# include #endif #ifdef NO_ERRNO_H extern int errno; @@ -111,9 +109,6 @@ #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif -#ifndef TRYFREE -# define TRYFREE(p) { free(p);} -#endif #define SIZECENTRALDIRITEM (0x2e) #define SIZEZIPLOCALHEADER (0x1e) @@ -153,7 +148,7 @@ typedef struct ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ + voidpf filestream; /* io structure of the zipfile */ uLong compression_method; /* compression method (0==store) */ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ int raw; @@ -166,7 +161,7 @@ typedef struct { zlib_filefunc64_32_def z_filefunc; int is64bitOpenFunction; - voidpf filestream; /* io structore of the zipfile */ + voidpf filestream; /* io structure of the zipfile */ unz_global_info64 gi; /* public global information */ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ ZPOS64_T num_file; /* number of the current file in the zipfile*/ @@ -197,29 +192,44 @@ typedef struct #include "crypt.h" #endif + /* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been successfully opened for reading. + Reads a long in LSB order from the given gz_stream. Sets */ - -local int unz64local_getByte OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - int *pi)); - -local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) -{ - unsigned char c; - int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) +local int unz64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) { + unsigned char c[2]; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,2); + if (err==2) { - *pi = (int)c; + *pX = c[0] | ((uLong)c[1] << 8); return UNZ_OK; } else { + *pX = 0; + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + +local int unz64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) { + unsigned char c[4]; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,4); + if (err==4) + { + *pX = c[0] | ((uLong)c[1] << 8) | ((uLong)c[2] << 16) | ((uLong)c[3] << 24); + return UNZ_OK; + } + else + { + *pX = 0; if (ZERROR64(*pzlib_filefunc_def,filestream)) return UNZ_ERRNO; else @@ -228,126 +238,29 @@ local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, v } -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unz64local_getShort OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX) -{ - uLong x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; +local int unz64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX) { + unsigned char c[8]; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,8); + if (err==8) + { + *pX = c[0] | ((ZPOS64_T)c[1] << 8) | ((ZPOS64_T)c[2] << 16) | ((ZPOS64_T)c[3] << 24) + | ((ZPOS64_T)c[4] << 32) | ((ZPOS64_T)c[5] << 40) | ((ZPOS64_T)c[6] << 48) | ((ZPOS64_T)c[7] << 56); + return UNZ_OK; + } else + { *pX = 0; - return err; -} - -local int unz64local_getLong OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX) -{ - uLong x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unz64local_getLong64 OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - ZPOS64_T *pX)); - - -local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - ZPOS64_T *pX) -{ - ZPOS64_T x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (ZPOS64_T)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<8; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<16; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<24; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<32; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<40; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<48; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<56; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } } /* My own strcmpi / strcasecmp */ -local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) -{ +local int strcmpcasenosensitive_internal(const char* fileName1, const char* fileName2) { for (;;) { char c1=*(fileName1++); @@ -379,19 +292,17 @@ local int strcmpcasenosensitive_internal (const char* fileName1, const char* fil #endif /* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + Compare two filenames (fileName1,fileName2). + If iCaseSensitivity = 1, comparison is case sensitive (like strcmp) + If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + If iCaseSensitivity = 0, case sensitivity is default of your operating system (like 1 on Unix, 2 on Windows) */ extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, - const char* fileName2, - int iCaseSensitivity) - -{ + const char* fileName2, + int iCaseSensitivity) { if (iCaseSensitivity==0) iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; @@ -405,21 +316,23 @@ extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, #define BUFREADCOMMENT (0x400) #endif +#ifndef CENTRALDIRINVALID +#define CENTRALDIRINVALID ((ZPOS64_T)(-1)) +#endif + /* Locate the Central directory of a zipfile (at the end, just before the global comment) */ -local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); -local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ +local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; + ZPOS64_T uPosFound=CENTRALDIRINVALID; if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; + return CENTRALDIRINVALID; uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); @@ -429,7 +342,7 @@ local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) - return 0; + return CENTRALDIRINVALID; uBackRead = 4; while (uBackReadz_filefunc, s->filestream); - TRYFREE(s); + free(s); return UNZ_OK; } @@ -825,8 +727,7 @@ extern int ZEXPORT unzClose (unzFile file) Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) -{ +extern int ZEXPORT unzGetGlobalInfo64(unzFile file, unz_global_info64* pglobal_info) { unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; @@ -835,8 +736,7 @@ extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_ return UNZ_OK; } -extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) -{ +extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32) { unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; @@ -847,10 +747,9 @@ extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info return UNZ_OK; } /* - Translate date/time from Dos format to tm_unz (readable more easilty) + Translate date/time from Dos format to tm_unz (readable more easily) */ -local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) -{ +local void unz64local_DosDateToTmuDate(ZPOS64_T ulDosDate, tm_unz* ptm) { ZPOS64_T uDate; uDate = (ZPOS64_T)(ulDosDate>>16); ptm->tm_mday = (int)(uDate&0x1f) ; @@ -865,28 +764,16 @@ local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) /* Get Info about the current file in the zipfile, with internal only info */ -local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, - unz_file_info64 *pfile_info, - unz_file_info64_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); - -local int unz64local_GetCurrentFileInfoInternal (unzFile file, - unz_file_info64 *pfile_info, - unz_file_info64_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize) -{ +local int unz64local_GetCurrentFileInfoInternal(unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) { unz64_s* s; unz_file_info64 file_info; unz_file_info64_internal file_info_internal; @@ -1038,33 +925,31 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file, /* ZIP64 extra fields */ if (headerId == 0x0001) { - uLong uL; + if(file_info.uncompressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } - if(file_info.uncompressed_size == MAXU32) - { - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - } + if(file_info.compressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } - if(file_info.compressed_size == MAXU32) - { - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - } + if(file_info_internal.offset_curfile == MAXU32) + { + /* Relative Header offset */ + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + } - if(file_info_internal.offset_curfile == MAXU32) - { - /* Relative Header offset */ - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - } - - if(file_info.disk_num_start == MAXU32) - { - /* Disk Start Number */ - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - } + if(file_info.disk_num_start == 0xffff) + { + /* Disk Start Number */ + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + } } else @@ -1121,24 +1006,22 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file, No preparation of the structure is needed return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, - unz_file_info64 * pfile_info, - char * szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char* szComment, uLong commentBufferSize) -{ +extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file, + unz_file_info64 * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) { return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); } -extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, - unz_file_info * pfile_info, - char * szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char* szComment, uLong commentBufferSize) -{ +extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, + unz_file_info * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) { int err; unz_file_info64 file_info64; err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, @@ -1162,7 +1045,7 @@ extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, pfile_info->internal_fa = file_info64.internal_fa; pfile_info->external_fa = file_info64.external_fa; - pfile_info->tmu_date = file_info64.tmu_date, + pfile_info->tmu_date = file_info64.tmu_date; pfile_info->compressed_size = (uLong)file_info64.compressed_size; @@ -1175,8 +1058,7 @@ extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ -extern int ZEXPORT unzGoToFirstFile (unzFile file) -{ +extern int ZEXPORT unzGoToFirstFile(unzFile file) { int err=UNZ_OK; unz64_s* s; if (file==NULL) @@ -1196,8 +1078,7 @@ extern int ZEXPORT unzGoToFirstFile (unzFile file) return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ -extern int ZEXPORT unzGoToNextFile (unzFile file) -{ +extern int ZEXPORT unzGoToNextFile(unzFile file) { unz64_s* s; int err; @@ -1229,8 +1110,7 @@ extern int ZEXPORT unzGoToNextFile (unzFile file) UNZ_OK if the file is found. It becomes the current file. UNZ_END_OF_LIST_OF_FILE if the file is not found */ -extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) -{ +extern int ZEXPORT unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity) { unz64_s* s; int err; @@ -1305,8 +1185,7 @@ typedef struct unz_file_pos_s } unz_file_pos; */ -extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) -{ +extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) { unz64_s* s; if (file==NULL || file_pos==NULL) @@ -1321,10 +1200,7 @@ extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) return UNZ_OK; } -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos) -{ +extern int ZEXPORT unzGetFilePos(unzFile file, unz_file_pos* file_pos) { unz64_file_pos file_pos64; int err = unzGetFilePos64(file,&file_pos64); if (err==UNZ_OK) @@ -1335,8 +1211,7 @@ extern int ZEXPORT unzGetFilePos( return err; } -extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) -{ +extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) { unz64_s* s; int err; @@ -1357,10 +1232,7 @@ extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos return err; } -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos) -{ +extern int ZEXPORT unzGoToFilePos(unzFile file, unz_file_pos* file_pos) { unz64_file_pos file_pos64; if (file_pos == NULL) return UNZ_PARAMERROR; @@ -1382,10 +1254,9 @@ extern int ZEXPORT unzGoToFilePos( store in *piSizeVar the size of extra info in local header (filename and size of extra field data) */ -local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, - ZPOS64_T * poffset_local_extrafield, - uInt * psize_local_extrafield) -{ +local int unz64local_CheckCurrentFileCoherencyHeader(unz64_s* s, uInt* piSizeVar, + ZPOS64_T * poffset_local_extrafield, + uInt * psize_local_extrafield) { uLong uMagic,uData,uFlags; uLong size_filename; uLong size_extra_field; @@ -1469,9 +1340,8 @@ local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVa Open for reading data the current file in the zipfile. If there is no error and the file is opened, the return value is UNZ_OK. */ -extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, - int* level, int raw, const char* password) -{ +extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int* method, + int* level, int raw, const char* password) { int err=UNZ_OK; uInt iSizeVar; unz64_s* s; @@ -1509,7 +1379,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, if (pfile_in_zip_read_info->read_buffer==NULL) { - TRYFREE(pfile_in_zip_read_info); + free(pfile_in_zip_read_info); return UNZ_INTERNALERROR; } @@ -1566,8 +1436,8 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; else { - TRYFREE(pfile_in_zip_read_info->read_buffer); - TRYFREE(pfile_in_zip_read_info); + free(pfile_in_zip_read_info->read_buffer); + free(pfile_in_zip_read_info); return err; } #else @@ -1587,8 +1457,8 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; else { - TRYFREE(pfile_in_zip_read_info->read_buffer); - TRYFREE(pfile_in_zip_read_info); + free(pfile_in_zip_read_info->read_buffer); + free(pfile_in_zip_read_info); return err; } /* windowBits is passed < 0 to tell that there is no zlib header. @@ -1640,25 +1510,21 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, return UNZ_OK; } -extern int ZEXPORT unzOpenCurrentFile (unzFile file) -{ +extern int ZEXPORT unzOpenCurrentFile(unzFile file) { return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); } -extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) -{ +extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char* password) { return unzOpenCurrentFile3(file, NULL, NULL, 0, password); } -extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) -{ +extern int ZEXPORT unzOpenCurrentFile2(unzFile file, int* method, int* level, int raw) { return unzOpenCurrentFile3(file, method, level, raw, NULL); } /** Addition for GDAL : START */ -extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) -{ +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; s=(unz64_s*)file; @@ -1678,13 +1544,12 @@ extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) buf contain buffer where data must be copied len the size of buf. - return the number of byte copied if somes bytes are copied + return the number of byte copied if some bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ -extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) -{ +extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len) { int err=UNZ_OK; uInt iRead = 0; unz64_s* s; @@ -1891,8 +1756,7 @@ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) /* Give the current position in uncompressed data */ -extern z_off_t ZEXPORT unztell (unzFile file) -{ +extern z_off_t ZEXPORT unztell(unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) @@ -1906,8 +1770,7 @@ extern z_off_t ZEXPORT unztell (unzFile file) return (z_off_t)pfile_in_zip_read_info->stream.total_out; } -extern ZPOS64_T ZEXPORT unztell64 (unzFile file) -{ +extern ZPOS64_T ZEXPORT unztell64(unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; @@ -1926,8 +1789,7 @@ extern ZPOS64_T ZEXPORT unztell64 (unzFile file) /* return 1 if the end of file was reached, 0 elsewhere */ -extern int ZEXPORT unzeof (unzFile file) -{ +extern int ZEXPORT unzeof(unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) @@ -1958,8 +1820,7 @@ more info in the local-header version than in the central-header) the return value is the number of bytes copied in buf, or (if <0) the error code */ -extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) -{ +extern int ZEXPORT unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; uInt read_now; @@ -2006,8 +1867,7 @@ extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) Close the file in zip opened with unzOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ -extern int ZEXPORT unzCloseCurrentFile (unzFile file) -{ +extern int ZEXPORT unzCloseCurrentFile(unzFile file) { int err=UNZ_OK; unz64_s* s; @@ -2029,7 +1889,7 @@ extern int ZEXPORT unzCloseCurrentFile (unzFile file) } - TRYFREE(pfile_in_zip_read_info->read_buffer); + free(pfile_in_zip_read_info->read_buffer); pfile_in_zip_read_info->read_buffer = NULL; if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) inflateEnd(&pfile_in_zip_read_info->stream); @@ -2040,7 +1900,7 @@ extern int ZEXPORT unzCloseCurrentFile (unzFile file) pfile_in_zip_read_info->stream_initialised = 0; - TRYFREE(pfile_in_zip_read_info); + free(pfile_in_zip_read_info); s->pfile_in_zip_read=NULL; @@ -2053,8 +1913,7 @@ extern int ZEXPORT unzCloseCurrentFile (unzFile file) uSizeBuf is the size of the szComment buffer. return the number of byte copied or an error code <0 */ -extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) -{ +extern int ZEXPORT unzGetGlobalComment(unzFile file, char * szComment, uLong uSizeBuf) { unz64_s* s; uLong uReadThis ; if (file==NULL) @@ -2081,8 +1940,7 @@ extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uS } /* Additions by RX '2004 */ -extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) -{ +extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) { unz64_s* s; if (file==NULL) @@ -2096,8 +1954,7 @@ extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) return s->pos_in_central_dir; } -extern uLong ZEXPORT unzGetOffset (unzFile file) -{ +extern uLong ZEXPORT unzGetOffset(unzFile file) { ZPOS64_T offset64; if (file==NULL) @@ -2106,8 +1963,7 @@ extern uLong ZEXPORT unzGetOffset (unzFile file) return (uLong)offset64; } -extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) -{ +extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) { unz64_s* s; int err; @@ -2124,7 +1980,6 @@ extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) return err; } -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) -{ +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) { return unzSetOffset64(file,pos); } diff --git a/zlib/contrib/minizip/unzip.h b/zlib/contrib/minizip/unzip.h index 6f95e94d756..14105840f6d 100644 --- a/zlib/contrib/minizip/unzip.h +++ b/zlib/contrib/minizip/unzip.h @@ -150,21 +150,21 @@ typedef struct unz_file_info_s tm_unz tmu_date; } unz_file_info; -extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, - const char* fileName2, - int iCaseSensitivity)); +extern int ZEXPORT unzStringFileNameCompare(const char* fileName1, + const char* fileName2, + int iCaseSensitivity); /* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + Compare two filenames (fileName1,fileName2). + If iCaseSensitivity = 1, comparison is case sensitive (like strcmp) + If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + If iCaseSensitivity = 0, case sensitivity is default of your operating system (like 1 on Unix, 2 on Windows) */ -extern unzFile ZEXPORT unzOpen OF((const char *path)); -extern unzFile ZEXPORT unzOpen64 OF((const void *path)); +extern unzFile ZEXPORT unzOpen(const char *path); +extern unzFile ZEXPORT unzOpen64(const void *path); /* Open a Zip file. path contain the full pathname (by example, on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer @@ -181,41 +181,41 @@ extern unzFile ZEXPORT unzOpen64 OF((const void *path)); */ -extern unzFile ZEXPORT unzOpen2 OF((const char *path, - zlib_filefunc_def* pzlib_filefunc_def)); +extern unzFile ZEXPORT unzOpen2(const char *path, + zlib_filefunc_def* pzlib_filefunc_def); /* Open a Zip file, like unzOpen, but provide a set of file low level API for read/write the zip file (see ioapi.h) */ -extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, - zlib_filefunc64_def* pzlib_filefunc_def)); +extern unzFile ZEXPORT unzOpen2_64(const void *path, + zlib_filefunc64_def* pzlib_filefunc_def); /* Open a Zip file, like unz64Open, but provide a set of file low level API for read/write the zip file (see ioapi.h) */ -extern int ZEXPORT unzClose OF((unzFile file)); +extern int ZEXPORT unzClose(unzFile file); /* Close a ZipFile opened with unzOpen. If there is files inside the .Zip opened with unzOpenCurrentFile (see later), these files MUST be closed with unzCloseCurrentFile before call unzClose. return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, - unz_global_info *pglobal_info)); +extern int ZEXPORT unzGetGlobalInfo(unzFile file, + unz_global_info *pglobal_info); -extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, - unz_global_info64 *pglobal_info)); +extern int ZEXPORT unzGetGlobalInfo64(unzFile file, + unz_global_info64 *pglobal_info); /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalComment OF((unzFile file, - char *szComment, - uLong uSizeBuf)); +extern int ZEXPORT unzGetGlobalComment(unzFile file, + char *szComment, + uLong uSizeBuf); /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. @@ -226,22 +226,22 @@ extern int ZEXPORT unzGetGlobalComment OF((unzFile file, /***************************************************************************/ /* Unzip package allow you browse the directory of the zipfile */ -extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +extern int ZEXPORT unzGoToFirstFile(unzFile file); /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ -extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +extern int ZEXPORT unzGoToNextFile(unzFile file); /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ -extern int ZEXPORT unzLocateFile OF((unzFile file, - const char *szFileName, - int iCaseSensitivity)); +extern int ZEXPORT unzLocateFile(unzFile file, + const char *szFileName, + int iCaseSensitivity); /* Try locate the file szFileName in the zipfile. For the iCaseSensitivity signification, see unzStringFileNameCompare @@ -285,26 +285,26 @@ extern int ZEXPORT unzGoToFilePos64( /* ****************************************** */ -extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, - unz_file_info64 *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); +extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize); -extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); +extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize); /* Get Info about the current file - if pfile_info!=NULL, the *pfile_info structure will contain somes info about + if pfile_info!=NULL, the *pfile_info structure will contain some info about the current file if szFileName!=NULL, the filemane string will be copied in szFileName (fileNameBufferSize is the size of the buffer) @@ -318,7 +318,7 @@ extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, /** Addition for GDAL : START */ -extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file); /** Addition for GDAL : END */ @@ -328,24 +328,24 @@ extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); from it, and close it (you can close it before reading all the file) */ -extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +extern int ZEXPORT unzOpenCurrentFile(unzFile file); /* Open for reading data the current file in the zipfile. If there is no error, the return value is UNZ_OK. */ -extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, - const char* password)); +extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, + const char* password); /* Open for reading data the current file in the zipfile. password is a crypting password If there is no error, the return value is UNZ_OK. */ -extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, - int* method, - int* level, - int raw)); +extern int ZEXPORT unzOpenCurrentFile2(unzFile file, + int* method, + int* level, + int raw); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 @@ -355,11 +355,11 @@ extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, but you CANNOT set method parameter as NULL */ -extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, - int* method, - int* level, - int raw, - const char* password)); +extern int ZEXPORT unzOpenCurrentFile3(unzFile file, + int* method, + int* level, + int raw, + const char* password); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 @@ -370,41 +370,41 @@ extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, */ -extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +extern int ZEXPORT unzCloseCurrentFile(unzFile file); /* Close the file in zip opened with unzOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ -extern int ZEXPORT unzReadCurrentFile OF((unzFile file, - voidp buf, - unsigned len)); +extern int ZEXPORT unzReadCurrentFile(unzFile file, + voidp buf, + unsigned len); /* Read bytes from the current file (opened by unzOpenCurrentFile) buf contain buffer where data must be copied len the size of buf. - return the number of byte copied if somes bytes are copied + return the number of byte copied if some bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ -extern z_off_t ZEXPORT unztell OF((unzFile file)); +extern z_off_t ZEXPORT unztell(unzFile file); -extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); +extern ZPOS64_T ZEXPORT unztell64(unzFile file); /* Give the current position in uncompressed data */ -extern int ZEXPORT unzeof OF((unzFile file)); +extern int ZEXPORT unzeof(unzFile file); /* return 1 if the end of file was reached, 0 elsewhere */ -extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, - voidp buf, - unsigned len)); +extern int ZEXPORT unzGetLocalExtrafield(unzFile file, + voidp buf, + unsigned len); /* Read extra field from the current file (opened by unzOpenCurrentFile) This is the local-header version of the extra field (sometimes, there is diff --git a/zlib/contrib/minizip/zip.c b/zlib/contrib/minizip/zip.c index 66d693f85a5..3d3d4caddef 100644 --- a/zlib/contrib/minizip/zip.c +++ b/zlib/contrib/minizip/zip.c @@ -14,7 +14,7 @@ Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data - It is used when recreting zip archive with RAW when deleting items from a zip. + It is used when recreating zip archive with RAW when deleting items from a zip. ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed. Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer @@ -25,14 +25,13 @@ #include #include #include +#include #include #include "zlib.h" #include "zip.h" #ifdef STDC # include -# include -# include #endif #ifdef NO_ERRNO_H extern int errno; @@ -47,7 +46,7 @@ /* compile with -Dlocal if your debugger can't find static symbols */ #ifndef VERSIONMADEBY -# define VERSIONMADEBY (0x0) /* platform depedent */ +# define VERSIONMADEBY (0x0) /* platform dependent */ #endif #ifndef Z_BUFSIZE @@ -61,9 +60,6 @@ #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif /* #define SIZECENTRALDIRITEM (0x2e) @@ -138,20 +134,20 @@ typedef struct uInt pos_in_buffered_data; /* last written byte in buffered_data */ ZPOS64_T pos_local_header; /* offset of the local header of the file - currenty writing */ + currently writing */ char* central_header; /* central header data for the current file */ uLong size_centralExtra; uLong size_centralheader; /* size of the central header for cur file */ uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ uLong flag; /* flag of the file currently writing */ - int method; /* compression method of file currenty wr.*/ + int method; /* compression method of file currently wr.*/ int raw; /* 1 for directly writing raw data */ Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ uLong dosDate; uLong crc32; int encrypt; - int zip64; /* Add ZIP64 extened information in the extra field */ + int zip64; /* Add ZIP64 extended information in the extra field */ ZPOS64_T pos_zip64extrainfo; ZPOS64_T totalCompressedData; ZPOS64_T totalUncompressedData; @@ -165,10 +161,10 @@ typedef struct typedef struct { zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ + voidpf filestream; /* io structure of the zipfile */ linkedlist_data central_dir;/* datablock with central dir in construction*/ int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ - curfile64_info ci; /* info on the file curretly writing */ + curfile64_info ci; /* info on the file currently writing */ ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ ZPOS64_T add_position_when_writing_offset; @@ -186,8 +182,7 @@ typedef struct #include "crypt.h" #endif -local linkedlist_datablock_internal* allocate_new_datablock() -{ +local linkedlist_datablock_internal* allocate_new_datablock(void) { linkedlist_datablock_internal* ldi; ldi = (linkedlist_datablock_internal*) ALLOC(sizeof(linkedlist_datablock_internal)); @@ -200,30 +195,26 @@ local linkedlist_datablock_internal* allocate_new_datablock() return ldi; } -local void free_datablock(linkedlist_datablock_internal* ldi) -{ +local void free_datablock(linkedlist_datablock_internal* ldi) { while (ldi!=NULL) { linkedlist_datablock_internal* ldinext = ldi->next_datablock; - TRYFREE(ldi); + free(ldi); ldi = ldinext; } } -local void init_linkedlist(linkedlist_data* ll) -{ +local void init_linkedlist(linkedlist_data* ll) { ll->first_block = ll->last_block = NULL; } -local void free_linkedlist(linkedlist_data* ll) -{ +local void free_linkedlist(linkedlist_data* ll) { free_datablock(ll->first_block); ll->first_block = ll->last_block = NULL; } -local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) -{ +local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) { linkedlist_datablock_internal* ldi; const unsigned char* from_copy; @@ -238,7 +229,7 @@ local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) } ldi = ll->last_block; - from_copy = (unsigned char*)buf; + from_copy = (const unsigned char*)buf; while (len>0) { @@ -283,9 +274,7 @@ local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) */ -local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); -local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) -{ +local int zip64local_putValue(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) { unsigned char buf[8]; int n; for (n = 0; n < nbByte; n++) @@ -307,9 +296,7 @@ local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, return ZIP_OK; } -local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); -local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) -{ +local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) { unsigned char* buf=(unsigned char*)dest; int n; for (n = 0; n < nbByte; n++) { @@ -329,8 +316,7 @@ local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) /****************************************************************************/ -local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) -{ +local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) { uLong year = (uLong)ptm->tm_year; if (year>=1980) year-=1980; @@ -344,10 +330,7 @@ local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) /****************************************************************************/ -local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); - -local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) -{ +local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi) { unsigned char c; int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); if (err==1) @@ -368,10 +351,7 @@ local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,vo /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ -local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ +local int zip64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) { uLong x ; int i = 0; int err; @@ -390,10 +370,7 @@ local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, return err; } -local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ +local int zip64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) { uLong x ; int i = 0; int err; @@ -420,11 +397,8 @@ local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, return err; } -local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); - -local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) -{ +local int zip64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) { ZPOS64_T x; int i = 0; int err; @@ -475,10 +449,7 @@ local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def Locate the Central directory of a zipfile (at the end, just before the global comment) */ -local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ +local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; @@ -529,7 +500,7 @@ local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f if (uPosFound!=0) break; } - TRYFREE(buf); + free(buf); return uPosFound; } @@ -537,10 +508,7 @@ local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before the global comment) */ -local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ +local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; @@ -595,7 +563,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib break; } - TRYFREE(buf); + free(buf); if (uPosFound == 0) return 0; @@ -637,8 +605,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib return relativeOffset; } -local int LoadCentralDirectoryRecord(zip64_internal* pziinit) -{ +local int LoadCentralDirectoryRecord(zip64_internal* pziinit) { int err=ZIP_OK; ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ @@ -648,9 +615,9 @@ local int LoadCentralDirectoryRecord(zip64_internal* pziinit) uLong uL; uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ + spanning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ + for spanning ZIP, unsupported, always 0*/ ZPOS64_T number_entry; ZPOS64_T number_entry_CD; /* total number of entries in the central dir @@ -830,7 +797,7 @@ local int LoadCentralDirectoryRecord(zip64_internal* pziinit) size_central_dir_to_read-=read_this; } - TRYFREE(buf_read); + free(buf_read); } pziinit->begin_pos = byte_before_the_zipfile; pziinit->number_entry = number_entry_CD; @@ -846,8 +813,7 @@ local int LoadCentralDirectoryRecord(zip64_internal* pziinit) /************************************************************/ -extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) -{ +extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) { zip64_internal ziinit; zip64_internal* zi; int err=ZIP_OK; @@ -905,9 +871,9 @@ extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* gl if (err != ZIP_OK) { # ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(ziinit.globalcomment); + free(ziinit.globalcomment); # endif /* !NO_ADDFILEINEXISTINGZIP*/ - TRYFREE(zi); + free(zi); return NULL; } else @@ -917,8 +883,7 @@ extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* gl } } -extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) -{ +extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) { if (pzlib_filefunc32_def != NULL) { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; @@ -929,8 +894,7 @@ extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* gl return zipOpen3(pathname, append, globalcomment, NULL); } -extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) -{ +extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) { if (pzlib_filefunc_def != NULL) { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; @@ -945,18 +909,15 @@ extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* -extern zipFile ZEXPORT zipOpen (const char* pathname, int append) -{ +extern zipFile ZEXPORT zipOpen(const char* pathname, int append) { return zipOpen3((const void*)pathname,append,NULL,NULL); } -extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) -{ +extern zipFile ZEXPORT zipOpen64(const void* pathname, int append) { return zipOpen3(pathname,append,NULL,NULL); } -local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) -{ +local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) { /* write the local header */ int err; uInt size_filename = (uInt)strlen(filename); @@ -1052,14 +1013,13 @@ local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt s It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize unnecessary allocations. */ -extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, - uLong versionMadeBy, uLong flagBase, int zip64) -{ +extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase, int zip64) { zip64_internal* zi; uInt size_filename; uInt size_comment; @@ -1262,35 +1222,33 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, return err; } -extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, - uLong versionMadeBy, uLong flagBase) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, versionMadeBy, flagBase, 0); +extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, versionMadeBy, flagBase, 0); } -extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, VERSIONMADEBY, 0, 0); +extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, 0); } extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, @@ -1298,70 +1256,64 @@ extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, c const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, VERSIONMADEBY, 0, zip64); + const char* password, uLong crcForCrypting, int zip64) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, zip64); } extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, 0); + const char* comment, int method, int level, int raw) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); } extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, zip64); + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, int zip64) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); } -extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void*extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, zip64); +extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int zip64) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); } -extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void*extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, 0); +extern int ZEXPORT zipOpenNewFileInZip(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); } -local int zip64FlushWriteBuffer(zip64_internal* zi) -{ +local int zip64FlushWriteBuffer(zip64_internal* zi) { int err=ZIP_OK; if (zi->ci.encrypt != 0) @@ -1399,8 +1351,7 @@ local int zip64FlushWriteBuffer(zip64_internal* zi) return err; } -extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) -{ +extern int ZEXPORT zipWriteInFileInZip(zipFile file, const void* buf, unsigned int len) { zip64_internal* zi; int err=ZIP_OK; @@ -1450,7 +1401,7 @@ extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned in else #endif { - zi->ci.stream.next_in = (Bytef*)buf; + zi->ci.stream.next_in = (Bytef*)(uintptr_t)buf; zi->ci.stream.avail_in = len; while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) @@ -1501,13 +1452,11 @@ extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned in return err; } -extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) -{ +extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, uLong crc32) { return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); } -extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) -{ +extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32) { zip64_internal* zi; ZPOS64_T compressed_size; uLong invalidValue = 0xffffffff; @@ -1742,13 +1691,11 @@ extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_s return err; } -extern int ZEXPORT zipCloseFileInZip (zipFile file) -{ +extern int ZEXPORT zipCloseFileInZip(zipFile file) { return zipCloseFileInZipRaw (file,0,0); } -local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) -{ +local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) { int err = ZIP_OK; ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset; @@ -1769,8 +1716,7 @@ local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T z return err; } -local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ +local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK; uLong Zip64DataSize = 44; @@ -1808,8 +1754,8 @@ local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_ } return err; } -local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ + +local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK; /*signature*/ @@ -1856,8 +1802,7 @@ local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centr return err; } -local int Write_GlobalComment(zip64_internal* zi, const char* global_comment) -{ +local int Write_GlobalComment(zip64_internal* zi, const char* global_comment) { int err = ZIP_OK; uInt size_global_comment = 0; @@ -1874,8 +1819,7 @@ local int Write_GlobalComment(zip64_internal* zi, const char* global_comment) return err; } -extern int ZEXPORT zipClose (zipFile file, const char* global_comment) -{ +extern int ZEXPORT zipClose(zipFile file, const char* global_comment) { zip64_internal* zi; int err = 0; uLong size_centraldir = 0; @@ -1936,15 +1880,14 @@ extern int ZEXPORT zipClose (zipFile file, const char* global_comment) err = ZIP_ERRNO; #ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(zi->globalcomment); + free(zi->globalcomment); #endif - TRYFREE(zi); + free(zi); return err; } -extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) -{ +extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader) { char* p = pData; int size = 0; char* pNewHeader; @@ -1996,7 +1939,7 @@ extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHe else retVal = ZIP_ERRNO; - TRYFREE(pNewHeader); + free(pNewHeader); return retVal; } diff --git a/zlib/contrib/minizip/zip.h b/zlib/contrib/minizip/zip.h index 7e4509d77be..5fc08413241 100644 --- a/zlib/contrib/minizip/zip.h +++ b/zlib/contrib/minizip/zip.h @@ -113,8 +113,8 @@ typedef const char* zipcharpc; #define APPEND_STATUS_CREATEAFTER (1) #define APPEND_STATUS_ADDINZIP (2) -extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); -extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); +extern zipFile ZEXPORT zipOpen(const char *pathname, int append); +extern zipFile ZEXPORT zipOpen64(const void *pathname, int append); /* Create a zipfile. pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on @@ -131,46 +131,46 @@ extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); /* Note : there is no delete function into a zipfile. If you want delete file into a zipfile, you must open a zipfile, and create another - Of couse, you can use RAW reading and writing to copy the file you did not want delte + Of course, you can use RAW reading and writing to copy the file you did not want delete */ -extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, +extern zipFile ZEXPORT zipOpen2(const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def); + +extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, - zlib_filefunc_def* pzlib_filefunc_def)); + zlib_filefunc64_def* pzlib_filefunc_def); -extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, - int append, - zipcharpc* globalcomment, - zlib_filefunc64_def* pzlib_filefunc_def)); +extern zipFile ZEXPORT zipOpen3(const void *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc64_32_def* pzlib_filefunc64_32_def); -extern zipFile ZEXPORT zipOpen3 OF((const void *pathname, - int append, - zipcharpc* globalcomment, - zlib_filefunc64_32_def* pzlib_filefunc64_32_def)); +extern int ZEXPORT zipOpenNewFileInZip(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level); -extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level)); - -extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int zip64)); +extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int zip64); /* Open a file in the ZIP for writing. @@ -189,70 +189,69 @@ extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, */ -extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw)); +extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw); -extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int zip64)); +extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int zip64); /* Same than zipOpenNewFileInZip, except if raw=1, we write raw file */ -extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting)); +extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting); -extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - int zip64 - )); +extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + int zip64); /* Same than zipOpenNewFileInZip2, except @@ -261,47 +260,45 @@ extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, crcForCrypting : crc of file to compress (needed for crypting) */ -extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - uLong versionMadeBy, - uLong flagBase - )); +extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase); -extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - uLong versionMadeBy, - uLong flagBase, - int zip64 - )); +extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase, + int zip64); /* Same than zipOpenNewFileInZip4, except versionMadeBy : value for Version made by field @@ -309,25 +306,25 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, */ -extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, - const void* buf, - unsigned len)); +extern int ZEXPORT zipWriteInFileInZip(zipFile file, + const void* buf, + unsigned len); /* Write data in the zipfile */ -extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +extern int ZEXPORT zipCloseFileInZip(zipFile file); /* Close the current file in the zipfile */ -extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, - uLong uncompressed_size, - uLong crc32)); +extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, + uLong uncompressed_size, + uLong crc32); -extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, - ZPOS64_T uncompressed_size, - uLong crc32)); +extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, + ZPOS64_T uncompressed_size, + uLong crc32); /* Close the current file in the zipfile, for file opened with @@ -335,14 +332,14 @@ extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, uncompressed_size and crc32 are value for the uncompressed size */ -extern int ZEXPORT zipClose OF((zipFile file, - const char* global_comment)); +extern int ZEXPORT zipClose(zipFile file, + const char* global_comment); /* Close the zipfile */ -extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader)); +extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader); /* zipRemoveExtraInfoBlock - Added by Mathias Svensson diff --git a/zlib/contrib/pascal/zlibpas.pas b/zlib/contrib/pascal/zlibpas.pas index bf3fff6ff6f..a2b24a593fa 100644 --- a/zlib/contrib/pascal/zlibpas.pas +++ b/zlib/contrib/pascal/zlibpas.pas @@ -10,7 +10,7 @@ unit zlibpas; interface const - ZLIB_VERSION = '1.2.13'; + ZLIB_VERSION = '1.3.0'; ZLIB_VERNUM = $12a0; type diff --git a/zlib/contrib/testzlib/testzlib.c b/zlib/contrib/testzlib/testzlib.c index 5f659dea00f..b3c0014f9bc 100644 --- a/zlib/contrib/testzlib/testzlib.c +++ b/zlib/contrib/testzlib/testzlib.c @@ -169,7 +169,7 @@ int main(int argc, char *argv[]) printf("error reading %s\n",argv[1]); return 1; } - else printf("file %s read, %u bytes\n",argv[1],lFileSize); + else printf("file %s read, %ld bytes\n",argv[1],lFileSize); if (argc>=3) BlockSizeCompress=atol(argv[2]); diff --git a/zlib/contrib/untgz/untgz.c b/zlib/contrib/untgz/untgz.c index 2c391e59867..78579211fec 100644 --- a/zlib/contrib/untgz/untgz.c +++ b/zlib/contrib/untgz/untgz.c @@ -4,6 +4,22 @@ * written by Pedro A. Aranda Gutierrez * adaptation to Unix by Jean-loup Gailly * various fixes by Cosmin Truta + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. */ #include @@ -14,15 +30,10 @@ #include "zlib.h" -#ifdef unix -# include -#else +#ifdef _WIN32 # include # include -#endif - -#ifdef WIN32 -#include +# include # ifndef F_OK # define F_OK 0 # endif @@ -33,6 +44,8 @@ # define strdup(str) _strdup(str) # endif #else +# include +# include # include #endif @@ -102,28 +115,14 @@ struct attr_item enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID }; -char *TGZfname OF((const char *)); -void TGZnotfound OF((const char *)); - -int getoct OF((char *, int)); -char *strtime OF((time_t *)); -int setfiletime OF((char *, time_t)); -void push_attr OF((struct attr_item **, char *, int, time_t)); -void restore_attr OF((struct attr_item **)); - -int ExprMatch OF((char *, char *)); - -int makedir OF((char *)); -int matchname OF((int, int, char **, char *)); - -void error OF((const char *)); -int tar OF((gzFile, int, int, int, char **)); - -void help OF((int)); -int main OF((int, char **)); - char *prog; +void error(const char *msg) +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL }; /* return the file name of the TGZ archive */ @@ -205,7 +204,7 @@ char *strtime (time_t *t) int setfiletime (char *fname,time_t ftime) { -#ifdef WIN32 +#ifdef _WIN32 static int isWinNT = -1; SYSTEMTIME st; FILETIME locft, modft; @@ -590,12 +589,6 @@ void help(int exitval) exit(exitval); } -void error(const char *msg) -{ - fprintf(stderr, "%s: %s\n", prog, msg); - exit(1); -} - /* ============================================================ */ @@ -608,7 +601,7 @@ int main(int argc,char **argv) int action = TGZ_EXTRACT; int arg = 1; char *TGZfile; - gzFile *f; + gzFile f; prog = strrchr(argv[0],'\\'); if (prog == NULL) diff --git a/zlib/contrib/vstudio/readme.txt b/zlib/contrib/vstudio/readme.txt index 17e693ffd54..05ba487c941 100644 --- a/zlib/contrib/vstudio/readme.txt +++ b/zlib/contrib/vstudio/readme.txt @@ -1,4 +1,4 @@ -Building instructions for the DLL versions of Zlib 1.2.13 +Building instructions for the DLL versions of Zlib 1.3.0 ======================================================== This directory contains projects that build zlib and minizip using diff --git a/zlib/contrib/vstudio/vc10/zlib.rc b/zlib/contrib/vstudio/vc10/zlib.rc index 876027498a3..29af8e11acc 100644 --- a/zlib/contrib/vstudio/vc10/zlib.rc +++ b/zlib/contrib/vstudio/vc10/zlib.rc @@ -2,8 +2,8 @@ #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 13, 0 - PRODUCTVERSION 1, 2, 13, 0 + FILEVERSION 1, 3, 0, 0 + PRODUCTVERSION 1, 3, 0, 0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 @@ -17,12 +17,12 @@ BEGIN BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.13\0" + VALUE "FileVersion", "1.3.0\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2022 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" diff --git a/zlib/contrib/vstudio/vc10/zlibvc.def b/zlib/contrib/vstudio/vc10/zlibvc.def index ba09bc1b98f..f28aa6c73bc 100644 --- a/zlib/contrib/vstudio/vc10/zlibvc.def +++ b/zlib/contrib/vstudio/vc10/zlibvc.def @@ -1,7 +1,7 @@ LIBRARY ; zlib data compression and ZIP file I/O library -VERSION 1.2 +VERSION 1.3 EXPORTS adler32 @1 diff --git a/zlib/contrib/vstudio/vc11/zlib.rc b/zlib/contrib/vstudio/vc11/zlib.rc index 876027498a3..29af8e11acc 100644 --- a/zlib/contrib/vstudio/vc11/zlib.rc +++ b/zlib/contrib/vstudio/vc11/zlib.rc @@ -2,8 +2,8 @@ #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 13, 0 - PRODUCTVERSION 1, 2, 13, 0 + FILEVERSION 1, 3, 0, 0 + PRODUCTVERSION 1, 3, 0, 0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 @@ -17,12 +17,12 @@ BEGIN BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.13\0" + VALUE "FileVersion", "1.3.0\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2022 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" diff --git a/zlib/contrib/vstudio/vc11/zlibvc.def b/zlib/contrib/vstudio/vc11/zlibvc.def index ba09bc1b98f..f28aa6c73bc 100644 --- a/zlib/contrib/vstudio/vc11/zlibvc.def +++ b/zlib/contrib/vstudio/vc11/zlibvc.def @@ -1,7 +1,7 @@ LIBRARY ; zlib data compression and ZIP file I/O library -VERSION 1.2 +VERSION 1.3 EXPORTS adler32 @1 diff --git a/zlib/contrib/vstudio/vc12/zlib.rc b/zlib/contrib/vstudio/vc12/zlib.rc index cdd7985d41e..57fb31a3216 100644 --- a/zlib/contrib/vstudio/vc12/zlib.rc +++ b/zlib/contrib/vstudio/vc12/zlib.rc @@ -2,8 +2,8 @@ #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 13, 0 - PRODUCTVERSION 1, 2, 13, 0 + FILEVERSION 1, 3, 0, 0 + PRODUCTVERSION 1, 3, 0, 0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 @@ -17,12 +17,12 @@ BEGIN BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.13\0" + VALUE "FileVersion", "1.3.0\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2022 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" diff --git a/zlib/contrib/vstudio/vc12/zlibvc.def b/zlib/contrib/vstudio/vc12/zlibvc.def index ba09bc1b98f..f28aa6c73bc 100644 --- a/zlib/contrib/vstudio/vc12/zlibvc.def +++ b/zlib/contrib/vstudio/vc12/zlibvc.def @@ -1,7 +1,7 @@ LIBRARY ; zlib data compression and ZIP file I/O library -VERSION 1.2 +VERSION 1.3 EXPORTS adler32 @1 diff --git a/zlib/contrib/vstudio/vc14/zlib.rc b/zlib/contrib/vstudio/vc14/zlib.rc index cdd7985d41e..57fb31a3216 100644 --- a/zlib/contrib/vstudio/vc14/zlib.rc +++ b/zlib/contrib/vstudio/vc14/zlib.rc @@ -2,8 +2,8 @@ #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 13, 0 - PRODUCTVERSION 1, 2, 13, 0 + FILEVERSION 1, 3, 0, 0 + PRODUCTVERSION 1, 3, 0, 0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 @@ -17,12 +17,12 @@ BEGIN BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.13\0" + VALUE "FileVersion", "1.3.0\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2022 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" diff --git a/zlib/contrib/vstudio/vc14/zlibvc.def b/zlib/contrib/vstudio/vc14/zlibvc.def index ba09bc1b98f..f28aa6c73bc 100644 --- a/zlib/contrib/vstudio/vc14/zlibvc.def +++ b/zlib/contrib/vstudio/vc14/zlibvc.def @@ -1,7 +1,7 @@ LIBRARY ; zlib data compression and ZIP file I/O library -VERSION 1.2 +VERSION 1.3 EXPORTS adler32 @1 diff --git a/zlib/contrib/vstudio/vc9/zlib.rc b/zlib/contrib/vstudio/vc9/zlib.rc index 876027498a3..29af8e11acc 100644 --- a/zlib/contrib/vstudio/vc9/zlib.rc +++ b/zlib/contrib/vstudio/vc9/zlib.rc @@ -2,8 +2,8 @@ #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 13, 0 - PRODUCTVERSION 1, 2, 13, 0 + FILEVERSION 1, 3, 0, 0 + PRODUCTVERSION 1, 3, 0, 0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 @@ -17,12 +17,12 @@ BEGIN BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.13\0" + VALUE "FileVersion", "1.3.0\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2022 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2023 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" diff --git a/zlib/contrib/vstudio/vc9/zlibvc.def b/zlib/contrib/vstudio/vc9/zlibvc.def index ba09bc1b98f..f28aa6c73bc 100644 --- a/zlib/contrib/vstudio/vc9/zlibvc.def +++ b/zlib/contrib/vstudio/vc9/zlibvc.def @@ -1,7 +1,7 @@ LIBRARY ; zlib data compression and ZIP file I/O library -VERSION 1.2 +VERSION 1.3 EXPORTS adler32 @1 diff --git a/zlib/crc32.c b/zlib/crc32.c index f8357b083f7..6c38f5c04c6 100644 --- a/zlib/crc32.c +++ b/zlib/crc32.c @@ -103,19 +103,6 @@ # define ARMCRC32 #endif -/* Local functions. */ -local z_crc_t multmodp OF((z_crc_t a, z_crc_t b)); -local z_crc_t x2nmodp OF((z_off64_t n, unsigned k)); - -#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) - local z_word_t byte_swap OF((z_word_t word)); -#endif - -#if defined(W) && !defined(ARMCRC32) - local z_crc_t crc_word OF((z_word_t data)); - local z_word_t crc_word_big OF((z_word_t data)); -#endif - #if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) /* Swap the bytes in a z_word_t to convert between little and big endian. Any @@ -123,9 +110,7 @@ local z_crc_t x2nmodp OF((z_off64_t n, unsigned k)); instruction, if one is available. This assumes that word_t is either 32 bits or 64 bits. */ -local z_word_t byte_swap(word) - z_word_t word; -{ +local z_word_t byte_swap(z_word_t word) { # if W == 8 return (word & 0xff00000000000000) >> 56 | @@ -146,24 +131,77 @@ local z_word_t byte_swap(word) } #endif +#ifdef DYNAMIC_CRC_TABLE +/* ========================================================================= + * Table of powers of x for combining CRC-32s, filled in by make_crc_table() + * below. + */ + local z_crc_t FAR x2n_table[32]; +#else +/* ========================================================================= + * Tables for byte-wise and braided CRC-32 calculations, and a table of powers + * of x for combining CRC-32s, all made by make_crc_table(). + */ +# include "crc32.h" +#endif + /* CRC polynomial. */ #define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ -#ifdef DYNAMIC_CRC_TABLE +/* + Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, + reflected. For speed, this requires that a not be zero. + */ +local z_crc_t multmodp(z_crc_t a, z_crc_t b) { + z_crc_t m, p; + m = (z_crc_t)1 << 31; + p = 0; + for (;;) { + if (a & m) { + p ^= b; + if ((a & (m - 1)) == 0) + break; + } + m >>= 1; + b = b & 1 ? (b >> 1) ^ POLY : b >> 1; + } + return p; +} + +/* + Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been + initialized. + */ +local z_crc_t x2nmodp(z_off64_t n, unsigned k) { + z_crc_t p; + + p = (z_crc_t)1 << 31; /* x^0 == 1 */ + while (n) { + if (n & 1) + p = multmodp(x2n_table[k & 31], p); + n >>= 1; + k++; + } + return p; +} + +#ifdef DYNAMIC_CRC_TABLE +/* ========================================================================= + * Build the tables for byte-wise and braided CRC-32 calculations, and a table + * of powers of x for combining CRC-32s. + */ local z_crc_t FAR crc_table[256]; -local z_crc_t FAR x2n_table[32]; -local void make_crc_table OF((void)); #ifdef W local z_word_t FAR crc_big_table[256]; local z_crc_t FAR crc_braid_table[W][256]; local z_word_t FAR crc_braid_big_table[W][256]; - local void braid OF((z_crc_t [][256], z_word_t [][256], int, int)); + local void braid(z_crc_t [][256], z_word_t [][256], int, int); #endif #ifdef MAKECRCH - local void write_table OF((FILE *, const z_crc_t FAR *, int)); - local void write_table32hi OF((FILE *, const z_word_t FAR *, int)); - local void write_table64 OF((FILE *, const z_word_t FAR *, int)); + local void write_table(FILE *, const z_crc_t FAR *, int); + local void write_table32hi(FILE *, const z_word_t FAR *, int); + local void write_table64(FILE *, const z_word_t FAR *, int); #endif /* MAKECRCH */ /* @@ -176,7 +214,6 @@ local void make_crc_table OF((void)); /* Definition of once functionality. */ typedef struct once_s once_t; -local void once OF((once_t *, void (*)(void))); /* Check for the availability of atomics. */ #if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ @@ -196,10 +233,7 @@ struct once_s { invoke once() at the same time. The state must be a once_t initialized with ONCE_INIT. */ -local void once(state, init) - once_t *state; - void (*init)(void); -{ +local void once(once_t *state, void (*init)(void)) { if (!atomic_load(&state->done)) { if (atomic_flag_test_and_set(&state->begun)) while (!atomic_load(&state->done)) @@ -222,10 +256,7 @@ struct once_s { /* Test and set. Alas, not atomic, but tries to minimize the period of vulnerability. */ -local int test_and_set OF((int volatile *)); -local int test_and_set(flag) - int volatile *flag; -{ +local int test_and_set(int volatile *flag) { int was; was = *flag; @@ -234,10 +265,7 @@ local int test_and_set(flag) } /* Run the provided init() function once. This is not thread-safe. */ -local void once(state, init) - once_t *state; - void (*init)(void); -{ +local void once(once_t *state, void (*init)(void)) { if (!state->done) { if (test_and_set(&state->begun)) while (!state->done) @@ -279,8 +307,7 @@ local once_t made = ONCE_INIT; combinations of CRC register values and incoming bytes. */ -local void make_crc_table() -{ +local void make_crc_table(void) { unsigned i, j, n; z_crc_t p; @@ -447,11 +474,7 @@ local void make_crc_table() Write the 32-bit values in table[0..k-1] to out, five per line in hexadecimal separated by commas. */ -local void write_table(out, table, k) - FILE *out; - const z_crc_t FAR *table; - int k; -{ +local void write_table(FILE *out, const z_crc_t FAR *table, int k) { int n; for (n = 0; n < k; n++) @@ -464,11 +487,7 @@ local void write_table(out, table, k) Write the high 32-bits of each value in table[0..k-1] to out, five per line in hexadecimal separated by commas. */ -local void write_table32hi(out, table, k) -FILE *out; -const z_word_t FAR *table; -int k; -{ +local void write_table32hi(FILE *out, const z_word_t FAR *table, int k) { int n; for (n = 0; n < k; n++) @@ -484,11 +503,7 @@ int k; bits. If not, then the type cast and format string can be adjusted accordingly. */ -local void write_table64(out, table, k) - FILE *out; - const z_word_t FAR *table; - int k; -{ +local void write_table64(FILE *out, const z_word_t FAR *table, int k) { int n; for (n = 0; n < k; n++) @@ -498,8 +513,7 @@ local void write_table64(out, table, k) } /* Actually do the deed. */ -int main() -{ +int main(void) { make_crc_table(); return 0; } @@ -511,12 +525,7 @@ int main() Generate the little and big-endian braid tables for the given n and z_word_t size w. Each array must have room for w blocks of 256 elements. */ -local void braid(ltl, big, n, w) - z_crc_t ltl[][256]; - z_word_t big[][256]; - int n; - int w; -{ +local void braid(z_crc_t ltl[][256], z_word_t big[][256], int n, int w) { int k; z_crc_t i, p, q; for (k = 0; k < w; k++) { @@ -531,69 +540,13 @@ local void braid(ltl, big, n, w) } #endif -#else /* !DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Tables for byte-wise and braided CRC-32 calculations, and a table of powers - * of x for combining CRC-32s, all made by make_crc_table(). - */ -#include "crc32.h" #endif /* DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Routines used for CRC calculation. Some are also required for the table - * generation above. - */ - -/* - Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, - reflected. For speed, this requires that a not be zero. - */ -local z_crc_t multmodp(a, b) - z_crc_t a; - z_crc_t b; -{ - z_crc_t m, p; - - m = (z_crc_t)1 << 31; - p = 0; - for (;;) { - if (a & m) { - p ^= b; - if ((a & (m - 1)) == 0) - break; - } - m >>= 1; - b = b & 1 ? (b >> 1) ^ POLY : b >> 1; - } - return p; -} - -/* - Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been - initialized. - */ -local z_crc_t x2nmodp(n, k) - z_off64_t n; - unsigned k; -{ - z_crc_t p; - - p = (z_crc_t)1 << 31; /* x^0 == 1 */ - while (n) { - if (n & 1) - p = multmodp(x2n_table[k & 31], p); - n >>= 1; - k++; - } - return p; -} - /* ========================================================================= * This function can be used by asm versions of crc32(), and to force the * generation of the CRC tables in a threaded application. */ -const z_crc_t FAR * ZEXPORT get_crc_table() -{ +const z_crc_t FAR * ZEXPORT get_crc_table(void) { #ifdef DYNAMIC_CRC_TABLE once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ @@ -619,11 +572,8 @@ const z_crc_t FAR * ZEXPORT get_crc_table() #define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */ #define Z_BATCH_MIN 800 /* fewest words in a final batch */ -unsigned long ZEXPORT crc32_z(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ +unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, + z_size_t len) { z_crc_t val; z_word_t crc1, crc2; const z_word_t *word; @@ -723,18 +673,14 @@ unsigned long ZEXPORT crc32_z(crc, buf, len) least-significant byte of the word as the first byte of data, without any pre or post conditioning. This is used to combine the CRCs of each braid. */ -local z_crc_t crc_word(data) - z_word_t data; -{ +local z_crc_t crc_word(z_word_t data) { int k; for (k = 0; k < W; k++) data = (data >> 8) ^ crc_table[data & 0xff]; return (z_crc_t)data; } -local z_word_t crc_word_big(data) - z_word_t data; -{ +local z_word_t crc_word_big(z_word_t data) { int k; for (k = 0; k < W; k++) data = (data << 8) ^ @@ -745,11 +691,8 @@ local z_word_t crc_word_big(data) #endif /* ========================================================================= */ -unsigned long ZEXPORT crc32_z(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ +unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, + z_size_t len) { /* Return initial CRC, if requested. */ if (buf == Z_NULL) return 0; @@ -781,8 +724,8 @@ unsigned long ZEXPORT crc32_z(crc, buf, len) words = (z_word_t const *)buf; /* Do endian check at execution time instead of compile time, since ARM - processors can change the endianess at execution time. If the - compiler knows what the endianess will be, it can optimize out the + processors can change the endianness at execution time. If the + compiler knows what the endianness will be, it can optimize out the check and the unused branch. */ endian = 1; if (*(unsigned char *)&endian) { @@ -1069,20 +1012,13 @@ unsigned long ZEXPORT crc32_z(crc, buf, len) #endif /* ========================================================================= */ -unsigned long ZEXPORT crc32(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - uInt len; -{ +unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, + uInt len) { return crc32_z(crc, buf, len); } /* ========================================================================= */ -uLong ZEXPORT crc32_combine64(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off64_t len2; -{ +uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) { #ifdef DYNAMIC_CRC_TABLE once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ @@ -1090,18 +1026,12 @@ uLong ZEXPORT crc32_combine64(crc1, crc2, len2) } /* ========================================================================= */ -uLong ZEXPORT crc32_combine(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off_t len2; -{ +uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) { return crc32_combine64(crc1, crc2, (z_off64_t)len2); } /* ========================================================================= */ -uLong ZEXPORT crc32_combine_gen64(len2) - z_off64_t len2; -{ +uLong ZEXPORT crc32_combine_gen64(z_off64_t len2) { #ifdef DYNAMIC_CRC_TABLE once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ @@ -1109,17 +1039,11 @@ uLong ZEXPORT crc32_combine_gen64(len2) } /* ========================================================================= */ -uLong ZEXPORT crc32_combine_gen(len2) - z_off_t len2; -{ +uLong ZEXPORT crc32_combine_gen(z_off_t len2) { return crc32_combine_gen64((z_off64_t)len2); } /* ========================================================================= */ -uLong ZEXPORT crc32_combine_op(crc1, crc2, op) - uLong crc1; - uLong crc2; - uLong op; -{ +uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op) { return multmodp(op, crc1) ^ (crc2 & 0xffffffff); } diff --git a/zlib/deflate.c b/zlib/deflate.c index 4a689db3598..bd011751920 100644 --- a/zlib/deflate.c +++ b/zlib/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.13 Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; + " deflate 1.3 Copyright 1995-2023 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -60,9 +60,6 @@ const char deflate_copyright[] = copyright string in the executable of your product. */ -/* =========================================================================== - * Function prototypes. - */ typedef enum { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ @@ -70,29 +67,16 @@ typedef enum { finish_done /* finish done, accept no more input or output */ } block_state; -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +typedef block_state (*compress_func)(deflate_state *s, int flush); /* Compression function. Returns the block state after the call. */ -local int deflateStateCheck OF((z_streamp strm)); -local void slide_hash OF((deflate_state *s)); -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); +local block_state deflate_stored(deflate_state *s, int flush); +local block_state deflate_fast(deflate_state *s, int flush); #ifndef FASTEST -local block_state deflate_slow OF((deflate_state *s, int flush)); -#endif -local block_state deflate_rle OF((deflate_state *s, int flush)); -local block_state deflate_huff OF((deflate_state *s, int flush)); -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); -local void flush_pending OF((z_streamp strm)); -local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -local uInt longest_match OF((deflate_state *s, IPos cur_match)); - -#ifdef ZLIB_DEBUG -local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); +local block_state deflate_slow(deflate_state *s, int flush); #endif +local block_state deflate_rle(deflate_state *s, int flush); +local block_state deflate_huff(deflate_state *s, int flush); /* =========================================================================== * Local data @@ -195,9 +179,12 @@ local const config configuration_table[10] = { * bit values at the expense of memory usage). We slide even when level == 0 to * keep the hash table consistent if we switch back to level > 0 later. */ -local void slide_hash(s) - deflate_state *s; -{ +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + __attribute__((no_sanitize("memory"))) +# endif +#endif +local void slide_hash(deflate_state *s) { unsigned n, m; Posf *p; uInt wsize = s->w_size; @@ -221,30 +208,177 @@ local void slide_hash(s) #endif } +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size) { + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + zmemcpy(buf, strm->next_in, len); + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, buf, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, buf, len); + } +#endif + strm->next_in += len; + strm->total_in += len; + + return len; +} + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(deflate_state *s) { + unsigned n; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize + MAX_DIST(s)) { + + zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + if (s->insert > s->strstart) + s->insert = s->strstart; + slide_hash(s); + more += wsize; + } + if (s->strm->avail_in == 0) break; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead + s->insert >= MIN_MATCH) { + uInt str = s->strstart - s->insert; + s->ins_h = s->window[str]; + UPDATE_HASH(s, s->ins_h, s->window[str + 1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + while (s->insert) { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + s->insert--; + if (s->lookahead + s->insert < MIN_MATCH) + break; + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } + + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "not enough room for search"); +} + /* ========================================================================= */ -int ZEXPORT deflateInit_(strm, level, version, stream_size) - z_streamp strm; - int level; - const char *version; - int stream_size; -{ +int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, + int stream_size) { return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ -int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - version, stream_size) - z_streamp strm; - int level; - int method; - int windowBits; - int memLevel; - int strategy; - const char *version; - int stream_size; -{ +int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, + int windowBits, int memLevel, int strategy, + const char *version, int stream_size) { deflate_state *s; int wrap = 1; static const char my_version[] = ZLIB_VERSION; @@ -386,9 +520,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, /* ========================================================================= * Check for a valid deflate stream state. Return 0 if ok, 1 if not. */ -local int deflateStateCheck(strm) - z_streamp strm; -{ +local int deflateStateCheck(z_streamp strm) { deflate_state *s; if (strm == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) @@ -409,11 +541,8 @@ local int deflateStateCheck(strm) } /* ========================================================================= */ -int ZEXPORT deflateSetDictionary(strm, dictionary, dictLength) - z_streamp strm; - const Bytef *dictionary; - uInt dictLength; -{ +int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary, + uInt dictLength) { deflate_state *s; uInt str, n; int wrap; @@ -478,11 +607,8 @@ int ZEXPORT deflateSetDictionary(strm, dictionary, dictLength) } /* ========================================================================= */ -int ZEXPORT deflateGetDictionary(strm, dictionary, dictLength) - z_streamp strm; - Bytef *dictionary; - uInt *dictLength; -{ +int ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary, + uInt *dictLength) { deflate_state *s; uInt len; @@ -500,9 +626,7 @@ int ZEXPORT deflateGetDictionary(strm, dictionary, dictLength) } /* ========================================================================= */ -int ZEXPORT deflateResetKeep(strm) - z_streamp strm; -{ +int ZEXPORT deflateResetKeep(z_streamp strm) { deflate_state *s; if (deflateStateCheck(strm)) { @@ -537,10 +661,32 @@ int ZEXPORT deflateResetKeep(strm) return Z_OK; } +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init(deflate_state *s) { + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->insert = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +} + /* ========================================================================= */ -int ZEXPORT deflateReset(strm) - z_streamp strm; -{ +int ZEXPORT deflateReset(z_streamp strm) { int ret; ret = deflateResetKeep(strm); @@ -550,10 +696,7 @@ int ZEXPORT deflateReset(strm) } /* ========================================================================= */ -int ZEXPORT deflateSetHeader(strm, head) - z_streamp strm; - gz_headerp head; -{ +int ZEXPORT deflateSetHeader(z_streamp strm, gz_headerp head) { if (deflateStateCheck(strm) || strm->state->wrap != 2) return Z_STREAM_ERROR; strm->state->gzhead = head; @@ -561,11 +704,7 @@ int ZEXPORT deflateSetHeader(strm, head) } /* ========================================================================= */ -int ZEXPORT deflatePending(strm, pending, bits) - unsigned *pending; - int *bits; - z_streamp strm; -{ +int ZEXPORT deflatePending(z_streamp strm, unsigned *pending, int *bits) { if (deflateStateCheck(strm)) return Z_STREAM_ERROR; if (pending != Z_NULL) *pending = strm->state->pending; @@ -575,11 +714,7 @@ int ZEXPORT deflatePending(strm, pending, bits) } /* ========================================================================= */ -int ZEXPORT deflatePrime(strm, bits, value) - z_streamp strm; - int bits; - int value; -{ +int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) { deflate_state *s; int put; @@ -602,11 +737,7 @@ int ZEXPORT deflatePrime(strm, bits, value) } /* ========================================================================= */ -int ZEXPORT deflateParams(strm, level, strategy) - z_streamp strm; - int level; - int strategy; -{ +int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) { deflate_state *s; compress_func func; @@ -651,13 +782,8 @@ int ZEXPORT deflateParams(strm, level, strategy) } /* ========================================================================= */ -int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) - z_streamp strm; - int good_length; - int max_lazy; - int nice_length; - int max_chain; -{ +int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, + int nice_length, int max_chain) { deflate_state *s; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -693,10 +819,7 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) * * Shifts are used to approximate divisions, for speed. */ -uLong ZEXPORT deflateBound(strm, sourceLen) - z_streamp strm; - uLong sourceLen; -{ +uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) { deflate_state *s; uLong fixedlen, storelen, wraplen; @@ -752,7 +875,8 @@ uLong ZEXPORT deflateBound(strm, sourceLen) /* if not default parameters, return one of the conservative bounds */ if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return (s->w_bits <= s->hash_bits ? fixedlen : storelen) + wraplen; + return (s->w_bits <= s->hash_bits && s->level ? fixedlen : storelen) + + wraplen; /* default settings: return tight bound for that case -- ~0.03% overhead plus a small constant */ @@ -765,10 +889,7 @@ uLong ZEXPORT deflateBound(strm, sourceLen) * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ -local void putShortMSB(s, b) - deflate_state *s; - uInt b; -{ +local void putShortMSB(deflate_state *s, uInt b) { put_byte(s, (Byte)(b >> 8)); put_byte(s, (Byte)(b & 0xff)); } @@ -779,9 +900,7 @@ local void putShortMSB(s, b) * applications may wish to modify it to avoid allocating a large * strm->next_out buffer and copying into it. (See also read_buf()). */ -local void flush_pending(strm) - z_streamp strm; -{ +local void flush_pending(z_streamp strm) { unsigned len; deflate_state *s = strm->state; @@ -812,10 +931,7 @@ local void flush_pending(strm) } while (0) /* ========================================================================= */ -int ZEXPORT deflate(strm, flush) - z_streamp strm; - int flush; -{ +int ZEXPORT deflate(z_streamp strm, int flush) { int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; @@ -1127,9 +1243,7 @@ int ZEXPORT deflate(strm, flush) } /* ========================================================================= */ -int ZEXPORT deflateEnd(strm) - z_streamp strm; -{ +int ZEXPORT deflateEnd(z_streamp strm) { int status; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -1153,11 +1267,10 @@ int ZEXPORT deflateEnd(strm) * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ -int ZEXPORT deflateCopy(dest, source) - z_streamp dest; - z_streamp source; -{ +int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) { #ifdef MAXSEG_64K + (void)dest; + (void)source; return Z_STREAM_ERROR; #else deflate_state *ds; @@ -1205,66 +1318,6 @@ int ZEXPORT deflateCopy(dest, source) #endif /* MAXSEG_64K */ } -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -local unsigned read_buf(strm, buf, size) - z_streamp strm; - Bytef *buf; - unsigned size; -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - zmemcpy(buf, strm->next_in, len); - if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, buf, len); - } -#ifdef GZIP - else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, buf, len); - } -#endif - strm->next_in += len; - strm->total_in += len; - - return len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -local void lm_init(s) - deflate_state *s; -{ - s->window_size = (ulg)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->insert = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -} - #ifndef FASTEST /* =========================================================================== * Set match_start to the longest match starting at the given string and @@ -1275,10 +1328,7 @@ local void lm_init(s) * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ +local uInt longest_match(deflate_state *s, IPos cur_match) { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ @@ -1426,10 +1476,7 @@ local uInt longest_match(s, cur_match) /* --------------------------------------------------------------------------- * Optimized version for FASTEST only */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ +local uInt longest_match(deflate_state *s, IPos cur_match) { register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ @@ -1490,11 +1537,7 @@ local uInt longest_match(s, cur_match) /* =========================================================================== * Check that the match at match_start is indeed a match. */ -local void check_match(s, start, match, length) - deflate_state *s; - IPos start, match; - int length; -{ +local void check_match(deflate_state *s, IPos start, IPos match, int length) { /* check that the match is indeed a match */ if (zmemcmp(s->window + match, s->window + start, length) != EQUAL) { @@ -1514,137 +1557,6 @@ local void check_match(s, start, match, length) # define check_match(s, start, match, length) #endif /* ZLIB_DEBUG */ -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -local void fill_window(s) - deflate_state *s; -{ - unsigned n; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s->strstart >= wsize + MAX_DIST(s)) { - - zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - if (s->insert > s->strstart) - s->insert = s->strstart; - slide_hash(s); - more += wsize; - } - if (s->strm->avail_in == 0) break; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead + s->insert >= MIN_MATCH) { - uInt str = s->strstart - s->insert; - s->ins_h = s->window[str]; - UPDATE_HASH(s, s->ins_h, s->window[str + 1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - while (s->insert) { - UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); -#ifndef FASTEST - s->prev[str & s->w_mask] = s->head[s->ins_h]; -#endif - s->head[s->ins_h] = (Pos)str; - str++; - s->insert--; - if (s->lookahead + s->insert < MIN_MATCH) - break; - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - if (s->high_water < s->window_size) { - ulg curr = s->strstart + (ulg)(s->lookahead); - ulg init; - - if (s->high_water < curr) { - /* Previous high water mark below current data -- zero WIN_INIT - * bytes or up to end of window, whichever is less. - */ - init = s->window_size - curr; - if (init > WIN_INIT) - init = WIN_INIT; - zmemzero(s->window + curr, (unsigned)init); - s->high_water = curr + init; - } - else if (s->high_water < (ulg)curr + WIN_INIT) { - /* High water mark at or above current data, but below current data - * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - * to end of window, whichever is less. - */ - init = (ulg)curr + WIN_INIT - s->high_water; - if (init > s->window_size - s->high_water) - init = s->window_size - s->high_water; - zmemzero(s->window + s->high_water, (unsigned)init); - s->high_water += init; - } - } - - Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "not enough room for search"); -} - /* =========================================================================== * Flush the current block, with given end-of-file flag. * IN assertion: strstart is set to the end of the current match. @@ -1687,10 +1599,7 @@ local void fill_window(s) * copied. It is most efficient with large input and output buffers, which * maximizes the opportunities to have a single copy from next_in to next_out. */ -local block_state deflate_stored(s, flush) - deflate_state *s; - int flush; -{ +local block_state deflate_stored(deflate_state *s, int flush) { /* Smallest worthy block size when not flushing or finishing. By default * this is 32K. This can be as small as 507 bytes for memLevel == 1. For * large input and output buffers, the stored block size will be larger. @@ -1874,10 +1783,7 @@ local block_state deflate_stored(s, flush) * new strings in the dictionary only for unmatched strings or for short * matches. It is used only for the fast compression options. */ -local block_state deflate_fast(s, flush) - deflate_state *s; - int flush; -{ +local block_state deflate_fast(deflate_state *s, int flush) { IPos hash_head; /* head of the hash chain */ int bflush; /* set if current block must be flushed */ @@ -1976,10 +1882,7 @@ local block_state deflate_fast(s, flush) * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ -local block_state deflate_slow(s, flush) - deflate_state *s; - int flush; -{ +local block_state deflate_slow(deflate_state *s, int flush) { IPos hash_head; /* head of hash chain */ int bflush; /* set if current block must be flushed */ @@ -2107,10 +2010,7 @@ local block_state deflate_slow(s, flush) * one. Do not maintain a hash table. (It will be regenerated if this run of * deflate switches away from Z_RLE.) */ -local block_state deflate_rle(s, flush) - deflate_state *s; - int flush; -{ +local block_state deflate_rle(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ uInt prev; /* byte at distance one to match */ Bytef *scan, *strend; /* scan goes up to strend for length of run */ @@ -2181,10 +2081,7 @@ local block_state deflate_rle(s, flush) * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. * (It will be regenerated if this run of deflate switches away from Huffman.) */ -local block_state deflate_huff(s, flush) - deflate_state *s; - int flush; -{ +local block_state deflate_huff(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ for (;;) { diff --git a/zlib/deflate.h b/zlib/deflate.h index 1a06cd5f25d..8696791429f 100644 --- a/zlib/deflate.h +++ b/zlib/deflate.h @@ -291,14 +291,14 @@ typedef struct internal_state { memory checker errors from longest match routines */ /* in trees.c */ -void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); -int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); -void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_init(deflate_state *s); +int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc); +void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, + ulg stored_len, int last); +void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s); +void ZLIB_INTERNAL _tr_align(deflate_state *s); +void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, + ulg stored_len, int last); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) diff --git a/zlib/examples/fitblk.c b/zlib/examples/fitblk.c index 68f56809d0c..723dc002812 100644 --- a/zlib/examples/fitblk.c +++ b/zlib/examples/fitblk.c @@ -198,7 +198,7 @@ int main(int argc, char **argv) if (ret == Z_MEM_ERROR) quit("out of memory"); - /* set up for next reocmpression */ + /* set up for next recompression */ ret = inflateReset(&inf); assert(ret != Z_STREAM_ERROR); ret = deflateReset(&def); diff --git a/zlib/examples/zlib_how.html b/zlib/examples/zlib_how.html index 444ff1c9a32..43271b988a7 100644 --- a/zlib/examples/zlib_how.html +++ b/zlib/examples/zlib_how.html @@ -1,10 +1,10 @@ - + zlib Usage Example - +

zlib Usage Example

@@ -17,7 +17,7 @@ from an input file to an output file using deflate() and inflate()< annotations are interspersed between lines of the code. So please read between the lines. We hope this helps explain some of the intricacies of zlib.

-Without further adieu, here is the program zpipe.c: +Without further ado, here is the program zpipe.c:


 /* zpipe.c: example of proper use of zlib's inflate() and deflate()
    Not copyrighted -- provided to the public domain
@@ -155,13 +155,11 @@ before we fall out of the loop at the bottom.
 
We start off by reading data from the input file. The number of bytes read is put directly into avail_in, and a pointer to those bytes is put into next_in. We also -check to see if end-of-file on the input has been reached. If we are at the end of file, then flush is set to the +check to see if end-of-file on the input has been reached using feof(). +If we are at the end of file, then flush is set to the zlib constant Z_FINISH, which is later passed to deflate() to -indicate that this is the last chunk of input data to compress. We need to use feof() -to check for end-of-file as opposed to seeing if fewer than CHUNK bytes have been read. The -reason is that if the input file length is an exact multiple of CHUNK, we will miss -the fact that we got to the end-of-file, and not know to tell deflate() to finish -up the compressed stream. If we are not yet at the end of the input, then the zlib +indicate that this is the last chunk of input data to compress. +If we are not yet at the end of the input, then the zlib constant Z_NO_FLUSH will be passed to deflate to indicate that we are still in the middle of the uncompressed data.

@@ -540,6 +538,12 @@ int main(int argc, char **argv) }


-Copyright (c) 2004, 2005 by Mark Adler
Last modified 11 December 2005
+Last modified 24 January 2023
+Copyright © 2004-2023 Mark Adler

+ +Creative Commons License + +Creative Commons Attribution-NoDerivatives 4.0 International License. diff --git a/zlib/examples/zran.c b/zlib/examples/zran.c index 879c47ccf74..32c93686c60 100644 --- a/zlib/examples/zran.c +++ b/zlib/examples/zran.c @@ -1,114 +1,102 @@ -/* zran.c -- example of zlib/gzip stream indexing and random access - * Copyright (C) 2005, 2012, 2018 Mark Adler +/* zran.c -- example of deflate stream indexing and random access + * Copyright (C) 2005, 2012, 2018, 2023 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h - * Version 1.2 14 Oct 2018 Mark Adler */ + * Version 1.4 13 Apr 2023 Mark Adler */ /* Version History: 1.0 29 May 2005 First version 1.1 29 Sep 2012 Fix memory reallocation error 1.2 14 Oct 2018 Handle gzip streams with multiple members Add a header file to facilitate usage in applications + 1.3 18 Feb 2023 Permit raw deflate streams as well as zlib and gzip + Permit crossing gzip member boundaries when extracting + Support a size_t size when extracting (was an int) + Do a binary search over the index for an access point + Expose the access point type to enable save and load + 1.4 13 Apr 2023 Add a NOPRIME define to not use inflatePrime() */ -/* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() - for random access of a compressed file. A file containing a zlib or gzip - stream is provided on the command line. The compressed stream is decoded in - its entirety, and an index built with access points about every SPAN bytes - in the uncompressed output. The compressed file is left open, and can then - be read randomly, having to decompress on the average SPAN/2 uncompressed - bytes before getting to the desired block of data. - - An access point can be created at the start of any deflate block, by saving - the starting file offset and bit of that block, and the 32K bytes of - uncompressed data that precede that block. Also the uncompressed offset of - that block is saved to provide a reference for locating a desired starting - point in the uncompressed stream. deflate_index_build() works by - decompressing the input zlib or gzip stream a block at a time, and at the - end of each block deciding if enough uncompressed data has gone by to - justify the creation of a new access point. If so, that point is saved in a - data structure that grows as needed to accommodate the points. - - To use the index, an offset in the uncompressed data is provided, for which - the latest access point at or preceding that offset is located in the index. - The input file is positioned to the specified location in the index, and if - necessary the first few bits of the compressed data is read from the file. - inflate is initialized with those bits and the 32K of uncompressed data, and - the decompression then proceeds until the desired offset in the file is - reached. Then the decompression continues to read the desired uncompressed - data from the file. - - Another approach would be to generate the index on demand. In that case, - requests for random access reads from the compressed data would try to use - the index, but if a read far enough past the end of the index is required, - then further index entries would be generated and added. - - There is some fair bit of overhead to starting inflation for the random - access, mainly copying the 32K byte dictionary. So if small pieces of the - file are being accessed, it would make sense to implement a cache to hold - some lookahead and avoid many calls to deflate_index_extract() for small - lengths. - - Another way to build an index would be to use inflateCopy(). That would - not be constrained to have access points at block boundaries, but requires - more memory per access point, and also cannot be saved to file due to the - use of pointers in the state. The approach here allows for storage of the - index in a file. - */ +// Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() +// for random access of a compressed file. A file containing a raw deflate +// stream is provided on the command line. The compressed stream is decoded in +// its entirety, and an index built with access points about every SPAN bytes +// in the uncompressed output. The compressed file is left open, and can then +// be read randomly, having to decompress on the average SPAN/2 uncompressed +// bytes before getting to the desired block of data. +// +// An access point can be created at the start of any deflate block, by saving +// the starting file offset and bit of that block, and the 32K bytes of +// uncompressed data that precede that block. Also the uncompressed offset of +// that block is saved to provide a reference for locating a desired starting +// point in the uncompressed stream. deflate_index_build() decompresses the +// input raw deflate stream a block at a time, and at the end of each block +// decides if enough uncompressed data has gone by to justify the creation of a +// new access point. If so, that point is saved in a data structure that grows +// as needed to accommodate the points. +// +// To use the index, an offset in the uncompressed data is provided, for which +// the latest access point at or preceding that offset is located in the index. +// The input file is positioned to the specified location in the index, and if +// necessary the first few bits of the compressed data is read from the file. +// inflate is initialized with those bits and the 32K of uncompressed data, and +// decompression then proceeds until the desired offset in the file is reached. +// Then decompression continues to read the requested uncompressed data from +// the file. +// +// There is some fair bit of overhead to starting inflation for the random +// access, mainly copying the 32K byte dictionary. If small pieces of the file +// are being accessed, it would make sense to implement a cache to hold some +// lookahead to avoid many calls to deflate_index_extract() for small lengths. +// +// Another way to build an index would be to use inflateCopy(). That would not +// be constrained to have access points at block boundaries, but would require +// more memory per access point, and could not be saved to a file due to the +// use of pointers in the state. The approach here allows for storage of the +// index in a file. #include #include #include +#include #include "zlib.h" #include "zran.h" -#define WINSIZE 32768U /* sliding window size */ -#define CHUNK 16384 /* file input buffer size */ +#define WINSIZE 32768U // sliding window size +#define CHUNK 16384 // file input buffer size -/* Access point entry. */ -struct point { - off_t out; /* corresponding offset in uncompressed data */ - off_t in; /* offset in input file of first full byte */ - int bits; /* number of bits (1-7) from byte at in-1, or 0 */ - unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */ -}; - -/* See comments in zran.h. */ -void deflate_index_free(struct deflate_index *index) -{ +// See comments in zran.h. +void deflate_index_free(struct deflate_index *index) { if (index != NULL) { free(index->list); free(index); } } -/* Add an entry to the access point list. If out of memory, deallocate the - existing list and return NULL. index->gzip is the allocated size of the - index in point entries, until it is time for deflate_index_build() to - return, at which point gzip is set to indicate a gzip file or not. - */ -static struct deflate_index *addpoint(struct deflate_index *index, int bits, - off_t in, off_t out, unsigned left, - unsigned char *window) -{ - struct point *next; - - /* if list is empty, create it (start with eight points) */ +// Add an access point to the list. If out of memory, deallocate the existing +// list and return NULL. index->mode is temporarily the allocated number of +// access points, until it is time for deflate_index_build() to return. Then +// index->mode is set to the mode of inflation. +static struct deflate_index *add_point(struct deflate_index *index, int bits, + off_t in, off_t out, unsigned left, + unsigned char *window) { if (index == NULL) { + // The list is empty. Create it, starting with eight access points. index = malloc(sizeof(struct deflate_index)); - if (index == NULL) return NULL; - index->list = malloc(sizeof(struct point) << 3); + if (index == NULL) + return NULL; + index->have = 0; + index->mode = 8; + index->list = malloc(sizeof(point_t) * index->mode); if (index->list == NULL) { free(index); return NULL; } - index->gzip = 8; - index->have = 0; } - /* if list is full, make it bigger */ - else if (index->have == index->gzip) { - index->gzip <<= 1; - next = realloc(index->list, sizeof(struct point) * index->gzip); + else if (index->have == index->mode) { + // The list is full. Make it bigger. + index->mode <<= 1; + point_t *next = realloc(index->list, sizeof(point_t) * index->mode); if (next == NULL) { deflate_index_free(index); return NULL; @@ -116,318 +104,379 @@ static struct deflate_index *addpoint(struct deflate_index *index, int bits, index->list = next; } - /* fill in entry and increment how many we have */ - next = (struct point *)(index->list) + index->have; - next->bits = bits; - next->in = in; + // Fill in the access point and increment how many we have. + point_t *next = (point_t *)(index->list) + index->have++; + if (index->have < 0) { + // Overflowed the int! + deflate_index_free(index); + return NULL; + } next->out = out; + next->in = in; + next->bits = bits; if (left) memcpy(next->window, window + WINSIZE - left, left); if (left < WINSIZE) memcpy(next->window + left, window, WINSIZE - left); - index->have++; - /* return list, possibly reallocated */ + // Return the index, which may have been newly allocated or destroyed. return index; } -/* See comments in zran.h. */ -int deflate_index_build(FILE *in, off_t span, struct deflate_index **built) -{ - int ret; - int gzip = 0; /* true if reading a gzip file */ - off_t totin, totout; /* our own total counters to avoid 4GB limit */ - off_t last; /* totout value of last access point */ - struct deflate_index *index; /* access points being generated */ - z_stream strm; - unsigned char input[CHUNK]; - unsigned char window[WINSIZE]; +// Decompression modes. These are the inflateInit2() windowBits parameter. +#define RAW -15 +#define ZLIB 15 +#define GZIP 31 - /* initialize inflate */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */ - if (ret != Z_OK) - return ret; +// See comments in zran.h. +int deflate_index_build(FILE *in, off_t span, struct deflate_index **built) { + // Set up inflation state. + z_stream strm = {0}; // inflate engine (gets fired up later) + unsigned char buf[CHUNK]; // input buffer + unsigned char win[WINSIZE] = {0}; // output sliding window + off_t totin = 0; // total bytes read from input + off_t totout = 0; // total bytes uncompressed + int mode = 0; // mode: RAW, ZLIB, or GZIP (0 => not set yet) - /* inflate the input, maintain a sliding window, and build an index -- this - also validates the integrity of the compressed data using the check - information in the gzip or zlib stream */ - totin = totout = last = 0; - index = NULL; /* will be allocated by first addpoint() */ - strm.avail_out = 0; + // Decompress from in, generating access points along the way. + int ret; // the return value from zlib, or Z_ERRNO + off_t last; // last access point uncompressed offset + struct deflate_index *index = NULL; // list of access points do { - /* get some compressed data from input file */ - strm.avail_in = fread(input, 1, CHUNK, in); - if (ferror(in)) { - ret = Z_ERRNO; - goto deflate_index_build_error; - } + // Assure available input, at least until reaching EOF. if (strm.avail_in == 0) { - ret = Z_DATA_ERROR; - goto deflate_index_build_error; - } - strm.next_in = input; - - /* check for a gzip stream */ - if (totin == 0 && strm.avail_in >= 3 && - input[0] == 31 && input[1] == 139 && input[2] == 8) - gzip = 1; - - /* process all of that, or until end of stream */ - do { - /* reset sliding window if necessary */ - if (strm.avail_out == 0) { - strm.avail_out = WINSIZE; - strm.next_out = window; - } - - /* inflate until out of input, output, or at end of block -- - update the total input and output counters */ + strm.avail_in = fread(buf, 1, sizeof(buf), in); totin += strm.avail_in; - totout += strm.avail_out; - ret = inflate(&strm, Z_BLOCK); /* return at end of block */ - totin -= strm.avail_in; - totout -= strm.avail_out; - if (ret == Z_NEED_DICT) - ret = Z_DATA_ERROR; - if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) - goto deflate_index_build_error; - if (ret == Z_STREAM_END) { - if (gzip && - (strm.avail_in || ungetc(getc(in), in) != EOF)) { - ret = inflateReset(&strm); - if (ret != Z_OK) - goto deflate_index_build_error; - continue; - } + strm.next_in = buf; + if (strm.avail_in < sizeof(buf) && ferror(in)) { + ret = Z_ERRNO; break; } - /* if at end of block, consider adding an index entry (note that if - data_type indicates an end-of-block, then all of the - uncompressed data from that block has been delivered, and none - of the compressed data after that block has been consumed, - except for up to seven bits) -- the totout == 0 provides an - entry point after the zlib or gzip header, and assures that the - index always has at least one access point; we avoid creating an - access point after the last block by checking bit 6 of data_type - */ - if ((strm.data_type & 128) && !(strm.data_type & 64) && - (totout == 0 || totout - last > span)) { - index = addpoint(index, strm.data_type & 7, totin, - totout, strm.avail_out, window); - if (index == NULL) { - ret = Z_MEM_ERROR; - goto deflate_index_build_error; - } - last = totout; + if (mode == 0) { + // At the start of the input -- determine the type. Assume raw + // if it is neither zlib nor gzip. This could in theory result + // in a false positive for zlib, but in practice the fill bits + // after a stored block are always zeros, so a raw stream won't + // start with an 8 in the low nybble. + mode = strm.avail_in == 0 ? RAW : // empty -- will fail + (strm.next_in[0] & 0xf) == 8 ? ZLIB : + strm.next_in[0] == 0x1f ? GZIP : + /* else */ RAW; + ret = inflateInit2(&strm, mode); + if (ret != Z_OK) + break; } - } while (strm.avail_in != 0); - } while (ret != Z_STREAM_END); + } - /* clean up and return index (release unused entries in list) */ - (void)inflateEnd(&strm); - index->list = realloc(index->list, sizeof(struct point) * index->have); - index->gzip = gzip; + // Assure available output. This rotates the output through, for use as + // a sliding window on the uncompressed data. + if (strm.avail_out == 0) { + strm.avail_out = sizeof(win); + strm.next_out = win; + } + + if (mode == RAW && index == NULL) + // We skip the inflate() call at the start of raw deflate data in + // order generate an access point there. Set data_type to imitate + // the end of a header. + strm.data_type = 0x80; + else { + // Inflate and update the number of uncompressed bytes. + unsigned before = strm.avail_out; + ret = inflate(&strm, Z_BLOCK); + totout += before - strm.avail_out; + } + + if ((strm.data_type & 0xc0) == 0x80 && + (index == NULL || totout - last >= span)) { + // We are at the end of a header or a non-last deflate block, so we + // can add an access point here. Furthermore, we are either at the + // very start for the first access point, or there has been span or + // more uncompressed bytes since the last access point, so we want + // to add an access point here. + index = add_point(index, strm.data_type & 7, totin - strm.avail_in, + totout, strm.avail_out, win); + if (index == NULL) { + ret = Z_MEM_ERROR; + break; + } + last = totout; + } + + if (ret == Z_STREAM_END && mode == GZIP && + (strm.avail_in || ungetc(getc(in), in) != EOF)) + // There is more input after the end of a gzip member. Reset the + // inflate state to read another gzip member. On success, this will + // set ret to Z_OK to continue decompressing. + ret = inflateReset2(&strm, GZIP); + + // Keep going until Z_STREAM_END or error. If the compressed data ends + // prematurely without a file read error, Z_BUF_ERROR is returned. + } while (ret == Z_OK); + inflateEnd(&strm); + + if (ret != Z_STREAM_END) { + // An error was encountered. Discard the index and return a negative + // error code. + deflate_index_free(index); + return ret == Z_NEED_DICT ? Z_DATA_ERROR : ret; + } + + // Shrink the index to only the occupied access points and return it. + index->mode = mode; index->length = totout; + point_t *list = realloc(index->list, sizeof(point_t) * index->have); + if (list == NULL) { + // Seems like a realloc() to make something smaller should always work, + // but just in case. + deflate_index_free(index); + return Z_MEM_ERROR; + } + index->list = list; *built = index; return index->have; - - /* return error */ - deflate_index_build_error: - (void)inflateEnd(&strm); - deflate_index_free(index); - return ret; } -/* See comments in zran.h. */ -int deflate_index_extract(FILE *in, struct deflate_index *index, off_t offset, - unsigned char *buf, int len) -{ - int ret, skip; - z_stream strm; - struct point *here; - unsigned char input[CHUNK]; - unsigned char discard[WINSIZE]; +#ifdef NOPRIME +// Support zlib versions before 1.2.3 (July 2005), or incomplete zlib clones +// that do not have inflatePrime(). - /* proceed only if something reasonable to do */ - if (len < 0) +# define INFLATEPRIME inflatePreface + +// Append the low bits bits of value to in[] at bit position *have, updating +// *have. value must be zero above its low bits bits. bits must be positive. +// This assumes that any bits above the *have bits in the last byte are zeros. +// That assumption is preserved on return, as any bits above *have + bits in +// the last byte written will be set to zeros. +static inline void append_bits(unsigned value, int bits, + unsigned char *in, int *have) { + in += *have >> 3; // where the first bits from value will go + int k = *have & 7; // the number of bits already there + *have += bits; + if (k) + *in |= value << k; // write value above the low k bits + else + *in = value; + k = 8 - k; // the number of bits just appended + while (bits > k) { + value >>= k; // drop the bits appended + bits -= k; + k = 8; // now at a byte boundary + *++in = value; + } +} + +// Insert enough bits in the form of empty deflate blocks in front of the the +// low bits bits of value, in order to bring the sequence to a byte boundary. +// Then feed that to inflate(). This does what inflatePrime() does, except that +// a negative value of bits is not supported. bits must be in 0..16. If the +// arguments are invalid, Z_STREAM_ERROR is returned. Otherwise the return +// value from inflate() is returned. +static int inflatePreface(z_stream *strm, int bits, int value) { + // Check input. + if (strm == Z_NULL || bits < 0 || bits > 16) + return Z_STREAM_ERROR; + if (bits == 0) + return Z_OK; + value &= (2 << (bits - 1)) - 1; + + // An empty dynamic block with an odd number of bits (95). The high bit of + // the last byte is unused. + static const unsigned char dyn[] = { + 4, 0xe0, 0x81, 8, 0, 0, 0, 0, 0x20, 0xa8, 0xab, 0x1f + }; + const int dynlen = 95; // number of bits in the block + + // Build an input buffer for inflate that is a multiple of eight bits in + // length, and that ends with the low bits bits of value. + unsigned char in[(dynlen + 3 * 10 + 16 + 7) / 8]; + int have = 0; + if (bits & 1) { + // Insert an empty dynamic block to get to an odd number of bits, so + // when bits bits from value are appended, we are at an even number of + // bits. + memcpy(in, dyn, sizeof(dyn)); + have = dynlen; + } + while ((have + bits) & 7) + // Insert empty fixed blocks until appending bits bits would put us on + // a byte boundary. This will insert at most three fixed blocks. + append_bits(2, 10, in, &have); + + // Append the bits bits from value, which takes us to a byte boundary. + append_bits(value, bits, in, &have); + + // Deliver the input to inflate(). There is no output space provided, but + // inflate() can't get stuck waiting on output not ingesting all of the + // provided input. The reason is that there will be at most 16 bits of + // input from value after the empty deflate blocks (which themselves + // generate no output). At least ten bits are needed to generate the first + // output byte from a fixed block. The last two bytes of the buffer have to + // be ingested in order to get ten bits, which is the most that value can + // occupy. + strm->avail_in = have >> 3; + strm->next_in = in; + strm->avail_out = 0; + strm->next_out = in; // not used, but can't be NULL + return inflate(strm, Z_NO_FLUSH); +} + +#else +# define INFLATEPRIME inflatePrime +#endif + +// See comments in zran.h. +ptrdiff_t deflate_index_extract(FILE *in, struct deflate_index *index, + off_t offset, unsigned char *buf, size_t len) { + // Do a quick sanity check on the index. + if (index == NULL || index->have < 1 || index->list[0].out != 0) + return Z_STREAM_ERROR; + + // If nothing to extract, return zero bytes extracted. + if (len == 0 || offset < 0 || offset >= index->length) return 0; - /* find where in stream to start */ - here = index->list; - ret = index->have; - while (--ret && here[1].out <= offset) - here++; + // Find the access point closest to but not after offset. + int lo = -1, hi = index->have; + point_t *point = index->list; + while (hi - lo > 1) { + int mid = (lo + hi) >> 1; + if (offset < point[mid].out) + hi = mid; + else + lo = mid; + } + point += lo; - /* initialize file and inflate state to start there */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, -15); /* raw inflate */ + // Initialize the input file and prime the inflate engine to start there. + int ret = fseeko(in, point->in - (point->bits ? 1 : 0), SEEK_SET); + if (ret == -1) + return Z_ERRNO; + int ch = 0; + if (point->bits && (ch = getc(in)) == EOF) + return ferror(in) ? Z_ERRNO : Z_BUF_ERROR; + z_stream strm = {0}; + ret = inflateInit2(&strm, RAW); if (ret != Z_OK) return ret; - ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET); - if (ret == -1) - goto deflate_index_extract_ret; - if (here->bits) { - ret = getc(in); - if (ret == -1) { - ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR; - goto deflate_index_extract_ret; - } - (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits)); - } - (void)inflateSetDictionary(&strm, here->window, WINSIZE); + if (point->bits) + INFLATEPRIME(&strm, point->bits, ch >> (8 - point->bits)); + inflateSetDictionary(&strm, point->window, WINSIZE); - /* skip uncompressed bytes until offset reached, then satisfy request */ - offset -= here->out; - strm.avail_in = 0; - skip = 1; /* while skipping to offset */ + // Skip uncompressed bytes until offset reached, then satisfy request. + unsigned char input[CHUNK]; + unsigned char discard[WINSIZE]; + offset -= point->out; // number of bytes to skip to get to offset + size_t left = len; // number of bytes left to read after offset do { - /* define where to put uncompressed data, and how much */ - if (offset > WINSIZE) { /* skip WINSIZE bytes */ - strm.avail_out = WINSIZE; + if (offset) { + // Discard up to offset uncompressed bytes. + strm.avail_out = offset < WINSIZE ? (unsigned)offset : WINSIZE; strm.next_out = discard; - offset -= WINSIZE; } - else if (offset > 0) { /* last skip */ - strm.avail_out = (unsigned)offset; - strm.next_out = discard; - offset = 0; - } - else if (skip) { /* at offset now */ - strm.avail_out = len; - strm.next_out = buf; - skip = 0; /* only do this once */ + else { + // Uncompress up to left bytes into buf. + strm.avail_out = left < UINT_MAX ? (unsigned)left : UINT_MAX; + strm.next_out = buf + len - left; } - /* uncompress until avail_out filled, or end of stream */ - do { - if (strm.avail_in == 0) { - strm.avail_in = fread(input, 1, CHUNK, in); - if (ferror(in)) { - ret = Z_ERRNO; - goto deflate_index_extract_ret; - } - if (strm.avail_in == 0) { - ret = Z_DATA_ERROR; - goto deflate_index_extract_ret; - } - strm.next_in = input; + // Uncompress, setting got to the number of bytes uncompressed. + if (strm.avail_in == 0) { + // Assure available input. + strm.avail_in = fread(input, 1, CHUNK, in); + if (strm.avail_in < CHUNK && ferror(in)) { + ret = Z_ERRNO; + break; } - ret = inflate(&strm, Z_NO_FLUSH); /* normal inflate */ - if (ret == Z_NEED_DICT) - ret = Z_DATA_ERROR; - if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) - goto deflate_index_extract_ret; - if (ret == Z_STREAM_END) { - /* the raw deflate stream has ended */ - if (index->gzip == 0) - /* this is a zlib stream that has ended -- done */ - break; + strm.next_in = input; + } + unsigned got = strm.avail_out; + ret = inflate(&strm, Z_NO_FLUSH); + got -= strm.avail_out; - /* near the end of a gzip member, which might be followed by - another gzip member -- skip the gzip trailer and see if - there is more input after it */ - if (strm.avail_in < 8) { - fseeko(in, 8 - strm.avail_in, SEEK_CUR); - strm.avail_in = 0; - } - else { - strm.avail_in -= 8; - strm.next_in += 8; - } - if (strm.avail_in == 0 && ungetc(getc(in), in) == EOF) - /* the input ended after the gzip trailer -- done */ - break; + // Update the appropriate count. + if (offset) + offset -= got; + else + left -= got; - /* there is more input, so another gzip member should follow -- - validate and skip the gzip header */ - ret = inflateReset2(&strm, 31); - if (ret != Z_OK) - goto deflate_index_extract_ret; + // If we're at the end of a gzip member and there's more to read, + // continue to the next gzip member. + if (ret == Z_STREAM_END && index->mode == GZIP) { + // Discard the gzip trailer. + unsigned drop = 8; // length of gzip trailer + if (strm.avail_in >= drop) { + strm.avail_in -= drop; + strm.next_in += drop; + } + else { + // Read and discard the remainder of the gzip trailer. + drop -= strm.avail_in; + strm.avail_in = 0; + do { + if (getc(in) == EOF) + // The input does not have a complete trailer. + return ferror(in) ? Z_ERRNO : Z_BUF_ERROR; + } while (--drop); + } + + if (strm.avail_in || ungetc(getc(in), in) != EOF) { + // There's more after the gzip trailer. Use inflate to skip the + // gzip header and resume the raw inflate there. + inflateReset2(&strm, GZIP); do { if (strm.avail_in == 0) { strm.avail_in = fread(input, 1, CHUNK, in); - if (ferror(in)) { + if (strm.avail_in < CHUNK && ferror(in)) { ret = Z_ERRNO; - goto deflate_index_extract_ret; - } - if (strm.avail_in == 0) { - ret = Z_DATA_ERROR; - goto deflate_index_extract_ret; + break; } strm.next_in = input; } - ret = inflate(&strm, Z_BLOCK); - if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) - goto deflate_index_extract_ret; - } while ((strm.data_type & 128) == 0); - - /* set up to continue decompression of the raw deflate stream - that follows the gzip header */ - ret = inflateReset2(&strm, -15); + strm.avail_out = WINSIZE; + strm.next_out = discard; + ret = inflate(&strm, Z_BLOCK); // stop at end of header + } while (ret == Z_OK && (strm.data_type & 0x80) == 0); if (ret != Z_OK) - goto deflate_index_extract_ret; + break; + inflateReset2(&strm, RAW); } + } - /* continue to process the available input before reading more */ - } while (strm.avail_out != 0); + // Continue until we have the requested data, the deflate data has + // ended, or an error is encountered. + } while (ret == Z_OK && left); + inflateEnd(&strm); - if (ret == Z_STREAM_END) - /* reached the end of the compressed data -- return the data that - was available, possibly less than requested */ - break; - - /* do until offset reached and requested data read */ - } while (skip); - - /* compute the number of uncompressed bytes read after the offset */ - ret = skip ? 0 : len - strm.avail_out; - - /* clean up and return the bytes read, or the negative error */ - deflate_index_extract_ret: - (void)inflateEnd(&strm); - return ret; + // Return the number of uncompressed bytes read into buf, or the error. + return ret == Z_OK || ret == Z_STREAM_END ? len - left : ret; } #ifdef TEST -#define SPAN 1048576L /* desired distance between access points */ -#define LEN 16384 /* number of bytes to extract */ +#define SPAN 1048576L // desired distance between access points +#define LEN 16384 // number of bytes to extract -/* Demonstrate the use of deflate_index_build() and deflate_index_extract() by - processing the file provided on the command line, and extracting LEN bytes - from 2/3rds of the way through the uncompressed output, writing that to - stdout. An offset can be provided as the second argument, in which case the - data is extracted from there instead. */ -int main(int argc, char **argv) -{ - int len; - off_t offset = -1; - FILE *in; - struct deflate_index *index = NULL; - unsigned char buf[LEN]; - - /* open input file */ +// Demonstrate the use of deflate_index_build() and deflate_index_extract() by +// processing the file provided on the command line, and extracting LEN bytes +// from 2/3rds of the way through the uncompressed output, writing that to +// stdout. An offset can be provided as the second argument, in which case the +// data is extracted from there instead. +int main(int argc, char **argv) { + // Open the input file. if (argc < 2 || argc > 3) { - fprintf(stderr, "usage: zran file.gz [offset]\n"); + fprintf(stderr, "usage: zran file.raw [offset]\n"); return 1; } - in = fopen(argv[1], "rb"); + FILE *in = fopen(argv[1], "rb"); if (in == NULL) { fprintf(stderr, "zran: could not open %s for reading\n", argv[1]); return 1; } - /* get optional offset */ + // Get optional offset. + off_t offset = -1; if (argc == 3) { char *end; offset = strtoll(argv[2], &end, 10); @@ -437,14 +486,18 @@ int main(int argc, char **argv) } } - /* build index */ - len = deflate_index_build(in, SPAN, &index); + // Build index. + struct deflate_index *index = NULL; + int len = deflate_index_build(in, SPAN, &index); if (len < 0) { fclose(in); switch (len) { case Z_MEM_ERROR: fprintf(stderr, "zran: out of memory\n"); break; + case Z_BUF_ERROR: + fprintf(stderr, "zran: %s ended prematurely\n", argv[1]); + break; case Z_DATA_ERROR: fprintf(stderr, "zran: compressed data error in %s\n", argv[1]); break; @@ -458,19 +511,20 @@ int main(int argc, char **argv) } fprintf(stderr, "zran: built index with %d access points\n", len); - /* use index by reading some bytes from an arbitrary offset */ + // Use index by reading some bytes from an arbitrary offset. + unsigned char buf[LEN]; if (offset == -1) - offset = (index->length << 1) / 3; - len = deflate_index_extract(in, index, offset, buf, LEN); - if (len < 0) + offset = ((index->length + 1) << 1) / 3; + ptrdiff_t got = deflate_index_extract(in, index, offset, buf, LEN); + if (got < 0) fprintf(stderr, "zran: extraction failed: %s error\n", - len == Z_MEM_ERROR ? "out of memory" : "input corrupted"); + got == Z_MEM_ERROR ? "out of memory" : "input corrupted"); else { - fwrite(buf, 1, len, stdout); - fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset); + fwrite(buf, 1, got, stdout); + fprintf(stderr, "zran: extracted %ld bytes at %lld\n", got, offset); } - /* clean up and exit */ + // Clean up and exit. deflate_index_free(index); fclose(in); return 0; diff --git a/zlib/examples/zran.h b/zlib/examples/zran.h index 2314125d6e9..ebf780d0c1f 100644 --- a/zlib/examples/zran.h +++ b/zlib/examples/zran.h @@ -1,40 +1,51 @@ -/* zran.h -- example of zlib/gzip stream indexing and random access - * Copyright (C) 2005, 2012, 2018 Mark Adler +/* zran.h -- example of deflated stream indexing and random access + * Copyright (C) 2005, 2012, 2018, 2023 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h - * Version 1.2 14 Oct 2018 Mark Adler */ + * Version 1.3 18 Feb 2023 Mark Adler */ #include #include "zlib.h" -/* Access point list. */ +// Access point. +typedef struct point { + off_t out; // offset in uncompressed data + off_t in; // offset in compressed file of first full byte + int bits; // 0, or number of bits (1-7) from byte at in-1 + unsigned char window[32768]; // preceding 32K of uncompressed data +} point_t; + +// Access point list. struct deflate_index { - int have; /* number of list entries */ - int gzip; /* 1 if the index is of a gzip file, 0 if it is of a - zlib stream */ - off_t length; /* total length of uncompressed data */ - void *list; /* allocated list of entries */ + int have; // number of access points in list + int mode; // -15 for raw, 15 for zlib, or 31 for gzip + off_t length; // total length of uncompressed data + point_t *list; // allocated list of access points }; -/* Make one entire pass through a zlib or gzip compressed stream and build an - index, with access points about every span bytes of uncompressed output. - gzip files with multiple members are indexed in their entirety. span should - be chosen to balance the speed of random access against the memory - requirements of the list, about 32K bytes per access point. The return value - is the number of access points on success (>= 1), Z_MEM_ERROR for out of - memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a file - read error. On success, *built points to the resulting index. */ +// Make one pass through a zlib, gzip, or raw deflate compressed stream and +// build an index, with access points about every span bytes of uncompressed +// output. gzip files with multiple members are fully indexed. span should be +// chosen to balance the speed of random access against the memory requirements +// of the list, which is about 32K bytes per access point. The return value is +// the number of access points on success (>= 1), Z_MEM_ERROR for out of +// memory, Z_BUF_ERROR for a premature end of input, Z_DATA_ERROR for a format +// or verification error in the input file, or Z_ERRNO for a file read error. +// On success, *built points to the resulting index. int deflate_index_build(FILE *in, off_t span, struct deflate_index **built); -/* Deallocate an index built by deflate_index_build() */ -void deflate_index_free(struct deflate_index *index); +// Use the index to read len bytes from offset into buf. Return the number of +// bytes read or a negative error code. If data is requested past the end of +// the uncompressed data, then deflate_index_extract() will return a value less +// than len, indicating how much was actually read into buf. If given a valid +// index, this function should not return an error unless the file was modified +// somehow since the index was generated, given that deflate_index_build() had +// validated all of the input. If nevertheless there is a failure, Z_BUF_ERROR +// is returned if the compressed data ends prematurely, Z_DATA_ERROR if the +// deflate compressed data is not valid, Z_MEM_ERROR if out of memory, +// Z_STREAM_ERROR if the index is not valid, or Z_ERRNO if there is an error +// reading or seeking on the input file. +ptrdiff_t deflate_index_extract(FILE *in, struct deflate_index *index, + off_t offset, unsigned char *buf, size_t len); -/* Use the index to read len bytes from offset into buf. Return bytes read or - negative for error (Z_DATA_ERROR or Z_MEM_ERROR). If data is requested past - the end of the uncompressed data, then deflate_index_extract() will return a - value less than len, indicating how much was actually read into buf. This - function should not return a data error unless the file was modified since - the index was generated, since deflate_index_build() validated all of the - input. deflate_index_extract() will return Z_ERRNO if there is an error on - reading or seeking the input file. */ -int deflate_index_extract(FILE *in, struct deflate_index *index, off_t offset, - unsigned char *buf, int len); +// Deallocate an index built by deflate_index_build(). +void deflate_index_free(struct deflate_index *index); diff --git a/zlib/gzclose.c b/zlib/gzclose.c index caeb99a3177..48d6a86f04b 100644 --- a/zlib/gzclose.c +++ b/zlib/gzclose.c @@ -8,9 +8,7 @@ /* gzclose() is in a separate file so that it is linked in only if it is used. That way the other gzclose functions can be used instead to avoid linking in unneeded compression or decompression routines. */ -int ZEXPORT gzclose(file) - gzFile file; -{ +int ZEXPORT gzclose(gzFile file) { #ifndef NO_GZCOMPRESS gz_statep state; diff --git a/zlib/gzguts.h b/zlib/gzguts.h index 57faf37165a..f9375047e8c 100644 --- a/zlib/gzguts.h +++ b/zlib/gzguts.h @@ -7,9 +7,8 @@ # ifndef _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE 1 # endif -# ifdef _FILE_OFFSET_BITS -# undef _FILE_OFFSET_BITS -# endif +# undef _FILE_OFFSET_BITS +# undef _TIME_BITS #endif #ifdef HAVE_HIDDEN @@ -119,8 +118,8 @@ /* gz* functions always use library allocation functions */ #ifndef STDC - extern voidp malloc OF((uInt size)); - extern void free OF((voidpf ptr)); + extern voidp malloc(uInt size); + extern void free(voidpf ptr); #endif /* get errno and strerror definition */ @@ -138,10 +137,10 @@ /* provide prototypes for these when building zlib without LFS */ #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); + ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); #endif /* default memLevel */ @@ -203,9 +202,9 @@ typedef struct { typedef gz_state FAR *gz_statep; /* shared functions */ -void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +void ZLIB_INTERNAL gz_error(gz_statep, int, const char *); #if defined UNDER_CE -char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +char ZLIB_INTERNAL *gz_strwinerror(DWORD error); #endif /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t @@ -214,6 +213,6 @@ char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); #ifdef INT_MAX # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) #else -unsigned ZLIB_INTERNAL gz_intmax OF((void)); +unsigned ZLIB_INTERNAL gz_intmax(void); # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) #endif diff --git a/zlib/gzlib.c b/zlib/gzlib.c index 55da46a453f..29fc4486fba 100644 --- a/zlib/gzlib.c +++ b/zlib/gzlib.c @@ -15,10 +15,6 @@ #endif #endif -/* Local functions */ -local void gz_reset OF((gz_statep)); -local gzFile gz_open OF((const void *, int, const char *)); - #if defined UNDER_CE /* Map the Windows error number in ERROR to a locale-dependent error message @@ -30,9 +26,7 @@ local gzFile gz_open OF((const void *, int, const char *)); The gz_strwinerror function does not change the current setting of GetLastError. */ -char ZLIB_INTERNAL *gz_strwinerror(error) - DWORD error; -{ +char ZLIB_INTERNAL *gz_strwinerror(DWORD error) { static char buf[1024]; wchar_t *msgbuf; @@ -72,9 +66,7 @@ char ZLIB_INTERNAL *gz_strwinerror(error) #endif /* UNDER_CE */ /* Reset gzip file state */ -local void gz_reset(state) - gz_statep state; -{ +local void gz_reset(gz_statep state) { state->x.have = 0; /* no output data available */ if (state->mode == GZ_READ) { /* for reading ... */ state->eof = 0; /* not at end of file */ @@ -90,11 +82,7 @@ local void gz_reset(state) } /* Open a gzip file either by name or file descriptor. */ -local gzFile gz_open(path, fd, mode) - const void *path; - int fd; - const char *mode; -{ +local gzFile gz_open(const void *path, int fd, const char *mode) { gz_statep state; z_size_t len; int oflag; @@ -269,26 +257,17 @@ local gzFile gz_open(path, fd, mode) } /* -- see zlib.h -- */ -gzFile ZEXPORT gzopen(path, mode) - const char *path; - const char *mode; -{ +gzFile ZEXPORT gzopen(const char *path, const char *mode) { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ -gzFile ZEXPORT gzopen64(path, mode) - const char *path; - const char *mode; -{ +gzFile ZEXPORT gzopen64(const char *path, const char *mode) { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ -gzFile ZEXPORT gzdopen(fd, mode) - int fd; - const char *mode; -{ +gzFile ZEXPORT gzdopen(int fd, const char *mode) { char *path; /* identifier for error messages */ gzFile gz; @@ -306,19 +285,13 @@ gzFile ZEXPORT gzdopen(fd, mode) /* -- see zlib.h -- */ #ifdef WIDECHAR -gzFile ZEXPORT gzopen_w(path, mode) - const wchar_t *path; - const char *mode; -{ +gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) { return gz_open(path, -2, mode); } #endif /* -- see zlib.h -- */ -int ZEXPORT gzbuffer(file, size) - gzFile file; - unsigned size; -{ +int ZEXPORT gzbuffer(gzFile file, unsigned size) { gz_statep state; /* get internal structure and check integrity */ @@ -335,16 +308,14 @@ int ZEXPORT gzbuffer(file, size) /* check and set requested size */ if ((size << 1) < size) return -1; /* need to be able to double it */ - if (size < 2) - size = 2; /* need two bytes to check magic header */ + if (size < 8) + size = 8; /* needed to behave well with flushing */ state->want = size; return 0; } /* -- see zlib.h -- */ -int ZEXPORT gzrewind(file) - gzFile file; -{ +int ZEXPORT gzrewind(gzFile file) { gz_statep state; /* get internal structure */ @@ -365,11 +336,7 @@ int ZEXPORT gzrewind(file) } /* -- see zlib.h -- */ -z_off64_t ZEXPORT gzseek64(file, offset, whence) - gzFile file; - z_off64_t offset; - int whence; -{ +z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { unsigned n; z_off64_t ret; gz_statep state; @@ -442,11 +409,7 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence) } /* -- see zlib.h -- */ -z_off_t ZEXPORT gzseek(file, offset, whence) - gzFile file; - z_off_t offset; - int whence; -{ +z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) { z_off64_t ret; ret = gzseek64(file, (z_off64_t)offset, whence); @@ -454,9 +417,7 @@ z_off_t ZEXPORT gzseek(file, offset, whence) } /* -- see zlib.h -- */ -z_off64_t ZEXPORT gztell64(file) - gzFile file; -{ +z_off64_t ZEXPORT gztell64(gzFile file) { gz_statep state; /* get internal structure and check integrity */ @@ -471,9 +432,7 @@ z_off64_t ZEXPORT gztell64(file) } /* -- see zlib.h -- */ -z_off_t ZEXPORT gztell(file) - gzFile file; -{ +z_off_t ZEXPORT gztell(gzFile file) { z_off64_t ret; ret = gztell64(file); @@ -481,9 +440,7 @@ z_off_t ZEXPORT gztell(file) } /* -- see zlib.h -- */ -z_off64_t ZEXPORT gzoffset64(file) - gzFile file; -{ +z_off64_t ZEXPORT gzoffset64(gzFile file) { z_off64_t offset; gz_statep state; @@ -504,9 +461,7 @@ z_off64_t ZEXPORT gzoffset64(file) } /* -- see zlib.h -- */ -z_off_t ZEXPORT gzoffset(file) - gzFile file; -{ +z_off_t ZEXPORT gzoffset(gzFile file) { z_off64_t ret; ret = gzoffset64(file); @@ -514,9 +469,7 @@ z_off_t ZEXPORT gzoffset(file) } /* -- see zlib.h -- */ -int ZEXPORT gzeof(file) - gzFile file; -{ +int ZEXPORT gzeof(gzFile file) { gz_statep state; /* get internal structure and check integrity */ @@ -531,10 +484,7 @@ int ZEXPORT gzeof(file) } /* -- see zlib.h -- */ -const char * ZEXPORT gzerror(file, errnum) - gzFile file; - int *errnum; -{ +const char * ZEXPORT gzerror(gzFile file, int *errnum) { gz_statep state; /* get internal structure and check integrity */ @@ -552,9 +502,7 @@ const char * ZEXPORT gzerror(file, errnum) } /* -- see zlib.h -- */ -void ZEXPORT gzclearerr(file) - gzFile file; -{ +void ZEXPORT gzclearerr(gzFile file) { gz_statep state; /* get internal structure and check integrity */ @@ -578,11 +526,7 @@ void ZEXPORT gzclearerr(file) memory). Simply save the error message as a static string. If there is an allocation failure constructing the error message, then convert the error to out of memory. */ -void ZLIB_INTERNAL gz_error(state, err, msg) - gz_statep state; - int err; - const char *msg; -{ +void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) { /* free previously allocated message and clear */ if (state->msg != NULL) { if (state->err != Z_MEM_ERROR) @@ -624,8 +568,7 @@ void ZLIB_INTERNAL gz_error(state, err, msg) available) -- we need to do this to cover cases where 2's complement not used, since C standard permits 1's complement and sign-bit representations, otherwise we could just use ((unsigned)-1) >> 1 */ -unsigned ZLIB_INTERNAL gz_intmax() -{ +unsigned ZLIB_INTERNAL gz_intmax(void) { unsigned p, q; p = 1; diff --git a/zlib/gzread.c b/zlib/gzread.c index dd77381596c..4168cbc8875 100644 --- a/zlib/gzread.c +++ b/zlib/gzread.c @@ -5,25 +5,12 @@ #include "gzguts.h" -/* Local functions */ -local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); -local int gz_avail OF((gz_statep)); -local int gz_look OF((gz_statep)); -local int gz_decomp OF((gz_statep)); -local int gz_fetch OF((gz_statep)); -local int gz_skip OF((gz_statep, z_off64_t)); -local z_size_t gz_read OF((gz_statep, voidp, z_size_t)); - /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from state->fd, and update state->eof, state->err, and state->msg as appropriate. This function needs to loop on read(), since read() is not guaranteed to read the number of bytes requested, depending on the type of descriptor. */ -local int gz_load(state, buf, len, have) - gz_statep state; - unsigned char *buf; - unsigned len; - unsigned *have; -{ +local int gz_load(gz_statep state, unsigned char *buf, unsigned len, + unsigned *have) { int ret; unsigned get, max = ((unsigned)-1 >> 2) + 1; @@ -53,9 +40,7 @@ local int gz_load(state, buf, len, have) If strm->avail_in != 0, then the current data is moved to the beginning of the input buffer, and then the remainder of the buffer is loaded with the available data from the input file. */ -local int gz_avail(state) - gz_statep state; -{ +local int gz_avail(gz_statep state) { unsigned got; z_streamp strm = &(state->strm); @@ -88,9 +73,7 @@ local int gz_avail(state) case, all further file reads will be directly to either the output buffer or a user buffer. If decompressing, the inflate state will be initialized. gz_look() will return 0 on success or -1 on failure. */ -local int gz_look(state) - gz_statep state; -{ +local int gz_look(gz_statep state) { z_streamp strm = &(state->strm); /* allocate read buffers and inflate memory */ @@ -170,9 +153,7 @@ local int gz_look(state) data. If the gzip stream completes, state->how is reset to LOOK to look for the next gzip stream or raw data, once state->x.have is depleted. Returns 0 on success, -1 on failure. */ -local int gz_decomp(state) - gz_statep state; -{ +local int gz_decomp(gz_statep state) { int ret = Z_OK; unsigned had; z_streamp strm = &(state->strm); @@ -224,9 +205,7 @@ local int gz_decomp(state) looked for to determine whether to copy or decompress. Returns -1 on error, otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the end of the input file has been reached and all data has been processed. */ -local int gz_fetch(state) - gz_statep state; -{ +local int gz_fetch(gz_statep state) { z_streamp strm = &(state->strm); do { @@ -254,10 +233,7 @@ local int gz_fetch(state) } /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ -local int gz_skip(state, len) - gz_statep state; - z_off64_t len; -{ +local int gz_skip(gz_statep state, z_off64_t len) { unsigned n; /* skip over len bytes or reach end-of-file, whichever comes first */ @@ -289,11 +265,7 @@ local int gz_skip(state, len) input. Return the number of bytes read. If zero is returned, either the end of file was reached, or there was an error. state->err must be consulted in that case to determine which. */ -local z_size_t gz_read(state, buf, len) - gz_statep state; - voidp buf; - z_size_t len; -{ +local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) { z_size_t got; unsigned n; @@ -370,11 +342,7 @@ local z_size_t gz_read(state, buf, len) } /* -- see zlib.h -- */ -int ZEXPORT gzread(file, buf, len) - gzFile file; - voidp buf; - unsigned len; -{ +int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) { gz_statep state; /* get internal structure */ @@ -406,12 +374,7 @@ int ZEXPORT gzread(file, buf, len) } /* -- see zlib.h -- */ -z_size_t ZEXPORT gzfread(buf, size, nitems, file) - voidp buf; - z_size_t size; - z_size_t nitems; - gzFile file; -{ +z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) { z_size_t len; gz_statep state; @@ -442,9 +405,7 @@ z_size_t ZEXPORT gzfread(buf, size, nitems, file) #else # undef gzgetc #endif -int ZEXPORT gzgetc(file) - gzFile file; -{ +int ZEXPORT gzgetc(gzFile file) { unsigned char buf[1]; gz_statep state; @@ -469,17 +430,12 @@ int ZEXPORT gzgetc(file) return gz_read(state, buf, 1) < 1 ? -1 : buf[0]; } -int ZEXPORT gzgetc_(file) -gzFile file; -{ +int ZEXPORT gzgetc_(gzFile file) { return gzgetc(file); } /* -- see zlib.h -- */ -int ZEXPORT gzungetc(c, file) - int c; - gzFile file; -{ +int ZEXPORT gzungetc(int c, gzFile file) { gz_statep state; /* get internal structure */ @@ -487,6 +443,10 @@ int ZEXPORT gzungetc(c, file) return -1; state = (gz_statep)file; + /* in case this was just opened, set up the input buffer */ + if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) + (void)gz_look(state); + /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) @@ -536,11 +496,7 @@ int ZEXPORT gzungetc(c, file) } /* -- see zlib.h -- */ -char * ZEXPORT gzgets(file, buf, len) - gzFile file; - char *buf; - int len; -{ +char * ZEXPORT gzgets(gzFile file, char *buf, int len) { unsigned left, n; char *str; unsigned char *eol; @@ -600,9 +556,7 @@ char * ZEXPORT gzgets(file, buf, len) } /* -- see zlib.h -- */ -int ZEXPORT gzdirect(file) - gzFile file; -{ +int ZEXPORT gzdirect(gzFile file) { gz_statep state; /* get internal structure */ @@ -620,9 +574,7 @@ int ZEXPORT gzdirect(file) } /* -- see zlib.h -- */ -int ZEXPORT gzclose_r(file) - gzFile file; -{ +int ZEXPORT gzclose_r(gzFile file) { int ret, err; gz_statep state; diff --git a/zlib/gzwrite.c b/zlib/gzwrite.c index eb8a0e5893f..435b4621b53 100644 --- a/zlib/gzwrite.c +++ b/zlib/gzwrite.c @@ -5,18 +5,10 @@ #include "gzguts.h" -/* Local functions */ -local int gz_init OF((gz_statep)); -local int gz_comp OF((gz_statep, int)); -local int gz_zero OF((gz_statep, z_off64_t)); -local z_size_t gz_write OF((gz_statep, voidpc, z_size_t)); - /* Initialize state for writing a gzip file. Mark initialization by setting state->size to non-zero. Return -1 on a memory allocation failure, or 0 on success. */ -local int gz_init(state) - gz_statep state; -{ +local int gz_init(gz_statep state) { int ret; z_streamp strm = &(state->strm); @@ -70,10 +62,7 @@ local int gz_init(state) deflate() flush value. If flush is Z_FINISH, then the deflate() state is reset to start a new gzip stream. If gz->direct is true, then simply write to the output file without compressing, and ignore flush. */ -local int gz_comp(state, flush) - gz_statep state; - int flush; -{ +local int gz_comp(gz_statep state, int flush) { int ret, writ; unsigned have, put, max = ((unsigned)-1 >> 2) + 1; z_streamp strm = &(state->strm); @@ -151,10 +140,7 @@ local int gz_comp(state, flush) /* Compress len zeros to output. Return -1 on a write error or memory allocation failure by gz_comp(), or 0 on success. */ -local int gz_zero(state, len) - gz_statep state; - z_off64_t len; -{ +local int gz_zero(gz_statep state, z_off64_t len) { int first; unsigned n; z_streamp strm = &(state->strm); @@ -184,11 +170,7 @@ local int gz_zero(state, len) /* Write len bytes from buf to file. Return the number of bytes written. If the returned value is less than len, then there was an error. */ -local z_size_t gz_write(state, buf, len) - gz_statep state; - voidpc buf; - z_size_t len; -{ +local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) { z_size_t put = len; /* if len is zero, avoid unnecessary operations */ @@ -252,11 +234,7 @@ local z_size_t gz_write(state, buf, len) } /* -- see zlib.h -- */ -int ZEXPORT gzwrite(file, buf, len) - gzFile file; - voidpc buf; - unsigned len; -{ +int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) { gz_statep state; /* get internal structure */ @@ -280,12 +258,8 @@ int ZEXPORT gzwrite(file, buf, len) } /* -- see zlib.h -- */ -z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) - voidpc buf; - z_size_t size; - z_size_t nitems; - gzFile file; -{ +z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems, + gzFile file) { z_size_t len; gz_statep state; @@ -310,10 +284,7 @@ z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) } /* -- see zlib.h -- */ -int ZEXPORT gzputc(file, c) - gzFile file; - int c; -{ +int ZEXPORT gzputc(gzFile file, int c) { unsigned have; unsigned char buf[1]; gz_statep state; @@ -358,10 +329,7 @@ int ZEXPORT gzputc(file, c) } /* -- see zlib.h -- */ -int ZEXPORT gzputs(file, s) - gzFile file; - const char *s; -{ +int ZEXPORT gzputs(gzFile file, const char *s) { z_size_t len, put; gz_statep state; @@ -388,8 +356,7 @@ int ZEXPORT gzputs(file, s) #include /* -- see zlib.h -- */ -int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) -{ +int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { int len; unsigned left; char *next; @@ -460,8 +427,7 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) return len; } -int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) -{ +int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) { va_list va; int ret; @@ -474,13 +440,10 @@ int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) #else /* !STDC && !Z_HAVE_STDARG_H */ /* -- see zlib.h -- */ -int ZEXPORTVA gzprintf(file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) - gzFile file; - const char *format; - int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; -{ +int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3, + int a4, int a5, int a6, int a7, int a8, int a9, int a10, + int a11, int a12, int a13, int a14, int a15, int a16, + int a17, int a18, int a19, int a20) { unsigned len, left; char *next; gz_statep state; @@ -562,10 +525,7 @@ int ZEXPORTVA gzprintf(file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, #endif /* -- see zlib.h -- */ -int ZEXPORT gzflush(file, flush) - gzFile file; - int flush; -{ +int ZEXPORT gzflush(gzFile file, int flush) { gz_statep state; /* get internal structure */ @@ -594,11 +554,7 @@ int ZEXPORT gzflush(file, flush) } /* -- see zlib.h -- */ -int ZEXPORT gzsetparams(file, level, strategy) - gzFile file; - int level; - int strategy; -{ +int ZEXPORT gzsetparams(gzFile file, int level, int strategy) { gz_statep state; z_streamp strm; @@ -609,7 +565,7 @@ int ZEXPORT gzsetparams(file, level, strategy) strm = &(state->strm); /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) + if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct) return Z_STREAM_ERROR; /* if no change is requested, then do nothing */ @@ -636,9 +592,7 @@ int ZEXPORT gzsetparams(file, level, strategy) } /* -- see zlib.h -- */ -int ZEXPORT gzclose_w(file) - gzFile file; -{ +int ZEXPORT gzclose_w(gzFile file) { int ret = Z_OK; gz_statep state; diff --git a/zlib/infback.c b/zlib/infback.c index babeaf1806f..e7b25b307a3 100644 --- a/zlib/infback.c +++ b/zlib/infback.c @@ -15,9 +15,6 @@ #include "inflate.h" #include "inffast.h" -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); - /* strm provides memory allocation functions in zalloc and zfree, or Z_NULL to use the library memory allocation functions. @@ -25,13 +22,9 @@ local void fixedtables OF((struct inflate_state FAR *state)); windowBits is in the range 8..15, and window is a user-supplied window and output buffer that is 2**windowBits bytes. */ -int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) -z_streamp strm; -int windowBits; -unsigned char FAR *window; -const char *version; -int stream_size; -{ +int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, + unsigned char FAR *window, const char *version, + int stream_size) { struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || @@ -80,9 +73,7 @@ int stream_size; used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ -local void fixedtables(state) -struct inflate_state FAR *state; -{ +local void fixedtables(struct inflate_state FAR *state) { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; @@ -248,13 +239,8 @@ struct inflate_state FAR *state; inflateBack() can also return Z_STREAM_ERROR if the input parameters are not correct, i.e. strm is Z_NULL or the state was not initialized. */ -int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) -z_streamp strm; -in_func in; -void FAR *in_desc; -out_func out; -void FAR *out_desc; -{ +int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc) { struct inflate_state FAR *state; z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ @@ -632,9 +618,7 @@ void FAR *out_desc; return ret; } -int ZEXPORT inflateBackEnd(strm) -z_streamp strm; -{ +int ZEXPORT inflateBackEnd(z_streamp strm) { if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; ZFREE(strm, strm->state); diff --git a/zlib/inffast.c b/zlib/inffast.c index 1fec7f363fa..9354676e786 100644 --- a/zlib/inffast.c +++ b/zlib/inffast.c @@ -47,10 +47,7 @@ requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ -void ZLIB_INTERNAL inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ +void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) { struct inflate_state FAR *state; z_const unsigned char FAR *in; /* local strm->next_in */ z_const unsigned char FAR *last; /* have enough input while in < last */ diff --git a/zlib/inffast.h b/zlib/inffast.h index e5c1aa4ca8c..49c6d156c5c 100644 --- a/zlib/inffast.h +++ b/zlib/inffast.h @@ -8,4 +8,4 @@ subject to change. Applications should only use zlib.h. */ -void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); +void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start); diff --git a/zlib/inflate.c b/zlib/inflate.c index 8acbef44e99..b0757a9b249 100644 --- a/zlib/inflate.c +++ b/zlib/inflate.c @@ -91,20 +91,7 @@ # endif #endif -/* function prototypes */ -local int inflateStateCheck OF((z_streamp strm)); -local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, - unsigned copy)); -#ifdef BUILDFIXED - void makefixed OF((void)); -#endif -local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, - unsigned len)); - -local int inflateStateCheck(strm) -z_streamp strm; -{ +local int inflateStateCheck(z_streamp strm) { struct inflate_state FAR *state; if (strm == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) @@ -116,9 +103,7 @@ z_streamp strm; return 0; } -int ZEXPORT inflateResetKeep(strm) -z_streamp strm; -{ +int ZEXPORT inflateResetKeep(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -142,9 +127,7 @@ z_streamp strm; return Z_OK; } -int ZEXPORT inflateReset(strm) -z_streamp strm; -{ +int ZEXPORT inflateReset(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -155,10 +138,7 @@ z_streamp strm; return inflateResetKeep(strm); } -int ZEXPORT inflateReset2(strm, windowBits) -z_streamp strm; -int windowBits; -{ +int ZEXPORT inflateReset2(z_streamp strm, int windowBits) { int wrap; struct inflate_state FAR *state; @@ -195,12 +175,8 @@ int windowBits; return inflateReset(strm); } -int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) -z_streamp strm; -int windowBits; -const char *version; -int stream_size; -{ +int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size) { int ret; struct inflate_state FAR *state; @@ -239,22 +215,17 @@ int stream_size; return ret; } -int ZEXPORT inflateInit_(strm, version, stream_size) -z_streamp strm; -const char *version; -int stream_size; -{ +int ZEXPORT inflateInit_(z_streamp strm, const char *version, + int stream_size) { return inflateInit2_(strm, DEF_WBITS, version, stream_size); } -int ZEXPORT inflatePrime(strm, bits, value) -z_streamp strm; -int bits; -int value; -{ +int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + if (bits == 0) + return Z_OK; state = (struct inflate_state FAR *)strm->state; if (bits < 0) { state->hold = 0; @@ -278,9 +249,7 @@ int value; used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ -local void fixedtables(state) -struct inflate_state FAR *state; -{ +local void fixedtables(struct inflate_state FAR *state) { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; @@ -342,7 +311,7 @@ struct inflate_state FAR *state; a.out > inffixed.h */ -void makefixed() +void makefixed(void) { unsigned low, size; struct inflate_state state; @@ -396,11 +365,7 @@ void makefixed() output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ -local int updatewindow(strm, end, copy) -z_streamp strm; -const Bytef *end; -unsigned copy; -{ +local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) { struct inflate_state FAR *state; unsigned dist; @@ -622,10 +587,7 @@ unsigned copy; will return Z_BUF_ERROR if it has not reached the end of the stream. */ -int ZEXPORT inflate(strm, flush) -z_streamp strm; -int flush; -{ +int ZEXPORT inflate(z_streamp strm, int flush) { struct inflate_state FAR *state; z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ @@ -1301,9 +1263,7 @@ int flush; return ret; } -int ZEXPORT inflateEnd(strm) -z_streamp strm; -{ +int ZEXPORT inflateEnd(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -1315,11 +1275,8 @@ z_streamp strm; return Z_OK; } -int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) -z_streamp strm; -Bytef *dictionary; -uInt *dictLength; -{ +int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary, + uInt *dictLength) { struct inflate_state FAR *state; /* check state */ @@ -1338,11 +1295,8 @@ uInt *dictLength; return Z_OK; } -int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) -z_streamp strm; -const Bytef *dictionary; -uInt dictLength; -{ +int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, + uInt dictLength) { struct inflate_state FAR *state; unsigned long dictid; int ret; @@ -1373,10 +1327,7 @@ uInt dictLength; return Z_OK; } -int ZEXPORT inflateGetHeader(strm, head) -z_streamp strm; -gz_headerp head; -{ +int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) { struct inflate_state FAR *state; /* check state */ @@ -1401,11 +1352,8 @@ gz_headerp head; called again with more data and the *have state. *have is initialized to zero for the first call. */ -local unsigned syncsearch(have, buf, len) -unsigned FAR *have; -const unsigned char FAR *buf; -unsigned len; -{ +local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf, + unsigned len) { unsigned got; unsigned next; @@ -1424,9 +1372,7 @@ unsigned len; return next; } -int ZEXPORT inflateSync(strm) -z_streamp strm; -{ +int ZEXPORT inflateSync(z_streamp strm) { unsigned len; /* number of bytes to look at or looked at */ int flags; /* temporary to save header status */ unsigned long in, out; /* temporary to save total_in and total_out */ @@ -1482,9 +1428,7 @@ z_streamp strm; block. When decompressing, PPP checks that at the end of input packet, inflate is waiting for these length bytes. */ -int ZEXPORT inflateSyncPoint(strm) -z_streamp strm; -{ +int ZEXPORT inflateSyncPoint(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -1492,10 +1436,7 @@ z_streamp strm; return state->mode == STORED && state->bits == 0; } -int ZEXPORT inflateCopy(dest, source) -z_streamp dest; -z_streamp source; -{ +int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) { struct inflate_state FAR *state; struct inflate_state FAR *copy; unsigned char FAR *window; @@ -1539,10 +1480,7 @@ z_streamp source; return Z_OK; } -int ZEXPORT inflateUndermine(strm, subvert) -z_streamp strm; -int subvert; -{ +int ZEXPORT inflateUndermine(z_streamp strm, int subvert) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -1557,10 +1495,7 @@ int subvert; #endif } -int ZEXPORT inflateValidate(strm, check) -z_streamp strm; -int check; -{ +int ZEXPORT inflateValidate(z_streamp strm, int check) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -1572,9 +1507,7 @@ int check; return Z_OK; } -long ZEXPORT inflateMark(strm) -z_streamp strm; -{ +long ZEXPORT inflateMark(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) @@ -1585,9 +1518,7 @@ z_streamp strm; (state->mode == MATCH ? state->was - state->length : 0)); } -unsigned long ZEXPORT inflateCodesUsed(strm) -z_streamp strm; -{ +unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return (unsigned long)-1; state = (struct inflate_state FAR *)strm->state; diff --git a/zlib/inftrees.c b/zlib/inftrees.c index 57d2793bec9..8a208c2daa8 100644 --- a/zlib/inftrees.c +++ b/zlib/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2022 Mark Adler + * Copyright (C) 1995-2023 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.13 Copyright 1995-2022 Mark Adler "; + " inflate 1.3 Copyright 1995-2023 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -29,14 +29,9 @@ const char inflate_copyright[] = table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ -int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) -codetype type; -unsigned short FAR *lens; -unsigned codes; -code FAR * FAR *table; -unsigned FAR *bits; -unsigned short FAR *work; -{ +int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work) { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ unsigned min, max; /* minimum and maximum code lengths */ @@ -62,7 +57,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 194, 65}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 203}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, diff --git a/zlib/inftrees.h b/zlib/inftrees.h index f53665311c1..a10712d8cb5 100644 --- a/zlib/inftrees.h +++ b/zlib/inftrees.h @@ -57,6 +57,6 @@ typedef enum { DISTS } codetype; -int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); +int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work); diff --git a/zlib/os400/README400 b/zlib/os400/README400 index c06fa8459a0..6dd41aa6510 100644 --- a/zlib/os400/README400 +++ b/zlib/os400/README400 @@ -1,4 +1,4 @@ - ZLIB version 1.2.13 for OS/400 installation instructions + ZLIB version 1.3.0 for OS/400 installation instructions 1) Download and unpack the zlib tarball to some IFS directory. (i.e.: /path/to/the/zlib/ifs/source/directory) diff --git a/zlib/os400/zlib.inc b/zlib/os400/zlib.inc index c273c863c61..0d9e2f2090b 100644 --- a/zlib/os400/zlib.inc +++ b/zlib/os400/zlib.inc @@ -1,7 +1,7 @@ * ZLIB.INC - Interface to the general purpose compression library * * ILE RPG400 version by Patrick Monnerat, DATASPHERE. - * Version 1.2.13 + * Version 1.3.0 * * * WARNING: @@ -22,12 +22,12 @@ * * Versioning information. * - D ZLIB_VERSION C '1.2.13' + D ZLIB_VERSION C '1.3.0' D ZLIB_VERNUM C X'12a0' D ZLIB_VER_MAJOR C 1 - D ZLIB_VER_MINOR C 2 + D ZLIB_VER_MINOR C 3 D ZLIB_VER_REVISION... - D C 13 + D C 0 D ZLIB_VER_SUBREVISION... D C 0 * diff --git a/zlib/qnx/package.qpg b/zlib/qnx/package.qpg index ba2f1a2d6c3..d882af2bfb3 100644 --- a/zlib/qnx/package.qpg +++ b/zlib/qnx/package.qpg @@ -25,10 +25,10 @@ - - - - + + + + @@ -63,7 +63,7 @@ - 1.2.13 + 1.3.0 Medium Stable diff --git a/zlib/test/example.c b/zlib/test/example.c index 1470bc842ee..582a17a3ce9 100644 --- a/zlib/test/example.c +++ b/zlib/test/example.c @@ -34,37 +34,14 @@ static z_const char hello[] = "hello, hello!"; static const char dictionary[] = "hello"; static uLong dictId; /* Adler32 value of the dictionary */ -void test_deflate OF((Byte *compr, uLong comprLen)); -void test_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_deflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_flush OF((Byte *compr, uLong *comprLen)); -void test_sync OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_dict_deflate OF((Byte *compr, uLong comprLen)); -void test_dict_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -int main OF((int argc, char *argv[])); - - #ifdef Z_SOLO -void *myalloc OF((void *, unsigned, unsigned)); -void myfree OF((void *, void *)); - -void *myalloc(q, n, m) - void *q; - unsigned n, m; -{ +void *myalloc(void *q, unsigned n, unsigned m) { (void)q; return calloc(n, m); } -void myfree(void *q, void *p) -{ +void myfree(void *q, void *p) { (void)q; free(p); } @@ -77,18 +54,11 @@ static free_func zfree = myfree; static alloc_func zalloc = (alloc_func)0; static free_func zfree = (free_func)0; -void test_compress OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_gzio OF((const char *fname, - Byte *uncompr, uLong uncomprLen)); - /* =========================================================================== * Test compress() and uncompress() */ -void test_compress(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ +void test_compress(Byte *compr, uLong comprLen, Byte *uncompr, + uLong uncomprLen) { int err; uLong len = (uLong)strlen(hello)+1; @@ -111,11 +81,7 @@ void test_compress(compr, comprLen, uncompr, uncomprLen) /* =========================================================================== * Test read/write of .gz files */ -void test_gzio(fname, uncompr, uncomprLen) - const char *fname; /* compressed file name */ - Byte *uncompr; - uLong uncomprLen; -{ +void test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) { #ifdef NO_GZCOMPRESS fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); #else @@ -197,10 +163,7 @@ void test_gzio(fname, uncompr, uncomprLen) /* =========================================================================== * Test deflate() with small buffers */ -void test_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ +void test_deflate(Byte *compr, uLong comprLen) { z_stream c_stream; /* compression stream */ int err; uLong len = (uLong)strlen(hello)+1; @@ -235,10 +198,8 @@ void test_deflate(compr, comprLen) /* =========================================================================== * Test inflate() with small buffers */ -void test_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ +void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr, + uLong uncomprLen) { int err; z_stream d_stream; /* decompression stream */ @@ -276,10 +237,8 @@ void test_inflate(compr, comprLen, uncompr, uncomprLen) /* =========================================================================== * Test deflate() with large buffers and dynamic change of compression level */ -void test_large_deflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ +void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr, + uLong uncomprLen) { z_stream c_stream; /* compression stream */ int err; @@ -308,7 +267,7 @@ void test_large_deflate(compr, comprLen, uncompr, uncomprLen) /* Feed in already compressed data and switch to no compression: */ deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); c_stream.next_in = compr; - c_stream.avail_in = (uInt)comprLen/2; + c_stream.avail_in = (uInt)uncomprLen/2; err = deflate(&c_stream, Z_NO_FLUSH); CHECK_ERR(err, "deflate"); @@ -331,10 +290,8 @@ void test_large_deflate(compr, comprLen, uncompr, uncomprLen) /* =========================================================================== * Test inflate() with large buffers */ -void test_large_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ +void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr, + uLong uncomprLen) { int err; z_stream d_stream; /* decompression stream */ @@ -361,7 +318,7 @@ void test_large_inflate(compr, comprLen, uncompr, uncomprLen) err = inflateEnd(&d_stream); CHECK_ERR(err, "inflateEnd"); - if (d_stream.total_out != 2*uncomprLen + comprLen/2) { + if (d_stream.total_out != 2*uncomprLen + uncomprLen/2) { fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); exit(1); } else { @@ -372,10 +329,7 @@ void test_large_inflate(compr, comprLen, uncompr, uncomprLen) /* =========================================================================== * Test deflate() with full flush */ -void test_flush(compr, comprLen) - Byte *compr; - uLong *comprLen; -{ +void test_flush(Byte *compr, uLong *comprLen) { z_stream c_stream; /* compression stream */ int err; uInt len = (uInt)strlen(hello)+1; @@ -410,10 +364,7 @@ void test_flush(compr, comprLen) /* =========================================================================== * Test inflateSync() */ -void test_sync(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ +void test_sync(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) { int err; z_stream d_stream; /* decompression stream */ @@ -453,10 +404,7 @@ void test_sync(compr, comprLen, uncompr, uncomprLen) /* =========================================================================== * Test deflate() with preset dictionary */ -void test_dict_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ +void test_dict_deflate(Byte *compr, uLong comprLen) { z_stream c_stream; /* compression stream */ int err; @@ -490,10 +438,8 @@ void test_dict_deflate(compr, comprLen) /* =========================================================================== * Test inflate() with a preset dictionary */ -void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ +void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr, + uLong uncomprLen) { int err; z_stream d_stream; /* decompression stream */ @@ -541,13 +487,10 @@ void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) * Usage: example [output.gz [input.gz]] */ -int main(argc, argv) - int argc; - char *argv[]; -{ +int main(int argc, char *argv[]) { Byte *compr, *uncompr; - uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ - uLong uncomprLen = comprLen; + uLong uncomprLen = 20000; + uLong comprLen = 3 * uncomprLen; static const char* myVersion = ZLIB_VERSION; if (zlibVersion()[0] != myVersion[0]) { @@ -590,7 +533,7 @@ int main(argc, argv) test_flush(compr, &comprLen); test_sync(compr, comprLen, uncompr, uncomprLen); - comprLen = uncomprLen; + comprLen = 3 * uncomprLen; test_dict_deflate(compr, comprLen); test_dict_inflate(compr, comprLen, uncompr, uncomprLen); diff --git a/zlib/test/infcover.c b/zlib/test/infcover.c index 2be01646cec..8912c403dd2 100644 --- a/zlib/test/infcover.c +++ b/zlib/test/infcover.c @@ -373,7 +373,7 @@ local void cover_support(void) mem_setup(&strm); strm.avail_in = 0; strm.next_in = Z_NULL; - ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream)); + ret = inflateInit_(&strm, "!", (int)sizeof(z_stream)); assert(ret == Z_VERSION_ERROR); mem_done(&strm, "wrong version"); @@ -462,7 +462,8 @@ local unsigned pull(void *desc, unsigned char **buf) local int push(void *desc, unsigned char *buf, unsigned len) { - buf += len; + (void)buf; + (void)len; return desc != Z_NULL; /* force error if desc not null */ } diff --git a/zlib/test/minigzip.c b/zlib/test/minigzip.c index a649d2b3d9b..8a21ddfb57e 100644 --- a/zlib/test/minigzip.c +++ b/zlib/test/minigzip.c @@ -59,7 +59,7 @@ #if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) #ifndef WIN32 /* unlink already in stdio.h for WIN32 */ - extern int unlink OF((const char *)); + extern int unlink(const char *); #endif #endif @@ -149,20 +149,12 @@ static void pwinerror (s) # include /* for unlink() */ #endif -void *myalloc OF((void *, unsigned, unsigned)); -void myfree OF((void *, void *)); - -void *myalloc(q, n, m) - void *q; - unsigned n, m; -{ +void *myalloc(void *q, unsigned n, unsigned m) { (void)q; return calloc(n, m); } -void myfree(q, p) - void *q, *p; -{ +void myfree(void *q, void *p) { (void)q; free(p); } @@ -175,29 +167,7 @@ typedef struct gzFile_s { z_stream strm; } *gzFile; -gzFile gzopen OF((const char *, const char *)); -gzFile gzdopen OF((int, const char *)); -gzFile gz_open OF((const char *, int, const char *)); - -gzFile gzopen(path, mode) -const char *path; -const char *mode; -{ - return gz_open(path, -1, mode); -} - -gzFile gzdopen(fd, mode) -int fd; -const char *mode; -{ - return gz_open(NULL, fd, mode); -} - -gzFile gz_open(path, fd, mode) - const char *path; - int fd; - const char *mode; -{ +gzFile gz_open(const char *path, int fd, const char *mode) { gzFile gz; int ret; @@ -231,13 +201,15 @@ gzFile gz_open(path, fd, mode) return gz; } -int gzwrite OF((gzFile, const void *, unsigned)); +gzFile gzopen(const char *path, const char *mode) { + return gz_open(path, -1, mode); +} -int gzwrite(gz, buf, len) - gzFile gz; - const void *buf; - unsigned len; -{ +gzFile gzdopen(int fd, const char *mode) { + return gz_open(NULL, fd, mode); +} + +int gzwrite(gzFile gz, const void *buf, unsigned len) { z_stream *strm; unsigned char out[BUFLEN]; @@ -255,13 +227,7 @@ int gzwrite(gz, buf, len) return len; } -int gzread OF((gzFile, void *, unsigned)); - -int gzread(gz, buf, len) - gzFile gz; - void *buf; - unsigned len; -{ +int gzread(gzFile gz, void *buf, unsigned len) { int ret; unsigned got; unsigned char in[1]; @@ -292,11 +258,7 @@ int gzread(gz, buf, len) return len - strm->avail_out; } -int gzclose OF((gzFile)); - -int gzclose(gz) - gzFile gz; -{ +int gzclose(gzFile gz) { z_stream *strm; unsigned char out[BUFLEN]; @@ -321,12 +283,7 @@ int gzclose(gz) return Z_OK; } -const char *gzerror OF((gzFile, int *)); - -const char *gzerror(gz, err) - gzFile gz; - int *err; -{ +const char *gzerror(gzFile gz, int *err) { *err = gz->err; return gz->msg; } @@ -335,67 +292,20 @@ const char *gzerror(gz, err) static char *prog; -void error OF((const char *msg)); -void gz_compress OF((FILE *in, gzFile out)); -#ifdef USE_MMAP -int gz_compress_mmap OF((FILE *in, gzFile out)); -#endif -void gz_uncompress OF((gzFile in, FILE *out)); -void file_compress OF((char *file, char *mode)); -void file_uncompress OF((char *file)); -int main OF((int argc, char *argv[])); - /* =========================================================================== * Display error message and exit */ -void error(msg) - const char *msg; -{ +void error(const char *msg) { fprintf(stderr, "%s: %s\n", prog, msg); exit(1); } -/* =========================================================================== - * Compress input to output then close both files. - */ - -void gz_compress(in, out) - FILE *in; - gzFile out; -{ - local char buf[BUFLEN]; - int len; - int err; - -#ifdef USE_MMAP - /* Try first compressing with mmap. If mmap fails (minigzip used in a - * pipe), use the normal fread loop. - */ - if (gz_compress_mmap(in, out) == Z_OK) return; -#endif - for (;;) { - len = (int)fread(buf, 1, sizeof(buf), in); - if (ferror(in)) { - perror("fread"); - exit(1); - } - if (len == 0) break; - - if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); - } - fclose(in); - if (gzclose(out) != Z_OK) error("failed gzclose"); -} - #ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ /* Try compressing the input file at once using mmap. Return Z_OK if * if success, Z_ERRNO otherwise. */ -int gz_compress_mmap(in, out) - FILE *in; - gzFile out; -{ +int gz_compress_mmap(FILE *in, gzFile out) { int len; int err; int ifd = fileno(in); @@ -424,13 +334,39 @@ int gz_compress_mmap(in, out) } #endif /* USE_MMAP */ +/* =========================================================================== + * Compress input to output then close both files. + */ + +void gz_compress(FILE *in, gzFile out) { + local char buf[BUFLEN]; + int len; + int err; + +#ifdef USE_MMAP + /* Try first compressing with mmap. If mmap fails (minigzip used in a + * pipe), use the normal fread loop. + */ + if (gz_compress_mmap(in, out) == Z_OK) return; +#endif + for (;;) { + len = (int)fread(buf, 1, sizeof(buf), in); + if (ferror(in)) { + perror("fread"); + exit(1); + } + if (len == 0) break; + + if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); + } + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); +} + /* =========================================================================== * Uncompress input to output then close both files. */ -void gz_uncompress(in, out) - gzFile in; - FILE *out; -{ +void gz_uncompress(gzFile in, FILE *out) { local char buf[BUFLEN]; int len; int err; @@ -454,10 +390,7 @@ void gz_uncompress(in, out) * Compress the given file: create a corresponding .gz file and remove the * original. */ -void file_compress(file, mode) - char *file; - char *mode; -{ +void file_compress(char *file, char *mode) { local char outfile[MAX_NAME_LEN]; FILE *in; gzFile out; @@ -493,9 +426,7 @@ void file_compress(file, mode) /* =========================================================================== * Uncompress the given file and remove the original. */ -void file_uncompress(file) - char *file; -{ +void file_uncompress(char *file) { local char buf[MAX_NAME_LEN]; char *infile, *outfile; FILE *out; @@ -553,10 +484,7 @@ void file_uncompress(file) * -1 to -9 : compression level */ -int main(argc, argv) - int argc; - char *argv[]; -{ +int main(int argc, char *argv[]) { int copyout = 0; int uncompr = 0; gzFile file; diff --git a/zlib/treebuild.xml b/zlib/treebuild.xml index 0017a45d3c5..1d1b007707c 100644 --- a/zlib/treebuild.xml +++ b/zlib/treebuild.xml @@ -1,6 +1,6 @@ - - + + zip compression library diff --git a/zlib/trees.c b/zlib/trees.c index 5f305c47221..8dbdc40bacc 100644 --- a/zlib/trees.c +++ b/zlib/trees.c @@ -122,39 +122,116 @@ struct static_tree_desc_s { int max_length; /* max bit length for the codes */ }; -local const static_tree_desc static_l_desc = +#ifdef NO_INIT_GLOBAL_POINTERS +# define TCONST +#else +# define TCONST const +#endif + +local TCONST static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; -local const static_tree_desc static_d_desc = +local TCONST static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; -local const static_tree_desc static_bl_desc = +local TCONST static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== - * Local (static) routines in this file. + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} -local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local int build_bl_tree OF((deflate_state *s)); -local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); -local void compress_block OF((deflate_state *s, const ct_data *ltree, - const ct_data *dtree)); -local int detect_data_type OF((deflate_state *s)); -local unsigned bi_reverse OF((unsigned code, int len)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(unsigned code, int len) { + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(deflate_state *s) { + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(deflate_state *s) { + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef ZLIB_DEBUG + s->bits_sent = (s->bits_sent + 7) & ~7; +#endif +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes(ct_data *tree, int max_code, ushf *bl_count) { + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + unsigned code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + code = (code + bl_count[bits - 1]) << 1; + next_code[bits] = (ush)code; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1, + "inconsistent bit counts"); + Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n].Len; + if (len == 0) continue; + /* Now reverse the bits */ + tree[n].Code = (ush)bi_reverse(next_code[len]++, len); + + Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", + n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1)); + } +} #ifdef GEN_TREES_H -local void gen_trees_header OF((void)); +local void gen_trees_header(void); #endif #ifndef ZLIB_DEBUG @@ -167,27 +244,12 @@ local void gen_trees_header OF((void)); send_bits(s, tree[c].Code, tree[c].Len); } #endif -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - /* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ #ifdef ZLIB_DEBUG -local void send_bits OF((deflate_state *s, int value, int length)); - -local void send_bits(s, value, length) - deflate_state *s; - int value; /* value to send */ - int length; /* number of bits */ -{ +local void send_bits(deflate_state *s, int value, int length) { Tracevv((stderr," l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); s->bits_sent += (ulg)length; @@ -229,8 +291,7 @@ local void send_bits(s, value, length) /* =========================================================================== * Initialize the various 'constant' tables. */ -local void tr_static_init() -{ +local void tr_static_init(void) { #if defined(GEN_TREES_H) || !defined(STDC) static int static_init_done = 0; int n; /* iterates over tree elements */ @@ -323,8 +384,7 @@ local void tr_static_init() ((i) == (last)? "\n};\n\n" : \ ((i) % (width) == (width) - 1 ? ",\n" : ", ")) -void gen_trees_header() -{ +void gen_trees_header(void) { FILE *header = fopen("trees.h", "w"); int i; @@ -373,12 +433,26 @@ void gen_trees_header() } #endif /* GEN_TREES_H */ +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(deflate_state *s) { + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->sym_next = s->matches = 0; +} + /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ -void ZLIB_INTERNAL _tr_init(s) - deflate_state *s; -{ +void ZLIB_INTERNAL _tr_init(deflate_state *s) { tr_static_init(); s->l_desc.dyn_tree = s->dyn_ltree; @@ -401,24 +475,6 @@ void ZLIB_INTERNAL _tr_init(s) init_block(s); } -/* =========================================================================== - * Initialize a new block. - */ -local void init_block(s) - deflate_state *s; -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->sym_next = s->matches = 0; -} - #define SMALLEST 1 /* Index within the heap array of least frequent node in the Huffman tree */ @@ -448,11 +504,7 @@ local void init_block(s) * when the heap property is re-established (each father smaller than its * two sons). */ -local void pqdownheap(s, tree, k) - deflate_state *s; - ct_data *tree; /* the tree to restore */ - int k; /* node to move down */ -{ +local void pqdownheap(deflate_state *s, ct_data *tree, int k) { int v = s->heap[k]; int j = k << 1; /* left son of k */ while (j <= s->heap_len) { @@ -483,10 +535,7 @@ local void pqdownheap(s, tree, k) * The length opt_len is updated; static_len is also updated if stree is * not null. */ -local void gen_bitlen(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ +local void gen_bitlen(deflate_state *s, tree_desc *desc) { ct_data *tree = desc->dyn_tree; int max_code = desc->max_code; const ct_data *stree = desc->stat_desc->static_tree; @@ -561,48 +610,9 @@ local void gen_bitlen(s, desc) } } -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes(tree, max_code, bl_count) - ct_data *tree; /* the tree to decorate */ - int max_code; /* largest code with non zero frequency */ - ushf *bl_count; /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - unsigned code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - code = (code + bl_count[bits - 1]) << 1; - next_code[bits] = (ush)code; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1, - "inconsistent bit counts"); - Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); - - for (n = 0; n <= max_code; n++) { - int len = tree[n].Len; - if (len == 0) continue; - /* Now reverse the bits */ - tree[n].Code = (ush)bi_reverse(next_code[len]++, len); - - Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", - n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1)); - } -} +#ifdef DUMP_BL_TREE +# include +#endif /* =========================================================================== * Construct one Huffman tree and assigns the code bit strings and lengths. @@ -612,10 +622,7 @@ local void gen_codes(tree, max_code, bl_count) * and corresponding code. The length opt_len is updated; static_len is * also updated if stree is not null. The field max_code is set. */ -local void build_tree(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ +local void build_tree(deflate_state *s, tree_desc *desc) { ct_data *tree = desc->dyn_tree; const ct_data *stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; @@ -700,11 +707,7 @@ local void build_tree(s, desc) * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ -local void scan_tree(s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ +local void scan_tree(deflate_state *s, ct_data *tree, int max_code) { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ @@ -745,11 +748,7 @@ local void scan_tree(s, tree, max_code) * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ -local void send_tree(s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ +local void send_tree(deflate_state *s, ct_data *tree, int max_code) { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ @@ -796,9 +795,7 @@ local void send_tree(s, tree, max_code) * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */ -local int build_bl_tree(s) - deflate_state *s; -{ +local int build_bl_tree(deflate_state *s) { int max_blindex; /* index of last bit length code of non zero freq */ /* Determine the bit length frequencies for literal and distance trees */ @@ -831,10 +828,8 @@ local int build_bl_tree(s) * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ -local void send_all_trees(s, lcodes, dcodes, blcodes) - deflate_state *s; - int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ +local void send_all_trees(deflate_state *s, int lcodes, int dcodes, + int blcodes) { int rank; /* index in bl_order */ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); @@ -860,12 +855,8 @@ local void send_all_trees(s, lcodes, dcodes, blcodes) /* =========================================================================== * Send a stored block */ -void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) - deflate_state *s; - charf *buf; /* input block */ - ulg stored_len; /* length of input block */ - int last; /* one if this is the last block for a file */ -{ +void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, + ulg stored_len, int last) { send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */ bi_windup(s); /* align on byte boundary */ put_short(s, (ush)stored_len); @@ -884,9 +875,7 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) /* =========================================================================== * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) */ -void ZLIB_INTERNAL _tr_flush_bits(s) - deflate_state *s; -{ +void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s) { bi_flush(s); } @@ -894,9 +883,7 @@ void ZLIB_INTERNAL _tr_flush_bits(s) * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. */ -void ZLIB_INTERNAL _tr_align(s) - deflate_state *s; -{ +void ZLIB_INTERNAL _tr_align(deflate_state *s) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef ZLIB_DEBUG @@ -905,16 +892,99 @@ void ZLIB_INTERNAL _tr_align(s) bi_flush(s); } +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(deflate_state *s, const ct_data *ltree, + const ct_data *dtree) { + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned sx = 0; /* running index in sym_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->sym_next != 0) do { + dist = s->sym_buf[sx++] & 0xff; + dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; + lc = s->sym_buf[sx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code + LITERALS + 1, ltree); /* send length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= (unsigned)base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and sym_buf is ok: */ + Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); + + } while (sx < s->sym_next); + + send_code(s, END_BLOCK, ltree); +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "block list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(deflate_state *s) { + /* block_mask is the bit mask of block-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long block_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("block-listed") bytes. */ + for (n = 0; n <= 31; n++, block_mask >>= 1) + if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("allow-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "block-listed" or "allow-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and write out the encoded block. */ -void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) - deflate_state *s; - charf *buf; /* input block, or NULL if too old */ - ulg stored_len; /* length of input block */ - int last; /* one if this is the last block for a file */ -{ +void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, + ulg stored_len, int last) { ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex = 0; /* index of last bit length code of non zero freq */ @@ -1011,11 +1081,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ -int ZLIB_INTERNAL _tr_tally(s, dist, lc) - deflate_state *s; - unsigned dist; /* distance of matched string */ - unsigned lc; /* match length - MIN_MATCH or unmatched char (dist==0) */ -{ +int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) { s->sym_buf[s->sym_next++] = (uch)dist; s->sym_buf[s->sym_next++] = (uch)(dist >> 8); s->sym_buf[s->sym_next++] = (uch)lc; @@ -1035,147 +1101,3 @@ int ZLIB_INTERNAL _tr_tally(s, dist, lc) } return (s->sym_next == s->sym_end); } - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -local void compress_block(s, ltree, dtree) - deflate_state *s; - const ct_data *ltree; /* literal tree */ - const ct_data *dtree; /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned sx = 0; /* running index in sym_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->sym_next != 0) do { - dist = s->sym_buf[sx++] & 0xff; - dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; - lc = s->sym_buf[sx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code + LITERALS + 1, ltree); /* send length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= (unsigned)base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and sym_buf is ok: */ - Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); - - } while (sx < s->sym_next); - - send_code(s, END_BLOCK, ltree); -} - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "block list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -local int detect_data_type(s) - deflate_state *s; -{ - /* block_mask is the bit mask of block-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - unsigned long block_mask = 0xf3ffc07fUL; - int n; - - /* Check for non-textual ("block-listed") bytes. */ - for (n = 0; n <= 31; n++, block_mask >>= 1) - if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0)) - return Z_BINARY; - - /* Check for textual ("allow-listed") bytes. */ - if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 - || s->dyn_ltree[13].Freq != 0) - return Z_TEXT; - for (n = 32; n < LITERALS; n++) - if (s->dyn_ltree[n].Freq != 0) - return Z_TEXT; - - /* There are no "block-listed" or "allow-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -local unsigned bi_reverse(code, len) - unsigned code; /* the value to invert */ - int len; /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -local void bi_flush(s) - deflate_state *s; -{ - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -local void bi_windup(s) - deflate_state *s; -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef ZLIB_DEBUG - s->bits_sent = (s->bits_sent + 7) & ~7; -#endif -} diff --git a/zlib/uncompr.c b/zlib/uncompr.c index f9532f46c1a..5e256663b45 100644 --- a/zlib/uncompr.c +++ b/zlib/uncompr.c @@ -24,12 +24,8 @@ Z_DATA_ERROR if the input data was corrupted, including if the input data is an incomplete zlib stream. */ -int ZEXPORT uncompress2(dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong *sourceLen; -{ +int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong *sourceLen) { z_stream stream; int err; const uInt max = (uInt)-1; @@ -83,11 +79,7 @@ int ZEXPORT uncompress2(dest, destLen, source, sourceLen) err; } -int ZEXPORT uncompress(dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ +int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen) { return uncompress2(dest, destLen, source, &sourceLen); } diff --git a/zlib/win32/README-WIN32.txt b/zlib/win32/README-WIN32.txt index 050197d80f7..384c988fa84 100644 --- a/zlib/win32/README-WIN32.txt +++ b/zlib/win32/README-WIN32.txt @@ -1,6 +1,6 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.13 is a general purpose data compression library. All the code is +zlib 1.3.0 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) @@ -22,7 +22,7 @@ before asking for help. Manifest: -The package zlib-1.2.13-win32-x86.zip will contain the following files: +The package zlib-1.3.0-win32-x86.zip will contain the following files: README-WIN32.txt This document ChangeLog Changes since previous zlib packages diff --git a/zlib/zconf.h b/zlib/zconf.h index bf977d3e70a..fb76ffe312a 100644 --- a/zlib/zconf.h +++ b/zlib/zconf.h @@ -241,7 +241,11 @@ #endif #ifdef Z_SOLO - typedef unsigned long z_size_t; +# ifdef _WIN64 + typedef unsigned long long z_size_t; +# else + typedef unsigned long z_size_t; +# endif #else # define z_longlong long long # if defined(NO_SIZE_T) @@ -520,7 +524,7 @@ typedef uLong FAR uLongf; #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# if defined(_WIN32) && !defined(__GNUC__) # define z_off64_t __int64 # else # define z_off64_t z_off_t diff --git a/zlib/zconf.h.cmakein b/zlib/zconf.h.cmakein index 247ba2461dd..310c43928a2 100644 --- a/zlib/zconf.h.cmakein +++ b/zlib/zconf.h.cmakein @@ -243,7 +243,11 @@ #endif #ifdef Z_SOLO - typedef unsigned long z_size_t; +# ifdef _WIN64 + typedef unsigned long long z_size_t; +# else + typedef unsigned long z_size_t; +# endif #else # define z_longlong long long # if defined(NO_SIZE_T) @@ -522,7 +526,7 @@ typedef uLong FAR uLongf; #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# if defined(_WIN32) && !defined(__GNUC__) # define z_off64_t __int64 # else # define z_off64_t z_off_t diff --git a/zlib/zconf.h.in b/zlib/zconf.h.in index bf977d3e70a..fb76ffe312a 100644 --- a/zlib/zconf.h.in +++ b/zlib/zconf.h.in @@ -241,7 +241,11 @@ #endif #ifdef Z_SOLO - typedef unsigned long z_size_t; +# ifdef _WIN64 + typedef unsigned long long z_size_t; +# else + typedef unsigned long z_size_t; +# endif #else # define z_longlong long long # if defined(NO_SIZE_T) @@ -520,7 +524,7 @@ typedef uLong FAR uLongf; #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# if defined(_WIN32) && !defined(__GNUC__) # define z_off64_t __int64 # else # define z_off64_t z_off_t diff --git a/zlib/zlib.3 b/zlib/zlib.3 index 6f6e91404df..4dd28967534 100644 --- a/zlib/zlib.3 +++ b/zlib/zlib.3 @@ -1,4 +1,4 @@ -.TH ZLIB 3 "13 Oct 2022" +.TH ZLIB 3 "18 Aug 2023" .SH NAME zlib \- compression/decompression library .SH SYNOPSIS @@ -105,9 +105,9 @@ before asking for help. Send questions and/or comments to zlib@gzip.org, or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). .SH AUTHORS AND LICENSE -Version 1.2.13 +Version 1.3 .LP -Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler +Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler .LP This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/zlib/zlib.3.pdf b/zlib/zlib.3.pdf index 8132d840c861ea6823b8ec0b41ee5050ea56ff15..da12d37183a7371513c0991fd14a7d932fd42e84 100644 GIT binary patch delta 13422 zcmaiaQ*@=zzHMyVR);Gqwr$%sJ5E-|Ham7Yb~^6ZPCB-2^Zxfa=Z8-J2Z2t#&YpLDBf!vw}Auu-OzcX?ygM@NhFm62C@flnE4l{ek`%ET(9 zsdww@;^C6K&4Pn!^=hGrA(8~3ioU={fJz;!4`@5F@6xf-U2&!~#%VYWs7-~!y zLlV@knm!B)EB9g9N)GlRm}i`tFe@ebm|Lo>u|G}goVN3$joW4zdf@BV^fyHRP2BD2 zk{lSy9z8SCCT*G-X3lK(&iH)2`%w}wN&-nT(T4Z>+JUTeamL*HPFL)B|kbW-)8@=*sc~fC5kgM zdHyum(a2Mj#HhJxOHm4(RQ(9Jp4oN{qWRXHs!GFl9UagD>amg+l2&^X_TFbcu8gXR z_Gr$V^cKgLGgrO@aQ>;x8J0STQOmX5)G;#J>~8n=?ecoN0rfWy8`#Gwj{i!S^7+0z zJIr6gYSqW@DUx`d3Ox#+O`Xyfk7rTfquWA78!ut-i(0f?e|r;rfu03y%0r-4*qmKX z0_Qxlh3u?zd=#B`hJhc+hG1}72V)ja6dnaO`UQ=;-8pfa+%NeilDN0@$HyWxcu~h> z_sCN5q{cHC7>K_Ql}%)iy-I+k^`{kOc!ma}xwl-)V2etrZ00ZOK)FJ8R%Qg0wk!7&aH@GCHIT+6y_DH#_enaZhKBa$S9W6m+VJxl1!C zPK32-B&d=v;cuz-BsYyJ7EGS*96wnTd;Dm|ELyg)9~AhK7esLE2N>=IUqw&)T!^0P zfM?s(;vfvh{D^U@(sZtmy z1p{JfHC#&9Wt@#to#Z!TgLk$(264E1ZT=dOZ4iYQVbqZ;4C9Db3belzL7kt{?P}>se)ZSwhnYxJ`w1x*)b6fR{lYa${d=$( znMT{e{&pQH2JC{kJ;-Q6p$39YOq~d`ukEjk2Xw0q@|t?81T#;nuDTdqV2rH2$DMM= zzC(3jhUf8(#wJcXub4b`Nr*a}ecUi635%!wN@OQNs?ToL@O#}9VnXvBNUI9k_CsZjRhSCPG0_ zl=y0cr}f7!m4E;yn?d3DFhR;+7*lnd59qS!zp^S2%>y(YEHOVk3n%2jtL*LMDfKiO zBFr>qBXxdLC&+d2dbQcAff>eW10BKMF(5ID@ae-$$>BGP;R5i@19%ZF6M63P#h1&`9$h*5$lyIVeuRe^ZpNGr#aBokk!dfyV2=6r0}|vgHW7u@4y3Z{ z!h_WRsZa!_3L?PKUYB!e=4GcVF*UQX7?ySF5qB0eAXRTEGUivXN05-qwX~*0OwJd+ zv_&opx@Wos`g>GTiKY(Y(KKnsB?Elb>_@gH_~GK^6i6tUmAO)p&*4 zkxl;Pq9kdVe!U??^-sHGlvGl38UsBzt8=$|lGAX@vPw)a=yT9xyKD84EA_WkNcBvI zN_fr#*|9+)McWRuKP9r)$d|&GKJ@-jSPoF&pN{-mc@ToIxIi^G zos3S<`rG#HXKpd*&q+GLRH?N~xLbiBUv{$IpCi(96HRde_ak~^r_7)1?&gG8X>;l^ zwkr0vD%EGy&uoc13yZaAKB}f+`v~-4Zk%*P%3bZUvlBV})qc2s5Kt!j3+DZ}h3&o! zRY)46B7s}N;`HrdIAn3*?OdvfV{S>lDFWJWP%WZr1rqq6{FziPc6wmfH|?fi1l9w0 z_>0PM#4Jx72TJ$}MXcz9z)qK5aI8_2>INV-6potL&v2q)`F^VX-$UW@+_82V2OKS= z79ZOPhIeqC|oiS7#UHS&@xE`{cok-6z zW=rekiA|T{fyXOPgtN<|#U|(+@f^XJ)H#|~#@`R2bexah^ei*E>@_|wm_iShN_gRUCy1%TzV`Zb{aSCv;oZ#cw$rtGIJpLoNSewX zEs1uyBT(097ISJdnKZ*610=n0Sjn_?-O>PP8Dl$6LTaZ zyH&EXw1!TfL4f2uAf{Ep#?0%_sWpOhQHZcDF2z5$AVOM2{BYvof$(gFb=XjefF;pL zEuP$BV(B*lNHQO`#w_jg$R)A62`SXF%K#*0baPJ7FKHd#U&F7^s}Vbzx2W)V%F^9G67$oPL}tv# za1yl{nr6GZdNK?EabM&>)W11x8_oZEY30?(nhyA+>&hg@@ zAx5hqNOT_?NnjbL1#oy4d4r*Holl;G(nG%sv-a|>efosZd;7~8RT>TZiU29Mk4wpo zL95UUbW4OFk(t{OjEDD^uyh3N(>R8SBN^zOuOmrhDSQxlHzsYd-J)32E} zMaaLSPrjTeT?JXBr(fnulBybi8>Qe93{0BA3GHfCB~w2Ygp8`gMBuOQmSk=zzR1U& z+n{OE+Y!bv5`kW`vtVLjyV8AGMTH`4caC+jXO7h#{uYaQ*6Z^0qm2MWD&xMECP3+T zv~F8xWSC$SPNMYuB@X#h@~>G!h)mi$IaBnX7ebs3vac$iJTn(UMr3N~(@%J?WYg{7 z&W{i*V_7aNm|tC4g{wc&9aG9Lv5AtA5YpmG;TW+v5ul;eZ3H<|J#bBQw@hdX2Zh%3 z$a}%6g3(e{^+LyXiJT}vIr(sG40NCRi)TaY0+5mIY4_y(>MrpcrYvaS(nQsD5LWzEw+FI}wV z3BsJ3jW||@Gq3xBbR#JaD|*5v9h=kmrzYDQ%&hJ>4_^=beNvHt8F&L3^h%Q z0(AtP6gBL{6*{4znNj!UcJ98_h_g%-_dOI-v58s^*K0mBUlAV}ap`PeS?B;w z6BW?ZR;$_G7VuLS5{{}z5Ob9_ETP>ogtOQ{w(I~T3zM&`0<9smT*UOfJC{h`UDOO} zr}O3d3uJlQU1LtSYYPr3&rrq2>S1DP+cgptQ2UxDTK6s7p^|)`_Z;GE3;Svtqc^n| zkao|aO+E|_cNdYHG36m&#V}YULGh|0Aj4XWTOG9^gA5;5VVs1o`s|LHAvp&3b0z>D z)bIo3_gwrNGDij}+nS_IL~qIA*vqHzSmnMysiQ^aee_mUl@YN70g9_3)9Z%JRQCV^ zG&-t?q5f9!5_bLQCHqd!cubcHWhPWtO8g6es+o0Ht}LX~s;M@T0WOLDG5I#^6<;hueiG<ZiS>M!@BZIrj4_6FZi;GT5WzXP z?I~~2g*iU%82r4I-nss4%6;th`Iz#z%-E#-tE2b)=_3_pE84$MqpoiUt^V%N`$kcOxQxWkng^!eSG3 zd05<|G+TKKUde2^$>kZZve6_lu%OgvGR!d&?a%%z!Cg^*W)3kKo@MB$4EVwPQZ~?ATjLpdP2Z*3Ho(Ksi1vC+=|RaUS8QnTdf8UD$L?6EsB{tIHC`u0a{ zHk9ho&r9e^p0$9sWgJ2TgFY`WgjAXq(Y}MVtB|_LWE=~N`B9zc!}(ta556#CQS|2q9g|@# zpmLXstE-bZn!& z^QBWa0XgQ6iMU@%!B3R7=J`Eo!2|d_8_(>al6Rf(LVs%%NgpxjpGRMjJl#yeJXe&X zc9!Qp2V|Occx9{HS#MJ0W8*KbtB`MDJ0mCWZ3#Q;&)o>3C&x-=ebR zseXV);e#^BWv)SrDKz7K^As%-rO}0E11>j+xbR1q;$Y~~6ErQDe34`n8Oze=;ei?H-hocf1Q zSB)M-DQ6x!N)}jmE@1OkvSuc+Bc+;Jo@t)XMRe>P^Xn|aXL;A=TRqk?0Q?x5*)fxP z8kpmW|Kdk~j;yX1P4o2hfx9mEYwXBYAf0xh()FG`{sJwn$pLdx548KO#;6VNh8X_1Q49aa0KOpgd6Z3vY!P4*H8NseYh=k-|83$_|B>^rdh3G1x1N<68%7ZuS%~}It~F1r4L7_ zynJhWrvwpu*hws@_G+rcQhB4Vg>9?&YoxyQj^r4rJ*bbR$F!!J-=vW<#a$RTdkg@g z#b0>UR}Lg_b?140jBOCH3=n#GgbsJqqY_J|84DPeV%f zl$;%5K$+hd*RtWr4^$svKg_y;fy4qWgSvJ&+bMdIpy&cGBU*j{bqW^9pf%wP18o?? z10=DR2*=09Y^xkBF0|#X;x(la-Qo|nJFMN?+Oz%I$exsC!+yUyRn)B?$1u%Z*A=bZ zu{Go4ZN$9>Z=9s*R}LXmJ8v%Qu3A^nwathgwOi{8t1>qpWU!a4sshZYS|~uUegcyi z)@(xaPC6sNh`{3A7=+YswMg{&Vxix2`Faq8m?7f=y#?{ zmNo2WfLH?t(gmaT@LB!3tzV@xl31@%$OoVMWR~2^eb1;x&Dzf|+Rq({*8I8C%s!;k z{?a*kJGZ=DO21{o_+NJd#Ew8EpKrtwL9AXxtaa5Qma@$9L2z*6QR!t2Y>m67PWe8) z42yk#pqTOu!Oog;sF%c7{^miwk+(~_7;41I)Ik*1zH`onZ3&ZWCUo@*5PSAM=b3^b z(!oMmvV=ZNDk_swD+&@wEY-_17kK*l^L)x1JBOdaI>Km_;3Xqsn81UoutM!o9&j6} z7=tv32_0psD_%Qcybzug4LV&L3JTkH2`(fCLBv>x$UA5TsR6u|lKvQ{J01^3rJ$UT zmW~2cp8}r0ej^F~^6)F#C2hQ^!CNAh|KvORy%;$eGQff#X$0W3X-K zPgrcpFXvBTQGPJ9yC$I9l`DYR(a7Up)L2gnz6z~~AP1iPYi0^_IaB9E&hJj;L`RVHlQyEAxbH`hf1x&t zW0l?1^OKDAW{&-u%=esOPv@eVrv@4YG83yXD8#@|D|3S~tHf~^7Tg^DvJgKwK~f(v zlkw{D+VEk3@tOTqoBEPgxR+B#HH0Br%{9i&9O!(- z`}L8}cUUX74l$$iL4y*6@W$$J|8hOZTFS~EWEo^m!U4$M&wI| z@TAjIwcDFK8KQ*2w-1AqYJu^qvtEFE#@S{4G`gt!3O3;)sgJqp^-~zEqvhXZXw&*O zWTtO}`hmu!5O?Ep{#)Inj)sj*fRc$psc;+}9wxuB=r%mrI;uy((xPH~7UgaScsjbD zt|p08Qv-D)6oc2;O?MCTe}8jYS;~{m0FuxaHdfZ|$-e+^AWjZ0LBan?LA3CBadkCk|TD+N4HGPOhJJ9_D#ND_R~39SK=Yfwp@pE3|%JzFl^0ebhwE5lBUf zQ(XK=0mXEttaHdj_N8JwQS6q*?UhAw?M?^mFj3GgEr-_GFEKZ_ zU{D3Ri7nA-I;|TMq-M137_oeQ$*W*t@29p+fcWfGJhG>Kwut^9f3|@W;vPXC(!x0C z66+^msb&ymCK2S~B$Bkz*gD*|XT(rPm2_a(+iR_^On-OIwmLoEZSQeNJ7`-$Oi$NV zOTovMY*Rf{=jI5G%3uHWQ=Q5}L_($Um-SduRDq?M936x0H;!;!NpH19b;jn1hJsx> zQqWkMuHuWTM+)hI(qst)9jqWmqZ9*z!RVHY$j}L{F2fYv`2j&9l#1 zvG-8o-xTZ_<1mh*-p=-rGLQ3V?hqgNA2GA0K^c(ply`)LeU7GC z!||k~yq~lVTo+GGZ?pi+M|tZEK(SdBW@U0oqt;Q$rTqr~hJU-2d+izL$!FnFO?tjo z*;U0KrLP~KIgy5#l{B1+M63V~ZQHt`{B`H99g=>*a=5AE@(X2r#;fg%adAHybC8Pz zx7=;!(Axq6{9?gPFM8;{Ry%P6)wK?6IM;kWWEX}&H%jVFV)cnd7}G_rKwZb0v`JP9DZdL!6zQKm9V`c*BipH)U*_St~slUw%BEN6{DDb5F30@)^4eS!=hF-bV;X`C( z9WOlYWhw51YJ_Fz%BAZCg{;&LA4|;Dz%KWUQTN&AxW+QQJmXuvw0L+t96@|e8_ex9 zsNX+Kxu=Y_>q?67AA7qY4*`UXuvcsqb~F?grGFdN&c{P_!K==OLDqPca#FgVA#n=!=rtWww%y(;E@tE7NGt1-R4k zqDXwZa7lZWyW+9L$0yP$n}K4WsUzSltT#@DsbpJfNMZYbX#r5b}Oi90o5BWIY% zMY&#Mi(`K~(=0*K9y73V5N4tys=*3FIc~F|4w%S53!(U*C_!&3L2;sX4p4Hb#FMnP@ zg`|#2@2)$)(VzZ?8g|DteR#M&+X!JYW<^sk6Z$@826i?-4s6)+2=*HzHWPArEfLGr zD~4nh860EIKz3c_y@M!7<#IP<=~Sb_)J@@n4CC@@7UaVzHVw;HI10DNQwW@NQD3Ef zoao3syMz8OfY$+lz+7kI()& zjJsWe@rTL?pkW&&iAAp)zr~s+vGi(U_a_5&|DknP>vPM*00X2V@MO%eG(HMYA-`I_ zH&Brvk>!Ys)jR8=IM|-$UwI1`Rt|VeWHE*(SSO5RxoAi=E_H&p*7=QIn9Yv?t?cUstcyGiq09KJH}s zSVWHV4uW*3g9f>16)XHa$L}Ixtk-1m5JRz6aWsGT+wx)*S&kTN10b)7o!1g;<0)cjE&)6GEj@YB|hSZ-n} z(QxhYk4c~|`eDF=`MvTPo}LwyV;ttIVH?WixG4X_QV#?{a1RufY#Kr^VYNRG6WBmp ziz&`}?v(LsL#(kV)>0_)%fX=y_$Z38(q~VLQ8Qa`0+uWBRq*KC{dlm92scZ)+bzdS zOK57wSK-GtWhJmd*UyH6_iGyn8%iTUwIB0MpoX#=qZV!DU9hw$?4LFkfVas@xGh17 zdbV~jQ3Q!BX7;HMywVt*r5ZJ&nAUj=ivqxGtZ4DZo*B%BG0*R~XaX;O`MbqFAZ_Xb zlXFYzIjIr(2&zV{a_3mQJGMAHl4jj*A1?~WKb-6ICO{hf4jV7{mD zK}?7IVq7$3qnzeWD(CuRk2Ahk2K;{mmxt3EOhE^PKX;pgo<4q?UQ9ygRrw0J`%6OH zT2*KD1vphywra4vu^)hGJSYEx2yO{rIGk)vnI&*4ljXzzWaq6eX{KikqTwqcdvV3knrQQY^|1PPpr9$qi@ z=MhQJ&X)U2{o!`mpP6N07E9E1y3OP855v0W^&0he-Rp0BDVwtmQu0o&;A|Y$4JqRf zlkY`B;$7R$QEg*0*zcsDg{}9PbpW8pIDUU$ceQBt{AN-vW#;@F`PvtD!0(kxdLJZG z7zo}B;fAD0Iy;PS>km(pfpje_mIM>RC{f*MSQ&we`D<)|ux74RrifB!#J6P^1?KXm zJ?TsQiK%w+dJT?@`57fBMhpH7!27rh{bZx6_R_09y| zgmgM274ZP2`;#g2*-@|?Bp=sfL4B?k6`U6;XLLCQ^+e^po+UO8>_@;budo)>C^ zxO#(x-%VY|?NkW;W(?1!{d;}VVbm3teAw9%5f9ErxP9>@fP2f4DrZa&gKN{GxL=5d zMxB|nS5>Mic7u34xQ01Vix#wSxGpMGSedGoxoi)UMZ?1JBvWm_Op~PqviwVez-}w` z6qncW{(Z7Q66%$a6?a6M?K%w2F@F(}(Ch@rQs!On(9_G;9RIdo<=0cDg=im&!2{m8ORNTA>a_KgF9Fhsb+yMd7(H`i`H8xi- z7!p}qvP2dP!Js-RzRr6uITm|A7kQ#hMGwBPeo)1WGi``}Me0e~HD&!05_!|eU2bWU z_o&Kehb?I^BXA~rew44pZWD0f*22pw7OURqLft5nW!m#?7^Jdm84^Wk`nBBV z_u)}tyT8_7(0ZWY27{(b5igHY(x(>lNpO$^NZ<%0eaa3#xBQyBAswuv_HhY_` zvCo=-E2^ciJVjLZyRjx}@rW`W*xHHCt=3~5HYak;qT?%7QVA(gP3gpiIM^%{A5w#) z+sYSl(_4J$3v6Eqi?rWP%uk|d`ShcGaw)?H$2ACZ;X7O1u#&La*iLtD%{vY_U`eVk!!0v@Xh%=EG)Z^s~f| zDrS>Lfe!k-W#Y~_RxK4}=uYsZyDB^a6O8_~&L>iQ%A?^x(o**$qbO90M;nE|Vr{zV zf#OWKjgCI*ZlGWIC2)eY=Z{>?@UUwsnXol={sZCx5G4JHQ6hYBx;AnDkd+eg+$|Gw+zj8xe8vhg{3#L5|m zv@I*SOSAE#)URSW%EWel1!I&X+pqj;gc)-W=sg;sy9`qAJ3;-6 zOB&Tvr>7q{&ja_-j~LGE!{O=@MkZkLCN}%KP6J6}W@M*2+PLx>#fRw>#1!^xDZA~( zE>N^ysXD@`Ka5Jo^u@$PF5o9`+Wi^?1otMe0VLs?6~=VRPBhD-&VPkm2Y@utgRy+2}Z#UAPa*mHe`o|S+GHuhru~=8d5`CCKIViy}$8<>+e8`eA)QOw&d@s z1?^Nue|%@Tl>dBqjFqxR8H@XCb{M1SSdoc$gW!D62d^;?m?^ zk&;@|8(ez-Ow1lRh?q<1KdbN~Ek?y01=-)YgOz?H8S;HK>94N2-`YEzVP&-DBWD@k zd2ZBAqO5=!xLQo#d`OKm8}N7#))O!73Z!A1Q{j$r+3WlhfZQxQLw^t(FR|=yjNCN* ztJn#@xee)7ce}hM9uTZVWzWJV0S>cuw=={)JChZ%SNeS{v7)lIN1z_EfDD7N zGgbwM)y$GNwW`vzM6;o45KV~o7L6iL`h!;FX$@t~P~Q_tTl9mXm&@Ea_EGy(o&TwN z5GW6T3MCHH5DOGjmj6sxr*dlse>%1ugkG3{xLA-0Ne?XIOMBKR{!KGdT#Hksh~SwO zM2ouC>kjxhV*#`=ly5#H$@9kOfaai9YihOkNq_g*?c7!}F)h`$jF!}18&n5|!C94E zOTT%WJP7zdc)|{cu}56}DD{{fByWAz*N3fHH>vtq#-&?`)MYkw?7UT50fV4~@`1jH zd`dbKn}Q3jj7){*92^qkyq@}4HTzvV7VRROQUZ-2QrXRHYqCQeKw0+Q3z}XeXB@Ek zObR;^TH^X9Mfh&#b*&4vCrw>NTnW{!Z`VZj=|@8|y_h(Lb(y&Xo9!(I9{j#J9lteN z3Q*vytSvIcafgail{1Vc(Abq!WjS2>nG{iYejh)Y8zx{?TfqECy)s9OrGAFV>L>j; z(I?rwyn6L-s=Yfgd@F8R39_lb#6OcSzw37uKU=JRms_x!eiUL3tihXGZksJTNdr3YXO!Y$&%aaNGrJ zc@cKxV{(Z0C*9iAsu}rD@>(nRQOAJVY_Wz?@2eLu*Jg9KrsD0;8g%j7)n>ZEU*qiR zXH!9#8W(}%7TF+o`?NbE{jlQ0&1@gJhSfLhDf^RRm3KK z)%7O@s^NLFTGGPo37a=HX38XFUUn~9ZM9l*-V&dSTik-QsWEWM ze}ujvu!#Lr+2d~Ge6f0*Xr;pYB# z5l(il{}AQ|{C_r^s`@oxl&zvd3GP zuS-8<^jW4@1dE@dhBh)hwc=G1*&|1dy-RPShpy)a2;N^8veJI4ZcKs0KdoAyXnk@9 zmYCukAyeXq76^PFche?T-23{kU)$qN8{pU+YV2KGs6NT7+&b6N^fX!~hdNL`#J8VG zH1MRR60xHL6^;_cGd{YOllF?bj}k|oE_JDx1|Cl)w>GBYEp6GRR-yK0(LtXSuQuSY z={C=JvyXs>QAw|I>qeH&1wT$a;2ytP^XmO})YkpfUJ(*Y`snR;bsej{zORRKx5wSb zM$(9$4M|QaTSeFXOMOwC_%P<{jHFl}tu8+fW&((%ty$899|SI|;#H1+ZKQu>b)iWiK*(-Ak&M#8vV*$bhGIuqJ!x*%|Pf>Kx8`Zf= z_160}u|{#6Abll6Xb8XQ)NQ1ClFzsrcUDG`p=Ek7EYNdbR-f$F7dya^Q9<)crEUM{ z+QJsF(M+sm%>=tP7v`m=WD%EAz);`d$8wt{ zbz%iKZY*~wtZ^!@`DvVK3%v$gLKA-!o2wmT)=T?jIV8lu6iAJZLTN+T40USBmMYHXE(^g7v|BVUO*GRrF@b0e8mLOK0wYn%S>T{72czX5w7B;p!H} z(RBEG3u)$}m`nMn4%8(HPyL;++ZZe|&+no^SX>yAvQ*Fw$ha~|f^|@M)sdl00ian9 z9Ec_xRut4N!%Ffdb(q0F>*K@BD-VThmEUC@MIED`X%` z-$@dc;BmSr$?^w)OqDKfkbt1zU8Pt=*oyiZh=Ei%$TX1y6=TZ?mO+T&S_6%X-#qP@I`MEyPKhZL*KR*KQbbBt6MmS(c#9F$)RAAovPqKRZcfBu^Lms>HFz?Et zm_&a(6bW5=oDwC4pks*n8KDxt!#{t?O1$w4IQBJfifgXOr}Af-z_xwK2U8);#K@Cb zr%{3ngfuQT&2d4KMq$1m)&vC`GL7HSIeLg|LS04+sxT>6 z%n6o~2keix)p5hi?dW+ggX?6svBd(a0!p+>gH3+SYsLqa9BR!245BVjS5UG&07eAX z1T%70iTr!t!fV{~H^Na#&S+SooQ|QB@odeO3^a8hpoVb`=$FSatDOy?zRMQh!J58D zJTRv@HS;!;rI;HZ1P_hd^im7t)uQq8CiYnsGh=@BOfQJxm$r&%1}|vwPAb-xVexWg zR{kyd-M;K$_J`YhPuSThkGA=Z*AQBsW4}}D%=piIDQ`%blD5XH)51?q^=oAi`%mqo zDe+QSgG1%t+1ogZrvjSQ$OB}alsi;ca|9sz2u#6bJB6lmHE*F-!O&k)C~RN^;G7bZYHz`Gp~=SQ{9TzgwG})>v5l-^F${ zd5$y54#YBFhev+ONh~=N6x5DT=!hPS9Qz;Ge?2WuxLy9u`wi@iIEl&tgI#|{*^E2c zZj^%3X>`&l`*7)mp$@(M?9qGm?7G~DiiP=-cBX_#(9*Oc8CbHTNv))wob#E9|R|?ZLJP>6U~G9V~=4LY2dRalRW~ z#Gxr-v~F(($ol`VvpC{@W$?*eCRZA!sB4Y{D2W_Ezj&R%qs_SCzCYsfI<0pHzMZ^o zJmTS@p`kS`r^0jMo9;!y>G^b4rq-Ql;{mD-XgUb?^UqX0?ReE%Pky$*MO>QOWDtzd z!B1{8lYk3Rk$#5tvc9uW_6K`q!)ya|9zgXgbA^I%hLo0O`1X4-tTkP<^-6nRmb$EW#!Vktdve0m&F_)qp1Yg5( z$foU~(xzt{My^Q(*&b~tUqG6i_fjkUbasT&QwN8ylGM__B6GnY!_)K2_^6bHO_svK zrlL7GRYJ@CnHL4HMQSPNq?M*kVAgo`9k0h}$NHw1OVPQOWfE#z{`{b4-``mRyCCFQ z(F?X}q3sM1!Oes&D3cESRzK&#e3BAlF&;rP`WjH;V{$jgXqbt1a0Fd0Z+wJ5BOQ38 z-vZWQg8J(6OcBQuU;f1q$|7dhF}0TnG^4WdxLQ%hU2MPB!A6C9l&oeZL>AKW`ifi} z67{|zZSN%mO?+{G`?6>S4GTx>?_aHdmdKn7jlxPXFUIF z+8j5ajN`CYyp$2a8==OADS2mz;wJK)8mEvcxDkL+uG!AU#6E>7>p$$fO z3>*=k3m$$SGRw6P%ygH{WmRdj9@t9LMdi7?{msGi{Uhi^&A7wk?$W~P;`90AVBvt3 zE2)*ge3W&9&$}fB4(~^Vi3>5|)r3)M)r=AM&`?He_v81Q^)+WGTlT4fzw6Wa)SzJ2 zM40<(*Ml;pgT!eymag4w^;)b`GBgd~sp0aglqY(Cn_E;7xBuohF1udI9kAZq46T}b z$AeTwS+a`43C*h|KNM!0K>Q?(5>P*#9?VQ(Q}PL=6Gjb)EsIidRtYe>j#9&>f7Eko z=h9G3=#^3w)E#y7F0!ecr|o4P<|)jM_(C3<-+uS)^gBb8;LGdh4N$*K&D=?GEF6!^nv2d4^xq)b?4_n>5*wPD_QtmI?J31(Sb9U1F7X)yyk? z$)C3y_p-2Pbgb=Ec90zpLk`Sp;M+inPem83IsTi!V&F(15XKXZ`+02VMHR-IDJjd_JdZAiJ2P%Nwx9NH2i&moCkN&eNMwm=nUzC||I)NNQXR#S?oHDj- ztD(&GX)FpYy$_kpLqZ9x8MFyec%~z-Y6?_oPMm4F-{nL6?wuST7~h^*O`Kg}&FoB_ zU7XB}Y?1!0?2UgQagqVZ{%2<6;NePAMUwz?{?8k7d(w0PfgD1gi#3K2&aDIbWS?` zr_CEZ>Ur7ZY1nJ9z72_nTZ3VQsT6+Wq)|y@vZM!ZP1omo_sdC8nc$O+*DV*R#u*p_ zS-F+okT&RRuDGf6kd5=tTf432X$SUSk>L}X)b%|pe~2{K-(HU1b=+QGEZiPXhbETn z4PqZ8tfv?WuEmBTYeI^Mq7h%>!jvl7R<;b>gxT4g2EG#jF$u zkRna5i-`lgJT7)x?Q4(CA~d=sQ;lHP$Dl{3z9^=sMNoX=d+D8*9>+k!dt#cJtGQ>l z8F;^DWeN)`O!ubx>baIo%B|wmCXx-ua?c~@Yom$Y-Ey9f%_Jzr z)3b^|pJZ(qzBK@S^T?^{=egEq&BW!(7rvDDUj$xl2cPbDYYh9+^v;}4nH69M{`cxM zdGUs%AY@Uf5&U9-On3rQTIuRcqcO@`KMN5=o>uTG_nl^I=h=JAZinb>dIqy*a~V%VR(U4L$L<)g}2aI z+?t5FXm64aoShT$mfQWYtyg6l9yOX%BMR<|SlM3d2woEy2=G{@kM=O1EO{aBWdnoB z!cxCxP4(_urvGN|qCYyWovDcWv8-GgdFU`>t8|Dn5oh?h3PL&>lZuP%f=}LPJjWTg zkRO)&B^#Q~kDsBbLstdXFB*%_oD68>`=~5Z7~PZ73Vm*x2wf9!I);Ze;g>ji;!`Acco zN(wL?oYdjy@_)m$9}27zuZjt$AC(Ra(S0~vb!ak?nN2$VfLJRyw*N+)iZ`78yt$6WSK&B8i2LH5IR53I+S;M>3Mt z08@$OH;1fz`}?v2m?lXhwn+XTD}!IhR+w=DISUE<;4%vbC?h4mb(mWsPYS+*8WHD9 z@7+g#o(U)0Ke>o?ST`R+i!I+{2DwC&_oa*{Q8Q|=-}#h))z{WFkR}Z$G~%os`L9WjrI)XU9r5?j#IWaJR@uwuulw}})&QFL%i#V`SLis3McVZ9~JslKN% zOAem_r%{BEu#%gEqM$>C9!!a&+Z_6~(@Htl`*I$z# z%yJ8>j*mI=FdOoleq~)Zpsgpd zkQr434~1eyLBMwCQ597|^x$c@2a|ksr=zW>w}c|otw$iyb{E@q9YY2j^m(H>ft|YX z50oFeYcZP7KHVTDJm~uA+wQ)q;o?X`%VTODEs~1sOA@P!Zf= z$Ii;8Vi{5{2s(I-l?5+|l0OsJ8Bq8WIoPqlKOpdn&~j$`?Us!&hs!1cNLuLH+40z; z1}ymKV_e#a&(=J3qn?HY8VPtivYIuZiVsPiHaem1*=%a-Jc!|BAf2q-8k^bxlE^tX ze*C@){{HCqXTPj81@7h8=Tddy3&mIFIQEqX)rRrJb26m@F>fyKtH4G2HRPuV(5ro5 z42_rsR2M9S;2cgPV?y4k$6x4(52j-91?8QkB;Xxng5{Cd3@WSNYM33;cCCEPnrsrX z!{j(S#_4`sL$R2`_q@T+YZJBvdE;R{`j=9r0@#)0ITj4?vl}UB5+cCu-NYol>F4;3 zJG#yaB7Y0Ybn4Gue!b*-57OdQ)WgxK($X00!m=j}V#`Sva%|KZTh0RVq-7jP`!mAp=2Th8pJvC_ zzCmV`QarQwXHa$f1Vw$~Hu@fAd)^&-)6$HU?51mGIGpTKPlO~m?TirY&?rT6OHjNK zf{P<|v63*wFf)3%$w3_AZImL36n|612cwGoxNdpoKk>53!U+<^uBgCPkxUcM<+BL#h1Pm$?@;x!yZCo8e-j^hP%h=9p4y<6M^o;HZlGY;(- z8rM8JTY6sDt9%1fpeFq#HAEvtDq zXSYR~A$o8Zl9+cD6R^2&PSr#{Plxymg~zp#X^}J48SNv8_W)N}C7Sf=^@)5*t-9bG z6EJ~AsQM#loD!iw>8EX>=NV((?#lsRufmltmQbLG^uw;10 zAX3Xh&f_=xc|2@CM0FWGwUUiR%|DPi4is~VHuGS7Ct+AZ#j^$OSDFzagUzuP25a+~#;Vtx_N4O~c^8 zh$TaCS4=HJJr$&MK4YUmzN|VOhjai=poSsuL_wa?(3jH2#zt)&?-fs`(m6?n;*fU9 z1#Y|=L5;epG-M~VQgbisk4mKJn6Y(=7z82AD_%dbW$Hr_z0a3CmH$*I(GdGWnBlOg&}=6J)rFQEZH=hh3m@|HIS6 zVFvH#2$PLccQd$Sx)G!)cgt|GqS0~5jPhWxx&JiWhy0k83u#D}*m9(gutC|-a2-iMLXUM}6i zWJnS_j;5cj5*a)t00Ihfem>#cg5Tq@ah(B#Fm;-YpP0>lzaXns&}C{Pauva#^PqI? zAuY8pG<|U4zi!tY_n*PMd*k%b3*Li zBO1Rkfh*$E-2$_<@h&7Q$HT}Nme9F?ozr{Lsf{qIPnR8JeyDKlbM&jUx$o|#?8V?P z<1AUSGVEk+JJ^T&r=LbAt+ZtB%|QILCgJ!z`}SyP1fqmt(K|CTi?P3o?QOYJBID@l4;<7wGn|C#&6bl;GDvAP_-cZu|4#M@fe(D~zjgxEU%>J5%sSPLtMp0oUd3lybq%{(E=Sg4n)aLC%ll=j$x-%=bFK(nG=8NC$T7yW~ zmfiDu>g%k^`Oi3p%gxg}FgMy{W4~xWrsVH;;BuZi+}ucLM-&NkAU-Q zYwX4Fy!;SBtaq1&Q=M}3NP6NKO%ssgz_Rl|k>K9+c7lFDLPI0)iL_{;34#7E-2W+Y zpa2z+3Q3g!$)rcX3z&n4Q&8}Kiy0MKM+Sl|f>VW&SeZxA`${to)rUlu}*!>HwR=EMxlwekBcO~UQ7YkPHKfB?Oy9g^z z+0T;ozx**IGZjb0LS>^LV$jd`3$M_hR#6VWl$x>&%(}<#nCPK>jRY9*)U zS|6N(HaC741uSH7sr%7S;Fg$auOvowB}Z4=xJsMbEmPe0A52siVzQ;Z-|u|dGei~! zmYGl8OoB60zaIUZ7qWP1^k45iV7m>x#R}43LZSbT#4L*{gQ$>`ftx_mPWQv{Z(@41 z*69k%p5Df0OXe|f#W{N8ra|Q}mD@(v!6oxbR%ua{`#^X_k*z{W73M%Hrj&wShar+s zR9wYP6@?=;Q+!3Gslsudcs$K1-?+jmnG#3xSqUsZuREUSR9dRSq6)#0i&U&zL6A&@ zBi63cH{Yp>z!88{LZfUnPxS+Vx(s`MZC)|5G*oGTUgihPkcz!h7@f)K*YPN2m7wx} z;u@&rcRBsMAww`#6sV9!C1l>pi$6zF2!9)BxaqG4tv||Ss?_MCRi;!w%Ugsc(E|bv zr-G%7TN~VLpk8@i)7f?d+b?vP9|O@2G_LRMS9((37BNgD_iTsdpu6E&h@X}RS4|_O zYR9aSh-i9Hkw}{D6ese9WU*wkeh+80XE6h+xV%9ggWHdAM_=@Xo_6CE!m{I4oEY1+ zWB0ueaBiz^Ik|sSx=RqIuTgYZS^}{egTXY}LtVx<>fM=rG)$YbRpx#sS>#ax(>gF+ ziLhA5hO$G1#Tb-Ca~!v!=6P<*^X9eOi)5D=DBi0(C}rjEBPpR_t`>Gt`t(6v14HA;0)`dhu9opQNxhn*qD5xA??}l*}m28?SL76 z4`~o=Yo5q3+bs4=*L11D*K`1K+IL;g6lWTL&W3E@Sjgx8(G}BB(ol|>lhP;Oj>(swB=hK#J5 zN6Z51e%6P_^DyBgRg;H= zZ5i*?MKh?f;bnUP2}f|;NT<7O#&-dkv0f^;EX#Qr8UQ;-O7d2C3Z|W=VaB#PA<01r zED%NCnkC!}pqLf6US6)k<y8ewLwC*=>0j-NT%Bl}(C$QB= zugi&B!>naX5QNK;aW=_lE_g^~%C7io&)DnC>?f~Y|A#QrYk_xBRd;K;a9mz}o^vlwKM7kwBM(3Q5)of&w|DZC5^x~~8+uej~ zPxu}Kkht%l>3wmR`nq=CMjcW$?(gw(Jt#|-+upX6>Qyv!Pk7tM?Pu59#0xnk)G*1is%6ZzGJBlMW z5fh!aO&UiKJn5N@Oxb`u__3(G=_T1do!c&f&X>7Hx4Ja<)fTiY((8pMA=h8@2IU9R zYyi@-SwH%<+{}T@pdb5Q(4vqr@>)BZbzz^#X&Z{s>hB0U3ju`fG4mYo+WNjOyW@qC)~n4jg6N7B~l2f|NH|MA8XaruBR4 z)D6tlAv^P%d_PwKdOU5);acULL|gplHr6QH#mD6YOf?2 z1mL+*u}jNw4aeWwk^1D~zXf8?%BbQ#&24}(GHWFxFvIS95+k2#3ThuQr(Fh==(pKb zB&QOOR_& ze5txkhpzbWbsij63^0fHxbrfq zw`4QQgBdk(>fwm$n4V0>D(g!K5b6Bg%aK33Yt6SxtjDK~Q4jS+3<_+CCR(qTaiL(6 zTUr6M?n=Y`k9+8($xh9Ow_}aDUn?&!IyuuWwm((R)EnRFuiGJ@#|$c{rl2)-DPM#+ zR3Fu%z=Ze`rp3XIU~+HN2jp$|JgMbzN2*j&Fx6gfKf7+EXhW#y??6~8e;#?m+(zFK zL2b&=R(~|5TF$obE{q?T0bLp!E>S9~A-*a}E0&1kBotJ?w%K+#)aA001lY7-!+7e4 zykYcu3`0J`3>V01a_43q$52ZXSH6cESK|^xsVsSi)FAF%q3<#lu{>~&GQ)orW z94e!1c7lAQ`L7AUs5D$KrY$5WYnSYBYu2}@N^MsgYLu!gPp&S4A?b7vK||I=;rtVQ z&d|5)Me%|s#rWWFCou~)RtO12wNuJ2KFMEq+jp&%5f}PXZ@t1snNm`D8dtVsP4ED^ z(#W!Of?LBbnJC^}2kY1*x+dD?WV0qx6^zSg(H$cruE5_e?o=lGvv4yHhTK(?FK&i^ z)X~mKpwut_J~e-1N1j~EbLIRT?VudOdycv9Pc2)rYo`3Qw~8XEmbWYwa-S@}F6A;P zVnDWyZ4;Aojid{4WhnXm%#KIZR}Q@3RfUNU1MT?)QPqpVs_um!aE8nukN#(xFe{!_ zR|2C53n74YEUu|ifnN->!HjZ49NUhlZ&`05clljyC{?c9%tHmG z_7`||{N1&|rzyWOXp820HJQ)qpvy9lGBg-F-@iL@>Y|d{@gZv?b2e18Na@qV1wV`?KhVi zpEXAMjcEs&d_q842$J4{N&^^H{ddOchn)=;!nNCdci3k{t)ErH_Oj3GrsG$rO{m)j zjy@nxnGqBlOD`kBx_tbi$HfHJQgYn}K{i5XaBz8N0rD+wT~-`Z{oU5JE98*|%wLGG zY%8EqCD>C&M5&`7MpH&hbnC{Ra#*=B#SDI_cAoALFZnQE_1BiZTL@T}M8H+w&LJB! zwyT0JB~hx_m3KCrj0A4*vc_a>JZZQpGH9l2`shkg2cjuXZmZ{VJG5-buyMC|$?@XE zM6EmrzWvdb9%sY1q8>y+5;Gwx8^2n=YRt$XRHdccKXEwiN@gL*YJg#T#`1-yx}dW$tD! zDri2!?~iJ3btSj9jPeGSnuR+8yv7&jwVq-Wy`8H?^>-wni*v9ewQ@aolaf%Pm<%B0 zp69-7{rnNx0^CfJ;#2;2Pnyd|y9@dzu5$dU{BIEVclJ!vjp2tC0)euU9b}5^&lw%0 zdUflz3&=AsW>+w-0>Z+~R+7q1Y%!&BA#Od|Wsneyg?^(4ke?jY70zU6mpFUiZ@WRa zvZ(v9m`ULG6jiX?PbZW2{u>?OojdV&jnWjH)S`*5wuK1(5w{+`0aXt)IDROdlD3qy zAiczl7dHa#_&C~!%2x-!IfZC^q`ZX1q1d52lx~lP<%wt`BU&rt7u9=vW|`K%_O;wM zb+zIX^mZGaZ=&yUw8~H^Z5m!=8y^lJ&rlb}*nN^AU1IQAUOE?>e1;>nBN$>AhvkFL z@8k{rgT>+{%m57Wk|Ii;3}ZO3yAx{1uXRoXxsAB*MAhDGM4ml(8yNCWw!H@Nd#YT3 ztqOWB0&YnNl27J>3Fvfl2-DEB`A~Ou`1Qf0$lDMP+D_O@{tLH~H?HIJrx{_;7+1D` z+y0PD_koeIhGSeK!Enw-b_a7K?~>u67kZ#&d3=lI%@T#EZBRWEn3_bX7hXoca=*YM zWVB8)PIi5s9)HvLr~c=Qs>Ngz?E*>zsP7020V$r zKMvbfzMNk_yuVKQxtGJ;Jl08iNHWEKky7CqF$8xaB10`2Yaj!QdJ?1bCY_WP*t$n_ z9f?x=MU9AbrUcso(;L*ht3!gnP9Nh`2PY(wOV72HFTs58^fyhdaUF*HtS1XtvE|rb zUBhD4xKP9T{KGJ7Rnn4Oux4nVl28qwYP3+TD}Ea40a{lYaB@G?K<&U=b{^`r{Dz$nr3 zPW8ibrri^a=sR3ttcPbTqxBH8`NME8qDC+XbkKKde?R?8l;M@eZd=+}ZrH%}VaeN? z6%zF%X#>0OK49YzCT>p=VIR<8{-TPO?FFW&ff69}`EaL)?JzDcq1k*ez_1>+9Aw-I)*WjWG`X zdEfr(GX=k2>SY&<%5~chjD&DqiG8~ofiaVe>gy&{?{D|=5}VBA*=f1jduxG{_fTL| zIfE3^o&bfNQ%==v$*=tB-;ZRcy9%vc8?~KAZKj;5F~nC+NRxm|T%=WEkIzS@qoTgm zp>{rGL1<&?z-4|IcyfLcqa`BlV*)E|mL@wxEO>o{b&NK(0Czl1ELDQCz0=x0Bq!Z8cpD{!#csOveN()6c%kV zUEwmk+PF>hECC>GiiWIidP)b=0?6xQh!^m~ZPJU}VdTJv1w-%# zL5a})ZOkg%qLBB+7Tr>7pDb9}nWVSuvjr<4{)KBHV${5+L#8;N&)_|e*rSQUQJ|gB z(}L(Ji8@c@1l(P0j5m83>a7ryNC$CtIkVMANRTXA zDHmFC7c7@jA%t&ue$wVnE|AdW+Y0PS35gUVq2Cx8c-Ni2paQ`2U0s{1@_n0)ZgT z|8|Cpi|s#2fLv^BY)NS{0(uf6Vw_@J?84&0T%tSxVF?fi2RrA#JqH($I8anrke~hk h521%7D2U|jV&vrF;bdlx1mx!803lIRiz`SV{a??({v`ka diff --git a/zlib/zlib.h b/zlib/zlib.h index 953cb5012dc..6b7244f9943 100644 --- a/zlib/zlib.h +++ b/zlib/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.13, October 13th, 2022 + version 1.3, August 18th, 2023 - Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -37,11 +37,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.13" -#define ZLIB_VERNUM 0x12d0 +#define ZLIB_VERSION "1.3" +#define ZLIB_VERNUM 0x1300 #define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 13 +#define ZLIB_VER_MINOR 3 +#define ZLIB_VER_REVISION 0 #define ZLIB_VER_SUBREVISION 0 /* @@ -78,8 +78,8 @@ extern "C" { even in the case of corrupted input. */ -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); +typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size); +typedef void (*free_func)(voidpf opaque, voidpf address); struct internal_state; @@ -217,7 +217,7 @@ typedef gz_header FAR *gz_headerp; /* basic functions */ -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +ZEXTERN const char * ZEXPORT zlibVersion(void); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check @@ -225,12 +225,12 @@ ZEXTERN const char * ZEXPORT zlibVersion OF((void)); */ /* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); +ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default - allocation functions. + allocation functions. total_in, total_out, adler, and msg are initialized. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all @@ -247,7 +247,7 @@ ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); */ -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce @@ -320,8 +320,8 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. + avail_out is greater than six when the flush marker begins, in order to avoid + repeated flush markers upon calling deflate() again when avail_out == 0. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was @@ -360,7 +360,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); */ -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT deflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending @@ -375,7 +375,7 @@ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); /* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateInit(z_streamp strm); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by @@ -383,7 +383,8 @@ ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); read or consumed. The allocation of a sliding window will be deferred to the first call of inflate (if the decompression does not complete on the first call). If zalloc and zfree are set to Z_NULL, inflateInit updates - them to use default allocation functions. + them to use default allocation functions. total_in, total_out, adler, and + msg are initialized. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the @@ -397,7 +398,7 @@ ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); */ -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce @@ -517,7 +518,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); */ -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending @@ -535,12 +536,12 @@ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); */ /* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); +ZEXTERN int ZEXPORT deflateInit2(z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy); This is another version of deflateInit with more compression options. The fields zalloc, zfree and opaque must be initialized before by the caller. @@ -607,9 +608,9 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, compression: this will be done by deflate(). */ -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); +ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); /* Initializes the compression dictionary from the given byte sequence without producing any compressed output. When using the zlib format, this @@ -651,9 +652,9 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, not perform any compression: this will be done by deflate(). */ -ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, - Bytef *dictionary, - uInt *dictLength)); +ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); /* Returns the sliding dictionary being maintained by deflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied @@ -673,8 +674,8 @@ ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, stream state is inconsistent. */ -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); +ZEXTERN int ZEXPORT deflateCopy(z_streamp dest, + z_streamp source); /* Sets the destination stream as a complete copy of the source stream. @@ -691,20 +692,20 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, destination. */ -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +ZEXTERN int ZEXPORT deflateReset(z_streamp strm); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate the internal compression state. The stream will leave the compression level and any other attributes that may have been - set unchanged. + set unchanged. total_in, total_out, adler, and msg are initialized. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); +ZEXTERN int ZEXPORT deflateParams(z_streamp strm, + int level, + int strategy); /* Dynamically update the compression level and compression strategy. The interpretation of level and strategy is as in deflateInit2(). This can be @@ -729,7 +730,7 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, Then no more input data should be provided before the deflateParams() call. If this is done, the old level and strategy will be applied to the data compressed before deflateParams(), and the new level and strategy will be - applied to the the data compressed after deflateParams(). + applied to the data compressed after deflateParams(). deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if @@ -740,11 +741,11 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, retried with more output space. */ -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); +ZEXTERN int ZEXPORT deflateTune(z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain); /* Fine tune deflate's internal compression parameters. This should only be used by someone who understands the algorithm used by zlib's deflate for @@ -757,8 +758,8 @@ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. */ -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); +ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm, + uLong sourceLen); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or @@ -772,9 +773,9 @@ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, than Z_FINISH or Z_NO_FLUSH are used. */ -ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, - unsigned *pending, - int *bits)); +ZEXTERN int ZEXPORT deflatePending(z_streamp strm, + unsigned *pending, + int *bits); /* deflatePending() returns the number of bytes and bits of output that have been generated, but not yet provided in the available output. The bytes not @@ -787,9 +788,9 @@ ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, stream state was inconsistent. */ -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); +ZEXTERN int ZEXPORT deflatePrime(z_streamp strm, + int bits, + int value); /* deflatePrime() inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits @@ -804,8 +805,8 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, source stream state was inconsistent. */ -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); +ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm, + gz_headerp head); /* deflateSetHeader() provides gzip header information for when a gzip stream is requested by deflateInit2(). deflateSetHeader() may be called @@ -821,16 +822,17 @@ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). + the time set to zero, and os set to the current operating system, with no + extra, name, or comment fields. The gzip header is returned to the default + state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); +ZEXTERN int ZEXPORT inflateInit2(z_streamp strm, + int windowBits); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized @@ -883,9 +885,9 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, deferred until inflate() is called. */ -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); +ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, @@ -906,9 +908,9 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, inflate(). */ -ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, - Bytef *dictionary, - uInt *dictLength)); +ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); /* Returns the sliding dictionary being maintained by inflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied @@ -921,7 +923,7 @@ ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, stream state is inconsistent. */ -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateSync(z_streamp strm); /* Skips invalid compressed data until a possible full flush point (see above for the description of deflate with Z_FULL_FLUSH) can be found, or until all @@ -940,8 +942,8 @@ ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); input each time, until success or end of the input data. */ -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); +ZEXTERN int ZEXPORT inflateCopy(z_streamp dest, + z_streamp source); /* Sets the destination stream as a complete copy of the source stream. @@ -956,18 +958,19 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, destination. */ -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateReset(z_streamp strm); /* This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. + total_in, total_out, adler, and msg are initialized. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, - int windowBits)); +ZEXTERN int ZEXPORT inflateReset2(z_streamp strm, + int windowBits); /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted @@ -980,9 +983,9 @@ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, the windowBits parameter is invalid. */ -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); +ZEXTERN int ZEXPORT inflatePrime(z_streamp strm, + int bits, + int value); /* This function inserts bits in the inflate input stream. The intent is that this function is used to start inflating at a bit position in the @@ -1001,7 +1004,7 @@ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, stream state was inconsistent. */ -ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +ZEXTERN long ZEXPORT inflateMark(z_streamp strm); /* This function returns two values, one in the lower 16 bits of the return value, and the other in the remaining upper bits, obtained by shifting the @@ -1029,8 +1032,8 @@ ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); source stream state was inconsistent. */ -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); +ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm, + gz_headerp head); /* inflateGetHeader() requests that gzip header information be stored in the provided gz_header structure. inflateGetHeader() may be called after @@ -1070,8 +1073,8 @@ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, */ /* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); +ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits, + unsigned char FAR *window); Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized @@ -1091,13 +1094,13 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, the version of the header file. */ -typedef unsigned (*in_func) OF((void FAR *, - z_const unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); +typedef unsigned (*in_func)(void FAR *, + z_const unsigned char FAR * FAR *); +typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned); -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); +ZEXTERN int ZEXPORT inflateBack(z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc); /* inflateBack() does a raw inflate with a single call using a call-back interface for input and output. This is potentially more efficient than @@ -1165,7 +1168,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, cannot return Z_OK. */ -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm); /* All memory allocated by inflateBackInit() is freed. @@ -1173,7 +1176,7 @@ ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); state was inconsistent. */ -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +ZEXTERN uLong ZEXPORT zlibCompileFlags(void); /* Return flags indicating compile-time options. Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: @@ -1226,8 +1229,8 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); you need special options. */ -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); +ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size @@ -1241,9 +1244,9 @@ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, buffer. */ -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); +ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte @@ -1257,15 +1260,15 @@ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, Z_STREAM_ERROR if the level parameter is invalid. */ -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen); /* compressBound() returns an upper bound on the compressed size after compress() or compress2() on sourceLen bytes. It would be used before a compress() or compress2() call to allocate the destination buffer. */ -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); +ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); /* Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size @@ -1282,8 +1285,8 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, buffer with the uncompressed data up to that point. */ -ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong *sourceLen)); +ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen); /* Same as uncompress, except that sourceLen is a pointer, where the length of the source is *sourceLen. On return, *sourceLen is the number of @@ -1302,7 +1305,7 @@ ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode); Open the gzip (.gz) file at path for reading and decompressing, or compressing and writing. The mode parameter is as in fopen ("rb" or "wb") @@ -1339,7 +1342,7 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); file could not be opened. */ -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode); /* Associate a gzFile with the file descriptor fd. File descriptors are obtained from calls like open, dup, creat, pipe or fileno (if the file has @@ -1362,7 +1365,7 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); will not detect if fd is invalid (unless fd is -1). */ -ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size); /* Set the internal buffer size used by this library's functions for file to size. The default buffer size is 8192 bytes. This function must be called @@ -1378,7 +1381,7 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); too late. */ -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy); /* Dynamically update the compression level and strategy for file. See the description of deflateInit2 for the meaning of these parameters. Previously @@ -1389,7 +1392,7 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); or Z_MEM_ERROR if there is a memory allocation error. */ -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len); /* Read and decompress up to len uncompressed bytes from file into buf. If the input file is not in gzip format, gzread copies the given number of @@ -1419,8 +1422,8 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); Z_STREAM_ERROR. */ -ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, - gzFile file)); +ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, + gzFile file); /* Read and decompress up to nitems items of size size from file into buf, otherwise operating as gzread() does. This duplicates the interface of @@ -1445,14 +1448,14 @@ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, file, resetting and retrying on end-of-file, when size is not 1. */ -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); +ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len); /* Compress and write the len uncompressed bytes at buf to file. gzwrite returns the number of uncompressed bytes written or 0 in case of error. */ -ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, - z_size_t nitems, gzFile file)); +ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, + z_size_t nitems, gzFile file); /* Compress and write nitems items of size size from buf to file, duplicating the interface of stdio's fwrite(), with size_t request and return types. If @@ -1465,7 +1468,7 @@ ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, is returned, and the error state is set to Z_STREAM_ERROR. */ -ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...); /* Convert, format, compress, and write the arguments (...) to file under control of the string format, as in fprintf. gzprintf returns the number of @@ -1480,7 +1483,7 @@ ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); This can be determined using zlibCompileFlags(). */ -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s); /* Compress and write the given null-terminated string s to file, excluding the terminating null character. @@ -1488,7 +1491,7 @@ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); gzputs returns the number of characters written, or -1 in case of error. */ -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len); /* Read and decompress bytes from file into buf, until len-1 characters are read, or until a newline character is read and transferred to buf, or an @@ -1502,13 +1505,13 @@ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); buf are indeterminate. */ -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +ZEXTERN int ZEXPORT gzputc(gzFile file, int c); /* Compress and write c, converted to an unsigned char, into file. gzputc returns the value that was written, or -1 in case of error. */ -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +ZEXTERN int ZEXPORT gzgetc(gzFile file); /* Read and decompress one byte from file. gzgetc returns this byte or -1 in case of end of file or error. This is implemented as a macro for speed. @@ -1517,7 +1520,7 @@ ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); points to has been clobbered or not. */ -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); /* Push c back onto the stream for file to be read as the first character on the next read. At least one character of push-back is always allowed. @@ -1529,7 +1532,7 @@ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); gzseek() or gzrewind(). */ -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +ZEXTERN int ZEXPORT gzflush(gzFile file, int flush); /* Flush all pending output to file. The parameter flush is as in the deflate() function. The return value is the zlib error number (see function @@ -1545,8 +1548,8 @@ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); */ /* -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); +ZEXTERN z_off_t ZEXPORT gzseek(gzFile file, + z_off_t offset, int whence); Set the starting position to offset relative to whence for the next gzread or gzwrite on file. The offset represents a number of bytes in the @@ -1564,7 +1567,7 @@ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, would be before the current position. */ -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +ZEXTERN int ZEXPORT gzrewind(gzFile file); /* Rewind file. This function is supported only for reading. @@ -1572,7 +1575,7 @@ ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); */ /* -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +ZEXTERN z_off_t ZEXPORT gztell(gzFile file); Return the starting position for the next gzread or gzwrite on file. This position represents a number of bytes in the uncompressed data stream, @@ -1583,7 +1586,7 @@ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); */ /* -ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); +ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file); Return the current compressed (actual) read or write offset of file. This offset includes the count of bytes that precede the gzip stream, for example @@ -1592,7 +1595,7 @@ ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); be used for a progress indicator. On error, gzoffset() returns -1. */ -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +ZEXTERN int ZEXPORT gzeof(gzFile file); /* Return true (1) if the end-of-file indicator for file has been set while reading, false (0) otherwise. Note that the end-of-file indicator is set @@ -1607,7 +1610,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); has grown since the previous end of file was detected. */ -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +ZEXTERN int ZEXPORT gzdirect(gzFile file); /* Return true (1) if file is being copied directly while reading, or false (0) if file is a gzip stream being decompressed. @@ -1628,7 +1631,7 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); gzip file reading and decompression, which may not be desired.) */ -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose(gzFile file); /* Flush all pending output for file, if necessary, close file and deallocate the (de)compression state. Note that once file is closed, you @@ -1641,8 +1644,8 @@ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); last read ended in the middle of a gzip stream, or Z_OK on success. */ -ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); -ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_r(gzFile file); +ZEXTERN int ZEXPORT gzclose_w(gzFile file); /* Same as gzclose(), but gzclose_r() is only for use when reading, and gzclose_w() is only for use when writing or appending. The advantage to @@ -1653,7 +1656,7 @@ ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); zlib library. */ -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum); /* Return the error message for the last error which occurred on file. errnum is set to zlib error number. If an error occurred in the file system @@ -1669,7 +1672,7 @@ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); functions above that do not distinguish those cases in their return values. */ -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +ZEXTERN void ZEXPORT gzclearerr(gzFile file); /* Clear the error and end-of-file flags for file. This is analogous to the clearerr() function in stdio. This is useful for continuing to read a gzip @@ -1686,7 +1689,7 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); library. */ -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. An Adler-32 value is in the range of a 32-bit @@ -1706,15 +1709,15 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (adler != original_adler) error(); */ -ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, - z_size_t len)); +ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, + z_size_t len); /* Same as adler32(), but with a size_t length. */ /* -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); +ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, + z_off_t len2); Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for @@ -1724,7 +1727,7 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, negative, the result has no meaning or utility. */ -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. @@ -1742,14 +1745,14 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); if (crc != original_crc) error(); */ -ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf, - z_size_t len)); +ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf, + z_size_t len); /* Same as crc32(), but with a size_t length. */ /* -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); +ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2); Combine two CRC-32 check values into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, CRC-32 check values were @@ -1759,13 +1762,13 @@ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); */ /* -ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2)); +ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2); Return the operator corresponding to length len2, to be used with crc32_combine_op(). */ -ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op)); +ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op); /* Give the same result as crc32_combine(), using op in place of len2. op is is generated from len2 by crc32_combine_gen(). This will be faster than @@ -1778,20 +1781,20 @@ ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op)); /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); +ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateInit_(z_streamp strm, + const char *version, int stream_size); +ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size); +ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size); #ifdef Z_PREFIX_SET # define z_deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) @@ -1836,7 +1839,7 @@ struct gzFile_s { unsigned char *next; z_off64_t pos; }; -ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */ #ifdef Z_PREFIX_SET # undef z_gzgetc # define z_gzgetc(g) \ @@ -1853,13 +1856,13 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ * without large file support, _LFS64_LARGEFILE must also be true */ #ifdef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t)); + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); + ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); #endif #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) @@ -1881,50 +1884,50 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ # define crc32_combine_gen crc32_combine_gen64 # endif # ifndef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); # endif #else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); + ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); #endif #else /* Z_SOLO */ - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); #endif /* !Z_SOLO */ /* undocumented functions */ -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); -ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); -ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); -ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF((z_streamp)); -ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); -ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +ZEXTERN const char * ZEXPORT zError(int); +ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void); +ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int); +ZEXTERN int ZEXPORT inflateValidate(z_streamp, int); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp); +ZEXTERN int ZEXPORT inflateResetKeep(z_streamp); +ZEXTERN int ZEXPORT deflateResetKeep(z_streamp); #if defined(_WIN32) && !defined(Z_SOLO) -ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, - const char *mode)); +ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path, + const char *mode); #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO -ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, - const char *format, - va_list va)); +ZEXTERN int ZEXPORTVA gzvprintf(gzFile file, + const char *format, + va_list va); # endif #endif diff --git a/zlib/zlib2ansi b/zlib/zlib2ansi deleted file mode 100755 index 23b2a1d5a3e..00000000000 --- a/zlib/zlib2ansi +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/perl - -# Transform K&R C function definitions into ANSI equivalent. -# -# Author: Paul Marquess -# Version: 1.0 -# Date: 3 October 2006 - -# TODO -# -# Assumes no function pointer parameters. unless they are typedefed. -# Assumes no literal strings that look like function definitions -# Assumes functions start at the beginning of a line - -use strict; -use warnings; - -local $/; -$_ = <>; - -my $sp = qr{ \s* (?: /\* .*? \*/ )? \s* }x; # assume no nested comments - -my $d1 = qr{ $sp (?: [\w\*\s]+ $sp)* $sp \w+ $sp [\[\]\s]* $sp }x ; -my $decl = qr{ $sp (?: \w+ $sp )+ $d1 }xo ; -my $dList = qr{ $sp $decl (?: $sp , $d1 )* $sp ; $sp }xo ; - - -while (s/^ - ( # Start $1 - ( # Start $2 - .*? # Minimal eat content - ( ^ \w [\w\s\*]+ ) # $3 -- function name - \s* # optional whitespace - ) # $2 - Matched up to before parameter list - - \( \s* # Literal "(" + optional whitespace - ( [^\)]+ ) # $4 - one or more anythings except ")" - \s* \) # optional whitespace surrounding a Literal ")" - - ( (?: $dList )+ ) # $5 - - $sp ^ { # literal "{" at start of line - ) # Remember to $1 - //xsom - ) -{ - my $all = $1 ; - my $prefix = $2; - my $param_list = $4 ; - my $params = $5; - - StripComments($params); - StripComments($param_list); - $param_list =~ s/^\s+//; - $param_list =~ s/\s+$//; - - my $i = 0 ; - my %pList = map { $_ => $i++ } - split /\s*,\s*/, $param_list; - my $pMatch = '(\b' . join('|', keys %pList) . '\b)\W*$' ; - - my @params = split /\s*;\s*/, $params; - my @outParams = (); - foreach my $p (@params) - { - if ($p =~ /,/) - { - my @bits = split /\s*,\s*/, $p; - my $first = shift @bits; - $first =~ s/^\s*//; - push @outParams, $first; - $first =~ /^(\w+\s*)/; - my $type = $1 ; - push @outParams, map { $type . $_ } @bits; - } - else - { - $p =~ s/^\s+//; - push @outParams, $p; - } - } - - - my %tmp = map { /$pMatch/; $_ => $pList{$1} } - @outParams ; - - @outParams = map { " $_" } - sort { $tmp{$a} <=> $tmp{$b} } - @outParams ; - - print $prefix ; - print "(\n" . join(",\n", @outParams) . ")\n"; - print "{" ; - -} - -# Output any trailing code. -print ; -exit 0; - - -sub StripComments -{ - - no warnings; - - # Strip C & C++ comments - # From the perlfaq - $_[0] =~ - - s{ - /\* ## Start of /* ... */ comment - [^*]*\*+ ## Non-* followed by 1-or-more *'s - ( - [^/*][^*]*\*+ - )* ## 0-or-more things which don't start with / - ## but do end with '*' - / ## End of /* ... */ comment - - | ## OR C++ Comment - // ## Start of C++ comment // - [^\n]* ## followed by 0-or-more non end of line characters - - | ## OR various things which aren't comments: - - ( - " ## Start of " ... " string - ( - \\. ## Escaped char - | ## OR - [^"\\] ## Non "\ - )* - " ## End of " ... " string - - | ## OR - - ' ## Start of ' ... ' string - ( - \\. ## Escaped char - | ## OR - [^'\\] ## Non '\ - )* - ' ## End of ' ... ' string - - | ## OR - - . ## Anything other char - [^/"'\\]* ## Chars which doesn't start a comment, string or escape - ) - }{$2}gxs; - -} diff --git a/zlib/zutil.c b/zlib/zutil.c index 9543ae825e3..b1c5d2d3c6d 100644 --- a/zlib/zutil.c +++ b/zlib/zutil.c @@ -24,13 +24,11 @@ z_const char * const z_errmsg[10] = { }; -const char * ZEXPORT zlibVersion() -{ +const char * ZEXPORT zlibVersion(void) { return ZLIB_VERSION; } -uLong ZEXPORT zlibCompileFlags() -{ +uLong ZEXPORT zlibCompileFlags(void) { uLong flags; flags = 0; @@ -121,9 +119,7 @@ uLong ZEXPORT zlibCompileFlags() # endif int ZLIB_INTERNAL z_verbose = verbose; -void ZLIB_INTERNAL z_error(m) - char *m; -{ +void ZLIB_INTERNAL z_error(char *m) { fprintf(stderr, "%s\n", m); exit(1); } @@ -132,9 +128,7 @@ void ZLIB_INTERNAL z_error(m) /* exported to allow conversion of error code to string for compress() and * uncompress() */ -const char * ZEXPORT zError(err) - int err; -{ +const char * ZEXPORT zError(int err) { return ERR_MSG(err); } @@ -148,22 +142,14 @@ const char * ZEXPORT zError(err) #ifndef HAVE_MEMCPY -void ZLIB_INTERNAL zmemcpy(dest, source, len) - Bytef* dest; - const Bytef* source; - uInt len; -{ +void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) { if (len == 0) return; do { *dest++ = *source++; /* ??? to be unrolled */ } while (--len != 0); } -int ZLIB_INTERNAL zmemcmp(s1, s2, len) - const Bytef* s1; - const Bytef* s2; - uInt len; -{ +int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) { uInt j; for (j = 0; j < len; j++) { @@ -172,10 +158,7 @@ int ZLIB_INTERNAL zmemcmp(s1, s2, len) return 0; } -void ZLIB_INTERNAL zmemzero(dest, len) - Bytef* dest; - uInt len; -{ +void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) { if (len == 0) return; do { *dest++ = 0; /* ??? to be unrolled */ @@ -216,8 +199,7 @@ local ptr_table table[MAX_PTR]; * a protected system like OS/2. Use Microsoft C instead. */ -voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) -{ +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { voidpf buf; ulg bsize = (ulg)items*size; @@ -242,8 +224,7 @@ voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) return buf; } -void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) -{ +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { int n; (void)opaque; @@ -279,14 +260,12 @@ void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) # define _hfree hfree #endif -voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) -{ +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) { (void)opaque; return _halloc((long)items, size); } -void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) -{ +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; _hfree(ptr); } @@ -299,25 +278,18 @@ void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC -extern voidp malloc OF((uInt size)); -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); +extern voidp malloc(uInt size); +extern voidp calloc(uInt items, uInt size); +extern void free(voidpf ptr); #endif -voidpf ZLIB_INTERNAL zcalloc(opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; -{ +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { (void)opaque; return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } -void ZLIB_INTERNAL zcfree(opaque, ptr) - voidpf opaque; - voidpf ptr; -{ +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; free(ptr); } diff --git a/zlib/zutil.h b/zlib/zutil.h index 0bc7f4ecd1c..902a304cc2d 100644 --- a/zlib/zutil.h +++ b/zlib/zutil.h @@ -191,9 +191,9 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* provide prototypes for these when building zlib without LFS */ #if !defined(_WIN32) && \ (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); #endif /* common defaults */ @@ -232,16 +232,16 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # define zmemzero(dest, len) memset(dest, 0, len) # endif #else - void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); + void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len); + int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len); + void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len); #endif /* Diagnostic functions */ #ifdef ZLIB_DEBUG # include extern int ZLIB_INTERNAL z_verbose; - extern void ZLIB_INTERNAL z_error OF((char *m)); + extern void ZLIB_INTERNAL z_error(char *m); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} @@ -258,9 +258,9 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #endif #ifndef Z_SOLO - voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, - unsigned size)); - void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); + voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, + unsigned size); + void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr); #endif #define ZALLOC(strm, items, size) \ From e467e8d8c2cc6810a189d12c2a04b8b9f482a327 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 9 Mar 2023 09:34:47 +1100 Subject: [PATCH 072/158] MDEV-30825 innodb_compression_algorithm=0 (none) increments Innodb_num_pages_page_compression_error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fil_page_compress_low returns 0 for both innodb_compression_algorithm=0 and where there is compression errors. On the two callers to this function, don't increment the compression errors if the algorithm was none. Reviewed by: Marko Mäkelä --- .../r/innodb-page_compression_none.result | 18 +++++++++++++ .../t/innodb-page_compression_none.test | 26 +++++++++++++++++++ storage/innobase/fil/fil0pagecompress.cc | 10 ++++--- 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb-page_compression_none.result create mode 100644 mysql-test/suite/innodb/t/innodb-page_compression_none.test diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_none.result b/mysql-test/suite/innodb/r/innodb-page_compression_none.result new file mode 100644 index 00000000000..58b2119e042 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-page_compression_none.result @@ -0,0 +1,18 @@ +# +# MDEV-30825 innodb_compression_algorithm=0 (none) increments Innodb_num_pages_page_compression_error +# +SET @save_compression_algorithm=@@GLOBAL.innodb_compression_algorithm; +SET GLOBAL innodb_compression_algorithm=0; +SELECT VARIABLE_VALUE INTO @compress_errors FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Innodb_num_pages_page_compression_error'; +CREATE TABLE t (c INT) page_compressed=1 page_compression_level=4 ENGINE=InnoDB; +INSERT INTO t VALUES (1); +FLUSH TABLES t FOR EXPORT; +UNLOCK TABLES; +SELECT VARIABLE_VALUE - @compress_errors AS NUMBER_OF_ERRORS FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Innodb_num_pages_page_compression_error'; +NUMBER_OF_ERRORS +0 +DROP TABLE t; +SET GLOBAL innodb_compression_algorithm=@save_compression_algorithm; +# +# End of 10.4 tests +# diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_none.test b/mysql-test/suite/innodb/t/innodb-page_compression_none.test new file mode 100644 index 00000000000..e4eaae8bcb2 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-page_compression_none.test @@ -0,0 +1,26 @@ +-- source include/innodb_checksum_algorithm.inc + +--echo # +--echo # MDEV-30825 innodb_compression_algorithm=0 (none) increments Innodb_num_pages_page_compression_error +--echo # + +SET @save_compression_algorithm=@@GLOBAL.innodb_compression_algorithm; +SET GLOBAL innodb_compression_algorithm=0; +SELECT VARIABLE_VALUE INTO @compress_errors FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Innodb_num_pages_page_compression_error'; + + +CREATE TABLE t (c INT) page_compressed=1 page_compression_level=4 ENGINE=InnoDB; +INSERT INTO t VALUES (1); + +FLUSH TABLES t FOR EXPORT; +UNLOCK TABLES; + +SELECT VARIABLE_VALUE - @compress_errors AS NUMBER_OF_ERRORS FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Innodb_num_pages_page_compression_error'; + +DROP TABLE t; +SET GLOBAL innodb_compression_algorithm=@save_compression_algorithm; + +--echo # +--echo # End of 10.4 tests +--echo # + diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index 21b148223f6..c830b0fd6ab 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -201,6 +201,7 @@ static ulint fil_page_compress_for_full_crc32( bool encrypted) { ulint comp_level = fsp_flags_get_page_compression_level(flags); + ulint comp_algo = fil_space_t::get_compression_algo(flags); if (comp_level == 0) { comp_level = page_zip_level; @@ -209,12 +210,12 @@ static ulint fil_page_compress_for_full_crc32( const ulint header_len = FIL_PAGE_COMP_ALGO; ulint write_size = fil_page_compress_low( - buf, out_buf, header_len, - fil_space_t::get_compression_algo(flags), comp_level); + buf, out_buf, header_len, comp_algo, comp_level); if (write_size == 0) { fail: - srv_stats.pages_page_compression_error.inc(); + if (comp_algo != PAGE_UNCOMPRESSED) + srv_stats.pages_page_compression_error.inc(); return 0; } @@ -293,7 +294,8 @@ static ulint fil_page_compress_for_non_full_crc32( header_len, comp_algo, comp_level); if (write_size == 0) { - srv_stats.pages_page_compression_error.inc(); + if (comp_algo != PAGE_UNCOMPRESSED) + srv_stats.pages_page_compression_error.inc(); return 0; } From 8f2f8f31737150c1fef548a61c6321ca99b71f89 Mon Sep 17 00:00:00 2001 From: Xiaotong Niu Date: Mon, 9 Oct 2023 14:13:46 +0800 Subject: [PATCH 073/158] MDEV-26494 Fix buffer overflow of string lib on Arm64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the hexlo function, the element type of the array hex_lo_digit is not explicitly declared as signed char, causing elements with a value of -1 to be converted to 255 on Arm64. The problem occurs because "char" is unsigned by default on Arm64 compiler, but signed on x86 compiler. This problem can be seen in https://godbolt.org/z/rT775xshj The above issue causes "use-after-poison" exception in my_mb_wc_filename function. The code snippet where the error occurred is shown below, copied from below link. https://github.com/MariaDB/server/blob/5fc19e71375fb39eb85354321bf852d998aecf81/strings/ctype-utf8.c#L2728 2728 if ((byte1= hexlo(byte1)) >= 0 && 2729 (byte2= hexlo(byte2)) >= 0) { 2731 int byte3= hexlo(s[3]); … } At line 2729, when byte2 is 0, which indicates the end of the string s. (1) On x86, hexlo(0) return -1 and line 2731 is skipped, as expected. (2) On Arm64, hexlo(0) return 255 and line 2731 is executed, not as expected, accessing s[3] after the null character of string s, thus raising the "user-after-poison" error. The problem was discovered when executing the main.mysqlcheck test. Signed-off-by: Xiaotong Niu --- strings/ctype-utf8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index cdac17be3c6..e3e5a248deb 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -6872,7 +6872,7 @@ static const uint16 uni_FF20_FF5F[64]= static int hexlo(int x) { - static const char hex_lo_digit[256]= + static const signed char hex_lo_digit[256]= { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* ................ */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* ................ */ From 19eac149b1043be712763a9dca115ce26e7c5823 Mon Sep 17 00:00:00 2001 From: hotairballoon-3573 <15198894161@139.com> Date: Sun, 17 Sep 2023 22:57:34 +0800 Subject: [PATCH 074/158] MDEV-32142 mariadb-install-db shows warning on missing directory /auth_pam_tool_dir Without pam compiled there will be no auth_pam_tool_dir, so check this before attempting something that will error. Reviewer: Sergei Golubchik / Daniel Black --- scripts/mysql_install_db.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index e358aeea551..79b566ec3c5 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -492,7 +492,7 @@ done if test -n "$user" then - if test -z "$srcdir" -a "$in_rpm" -eq 0 + if test -z "$srcdir" -a "$in_rpm" -eq 0 -a -d "$pamtooldir/auth_pam_tool_dir" then chown 0 "$pamtooldir/auth_pam_tool_dir/auth_pam_tool" && \ chmod 04755 "$pamtooldir/auth_pam_tool_dir/auth_pam_tool" From cfd1788182b0deb399d4eb7a75fb6093087b0c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 18 Oct 2023 16:51:04 +0300 Subject: [PATCH 075/158] MDEV-32511: Race condition between checkpoint and page write fil_aio_callback(): Invoke fil_node_t::complete_write() before releasing any page latch, so that in case a log checkpoint is executed roughly concurrently with the first write into a file since the previous checkpoint, we will not miss a fdatasync() or fsync() call to make the write durable. --- storage/innobase/fil/fil0fil.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index ea7c496b86b..885b0a700ea 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -3445,18 +3445,18 @@ void fil_aio_callback(const IORequest &request) if (!request.bpage) { + request.node->complete_write(); ut_ad(!srv_read_only_mode); if (request.type == IORequest::DBLWR_BATCH) buf_dblwr.flush_buffered_writes_completed(request); else ut_ad(request.type == IORequest::WRITE_ASYNC); -write_completed: request.node->complete_write(); } else if (request.is_write()) { + request.node->complete_write(); buf_page_write_complete(request); - goto write_completed; } else { From 3f663d273b78916aa5f230f38e626215d39c9427 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 18 Oct 2023 17:34:26 +0300 Subject: [PATCH 076/158] Removed fixed temporay file paths in mtr --- mysql-test/main/subselect3.inc | 6 +++--- mysql-test/main/subselect3.result | 4 ++-- mysql-test/main/subselect3_jcl6.result | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mysql-test/main/subselect3.inc b/mysql-test/main/subselect3.inc index 881cda2e736..2258456f355 100644 --- a/mysql-test/main/subselect3.inc +++ b/mysql-test/main/subselect3.inc @@ -642,14 +642,14 @@ DROP TABLE t1, t2; create table t1 (a int, b decimal(13, 3)); insert into t1 values (1, 0.123); --disable_ps2_protocol -select a, (select max(b) from t1) into outfile "subselect.out.file.1" from t1; +select a, (select max(b) from t1) into outfile "../../tmp/subselect.out.file.1" from t1; --enable_ps2_protocol delete from t1; -load data infile "subselect.out.file.1" into table t1; +load data infile "../../tmp/subselect.out.file.1" into table t1; select * from t1; drop table t1; let $datadir=`select @@datadir`; ---remove_file $datadir/test/subselect.out.file.1 +--remove_file $MYSQLTEST_VARDIR/tmp/subselect.out.file.1 # # Bug #37894: Assertion in init_read_record_seq in handler.h line 1444 diff --git a/mysql-test/main/subselect3.result b/mysql-test/main/subselect3.result index 0034f61ac23..3554fdb3fab 100644 --- a/mysql-test/main/subselect3.result +++ b/mysql-test/main/subselect3.result @@ -795,9 +795,9 @@ SELECT 1 FROM t1 WHERE t1.a NOT IN (SELECT 1 FROM t1, t2 WHERE 0); DROP TABLE t1, t2; create table t1 (a int, b decimal(13, 3)); insert into t1 values (1, 0.123); -select a, (select max(b) from t1) into outfile "subselect.out.file.1" from t1; +select a, (select max(b) from t1) into outfile "../../tmp/subselect.out.file.1" from t1; delete from t1; -load data infile "subselect.out.file.1" into table t1; +load data infile "../../tmp/subselect.out.file.1" into table t1; select * from t1; a b 1 0.123 diff --git a/mysql-test/main/subselect3_jcl6.result b/mysql-test/main/subselect3_jcl6.result index b7b18bf80e0..74de2199977 100644 --- a/mysql-test/main/subselect3_jcl6.result +++ b/mysql-test/main/subselect3_jcl6.result @@ -798,9 +798,9 @@ SELECT 1 FROM t1 WHERE t1.a NOT IN (SELECT 1 FROM t1, t2 WHERE 0); DROP TABLE t1, t2; create table t1 (a int, b decimal(13, 3)); insert into t1 values (1, 0.123); -select a, (select max(b) from t1) into outfile "subselect.out.file.1" from t1; +select a, (select max(b) from t1) into outfile "../../tmp/subselect.out.file.1" from t1; delete from t1; -load data infile "subselect.out.file.1" into table t1; +load data infile "../../tmp/subselect.out.file.1" into table t1; select * from t1; a b 1 0.123 From 699cfee595b917ab05a99426bc6e9adbaa342e71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 19 Oct 2023 08:11:28 +0300 Subject: [PATCH 077/158] MDEV-32518 Fix ./mtr main.log_slow_debug main.subselect Clean up after main.log_slow_debug. --- mysql-test/main/log_slow_debug.result | 18 +++++++++--------- mysql-test/main/log_slow_debug.test | 23 +++++++++++------------ 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/mysql-test/main/log_slow_debug.result b/mysql-test/main/log_slow_debug.result index f06e47604ac..88019d87322 100644 --- a/mysql-test/main/log_slow_debug.result +++ b/mysql-test/main/log_slow_debug.result @@ -216,15 +216,6 @@ sql_text [slow] DEALLOCATE PREPARE stmt [slow] DROP SEQUENCE s4 # -# Clean up -# -SET SESSION debug_dbug=@saved_dbug; -TRUNCATE mysql.slow_log; -SET @@global.slow_query_log= @org_slow_query_log; -SET @@global.log_output= @org_log_output; -SET @@global.log_slow_admin_statements= @org_log_slow_admin_statements; -DROP PROCEDURE show_slow_log; -# # MDEV-30820: slow log Rows_examined out of range # CREATE TABLE `tab_MDEV_30820` ( @@ -253,3 +244,12 @@ drop table tab_MDEV_30820; # # End of 10.4 test # +# +# Clean up +# +SET SESSION debug_dbug=@saved_dbug; +TRUNCATE mysql.slow_log; +SET @@global.slow_query_log= @org_slow_query_log; +SET @@global.log_output= @org_log_output; +SET @@global.log_slow_admin_statements= @org_log_slow_admin_statements; +DROP PROCEDURE show_slow_log; diff --git a/mysql-test/main/log_slow_debug.test b/mysql-test/main/log_slow_debug.test index 17ca9039850..5c8385f2fc9 100644 --- a/mysql-test/main/log_slow_debug.test +++ b/mysql-test/main/log_slow_debug.test @@ -83,18 +83,6 @@ TRUNCATE TABLE mysql.slow_log; CALL show_slow_log(); ---echo # ---echo # Clean up ---echo # - -SET SESSION debug_dbug=@saved_dbug; -TRUNCATE mysql.slow_log; -SET @@global.slow_query_log= @org_slow_query_log; -SET @@global.log_output= @org_log_output; -SET @@global.log_slow_admin_statements= @org_log_slow_admin_statements; -DROP PROCEDURE show_slow_log; - - --echo # --echo # MDEV-30820: slow log Rows_examined out of range --echo # @@ -131,3 +119,14 @@ drop table tab_MDEV_30820; --echo # --echo # End of 10.4 test --echo # + +--echo # +--echo # Clean up +--echo # + +SET SESSION debug_dbug=@saved_dbug; +TRUNCATE mysql.slow_log; +SET @@global.slow_query_log= @org_slow_query_log; +SET @@global.log_output= @org_log_output; +SET @@global.log_slow_admin_statements= @org_log_slow_admin_statements; +DROP PROCEDURE show_slow_log; From 2d6dc65de56be1d151374cd0257e616407cd1c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 19 Oct 2023 08:24:37 +0300 Subject: [PATCH 078/158] MDEV-32144 fixup In commit 384eb570a654261639dc1fc73c347f0d3759f567 the debug check was relaxed in trx_undo_header_create(), not in the intended function trx_undo_write_xid(). --- storage/innobase/trx/trx0undo.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index 15acd40645a..bb327f6cc9d 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -523,8 +523,9 @@ static void trx_undo_write_xid(buf_block_t *block, uint16_t offset, static_cast(xid.bqual_length)); const ulint xid_length= static_cast(xid.gtrid_length + xid.bqual_length); - mtr->memcpy(*block, &block->frame[offset + TRX_UNDO_XA_XID], - xid.data, xid_length); + mtr->memcpy(*block, + &block->frame[offset + TRX_UNDO_XA_XID], + xid.data, xid_length); if (UNIV_LIKELY(xid_length < XIDDATASIZE)) mtr->memset(block, offset + TRX_UNDO_XA_XID + xid_length, XIDDATASIZE - xid_length, 0); From dbba1bb1c3522090f9a3bc54c107d684bfaed4ab Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Thu, 19 Oct 2023 13:11:20 +0530 Subject: [PATCH 079/158] MDEV-31851 After crash recovery, undo tablespace fails to open recv_recovery_from_checkpoint_start(): InnoDB should add the redo log block header + trailer size while checking the log sequence number in log file with log sequence number in the system tablespace first page. --- storage/innobase/log/log0recv.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 3b59fb43ed3..a213b4842ce 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3559,7 +3559,8 @@ completed: } else if (checkpoint_lsn != flush_lsn) { ut_ad(!srv_log_file_created); - if (checkpoint_lsn + sizeof_checkpoint < flush_lsn) { + if (checkpoint_lsn + sizeof_checkpoint + + log_sys.framing_size() < flush_lsn) { ib::warn() << "Are you sure you are using the right " << LOG_FILE_NAME From f53321cbdb53c949295732c95f8a01dd3585fb78 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 18 Oct 2023 12:34:04 +0200 Subject: [PATCH 080/158] MDEV-20471 Assertion during cleanup of failed CREATE TABLE LIKE While cleaning up a failed CREATE TABLE LIKE , `mysql_rm_table_no_locks` erroneously attempted to remove all tables involved in the query, including the source table (sequence). Fix to temporarily modify `table_list` to ensure that only the intended table is removed during the cleanup. --- mysql-test/main/sequence_debug.result | 12 ++++++++++++ mysql-test/main/sequence_debug.test | 16 ++++++++++++++++ sql/sql_sequence.cc | 3 ++- sql/sql_table.cc | 10 +++++++++- 4 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 mysql-test/main/sequence_debug.result create mode 100644 mysql-test/main/sequence_debug.test diff --git a/mysql-test/main/sequence_debug.result b/mysql-test/main/sequence_debug.result new file mode 100644 index 00000000000..5147837bade --- /dev/null +++ b/mysql-test/main/sequence_debug.result @@ -0,0 +1,12 @@ +# +# MDEV-20471 Assertion during cleanup of failed CREATE TABLE LIKE +# +CREATE SEQUENCE s; +set @save_debug_dbug=@@debug_dbug; +set debug_dbug='+d,kill_query_on_sequence_insert'; +CREATE TABLE t LIKE s; +ERROR 70100: Query execution was interrupted +DROP TABLE t; +ERROR 42S02: Unknown table 'test.t' +DROP SEQUENCE s; +set debug_dbug=@save_debug_dbug; diff --git a/mysql-test/main/sequence_debug.test b/mysql-test/main/sequence_debug.test new file mode 100644 index 00000000000..a9ccc2c61b2 --- /dev/null +++ b/mysql-test/main/sequence_debug.test @@ -0,0 +1,16 @@ +--source include/have_debug.inc + +--echo # +--echo # MDEV-20471 Assertion during cleanup of failed CREATE TABLE LIKE +--echo # + +CREATE SEQUENCE s; +set @save_debug_dbug=@@debug_dbug; +set debug_dbug='+d,kill_query_on_sequence_insert'; +--error ER_QUERY_INTERRUPTED +CREATE TABLE t LIKE s; +--error ER_BAD_TABLE_ERROR +DROP TABLE t; + +DROP SEQUENCE s; +set debug_dbug=@save_debug_dbug; diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index 9387d2527fe..ab77eabfa28 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -300,7 +300,8 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *org_table_list) Query_tables_list query_tables_list_backup; TABLE_LIST table_list; // For sequence table DBUG_ENTER("sequence_insert"); - + DBUG_EXECUTE_IF("kill_query_on_sequence_insert", + thd->set_killed(KILL_QUERY);); /* seq is 0 if sequence was created with CREATE TABLE instead of CREATE SEQUENCE diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 99839e61ba8..987c66e8aeb 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5306,7 +5306,14 @@ int mysql_create_table_no_lock(THD *thd, const LEX_CSTRING *db, if (res) { DBUG_ASSERT(thd->is_error()); - /* Drop the table as it wasn't completely done */ + /* + Drop the new table, we were not completely done. + + Temporarily modify table_list to avoid dropping source sequence + in CREATE TABLE LIKE . + */ + TABLE_LIST *tail= table_list->next_local; + table_list->next_local= NULL; if (!mysql_rm_table_no_locks(thd, table_list, 1, create_info->tmp_table(), false, true /* Sequence*/, @@ -5320,6 +5327,7 @@ int mysql_create_table_no_lock(THD *thd, const LEX_CSTRING *db, */ res= 2; } + table_list->next_local= tail; } } From 85751ed81d6cdfffbe2572f401e62884a4e8c8dc Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Thu, 19 Oct 2023 15:39:44 +0530 Subject: [PATCH 081/158] MDEV-31851 After crash recovery, undo tablespace fails to open srv_all_undo_tablespaces_open(): While opening the extra unused undo tablespaces, InnoDB should use ULINT_UNDEFINED instead of SRV_SPACE_ID_UPPER_BOUND. --- storage/innobase/srv/srv0start.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 180c8a1a825..9b8ce4b2fa8 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -702,7 +702,7 @@ unused_undo: snprintf(name, sizeof(name), "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, i); ulint space_id= srv_undo_tablespace_open(create_new_db, name, i); - if (!space_id || space_id == SRV_SPACE_ID_UPPER_BOUND) + if (!space_id || space_id == ULINT_UNDEFINED) break; ++srv_undo_tablespaces_open; } From 04c664bd8fd5034eb9d3dd545af9b79cbf35de64 Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Wed, 18 Oct 2023 16:26:15 +0300 Subject: [PATCH 082/158] MDEV-32512 log_page_corruption.test fails on windows build Some calls of extend_space() perl function miss the last parameter. Some cases in the test check corrupted pages info absence in the output file if the table is dropped. We should also test if the corruption presents before testing its absence. Reviewed by: Vladislav Vaintroub --- .../mariabackup/log_page_corruption.result | 28 +++++++++++++++ .../mariabackup/log_page_corruption.test | 36 +++++++++++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/mariabackup/log_page_corruption.result b/mysql-test/suite/mariabackup/log_page_corruption.result index 101471002b8..507784bd190 100644 --- a/mysql-test/suite/mariabackup/log_page_corruption.result +++ b/mysql-test/suite/mariabackup/log_page_corruption.result @@ -26,6 +26,17 @@ INSERT INTO t7_corrupted_to_alter VALUES (3), (4), (5), (6), (7), (8), (9); # Backup must fail due to page corruption FOUND 1 /Database page corruption detected.*/ in backup.log # "innodb_corrupted_pages" file must not exist +# Backup must not fail, but "innodb_corrupted_pages" file must be created due to --log-innodb-page-corruption option, and the file must contain all corrupted pages info, including those, which are supposed to be absent in the next test due to "DROP TABLE" execution during backup +--- "innodb_corrupted_pages" file content: --- +test/t1_corrupted +4 6 7 +test/t2_corrupted +5 6 8 +test/t5_corrupted_to_rename +4 +test/t6_corrupted_to_drop +4 +------ # Backup must not fail, but "innodb_corrupted_pages" file must be created due to --log-innodb-page-corruption option FOUND 1 /Database page corruption detected.*/ in backup.log FOUND 1 /completed OK!/ in backup.log @@ -45,6 +56,23 @@ INSERT INTO t1_inc_corrupted VALUES (3), (4), (5), (6), (7), (8), (9); INSERT INTO t2_inc_corrupted VALUES (3), (4), (5), (6), (7), (8), (9); INSERT INTO t3_inc VALUES (3), (4), (5), (6), (7), (8), (9); # restart +# Backup must not fail, but "innodb_corrupted_pages" file must be created due to --log-innodb-page-corruption option, and the file must contain all corrupted pages info, including those, which are supposed to be absent in the next test due to "DROP TABLE" execution during backup +--- "innodb_corrupted_pages" file content: --- +test/t1_corrupted +4 6 7 +test/t1_inc_corrupted +4 6 7 +test/t2_corrupted +5 6 8 +test/t2_inc_corrupted +5 6 8 +test/t5_corrupted_to_rename_renamed +4 +test/t5_inc_corrupted_to_rename +4 +test/t6_inc_corrupted_to_drop +4 +------ # Backup must not fail, but "innodb_corrupted_pages" file must be created due to --log-innodb-page-corruption option --- "innodb_corrupted_pages" file content: --- test/t1_corrupted diff --git a/mysql-test/suite/mariabackup/log_page_corruption.test b/mysql-test/suite/mariabackup/log_page_corruption.test index e14735fd024..b4723c30213 100644 --- a/mysql-test/suite/mariabackup/log_page_corruption.test +++ b/mysql-test/suite/mariabackup/log_page_corruption.test @@ -49,7 +49,7 @@ corrupt_space_page_id("$schema/t2_corrupted.ibd", $last_page_no = extend_space("$schema/t5_corrupted_to_rename.ibd", 1); corrupt_space_page_id("$schema/t5_corrupted_to_rename.ibd", $last_page_no); -$last_page_no = extend_space("$schema/t6_corrupted_to_drop.ibd", ); +$last_page_no = extend_space("$schema/t6_corrupted_to_drop.ibd", 1); corrupt_space_page_id("$schema/t6_corrupted_to_drop.ibd", $last_page_no); EOF --source include/start_mysqld.inc @@ -74,6 +74,21 @@ exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir= --file_exists $corrupted_pages_file --rmdir $targetdir +--echo # Backup must not fail, but "innodb_corrupted_pages" file must be created due to --log-innodb-page-corruption option, and the file must contain all corrupted pages info, including those, which are supposed to be absent in the next test due to "DROP TABLE" execution during backup +--disable_result_log +--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --log-innodb-page-corruption --target-dir=$targetdir +--enable_result_log + +--echo --- "innodb_corrupted_pages" file content: --- +perl; +do "$ENV{MTR_SUITE_DIR}/include/corrupt-page.pl"; +print_corrupted_pages_file($ENV{corrupted_pages_file}, + $ENV{corrupted_pages_file_filt}); +EOF +--cat_file $corrupted_pages_file_filt +--echo ------ +--rmdir $targetdir + --let after_load_tablespaces=CREATE TABLE test.t4_corrupted_new ENGINE=INNODB SELECT UUID() from test.seq_1_to_10 --let add_corrupted_page_for_test_t4_corrupted_new=1 --let after_copy_test_t5_corrupted_to_rename=RENAME TABLE test.t5_corrupted_to_rename TO test.t5_corrupted_to_rename_renamed @@ -134,7 +149,7 @@ $last_page_no = extend_space("$schema/t5_inc_corrupted_to_rename.ibd", 1); corrupt_space_page_id("$schema/t5_inc_corrupted_to_rename.ibd", $last_page_no); print $fh "$last_page_no\n"; -$last_page_no = extend_space("$schema/t6_inc_corrupted_to_drop.ibd", ); +$last_page_no = extend_space("$schema/t6_inc_corrupted_to_drop.ibd", 1); corrupt_space_page_id("$schema/t6_inc_corrupted_to_drop.ibd", $last_page_no); close $fh; @@ -143,6 +158,23 @@ EOF --let incdir=$MYSQLTEST_VARDIR/tmp/backup_inc +--echo # Backup must not fail, but "innodb_corrupted_pages" file must be created due to --log-innodb-page-corruption option, and the file must contain all corrupted pages info, including those, which are supposed to be absent in the next test due to "DROP TABLE" execution during backup +--disable_result_log +--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --log-innodb-page-corruption --target-dir=$incdir --incremental-basedir=$targetdir --dbug=+d,mariabackup_events,mariabackup_inject_code +--disable_result_log + +--let corrupted_pages_file = $incdir/innodb_corrupted_pages +--echo --- "innodb_corrupted_pages" file content: --- +perl; +do "$ENV{MTR_SUITE_DIR}/include/corrupt-page.pl"; +print_corrupted_pages_file($ENV{corrupted_pages_file}, + $ENV{corrupted_pages_file_filt}); +EOF +--cat_file $corrupted_pages_file_filt +--echo ------ +--remove_file $corrupted_pages_file_filt +--rmdir $incdir + --let after_load_tablespaces=CREATE TABLE test.t4_inc_corrupted_new ENGINE=INNODB SELECT UUID() from test.seq_1_to_10 --let add_corrupted_page_for_test_t4_inc_corrupted_new=1 --let after_copy_test_t5_inc_corrupted_to_rename=RENAME TABLE test.t5_inc_corrupted_to_rename TO test.t5_inc_corrupted_to_rename_renamed From a1b6befc781fde34e90078bae294c5e0470a72a8 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 18 Oct 2023 17:13:21 +0300 Subject: [PATCH 083/158] Fixed crash in is_stat_table() when using hash joins. Other usage if persistent statistics is checking 'stats_is_read' in caller, which is why this was not noticed earlier. Other things: - Simplified no_stat_values_provided --- mysql-test/main/analyze.result | 26 ++++++++++++++++++++++++++ mysql-test/main/analyze.test | 27 +++++++++++++++++++++++++++ sql/sql_statistics.cc | 9 +++------ sql/sql_statistics.h | 4 +--- 4 files changed, 57 insertions(+), 9 deletions(-) diff --git a/mysql-test/main/analyze.result b/mysql-test/main/analyze.result index aac9ed7b3a2..af39315d2b4 100644 --- a/mysql-test/main/analyze.result +++ b/mysql-test/main/analyze.result @@ -417,5 +417,31 @@ test t1 B 1 NULL test t1 B 2 NULL drop table t1; # +# Crash inis_eits_usable() +# +CREATE TABLE t1 (a int) ENGINE=MyISAM; +CREATE TABLE t2 (b int) ENGINE=MyISAM; +INSERT INTO t1 (a) VALUES (4), (6); +INSERT INTO t2 (b) VALUES (0), (8); +set @save_join_cache_level=@@join_cache_level; +set @save_optimizer_switch=@@optimizer_switch; +SET join_cache_level=3; +SET optimizer_switch='join_cache_hashed=on'; +SET optimizer_switch='join_cache_bka=on'; +set optimizer_switch='hash_join_cardinality=on'; +select benchmark(1,1); +benchmark(1,1) +0 +EXPLAIN +SELECT * FROM t1, t2 WHERE b=a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +1 SIMPLE t2 hash_ALL NULL #hash#$hj 5 test.t1.a 2 Using where; Using join buffer (flat, BNLH join) +SELECT * FROM t1, t2 WHERE b=a; +a b +DROP TABLE t1,t2; +set @@optimizer_switch=@save_optimizer_switch; +set @@join_cache_level=@save_join_cache_level; +# # End of 10.6 tests # diff --git a/mysql-test/main/analyze.test b/mysql-test/main/analyze.test index e3b776f11ca..357d5c503d3 100644 --- a/mysql-test/main/analyze.test +++ b/mysql-test/main/analyze.test @@ -269,6 +269,33 @@ alter ignore table t1 rename key `b` to `B`, LOCK=shared; select * from mysql.index_stats where table_name= "t1"; drop table t1; +--echo # +--echo # Crash inis_eits_usable() +--echo # + +CREATE TABLE t1 (a int) ENGINE=MyISAM; + +CREATE TABLE t2 (b int) ENGINE=MyISAM; + +INSERT INTO t1 (a) VALUES (4), (6); +INSERT INTO t2 (b) VALUES (0), (8); + +set @save_join_cache_level=@@join_cache_level; +set @save_optimizer_switch=@@optimizer_switch; +SET join_cache_level=3; +SET optimizer_switch='join_cache_hashed=on'; +SET optimizer_switch='join_cache_bka=on'; +set optimizer_switch='hash_join_cardinality=on'; + +select benchmark(1,1); +EXPLAIN +SELECT * FROM t1, t2 WHERE b=a; +SELECT * FROM t1, t2 WHERE b=a; +DROP TABLE t1,t2; + +set @@optimizer_switch=@save_optimizer_switch; +set @@join_cache_level=@save_join_cache_level; + --echo # --echo # End of 10.6 tests --echo # diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index abeeee8019b..32fe80c9a9f 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -3125,7 +3125,8 @@ void TABLE_STATISTICS_CB::update_stats_in_table(TABLE *table) for ( ; *field_ptr; field_ptr++, column_stats++) (*field_ptr)->read_stats= column_stats; /* Mark that stats are now usable */ - table->stats_is_read= true; + table->stats_is_read= (table->stats_cb->stats_available != + TABLE_STAT_NO_STATS); } @@ -3246,8 +3247,6 @@ read_statistics_for_tables(THD *thd, TABLE_LIST *tables, bool force_reload) } mysql_mutex_unlock(&table_share->LOCK_statistics); table->stats_cb->update_stats_in_table(table); - table->stats_is_read= (stats_cb->stats_available != - TABLE_STAT_NO_STATS); } } @@ -4312,11 +4311,9 @@ bool is_eits_usable(Field *field) Column_statistics* col_stats= field->read_stats; // check if column_statistics was allocated for this field - if (!col_stats) + if (!col_stats || !field->table->stats_is_read) return false; - DBUG_ASSERT(field->table->stats_is_read); - /* (1): checks if we have EITS statistics for a particular column (2): Don't use EITS for GEOMETRY columns diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h index 5c98451808a..166e7a75c79 100644 --- a/sql/sql_statistics.h +++ b/sql/sql_statistics.h @@ -445,9 +445,7 @@ public: */ bool no_stat_values_provided() { - if (column_stat_nulls == no_values_provided_bitmap()) - return true; - return false; + return (column_stat_nulls == no_values_provided_bitmap()); } }; From 6a674c3142456eee2b28b4a122c15974a9583e98 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 19 Oct 2023 12:57:30 +0300 Subject: [PATCH 084/158] MDEV-32476 LeakSanitizer errors in get_quick_select or Assertion ... Problem was that JOIN_TAB::cleanup() was not run because JOIN::top_join_tab_count was not set in case of early errors. Fixed by setting JOIN::tab_join_tab_count when JOIN_TAB's are allocated. Something that should eventually be fixed: - Cleaning up JOIN_TAB's is now done in 3 different loops. JOIN_TAB::cleanup() is only doing a partial cleanup. Other cleanups are done outside of JOIN_TAB::cleanup(). The above should be fixed so that JOIN_TAB::cleanup() is freeing everything related to it's own memory, including all its sub JOIN_ TAB's. JOIN::cleanup() should only loop over all it's top JOIN_TAB's and call JOIN_TAB::cleanup() on these. This will greatly simplify and speedup the current code (as we now do some cleanup's twice). --- mysql-test/main/leaks.result | 13 +++++++++++++ mysql-test/main/leaks.test | 22 ++++++++++++++++++++++ sql/sql_select.cc | 6 +++--- 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 mysql-test/main/leaks.result create mode 100644 mysql-test/main/leaks.test diff --git a/mysql-test/main/leaks.result b/mysql-test/main/leaks.result new file mode 100644 index 00000000000..386459b622a --- /dev/null +++ b/mysql-test/main/leaks.result @@ -0,0 +1,13 @@ +# +# MDEV-32476 LeakSanitizer errors in get_quick_select or +# Assertion `status_var.local_memory_used == 0 +# +CREATE TABLE t1 (pk INT AUTO_INCREMENT, f INT, PRIMARY KEY (pk), KEY(f)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,10),(2,20); +INSERT INTO t1 (f) SELECT t2.f FROM t1 t2, t1 t3 WHERE t2.f = 10 AND t3.pk > 'foo'; +ERROR 22007: Truncated incorrect DECIMAL value: 'foo' +DROP TABLE t1; +# +# End of 10.6 tests +# diff --git a/mysql-test/main/leaks.test b/mysql-test/main/leaks.test new file mode 100644 index 00000000000..3482aac702a --- /dev/null +++ b/mysql-test/main/leaks.test @@ -0,0 +1,22 @@ +# +# Collection of small tests that finds leaks and does not fit in any other +# tests +# + +--source include/have_innodb.inc + +--echo # +--echo # MDEV-32476 LeakSanitizer errors in get_quick_select or +--echo # Assertion `status_var.local_memory_used == 0 +--echo # + +CREATE TABLE t1 (pk INT AUTO_INCREMENT, f INT, PRIMARY KEY (pk), KEY(f)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,10),(2,20); +--error ER_TRUNCATED_WRONG_VALUE +INSERT INTO t1 (f) SELECT t2.f FROM t1 t2, t1 t3 WHERE t2.f = 10 AND t3.pk > 'foo'; +DROP TABLE t1; + +--echo # +--echo # End of 10.6 tests +--echo # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 14d6994ccc5..52eee901243 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5299,6 +5299,7 @@ make_join_statistics(JOIN *join, List &tables_list, /* The following should be optimized to only clear critical things */ bzero((void*)stat, sizeof(JOIN_TAB)* table_count); + join->top_join_tab_count= table_count; /* Initialize POSITION objects */ for (i=0 ; i <= table_count ; i++) @@ -5880,8 +5881,8 @@ make_join_statistics(JOIN *join, List &tables_list, join->cond_equal= &((Item_cond_and*) (join->conds))->m_cond_equal; s->quick=select->quick; - s->needed_reg=select->needed_reg; select->quick=0; + s->needed_reg=select->needed_reg; impossible_range= records == 0 && s->table->reginfo.impossible_range; if (join->thd->lex->sql_command == SQLCOM_SELECT && optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER)) @@ -14409,7 +14410,6 @@ void JOIN_TAB::cleanup() */ table->pos_in_table_list->table= NULL; free_tmp_table(join->thd, table); - table= NULL; } else { @@ -14422,8 +14422,8 @@ void JOIN_TAB::cleanup() multiple times (it may be) */ tmp->table= NULL; - table= NULL; } + table= NULL; DBUG_VOID_RETURN; } /* From 4941ac9192394a1489f0bf01b6dd2ee5ec2906c9 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Tue, 19 Sep 2023 18:22:49 +0300 Subject: [PATCH 085/158] MDEV-32113: utf8mb3_key_col=utf8mb4_value cannot be used for ref (Variant#3: Allow cross-charset comparisons, use a special CHARSET_INFO to create lookup keys. Review input addressed.) Equalities that compare utf8mb{3,4}_general_ci strings, like: WHERE ... utf8mb3_key_col=utf8mb4_value (MB3-4-CMP) can now be used to construct ref[const] access and also participate in multiple-equalities. This means that utf8mb3_key_col can be used for key-lookups when compared with an utf8mb4 constant, field or expression using '=' or '<=>' comparison operators. This is controlled by optimizer_switch='cset_narrowing=on', which is OFF by default. IMPLEMENTATION Item value comparison in (MB3-4-CMP) is done using utf8mb4_general_ci. This is valid as any utf8mb3 value is also an utf8mb4 value. When making index lookup value for utf8mb3_key_col, we do "Charset Narrowing": characters that are in the Basic Multilingual Plane (=BMP) are copied as-is, as they can be represented in utf8mb3. Characters that are outside the BMP cannot be represented in utf8mb3 and are replaced with U+FFFD, the "Replacement Character". In utf8mb4_general_ci, the Replacement Character compares as equal to any character that's not in BMP. Because of this, the constructed lookup value will find all index records that would be considered equal by the original condition (MB3-4-CMP). Approved-by: Monty --- include/m_ctype.h | 3 + libmysqld/CMakeLists.txt | 1 + mysql-test/main/cset_narrowing.result | 470 ++++++++++++++++++ mysql-test/main/cset_narrowing.test | 150 ++++++ mysql-test/main/mysqld--help.result | 2 +- .../main/mysqltest_tracking_info.result | 2 +- .../sys_vars/r/optimizer_switch_basic.result | 32 +- .../sys_vars/r/sysvars_server_embedded.result | 2 +- .../r/sysvars_server_notembedded.result | 2 +- sql/CMakeLists.txt | 4 +- sql/cset_narrowing.cc | 35 ++ sql/cset_narrowing.h | 143 ++++++ sql/field.cc | 15 +- sql/item.cc | 26 +- sql/item.h | 41 +- sql/item_cmpfunc.cc | 34 +- sql/opt_range.cc | 19 +- sql/sql_priv.h | 1 + sql/sql_select.cc | 3 +- sql/sql_select.h | 34 +- sql/sql_type.h | 8 +- sql/sys_vars.cc | 1 + strings/ctype-utf8.c | 12 + 23 files changed, 1001 insertions(+), 39 deletions(-) create mode 100644 mysql-test/main/cset_narrowing.result create mode 100644 mysql-test/main/cset_narrowing.test create mode 100644 sql/cset_narrowing.cc create mode 100644 sql/cset_narrowing.h diff --git a/include/m_ctype.h b/include/m_ctype.h index cda43d81b39..d5a274367a8 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -1711,6 +1711,9 @@ my_well_formed_length(CHARSET_INFO *cs, const char *b, const char *e, #include "t_ctype.h" #endif +int my_wc_mb_utf8mb4_bmp_only(CHARSET_INFO *cs, my_wc_t wc, uchar *r, + uchar *e); + #ifdef __cplusplus } #endif diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 6cff07ee132..b414903f705 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -50,6 +50,7 @@ ENDIF() SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc libmysql.c ../sql-common/errmsg.c ../sql-common/client.c + ../sql/cset_narrowing.cc ../sql-common/my_user.c ../sql-common/pack.c ../sql-common/client_plugin.c ../sql/password.c ../sql/discover.cc ../sql/derror.cc diff --git a/mysql-test/main/cset_narrowing.result b/mysql-test/main/cset_narrowing.result new file mode 100644 index 00000000000..b7cb32bc86c --- /dev/null +++ b/mysql-test/main/cset_narrowing.result @@ -0,0 +1,470 @@ +set +@tmp_csetn_os= @@optimizer_switch, +optimizer_switch='cset_narrowing=on'; +set names utf8mb4; +create table t1 ( +mb3name varchar(32), +mb3 varchar(32) collate utf8mb3_general_ci, +key(mb3) +); +insert into t1 select seq, seq from seq_1_to_10000; +insert into t1 values ('mb3-question-mark', '?'); +insert into t1 values ('mb3-replacement-char', _utf8mb3 0xEFBFBD); +create table t10 ( +pk int auto_increment primary key, +mb4name varchar(32), +mb4 varchar(32) character set utf8mb4 collate utf8mb4_general_ci +); +insert into t10 (mb4name, mb4) values +('mb4-question-mark','?'), +('mb4-replacement-char', _utf8mb4 0xEFBFBD), +('mb4-smiley', _utf8mb4 0xF09F988A), +('1', '1'); +analyze table t1,t10 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t10 analyze status Engine-independent statistics collected +test.t10 analyze status OK +# +# Check that constants are already handled: the following should use +# ref/range, because constants are converted into utf8mb3. +# +select collation('abc'); +collation('abc') +utf8mb4_general_ci +explain select * from t1 force index (mb3) where t1.mb3='abc'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref mb3 mb3 99 const 1 Using index condition +explain select * from t1 force index (mb3) where t1.mb3 in ('abc','cde','xyz'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range mb3 mb3 99 NULL 3 Using index condition +explain select * from t1 force index (mb3) where t1.mb3 between 'abc' and 'acc'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range mb3 mb3 99 NULL 1 Using index condition +explain select * from t1 force index (mb3) where t1.mb3 <'000'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range mb3 mb3 99 NULL 1 Using index condition +# If a constant can't be represented in utf8mb3, an error is produced: +explain select * from t1 force index (mb3) where t1.mb3='😊'; +ERROR HY000: Illegal mix of collations (utf8mb3_general_ci,IMPLICIT) and (utf8mb4_general_ci,COERCIBLE) for operation '=' +# +# Check ref access on mb3_field=mb4_field +# +explain format=json +select * from t10,t1 where t10.mb4=t1.mb3; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t10", + "access_type": "ALL", + "rows": 4, + "filtered": 100, + "attached_condition": "t10.mb4 is not null" + }, + "table": { + "table_name": "t1", + "access_type": "ref", + "possible_keys": ["mb3"], + "key": "mb3", + "key_length": "99", + "used_key_parts": ["mb3"], + "ref": ["test.t10.mb4"], + "rows": 1, + "filtered": 100, + "index_condition": "t1.mb3 = t10.mb4" + } + } +} +select * from t10,t1 where t10.mb4=t1.mb3; +pk mb4name mb4 mb3name mb3 +1 mb4-question-mark ? mb3-question-mark ? +2 mb4-replacement-char � mb3-replacement-char � +3 mb4-smiley 😊 mb3-replacement-char � +4 1 1 1 1 +select * from t10,t1 use index() where t10.mb4=t1.mb3; +pk mb4name mb4 mb3name mb3 +4 1 1 1 1 +1 mb4-question-mark ? mb3-question-mark ? +2 mb4-replacement-char � mb3-replacement-char � +3 mb4-smiley 😊 mb3-replacement-char � +explain format=json +select * from t10,t1 where t10.mb4<=>t1.mb3; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t10", + "access_type": "ALL", + "rows": 4, + "filtered": 100 + }, + "table": { + "table_name": "t1", + "access_type": "ref", + "possible_keys": ["mb3"], + "key": "mb3", + "key_length": "99", + "used_key_parts": ["mb3"], + "ref": ["test.t10.mb4"], + "rows": 1, + "filtered": 100, + "index_condition": "t10.mb4 <=> t1.mb3" + } + } +} +select * from t10,t1 where t10.mb4<=>t1.mb3; +pk mb4name mb4 mb3name mb3 +1 mb4-question-mark ? mb3-question-mark ? +2 mb4-replacement-char � mb3-replacement-char � +3 mb4-smiley 😊 mb3-replacement-char � +4 1 1 1 1 +set statement optimizer_switch='cset_narrowing=off', join_cache_level=0 for +explain format=json +select * from t10,t1 where t10.mb4=t1.mb3; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t10", + "access_type": "ALL", + "rows": 4, + "filtered": 100 + }, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 10002, + "filtered": 100, + "attached_condition": "t10.mb4 = convert(t1.mb3 using utf8mb4)" + } + } +} +# +# Check ref access on mb3_field=mb4_expr +# +explain format=json +select * from t10,t1 where t1.mb3=concat('',t10.mb4); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t10", + "access_type": "ALL", + "rows": 4, + "filtered": 100 + }, + "table": { + "table_name": "t1", + "access_type": "ref", + "possible_keys": ["mb3"], + "key": "mb3", + "key_length": "99", + "used_key_parts": ["mb3"], + "ref": ["func"], + "rows": 1, + "filtered": 100, + "index_condition": "t1.mb3 = concat('',t10.mb4)" + } + } +} +select * from t10,t1 where t1.mb3=concat('',t10.mb4); +pk mb4name mb4 mb3name mb3 +1 mb4-question-mark ? mb3-question-mark ? +2 mb4-replacement-char � mb3-replacement-char � +3 mb4-smiley 😊 mb3-replacement-char � +4 1 1 1 1 +select * from t10,t1 use index() where t1.mb3=concat('',t10.mb4); +pk mb4name mb4 mb3name mb3 +4 1 1 1 1 +1 mb4-question-mark ? mb3-question-mark ? +2 mb4-replacement-char � mb3-replacement-char � +3 mb4-smiley 😊 mb3-replacement-char � +# Check that ref optimizer gets the right constant. +# We need a const table for that, because key=const is handled by +# coercing the constant. +# +# So, we take the smiley: +select * from t10 where t10.pk=3; +pk mb4name mb4 +3 mb4-smiley 😊 +set optimizer_trace=1; +# And see that we've got the Replacement Character in the ranges: +explain +select * from t10, t1 where t10.mb4=t1.mb3 and t10.pk=3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t10 const PRIMARY PRIMARY 4 const 1 +1 SIMPLE t1 ref mb3 mb3 99 const 3 Using index condition +select +json_detailed(json_extract(trace, '$**.range_scan_alternatives')) as JS +from +information_schema.optimizer_trace; +JS +[ + [ + { + "index": "mb3", + "ranges": + ["(�) <= (mb3) <= (�)"], + "rowid_ordered": true, + "using_mrr": false, + "index_only": false, + "rows": 3, + "cost": 3.760377105, + "chosen": true + } + ] +] +select * from t10, t1 where t10.mb4=t1.mb3 and t10.pk=3; +pk mb4name mb4 mb3name mb3 +3 mb4-smiley 😊 mb3-replacement-char � +# +# Will range optimizer handle t1.mb3>t10.mb4? No... +# +explain format=json +select * from t10, t1 where (t1.mb3=t10.mb4 or t1.mb3='hello') and t10.pk=3; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t10", + "access_type": "const", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["pk"], + "ref": ["const"], + "rows": 1, + "filtered": 100 + }, + "table": { + "table_name": "t1", + "access_type": "range", + "possible_keys": ["mb3"], + "key": "mb3", + "key_length": "99", + "used_key_parts": ["mb3"], + "rows": 4, + "filtered": 100, + "index_condition": "t1.mb3 = '????' or t1.mb3 = 'hello'" + } + } +} +explain format=json +select * from t10, t1 where t1.mb3>t10.mb4 and t10.pk=3; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t10", + "access_type": "const", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["pk"], + "ref": ["const"], + "rows": 1, + "filtered": 100 + }, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 10002, + "filtered": 100, + "attached_condition": "convert(t1.mb3 using utf8mb4) > '????'" + } + } +} +# For comparison, it will handle it when collations match: +create table t2 ( +mb4name varchar(32), +mb4 varchar(32) collate utf8mb4_general_ci, +key(mb4) +); +insert into t2 select * from t1; +explain format=json +select * from t10, t2 where t2.mb4>t10.mb4 and t10.pk=3; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t10", + "access_type": "const", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["pk"], + "ref": ["const"], + "rows": 1, + "filtered": 100 + }, + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["mb4"], + "key": "mb4", + "key_length": "131", + "used_key_parts": ["mb4"], + "rows": 3, + "filtered": 100, + "index_condition": "t2.mb4 > '????'" + } + } +} +# +# Check multiple equalities +# +# - ref acccess lookup keys do use equality substitution, +# - concat() arguments don't +explain format=json +select straight_join * from t10,t1 force index(mb3),t2 +where +t1.mb3=t2.mb4 and t2.mb4=t10.mb4 and concat(t1.mb3, t2.mb4, t10.mb4)<>'Bebebe'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t10", + "access_type": "ALL", + "rows": 4, + "filtered": 100, + "attached_condition": "t10.mb4 is not null and t10.mb4 is not null" + }, + "table": { + "table_name": "t1", + "access_type": "ref", + "possible_keys": ["mb3"], + "key": "mb3", + "key_length": "99", + "used_key_parts": ["mb3"], + "ref": ["test.t10.mb4"], + "rows": 1, + "filtered": 100, + "index_condition": "t1.mb3 = t10.mb4" + }, + "table": { + "table_name": "t2", + "access_type": "ref", + "possible_keys": ["mb4"], + "key": "mb4", + "key_length": "131", + "used_key_parts": ["mb4"], + "ref": ["test.t10.mb4"], + "rows": 1, + "filtered": 100, + "index_condition": "concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe'" + } + } +} +select json_detailed(json_extract(trace, '$**.condition_processing')) as JS +from information_schema.optimizer_trace; +JS +[ + { + "condition": "WHERE", + "original_condition": "t1.mb3 = t2.mb4 and t2.mb4 = t10.mb4 and concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe'", + "steps": + [ + { + "transformation": "equality_propagation", + "resulting_condition": "concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe' and multiple equal(t1.mb3, t2.mb4, t10.mb4)" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe' and multiple equal(t1.mb3, t2.mb4, t10.mb4)" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe' and multiple equal(t1.mb3, t2.mb4, t10.mb4)" + } + ] + } +] +select straight_join * from t10,t1 force index(mb3),t2 +where +t1.mb3=t2.mb4 and t2.mb4=t10.mb4 and concat(t1.mb3, t2.mb4, t10.mb4)<>'Bebebe'; +pk mb4name mb4 mb3name mb3 mb4name mb4 +1 mb4-question-mark ? mb3-question-mark ? mb3-question-mark ? +2 mb4-replacement-char � mb3-replacement-char � mb3-replacement-char � +3 mb4-smiley 😊 mb3-replacement-char � mb3-replacement-char � +4 1 1 1 1 1 1 +# Equality substitution doesn't happen for constants, for both narrowing +# and non-narrowing comparisons: +explain format=json +select * from t10,t1,t2 +where +t1.mb3=t2.mb4 and t2.mb4=t10.mb4 and t10.mb4='hello' and +concat(t1.mb3, t2.mb4, t10.mb4)<>'Bebebe'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t10", + "access_type": "ALL", + "rows": 4, + "filtered": 0.78125, + "attached_condition": "t10.mb4 = 'hello'" + }, + "table": { + "table_name": "t1", + "access_type": "ref", + "possible_keys": ["mb3"], + "key": "mb3", + "key_length": "99", + "used_key_parts": ["mb3"], + "ref": ["const"], + "rows": 1, + "filtered": 100, + "index_condition": "t1.mb3 = t10.mb4" + }, + "table": { + "table_name": "t2", + "access_type": "ref", + "possible_keys": ["mb4"], + "key": "mb4", + "key_length": "131", + "used_key_parts": ["mb4"], + "ref": ["const"], + "rows": 1, + "filtered": 100, + "index_condition": "t2.mb4 = t10.mb4 and concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe'" + } + } +} +select json_detailed(json_extract(trace, '$**.condition_processing')) as JS +from information_schema.optimizer_trace; +JS +[ + { + "condition": "WHERE", + "original_condition": "t1.mb3 = t2.mb4 and t2.mb4 = t10.mb4 and t10.mb4 = 'hello' and concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe'", + "steps": + [ + { + "transformation": "equality_propagation", + "resulting_condition": "t10.mb4 = 'hello' and concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe' and multiple equal(t1.mb3, t2.mb4, t10.mb4)" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "t10.mb4 = 'hello' and concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe' and multiple equal(t1.mb3, t2.mb4, t10.mb4)" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "t10.mb4 = 'hello' and concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe' and multiple equal(t1.mb3, t2.mb4, t10.mb4)" + } + ] + } +] +drop table t2; +drop table t1, t10; +set optimizer_switch=@tmp_csetn_os; diff --git a/mysql-test/main/cset_narrowing.test b/mysql-test/main/cset_narrowing.test new file mode 100644 index 00000000000..4d0947f6376 --- /dev/null +++ b/mysql-test/main/cset_narrowing.test @@ -0,0 +1,150 @@ +# +# Test character set narrowing +# + +--source include/have_utf8mb4.inc +--source include/have_sequence.inc +--source include/not_embedded.inc + +set + @tmp_csetn_os= @@optimizer_switch, + optimizer_switch='cset_narrowing=on'; + +set names utf8mb4; +create table t1 ( + mb3name varchar(32), + mb3 varchar(32) collate utf8mb3_general_ci, + key(mb3) +); +insert into t1 select seq, seq from seq_1_to_10000; +insert into t1 values ('mb3-question-mark', '?'); +insert into t1 values ('mb3-replacement-char', _utf8mb3 0xEFBFBD); + +create table t10 ( + pk int auto_increment primary key, + mb4name varchar(32), + mb4 varchar(32) character set utf8mb4 collate utf8mb4_general_ci +); + +insert into t10 (mb4name, mb4) values + ('mb4-question-mark','?'), + ('mb4-replacement-char', _utf8mb4 0xEFBFBD), + ('mb4-smiley', _utf8mb4 0xF09F988A), + ('1', '1'); + +analyze table t1,t10 persistent for all; +--echo # +--echo # Check that constants are already handled: the following should use +--echo # ref/range, because constants are converted into utf8mb3. +--echo # +select collation('abc'); +explain select * from t1 force index (mb3) where t1.mb3='abc'; +explain select * from t1 force index (mb3) where t1.mb3 in ('abc','cde','xyz'); +explain select * from t1 force index (mb3) where t1.mb3 between 'abc' and 'acc'; +explain select * from t1 force index (mb3) where t1.mb3 <'000'; + +--echo # If a constant can't be represented in utf8mb3, an error is produced: +--error ER_CANT_AGGREGATE_2COLLATIONS +explain select * from t1 force index (mb3) where t1.mb3='😊'; + +--echo # +--echo # Check ref access on mb3_field=mb4_field +--echo # +explain format=json +select * from t10,t1 where t10.mb4=t1.mb3; + +select * from t10,t1 where t10.mb4=t1.mb3; + +select * from t10,t1 use index() where t10.mb4=t1.mb3; + +explain format=json +select * from t10,t1 where t10.mb4<=>t1.mb3; + +select * from t10,t1 where t10.mb4<=>t1.mb3; + +set statement optimizer_switch='cset_narrowing=off', join_cache_level=0 for +explain format=json +select * from t10,t1 where t10.mb4=t1.mb3; + +--echo # +--echo # Check ref access on mb3_field=mb4_expr +--echo # +explain format=json +select * from t10,t1 where t1.mb3=concat('',t10.mb4); + +select * from t10,t1 where t1.mb3=concat('',t10.mb4); + +select * from t10,t1 use index() where t1.mb3=concat('',t10.mb4); + +--echo # Check that ref optimizer gets the right constant. +--echo # We need a const table for that, because key=const is handled by +--echo # coercing the constant. +--echo # +--echo # So, we take the smiley: +select * from t10 where t10.pk=3; +set optimizer_trace=1; + +--echo # And see that we've got the Replacement Character in the ranges: +explain +select * from t10, t1 where t10.mb4=t1.mb3 and t10.pk=3; + +select + json_detailed(json_extract(trace, '$**.range_scan_alternatives')) as JS +from + information_schema.optimizer_trace; + +select * from t10, t1 where t10.mb4=t1.mb3 and t10.pk=3; + +--echo # +--echo # Will range optimizer handle t1.mb3>t10.mb4? No... +--echo # + +explain format=json +select * from t10, t1 where (t1.mb3=t10.mb4 or t1.mb3='hello') and t10.pk=3; + +explain format=json +select * from t10, t1 where t1.mb3>t10.mb4 and t10.pk=3; + +--echo # For comparison, it will handle it when collations match: +create table t2 ( + mb4name varchar(32), + mb4 varchar(32) collate utf8mb4_general_ci, + key(mb4) +); +insert into t2 select * from t1; +explain format=json +select * from t10, t2 where t2.mb4>t10.mb4 and t10.pk=3; + +--echo # +--echo # Check multiple equalities +--echo # + +--echo # - ref acccess lookup keys do use equality substitution, +--echo # - concat() arguments don't +explain format=json +select straight_join * from t10,t1 force index(mb3),t2 +where + t1.mb3=t2.mb4 and t2.mb4=t10.mb4 and concat(t1.mb3, t2.mb4, t10.mb4)<>'Bebebe'; +select json_detailed(json_extract(trace, '$**.condition_processing')) as JS +from information_schema.optimizer_trace; + +select straight_join * from t10,t1 force index(mb3),t2 +where + t1.mb3=t2.mb4 and t2.mb4=t10.mb4 and concat(t1.mb3, t2.mb4, t10.mb4)<>'Bebebe'; + +--echo # Equality substitution doesn't happen for constants, for both narrowing +--echo # and non-narrowing comparisons: +explain format=json +select * from t10,t1,t2 +where + t1.mb3=t2.mb4 and t2.mb4=t10.mb4 and t10.mb4='hello' and + concat(t1.mb3, t2.mb4, t10.mb4)<>'Bebebe'; + +select json_detailed(json_extract(trace, '$**.condition_processing')) as JS +from information_schema.optimizer_trace; + +drop table t2; +drop table t1, t10; + +set optimizer_switch=@tmp_csetn_os; + diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 01167912b37..1c851b9d06c 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -755,7 +755,7 @@ The following specify which files/extra groups are read (specified before remain condition_pushdown_for_derived, split_materialized, condition_pushdown_for_subquery, rowid_filter, condition_pushdown_from_having, not_null_range_scan, - hash_join_cardinality + hash_join_cardinality, cset_narrowing --optimizer-trace=name Controls tracing of the Optimizer: optimizer_trace=option=val[,option=val...], where option diff --git a/mysql-test/main/mysqltest_tracking_info.result b/mysql-test/main/mysqltest_tracking_info.result index 5436dd87122..cad96ef80c4 100644 --- a/mysql-test/main/mysqltest_tracking_info.result +++ b/mysql-test/main/mysqltest_tracking_info.result @@ -38,7 +38,7 @@ SET @@session.session_track_system_variables='optimizer_switch'; set optimizer_switch='index_merge=off,index_merge_union=off,index_merge_sort_union=off,index_merge_intersection=off,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=on,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=on,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off'; -- Tracker : SESSION_TRACK_SYSTEM_VARIABLES -- optimizer_switch --- index_merge=off,index_merge_union=off,index_merge_sort_union=off,index_merge_intersection=off,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=on,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=on,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off +-- index_merge=off,index_merge_union=off,index_merge_sort_union=off,index_merge_intersection=off,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=on,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=on,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off Warnings: Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release diff --git a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result index 7f2e1c6586c..8f5d9071e1e 100644 --- a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result +++ b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result @@ -1,60 +1,60 @@ set @@global.optimizer_switch=@@optimizer_switch; select @@global.optimizer_switch; @@global.optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off select @@session.optimizer_switch; @@session.optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off show global variables like 'optimizer_switch'; Variable_name Value -optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off +optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off show session variables like 'optimizer_switch'; Variable_name Value -optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off +optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off select * from information_schema.global_variables where variable_name='optimizer_switch'; VARIABLE_NAME VARIABLE_VALUE -OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off +OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off select * from information_schema.session_variables where variable_name='optimizer_switch'; VARIABLE_NAME VARIABLE_VALUE -OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off +OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off set global optimizer_switch=4101; set session optimizer_switch=2058; select @@global.optimizer_switch; @@global.optimizer_switch -index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=on,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off +index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=on,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off select @@session.optimizer_switch; @@session.optimizer_switch -index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=on,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off +index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=on,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off set global optimizer_switch="index_merge_sort_union=on"; set session optimizer_switch="index_merge=off"; select @@global.optimizer_switch; @@global.optimizer_switch -index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=on,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off +index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=on,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off select @@session.optimizer_switch; @@session.optimizer_switch -index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=on,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off +index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=on,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off show global variables like 'optimizer_switch'; Variable_name Value -optimizer_switch index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=on,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off +optimizer_switch index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=on,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off show session variables like 'optimizer_switch'; Variable_name Value -optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=on,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off +optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=on,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off select * from information_schema.global_variables where variable_name='optimizer_switch'; VARIABLE_NAME VARIABLE_VALUE -OPTIMIZER_SWITCH index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=on,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off +OPTIMIZER_SWITCH index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=on,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off select * from information_schema.session_variables where variable_name='optimizer_switch'; VARIABLE_NAME VARIABLE_VALUE -OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=on,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off +OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=on,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off set session optimizer_switch="default"; select @@session.optimizer_switch; @@session.optimizer_switch -index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=on,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off +index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=on,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off,hash_join_cardinality=off,cset_narrowing=off set optimizer_switch = replace(@@optimizer_switch, '=off', '=on'); Warnings: Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release select @@optimizer_switch; @@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=on,hash_join_cardinality=on +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=on,hash_join_cardinality=on,cset_narrowing=on set global optimizer_switch=1.1; ERROR 42000: Incorrect argument type to variable 'optimizer_switch' set global optimizer_switch=1e1; 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 a3f33afc416..a6ed72520e5 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -2329,7 +2329,7 @@ VARIABLE_COMMENT Fine-tune the optimizer behavior NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,condition_pushdown_from_having,not_null_range_scan,hash_join_cardinality,default +ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,condition_pushdown_from_having,not_null_range_scan,hash_join_cardinality,cset_narrowing,default READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_TRACE 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 17e8339a352..2ade2a9649a 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -2489,7 +2489,7 @@ VARIABLE_COMMENT Fine-tune the optimizer behavior NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,condition_pushdown_from_having,not_null_range_scan,hash_join_cardinality,default +ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,condition_pushdown_from_having,not_null_range_scan,hash_join_cardinality,cset_narrowing,default READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_TRACE diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index c667920edff..557fd5eb506 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -90,7 +90,9 @@ ENDIF() SET (SQL_SOURCE ${CMAKE_CURRENT_BINARY_DIR}/yy_mariadb.cc ${CMAKE_CURRENT_BINARY_DIR}/yy_oracle.cc - ../sql-common/client.c compat56.cc derror.cc des_key_file.cc + ../sql-common/client.c + cset_narrowing.cc + compat56.cc derror.cc des_key_file.cc discover.cc ../sql-common/errmsg.c field.cc field_conv.cc field_comp.cc filesort_utils.cc diff --git a/sql/cset_narrowing.cc b/sql/cset_narrowing.cc new file mode 100644 index 00000000000..abdaec16416 --- /dev/null +++ b/sql/cset_narrowing.cc @@ -0,0 +1,35 @@ +/* + Copyright (c) 2023, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifdef USE_PRAGMA_IMPLEMENTATION +#pragma implementation // gcc: Class implementation +#endif + +#include "mariadb.h" +#include "sql_priv.h" +#include "sql_select.h" + +Charset_utf8narrow utf8mb3_from_mb4; + +bool Utf8_narrow::should_do_narrowing(const THD *thd, + CHARSET_INFO *field_cset, + CHARSET_INFO *value_cset) +{ + return optimizer_flag(thd, OPTIMIZER_SWITCH_CSET_NARROWING) && + field_cset == &my_charset_utf8mb3_general_ci && + value_cset == &my_charset_utf8mb4_general_ci; +} + diff --git a/sql/cset_narrowing.h b/sql/cset_narrowing.h new file mode 100644 index 00000000000..bb0a3960b8e --- /dev/null +++ b/sql/cset_narrowing.h @@ -0,0 +1,143 @@ +/* + Copyright (c) 2023, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#ifndef CSET_NARROWING_H_INCLUDED +#define CSET_NARROWING_H_INCLUDED + +/* + A singleton class to provide "utf8mb3_from_mb4.charset()". + + This is a variant of utf8mb3_general_ci that one can use when they have data + in MB4 and want to make index lookup keys in MB3. +*/ +extern +class Charset_utf8narrow +{ + struct my_charset_handler_st cset_handler; + struct charset_info_st cset; +public: + Charset_utf8narrow() : + cset_handler(*my_charset_utf8mb3_general_ci.cset), + cset(my_charset_utf8mb3_general_ci) /* Copy the CHARSET_INFO structure */ + { + /* Insert our function wc_mb */ + cset_handler.wc_mb= my_wc_mb_utf8mb4_bmp_only; + cset.cset=&cset_handler; + + /* Charsets are compared by their name, so assign a different name */ + LEX_CSTRING tmp= {STRING_WITH_LEN("utf8_mb4_to_mb3")}; + cset.cs_name= tmp; + } + + CHARSET_INFO *charset() { return &cset; } + +} utf8mb3_from_mb4; + + +/* + A class to temporary change a field that uses utf8mb3_general_ci to enable + correct lookup key construction from string value in utf8mb4_general_ci + + Intended usage: + + // can do this in advance: + bool do_narrowing= Utf8_narrow::should_do_narrowing(field, value_cset); + ... + + // This sets the field to do narrowing if necessary: + Utf8_narrow narrow(field, do_narrowing); + + // write to 'field' here + // item->save_in_field(field) or something else + + // Stop doing narrowing + narrow.stop(); +*/ + +class Utf8_narrow +{ + Field *field; + DTCollation save_collation; + +public: + static bool should_do_narrowing(const THD *thd, CHARSET_INFO *field_cset, + CHARSET_INFO *value_cset); + + static bool should_do_narrowing(const Field *field, CHARSET_INFO *value_cset) + { + CHARSET_INFO *field_cset= field->charset(); + THD *thd= field->table->in_use; + return should_do_narrowing(thd, field_cset, value_cset); + } + + Utf8_narrow(Field *field_arg, bool is_applicable) + { + field= NULL; + if (is_applicable) + { + DTCollation mb3_from_mb4= utf8mb3_from_mb4.charset(); + field= field_arg; + save_collation= field->dtcollation(); + field->change_charset(mb3_from_mb4); + } + } + + void stop() + { + if (field) + field->change_charset(save_collation); +#ifndef NDEBUG + field= NULL; +#endif + } + + ~Utf8_narrow() + { + DBUG_ASSERT(!field); + } +}; + + +/* + @brief + Check if two fields can participate in a multiple equality using charset + narrowing. + + @detail + Normally, check_simple_equality() checks this by calling: + + left_field->eq_def(right_field) + + This function does the same but takes into account we might use charset + narrowing: + - collations are not the same but rather an utf8mb{3,4}_general_ci pair + - for field lengths, should compare # characters, not #bytes. +*/ + +inline +bool fields_equal_using_narrowing(const THD *thd, const Field *left, const Field *right) +{ + return + dynamic_cast(left) && + dynamic_cast(right) && + left->real_type() == right->real_type() && + (Utf8_narrow::should_do_narrowing(left, right->charset()) || + Utf8_narrow::should_do_narrowing(right, left->charset())) && + left->char_length() == right->char_length(); +}; + + +#endif /* CSET_NARROWING_H_INCLUDED */ diff --git a/sql/field.cc b/sql/field.cc index b52f481170e..44445e08d5d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7508,7 +7508,8 @@ Field_longstr::cmp_to_string_with_stricter_collation(const Item_bool_func *cond, return !cmp_is_done_using_type_handler_of_this(cond, item) ? Data_type_compatibility::INCOMPATIBLE_DATA_TYPE : (charset() != cond->compare_collation() && - !(cond->compare_collation()->state & MY_CS_BINSORT)) ? + !(cond->compare_collation()->state & MY_CS_BINSORT) && + !Utf8_narrow::should_do_narrowing(this, cond->compare_collation())) ? Data_type_compatibility::INCOMPATIBLE_COLLATION : Data_type_compatibility::OK; } @@ -7519,6 +7520,18 @@ Field_longstr::can_optimize_keypart_ref(const Item_bool_func *cond, const Item *item) const { DBUG_ASSERT(cmp_type() == STRING_RESULT); + /* + So, we have an equality: tbl.string_key = 'abc' + + The comparison is the string comparison. Can we use index lookups to + find matching rows? We can do that when: + - The comparison uses the same collation as tbl.string_key + - the comparison uses binary collation, while tbl.string_key + uses some other collation. + In this case, we will find matches in some collation. For example, for + 'abc' we may find 'abc', 'ABC', and 'äbc'. + But we're certain that will find the row with the identical binary, 'abc'. + */ return cmp_to_string_with_stricter_collation(cond, item); } diff --git a/sql/item.cc b/sql/item.cc index 1e03614ebf9..f810d7e88ce 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2522,7 +2522,8 @@ bool DTCollation::aggregate(const DTCollation &dt, uint flags) /******************************/ static -void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) +void my_coll_agg_error(const DTCollation &c1, const DTCollation &c2, + const char *fname) { my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), c1.collation->coll_name.str, c1.derivation_name(), @@ -2605,10 +2606,17 @@ bool Type_std_attributes::agg_item_collations(DTCollation &c, } +/* + @param single_err When nargs==1, use *single_err as the second aggregated + collation when producing error message. +*/ + bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll, const LEX_CSTRING &fname, Item **args, uint nargs, - uint flags, int item_sep) + uint flags, int item_sep, + const Single_coll_err + *single_err) { THD *thd= current_thd; if (thd->lex->is_ps_or_view_context_analysis()) @@ -2646,7 +2654,19 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll, args[0]= safe_args[0]; args[item_sep]= safe_args[1]; } - my_coll_agg_error(args, nargs, fname.str, item_sep); + if (nargs == 1 && single_err) + { + /* + Use *single_err to produce an error message mentioning two + collations. + */ + if (single_err->first) + my_coll_agg_error(args[0]->collation, single_err->coll, fname.str); + else + my_coll_agg_error(single_err->coll, args[0]->collation, fname.str); + } + else + my_coll_agg_error(args, nargs, fname.str, item_sep); return TRUE; } diff --git a/sql/item.h b/sql/item.h index 3be7cd7283a..3c6ebfb7d56 100644 --- a/sql/item.h +++ b/sql/item.h @@ -30,6 +30,8 @@ #include "sql_time.h" #include "mem_root_array.h" +#include "cset_narrowing.h" + C_MODE_START #include @@ -5399,8 +5401,10 @@ protected: public: // This method is used by Arg_comparator - bool agg_arg_charsets_for_comparison(CHARSET_INFO **cs, Item **a, Item **b) + bool agg_arg_charsets_for_comparison(CHARSET_INFO **cs, Item **a, Item **b, + bool allow_narrowing) { + THD *thd= current_thd; DTCollation tmp; if (tmp.set((*a)->collation, (*b)->collation, MY_COLL_CMP_CONV) || tmp.derivation == DERIVATION_NONE) @@ -5413,11 +5417,40 @@ public: func_name()); return true; } + + if (allow_narrowing && + (*a)->collation.derivation == (*b)->collation.derivation) + { + // allow_narrowing==true only for = and <=> comparisons. + if (Utf8_narrow::should_do_narrowing(thd, (*a)->collation.collation, + (*b)->collation.collation)) + { + // a is a subset, b is a superset (e.g. utf8mb3 vs utf8mb4) + *cs= (*b)->collation.collation; // Compare using the wider cset + return false; + } + else + if (Utf8_narrow::should_do_narrowing(thd, (*b)->collation.collation, + (*a)->collation.collation)) + { + // a is a superset, b is a subset (e.g. utf8mb4 vs utf8mb3) + *cs= (*a)->collation.collation; // Compare using the wider cset + return false; + } + } + /* + If necessary, convert both *a and *b to the collation in tmp: + */ + Single_coll_err error_for_a= {(*b)->collation, true}; + Single_coll_err error_for_b= {(*a)->collation, false}; + if (agg_item_set_converter(tmp, func_name_cstring(), - a, 1, MY_COLL_CMP_CONV, 1) || + a, 1, MY_COLL_CMP_CONV, 1, + /*just for error message*/ &error_for_a) || agg_item_set_converter(tmp, func_name_cstring(), - b, 1, MY_COLL_CMP_CONV, 1)) - return true; + b, 1, MY_COLL_CMP_CONV, 1, + /*just for error message*/ &error_for_b)) + return true; *cs= tmp.collation; return false; } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 0ea012f82b2..ed6417a4747 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -463,10 +463,24 @@ bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp) if (args[0]->cmp_type() == STRING_RESULT && args[1]->cmp_type() == STRING_RESULT) { - DTCollation tmp; - if (agg_arg_charsets_for_comparison(tmp, args, 2)) + CHARSET_INFO *tmp; + /* + Use charset narrowing only for equalities, as that would allow + to construct ref access. + Non-equality comparisons with constants work without charset narrowing, + the constant gets converted. + Non-equality comparisons with non-constants would need narrowing to + enable range optimizer to handle e.g. + t1.mb3key_col <= const_table.mb4_col + But this doesn't look important. + */ + bool allow_narrowing= MY_TEST(functype()==Item_func::EQ_FUNC || + functype()==Item_func::EQUAL_FUNC); + + if (agg_arg_charsets_for_comparison(&tmp, &args[0], &args[1], + allow_narrowing)) return true; - cmp->m_compare_collation= tmp.collation; + cmp->m_compare_collation= tmp; } // Convert constants when compared to int/year field DBUG_ASSERT(functype() != LIKE_FUNC); @@ -589,9 +603,19 @@ bool Arg_comparator::set_cmp_func_string(THD *thd) { /* We must set cmp_collation here as we may be called from for an automatic - generated item, like in natural join + generated item, like in natural join. + Allow reinterpted superset as subset. */ - if (owner->agg_arg_charsets_for_comparison(&m_compare_collation, a, b)) + bool allow_narrowing= false; + if (owner->type() == Item::FUNC_ITEM) + { + Item_func::Functype ftype= ((Item_func*)owner)->functype(); + if (ftype == Item_func::EQUAL_FUNC || ftype==Item_func::EQ_FUNC) + allow_narrowing= true; + } + + if (owner->agg_arg_charsets_for_comparison(&m_compare_collation, a, b, + allow_narrowing)) return true; if ((*a)->type() == Item::FUNC_ITEM && diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 09b19944bb5..1180b2acda2 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -8998,11 +8998,28 @@ SEL_ARG *Field_str::get_mm_leaf(RANGE_OPT_PARAM *prm, KEY_PART *key_part, const Item_bool_func *cond, scalar_comparison_op op, Item *value) { + int err; DBUG_ENTER("Field_str::get_mm_leaf"); if (can_optimize_scalar_range(prm, key_part, cond, op, value) != Data_type_compatibility::OK) DBUG_RETURN(0); - int err= value->save_in_field_no_warnings(this, 1); + + { + /* + Do CharsetNarrowing if necessary + This means that we are temporary changing the character set of the + current key field to make key lookups possible. + This is needed when comparing an utf8mb3 key field with an utf8mb4 value. + See cset_narrowing.h for more details. + */ + bool do_narrowing= + Utf8_narrow::should_do_narrowing(this, value->collation.collation); + Utf8_narrow narrow(this, do_narrowing); + + err= value->save_in_field_no_warnings(this, 1); + narrow.stop(); + } + if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) DBUG_RETURN(&null_element); if (err > 0) diff --git a/sql/sql_priv.h b/sql/sql_priv.h index 549f279e95a..a1adcb58079 100644 --- a/sql/sql_priv.h +++ b/sql/sql_priv.h @@ -235,6 +235,7 @@ #define OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING (1ULL << 34) #define OPTIMIZER_SWITCH_NOT_NULL_RANGE_SCAN (1ULL << 35) #define OPTIMIZER_SWITCH_HASH_JOIN_CARDINALITY (1ULL << 36) +#define OPTIMIZER_SWITCH_CSET_NARROWING (1ULL << 37) #define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \ OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 52eee901243..9f2e65cb59f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15702,7 +15702,8 @@ bool check_simple_equality(THD *thd, const Item::Context &ctx, Field *left_field= ((Item_field*) left_item)->field; Field *right_field= ((Item_field*) right_item)->field; - if (!left_field->eq_def(right_field)) + if (!left_field->eq_def(right_field) && + !fields_equal_using_narrowing(thd, left_field, right_field)) return FALSE; /* Search for multiple equalities containing field1 and/or field2 */ diff --git a/sql/sql_select.h b/sql/sql_select.h index f8358a12708..02a6a846bc4 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -34,6 +34,8 @@ #include "opt_range.h" /* SQL_SELECT, QUICK_SELECT_I */ #include "filesort.h" +#include "cset_narrowing.h" + typedef struct st_join_table JOIN_TAB; /* Values in optimize */ #define KEY_OPTIMIZE_EXISTS 1U @@ -1921,7 +1923,14 @@ public: { enum_check_fields org_count_cuted_fields= thd->count_cuted_fields; Use_relaxed_field_copy urfc(to_field->table->in_use); + + /* If needed, perform CharsetNarrowing for making ref access lookup keys. */ + Utf8_narrow do_narrow(to_field, do_cset_narrowing); + store_key_result result= copy_inner(); + + do_narrow.stop(); + thd->count_cuted_fields= org_count_cuted_fields; return result; } @@ -1931,6 +1940,12 @@ public: uchar *null_ptr; uchar err; + /* + This is set to true if we need to do Charset Narrowing when making a lookup + key. + */ + bool do_cset_narrowing= false; + virtual enum store_key_result copy_inner()=0; }; @@ -1950,6 +1965,7 @@ class store_key_field: public store_key if (to_field) { copy_field.set(to_field,from_field,0); + setup_charset_narrowing(); } } @@ -1960,6 +1976,15 @@ class store_key_field: public store_key { copy_field.set(to_field, fld_item->field, 0); field_name= fld_item->full_name(); + setup_charset_narrowing(); + } + + /* Setup CharsetNarrowing if necessary */ + void setup_charset_narrowing() + { + do_cset_narrowing= + Utf8_narrow::should_do_narrowing(copy_field.to_field, + copy_field.from_field->charset()); } protected: @@ -2000,7 +2025,12 @@ public: :store_key(thd, to_field_arg, ptr, null_ptr_arg ? null_ptr_arg : item_arg->maybe_null() ? &err : (uchar*) 0, length), item(item_arg), use_value(val) - {} + { + /* Setup CharsetNarrowing to be done if necessary */ + do_cset_narrowing= + Utf8_narrow::should_do_narrowing(to_field, + item->collation.collation); + } store_key_item(store_key &arg, Item *new_item, bool val) :store_key(arg), item(new_item), use_value(val) {} @@ -2388,7 +2418,7 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field, extern bool test_if_ref(Item *, Item_field *left_item,Item *right_item); -inline bool optimizer_flag(THD *thd, ulonglong flag) +inline bool optimizer_flag(const THD *thd, ulonglong flag) { return (thd->variables.optimizer_switch & flag); } diff --git a/sql/sql_type.h b/sql/sql_type.h index e7f02eb6b13..9992c8bf0bd 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -3268,10 +3268,16 @@ public: bool agg_item_collations(DTCollation &c, const LEX_CSTRING &name, Item **items, uint nitems, uint flags, int item_sep); + struct Single_coll_err + { + const DTCollation& coll; + bool first; + }; bool agg_item_set_converter(const DTCollation &coll, const LEX_CSTRING &name, Item **args, uint nargs, - uint flags, int item_sep); + uint flags, int item_sep, + const Single_coll_err *single_item_err= NULL); /* Collect arguments' character sets together. diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index aea757fdb3e..7550084456b 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2767,6 +2767,7 @@ export const char *optimizer_switch_names[]= "condition_pushdown_from_having", "not_null_range_scan", "hash_join_cardinality", + "cset_narrowing", "default", NullS }; diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 68e37e699ad..2f8fe534468 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -7973,4 +7973,16 @@ struct charset_info_st my_charset_utf8mb4_nopad_bin= &my_collation_utf8mb4_nopad_bin_handler }; +/* + Take a my_wc_t character and convert it to utf8mb3 representation. + Characters that are not in Basic Multilingual Plane are replaced with + MY_CS_REPLACEMENT_CHARACTER. +*/ +int my_wc_mb_utf8mb4_bmp_only(CHARSET_INFO *cs, my_wc_t wc, uchar *r, uchar *e) +{ + if (wc > 0xFFFF) + wc= MY_CS_REPLACEMENT_CHARACTER; + return my_wc_mb_utf8mb4(cs, wc, r, e); +} + #endif /* HAVE_CHARSET_utf8mb4 */ From 4f5346579a6ac8d13cddf3b2057edd8c4c420bcc Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 13 Sep 2023 22:35:01 +1000 Subject: [PATCH 086/158] MDEV-16641: mysql_client_test now stable 10.6+ already unmasked. Tested on 10.4 and 10.5 and passes on all 3 tests now occur with particular attention to the causing MDEVs: - MDEV-19511 Big endian issue in libmariadb - has been resolved; - CONC-208 Client tests (main.mysql_client_test, main.mysql_client_test_nonblock, main.mysql_client_test_comp) fail in buildbot on Power - observed passing in 10.5 - MDEV-19369 main.mysql_client_test, main.mysql_client_test_comp failed on ASAN build with error: 5888, status: 23, errno: 2 - passing on ASAN builder --- mysql-test/unstable-tests | 3 --- 1 file changed, 3 deletions(-) diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests index a76912f4c78..5ae6922a42a 100644 --- a/mysql-test/unstable-tests +++ b/mysql-test/unstable-tests @@ -101,9 +101,6 @@ main.mdev375 : MDEV-10607 - sporadic "can't connect" main.merge : MDEV-10607 - sporadic "can't connect" main.myisam : Modified in 10.4.18 main.mysql : MDEV-20156 - Wrong result -main.mysql_client_test : MDEV-19369 - error: 5888, status: 23, errno: 2; MDEV-19511 - Big endian issue -main.mysql_client_test_comp : MDEV-16641 - Error in exec -main.mysql_client_test_nonblock : CONC-208 - Error on Power; MDEV-15096 - exec failed main.mysql_cp932 : MDEV-21275 - Wrong result main.mysql_upgrade : MDEV-20161 - Wrong result; MDEV-20166 - FATAL ERROR: Upgrade failed; modified in 10.4.18 main.mysql_upgrade-6984 : MDEV-22514 - Wrong result From 057fd528766eba150b9d7a0de8f95a4094f0e460 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 20 Oct 2023 10:28:34 +1100 Subject: [PATCH 087/158] MDEV-32515 Use $MYSQLD_LAST_CMD in spider/bugfix.mdev_30370 $MYSQLD_CMD uses .1 as the defaults-group-suffix, which could cause the use of the default port (3306) or socket, which will fail in environment where these defaults are already in use by another server. Adding an extra --defaults-group-suffix=.1.1 does not help, because the first flag wins. So we use $MYSQLD_LAST_CMD instead, which uses the correct suffix. The extra innodb buffer pool warning is irrelevant to the goal of the test (running --wsrep-recover with --plug-load-add=ha_spider should not cause hang) --- storage/spider/mysql-test/spider/bugfix/r/mdev_30370.result | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_30370.test | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_30370.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_30370.result index 1ffbf2e6b01..7a0b6a2094a 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_30370.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_30370.result @@ -1,6 +1,7 @@ # # MDEV-30370 mariadbd hangs when running with --wsrep-recover and --plugin-load-add=ha_spider.so # +call mtr.add_suppression(".*\\[Warning\\] InnoDB: Skipping buffer pool dump/restore during wsrep recovery"); # Kill the server # restart Warnings: diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_30370.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_30370.test index 721a0996d96..73376d27b81 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_30370.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_30370.test @@ -3,10 +3,9 @@ --echo # MDEV-30370 mariadbd hangs when running with --wsrep-recover and --plugin-load-add=ha_spider.so --echo # -let $MYSQLD_DATADIR= `select @@datadir`; -let $PLUGIN_DIR=`select @@plugin_dir`; +call mtr.add_suppression(".*\\[Warning\\] InnoDB: Skipping buffer pool dump/restore during wsrep recovery"); --source include/kill_mysqld.inc ---exec $MYSQLD_CMD --datadir=$MYSQLD_DATADIR --wsrep-recover --plugin-dir=$PLUGIN_DIR --plugin-load-add=ha_spider +--exec $MYSQLD_LAST_CMD --wsrep-recover --plugin-load-add=ha_spider --source include/start_mysqld.inc --disable_query_log --source ../../include/clean_up_spider.inc From 1182451af1081cb4c08459669255bd9bc66544c4 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sat, 26 Aug 2023 13:32:47 +1000 Subject: [PATCH 088/158] MDEV-32018 Allow the setting of Auto_increment on FK referenced columns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In MDEV-31086, SET FOREIGN_KEY_CHECKS=0 cannot bypass checks that make column types of foreign keys incompatible. An unfortunate consequence is that adding an AUTO_INCREMENT is considered incompatible in Field_{num,decimal}::is_equal and for the purpose of FK checks this isn't relevant. innodb.foreign_key - pragmaticly left wait_until_count_sessions.inc at end of test to match the second line of test. Reporter: horrockss@github - https://github.com/MariaDB/mariadb-docker/issues/528 Co-Author: Marko Mäkelä Reviewer: Nikita Malyavin For the future reader this was attempted: Removing AUTO_INCREMENT checks from Field_{num,decimal}::is_equals failed in the following locations (noted for future fixing): * MyISAM and Aria (not InnoDB) don't adjust AUTO_INCREMENT next number correctly, hence added a test to main.auto_increment to catch the next person that attempts this fix. * InnoDB must perform an ALGORITHM=COPY to populate NULL values of an original table (MDEV-19190 mtr test period.copy), this requires ALTER_STORED_COLUMN_TYPE to be set in fill_alter_inplace_info which doesn't get hit because field->is_equal is true. * InnoDB must not perform the change inplace (below patch) * innodb.innodb-alter-timestamp main.partition_innodb test would also need futher investigation. InnoDB ha_innobase::check_if_supported_inplace_alter to support the removal of Field_{num,decimal}::is_equal AUTO_INCREMENT checks would need the following change diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index a5ccb1957f3..9d778e2d39a 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -2455,10 +2455,15 @@ ha_innobase::check_if_supported_inplace_alter( /* An AUTO_INCREMENT attribute can only be added to an existing column by ALGORITHM=COPY, but we can remove the attribute. */ - ut_ad((MTYP_TYPENR((*af)->unireg_check) - != Field::NEXT_NUMBER) - || (MTYP_TYPENR(f->unireg_check) - == Field::NEXT_NUMBER)); + if ((MTYP_TYPENR((*af)->unireg_check) + == Field::NEXT_NUMBER) + && (MTYP_TYPENR(f->unireg_check) + != Field::NEXT_NUMBER)) + { + ha_alter_info->unsupported_reason = my_get_err_msg( + ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_AUTOINC); + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } With this change the main.auto_increment test for bug #14573, under innodb, will pass without the 2 --error ER_DUP_ENTRY entries. The function header comment was updated to reflect the MDEV-31086 changes. --- mysql-test/suite/innodb/r/foreign_key.result | 15 +++++++++++++ mysql-test/suite/innodb/t/foreign_key.test | 22 +++++++++++++++++++- sql/sql_table.cc | 16 +++++++++++--- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index 68a54344519..f87aeb56b77 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -892,4 +892,19 @@ DROP INDEX fx ON t1; INSERT INTO t1 VALUES (2,11,11); DROP TABLE t1; SET FOREIGN_KEY_CHECKS=DEFAULT; +# +# MDEV-32018 Allow the setting of Auto_increment on FK referenced columns +# +CREATE TABLE t1 ( +id int unsigned NOT NULL PRIMARY KEY +); +CREATE TABLE t2 ( +id int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, +t1_id int unsigned DEFAULT NULL, +CONSTRAINT FK_t1_id FOREIGN KEY (t1_id) REFERENCES t1 (id) +); +ALTER TABLE t1 MODIFY id INT unsigned AUTO_INCREMENT; +DROP TABLE t1,t2; +# # End of 10.4 tests +# diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index c4b2b8331b0..032bab2408d 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -935,6 +935,26 @@ INSERT INTO t1 VALUES (2,11,11); DROP TABLE t1; SET FOREIGN_KEY_CHECKS=DEFAULT; --- echo # End of 10.4 tests +--echo # +--echo # MDEV-32018 Allow the setting of Auto_increment on FK referenced columns +--echo # + +CREATE TABLE t1 ( + id int unsigned NOT NULL PRIMARY KEY +); + +CREATE TABLE t2 ( + id int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, + t1_id int unsigned DEFAULT NULL, + CONSTRAINT FK_t1_id FOREIGN KEY (t1_id) REFERENCES t1 (id) +); + +ALTER TABLE t1 MODIFY id INT unsigned AUTO_INCREMENT; + +DROP TABLE t1,t2; + +--echo # +--echo # End of 10.4 tests +--echo # --source include/wait_until_count_sessions.inc diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 987c66e8aeb..6ffdea3b8cd 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -9135,8 +9135,7 @@ enum fk_column_change_type @retval FK_COLUMN_NO_CHANGE No significant changes are to be done on foreign key columns. @retval FK_COLUMN_DATA_CHANGE ALTER TABLE might result in value - change in foreign key column (and - foreign_key_checks is on). + change in foreign key column. @retval FK_COLUMN_RENAMED Foreign key column is renamed. @retval FK_COLUMN_DROPPED Foreign key column is dropped. */ @@ -9172,7 +9171,18 @@ fk_check_column_changes(THD *thd, Alter_info *alter_info, return FK_COLUMN_RENAMED; } - if ((old_field->is_equal(*new_field) == IS_EQUAL_NO) || + /* + Field_{num|decimal}::is_equal evaluates to IS_EQUAL_NO where + the new_field adds an AUTO_INCREMENT flag on a column due to a + limitation in MyISAM/ARIA. For the purposes of FK determination + it doesn't matter if AUTO_INCREMENT is there or not. + */ + const uint flags= new_field->flags; + new_field->flags&= ~AUTO_INCREMENT_FLAG; + const bool equal_result= old_field->is_equal(*new_field); + new_field->flags= flags; + + if ((equal_result == IS_EQUAL_NO) || ((new_field->flags & NOT_NULL_FLAG) && !(old_field->flags & NOT_NULL_FLAG))) { From 186ac474ddb4de64f5617f98510694b7ea4ec9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 20 Oct 2023 11:34:47 +0300 Subject: [PATCH 089/158] MDEV-32324 fixup: clang -Winconsistent-missing-override --- sql/item_subselect.h | 129 ++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 2bdd2252dc3..ac4df72c226 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -892,26 +892,26 @@ public: subselect_single_select_engine(st_select_lex *select, select_result_interceptor *result, Item_subselect *item); - void cleanup(); - int prepare(THD *thd); - bool fix_length_and_dec(Item_cache** row); - int exec(); - uint cols() const; - uint8 uncacheable(); - void exclude(); - table_map upper_select_const_tables(); - void print (String *str, enum_query_type query_type); + void cleanup() override; + int prepare(THD *thd) override; + bool fix_length_and_dec(Item_cache** row) override; + int exec() override; + uint cols() const override; + uint8 uncacheable() override; + void exclude() override; + table_map upper_select_const_tables() override; + void print(String *str, enum_query_type query_type) override; bool change_result(Item_subselect *si, select_result_interceptor *result, - bool temp); + bool temp) override; bool no_tables() const override; bool always_returns_one_row() const override; - bool may_be_null(); - bool is_executed() const { return executed; } - bool no_rows(); - virtual enum_engine_type engine_type() { return SINGLE_SELECT_ENGINE; } - int get_identifier(); - void force_reexecution(); + bool may_be_null() override; + bool is_executed() const override { return executed; } + bool no_rows() override; + enum_engine_type engine_type() override { return SINGLE_SELECT_ENGINE; } + int get_identifier() override; + void force_reexecution() override; void change_select(st_select_lex *new_select) { select_lex= new_select; } friend class subselect_hash_sj_engine; @@ -930,23 +930,23 @@ public: subselect_union_engine(st_select_lex_unit *u, select_result_interceptor *result, Item_subselect *item); - void cleanup(); - int prepare(THD *); - bool fix_length_and_dec(Item_cache** row); - int exec(); - uint cols() const; - uint8 uncacheable(); - void exclude(); - table_map upper_select_const_tables(); - void print (String *str, enum_query_type query_type); + void cleanup() override; + int prepare(THD *) override; + bool fix_length_and_dec(Item_cache** row) override; + int exec() override; + uint cols() const override; + uint8 uncacheable() override; + void exclude() override; + table_map upper_select_const_tables() override; + void print(String *str, enum_query_type query_type) override; bool change_result(Item_subselect *si, select_result_interceptor *result, - bool temp= FALSE); + bool temp= FALSE) override; bool no_tables() const override; - bool is_executed() const; - void force_reexecution(); - bool no_rows(); - virtual enum_engine_type engine_type() { return UNION_ENGINE; } + bool is_executed() const override; + void force_reexecution() override; + bool no_rows() override; + enum_engine_type engine_type() override { return UNION_ENGINE; } }; @@ -988,24 +988,24 @@ public: :subselect_engine(subs, 0), tab(tab_arg), cond(where) {} ~subselect_uniquesubquery_engine(); - void cleanup(); - int prepare(THD *); - bool fix_length_and_dec(Item_cache** row); - int exec(); - uint cols() const { return 1; } - uint8 uncacheable() { return UNCACHEABLE_DEPENDENT_INJECTED; } - void exclude(); - table_map upper_select_const_tables() { return 0; } - void print (String *str, enum_query_type query_type); + void cleanup() override; + int prepare(THD *) override; + bool fix_length_and_dec(Item_cache** row) override; + int exec() override; + uint cols() const override { return 1; } + uint8 uncacheable() override { return UNCACHEABLE_DEPENDENT_INJECTED; } + void exclude() override; + table_map upper_select_const_tables() override { return 0; } + void print(String *str, enum_query_type query_type) override; bool change_result(Item_subselect *si, select_result_interceptor *result, - bool temp= FALSE); + bool temp= FALSE) override; bool no_tables() const override; int index_lookup(); /* TIMOUR: this method needs refactoring. */ int scan_table(); bool copy_ref_key(bool skip_constants); - bool no_rows() { return empty_result_set; } - virtual enum_engine_type engine_type() { return UNIQUESUBQUERY_ENGINE; } + bool no_rows() override { return empty_result_set; } + enum_engine_type engine_type() override { return UNIQUESUBQUERY_ENGINE; } }; @@ -1126,25 +1126,25 @@ public: ~subselect_hash_sj_engine(); bool init(List *tmp_columns, uint subquery_id); - void cleanup(); - int prepare(THD *); - int exec(); - void print(String *str, enum_query_type query_type); - uint cols() const { return materialize_engine->cols(); } - uint8 uncacheable() { return materialize_engine->uncacheable(); } - table_map upper_select_const_tables() { return 0; } - bool no_rows() { return !tmp_table->file->stats.records; } - virtual enum_engine_type engine_type() { return HASH_SJ_ENGINE; } + void cleanup() override; + int prepare(THD *) override; + int exec() override; + void print(String *str, enum_query_type query_type) override; + uint cols() const override { return materialize_engine->cols(); } + uint8 uncacheable() override { return materialize_engine->uncacheable(); } + table_map upper_select_const_tables() override { return 0; } + bool no_rows() override { return !tmp_table->file->stats.records; } + enum_engine_type engine_type() override { return HASH_SJ_ENGINE; } /* TODO: factor out all these methods in a base subselect_index_engine class because all of them have dummy implementations and should never be called. */ - bool fix_length_and_dec(Item_cache** row);//=>base class - void exclude(); //=>base class + bool fix_length_and_dec(Item_cache** row) override;//=>base class + void exclude() override; //=>base class //=>base class bool change_result(Item_subselect *si, select_result_interceptor *result, - bool temp= FALSE); + bool temp= FALSE) override; bool no_tables() const override;//=>base class protected: @@ -1410,19 +1410,20 @@ public: bool has_covering_null_row_arg, bool has_covering_null_columns_arg, uint count_columns_with_nulls_arg); - int prepare(THD *thd_arg) { set_thd(thd_arg); return 0; } - int exec(); - bool fix_length_and_dec(Item_cache**) { return FALSE; } - uint cols() const { /* TODO: what is the correct value? */ return 1; } - uint8 uncacheable() { return UNCACHEABLE_DEPENDENT; } - void exclude() {} - table_map upper_select_const_tables() { return 0; } + int prepare(THD *thd_arg) override { set_thd(thd_arg); return 0; } + int exec() override; + bool fix_length_and_dec(Item_cache**) override { return FALSE; } + uint cols() const override + { /* TODO: what is the correct value? */ return 1; } + uint8 uncacheable() override { return UNCACHEABLE_DEPENDENT; } + void exclude() override {} + table_map upper_select_const_tables() override { return 0; } bool change_result(Item_subselect*, select_result_interceptor*, - bool temp= FALSE) + bool temp= FALSE) override { DBUG_ASSERT(FALSE); return false; } bool no_tables() const override { return false; } - bool no_rows() + bool no_rows() override { /* TODO: It is completely unclear what is the semantics of this @@ -1432,7 +1433,7 @@ public: */ return !(((Item_in_subselect *) item)->null_value); } - void print(String*, enum_query_type); + void print(String*, enum_query_type) override; friend void subselect_hash_sj_engine::cleanup(); }; From 7d89dcf1ae6683b3b0dc28cbc7d54a47ef7137e9 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 20 Oct 2023 13:17:40 +0530 Subject: [PATCH 090/158] MDEV-32527 Server aborts during alter operation when table doesn't have foreign index Problem: ======== InnoDB fails to find the foreign key index for the foreign key relation in the table while iterating the foreign key constraints during alter operation. This is caused by commit 5f09b53bdb4e973e7c7ec2c53a24c98321223f98 (MDEV-31086). Fix: ==== In check_col_is_in_fk_indexes(), while iterating through the foreign key relationship, InnoDB should consider that foreign key relation may not have foreign index when foreign key check is disabled. --- mysql-test/suite/innodb/r/fk_col_alter.result | 13 ++++++++++ mysql-test/suite/innodb/t/fk_col_alter.test | 14 +++++++++++ storage/innobase/handler/handler0alter.cc | 24 ++++++++----------- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/mysql-test/suite/innodb/r/fk_col_alter.result b/mysql-test/suite/innodb/r/fk_col_alter.result index 21a8f5da334..d58f68977ef 100644 --- a/mysql-test/suite/innodb/r/fk_col_alter.result +++ b/mysql-test/suite/innodb/r/fk_col_alter.result @@ -105,4 +105,17 @@ ALTER TABLE t MODIFY f VARCHAR(8); ALTER TABLE t MODIFY vf VARCHAR(18); ERROR HY000: This is not yet supported for generated columns DROP TABLE t; +# +# MDEV-32527 Server aborts during alter operation +# when table doesn't have foreign index +# +CREATE TABLE t1 (f1 INT NOT NULL, INDEX(f1)) ENGINE=InnoDB; +CREATE TABLE t2(f1 INT NOT NULL, f2 VARCHAR(100) DEFAULT NULL, +INDEX idx(f1, f2), +FOREIGN KEY(f1) REFERENCES t1(f1))ENGINE=INNODB; +SET SESSION FOREIGN_KEY_CHECKS = OFF; +ALTER TABLE t2 DROP INDEX idx; +ALTER TABLE t2 MODIFY f2 VARCHAR(1023); +SET SESSION FOREIGN_KEY_CHECKS = ON; +DROP TABLE t2, t1; # End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/fk_col_alter.test b/mysql-test/suite/innodb/t/fk_col_alter.test index afcea6093b4..6788c825b0f 100644 --- a/mysql-test/suite/innodb/t/fk_col_alter.test +++ b/mysql-test/suite/innodb/t/fk_col_alter.test @@ -139,4 +139,18 @@ ALTER TABLE t MODIFY f VARCHAR(8); --error ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN ALTER TABLE t MODIFY vf VARCHAR(18); DROP TABLE t; + +--echo # +--echo # MDEV-32527 Server aborts during alter operation +--echo # when table doesn't have foreign index +--echo # +CREATE TABLE t1 (f1 INT NOT NULL, INDEX(f1)) ENGINE=InnoDB; +CREATE TABLE t2(f1 INT NOT NULL, f2 VARCHAR(100) DEFAULT NULL, + INDEX idx(f1, f2), + FOREIGN KEY(f1) REFERENCES t1(f1))ENGINE=INNODB; +SET SESSION FOREIGN_KEY_CHECKS = OFF; +ALTER TABLE t2 DROP INDEX idx; +ALTER TABLE t2 MODIFY f2 VARCHAR(1023); +SET SESSION FOREIGN_KEY_CHECKS = ON; +DROP TABLE t2, t1; --echo # End of 10.4 tests diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index eb484281bf2..d3196c47ca2 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -7680,20 +7680,17 @@ bool check_col_is_in_fk_indexes( { char *fk_id= nullptr; - for (dict_foreign_set::iterator it= table->foreign_set.begin(); - it!= table->foreign_set.end();) + for (const auto &f : table->foreign_set) { - if (std::find(drop_fk.begin(), drop_fk.end(), (*it)) - != drop_fk.end()) - goto next_item; - for (ulint i= 0; i < (*it)->n_fields; i++) - if ((*it)->foreign_index->fields[i].col == col) + if (!f->foreign_index || + std::find(drop_fk.begin(), drop_fk.end(), f) != drop_fk.end()) + continue; + for (ulint i= 0; i < f->n_fields; i++) + if (f->foreign_index->fields[i].col == col) { - fk_id= (*it)->id; - goto err_exit; + fk_id= f->id; + goto err_exit; } -next_item: - it++; } for (const auto &a : add_fk) @@ -7703,17 +7700,16 @@ next_item: if (a->foreign_index->fields[i].col == col) { fk_id= a->id; - goto err_exit; + goto err_exit; } } } for (const auto &f : table->referenced_set) { + if (!f->referenced_index) continue; for (ulint i= 0; i < f->n_fields; i++) { - if (!f->referenced_index) - continue; if (f->referenced_index->fields[i].col == col) { my_error(ER_FK_COLUMN_CANNOT_CHANGE_CHILD, MYF(0), From e913f4e11e1e519196f276d7c5689f653e724547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Sat, 21 Oct 2023 10:11:16 +0200 Subject: [PATCH 091/158] MDEV-32024 : Galera library 26.4.16 fails with every server version Problem was that total order isolation (TOI) is started before we know sequence implementing storage engine. This led to situation where table implementing persistent storate for sequence in case of MyISAM was created on applier causing errors later in test execution. Therefore, in both CREATE SEQUENCE and ALTER TABLE to implementing persistent storage we need to check implementing storage engine after open_tables and this check must be done in both master and applier, because if implementing storage engine is MyISAM it does not support rollback. Added tests to make sure that if sequence implementing storage engine is MyISAM or we try to alter it to MyISAM user gets error and changes are not replicated. Signed-off-by: Julius Goryavsky --- .../galera/r/galera_concurrent_ctas.result | 25 ++++ .../suite/galera/r/galera_sequences.result | 56 +++++++- .../galera/t/galera_concurrent_ctas.test | 123 +++++++++++------- .../suite/galera/t/galera_sequences.test | 41 ++++-- sql/sql_alter.cc | 25 ++-- sql/sql_table.cc | 27 +++- 6 files changed, 221 insertions(+), 76 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_concurrent_ctas.result b/mysql-test/suite/galera/r/galera_concurrent_ctas.result index 39c55277c52..933f1d2a98e 100644 --- a/mysql-test/suite/galera/r/galera_concurrent_ctas.result +++ b/mysql-test/suite/galera/r/galera_concurrent_ctas.result @@ -1,5 +1,30 @@ connection node_2; connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_1; +SET DEBUG_SYNC = 'wsrep_create_table_as_select WAIT_FOR continue'; +CREATE table t1 as SELECT SLEEP(0.1);; +connection node_1a; +# Wait until CTAS is on debug sync point +connection node_1b; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL debug_dbug = '+d,sync.wsrep_apply_cb'; +connection node_2; +CREATE table t1 as SELECT SLEEP(0.2);; +connection node_1b; +SET SESSION debug_sync = 'now WAIT_FOR sync.wsrep_apply_cb_reached'; +# Signal first CTAS to continue and wait until CTAS has executed +SET DEBUG_SYNC= 'now SIGNAL continue'; +SET GLOBAL debug_dbug= ''; +SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +connection node_2a; +connection node_1b; +SET DEBUG_SYNC= 'RESET'; +connection node_2; +connection node_1; +DROP TABLE t1; disconnect node_2; disconnect node_1; # End of test diff --git a/mysql-test/suite/galera/r/galera_sequences.result b/mysql-test/suite/galera/r/galera_sequences.result index e696a707cdf..1a5219c2d45 100644 --- a/mysql-test/suite/galera/r/galera_sequences.result +++ b/mysql-test/suite/galera/r/galera_sequences.result @@ -31,7 +31,7 @@ select NEXT VALUE FOR Seq1_1; NEXT VALUE FOR Seq1_1 1 alter table Seq1_1 engine=myisam; -ERROR 42000: This version of MariaDB doesn't yet support 'Galera cluster does support only InnoDB sequences' +ERROR 42000: This version of MariaDB doesn't yet support 'non-InnoDB sequences in Galera cluster' select NEXT VALUE FOR Seq1_1; NEXT VALUE FOR Seq1_1 2 @@ -156,7 +156,53 @@ a b DROP TABLE t1; DROP SEQUENCE t; CREATE SEQUENCE t ENGINE=MYISAM; -ERROR 42000: This version of MariaDB doesn't yet support 'Galera cluster does support only InnoDB sequences' +ERROR 42000: This version of MariaDB doesn't yet support 'non-InnoDB sequences in Galera cluster' +SHOW CREATE SEQUENCE t; +ERROR 42S02: Table 'test.t' doesn't exist +SHOW CREATE TABLE t; +ERROR 42S02: Table 'test.t' doesn't exist +connection node_2; +SHOW CREATE SEQUENCE t; +ERROR 42S02: Table 'test.t' doesn't exist +SHOW CREATE TABLE t; +ERROR 42S02: Table 'test.t' doesn't exist +connection node_1; +CREATE SEQUENCE t NOCACHE ENGINE=InnoDB; +ALTER TABLE t ENGINE=MyISAM; +ERROR 42000: This version of MariaDB doesn't yet support 'non-InnoDB sequences in Galera cluster' +SHOW CREATE SEQUENCE t; +Table Create Table +t CREATE SEQUENCE `t` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=InnoDB +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `next_not_cached_value` bigint(21) NOT NULL, + `minimum_value` bigint(21) NOT NULL, + `maximum_value` bigint(21) NOT NULL, + `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', + `increment` bigint(21) NOT NULL COMMENT 'increment value', + `cache_size` bigint(21) unsigned NOT NULL, + `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', + `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' +) ENGINE=InnoDB SEQUENCE=1 +connection node_2; +SHOW CREATE SEQUENCE t; +Table Create Table +t CREATE SEQUENCE `t` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=InnoDB +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `next_not_cached_value` bigint(21) NOT NULL, + `minimum_value` bigint(21) NOT NULL, + `maximum_value` bigint(21) NOT NULL, + `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', + `increment` bigint(21) NOT NULL COMMENT 'increment value', + `cache_size` bigint(21) unsigned NOT NULL, + `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', + `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' +) ENGINE=InnoDB SEQUENCE=1 +connection node_1; +DROP SEQUENCE t; CREATE SEQUENCE t INCREMENT BY 1 NOCACHE ENGINE=INNODB; CREATE TABLE t1(a int not null primary key default nextval(t), b int) engine=innodb; connection node_2; @@ -185,7 +231,7 @@ DROP TABLE t1; CREATE SEQUENCE t INCREMENT BY 0 NOCACHE ENGINE=INNODB; DROP SEQUENCE t; CREATE SEQUENCE t INCREMENT BY 1 CACHE=20 ENGINE=INNODB; -ERROR 42000: This version of MariaDB doesn't yet support 'In Galera if you use CACHE you should set INCREMENT BY 0 to behave correctly in a cluster' +ERROR 42000: This version of MariaDB doesn't yet support 'CACHE without INCREMENT BY 0 in Galera cluster' CREATE SEQUENCE t INCREMENT BY 0 CACHE=20 ENGINE=INNODB; CREATE TABLE t1(a int not null primary key default nextval(t), b int) engine=innodb; connection node_2; @@ -201,9 +247,9 @@ DROP SEQUENCE t; DROP TABLE t1; CREATE SEQUENCE t INCREMENT BY 0 CACHE=20 ENGINE=INNODB; ALTER TABLE t ENGINE=MYISAM; -ERROR 42000: This version of MariaDB doesn't yet support 'Galera cluster does support only InnoDB sequences' +ERROR 42000: This version of MariaDB doesn't yet support 'non-InnoDB sequences in Galera cluster' ALTER SEQUENCE t INCREMENT BY 1 CACHE=10; -ERROR 42000: This version of MariaDB doesn't yet support 'In Galera if you use CACHE you should set INCREMENT BY 0 to behave correctly in a cluster' +ERROR 42000: This version of MariaDB doesn't yet support 'CACHE without INCREMENT BY 0 in Galera cluster' ALTER SEQUENCE t INCREMENT BY 1 NOCACHE; ALTER SEQUENCE t INCREMENT BY 0 NOCACHE; ALTER SEQUENCE t INCREMENT BY 0 CACHE=10; diff --git a/mysql-test/suite/galera/t/galera_concurrent_ctas.test b/mysql-test/suite/galera/t/galera_concurrent_ctas.test index 61038664b21..e22ac811c8b 100644 --- a/mysql-test/suite/galera/t/galera_concurrent_ctas.test +++ b/mysql-test/suite/galera/t/galera_concurrent_ctas.test @@ -1,56 +1,85 @@ --source include/galera_cluster.inc --source include/big_test.inc +--source include/have_debug_sync.inc ---write_file $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql -CREATE table t1 as SELECT SLEEP(0.1); -DROP table t1; -CREATE table t1 as SELECT SLEEP(0.1); -DROP table t1; -CREATE table t1 as SELECT SLEEP(0.1); -DROP table t1; -CREATE table t1 as SELECT SLEEP(0.1); -DROP table t1; -CREATE table t1 as SELECT SLEEP(0.1); -DROP table t1; -CREATE table t1 as SELECT SLEEP(0.1); -DROP table t1; -CREATE table t1 as SELECT SLEEP(0.1); -DROP table t1; -CREATE table t1 as SELECT SLEEP(0.1); -DROP table t1; -CREATE table t1 as SELECT SLEEP(0.2); -CREATE table t2 as SELECT SLEEP(0.2); -CREATE table t3 as SELECT SLEEP(0.2); -CREATE table t4 as SELECT SLEEP(0.2); -CREATE table t5 as SELECT SLEEP(0.2); -CREATE table t6 as SELECT SLEEP(0.2); -CREATE table t7 as SELECT SLEEP(0.2); -CREATE table t8 as SELECT SLEEP(0.2); -CREATE table t9 as SELECT SLEEP(0.2); -DROP table t1; -DROP table t2; -DROP table t3; -DROP table t4; -DROP table t5; -DROP table t6; -DROP table t7; -DROP table t8; -DROP table t9; -EOF +# +# To have real concurrent CTAS this test uses DEBUG_SYNC +# -let $run=10; +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 -while($run) -{ - --error 0,1 - exec $MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_1 test \ - < $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql & \ - $MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_2 test \ - < $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql; - dec $run; -} +--connection node_1 +# +# Send CTAS it will block before open_tables call +# +SET DEBUG_SYNC = 'wsrep_create_table_as_select WAIT_FOR continue'; +--send CREATE table t1 as SELECT SLEEP(0.1); + +--connection node_1a +# +# Wait for CTAS to block +# +--echo # Wait until CTAS is on debug sync point +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: wsrep_create_table_as_select' +--source include/wait_condition.inc + +--connection node_1b +# +# Block node_1 applier +# +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL debug_dbug = '+d,sync.wsrep_apply_cb'; + +# +# Send concurrent CTAS it will block on applier +# +--connection node_2 +--send CREATE table t1 as SELECT SLEEP(0.2); + +# +# Wait until second CTAS is blocked +# +--connection node_1b +SET SESSION debug_sync = 'now WAIT_FOR sync.wsrep_apply_cb_reached'; + +--echo # Signal first CTAS to continue and wait until CTAS has executed +SET DEBUG_SYNC= 'now SIGNAL continue'; +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'Creating table CREATE table t1 as SELECT SLEEP(0.1)' +--source include/wait_condition.inc +# +# Release second CTAS and cleanup +# +SET GLOBAL debug_dbug= ''; +SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +# +# Wait until second CTAS continues +# +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'debug sync point: now%' +--source include/wait_condition.inc +# +# Wait until second CTAS finishes +# +--connection node_2a +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'Creating table CREATE table t1 as SELECT SLEEP(0.2)' +--source include/wait_condition.inc +# +# Cleanup +# +--connection node_1b +SET DEBUG_SYNC= 'RESET'; +# +# Verify that at least one is successful +# +--connection node_2 +--reap + +--connection node_1 +--error 0,ER_TABLE_EXISTS_ERROR,ER_QUERY_INTERRUPTED +--reap +DROP TABLE t1; ---remove_file $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql --source include/galera_end.inc --echo # End of test diff --git a/mysql-test/suite/galera/t/galera_sequences.test b/mysql-test/suite/galera/t/galera_sequences.test index 5c03ab973e0..53417055d7d 100644 --- a/mysql-test/suite/galera/t/galera_sequences.test +++ b/mysql-test/suite/galera/t/galera_sequences.test @@ -134,6 +134,31 @@ DROP SEQUENCE t; # --error ER_NOT_SUPPORTED_YET CREATE SEQUENCE t ENGINE=MYISAM; +--error ER_NO_SUCH_TABLE +SHOW CREATE SEQUENCE t; +--error ER_NO_SUCH_TABLE +SHOW CREATE TABLE t; + +--connection node_2 +# Verify that above MyISAM sequence does not replicate +--error ER_NO_SUCH_TABLE +SHOW CREATE SEQUENCE t; +--error ER_NO_SUCH_TABLE +SHOW CREATE TABLE t; + +--connection node_1 +CREATE SEQUENCE t NOCACHE ENGINE=InnoDB; +--error ER_NOT_SUPPORTED_YET +ALTER TABLE t ENGINE=MyISAM; +SHOW CREATE SEQUENCE t; +SHOW CREATE TABLE t; + +--connection node_2 +SHOW CREATE SEQUENCE t; +SHOW CREATE TABLE t; + +--connection node_1 +DROP SEQUENCE t; CREATE SEQUENCE t INCREMENT BY 1 NOCACHE ENGINE=INNODB; CREATE TABLE t1(a int not null primary key default nextval(t), b int) engine=innodb; @@ -164,15 +189,15 @@ SET SESSION wsrep_sync_wait=0; while ($count) { --connection node_1 ---error 0,ER_LOCK_WAIT_TIMEOUT +--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK INSERT INTO t1(b) values (1); --connection node_2 ---error 0,ER_LOCK_WAIT_TIMEOUT +--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK INSERT INTO t1(b) values (2); ---error 0,ER_LOCK_WAIT_TIMEOUT +--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK INSERT INTO t1(b) values (2); --connection node_1 ---error 0,ER_LOCK_WAIT_TIMEOUT +--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK INSERT INTO t1(b) values (1); --dec $count } @@ -222,15 +247,15 @@ SET SESSION wsrep_sync_wait=0; while ($count) { --connection node_1 ---error 0,ER_LOCK_WAIT_TIMEOUT +--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK INSERT INTO t1(b) values (1),(2),(3),(4),(5),(6),(7),(8),(9); --connection node_2 ---error 0,ER_LOCK_WAIT_TIMEOUT +--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK INSERT INTO t1(b) values (21),(22),(23),(24),(25),(26),(27),(28),(29); ---error 0,ER_LOCK_WAIT_TIMEOUT +--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK INSERT INTO t1(b) values (21),(22),(23),(24),(25),(26),(27),(28),(29); --connection node_1 ---error 0,ER_LOCK_WAIT_TIMEOUT +--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK INSERT INTO t1(b) values (1),(2),(3),(4),(5),(6),(7),(8),(9); --dec $count } diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index cf44ed67120..f83f629a715 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -470,22 +470,12 @@ bool Sql_cmd_alter_table::execute(THD *thd) if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE)) DBUG_RETURN(TRUE); /* purecov: inspected */ + #ifdef WITH_WSREP if (WSREP(thd) && (!thd->is_current_stmt_binlog_format_row() || !thd->find_temporary_table(first_table))) { - wsrep::key_array keys; - wsrep_append_fk_parent_table(thd, first_table, &keys); - - WSREP_TO_ISOLATION_BEGIN_ALTER((lex->name.str ? select_lex->db.str : NULL), - (lex->name.str ? lex->name.str : NULL), - first_table, &alter_info, &keys) - { - WSREP_WARN("ALTER TABLE isolation failure"); - DBUG_RETURN(TRUE); - } - /* It makes sense to set auto_increment_* to defaults in TOI operations. Must be done before wsrep_TOI_begin() since Query_log_event encapsulating @@ -498,6 +488,19 @@ bool Sql_cmd_alter_table::execute(THD *thd) thd->variables.auto_increment_offset = 1; thd->variables.auto_increment_increment = 1; } + + wsrep::key_array keys; + wsrep_append_fk_parent_table(thd, first_table, &keys); + + WSREP_TO_ISOLATION_BEGIN_ALTER((lex->name.str ? select_lex->db.str : NULL), + (lex->name.str ? lex->name.str : NULL), + first_table, &alter_info, &keys) + { + WSREP_WARN("ALTER TABLE isolation failure"); + DBUG_RETURN(TRUE); + } + + DEBUG_SYNC(thd, "wsrep_alter_table_after_toi"); } #endif diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6ffdea3b8cd..78a0aefc4f7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5339,12 +5339,15 @@ int mysql_create_table_no_lock(THD *thd, const LEX_CSTRING *db, @param thd thread handle @param seq sequence definition -@retval 0 failure -@retval 1 success +@retval false success +@retval true failure */ bool wsrep_check_sequence(THD* thd, const sequence_definition *seq) { enum legacy_db_type db_type; + + DBUG_ASSERT(WSREP(thd)); + if (thd->lex->create_info.used_fields & HA_CREATE_USED_ENGINE) { db_type= thd->lex->create_info.db_type->db_type; @@ -5359,7 +5362,7 @@ bool wsrep_check_sequence(THD* thd, const sequence_definition *seq) if (db_type != DB_TYPE_INNODB) { my_error(ER_NOT_SUPPORTED_YET, MYF(0), - "Galera cluster does support only InnoDB sequences"); + "non-InnoDB sequences in Galera cluster"); return(true); } @@ -5370,8 +5373,7 @@ bool wsrep_check_sequence(THD* thd, const sequence_definition *seq) seq->cache) { my_error(ER_NOT_SUPPORTED_YET, MYF(0), - "In Galera if you use CACHE you should set INCREMENT BY 0" - " to behave correctly in a cluster"); + "CACHE without INCREMENT BY 0 in Galera cluster"); return(true); } @@ -9780,6 +9782,15 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, TABLE *table= table_list->table; bool versioned= table && table->versioned(); +#ifdef WITH_WSREP + /* + If this ALTER TABLE is actually SEQUENCE we need to check + if we can support implementing storage engine. + */ + if (WSREP(thd) && table && table->s->sequence && + wsrep_check_sequence(thd, thd->lex->create_info.seq_create_info)) + DBUG_RETURN(TRUE); +#endif /* WITH_WSREP */ if (versioned) { @@ -11797,6 +11808,8 @@ bool Sql_cmd_create_table_like::execute(THD *thd) /* Store reference to table in case of LOCK TABLES */ create_info.table= create_table->table; + DEBUG_SYNC(thd, "wsrep_create_table_as_select"); + /* select_create is currently not re-execution friendly and needs to be created for every execution of a PS/SP. @@ -11855,6 +11868,10 @@ bool Sql_cmd_create_table_like::execute(THD *thd) !create_info.tmp_table())) { #ifdef WITH_WSREP + if (thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE && + wsrep_check_sequence(thd, lex->create_info.seq_create_info)) + DBUG_RETURN(true); + WSREP_TO_ISOLATION_BEGIN_ALTER(create_table->db.str, create_table->table_name.str, first_table, &alter_info, NULL) { From 179424db5ffd7f65e49dce9746177db6ad3234a6 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 4 Sep 2023 14:12:12 +0400 Subject: [PATCH 092/158] MDEV-32025 Crashes in MDL_key::mdl_key_init with lower-case-table-names=2 Backporting a part of MDEV-32026 (which also fixed MDEV-32025 in 11.3) from 11.3 to 10.4. The reported crash happened with --lower-case-table-names=2 on statements like: ALTER DATABASE Db1 DEFAULT CHARACTER SET utf8; ALTER DATABASE `#mysql50#D+b1` UPGRADE DATA DIRECTORY NAME; lock_schema_name() expects a normalized database name and assert if a non-normalized name comes. mysql_alter_db_internal() and mysql_upgrade_db() get a non-normalized database name in the parameter. Fixing them to normalize the database name before passing it to lock_schema_name(). --- mysql-test/main/lowercase_table2.result | 21 +++++++++++++++++++++ mysql-test/main/lowercase_table2.test | 18 +++++++++++++++++- sql/sql_db.cc | 11 +++++++++-- 3 files changed, 47 insertions(+), 3 deletions(-) mode change 100644 => 100755 mysql-test/main/lowercase_table2.result diff --git a/mysql-test/main/lowercase_table2.result b/mysql-test/main/lowercase_table2.result old mode 100644 new mode 100755 index fe06fb671a2..039e87b90ae --- a/mysql-test/main/lowercase_table2.result +++ b/mysql-test/main/lowercase_table2.result @@ -358,3 +358,24 @@ disconnect conn1; drop user 'mysqltest_1'@'localhost'; drop tables a, B; drop database db1; +# +# MDEV-32025 Crashes in MDL_key::mdl_key_init with lower-case-table-names=2 +# +CREATE DATABASE `#mysql50#D+b1`; +ALTER DATABASE `#mysql50#D+b1` UPGRADE DATA DIRECTORY NAME; +SHOW CREATE DATABASE `D+b1`; +Database Create Database +D+b1 CREATE DATABASE `D+b1` /*!40100 DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci */ +SHOW CREATE DATABASE `d+b1`; +Database Create Database +d+b1 CREATE DATABASE `d+b1` /*!40100 DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci */ +DROP DATABASE `D+b1`; +CREATE DATABASE Db1; +ALTER DATABASE Db1 DEFAULT CHARACTER SET utf8; +SHOW CREATE DATABASE Db1; +Database Create Database +Db1 CREATE DATABASE `Db1` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci */ +SHOW CREATE DATABASE db1; +Database Create Database +db1 CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci */ +DROP DATABASE Db1; diff --git a/mysql-test/main/lowercase_table2.test b/mysql-test/main/lowercase_table2.test index 82c07bf9345..791119c0f7b 100644 --- a/mysql-test/main/lowercase_table2.test +++ b/mysql-test/main/lowercase_table2.test @@ -313,4 +313,20 @@ connection default; disconnect conn1; drop user 'mysqltest_1'@'localhost'; drop tables a, B; -drop database db1; \ No newline at end of file +drop database db1; + +--echo # +--echo # MDEV-32025 Crashes in MDL_key::mdl_key_init with lower-case-table-names=2 +--echo # + +CREATE DATABASE `#mysql50#D+b1`; +ALTER DATABASE `#mysql50#D+b1` UPGRADE DATA DIRECTORY NAME; +SHOW CREATE DATABASE `D+b1`; +SHOW CREATE DATABASE `d+b1`; +DROP DATABASE `D+b1`; + +CREATE DATABASE Db1; +ALTER DATABASE Db1 DEFAULT CHARACTER SET utf8; +SHOW CREATE DATABASE Db1; +SHOW CREATE DATABASE db1; +DROP DATABASE Db1; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index b2b591464f7..5ef2e186ff2 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -715,7 +715,10 @@ mysql_alter_db_internal(THD *thd, const LEX_CSTRING *db, int error= 0; DBUG_ENTER("mysql_alter_db"); - if (lock_schema_name(thd, db->str)) + char dbnorm_buffer[SAFE_NAME_LEN + 1]; + const char *dbnorm= normalize_db_name(db->str, dbnorm_buffer, + sizeof(dbnorm_buffer)); + if (lock_schema_name(thd, dbnorm)) DBUG_RETURN(TRUE); /* @@ -1686,8 +1689,12 @@ bool mysql_upgrade_db(THD *thd, const LEX_CSTRING *old_db) new_db.str= old_db->str + MYSQL50_TABLE_NAME_PREFIX_LENGTH; new_db.length= old_db->length - MYSQL50_TABLE_NAME_PREFIX_LENGTH; + char dbnorm_buffer_old[SAFE_NAME_LEN + 1]; + const char *old_dbnorm= normalize_db_name(old_db->str, dbnorm_buffer_old, + sizeof(dbnorm_buffer_old)); + /* Lock the old name, the new name will be locked by mysql_create_db().*/ - if (lock_schema_name(thd, old_db->str)) + if (lock_schema_name(thd, old_dbnorm)) DBUG_RETURN(1); /* From babd833685e1fd1da4411a0874ba1c98bb0b631d Mon Sep 17 00:00:00 2001 From: Anthony Ryan Date: Fri, 20 Oct 2023 22:27:14 -0400 Subject: [PATCH 093/158] MDEV-29914: Fix maridab-upgrade when sql_safe_updates = on is set in my.cnf Tested multiple major version upgrades with sql_safe_updates enabled, and confirmed the issue is resolved. Reviewer: Daniel Black --- mysql-test/main/mysql_upgrade.result | 52 ++++++++++++++++++++++++++++ mysql-test/main/mysql_upgrade.test | 10 ++++++ scripts/mysql_system_tables_fix.sql | 1 + 3 files changed, 63 insertions(+) diff --git a/mysql-test/main/mysql_upgrade.result b/mysql-test/main/mysql_upgrade.result index 93888ba805f..64d6cd12753 100644 --- a/mysql-test/main/mysql_upgrade.result +++ b/mysql-test/main/mysql_upgrade.result @@ -1006,4 +1006,56 @@ disconnect con1; connection default; drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +# +# mariadb-upgrade fails with sql_safe_updates = on +# +set @orig_sql_safe_updates = @@GLOBAL.sql_safe_updates; +set global sql_safe_updates=ON; +Phase 1/7: Checking and upgrading mysql database +Processing databases +mysql +mysql.column_stats OK +mysql.columns_priv OK +mysql.db OK +mysql.event OK +mysql.func OK +mysql.global_priv OK +mysql.gtid_slave_pos OK +mysql.help_category OK +mysql.help_keyword OK +mysql.help_relation OK +mysql.help_topic OK +mysql.index_stats OK +mysql.innodb_index_stats OK +mysql.innodb_table_stats OK +mysql.plugin OK +mysql.proc OK +mysql.procs_priv OK +mysql.proxies_priv OK +mysql.roles_mapping OK +mysql.servers OK +mysql.table_stats OK +mysql.tables_priv OK +mysql.time_zone OK +mysql.time_zone_leap_second OK +mysql.time_zone_name OK +mysql.time_zone_transition OK +mysql.time_zone_transition_type OK +mysql.transaction_registry OK +Phase 2/7: Installing used storage engines... Skipped +Phase 3/7: Fixing views +mysql.user OK +Phase 4/7: Running 'mysql_fix_privilege_tables' +Phase 5/7: Fixing table and database names +Phase 6/7: Checking and upgrading tables +Processing databases +information_schema +mtr +mtr.global_suppressions OK +mtr.test_suppressions OK +performance_schema +test +Phase 7/7: Running 'FLUSH PRIVILEGES' +OK +set global sql_safe_updates=@orig_sql_safe_updates; # End of 10.4 tests diff --git a/mysql-test/main/mysql_upgrade.test b/mysql-test/main/mysql_upgrade.test index be014bb19ae..f7a1bdf7be0 100644 --- a/mysql-test/main/mysql_upgrade.test +++ b/mysql-test/main/mysql_upgrade.test @@ -485,4 +485,14 @@ drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; --remove_file $MYSQLD_DATADIR/mysql_upgrade_info +--echo # +--echo # mariadb-upgrade fails with sql_safe_updates = on +--echo # + +set @orig_sql_safe_updates = @@GLOBAL.sql_safe_updates; +set global sql_safe_updates=ON; +--exec $MYSQL_UPGRADE --force 2>&1 +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info +set global sql_safe_updates=@orig_sql_safe_updates; + --echo # End of 10.4 tests diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 885d01e6b20..fe3470352ef 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -25,6 +25,7 @@ # adding a 'SHOW WARNINGS' after the statement. set sql_mode=''; +set sql_safe_updates='OFF'; set storage_engine=Aria; set enforce_storage_engine=NULL; set alter_algorithm='DEFAULT'; From d2d657e72217889c69550fc4fd0ce751a38d9177 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 28 Apr 2023 14:04:06 +0400 Subject: [PATCH 094/158] MDEV-31187 Add class Sql_mode_save_for_frm_handling --- sql/sql_class.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ sql/sql_partition.cc | 4 +--- sql/sql_view.cc | 37 ++----------------------------------- sql/table.cc | 4 +--- sql/unireg.cc | 14 +++++++------- 5 files changed, 55 insertions(+), 48 deletions(-) diff --git a/sql/sql_class.h b/sql/sql_class.h index 066e42ca0f0..3e95b614756 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -6910,6 +6910,50 @@ class Sql_mode_save sql_mode_t old_mode; // SQL mode saved at construction time. }; + +/* + Save the current sql_mode. Switch off sql_mode flags which can prevent + normal parsing of VIEWs, expressions in generated columns. + Restore the old sql_mode on destructor. +*/ +class Sql_mode_save_for_frm_handling: public Sql_mode_save +{ +public: + Sql_mode_save_for_frm_handling(THD *thd) + :Sql_mode_save(thd) + { + /* + - MODE_REAL_AS_FLOAT affect only CREATE TABLE parsing + + MODE_PIPES_AS_CONCAT affect expression parsing + + MODE_ANSI_QUOTES affect expression parsing + + MODE_IGNORE_SPACE affect expression parsing + - MODE_IGNORE_BAD_TABLE_OPTIONS affect only CREATE/ALTER TABLE parsing + * MODE_ONLY_FULL_GROUP_BY affect execution + * MODE_NO_UNSIGNED_SUBTRACTION affect execution + - MODE_NO_DIR_IN_CREATE affect table creation only + - MODE_POSTGRESQL compounded from other modes + + MODE_ORACLE affects Item creation (e.g for CONCAT) + - MODE_MSSQL compounded from other modes + - MODE_DB2 compounded from other modes + - MODE_MAXDB affect only CREATE TABLE parsing + - MODE_NO_KEY_OPTIONS affect only SHOW + - MODE_NO_TABLE_OPTIONS affect only SHOW + - MODE_NO_FIELD_OPTIONS affect only SHOW + - MODE_MYSQL323 affect only SHOW + - MODE_MYSQL40 affect only SHOW + - MODE_ANSI compounded from other modes + (+ transaction mode) + ? MODE_NO_AUTO_VALUE_ON_ZERO affect UPDATEs + + MODE_NO_BACKSLASH_ESCAPES affect expression parsing + + MODE_EMPTY_STRING_IS_NULL affect expression parsing + */ + thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES | + MODE_ORACLE | MODE_EMPTY_STRING_IS_NULL); + }; +}; + + class Abort_on_warning_instant_set { THD *m_thd; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 487800df1ab..74459480c61 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -2589,11 +2589,9 @@ char *generate_partition_syntax_for_frm(THD *thd, partition_info *part_info, HA_CREATE_INFO *create_info, Alter_info *alter_info) { - sql_mode_t old_mode= thd->variables.sql_mode; - thd->variables.sql_mode &= ~MODE_ANSI_QUOTES; + Sql_mode_save_for_frm_handling sql_mode_save(thd); char *res= generate_partition_syntax(thd, part_info, buf_length, true, create_info, alter_info); - thd->variables.sql_mode= old_mode; return res; } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 54debf98eff..6eaf739a417 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -952,8 +952,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, view_query.length(0); is_query.length(0); { - sql_mode_t sql_mode= thd->variables.sql_mode & MODE_ANSI_QUOTES; - thd->variables.sql_mode&= ~MODE_ANSI_QUOTES; + Sql_mode_save_for_frm_handling sql_mode_save(thd); lex->unit.print(&view_query, enum_query_type(QT_VIEW_INTERNAL | QT_ITEM_ORIGINAL_FUNC_NULLIF | @@ -962,8 +961,6 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, QT_WITHOUT_INTRODUCERS | QT_ITEM_ORIGINAL_FUNC_NULLIF | QT_NO_WRAPPERS_FOR_TVC_IN_VIEW)); - - thd->variables.sql_mode|= sql_mode; } DBUG_PRINT("info", ("View: %.*s", view_query.length(), view_query.ptr())); @@ -1423,35 +1420,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, lex_start(thd); lex->stmt_lex= old_lex; - sql_mode_t saved_mode= thd->variables.sql_mode; - /* switch off modes which can prevent normal parsing of VIEW - - MODE_REAL_AS_FLOAT affect only CREATE TABLE parsing - + MODE_PIPES_AS_CONCAT affect expression parsing - + MODE_ANSI_QUOTES affect expression parsing - + MODE_IGNORE_SPACE affect expression parsing - - MODE_IGNORE_BAD_TABLE_OPTIONS affect only CREATE/ALTER TABLE parsing - * MODE_ONLY_FULL_GROUP_BY affect execution - * MODE_NO_UNSIGNED_SUBTRACTION affect execution - - MODE_NO_DIR_IN_CREATE affect table creation only - - MODE_POSTGRESQL compounded from other modes - - MODE_ORACLE affects Item creation (e.g for CONCAT) - - MODE_MSSQL compounded from other modes - - MODE_DB2 compounded from other modes - - MODE_MAXDB affect only CREATE TABLE parsing - - MODE_NO_KEY_OPTIONS affect only SHOW - - MODE_NO_TABLE_OPTIONS affect only SHOW - - MODE_NO_FIELD_OPTIONS affect only SHOW - - MODE_MYSQL323 affect only SHOW - - MODE_MYSQL40 affect only SHOW - - MODE_ANSI compounded from other modes - (+ transaction mode) - ? MODE_NO_AUTO_VALUE_ON_ZERO affect UPDATEs - + MODE_NO_BACKSLASH_ESCAPES affect expression parsing - */ - thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES | - MODE_ORACLE); - + Sql_mode_save_for_frm_handling sql_mode_save(thd); /* Parse the query. */ parse_status= parse_sql(thd, & parser_state, table->view_creation_ctx); @@ -1464,8 +1433,6 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, (old_lex->sql_command == SQLCOM_SHOW_CREATE)) lex->sql_command= old_lex->sql_command; - thd->variables.sql_mode= saved_mode; - if (dbchanged && mysql_change_db(thd, &old_db, TRUE)) goto err; } diff --git a/sql/table.cc b/sql/table.cc index 44d639e27a4..e6684cd1c72 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1101,7 +1101,7 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, Field **vfield_ptr= table->vfield; Field **dfield_ptr= table->default_field; Virtual_column_info **check_constraint_ptr= table->check_constraints; - sql_mode_t saved_mode= thd->variables.sql_mode; + Sql_mode_save_for_frm_handling sql_mode_save(thd); Query_arena backup_arena; Virtual_column_info *vcol= 0; StringBuffer expr_str; @@ -1128,7 +1128,6 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, thd->stmt_arena= table->expr_arena; thd->update_charset(&my_charset_utf8mb4_general_ci, table->s->table_charset); expr_str.append(&parse_vcol_keyword); - thd->variables.sql_mode &= ~(MODE_NO_BACKSLASH_ESCAPES | MODE_EMPTY_STRING_IS_NULL); while (pos < end) { @@ -1315,7 +1314,6 @@ end: thd->stmt_arena= backup_stmt_arena_ptr; if (save_character_set_client) thd->update_charset(save_character_set_client, save_collation); - thd->variables.sql_mode= saved_mode; DBUG_RETURN(res); } diff --git a/sql/unireg.cc b/sql/unireg.cc index b4213786abb..f2d57e7549f 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -42,7 +42,8 @@ static uint pack_keys(uchar *,uint, KEY *, ulong, uint); static bool pack_header(THD *, uchar *, List &, HA_CREATE_INFO *, ulong, handler *); -static bool pack_vcols(String *, List &, List *); +static bool pack_vcols(THD *thd, String *, + List &, List *); static uint get_interval_id(uint *,List &, Create_field *); static bool pack_fields(uchar **, List &, HA_CREATE_INFO*, ulong); @@ -199,10 +200,8 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table, create_info->null_bits++; data_offset= (create_info->null_bits + 7) / 8; - sql_mode_t save_sql_mode= thd->variables.sql_mode; - thd->variables.sql_mode &= ~MODE_ANSI_QUOTES; - error= pack_vcols(&vcols, create_fields, create_info->check_constraint_list); - thd->variables.sql_mode= save_sql_mode; + error= pack_vcols(thd, &vcols, + create_fields, create_info->check_constraint_list); if (unlikely(error)) DBUG_RETURN(frm); @@ -635,9 +634,10 @@ static bool pack_expression(String *buf, Virtual_column_info *vcol, } -static bool pack_vcols(String *buf, List &create_fields, - List *check_constraint_list) +static bool pack_vcols(THD *thd, String *buf, List &create_fields, + List *check_constraint_list) { + Sql_mode_save_for_frm_handling sql_mode_save(thd); List_iterator it(create_fields); Create_field *field; From 0a4103e6bb40c8fcda5d020792d11a8d6eff4803 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 23 Oct 2023 08:22:18 +0200 Subject: [PATCH 095/158] new CC v3.3 --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index c0ddc2c8cff..64f9d88f306 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit c0ddc2c8cff30aebbedc5ae175e435c2c6fec646 +Subproject commit 64f9d88f3061352f3b368d9d73073ebf6c80cbb1 From 5ca941caec3bfe4b89a61dd76a9590615156bd31 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 23 Oct 2023 08:17:56 +0200 Subject: [PATCH 096/158] New CC v3.1 --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index 3393fe35d37..ae565eea90d 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 3393fe35d378744e12636766931cf5109cc6c2e5 +Subproject commit ae565eea90dd3053a5a7857e7cdad93342dbc645 From 1fe4a71b67020a4fe3c1327df62668c11a0acb85 Mon Sep 17 00:00:00 2001 From: Andrei Date: Mon, 23 Oct 2023 12:53:12 +0300 Subject: [PATCH 097/158] MDEV-31792 Assertion fails in MDL_context::acquire_lock upon parallel replication of CREATE SEQUENCE The assert's reason was in missed FL_DDL flagging of CREATE-or-REPLACE Query event. MDEV-27365 fixes covered only the non-pre-existing table execution branch so did not see a possibility of implicit commit in the middle of execution in a rollback branch when the being CREATEd sequence table is actually replaced. The pre-existing table branch cleared the DDL modification flag so the query lost FL_DDL in binlog and its parallel execution on slave may have ended up with the assert to indicate the query is raced by a following in binlog order event. Fixed with applying the MDEV-27365 pattern. An mtr test is added to cover the rollback situation. The description test [ pass ] with a generous number of mtr parallel reties. --- .../suite/rpl/r/rpl_parallel_seq.result | 33 ++++++++++++- mysql-test/suite/rpl/t/rpl_parallel_seq.test | 47 ++++++++++++++++++- sql/log_event.cc | 3 ++ sql/sql_table.cc | 8 +++- 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_parallel_seq.result b/mysql-test/suite/rpl/r/rpl_parallel_seq.result index f5b062236db..fdb6bfef724 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_seq.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_seq.result @@ -82,6 +82,37 @@ SELECT @@global.gtid_binlog_state, @@global.gtid_slave_pos as "all through 101 h @@global.gtid_binlog_state all through 101 have been committed 0-1-101 0-1-101 connection slave; +flush tables with read lock; +connection master; +CREATE OR REPLACE SEQUENCE s3 ENGINE=innodb; +SELECT NEXT VALUE FOR s3 into @tmpvar; +include/save_master_gtid.inc +connection slave; +unlock tables; +include/sync_with_master_gtid.inc +connection slave; +flush tables with read lock; +connection master; +CREATE OR REPLACE SEQUENCE s3 ENGINE=innodb; +SELECT NEXT VALUE FOR s3 into @tmpvar; +include/save_master_gtid.inc +connection slave; +unlock tables; +include/sync_with_master_gtid.inc +connection slave; +BEGIN /* slave local Trx */; +select count(*) from s3; +count(*) +1 +connection master; +CREATE OR REPLACE SEQUENCE s3 ENGINE=innodb; +SELECT NEXT VALUE FOR s3 into @tmpvar; +include/save_master_gtid.inc +connection slave; +connection slave; +rollback /* Trx */; +include/sync_with_master_gtid.inc +connection slave; include/stop_slave.inc SET debug_sync = RESET; SET @@global.slave_parallel_threads= 0; @@ -90,7 +121,7 @@ SET @@global.debug_dbug = ""; SET @@global.gtid_strict_mode=0; include/start_slave.inc connection master; -DROP SEQUENCE s2; +DROP SEQUENCE s2,s3; DROP TABLE ti; connection slave; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_seq.test b/mysql-test/suite/rpl/t/rpl_parallel_seq.test index f0dc4fe4485..ecc29de779b 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_seq.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_seq.test @@ -128,8 +128,51 @@ SET DEBUG_SYNC = 'now SIGNAL continue_worker'; SELECT @@global.gtid_binlog_state, @@global.gtid_slave_pos as "all through 101 have been committed"; +# MDEV-31792 Assertion in MDL_context::acquire_lock upon parallel replication of CREATE SEQUENCE + +--let $iter = 3 +while ($iter) +{ +--connection slave +if (`select $iter > 1`) +{ + flush tables with read lock; +} +if (`select $iter = 1`) +{ + BEGIN /* slave local Trx */; + select count(*) from s3; +} + +--connection master +CREATE OR REPLACE SEQUENCE s3 ENGINE=innodb; +# select may return non-deterministically, don't print its result +SELECT NEXT VALUE FOR s3 into @tmpvar; +--source include/save_master_gtid.inc + +--connection slave +--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "Waiting for prior transaction to start commit%" +--source include/wait_condition.inc + +if (`select $iter > 1`) +{ + unlock tables; +} +if (`select $iter = 1`) +{ +--connection slave +rollback /* Trx */; +} + + +--source include/sync_with_master_gtid.inc + +--dec $iter +} + + # -# MDEV-29621/MDEV-31077 clean up. +# MDEV-29621/MDEV-31077/MDEV-31792 clean up. # --connection slave --source include/stop_slave.inc @@ -142,7 +185,7 @@ SET debug_sync = RESET; --source include/start_slave.inc --connection master -DROP SEQUENCE s2; +DROP SEQUENCE s2,s3; DROP TABLE ti; --sync_slave_with_master diff --git a/sql/log_event.cc b/sql/log_event.cc index 014968e31d4..7c791a4b6f5 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8023,6 +8023,9 @@ Gtid_log_event::Gtid_log_event(THD *thd_arg, uint64 seq_no_arg, /* Preserve any DDL or WAITED flag in the slave's binlog. */ if (thd_arg->rgi_slave) flags2|= (thd_arg->rgi_slave->gtid_ev_flags2 & (FL_DDL|FL_WAITED)); + + DBUG_ASSERT(thd_arg->lex->sql_command != SQLCOM_CREATE_SEQUENCE || + (flags2 & FL_DDL)); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 78a0aefc4f7..84ef23bf828 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5101,7 +5101,13 @@ int create_table_impl(THD *thd, const LEX_CSTRING &orig_db, Rollback the empty transaction started in mysql_create_table() call to open_and_lock_tables() when we are using LOCK TABLES. */ - (void) trans_rollback_stmt(thd); + { + uint save_unsafe_rollback_flags= + thd->transaction.stmt.m_unsafe_rollback_flags; + (void) trans_rollback_stmt(thd); + thd->transaction.stmt.m_unsafe_rollback_flags= + save_unsafe_rollback_flags; + } /* Remove normal table without logging. Keep tables locked */ if (mysql_rm_table_no_locks(thd, &table_list, 0, 0, 0, 0, 1, 1)) goto err; From b5e43a1d3539c7254c298dc9f63a261281345d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 23 Oct 2023 16:13:16 +0300 Subject: [PATCH 098/158] MDEV-32552 Write-ahead logging is broken for freed pages buf_page_free(): Flag the freed page as modified if it is found in the buffer pool. buf_flush_page(): If the page has been freed, ensure that the log for it has been durably written, before removing the page from buf_pool.flush_list. FindBlockX: Find also MTR_MEMO_PAGE_X_MODIFY in order to avoid an occasional failure of innodb.innodb_defrag_concurrent, which involves freeing and reallocating pages in the same mini-transaction. This fixes a regression that was introduced in commit a35b4ae89871d8184f04abb112c385481d557dbb (MDEV-15528). This logic was tested by commenting out the $shutdown_timeout line from a test and running the following: ./mtr --rr innodb.scrub rr replay var/log/mysqld.1.rr/mariadbd-0 A breakpoint in the modified buf_flush_page() was hit, and the FIL_PAGE_LSN of that page had been last modified during the mtr_t::commit() of a mini-transaction where buf_page_free() had been executed on that page. --- storage/innobase/buf/buf0buf.cc | 1 + storage/innobase/buf/buf0flu.cc | 11 +++++++++++ storage/innobase/mtr/mtr0mtr.cc | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 83eee85d749..c510d320759 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2324,6 +2324,7 @@ void buf_page_free(fil_space_t *space, uint32_t page, mtr_t *mtr, mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX); rw_lock_x_lock_inline(&block->lock, 0, file, line); buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); + mtr->set_modified(*block); #ifdef BTR_CUR_HASH_ADAPT if (block->index) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index ce75f95602c..3ee2ea97534 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -875,7 +875,18 @@ static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) page_t *frame= bpage->zip.data; if (status == buf_page_t::FREED) + { + if (UNIV_LIKELY(space->purpose == FIL_TYPE_TABLESPACE)) + { + const lsn_t lsn= mach_read_from_8(my_assume_aligned<8> + (FIL_PAGE_LSN + (frame ? frame + : block->frame))); + ut_ad(lsn >= oldest_modification); + if (lsn > log_sys.get_flushed_lsn()) + log_write_up_to(lsn, true); + } buf_pool.release_freed_page(&block->page); + } else { space->reacquire(); diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 7f4812e158a..b138dd13073 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -1027,7 +1027,8 @@ struct FindBlockX /** @return whether the block was not found x-latched */ bool operator()(const mtr_memo_slot_t *slot) const { - return slot->object != &block || slot->type != MTR_MEMO_PAGE_X_FIX; + return slot->object != &block || + (slot->type | MTR_MEMO_MODIFY) != MTR_MEMO_PAGE_X_MODIFY; } }; From 2eee0e9b894d77351c6ed730d5f3f79a1aefa8b5 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 19 Oct 2023 16:55:16 +0200 Subject: [PATCH 099/158] cleanup: mainly formatting, plus one helper --- mysql-test/main/information_schema_db.result | 24 ++++++-- mysql-test/main/information_schema_db.test | 48 +++++++-------- .../funcs_1/r/is_table_constraints.result | 6 -- .../suite/funcs_1/t/is_table_constraints.test | 14 ----- sql/sql_acl.cc | 11 +++- sql/sql_show.cc | 58 +++++++------------ sql/table.h | 3 + 7 files changed, 74 insertions(+), 90 deletions(-) diff --git a/mysql-test/main/information_schema_db.result b/mysql-test/main/information_schema_db.result index 14001039f7d..2724272efb3 100644 --- a/mysql-test/main/information_schema_db.result +++ b/mysql-test/main/information_schema_db.result @@ -1,9 +1,5 @@ set local sql_mode=""; set global sql_mode=""; -drop table if exists t1,t2; -drop view if exists v1,v2; -drop function if exists f1; -drop function if exists f2; show tables from INFORMATION_SCHEMA like 'T%'; Tables_in_information_schema (T%) TABLES @@ -17,6 +13,10 @@ create database mbase; use `inf%`; show tables; Tables_in_inf% +# +# Bug#18113 SELECT * FROM information_schema.xxx crashes server +# Bug#17204 second CALL to procedure crashes Server +# grant all privileges on `inf%`.* to 'mysqltest_1'@'localhost'; grant all privileges on `mbase`.* to 'mysqltest_1'@'localhost'; create table t1 (f1 int); @@ -65,6 +65,9 @@ drop database `inf%`; drop procedure mbase.p1; drop database mbase; disconnect user1; +# +# Bug#18282 INFORMATION_SCHEMA.TABLES provides inconsistent info about invalid views +# use test; create table t1 (i int); create function f1 () returns int return (select max(i) from t1); @@ -88,6 +91,10 @@ v2 VIEW VIEW drop function f1; drop function f2; drop view v1, v2; +# +# Bug#20543 select on information_schema strange warnings, view, different +# schemas/users +# create database testdb_1; create user testdb_1@localhost; grant all on testdb_1.* to testdb_1@localhost with grant option; @@ -216,6 +223,9 @@ disconnect testdb_2; connection default; drop user testdb_1@localhost; drop user testdb_2@localhost; +# +# Bug#22763 Disrepancy between SHOW CREATE VIEW and I_S.VIEWS +# create database testdb_1; create table testdb_1.t1 (a int); create view testdb_1.v1 as select * from testdb_1.t1; @@ -246,6 +256,9 @@ connection user1; disconnect user1; connection default; set global sql_mode=default; +# +# MDEV-20549 SQL SECURITY DEFINER does not work for INFORMATION_SCHEMA tables +# create user foo@localhost; grant select on test.* to foo@localhost; create procedure rootonly() select 1; @@ -325,3 +338,6 @@ disconnect foo; drop view v1d, v1i, v2d, v2i, v3d, v3i, v4d, v4i, v5d, v5i; drop user foo@localhost; drop procedure rootonly; +# +# End of 10.2 tests +# diff --git a/mysql-test/main/information_schema_db.test b/mysql-test/main/information_schema_db.test index e754d98a636..229ab0bfac0 100644 --- a/mysql-test/main/information_schema_db.test +++ b/mysql-test/main/information_schema_db.test @@ -2,21 +2,11 @@ # in the embedded server by default). So skip the test in embedded-server mode. -- source include/not_embedded.inc -#Don't run this test when thread_pool active ---source include/not_threadpool.inc - -- source include/testdb_only.inc set local sql_mode=""; set global sql_mode=""; ---disable_warnings -drop table if exists t1,t2; -drop view if exists v1,v2; -drop function if exists f1; -drop function if exists f2; ---enable_warnings - --replace_result 'Tables_in_INFORMATION_SCHEMA (T%)' 'Tables_in_information_schema (T%)' --sorted_result show tables from INFORMATION_SCHEMA like 'T%'; @@ -25,9 +15,10 @@ create database mbase; use `inf%`; show tables; -# -# Bug#18113 SELECT * FROM information_schema.xxx crashes server -# Bug#17204 second CALL to procedure crashes Server +--echo # +--echo # Bug#18113 SELECT * FROM information_schema.xxx crashes server +--echo # Bug#17204 second CALL to procedure crashes Server +--echo # # Crash happened when one selected data from one of INFORMATION_SCHEMA # tables and in order to build its contents server had to open view which # used stored function and table or view on which one had not global or @@ -89,9 +80,9 @@ drop procedure mbase.p1; drop database mbase; disconnect user1; -# -# Bug#18282 INFORMATION_SCHEMA.TABLES provides inconsistent info about invalid views -# +--echo # +--echo # Bug#18282 INFORMATION_SCHEMA.TABLES provides inconsistent info about invalid views +--echo # use test; create table t1 (i int); create function f1 () returns int return (select max(i) from t1); @@ -110,11 +101,10 @@ drop function f2; drop view v1, v2; --enable_view_protocol -# -# Bug#20543 select on information_schema strange warnings, view, different -# schemas/users -# -# +--echo # +--echo # Bug#20543 select on information_schema strange warnings, view, different +--echo # schemas/users +--echo # --disable_service_connection create database testdb_1; create user testdb_1@localhost; @@ -225,9 +215,9 @@ connection default; drop user testdb_1@localhost; drop user testdb_2@localhost; -# -# Bug#22763 Disrepancy between SHOW CREATE VIEW and I_S.VIEWS -# +--echo # +--echo # Bug#22763 Disrepancy between SHOW CREATE VIEW and I_S.VIEWS +--echo # create database testdb_1; create table testdb_1.t1 (a int); create view testdb_1.v1 as select * from testdb_1.t1; @@ -259,9 +249,9 @@ connection default; set global sql_mode=default; -# -# MDEV-20549 SQL SECURITY DEFINER does not work for INFORMATION_SCHEMA tables -# +--echo # +--echo # MDEV-20549 SQL SECURITY DEFINER does not work for INFORMATION_SCHEMA tables +--echo # create user foo@localhost; grant select on test.* to foo@localhost; @@ -303,3 +293,7 @@ drop view v1d, v1i, v2d, v2i, v3d, v3i, v4d, v4i, v5d, v5i; drop user foo@localhost; drop procedure rootonly; --enable_service_connection + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints.result b/mysql-test/suite/funcs_1/r/is_table_constraints.result index 73aa5e5633d..d306a83d15a 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints.result @@ -94,7 +94,6 @@ def mysql PRIMARY mysql transaction_registry ######################################################################################### # Testcase 3.2.7.2 + 3.2.7.3: INFORMATION_SCHEMA.TABLE_CONSTRAINTS accessible information ######################################################################################### -DROP DATABASE IF EXISTS db_datadict; CREATE DATABASE db_datadict; CREATE TABLE db_datadict.t1 (f1 BIGINT, f2 BIGINT, f3 BIGINT, f4 BIGINT, f5 BIGINT, f6 BIGINT, PRIMARY KEY (f1,f2)) @@ -104,7 +103,6 @@ CREATE UNIQUE INDEX my_idx2 ON db_datadict.t1(f3); CREATE TABLE db_datadict.t2 (f1 BIGINT, f2 BIGINT, f3 BIGINT, f4 BIGINT, f5 BIGINT, f6 BIGINT, PRIMARY KEY (f1,f2)) ENGINE = ; -DROP USER 'testuser1'@'localhost'; CREATE USER 'testuser1'@'localhost'; GRANT SELECT(f5) ON db_datadict.t1 TO 'testuser1'@'localhost'; SHOW GRANTS FOR 'testuser1'@'localhost'; @@ -158,8 +156,6 @@ DROP DATABASE db_datadict; ######################################################################################### # Testcase 3.2.1.13+3.2.1.14+3.2.1.15: INFORMATION_SCHEMA.TABLE_CONSTRAINTS modifications ######################################################################################### -DROP DATABASE IF EXISTS db_datadict; -DROP TABLE IF EXISTS test.t1_my_table; CREATE DATABASE db_datadict; SELECT table_name FROM information_schema.table_constraints WHERE table_name LIKE 't1_my_table%'; @@ -310,8 +306,6 @@ table_name # Testcases 3.2.1.3-3.2.1.5 + 3.2.1.8-3.2.1.12: INSERT/UPDATE/DELETE and # DDL on INFORMATION_SCHEMA tables are not supported ######################################################################## -DROP DATABASE IF EXISTS db_datadict; -DROP TABLE IF EXISTS db_datadict.t1; CREATE DATABASE db_datadict; CREATE TABLE db_datadict.t1 (f1 BIGINT, UNIQUE(f1)) ENGINE = ; diff --git a/mysql-test/suite/funcs_1/t/is_table_constraints.test b/mysql-test/suite/funcs_1/t/is_table_constraints.test index cf8d3fbf2d2..d841ae17789 100644 --- a/mysql-test/suite/funcs_1/t/is_table_constraints.test +++ b/mysql-test/suite/funcs_1/t/is_table_constraints.test @@ -36,7 +36,6 @@ eval SHOW TABLES FROM information_schema LIKE '$is_table'; # --source suite/funcs_1/datadict/is_table_query.inc - --echo ######################################################################### --echo # Testcase 3.2.10.1: INFORMATION_SCHEMA.TABLE_CONSTRAINTS layout --echo ######################################################################### @@ -85,9 +84,6 @@ ORDER BY constraint_schema, table_name, constraint_name; # mysql is_table_constraints_mysql # information_schema is_table_constraints_is # ---disable_warnings -DROP DATABASE IF EXISTS db_datadict; ---enable_warnings CREATE DATABASE db_datadict; --replace_result $engine_type eval @@ -102,8 +98,6 @@ CREATE TABLE db_datadict.t2 (f1 BIGINT, f2 BIGINT, f3 BIGINT, f4 BIGINT, f5 BIGINT, f6 BIGINT, PRIMARY KEY (f1,f2)) ENGINE = $engine_type; ---error 0,ER_CANNOT_USER -DROP USER 'testuser1'@'localhost'; CREATE USER 'testuser1'@'localhost'; GRANT SELECT(f5) ON db_datadict.t1 TO 'testuser1'@'localhost'; SHOW GRANTS FOR 'testuser1'@'localhost'; @@ -161,10 +155,6 @@ DROP DATABASE db_datadict; # automatically deletes all relevant information on that object from # every appropriate INFORMATION_SCHEMA table. # ---disable_warnings -DROP DATABASE IF EXISTS db_datadict; -DROP TABLE IF EXISTS test.t1_my_table; ---enable_warnings CREATE DATABASE db_datadict; SELECT table_name FROM information_schema.table_constraints @@ -281,10 +271,6 @@ WHERE table_name = 't1_my_tablex'; # 3.2.1.12: Ensure that no user may directly add to, alter, or delete any data # in an INFORMATION_SCHEMA table. # ---disable_warnings -DROP DATABASE IF EXISTS db_datadict; -DROP TABLE IF EXISTS db_datadict.t1; ---enable_warnings CREATE DATABASE db_datadict; --replace_result $engine_type eval diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 4c2d063b771..34011bf1a76 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -5210,6 +5210,13 @@ public: }; +ulong GRANT_INFO::all_privilege() +{ + return (grant_table_user ? grant_table_user->cols : 0) | + (grant_table_role ? grant_table_role->cols : 0) | privilege; +} + + void GRANT_NAME::set_user_details(const char *h, const char *d, const char *u, const char *t, bool is_routine) @@ -8227,9 +8234,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, if (!(~t_ref->grant.privilege & want_access)) continue; - if ((want_access&= ~((grant_table ? grant_table->cols : 0) | - (grant_table_role ? grant_table_role->cols : 0) | - t_ref->grant.privilege))) + if ((want_access&= ~t_ref->grant.all_privilege())) { goto err; // impossible } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1917daa2788..a178057a312 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -6778,10 +6778,8 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, if (show_table->file) { (void) read_statistics_for_tables(thd, tables); - show_table->file->info(HA_STATUS_VARIABLE | - HA_STATUS_NO_LOCK | - HA_STATUS_CONST | - HA_STATUS_TIME); + show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | + HA_STATUS_CONST | HA_STATUS_TIME); set_statistics_for_table(thd, show_table); } for (uint i=0 ; i < show_table->s->keys ; i++,key_info++) @@ -7108,14 +7106,10 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, TABLE *show_table= tables->table; KEY *key_info=show_table->s->key_info; uint primary_key= show_table->s->primary_key; - show_table->file->info(HA_STATUS_VARIABLE | - HA_STATUS_NO_LOCK | + show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); for (uint i=0 ; i < show_table->s->keys ; i++, key_info++) { - if (i != primary_key && !(key_info->flags & HA_NOSAME)) - continue; - if (i == primary_key && !strcmp(key_info->name.str, primary_key_name)) { if (store_constraints(thd, table, db_name, table_name, @@ -7133,16 +7127,14 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, } // Table check constraints - for ( uint i = 0; i < show_table->s->table_check_constraints; i++ ) + for (uint i = 0; i < show_table->s->table_check_constraints; i++) { - Virtual_column_info *check = show_table->check_constraints[ i ]; + Virtual_column_info *check = show_table->check_constraints[i]; - if ( store_constraints( thd, table, db_name, table_name, check->name.str, - check->name.length, - STRING_WITH_LEN( "CHECK" ) ) ) - { - DBUG_RETURN( 1 ); - } + if (store_constraints(thd, table, db_name, table_name, + check->name.str, check->name.length, + STRING_WITH_LEN("CHECK"))) + DBUG_RETURN(1); } show_table->file->get_foreign_key_list(thd, &f_key_list); @@ -7153,7 +7145,7 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, if (store_constraints(thd, table, db_name, table_name, f_key_info->foreign_id->str, strlen(f_key_info->foreign_id->str), - "FOREIGN KEY", 11)) + STRING_WITH_LEN("FOREIGN KEY"))) DBUG_RETURN(1); } } @@ -7284,8 +7276,7 @@ store_key_column_usage(TABLE *table, const LEX_CSTRING *db_name, } -static int get_schema_key_column_usage_record(THD *thd, - TABLE_LIST *tables, +static int get_schema_key_column_usage_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, const LEX_CSTRING *db_name, const LEX_CSTRING *table_name) @@ -7306,8 +7297,7 @@ static int get_schema_key_column_usage_record(THD *thd, TABLE *show_table= tables->table; KEY *key_info=show_table->s->key_info; uint primary_key= show_table->s->primary_key; - show_table->file->info(HA_STATUS_VARIABLE | - HA_STATUS_NO_LOCK | + show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); for (uint i=0 ; i < show_table->s->keys ; i++, key_info++) { @@ -7317,18 +7307,15 @@ static int get_schema_key_column_usage_record(THD *thd, KEY_PART_INFO *key_part= key_info->key_part; for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++) { - if (key_part->field) - { - f_idx++; - restore_record(table, s->default_values); - store_key_column_usage(table, db_name, table_name, - key_info->name.str, key_info->name.length, - key_part->field->field_name.str, - key_part->field->field_name.length, - (longlong) f_idx); - if (schema_table_store_record(thd, table)) - DBUG_RETURN(1); - } + f_idx++; + restore_record(table, s->default_values); + store_key_column_usage(table, db_name, table_name, + key_info->name.str, key_info->name.length, + key_part->field->field_name.str, + key_part->field->field_name.length, + (longlong) f_idx); + if (schema_table_store_record(thd, table)) + DBUG_RETURN(1); } } @@ -8189,8 +8176,7 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables, { List f_key_list; TABLE *show_table= tables->table; - show_table->file->info(HA_STATUS_VARIABLE | - HA_STATUS_NO_LOCK | + show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); show_table->file->get_foreign_key_list(thd, &f_key_list); diff --git a/sql/table.h b/sql/table.h index 1414659b78f..9b3d6062ec2 100644 --- a/sql/table.h +++ b/sql/table.h @@ -336,6 +336,9 @@ typedef struct st_grant_info ulong orig_want_privilege; /** The grant state for internal tables. */ GRANT_INTERNAL_INFO m_internal; + + /* OR table and all column privileges */ + ulong all_privilege(); } GRANT_INFO; enum tmp_table_type From 547dfc0e01bb5acbe070728706afb8a116b100e2 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 19 Oct 2023 17:02:37 +0200 Subject: [PATCH 100/158] MDEV-32500 Information schema leaks table names and structure to unauthorized users standard table KEY_COLUMN_USAGE should only show keys where a user has some privileges on every column of the key standard table TABLE_CONSTRAINTS should show tables where a user has any non-SELECT privilege on the table or on any column of the table standard table REFERENTIAL_CONSTRAINTS is defined in terms of TABLE_CONSTRAINTS, so the same rule applies. If the user has no rights to see the REFERENCED_TABLE_NAME value, it should be NULL SHOW INDEX (and STATISTICS table) is non-standard, but it seems reasonable to use the same logic as for KEY_COLUMN_USAGE. --- mysql-test/main/grant4.result | 1 - mysql-test/main/information_schema_db.result | 48 +++++- mysql-test/main/information_schema_db.test | 39 ++++- .../suite/funcs_1/r/is_columns_is.result | 2 +- .../funcs_1/r/is_columns_is_embedded.result | 2 +- .../suite/funcs_1/r/is_statistics.result | 4 - .../funcs_1/r/is_table_constraints.result | 11 +- .../suite/funcs_1/t/is_table_constraints.test | 2 +- sql/sql_parse.cc | 1 + sql/sql_show.cc | 144 +++++++++++++++++- 10 files changed, 229 insertions(+), 25 deletions(-) diff --git a/mysql-test/main/grant4.result b/mysql-test/main/grant4.result index a5873a4f8ac..1760f2a5d1f 100644 --- a/mysql-test/main/grant4.result +++ b/mysql-test/main/grant4.result @@ -101,7 +101,6 @@ ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table ** SHOW INDEX FROM t6 will succeed because there exist a privilege on a column combination on t6. SHOW INDEX FROM t6; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment -t6 1 i 1 s1 A NULL NULL NULL YES BTREE ** CHECK TABLE requires any privilege on any column combination and should succeed for t6: CHECK TABLE t6; Table Op Msg_type Msg_text diff --git a/mysql-test/main/information_schema_db.result b/mysql-test/main/information_schema_db.result index 2724272efb3..6fac8ea6fa4 100644 --- a/mysql-test/main/information_schema_db.result +++ b/mysql-test/main/information_schema_db.result @@ -262,8 +262,8 @@ set global sql_mode=default; create user foo@localhost; grant select on test.* to foo@localhost; create procedure rootonly() select 1; -create sql security definer view v1d as select current_user(),user from information_schema.processlist; -create sql security invoker view v1i as select current_user(),user from information_schema.processlist; +create sql security definer view v1d as select current_user(),user from information_schema.processlist where command!='daemon'; +create sql security invoker view v1i as select current_user(),user from information_schema.processlist where command!='daemon'; create sql security definer view v2d as select table_name from information_schema.tables where table_schema='mysql' and table_name like '%user%'; create sql security invoker view v2i as select table_name from information_schema.tables where table_schema='mysql' and table_name like '%user%'; create sql security definer view v3d as select schema_name from information_schema.schemata where schema_name like '%mysql%'; @@ -341,3 +341,47 @@ drop procedure rootonly; # # End of 10.2 tests # +# +# MDEV-32500 Information schema leaks table names and structure to unauthorized users +# +create database db; +create table db.t1 (x int, key(x)) engine=InnoDB; +create table db.t2 (a int, b int, c int, unique(b), check(c>b), foreign key(c) references db.t1(x)) engine=InnoDB; +create table db.t3 (d int, e int, f int, unique(e), check(f>e), foreign key(f) references db.t1(x), +foreign key(e) references db.t2(b), +foreign key(d) references db.t3(f) +) engine=InnoDB; +create user u@localhost; +grant select (a) on db.t2 to u@localhost; +grant update (d) on db.t3 to u@localhost; +connect con1,localhost,u,,db; +select table_name, column_name from information_schema.columns where table_name like 't_'; +table_name column_name +t2 a +t3 d +select table_name, column_name from information_schema.key_column_usage where table_name like 't_'; +table_name column_name +select table_name, unique_constraint_name, referenced_table_name from information_schema.referential_constraints where table_name like 't_'; +table_name unique_constraint_name referenced_table_name +t3 x NULL +t3 b NULL +t3 f t3 +select table_name, constraint_name, constraint_type from information_schema.table_constraints where table_name like 't_'; +table_name constraint_name constraint_type +t3 e UNIQUE +t3 CONSTRAINT_1 CHECK +t3 t3_ibfk_1 FOREIGN KEY +t3 t3_ibfk_2 FOREIGN KEY +t3 t3_ibfk_3 FOREIGN KEY +show index in t2; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +show index in t3; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t3 1 d 1 d A 0 NULL NULL YES BTREE +disconnect con1; +connection default; +drop user u@localhost; +drop database db; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/information_schema_db.test b/mysql-test/main/information_schema_db.test index 229ab0bfac0..4d5b9373af6 100644 --- a/mysql-test/main/information_schema_db.test +++ b/mysql-test/main/information_schema_db.test @@ -1,7 +1,7 @@ # this test mostly test privilege control (what doesn't work # in the embedded server by default). So skip the test in embedded-server mode. -- source include/not_embedded.inc - +-- source include/have_innodb.inc -- source include/testdb_only.inc set local sql_mode=""; @@ -256,8 +256,8 @@ set global sql_mode=default; create user foo@localhost; grant select on test.* to foo@localhost; create procedure rootonly() select 1; -create sql security definer view v1d as select current_user(),user from information_schema.processlist; -create sql security invoker view v1i as select current_user(),user from information_schema.processlist; +create sql security definer view v1d as select current_user(),user from information_schema.processlist where command!='daemon'; +create sql security invoker view v1i as select current_user(),user from information_schema.processlist where command!='daemon'; create sql security definer view v2d as select table_name from information_schema.tables where table_schema='mysql' and table_name like '%user%'; create sql security invoker view v2i as select table_name from information_schema.tables where table_schema='mysql' and table_name like '%user%'; create sql security definer view v3d as select schema_name from information_schema.schemata where schema_name like '%mysql%'; @@ -297,3 +297,36 @@ drop procedure rootonly; --echo # --echo # End of 10.2 tests --echo # + +--echo # +--echo # MDEV-32500 Information schema leaks table names and structure to unauthorized users +--echo # +create database db; +create table db.t1 (x int, key(x)) engine=InnoDB; +create table db.t2 (a int, b int, c int, unique(b), check(c>b), foreign key(c) references db.t1(x)) engine=InnoDB; +create table db.t3 (d int, e int, f int, unique(e), check(f>e), foreign key(f) references db.t1(x), + foreign key(e) references db.t2(b), + foreign key(d) references db.t3(f) + ) engine=InnoDB; + +create user u@localhost; +grant select (a) on db.t2 to u@localhost; +grant update (d) on db.t3 to u@localhost; + +--connect con1,localhost,u,,db +--sorted_result +select table_name, column_name from information_schema.columns where table_name like 't_'; +select table_name, column_name from information_schema.key_column_usage where table_name like 't_'; +select table_name, unique_constraint_name, referenced_table_name from information_schema.referential_constraints where table_name like 't_'; +select table_name, constraint_name, constraint_type from information_schema.table_constraints where table_name like 't_'; +show index in t2; +show index in t3; + +--disconnect con1 +--connection default +drop user u@localhost; +drop database db; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/suite/funcs_1/r/is_columns_is.result b/mysql-test/suite/funcs_1/r/is_columns_is.result index 910a86b31f0..50c16b54976 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is.result @@ -287,7 +287,7 @@ def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_NAME 3 NULL NO varchar def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL def information_schema REFERENTIAL_CONSTRAINTS DELETE_RULE 9 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL def information_schema REFERENTIAL_CONSTRAINTS MATCH_OPTION 7 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS REFERENCED_TABLE_NAME 11 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS REFERENCED_TABLE_NAME 11 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL def information_schema REFERENTIAL_CONSTRAINTS TABLE_NAME 10 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_CATALOG 4 NULL NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_NAME 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL diff --git a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result index 80865e6347d..7b6da4e23c0 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result @@ -287,7 +287,7 @@ def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_NAME 3 NULL NO varchar def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL def information_schema REFERENTIAL_CONSTRAINTS DELETE_RULE 9 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL def information_schema REFERENTIAL_CONSTRAINTS MATCH_OPTION 7 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema REFERENTIAL_CONSTRAINTS REFERENCED_TABLE_NAME 11 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema REFERENTIAL_CONSTRAINTS REFERENCED_TABLE_NAME 11 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL def information_schema REFERENTIAL_CONSTRAINTS TABLE_NAME 10 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_CATALOG 4 NULL NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL def information_schema REFERENTIAL_CONSTRAINTS UNIQUE_CONSTRAINT_NAME 6 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL diff --git a/mysql-test/suite/funcs_1/r/is_statistics.result b/mysql-test/suite/funcs_1/r/is_statistics.result index 715304ef0ec..aeee7595ffb 100644 --- a/mysql-test/suite/funcs_1/r/is_statistics.result +++ b/mysql-test/suite/funcs_1/r/is_statistics.result @@ -250,8 +250,6 @@ ORDER BY table_schema,table_name,index_name,seq_in_index,column_name; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLUMN_NAME COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT INDEX_COMMENT def db_datadict t1 1 db_datadict f2_ind 1 f2 NULL 0 NULL NULL YES HASH def db_datadict t1 0 db_datadict PRIMARY 1 f1 NULL 0 NULL NULL HASH -def db_datadict_2 t3 1 db_datadict_2 f2f1_ind 1 f2 NULL NULL NULL NULL YES HASH -def db_datadict_2 t3 1 db_datadict_2 f2f1_ind 2 f1 NULL 0 NULL NULL HASH def db_datadict_2 t3 0 db_datadict_2 f5 1 f5 NULL 0 NULL NULL YES HASH def db_datadict_2 t3 0 db_datadict_2 PRIMARY 1 f1 NULL 0 NULL NULL HASH SHOW GRANTS FOR 'testuser1'@'localhost'; @@ -282,8 +280,6 @@ SELECT * FROM information_schema.statistics WHERE table_schema LIKE 'db_datadict%' ORDER BY table_schema,table_name,index_name,seq_in_index,column_name; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLUMN_NAME COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT INDEX_COMMENT -def db_datadict_2 t3 1 db_datadict_2 f2f1_ind 1 f2 NULL NULL NULL NULL YES HASH -def db_datadict_2 t3 1 db_datadict_2 f2f1_ind 2 f1 NULL 0 NULL NULL HASH def db_datadict_2 t3 0 db_datadict_2 f5 1 f5 NULL 0 NULL NULL YES HASH def db_datadict_2 t3 0 db_datadict_2 PRIMARY 1 f1 NULL 0 NULL NULL HASH SHOW GRANTS FOR 'testuser1'@'localhost'; diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints.result b/mysql-test/suite/funcs_1/r/is_table_constraints.result index d306a83d15a..9d205dcdee3 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints.result @@ -104,11 +104,11 @@ CREATE TABLE db_datadict.t2 (f1 BIGINT, f2 BIGINT, f3 BIGINT, f4 BIGINT, f5 BIGINT, f6 BIGINT, PRIMARY KEY (f1,f2)) ENGINE = ; CREATE USER 'testuser1'@'localhost'; -GRANT SELECT(f5) ON db_datadict.t1 TO 'testuser1'@'localhost'; +GRANT SELECT(f5), UPDATE(f6) ON db_datadict.t1 TO 'testuser1'@'localhost'; SHOW GRANTS FOR 'testuser1'@'localhost'; Grants for testuser1@localhost GRANT USAGE ON *.* TO `testuser1`@`localhost` -GRANT SELECT (`f5`) ON `db_datadict`.`t1` TO `testuser1`@`localhost` +GRANT SELECT (`f5`), UPDATE (`f6`) ON `db_datadict`.`t1` TO `testuser1`@`localhost` SELECT * FROM information_schema.table_constraints WHERE table_schema = 'db_datadict' ORDER BY table_schema,table_name, constraint_name; @@ -132,7 +132,7 @@ connect testuser1, localhost, testuser1, , db_datadict; SHOW GRANTS FOR 'testuser1'@'localhost'; Grants for testuser1@localhost GRANT USAGE ON *.* TO `testuser1`@`localhost` -GRANT SELECT (`f5`) ON `db_datadict`.`t1` TO `testuser1`@`localhost` +GRANT SELECT (`f5`), UPDATE (`f6`) ON `db_datadict`.`t1` TO `testuser1`@`localhost` SELECT * FROM information_schema.table_constraints WHERE table_schema = 'db_datadict' ORDER BY table_schema,table_name, constraint_name; @@ -142,11 +142,6 @@ def db_datadict my_idx2 db_datadict t1 UNIQUE def db_datadict PRIMARY db_datadict t1 PRIMARY KEY SHOW INDEXES FROM db_datadict.t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment -t1 0 PRIMARY 1 f1 ### ### ### ### ### ### ### -t1 0 PRIMARY 2 f2 ### ### ### ### ### ### ### -t1 0 my_idx1 1 f6 ### ### ### ### ### ### ### -t1 0 my_idx1 2 f1 ### ### ### ### ### ### ### -t1 0 my_idx2 1 f3 ### ### ### ### ### ### ### SHOW INDEXES FROM db_datadict.t2; ERROR 42000: SELECT command denied to user 'testuser1'@'localhost' for table `db_datadict`.`t2` connection default; diff --git a/mysql-test/suite/funcs_1/t/is_table_constraints.test b/mysql-test/suite/funcs_1/t/is_table_constraints.test index d841ae17789..b4d550fc3b2 100644 --- a/mysql-test/suite/funcs_1/t/is_table_constraints.test +++ b/mysql-test/suite/funcs_1/t/is_table_constraints.test @@ -99,7 +99,7 @@ CREATE TABLE db_datadict.t2 (f1 BIGINT, f2 BIGINT, f3 BIGINT, f4 BIGINT, ENGINE = $engine_type; CREATE USER 'testuser1'@'localhost'; -GRANT SELECT(f5) ON db_datadict.t1 TO 'testuser1'@'localhost'; +GRANT SELECT(f5), UPDATE(f6) ON db_datadict.t1 TO 'testuser1'@'localhost'; SHOW GRANTS FOR 'testuser1'@'localhost'; let $my_select = SELECT * FROM information_schema.table_constraints diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c13637a3cfd..ffba37b84a7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7011,6 +7011,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) FALSE, FALSE)) return TRUE; /* Access denied */ + thd->col_access= dst_table->grant.privilege; // for sql_show.cc /* Check_grant will grant access if there is any column privileges on all of the tables thanks to the fourth parameter (bool show_table). diff --git a/sql/sql_show.cc b/sql/sql_show.cc index a178057a312..7d549c653f2 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -6782,6 +6782,21 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, HA_STATUS_CONST | HA_STATUS_TIME); set_statistics_for_table(thd, show_table); } + +#ifndef NO_EMBEDDED_ACCESS_CHECKS + bool need_column_checks= false; + /* we know that the table or at least some of the columns have + necessary privileges, but the caller didn't pass down the GRANT_INFO + object, so we have to rediscover everything again :( */ + if (!(thd->col_access & TABLE_ACLS)) + { + check_grant(thd, SELECT_ACL, tables, 0, 1, 1); + + if (!(tables->grant.privilege & TABLE_ACLS)) + need_column_checks= true; + } +#endif + for (uint i=0 ; i < show_table->s->keys ; i++,key_info++) { if ((key_info->flags & HA_INVISIBLE_KEY) && @@ -6790,6 +6805,26 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, KEY_PART_INFO *key_part= key_info->key_part; LEX_CSTRING *str; LEX_CSTRING unknown= {STRING_WITH_LEN("?unknown field?") }; + +#ifndef NO_EMBEDDED_ACCESS_CHECKS + if (need_column_checks) + { + uint j; + for (j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++) + { + uint access= get_column_grant(thd, &tables->grant, db_name->str, + table_name->str, + key_part->field->field_name.str); + + if (!access) + break; + } + if (j != key_info->user_defined_key_parts) + continue; + key_part= key_info->key_part; + } +#endif + for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++) { if (key_part->field->invisible >= INVISIBLE_SYSTEM && @@ -7102,6 +7137,21 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, } else if (!tables->view) { +#ifndef NO_EMBEDDED_ACCESS_CHECKS + /* need any non-SELECT privilege on the table or any of its columns */ + const ulong need= TABLE_ACLS & ~SELECT_ACL; + if (!(thd->col_access & need)) + { + /* we know that the table or at least some of the columns have + necessary privileges, but the caller didn't pass down the GRANT_INFO + object, so we have to rediscover everything again :( */ + check_grant(thd, SELECT_ACL, tables, 0, 1, 1); + + if (!(tables->grant.all_privilege() & need)) + DBUG_RETURN(0); + } +#endif + List f_key_list; TABLE *show_table= tables->table; KEY *key_info=show_table->s->key_info; @@ -7299,12 +7349,46 @@ static int get_schema_key_column_usage_record(THD *thd, TABLE_LIST *tables, uint primary_key= show_table->s->primary_key; show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); + +#ifndef NO_EMBEDDED_ACCESS_CHECKS + bool need_column_checks= false; + /* we know that the table or at least some of the columns have + necessary privileges, but the caller didn't pass down the GRANT_INFO + object, so we have to rediscover everything again :( */ + if (!(thd->col_access & TABLE_ACLS)) + { + check_grant(thd, SELECT_ACL, tables, 0, 1, 1); + + if (!(tables->grant.privilege & TABLE_ACLS)) + need_column_checks= true; + } +#endif + for (uint i=0 ; i < show_table->s->keys ; i++, key_info++) { if (i != primary_key && !(key_info->flags & HA_NOSAME)) continue; uint f_idx= 0; KEY_PART_INFO *key_part= key_info->key_part; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + if (need_column_checks) + { + uint j; + for (j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++) + { + uint access= get_column_grant(thd, &tables->grant, db_name->str, + table_name->str, + key_part->field->field_name.str); + + if (!access) + break; + } + if (j != key_info->user_defined_key_parts) + continue; + key_part= key_info->key_part; + } +#endif + for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++) { f_idx++; @@ -7329,6 +7413,23 @@ static int get_schema_key_column_usage_record(THD *thd, TABLE_LIST *tables, List_iterator_fast it(f_key_info->foreign_fields), it1(f_key_info->referenced_fields); uint f_idx= 0; + +#ifndef NO_EMBEDDED_ACCESS_CHECKS + if (need_column_checks) + { + while ((r_info= it1++)) + { + uint access= get_column_grant(thd, &tables->grant, db_name->str, + table_name->str, r_info->str); + + if (!access) + break; + } + if (!it1.at_end()) + continue; + it1.rewind(); + } +#endif while ((f_info= it++)) { r_info= it1++; @@ -8179,6 +8280,21 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables, show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); +#ifndef NO_EMBEDDED_ACCESS_CHECKS + /* need any non-SELECT privilege on the table or any of its columns */ + const ulong need= TABLE_ACLS & ~SELECT_ACL; + if (!(thd->col_access & need)) + { + /* we know that the table or at least some of the columns have + necessary privileges, but the caller didn't pass down the GRANT_INFO + object, so we have to rediscover everything again :( */ + check_grant(thd, SELECT_ACL, tables, 0, 1, 1); + + if (!(tables->grant.all_privilege() & need)) + DBUG_RETURN(0); + } +#endif + show_table->file->get_foreign_key_list(thd, &f_key_list); FOREIGN_KEY_INFO *f_key_info; List_iterator_fast it(f_key_list); @@ -8193,8 +8309,28 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables, table->field[3]->store(STRING_WITH_LEN("def"), cs); table->field[4]->store(f_key_info->referenced_db->str, f_key_info->referenced_db->length, cs); - table->field[10]->store(f_key_info->referenced_table->str, - f_key_info->referenced_table->length, cs); + bool show_ref_table= true; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + /* need any non-SELECT privilege on the table or any of its columns */ + if (!(thd->col_access & need)) + { + TABLE_LIST table_acl_check; + bzero((char*) &table_acl_check, sizeof(table_acl_check)); + table_acl_check.db= *f_key_info->referenced_db; + table_acl_check.table_name= *f_key_info->referenced_table; + table_acl_check.grant.privilege= thd->col_access; + check_grant(thd, SELECT_ACL, &table_acl_check, 0, 1, 1); + + if (!(table_acl_check.grant.all_privilege() & need)) + show_ref_table= false; + } +#endif + if (show_ref_table) + { + table->field[10]->set_notnull(); + table->field[10]->store(f_key_info->referenced_table->str, + f_key_info->referenced_table->length, cs); + } if (f_key_info->referenced_key_name) { table->field[5]->store(f_key_info->referenced_key_name->str, @@ -9898,8 +10034,8 @@ ST_FIELD_INFO referential_constraints_fields_info[]= {"UPDATE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, {"DELETE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, - {"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, - OPEN_FULL_TABLE}, + {"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, + MY_I_S_MAYBE_NULL, 0, OPEN_FULL_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; From 082aea7742455246fdcfd112a392b78c793dfebc Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 21 Oct 2023 17:33:29 +0200 Subject: [PATCH 101/158] MDEV-31112 vcol circular references lead to stack overflow --- mysql-test/suite/vcol/r/vcol_misc.result | 11 +++++++++++ mysql-test/suite/vcol/t/vcol_misc.test | 13 +++++++++++++ sql/item.cc | 7 ++++--- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result index 0a86d68b3ad..8038f18ffc7 100644 --- a/mysql-test/suite/vcol/r/vcol_misc.result +++ b/mysql-test/suite/vcol/r/vcol_misc.result @@ -569,3 +569,14 @@ drop table t1; # # End of 10.3 tests # +# +# MDEV-31112 vcol circular references lead to stack overflow +# +create table t (a int, c int as (a)); +alter table t alter column c drop default; +alter table t modify column a int as (c) stored; +ERROR 01000: Expression for field `a` is referring to uninitialized field `c` +drop table t; +# +# End of 10.4 tests +# diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test index f696d5d5814..3bbed408f6f 100644 --- a/mysql-test/suite/vcol/t/vcol_misc.test +++ b/mysql-test/suite/vcol/t/vcol_misc.test @@ -536,3 +536,16 @@ drop table t1; --echo # --echo # End of 10.3 tests --echo # + +--echo # +--echo # MDEV-31112 vcol circular references lead to stack overflow +--echo # +create table t (a int, c int as (a)); +alter table t alter column c drop default; +--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD +alter table t modify column a int as (c) stored; +drop table t; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/item.cc b/sql/item.cc index f9d8ac490ae..34272156aad 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -908,14 +908,15 @@ bool Item_field::register_field_in_write_map(void *arg) This is used by fix_vcol_expr() when a table is opened - We don't have to check fields that are marked as NO_DEFAULT_VALUE - as the upper level will ensure that all these will be given a value. + We don't have to check non-virtual fields that are marked as + NO_DEFAULT_VALUE as the upper level will ensure that all these + will be given a value. */ bool Item_field::check_field_expression_processor(void *arg) { Field *org_field= (Field*) arg; - if (field->flags & NO_DEFAULT_VALUE_FLAG) + if (field->flags & NO_DEFAULT_VALUE_FLAG && !field->vcol_info) return 0; if ((field->default_value && field->default_value->flags) || field->vcol_info) { From b00fd50fd8cf64f2cd3c94af785e125e431a8e35 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 21 Oct 2023 19:18:39 +0200 Subject: [PATCH 102/158] MDEV-32541 Assertion `!(thd->server_status & (1U | 8192U))' failed in MDL_context::release_transactional_locks SERVER_STATUS_IN_TRANS_READONLY should never be set without SERVER_STATUS_IN_TRANS. They're set together, must be removed together. --- mysql-test/suite/sql_sequence/other.result | 30 +++++++++++++++++++ mysql-test/suite/sql_sequence/other.test | 35 ++++++++++++++++++++++ sql/transaction.cc | 2 +- sql/wsrep_high_priority_service.cc | 2 +- 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/sql_sequence/other.result b/mysql-test/suite/sql_sequence/other.result index 8ac766702d3..930401616df 100644 --- a/mysql-test/suite/sql_sequence/other.result +++ b/mysql-test/suite/sql_sequence/other.result @@ -359,4 +359,34 @@ Note 4092 Unknown VIEW: 'test.s' DROP VIEW v1; DROP SEQUENCE s; DROP TABLE t; +# # End of 10.3 tests +# +# +# MDEV-32541 Assertion `!(thd->server_status & (1U | 8192U))' failed in MDL_context::release_transactional_locks +# +create sequence s1; +create sequence s2; +connect con1,localhost,root,,; +set session transaction read only; +start transaction; +connection default; +start transaction; +insert into s2 values (1, 1, 10000, 100, 1, 1000, 0, 0); +connection con1; +select lastval(s1); +lastval(s1) +NULL +select lastval(s2);; +connection default; +set lock_wait_timeout= 1; +insert into s1 values (1, 1, 10000, 100, 1, 1000, 0, 0); +connection con1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +disconnect con1; +connection default; +drop sequence s1; +drop sequence s2; +# +# End of 10.4 tests +# diff --git a/mysql-test/suite/sql_sequence/other.test b/mysql-test/suite/sql_sequence/other.test index a811853751a..48db1578ec7 100644 --- a/mysql-test/suite/sql_sequence/other.test +++ b/mysql-test/suite/sql_sequence/other.test @@ -387,4 +387,39 @@ DROP VIEW IF EXISTS s; DROP VIEW v1; DROP SEQUENCE s; DROP TABLE t; +--echo # --echo # End of 10.3 tests +--echo # + +--echo # +--echo # MDEV-32541 Assertion `!(thd->server_status & (1U | 8192U))' failed in MDL_context::release_transactional_locks +--echo # +create sequence s1; +create sequence s2; +--connect (con1,localhost,root,,) +set session transaction read only; +start transaction; + +--connection default +start transaction; +insert into s2 values (1, 1, 10000, 100, 1, 1000, 0, 0); + +--connection con1 +select lastval(s1); +--send select lastval(s2); + +--connection default +set lock_wait_timeout= 1; +insert into s1 values (1, 1, 10000, 100, 1, 1000, 0, 0); + +--connection con1 +--error ER_LOCK_DEADLOCK +--reap +--disconnect con1 +--connection default +drop sequence s1; +drop sequence s2; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/transaction.cc b/sql/transaction.cc index e98672eaa9d..2ccb05a9aec 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -383,7 +383,7 @@ bool trans_rollback_implicit(THD *thd) */ DBUG_ASSERT(thd->transaction.stmt.is_empty() && !thd->in_sub_stmt); - thd->server_status&= ~SERVER_STATUS_IN_TRANS; + thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); res= ha_rollback_trans(thd, true); /* diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc index 4874da51673..d1e58ed5bad 100644 --- a/sql/wsrep_high_priority_service.cc +++ b/sql/wsrep_high_priority_service.cc @@ -45,7 +45,7 @@ public: , m_server_status(thd->server_status) { m_thd->variables.option_bits&= ~OPTION_BEGIN; - m_thd->server_status&= ~SERVER_STATUS_IN_TRANS; + m_thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); m_thd->wsrep_cs().enter_toi_mode(ws_meta); } ~Wsrep_non_trans_mode() From 78cd45b29a7256ca4dbcd819e553b7ecdf561874 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 23 Oct 2023 12:15:46 +0200 Subject: [PATCH 103/158] ./mtr --skip-not-found New mtr option --skip-not-found makes it to show not found tests as skipped main.a [ skipped ] not found (but only if the test was specified with the suite name) and not error out early with mysql-test-run: *** ERROR: Could not find 'a' in 'main' suite This is useful in buildbot, on builders that generate the list of tests dynamically. --- mysql-test/lib/mtr_cases.pm | 12 +++++++++++- mysql-test/mysql-test-run.pl | 4 ++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 20baf24c9d6..a4473a07e81 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -154,7 +154,17 @@ sub collect_test_cases ($$$$) { { push (@$cases, @this_case); } - else + elsif ($::opt_skip_not_found) + { + push @$cases, My::Test->new + ( + name => "$sname.$tname", + shortname => $tname, + skip => 1, + comment => 'not found', + ); + } + else { mtr_error("Could not find '$tname' in '$sname' suite"); } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 6f3ff7144c8..11c11f400d2 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -259,6 +259,7 @@ sub using_extern { return (keys %opts_extern > 0);}; our $opt_fast= 0; our $opt_force= 0; +our $opt_skip_not_found= 0; our $opt_mem= $ENV{'MTR_MEM'}; our $opt_clean_vardir= $ENV{'MTR_CLEAN_VARDIR'}; @@ -1158,6 +1159,7 @@ sub command_line_setup { # Control what test suites or cases to run 'force+' => \$opt_force, + 'skip-not-found' => \$opt_skip_not_found, 'suite|suites=s' => \$opt_suites, 'skip-rpl' => \&collect_option, 'skip-test=s' => \&collect_option, @@ -5802,6 +5804,8 @@ Options to control what test suites or cases to run the execution will continue from the next test file. When specified twice, execution will continue executing the failed test file from the next command. + skip-not-found It is not an error if a test was not found in a + specified test suite. Test will be marked as skipped. do-test=PREFIX or REGEX Run test cases which name are prefixed with PREFIX or fulfills REGEX From 951775516522a3579c1fb83c97fd807ddebc48d1 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 23 Oct 2023 12:18:56 +0200 Subject: [PATCH 104/158] remove ./mtr --skip-im it did nothing for 14 years --- mysql-test/mysql-test-run.pl | 9 --------- 1 file changed, 9 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 11c11f400d2..cdd8f0bf6cd 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1063,13 +1063,6 @@ sub run_worker ($) { } -sub ignore_option { - my ($opt, $value)= @_; - mtr_report("Ignoring option '$opt'"); -} - - - # Setup any paths that are $opt_vardir related sub set_vardir { ($opt_vardir)= @_; @@ -1168,8 +1161,6 @@ sub command_line_setup { 'big-test+' => \$opt_big_test, 'combination=s' => \@opt_combinations, 'experimental=s' => \@opt_experimentals, - # skip-im is deprecated and silently ignored - 'skip-im' => \&ignore_option, 'staging-run' => \$opt_staging_run, # Specify ports From c5f776e9fa40d4543ecc0d07f847b9cc18a85e84 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 27 Sep 2023 14:39:03 -0600 Subject: [PATCH 105/158] MDEV-32265: seconds_behind_master is inaccurate for Delayed replication If a replica is actively delaying a transaction when restarted (STOP SLAVE/START SLAVE), when the sql thread is back up, Seconds_Behind_Master will present as 0 until the configured MASTER_DELAY has passed. That is, before the restart, last_master_timestamp is updated to the timestamp of the delayed event. Then after the restart, the negation of sql_thread_caught_up is skipped because the timestamp of the event has already been used for the last_master_timestamp, and their update is grouped together in the same conditional block. This patch fixes this by separating the negation of sql_thread_caught_up out of the timestamp-dependent block, so it is called any time an idle parallel slave queues an event to a worker. Note that sql_thread_caught_up is still left in the check for internal events, as SBM should remain idle in such case to not "magically" begin incrementing. Reviewed By: ============ Andrei Elkin --- .../suite/rpl/r/rpl_parallel_sbm.result | 13 ++++++--- mysql-test/suite/rpl/t/rpl_parallel_sbm.test | 29 +++++++++++++++---- sql/slave.cc | 2 +- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_parallel_sbm.result b/mysql-test/suite/rpl/r/rpl_parallel_sbm.result index f3cc8454510..7990a663f04 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_sbm.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_sbm.result @@ -15,9 +15,6 @@ create table t2 (a int); include/sync_slave_sql_with_master.inc # # Pt 1) Ensure SBM is updated immediately upon arrival of the next event -# Lock t1 on slave so the first received transaction does not complete/commit -connection slave; -LOCK TABLES t1 WRITE; connection master; # Sleep 2 to allow a buffer between events for SBM check insert into t1 values (0); @@ -26,8 +23,16 @@ connection slave; # Waiting for transaction to arrive on slave and begin SQL Delay.. # Validating SBM is updated on event arrival.. # ..done +# MDEV-32265. At time of STOP SLAVE, if the SQL Thread is currently +# delaying a transaction; then when the reciprocal START SLAVE occurs, +# if the event is still to be delayed, SBM should resume accordingly +include/stop_slave.inc +include/start_slave.inc connection slave; -UNLOCK TABLES; +# Waiting for replica to resume the delay for the transaction +# Sleeping 1s to increment SBM +# Ensuring Seconds_Behind_Master increases after sleeping.. +# ..done include/sync_with_master_gtid.inc # # Pt 2) If the worker threads have not entered an idle state, ensure diff --git a/mysql-test/suite/rpl/t/rpl_parallel_sbm.test b/mysql-test/suite/rpl/t/rpl_parallel_sbm.test index e738f55e7ec..58c0db15e47 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_sbm.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_sbm.test @@ -36,10 +36,6 @@ create table t2 (a int); --echo # --echo # Pt 1) Ensure SBM is updated immediately upon arrival of the next event ---echo # Lock t1 on slave so the first received transaction does not complete/commit ---connection slave -LOCK TABLES t1 WRITE; - --connection master --echo # Sleep 2 to allow a buffer between events for SBM check sleep 2; @@ -65,8 +61,31 @@ if (`SELECT $sbm_trx1_arrive > ($seconds_since_idling + 1)`) } --echo # ..done + +--echo # MDEV-32265. At time of STOP SLAVE, if the SQL Thread is currently +--echo # delaying a transaction; then when the reciprocal START SLAVE occurs, +--echo # if the event is still to be delayed, SBM should resume accordingly + +--source include/stop_slave.inc +--source include/start_slave.inc + --connection slave -UNLOCK TABLES; +--echo # Waiting for replica to resume the delay for the transaction +--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Waiting until MASTER_DELAY seconds after master executed event'; +--source include/wait_condition.inc + +--echo # Sleeping 1s to increment SBM +sleep 1; + +--echo # Ensuring Seconds_Behind_Master increases after sleeping.. +--let $sbm_trx1_after_1s_sleep= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1) +if (`SELECT $sbm_trx1_after_1s_sleep <= $sbm_trx1_arrive`) +{ + --echo # ..failed + --die Seconds_Behind_Master did not increase after sleeping, but should have +} +--echo # ..done + --source include/sync_with_master_gtid.inc --echo # diff --git a/sql/slave.cc b/sql/slave.cc index 44fcb93a3a9..3b9b5d6a83b 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4249,8 +4249,8 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, if (rli->last_master_timestamp < ev->when) { rli->last_master_timestamp= ev->when; - rli->sql_thread_caught_up= false; } + rli->sql_thread_caught_up= false; } int res= rli->parallel.do_event(serial_rgi, ev, event_size); From 09e237088c78d698ce22e4c6043a730401b1f078 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 28 Apr 2023 16:13:38 +0400 Subject: [PATCH 106/158] MDEV-31184 Remove parser tokens DECODE_MARIADB_SYM and DECODE_ORACLE_SYM Changing the code handling sql_mode-dependent function DECODE(): - removing parser tokens DECODE_MARIADB_SYM and DECODE_ORACLE_SYM - removing the DECODE() related code from sql_yacc.yy/sql_yacc_ora.yy - adding handling of DECODE() with help of a new Create_func_func_decode --- mysql-test/main/func_str.result | 12 +++++ mysql-test/main/func_str.test | 13 +++++ .../suite/compat/oracle/r/func_decode.result | 8 +-- .../suite/compat/oracle/t/func_decode.test | 8 +-- sql/item_create.cc | 53 ++++++++++++++----- sql/lex.h | 1 - sql/sql_lex.cc | 1 - sql/sql_yacc.yy | 36 ------------- sql/sql_yacc_ora.yy | 36 ------------- 9 files changed, 72 insertions(+), 96 deletions(-) diff --git a/mysql-test/main/func_str.result b/mysql-test/main/func_str.result index 4e36acd25ca..38c0ed03f42 100644 --- a/mysql-test/main/func_str.result +++ b/mysql-test/main/func_str.result @@ -5270,5 +5270,17 @@ SELECT GROUP_CONCAT( UpdateXML( 'new year', '/a', '2019-01-01 00:00:00' ) f 2019-01-01 00:00:00F}^i # +# MDEV-31184 Remove parser tokens DECODE_MARIADB_SYM and DECODE_ORACLE_SYM +# +SELECT DECODE(); +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE' +SELECT DECODE(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE' +SELECT DECODE(NULL,NULL); +DECODE(NULL,NULL) +NULL +SELECT DECODE(NULL, NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE' +# # End of 10.4 tests # diff --git a/mysql-test/main/func_str.test b/mysql-test/main/func_str.test index f99a1d912e8..5f9b6498de2 100644 --- a/mysql-test/main/func_str.test +++ b/mysql-test/main/func_str.test @@ -2292,6 +2292,19 @@ DROP TABLE t1,t2; SELECT GROUP_CONCAT( UpdateXML( 'new year', '/a', '2019-01-01 00:00:00' ), ENCODE('text','pass') ) AS f; +--echo # +--echo # MDEV-31184 Remove parser tokens DECODE_MARIADB_SYM and DECODE_ORACLE_SYM +--echo # + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT DECODE(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT DECODE(NULL); +SELECT DECODE(NULL,NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT DECODE(NULL, NULL, NULL); + + --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/suite/compat/oracle/r/func_decode.result b/mysql-test/suite/compat/oracle/r/func_decode.result index b49bad93627..2809e971be3 100644 --- a/mysql-test/suite/compat/oracle/r/func_decode.result +++ b/mysql-test/suite/compat/oracle/r/func_decode.result @@ -1,8 +1,8 @@ SET sql_mode=ORACLE; SELECT DECODE(10); -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 ')' at line 1 +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE' SELECT DECODE(10,10); -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 ')' at line 1 +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE' SELECT DECODE(10,10,'x10'); DECODE(10,10,'x10') x10 @@ -35,9 +35,9 @@ DROP TABLE decode; # MDEV-13863 sql_mode=ORACLE: DECODE does not treat two NULLs as equivalent # SELECT DECODE(10); -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 ')' at line 1 +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE' SELECT DECODE(10,10); -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 ')' at line 1 +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE' SELECT DECODE_ORACLE(10); ERROR 42000: Incorrect parameter count in the call to native function 'DECODE_ORACLE' SELECT DECODE_ORACLE(10,10); diff --git a/mysql-test/suite/compat/oracle/t/func_decode.test b/mysql-test/suite/compat/oracle/t/func_decode.test index 1d49cdd2102..b8be7178570 100644 --- a/mysql-test/suite/compat/oracle/t/func_decode.test +++ b/mysql-test/suite/compat/oracle/t/func_decode.test @@ -1,8 +1,8 @@ SET sql_mode=ORACLE; ---error ER_PARSE_ERROR +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT SELECT DECODE(10); ---error ER_PARSE_ERROR +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT SELECT DECODE(10,10); SELECT DECODE(10,10,'x10'); @@ -25,9 +25,9 @@ DROP TABLE decode; --echo # MDEV-13863 sql_mode=ORACLE: DECODE does not treat two NULLs as equivalent --echo # ---error ER_PARSE_ERROR +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT SELECT DECODE(10); ---error ER_PARSE_ERROR +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT SELECT DECODE(10,10); --error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT diff --git a/sql/item_create.cc b/sql/item_create.cc index 4235dcf2d31..89569412a37 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -602,7 +602,15 @@ class Create_func_decode_oracle : public Create_native_func { public: virtual Item *create_native(THD *thd, const LEX_CSTRING *name, - List *item_list); + List *item_list) + { + if (unlikely(!item_list || item_list->elements < 3)) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str); + return NULL; + } + return new (thd->mem_root) Item_func_decode_oracle(thd, *item_list); + } static Create_func_decode_oracle s_singleton; @@ -612,6 +620,33 @@ protected: }; +class Create_func_decode : public Create_native_func +{ +public: + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) + { + if (thd->variables.sql_mode & MODE_ORACLE) + return Create_func_decode_oracle::s_singleton.create_native(thd, name, + item_list); + if (unlikely(!item_list || item_list->elements != 2)) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str); + return NULL; + } + Item_args args(thd, *item_list); + return new (thd->mem_root) Item_func_decode(thd, args.arguments()[0], + args.arguments()[1]); + } + + static Create_func_decode s_singleton; + +protected: + Create_func_decode() {} + virtual ~Create_func_decode() {} +}; + + class Create_func_concat_ws : public Create_native_func { public: @@ -4074,20 +4109,9 @@ Create_func_decode_histogram::create_2_arg(THD *thd, Item *arg1, Item *arg2) return new (thd->mem_root) Item_func_decode_histogram(thd, arg1, arg2); } -Create_func_decode_oracle Create_func_decode_oracle::s_singleton; +Create_func_decode Create_func_decode::s_singleton; -Item* -Create_func_decode_oracle::create_native(THD *thd, const LEX_CSTRING *name, - List *item_list) -{ - uint arg_count= item_list ? item_list->elements : 0; - if (unlikely(arg_count < 3)) - { - my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str); - return NULL; - } - return new (thd->mem_root) Item_func_decode_oracle(thd, *item_list); -} +Create_func_decode_oracle Create_func_decode_oracle::s_singleton; Create_func_concat_ws Create_func_concat_ws::s_singleton; @@ -7285,6 +7309,7 @@ const Native_func_registry func_array[] = { { STRING_WITH_LEN("DAYOFMONTH") }, BUILDER(Create_func_dayofmonth)}, { { STRING_WITH_LEN("DAYOFWEEK") }, BUILDER(Create_func_dayofweek)}, { { STRING_WITH_LEN("DAYOFYEAR") }, BUILDER(Create_func_dayofyear)}, + { { STRING_WITH_LEN("DECODE") }, BUILDER(Create_func_decode)}, { { STRING_WITH_LEN("DEGREES") }, BUILDER(Create_func_degrees)}, { { STRING_WITH_LEN("DECODE_HISTOGRAM") }, BUILDER(Create_func_decode_histogram)}, { { STRING_WITH_LEN("DECODE_ORACLE") }, BUILDER(Create_func_decode_oracle)}, diff --git a/sql/lex.h b/sql/lex.h index e35e109a3bf..6f083075d3e 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -744,7 +744,6 @@ SYMBOL sql_functions[] = { { "DATE_ADD", SYM(DATE_ADD_INTERVAL)}, { "DATE_SUB", SYM(DATE_SUB_INTERVAL)}, { "DATE_FORMAT", SYM(DATE_FORMAT_SYM)}, - { "DECODE", SYM(DECODE_MARIADB_SYM)}, { "DENSE_RANK", SYM(DENSE_RANK_SYM)}, { "EXTRACT", SYM(EXTRACT_SYM)}, { "FIRST_VALUE", SYM(FIRST_VALUE_SYM)}, diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 8b9e8183b48..583322618f9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -873,7 +873,6 @@ int Lex_input_stream::find_keyword(Lex_ident_cli_st *kwd, case CLOB_MARIADB_SYM: return CLOB_ORACLE_SYM; case CONTINUE_MARIADB_SYM: return CONTINUE_ORACLE_SYM; case DECLARE_MARIADB_SYM: return DECLARE_ORACLE_SYM; - case DECODE_MARIADB_SYM: return DECODE_ORACLE_SYM; case ELSEIF_MARIADB_SYM: return ELSEIF_ORACLE_SYM; case ELSIF_MARIADB_SYM: return ELSIF_ORACLE_SYM; case EXCEPTION_MARIADB_SYM: return EXCEPTION_ORACLE_SYM; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cdc04d93708..048741b6ca1 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1275,8 +1275,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token DATE_SYM /* SQL-2003-R, Oracle-R, PLSQL-R */ %token DAY_SYM /* SQL-2003-R */ %token DEALLOCATE_SYM /* SQL-2003-R */ -%token DECODE_MARIADB_SYM /* Function, non-reserved */ -%token DECODE_ORACLE_SYM /* Function, non-reserved */ %token DEFINER_SYM %token DELAYED_SYM %token DELAY_KEY_WRITE_SYM @@ -1949,7 +1947,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type expr_list opt_udf_expr_list udf_expr_list when_list when_list_opt_else ident_list ident_list_arg opt_expr_list - decode_when_list_oracle execute_using execute_params @@ -11027,18 +11024,6 @@ function_call_nonkeyword: if (unlikely($$ == NULL)) MYSQL_YYABORT; } - | DECODE_MARIADB_SYM '(' expr ',' expr ')' - { - $$= new (thd->mem_root) Item_func_decode(thd, $3, $5); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } - | DECODE_ORACLE_SYM '(' expr ',' decode_when_list_oracle ')' - { - $5->push_front($3, thd->mem_root); - if (unlikely(!($$= new (thd->mem_root) Item_func_decode_oracle(thd, *$5)))) - MYSQL_YYABORT; - } | EXTRACT_SYM '(' interval FROM expr ')' { $$=new (thd->mem_root) Item_extract(thd, $3, $5); @@ -12209,25 +12194,6 @@ when_list_opt_else: } ; -decode_when_list_oracle: - expr ',' expr - { - $$= new (thd->mem_root) List; - if (unlikely($$ == NULL) || - unlikely($$->push_back($1, thd->mem_root)) || - unlikely($$->push_back($3, thd->mem_root))) - MYSQL_YYABORT; - - } - | decode_when_list_oracle ',' expr - { - $$= $1; - if (unlikely($$->push_back($3, thd->mem_root))) - MYSQL_YYABORT; - } - ; - - /* Equivalent to in the SQL:2003 standard. */ /* Warning - may return NULL in case of incomplete SELECT */ table_ref: @@ -16365,8 +16331,6 @@ keyword_sp_var_and_label: | DATAFILE_SYM | DATE_FORMAT_SYM | DAY_SYM - | DECODE_MARIADB_SYM - | DECODE_ORACLE_SYM | DEFINER_SYM | DELAY_KEY_WRITE_SYM | DES_KEY_FILE diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 5b734a27f8c..325ca4ccdc6 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -751,8 +751,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token DATE_SYM /* SQL-2003-R, Oracle-R, PLSQL-R */ %token DAY_SYM /* SQL-2003-R */ %token DEALLOCATE_SYM /* SQL-2003-R */ -%token DECODE_MARIADB_SYM /* Function, non-reserved */ -%token DECODE_ORACLE_SYM /* Function, non-reserved */ %token DEFINER_SYM %token DELAYED_SYM %token DELAY_KEY_WRITE_SYM @@ -1432,7 +1430,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type expr_list opt_udf_expr_list udf_expr_list when_list when_list_opt_else ident_list ident_list_arg opt_expr_list - decode_when_list_oracle execute_using execute_params @@ -11142,18 +11139,6 @@ function_call_nonkeyword: if (unlikely($$ == NULL)) MYSQL_YYABORT; } - | DECODE_MARIADB_SYM '(' expr ',' expr ')' - { - $$= new (thd->mem_root) Item_func_decode(thd, $3, $5); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } - | DECODE_ORACLE_SYM '(' expr ',' decode_when_list_oracle ')' - { - $5->push_front($3, thd->mem_root); - if (unlikely(!($$= new (thd->mem_root) Item_func_decode_oracle(thd, *$5)))) - MYSQL_YYABORT; - } | EXTRACT_SYM '(' interval FROM expr ')' { $$=new (thd->mem_root) Item_extract(thd, $3, $5); @@ -12324,25 +12309,6 @@ when_list_opt_else: } ; -decode_when_list_oracle: - expr ',' expr - { - $$= new (thd->mem_root) List; - if (unlikely($$ == NULL) || - unlikely($$->push_back($1, thd->mem_root)) || - unlikely($$->push_back($3, thd->mem_root))) - MYSQL_YYABORT; - - } - | decode_when_list_oracle ',' expr - { - $$= $1; - if (unlikely($$->push_back($3, thd->mem_root))) - MYSQL_YYABORT; - } - ; - - /* Equivalent to
in the SQL:2003 standard. */ /* Warning - may return NULL in case of incomplete SELECT */ table_ref: @@ -16535,8 +16501,6 @@ keyword_sp_var_and_label: | DATAFILE_SYM | DATE_FORMAT_SYM | DAY_SYM - | DECODE_MARIADB_SYM - | DECODE_ORACLE_SYM | DEFINER_SYM | DELAY_KEY_WRITE_SYM | DES_KEY_FILE From df72c57d6fbf97b12ec8cdc23edc56670a29fa7d Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 7 Apr 2023 12:15:41 +0400 Subject: [PATCH 107/158] MDEV-30048 Prefix keys for CHAR work differently for MyISAM vs InnoDB Also fixes: MDEV-30050 Inconsistent results of DISTINCT with NOPAD Problem: Key segments for CHAR columns where compared using strnncollsp() for engines MyISAM and Aria. This did not work correct in case if the engine applyied trailing space compression. Fix: Replacing ha_compare_text() calls to new functions: - ha_compare_char_varying() - ha_compare_char_fixed() - ha_compare_word() - ha_compare_word_prefix() - ha_compare_word_or_prefix() The code branch corresponding to comparison of CHAR column keys (HA_KEYTYPE_TEXT segment type) now uses ha_compare_char_fixed() which calls strnncollsp_nchars(). This patch does not change the behavior for the rest of the code: - comparison of VARCHAR/TEXT column keys (HA_KEYTYPE_VARTEXT1, HA_KEYTYPE_VARTEXT2 segments types) - comparison in the fulltext code --- include/my_compare.h | 131 +++++++++++++++- .../include/ctype_nopad_prefix_unique.inc | 6 - mysql-test/include/ctype_utf8mb3_uca_char.inc | 54 +++++++ mysql-test/main/ctype_utf8_uca.result | 141 ++++++++++++++++++ mysql-test/main/ctype_utf8_uca.test | 8 + .../suite/innodb/r/innodb_ctype_utf8.result | 84 +++++++++++ .../suite/innodb/t/innodb_ctype_utf8.test | 17 +++ .../suite/maria/ctype_utf8mb3_uca.result | 69 +++++++++ mysql-test/suite/maria/ctype_utf8mb3_uca.test | 12 ++ mysys/my_compare.c | 34 ++--- storage/innobase/handler/ha_innodb.cc | 20 +-- storage/maria/ma_check.c | 6 +- storage/maria/ma_ft_boolean_search.c | 31 ++-- storage/maria/ma_ft_nlq_search.c | 6 +- storage/maria/ma_ft_parser.c | 4 +- storage/maria/ma_ft_update.c | 7 +- storage/maria/ma_unique.c | 19 ++- storage/maria/ma_write.c | 6 +- storage/myisam/ft_boolean_search.c | 28 ++-- storage/myisam/ft_nlq_search.c | 6 +- storage/myisam/ft_parser.c | 4 +- storage/myisam/ft_stopwords.c | 6 +- storage/myisam/ft_update.c | 8 +- storage/myisam/mi_check.c | 6 +- storage/myisam/mi_unique.c | 19 ++- storage/myisam/mi_write.c | 4 +- 26 files changed, 634 insertions(+), 102 deletions(-) create mode 100644 mysql-test/include/ctype_utf8mb3_uca_char.inc create mode 100644 mysql-test/suite/maria/ctype_utf8mb3_uca.result create mode 100644 mysql-test/suite/maria/ctype_utf8mb3_uca.test diff --git a/include/my_compare.h b/include/my_compare.h index 2274b666be6..7cc078a72f3 100644 --- a/include/my_compare.h +++ b/include/my_compare.h @@ -110,8 +110,135 @@ static inline void set_rec_bits(uint16 bits, uchar *ptr, uchar ofs, uint len) #define clr_rec_bits(bit_ptr, bit_ofs, bit_len) \ set_rec_bits(0, bit_ptr, bit_ofs, bit_len) -extern int ha_compare_text(CHARSET_INFO *, const uchar *, size_t, - const uchar *, size_t , my_bool); + +/* + Compare two VARCHAR values. + @param charset_info - The character set and collation + @param a - The pointer to the first string + @param a_length - The length of the first string + @param b - The pointer to the second string + @param b_length - The length of the second string + @param b_is_prefix - Whether "b" is a prefix of "a", + e.g. in a prefix key (partial length key). + @returns - The result of comparison + + - If "b_is_prefix" is FALSE, then the two strings are compared + taking into account the PAD SPACE/NO PAD attribute of the collation. + + - If "b_is_prefix" is TRUE, then trailing spaces are compared in NO PAD style. + This is done e.g. when we compare a column value to its prefix key value + (the value of "a" to the value of "key_a"): + CREATE TABLE t1 (a VARCHAR(10), KEY(key_a(5)); +*/ +static inline int ha_compare_char_varying(CHARSET_INFO *charset_info, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + my_bool b_is_prefix) +{ + if (!b_is_prefix) + return charset_info->coll->strnncollsp(charset_info, a, a_length, + b, b_length); + return charset_info->coll->strnncoll(charset_info, + a, a_length, + b, b_length, TRUE/*prefix*/); +} + + +/* + Compare two CHAR values of the same declared character length, + e.g. CHAR(5) to CHAR(5). + + @param charset_info - The character set and collation + @param a - The pointer to the first string + @param a_length - The length of the first string + @param b - The pointer to the second string + @param b_length - The length of the second string + @param nchars - The declared length (in characters) + @param b_is_prefix - Whether "b" is a prefix of "a", + e.g. in a prefix key (partial length key). + @returns - The result of comparison + + - If "b_is_prefix" is FALSE, then the two strings are compared + taking into account the PAD SPACE/NO PAD attribute of the collation. + Additionally, this function assumes that the underlying storage could + optionally apply trailing space compression, so values can come into this + comparison function in different states: + - all trailing spaces removed + - some trailing spaced removed + - no trailing spaces removed (exactly "nchars" characters on the two sides) + This function virtually reconstructs trailing spaces up to the defined + length specified in "nchars". + If either of the sides have more than "nchar" characters, + then only leftmost "nchar" characters are compared. + + - If "b_is_prefix" is TRUE, then trailing spaces are compared in NO PAD style. + This is done e.g. when we compare a column value to its prefix key value + (the value of "a" to the value of "key_a"): + CREATE TABLE t1 (a CHAR(10), KEY(key_a(5)); +*/ +static inline int ha_compare_char_fixed(CHARSET_INFO *charset_info, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + size_t nchars, + my_bool b_is_prefix) +{ + if (!b_is_prefix) + return charset_info->coll->strnncollsp_nchars(charset_info, + a, a_length, + b, b_length, + nchars, + MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES); + return charset_info->coll->strnncoll(charset_info, + a, a_length, + b, b_length, TRUE/*prefix*/); +} + + +/* + A function to compare words of a text. + This is a common operation in full-text search: + SELECT MATCH (title) AGAINST ('word') FROM t1; +*/ +static inline int ha_compare_word(CHARSET_INFO *charset_info, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length) +{ + return charset_info->coll->strnncollsp(charset_info, + a, a_length, + b, b_length); +} + + +/* + A function to compare a word of a text to a word prefix. + This is a common operation in full-text search: + SELECT MATCH (title) AGAINST ('wor*' IN BOOLEAN MODE) FROM t1; +*/ +static inline int ha_compare_word_prefix(CHARSET_INFO *charset_info, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length) +{ + return charset_info->coll->strnncoll(charset_info, + a, a_length, + b, b_length, + TRUE/*b_is_prefix*/); +} + + +/* + Compare words (full match or prefix match), e.g. for full-text search. +*/ +static inline int ha_compare_word_or_prefix(CHARSET_INFO *charset_info, + const uchar *a, size_t a_length, + const uchar *b, size_t b_length, + my_bool b_is_prefix) +{ + if (!b_is_prefix) + return ha_compare_word(charset_info, a, a_length, b, b_length); + return ha_compare_word_prefix(charset_info, a, a_length, b, b_length); +} + + extern int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a, const uchar *b, uint key_length, uint nextflag, uint *diff_pos); diff --git a/mysql-test/include/ctype_nopad_prefix_unique.inc b/mysql-test/include/ctype_nopad_prefix_unique.inc index b25128e9fef..ec5bda0eb3a 100644 --- a/mysql-test/include/ctype_nopad_prefix_unique.inc +++ b/mysql-test/include/ctype_nopad_prefix_unique.inc @@ -58,11 +58,6 @@ DROP TABLE t1; # CHAR -# MyISAM is buggy on CHAR+BTREE+UNIQUE+PREFIX (see MDEV-30048), disable for now -# Other engines work fine - -if (`SELECT UPPER(@@storage_engine) != 'MYISAM'`) -{ EXECUTE IMMEDIATE REPLACE( 'CREATE TABLE t1 ( ' ' a CHAR(20) COLLATE ,' @@ -72,7 +67,6 @@ SHOW CREATE TABLE t1; INSERT INTO t1 VALUES ('ss '); INSERT INTO t1 VALUES (_utf8mb3 0xC39F20)/*SZ+SPACE*/; DROP TABLE t1; -} EXECUTE IMMEDIATE REPLACE( 'CREATE TABLE t1 ( ' diff --git a/mysql-test/include/ctype_utf8mb3_uca_char.inc b/mysql-test/include/ctype_utf8mb3_uca_char.inc new file mode 100644 index 00000000000..4540416a6ed --- /dev/null +++ b/mysql-test/include/ctype_utf8mb3_uca_char.inc @@ -0,0 +1,54 @@ +--echo # +--echo # MDEV-30048 Prefix keys for CHAR work differently for MyISAM vs InnoDB +--echo # + +SET NAMES utf8mb3; + +# +# Engines have different conditions based on the column size +# determining when to use trailing space compressions in key values, +# so let's test different column sizes for better coverage. +# + + +# +# CHAR(10) +# + +CREATE TABLE t1 (a CHAR(10) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; + +CREATE TABLE t1 (a CHAR(10) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a(2))); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; + +# +# CHAR(120) +# + +CREATE TABLE t1 (a CHAR(120) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; + +CREATE TABLE t1 (a CHAR(120) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a(100))); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; + +--echo # +--echo # MDEV-30050 Inconsistent results of DISTINCT with NOPAD +--echo # + +CREATE TABLE t1 (c CHAR(100) COLLATE utf8mb3_unicode_nopad_ci); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES ('ss'),('ß'); +SET big_tables=0; +SELECT DISTINCT c FROM t1; +SET big_tables=1; +SELECT DISTINCT c FROM t1; +DROP TABLE t1; +SET big_tables=DEFAULT; diff --git a/mysql-test/main/ctype_utf8_uca.result b/mysql-test/main/ctype_utf8_uca.result index 2e22097e6ac..546e77f4280 100644 --- a/mysql-test/main/ctype_utf8_uca.result +++ b/mysql-test/main/ctype_utf8_uca.result @@ -830,6 +830,20 @@ INSERT INTO t1 VALUES (_utf8mb3 0xC39F20)/*SZ+SPACE*/; ERROR 23000: Duplicate entry 'ß ' for key 'a' DROP TABLE t1; EXECUTE IMMEDIATE REPLACE( +'CREATE TABLE t1 ( ' + ' a CHAR(20) COLLATE ,' + 'UNIQUE(a(3)))', +'', @@collation_connection); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(20) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`(3)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss '); +INSERT INTO t1 VALUES (_utf8mb3 0xC39F20)/*SZ+SPACE*/; +DROP TABLE t1; +EXECUTE IMMEDIATE REPLACE( 'CREATE TABLE t1 ( ' ' a CHAR(20) COLLATE ,' 'UNIQUE(a(3)) USING HASH)', @@ -906,6 +920,133 @@ INSERT INTO t1 VALUES ('ss '); INSERT INTO t1 VALUES (_utf8mb3 0xC39F20)/*SZ+SPACE*/; DROP TABLE t1; SET STORAGE_ENGINE=DEFAULT; +SET default_storage_engine=MyISAM; +# +# MDEV-30048 Prefix keys for CHAR work differently for MyISAM vs InnoDB +# +SET NAMES utf8mb3; +CREATE TABLE t1 (a CHAR(10) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(10) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a(2))); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`(2)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(120) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(120) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(120) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a(100))); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(120) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`(100)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +# +# MDEV-30050 Inconsistent results of DISTINCT with NOPAD +# +CREATE TABLE t1 (c CHAR(100) COLLATE utf8mb3_unicode_nopad_ci); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` char(100) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +SET big_tables=0; +SELECT DISTINCT c FROM t1; +c +ss +ß +SET big_tables=1; +SELECT DISTINCT c FROM t1; +c +ss +ß +DROP TABLE t1; +SET big_tables=DEFAULT; +SET default_storage_engine=MEMORY; +# +# MDEV-30048 Prefix keys for CHAR work differently for MyISAM vs InnoDB +# +SET NAMES utf8mb3; +CREATE TABLE t1 (a CHAR(10) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`) +) ENGINE=MEMORY DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(10) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a(2))); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`(2)) +) ENGINE=MEMORY DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(120) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(120) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`) +) ENGINE=MEMORY DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(120) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a(100))); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(120) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`(100)) +) ENGINE=MEMORY DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +# +# MDEV-30050 Inconsistent results of DISTINCT with NOPAD +# +CREATE TABLE t1 (c CHAR(100) COLLATE utf8mb3_unicode_nopad_ci); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` char(100) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL +) ENGINE=MEMORY DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +SET big_tables=0; +SELECT DISTINCT c FROM t1; +c +ss +ß +SET big_tables=1; +SELECT DISTINCT c FROM t1; +c +ss +ß +DROP TABLE t1; +SET big_tables=DEFAULT; +SET default_storage_engine=DEFAULT; # # End of 10.4 tests # diff --git a/mysql-test/main/ctype_utf8_uca.test b/mysql-test/main/ctype_utf8_uca.test index 255390b5ce5..be6d5248329 100644 --- a/mysql-test/main/ctype_utf8_uca.test +++ b/mysql-test/main/ctype_utf8_uca.test @@ -65,6 +65,14 @@ SET STORAGE_ENGINE=HEAP; SET STORAGE_ENGINE=DEFAULT; + +SET default_storage_engine=MyISAM; +--source include/ctype_utf8mb3_uca_char.inc +SET default_storage_engine=MEMORY; +--source include/ctype_utf8mb3_uca_char.inc +SET default_storage_engine=DEFAULT; + + --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/suite/innodb/r/innodb_ctype_utf8.result b/mysql-test/suite/innodb/r/innodb_ctype_utf8.result index ab193db6e75..9a9de76c62a 100644 --- a/mysql-test/suite/innodb/r/innodb_ctype_utf8.result +++ b/mysql-test/suite/innodb/r/innodb_ctype_utf8.result @@ -379,5 +379,89 @@ INSERT INTO t1 VALUES ('ss '); INSERT INTO t1 VALUES (_utf8mb3 0xC39F20)/*SZ+SPACE*/; DROP TABLE t1; # +# MDEV-30048 Prefix keys for CHAR work differently for MyISAM vs InnoDB +# +SET NAMES utf8mb3; +CREATE TABLE t1 (a CHAR(10) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(10) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a(2))); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`(2)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(120) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(120) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(120) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a(100))); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(120) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`(100)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +# +# MDEV-30050 Inconsistent results of DISTINCT with NOPAD +# +CREATE TABLE t1 (c CHAR(100) COLLATE utf8mb3_unicode_nopad_ci); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` char(100) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +SET big_tables=0; +SELECT DISTINCT c FROM t1; +c +ss +ß +SET big_tables=1; +SELECT DISTINCT c FROM t1; +c +ss +ß +DROP TABLE t1; +SET big_tables=DEFAULT; +# +# MDEV-30050 Inconsistent results of DISTINCT with NOPAD +# +CREATE OR REPLACE TABLE t1 (c CHAR(100) COLLATE utf8mb3_unicode_nopad_ci); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` char(100) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 VALUES ('ss'),('ß'); +SET big_tables=0; +SELECT DISTINCT c FROM t1; +c +ss +ß +SET big_tables=1; +SELECT DISTINCT c FROM t1; +c +ss +ß +DROP TABLE t1; +SET big_tables=DEFAULT; +# # End 10.4 tests # diff --git a/mysql-test/suite/innodb/t/innodb_ctype_utf8.test b/mysql-test/suite/innodb/t/innodb_ctype_utf8.test index 9bc6408e0e0..82b5e000890 100644 --- a/mysql-test/suite/innodb/t/innodb_ctype_utf8.test +++ b/mysql-test/suite/innodb/t/innodb_ctype_utf8.test @@ -32,6 +32,23 @@ let $coll_pad='utf8_bin'; SET NAMES utf8mb3 COLLATE utf8mb3_unicode_nopad_ci; --source include/ctype_nopad_prefix_unique.inc +--source include/ctype_utf8mb3_uca_char.inc + +--echo # +--echo # MDEV-30050 Inconsistent results of DISTINCT with NOPAD +--echo # + +CREATE OR REPLACE TABLE t1 (c CHAR(100) COLLATE utf8mb3_unicode_nopad_ci); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES ('ss'),('ß'); +SET big_tables=0; +SELECT DISTINCT c FROM t1; +SET big_tables=1; +SELECT DISTINCT c FROM t1; +DROP TABLE t1; +SET big_tables=DEFAULT; + + --echo # --echo # End 10.4 tests --echo # diff --git a/mysql-test/suite/maria/ctype_utf8mb3_uca.result b/mysql-test/suite/maria/ctype_utf8mb3_uca.result new file mode 100644 index 00000000000..aa4a216ed57 --- /dev/null +++ b/mysql-test/suite/maria/ctype_utf8mb3_uca.result @@ -0,0 +1,69 @@ +# +# Start of 10.4 tests +# +SET default_storage_engine=Aria; +# +# MDEV-30048 Prefix keys for CHAR work differently for MyISAM vs InnoDB +# +SET NAMES utf8mb3; +CREATE TABLE t1 (a CHAR(10) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`) +) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(10) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a(2))); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`(2)) +) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(120) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(120) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`) +) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(120) COLLATE utf8mb3_unicode_nopad_ci, UNIQUE KEY(a(100))); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(120) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL, + UNIQUE KEY `a` (`a`(100)) +) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 +INSERT INTO t1 VALUES ('ss'),('ß'); +DROP TABLE t1; +# +# MDEV-30050 Inconsistent results of DISTINCT with NOPAD +# +CREATE TABLE t1 (c CHAR(100) COLLATE utf8mb3_unicode_nopad_ci); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` char(100) CHARACTER SET utf8 COLLATE utf8_unicode_nopad_ci DEFAULT NULL +) ENGINE=Aria DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 +INSERT INTO t1 VALUES ('ss'),('ß'); +SET big_tables=0; +SELECT DISTINCT c FROM t1; +c +ss +ß +SET big_tables=1; +SELECT DISTINCT c FROM t1; +c +ss +ß +DROP TABLE t1; +SET big_tables=DEFAULT; +# +# End of 10.4 tests +# diff --git a/mysql-test/suite/maria/ctype_utf8mb3_uca.test b/mysql-test/suite/maria/ctype_utf8mb3_uca.test new file mode 100644 index 00000000000..21cec59008b --- /dev/null +++ b/mysql-test/suite/maria/ctype_utf8mb3_uca.test @@ -0,0 +1,12 @@ +--source include/have_maria.inc + +--echo # +--echo # Start of 10.4 tests +--echo # + +SET default_storage_engine=Aria; +--source include/ctype_utf8mb3_uca_char.inc + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysys/my_compare.c b/mysys/my_compare.c index 358cb77008e..9745e8f40af 100644 --- a/mysys/my_compare.c +++ b/mysys/my_compare.c @@ -20,16 +20,6 @@ #include #include -int ha_compare_text(CHARSET_INFO *charset_info, const uchar *a, size_t a_length, - const uchar *b, size_t b_length, my_bool part_key) -{ - if (!part_key) - return charset_info->coll->strnncollsp(charset_info, a, a_length, - b, b_length); - return charset_info->coll->strnncoll(charset_info, a, a_length, - b, b_length, part_key); -} - static int compare_bin(const uchar *a, uint a_length, const uchar *b, uint b_length, @@ -183,9 +173,12 @@ int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a, next_key_length=key_length-b_length-pack_length; if (piks && - (flag=ha_compare_text(keyseg->charset,a,a_length,b,b_length, - (my_bool) ((nextflag & SEARCH_PREFIX) && - next_key_length <= 0)))) + (flag= ha_compare_char_fixed(keyseg->charset, + a, a_length, + b, b_length, + keyseg->length / keyseg->charset->mbmaxlen, + (my_bool) ((nextflag & SEARCH_PREFIX) && + next_key_length <= 0)))) return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); a+=a_length; b+=b_length; @@ -195,9 +188,12 @@ int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a, { uint length=(uint) (end-a), a_length=length, b_length=length; if (piks && - (flag= ha_compare_text(keyseg->charset, a, a_length, b, b_length, - (my_bool) ((nextflag & SEARCH_PREFIX) && - next_key_length <= 0)))) + (flag= ha_compare_char_fixed(keyseg->charset, + a, a_length, + b, b_length, + keyseg->length / keyseg->charset->mbmaxlen, + (my_bool) ((nextflag & SEARCH_PREFIX) && + next_key_length <= 0)))) return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); a=end; b+=length; @@ -242,7 +238,9 @@ int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a, next_key_length=key_length-b_length-pack_length; if (piks && - (flag= ha_compare_text(keyseg->charset,a,a_length,b,b_length, + (flag= ha_compare_char_varying(keyseg->charset, + a, a_length, + b, b_length, (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0)))) return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); @@ -260,7 +258,7 @@ int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a, next_key_length=key_length-b_length-pack_length; if (piks && - (flag=compare_bin(a,a_length,b,b_length, + (flag=compare_bin(a,a_length,b,b_length, (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0), 0))) return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 8116b3f499a..1c460a9ff85 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6751,9 +6751,9 @@ innobase_fts_text_cmp( const fts_string_t* s1 = (const fts_string_t*) p1; const fts_string_t* s2 = (const fts_string_t*) p2; - return(ha_compare_text( - charset, s1->f_str, static_cast(s1->f_len), - s2->f_str, static_cast(s2->f_len), 0)); + return(ha_compare_word(charset, + s1->f_str, static_cast(s1->f_len), + s2->f_str, static_cast(s2->f_len))); } /******************************************************************//** @@ -6774,9 +6774,9 @@ innobase_fts_text_case_cmp( newlen = strlen((const char*) s2->f_str); - return(ha_compare_text( - charset, s1->f_str, static_cast(s1->f_len), - s2->f_str, static_cast(newlen), 0)); + return(ha_compare_word(charset, + s1->f_str, static_cast(s1->f_len), + s2->f_str, static_cast(newlen))); } /******************************************************************//** @@ -6821,11 +6821,11 @@ innobase_fts_text_cmp_prefix( const fts_string_t* s2 = (const fts_string_t*) p2; int result; - result = ha_compare_text( - charset, s2->f_str, static_cast(s2->f_len), - s1->f_str, static_cast(s1->f_len), 1); + result = ha_compare_word_prefix(charset, + s2->f_str, static_cast(s2->f_len), + s1->f_str, static_cast(s1->f_len)); - /* We switched s1, s2 position in ha_compare_text. So we need + /* We switched s1, s2 position in the above call. So we need to negate the result */ return(-result); } diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 6835af928ee..9b3c14d40e3 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -5702,9 +5702,9 @@ static int sort_maria_ft_key_write(MARIA_SORT_PARAM *sort_param, } get_key_full_length_rdonly(val_off, ft_buf->lastkey); - if (ha_compare_text(sort_param->seg->charset, - a+1,a_len-1, - ft_buf->lastkey+1,val_off-1, 0)==0) + if (ha_compare_word(sort_param->seg->charset, + a + 1, a_len - 1, + ft_buf->lastkey + 1, val_off - 1) == 0) { uchar *p; if (!ft_buf->buf) /* store in second-level tree */ diff --git a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c index 7fe6d8ca2cc..4a4388b691f 100644 --- a/storage/maria/ma_ft_boolean_search.c +++ b/storage/maria/ma_ft_boolean_search.c @@ -162,8 +162,8 @@ static int FTB_WORD_cmp(my_off_t *v, FTB_WORD *a, FTB_WORD *b) static int FTB_WORD_cmp_list(CHARSET_INFO *cs, FTB_WORD **a, FTB_WORD **b) { /* ORDER BY word, ndepth */ - int i= ha_compare_text(cs, (uchar*) (*a)->word + 1,(*a)->len - 1, - (uchar*) (*b)->word + 1,(*b)->len - 1, 0); + int i= ha_compare_word(cs, (uchar*) (*a)->word + 1, (*a)->len - 1, + (uchar*) (*b)->word + 1, (*b)->len - 1); if (!i) i=CMP_NUM((*a)->ndepth, (*b)->ndepth); return i; @@ -403,13 +403,14 @@ static int _ft2_search_no_lock(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) if (!r && !ftbw->off) { - r= ha_compare_text(ftb->charset, - info->last_key.data+1, - info->last_key.data_length + info->last_key.ref_length- - extra-1, - (uchar*) ftbw->word+1, - ftbw->len-1, - (my_bool) (ftbw->flags & FTB_FLAG_TRUNC)); + r= ha_compare_word_or_prefix(ftb->charset, + info->last_key.data + 1, + info->last_key.data_length + + info->last_key.ref_length - + extra - 1, + (uchar*) ftbw->word + 1, + ftbw->len - 1, + (my_bool) (ftbw->flags & FTB_FLAG_TRUNC)); } if (r) /* not found */ @@ -899,9 +900,9 @@ static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, for (a= 0, b= ftb->queue.elements, c= (a+b)/2; b-a>1; c= (a+b)/2) { ftbw= ftb->list[c]; - if (ha_compare_text(ftb->charset, (uchar*)word, len, - (uchar*)ftbw->word+1, ftbw->len-1, - (my_bool)(ftbw->flags&FTB_FLAG_TRUNC)) < 0) + if (ha_compare_word_or_prefix(ftb->charset, (uchar*) word, len, + (uchar*) ftbw->word + 1, ftbw->len - 1, + (my_bool) (ftbw->flags & FTB_FLAG_TRUNC)) < 0) b= c; else a= c; @@ -926,9 +927,9 @@ static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, for (; c >= 0; c--) { ftbw= ftb->list[c]; - if (ha_compare_text(ftb->charset, (uchar*)word, len, - (uchar*)ftbw->word + 1,ftbw->len - 1, - (my_bool)(ftbw->flags & FTB_FLAG_TRUNC))) + if (ha_compare_word_or_prefix(ftb->charset, (uchar*) word, len, + (uchar*)ftbw->word + 1, ftbw->len - 1, + (my_bool) (ftbw->flags & FTB_FLAG_TRUNC))) { if (ftb->with_scan & FTB_FLAG_TRUNC) continue; diff --git a/storage/maria/ma_ft_nlq_search.c b/storage/maria/ma_ft_nlq_search.c index f7aa3afec9a..c9f68c6d874 100644 --- a/storage/maria/ma_ft_nlq_search.c +++ b/storage/maria/ma_ft_nlq_search.c @@ -111,11 +111,11 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) while (!r && gweight) { if (key.data_length && - ha_compare_text(aio->charset, - info->last_key.data+1, + ha_compare_word(aio->charset, + info->last_key.data + 1, info->last_key.data_length + info->last_key.ref_length - extra - 1, - key.data+1, key.data_length-1, 0)) + key.data + 1, key.data_length - 1)) break; if (subkeys.i < 0) diff --git a/storage/maria/ma_ft_parser.c b/storage/maria/ma_ft_parser.c index dbad6c4e7f5..e80c927f877 100644 --- a/storage/maria/ma_ft_parser.c +++ b/storage/maria/ma_ft_parser.c @@ -33,8 +33,8 @@ typedef struct st_my_maria_ft_parser_param static int FT_WORD_cmp(CHARSET_INFO* cs, FT_WORD *w1, FT_WORD *w2) { - return ha_compare_text(cs, (uchar*) w1->pos, w1->len, - (uchar*) w2->pos, w2->len, 0); + return ha_compare_word(cs, (uchar*) w1->pos, w1->len, + (uchar*) w2->pos, w2->len); } static int walk_and_copy(FT_WORD *word,uint32 count,FT_DOCSTAT *docstat) diff --git a/storage/maria/ma_ft_update.c b/storage/maria/ma_ft_update.c index 8e1bf397c86..17da19953b5 100644 --- a/storage/maria/ma_ft_update.c +++ b/storage/maria/ma_ft_update.c @@ -185,8 +185,7 @@ int _ma_ft_cmp(MARIA_HA *info, uint keynr, const uchar *rec1, const uchar *rec2) { if ((ftsi1.pos != ftsi2.pos) && (!ftsi1.pos || !ftsi2.pos || - ha_compare_text(cs, ftsi1.pos,ftsi1.len, - ftsi2.pos,ftsi2.len,0))) + ha_compare_word(cs, ftsi1.pos, ftsi1.len, ftsi2.pos, ftsi2.len))) DBUG_RETURN(THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT); } DBUG_RETURN(GEE_THEY_ARE_ABSOLUTELY_IDENTICAL); @@ -213,8 +212,8 @@ int _ma_ft_update(MARIA_HA *info, uint keynr, uchar *keybuf, error=0; while(old_word->pos && new_word->pos) { - cmp= ha_compare_text(cs, (uchar*) old_word->pos,old_word->len, - (uchar*) new_word->pos,new_word->len,0); + cmp= ha_compare_word(cs, (uchar*) old_word->pos, old_word->len, + (uchar*) new_word->pos, new_word->len); cmp2= cmp ? 0 : (fabs(old_word->weight - new_word->weight) > 1.e-5); if (cmp < 0 || cmp2) diff --git a/storage/maria/ma_unique.c b/storage/maria/ma_unique.c index ce7967608b9..73c1ac9a20b 100644 --- a/storage/maria/ma_unique.c +++ b/storage/maria/ma_unique.c @@ -236,11 +236,22 @@ my_bool _ma_unique_comp(MARIA_UNIQUEDEF *def, const uchar *a, const uchar *b, memcpy((void*) &pos_a, pos_a+keyseg->bit_start, sizeof(char*)); memcpy((void*) &pos_b, pos_b+keyseg->bit_start, sizeof(char*)); } - if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 || - type == HA_KEYTYPE_VARTEXT2) + if (type == HA_KEYTYPE_TEXT/* the CHAR data type*/) { - if (ha_compare_text(keyseg->charset, pos_a, a_length, - pos_b, b_length, 0)) + if (ha_compare_char_fixed(keyseg->charset, + pos_a, a_length, + pos_b, b_length, + keyseg->length / keyseg->charset->mbmaxlen, + FALSE/*b_is_prefix*/)) + return 1; + } + else if (type == HA_KEYTYPE_VARTEXT1 || + type == HA_KEYTYPE_VARTEXT2) + { + if (ha_compare_char_varying(keyseg->charset, + pos_a, a_length, + pos_b, b_length, + FALSE/*b_is_prefix*/)) return 1; } else diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 88486bca246..b44ecc8d841 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -890,8 +890,10 @@ ChangeSet@1.2562, 2008-04-09 07:41:40+02:00, serg@janus.mylan +9 -0 get_key_length(alen,a); DBUG_ASSERT(info->ft1_to_ft2==0); if (alen == blen && - ha_compare_text(keyinfo->seg->charset, a, alen, - b, blen, 0) == 0) + ha_compare_char_varying(keyinfo->seg->charset, + a, alen, + b, blen, + FALSE/*b_is_prefix*/) == 0) { /* Yup. converting */ info->ft1_to_ft2=(DYNAMIC_ARRAY *) diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index 406a9bbc951..2e7f7d76360 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -162,8 +162,8 @@ static int FTB_WORD_cmp(my_off_t *v, FTB_WORD *a, FTB_WORD *b) static int FTB_WORD_cmp_list(CHARSET_INFO *cs, FTB_WORD **a, FTB_WORD **b) { /* ORDER BY word, ndepth */ - int i= ha_compare_text(cs, (uchar*) (*a)->word + 1, (*a)->len - 1, - (uchar*) (*b)->word + 1, (*b)->len - 1, 0); + int i= ha_compare_word(cs, (uchar*) (*a)->word + 1, (*a)->len - 1, + (uchar*) (*b)->word + 1, (*b)->len - 1); if (!i) i= CMP_NUM((*a)->ndepth, (*b)->ndepth); return i; @@ -407,12 +407,12 @@ static int _ft2_search_no_lock(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) if (!r && !ftbw->off) { - r= ha_compare_text(ftb->charset, - info->lastkey+1, - info->lastkey_length-extra-1, - (uchar*) ftbw->word+1, - ftbw->len-1, - (my_bool) (ftbw->flags & FTB_FLAG_TRUNC)); + r= ha_compare_word_or_prefix(ftb->charset, + info->lastkey + 1, + info->lastkey_length - extra - 1, + (uchar*) ftbw->word + 1, + ftbw->len - 1, + (my_bool) (ftbw->flags & FTB_FLAG_TRUNC)); } if (r) /* not found */ @@ -907,9 +907,9 @@ static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, for (a= 0, b= ftb->queue.elements, c= (a+b)/2; b-a>1; c= (a+b)/2) { ftbw= ftb->list[c]; - if (ha_compare_text(ftb->charset, (uchar*)word, len, - (uchar*)ftbw->word+1, ftbw->len-1, - (my_bool) (ftbw->flags & FTB_FLAG_TRUNC)) < 0) + if (ha_compare_word_or_prefix(ftb->charset, (uchar*)word, len, + (uchar*)ftbw->word + 1, ftbw->len - 1, + (my_bool) (ftbw->flags & FTB_FLAG_TRUNC)) < 0) b= c; else a= c; @@ -934,9 +934,9 @@ static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, for (; c >= 0; c--) { ftbw= ftb->list[c]; - if (ha_compare_text(ftb->charset, (uchar*)word, len, - (uchar*)ftbw->word + 1,ftbw->len - 1, - (my_bool)(ftbw->flags & FTB_FLAG_TRUNC))) + if (ha_compare_word_or_prefix(ftb->charset, (uchar*) word, len, + (uchar*) ftbw->word + 1, ftbw->len - 1, + (my_bool) (ftbw->flags & FTB_FLAG_TRUNC))) { if (ftb->with_scan & FTB_FLAG_TRUNC) continue; diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index 3e433b71761..ad676de99cf 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -109,8 +109,10 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) { if (keylen && - ha_compare_text(aio->charset,info->lastkey+1, - info->lastkey_length-extra-1, keybuff+1,keylen-1,0)) + ha_compare_word(aio->charset, + info->lastkey + 1, + info->lastkey_length - extra - 1, + keybuff + 1, keylen - 1)) break; if (subkeys.i < 0) diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c index bc50301fab2..1761cba2f10 100644 --- a/storage/myisam/ft_parser.c +++ b/storage/myisam/ft_parser.c @@ -31,8 +31,8 @@ typedef struct st_my_ft_parser_param static int FT_WORD_cmp(CHARSET_INFO* cs, FT_WORD *w1, FT_WORD *w2) { - return ha_compare_text(cs, (uchar*) w1->pos, w1->len, - (uchar*) w2->pos, w2->len, 0); + return ha_compare_word(cs, (uchar*) w1->pos, w1->len, + (uchar*) w2->pos, w2->len); } static int walk_and_copy(FT_WORD *word,uint32 count,FT_DOCSTAT *docstat) diff --git a/storage/myisam/ft_stopwords.c b/storage/myisam/ft_stopwords.c index 3422a82a111..51340400548 100644 --- a/storage/myisam/ft_stopwords.c +++ b/storage/myisam/ft_stopwords.c @@ -33,9 +33,9 @@ static TREE *stopwords3=NULL; static int FT_STOPWORD_cmp(void* cmp_arg __attribute__((unused)), FT_STOPWORD *w1, FT_STOPWORD *w2) { - return ha_compare_text(ft_stopword_cs, - (uchar *)w1->pos,w1->len, - (uchar *)w2->pos,w2->len,0); + return ha_compare_word(ft_stopword_cs, + (uchar *) w1->pos, w1->len, + (uchar *) w2->pos, w2->len); } static int FT_STOPWORD_free(FT_STOPWORD *w, TREE_FREE action, diff --git a/storage/myisam/ft_update.c b/storage/myisam/ft_update.c index 0c97a926746..ea99dfb5aaf 100644 --- a/storage/myisam/ft_update.c +++ b/storage/myisam/ft_update.c @@ -181,8 +181,8 @@ int _mi_ft_cmp(MI_INFO *info, uint keynr, const uchar *rec1, const uchar *rec2) { if ((ftsi1.pos != ftsi2.pos) && (!ftsi1.pos || !ftsi2.pos || - ha_compare_text(cs, (uchar*) ftsi1.pos,ftsi1.len, - (uchar*) ftsi2.pos,ftsi2.len,0))) + ha_compare_word(cs, (uchar*) ftsi1.pos, ftsi1.len, + (uchar*) ftsi2.pos, ftsi2.len))) DBUG_RETURN(THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT); } DBUG_RETURN(GEE_THEY_ARE_ABSOLUTELY_IDENTICAL); @@ -210,8 +210,8 @@ int _mi_ft_update(MI_INFO *info, uint keynr, uchar *keybuf, error=0; while(old_word->pos && new_word->pos) { - cmp= ha_compare_text(cs, (uchar*) old_word->pos,old_word->len, - (uchar*) new_word->pos,new_word->len,0); + cmp= ha_compare_word(cs, (uchar*) old_word->pos, old_word->len, + (uchar*) new_word->pos, new_word->len); cmp2= cmp ? 0 : (fabs(old_word->weight - new_word->weight) > 1.e-5); if (cmp < 0 || cmp2) diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index baca24eb56f..b68c1eb6d36 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -3957,9 +3957,9 @@ static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a) } get_key_full_length_rdonly(val_off, ft_buf->lastkey); - if (ha_compare_text(sort_param->seg->charset, - ((uchar *)a)+1,a_len-1, - (uchar*) ft_buf->lastkey+1,val_off-1, 0)==0) + if (ha_compare_word(sort_param->seg->charset, + ((uchar *)a) + 1, a_len - 1, + (uchar*) ft_buf->lastkey + 1, val_off - 1) == 0) { if (!ft_buf->buf) /* store in second-level tree */ { diff --git a/storage/myisam/mi_unique.c b/storage/myisam/mi_unique.c index 5d16efb96a1..01b60f61d63 100644 --- a/storage/myisam/mi_unique.c +++ b/storage/myisam/mi_unique.c @@ -211,11 +211,22 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const uchar *a, const uchar *b, memcpy((char**) &pos_a, pos_a+keyseg->bit_start, sizeof(char*)); memcpy((char**) &pos_b, pos_b+keyseg->bit_start, sizeof(char*)); } - if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 || - type == HA_KEYTYPE_VARTEXT2) + if (type == HA_KEYTYPE_TEXT/*The CHAR data type*/) { - if (ha_compare_text(keyseg->charset, (uchar *) pos_a, a_length, - (uchar *) pos_b, b_length, 0)) + if (ha_compare_char_fixed(keyseg->charset, + (uchar *) pos_a, a_length, + (uchar *) pos_b, b_length, + keyseg->length / keyseg->charset->mbmaxlen, + FALSE/*b_is_prefix*/)) + return 1; + } + else if (type == HA_KEYTYPE_VARTEXT1 || + type == HA_KEYTYPE_VARTEXT2) + { + if (ha_compare_char_varying(keyseg->charset, + (uchar *) pos_a, a_length, + (uchar *) pos_b, b_length, + FALSE/*b_is_prefix*/)) return 1; } else diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c index 7345ab1604d..238d7243c5c 100644 --- a/storage/myisam/mi_write.c +++ b/storage/myisam/mi_write.c @@ -542,7 +542,9 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo, get_key_length(alen,a); DBUG_ASSERT(info->ft1_to_ft2==0); if (alen == blen && - ha_compare_text(keyinfo->seg->charset, a, alen, b, blen, 0)==0) + ha_compare_word(keyinfo->seg->charset, + a, alen, + b, blen) == 0) { /* yup. converting */ info->ft1_to_ft2=(DYNAMIC_ARRAY *) From 15a1168b36e23dde7b2b3796bb14f5168d859499 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Thu, 19 Oct 2023 12:15:39 +1100 Subject: [PATCH 108/158] MDEV-32507 Spider: Use $MTR_SUITE_DIR for init-file files This should fix certain CI builds where the spider suite test files and the main suite test files do not follow the same relative paths relations as the mariadb source. --- storage/spider/mysql-test/spider/bugfix/t/mdev_27233.opt | 2 +- .../spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.opt | 2 +- storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.opt | 2 +- .../spider/bugfix/t/udf_mysql_func_early_init_file.opt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.opt b/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.opt index 7bc1c2127a6..b046607108b 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.opt +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.opt @@ -1 +1 @@ ---init-file=$MYSQL_TEST_DIR/../storage/spider/mysql-test/spider/bugfix/t/mdev_27233.sql +--init-file=$MTR_SUITE_DIR/t/mdev_27233.sql diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.opt b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.opt index f7ce5b39b5e..556df9cdc10 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.opt +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.opt @@ -1 +1 @@ ---init-file=$MYSQL_TEST_DIR/../storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.sql +--init-file=$MTR_SUITE_DIR/t/mdev_28218_init_file.sql diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.opt b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.opt index 37d8664c6da..5561f625c8e 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.opt +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.opt @@ -1,2 +1,2 @@ --plugin-load-add=ha_spider ---init-file=$MYSQL_TEST_DIR/../storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.sql +--init-file=$MTR_SUITE_DIR/t/mdev_28218_mixed.sql diff --git a/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.opt b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.opt index 60bb42d2918..d0f5777db87 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.opt +++ b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.opt @@ -1 +1 @@ ---init-file=$MYSQL_TEST_DIR/../storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.sql +--init-file=$MTR_SUITE_DIR/t/udf_mysql_func_early_init_file.sql From 0b2fd01ed0bf8c9eef1e90ed375a297e02c5478b Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 17 Oct 2023 15:02:12 +1100 Subject: [PATCH 109/158] MDEV-32485 Fix Spider upgrade failure caused by duplication in mysql.func --- storage/spider/spd_init_query.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h index a322b73708d..001268164d5 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -657,7 +657,7 @@ static LEX_STRING spider_init_queries[] = { "if @win_plugin = 0 then" " begin not atomic" " declare exit handler for 1041, 1123" - " insert into mysql.func values" + " replace into mysql.func values" " ('spider_direct_sql', 2, 'ha_spider.so', 'function')," " ('spider_bg_direct_sql', 2, 'ha_spider.so', 'aggregate')," " ('spider_ping_table', 2, 'ha_spider.so', 'function')," @@ -677,7 +677,7 @@ static LEX_STRING spider_init_queries[] = { "else" " begin not atomic" " declare exit handler for 1041, 1123" - " insert into mysql.func values" + " replace into mysql.func values" " ('spider_direct_sql', 2, 'ha_spider.dll', 'function')," " ('spider_bg_direct_sql', 2, 'ha_spider.dll', 'aggregate')," " ('spider_ping_table', 2, 'ha_spider.dll', 'function')," From aae78d76090db99d645a5bca9accaa30ebb7cb2d Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 24 Oct 2023 02:16:46 +0200 Subject: [PATCH 110/158] galera: wsrep-lib submodule update --- wsrep-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsrep-lib b/wsrep-lib index 151d4f8591d..07af42c0528 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit 151d4f8591d26068afda997fb0d1f66b2f7f1964 +Subproject commit 07af42c0528139e54a8018975cf55eee3daffab3 From c7feacb0dee696cf602a19da32d1069d0b0ff7c4 Mon Sep 17 00:00:00 2001 From: sjaakola Date: Wed, 18 Oct 2023 14:13:25 +0300 Subject: [PATCH 111/158] 10.4-MDEV-31470 wsrep_sst_method variable validity checking This commit checks the validity of value change of wsrep_sst_method variable. The validity check is same as happens in donor node when incoming SST request is parsed. The commit has also a mtr test: wsrep.wsrep_variables_sst_method which verifies that wsrep_sst_method can be succesfully changed to acceptable values and that the SET command results in error if invalid value was entered. Signed-off-by: Julius Goryavsky --- .../wsrep/r/wsrep_variables_sst_method.result | 61 ++++++++++++++++ .../wsrep/t/wsrep_variables_sst_method.cnf | 7 ++ .../wsrep/t/wsrep_variables_sst_method.test | 50 +++++++++++++ sql/wsrep_sst.cc | 73 +++++++++++-------- 4 files changed, 160 insertions(+), 31 deletions(-) create mode 100644 mysql-test/suite/wsrep/r/wsrep_variables_sst_method.result create mode 100644 mysql-test/suite/wsrep/t/wsrep_variables_sst_method.cnf create mode 100644 mysql-test/suite/wsrep/t/wsrep_variables_sst_method.test diff --git a/mysql-test/suite/wsrep/r/wsrep_variables_sst_method.result b/mysql-test/suite/wsrep/r/wsrep_variables_sst_method.result new file mode 100644 index 00000000000..1c830d412f9 --- /dev/null +++ b/mysql-test/suite/wsrep/r/wsrep_variables_sst_method.result @@ -0,0 +1,61 @@ +SELECT @@wsrep_on; +@@wsrep_on +1 +SET @wsrep_sst_method_saved = @@global.wsrep_sst_method; +/* test currently supported methods */ +SET GLOBAL wsrep_sst_method=DEFAULT; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +rsync +SET GLOBAL wsrep_sst_method='rsync'; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +rsync +SET GLOBAL wsrep_sst_method='mysqldump'; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +mysqldump +SET GLOBAL wsrep_sst_method='mariabackup'; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +mariabackup +SET GLOBAL wsrep_sst_method='backup'; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +backup +SET GLOBAL wsrep_sst_method='backup1.sh'; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +backup1.sh +SET GLOBAL wsrep_sst_method='my method'; +ERROR 42000: Variable 'wsrep_sst_method' can't be set to the value of 'my method' +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +backup1.sh +SHOW WARNINGS; +Level Code Message +Error 1231 Variable 'wsrep_sst_method' can't be set to the value of 'my method' +SET GLOBAL wsrep_sst_method='/method'; +ERROR 42000: Variable 'wsrep_sst_method' can't be set to the value of '/method' +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +backup1.sh +SHOW WARNINGS; +Level Code Message +Error 1231 Variable 'wsrep_sst_method' can't be set to the value of '/method' +SET GLOBAL wsrep_sst_method='method!'; +ERROR 42000: Variable 'wsrep_sst_method' can't be set to the value of 'method!' +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +backup1.sh +SHOW WARNINGS; +Level Code Message +Error 1231 Variable 'wsrep_sst_method' can't be set to the value of 'method!' +SET GLOBAL wsrep_sst_method='method;'; +ERROR 42000: Variable 'wsrep_sst_method' can't be set to the value of 'method;' +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +backup1.sh +SHOW WARNINGS; +Level Code Message +Error 1231 Variable 'wsrep_sst_method' can't be set to the value of 'method;' diff --git a/mysql-test/suite/wsrep/t/wsrep_variables_sst_method.cnf b/mysql-test/suite/wsrep/t/wsrep_variables_sst_method.cnf new file mode 100644 index 00000000000..b1c96d2614d --- /dev/null +++ b/mysql-test/suite/wsrep/t/wsrep_variables_sst_method.cnf @@ -0,0 +1,7 @@ +!include ../my.cnf + +[mysqld.1] +wsrep-on=ON +wsrep-cluster-address=gcomm:// +wsrep-provider=@ENV.WSREP_PROVIDER +binlog-format=ROW diff --git a/mysql-test/suite/wsrep/t/wsrep_variables_sst_method.test b/mysql-test/suite/wsrep/t/wsrep_variables_sst_method.test new file mode 100644 index 00000000000..b41718792a2 --- /dev/null +++ b/mysql-test/suite/wsrep/t/wsrep_variables_sst_method.test @@ -0,0 +1,50 @@ +--source include/have_wsrep.inc +--source include/have_innodb.inc + +SELECT @@wsrep_on; + +SET @wsrep_sst_method_saved = @@global.wsrep_sst_method; + +/* test currently supported methods */ +SET GLOBAL wsrep_sst_method=DEFAULT; +SELECT @@global.wsrep_sst_method; + +SET GLOBAL wsrep_sst_method='rsync'; +SELECT @@global.wsrep_sst_method; + +SET GLOBAL wsrep_sst_method='mysqldump'; +SELECT @@global.wsrep_sst_method; + +SET GLOBAL wsrep_sst_method='mariabackup'; +SELECT @@global.wsrep_sst_method; + +SET GLOBAL wsrep_sst_method='backup'; +SELECT @@global.wsrep_sst_method; + +SET GLOBAL wsrep_sst_method='backup1.sh'; +SELECT @@global.wsrep_sst_method; + +--error ER_WRONG_VALUE_FOR_VAR +SET GLOBAL wsrep_sst_method='my method'; +SELECT @@global.wsrep_sst_method; +SHOW WARNINGS; + +--error ER_WRONG_VALUE_FOR_VAR +SET GLOBAL wsrep_sst_method='/method'; +SELECT @@global.wsrep_sst_method; +SHOW WARNINGS; + +--error ER_WRONG_VALUE_FOR_VAR +SET GLOBAL wsrep_sst_method='method!'; +SELECT @@global.wsrep_sst_method; +SHOW WARNINGS; + +--error ER_WRONG_VALUE_FOR_VAR +SET GLOBAL wsrep_sst_method='method;'; +SELECT @@global.wsrep_sst_method; +SHOW WARNINGS; + + +--disable_query_log +SET @@global.wsrep_sst_method = @wsrep_sst_method_saved; +--enable_query_log diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index a0540744c96..6591359b8f7 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -172,6 +172,36 @@ static void* wsrep_sst_joiner_monitor_thread(void *arg __attribute__((unused))) return NULL; } +/* return true if character can be a part of a filename */ +static bool filename_char(int const c) +{ + return isalnum(c) || (c == '-') || (c == '_') || (c == '.'); +} + +/* return true if character can be a part of an address string */ +static bool address_char(int const c) +{ + return filename_char(c) || + (c == ':') || (c == '[') || (c == ']') || (c == '/'); +} + +static bool check_request_str(const char* const str, + bool (*check) (int c), + bool log_warn = true) +{ + for (size_t i(0); str[i] != '\0'; ++i) + { + if (!check(str[i])) + { + if (log_warn) WSREP_WARN("Illegal character in state transfer request: %i (%c).", + str[i], str[i]); + return true; + } + } + + return false; +} + bool wsrep_sst_method_check (sys_var *self, THD* thd, set_var* var) { if ((! var->save_result.string_value.str) || @@ -183,6 +213,16 @@ bool wsrep_sst_method_check (sys_var *self, THD* thd, set_var* var) return 1; } + /* check also that method name is alphanumeric string */ + if (check_request_str(var->save_result.string_value.str, + filename_char, false)) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, + var->save_result.string_value.str ? + var->save_result.string_value.str : "NULL"); + return 1; + } + return 0; } @@ -1920,35 +1960,6 @@ static int sst_donate_other (const char* method, return arg.err; } -/* return true if character can be a part of a filename */ -static bool filename_char(int const c) -{ - return isalnum(c) || (c == '-') || (c == '_') || (c == '.'); -} - -/* return true if character can be a part of an address string */ -static bool address_char(int const c) -{ - return filename_char(c) || - (c == ':') || (c == '[') || (c == ']') || (c == '/'); -} - -static bool check_request_str(const char* const str, - bool (*check) (int c)) -{ - for (size_t i(0); str[i] != '\0'; ++i) - { - if (!check(str[i])) - { - WSREP_WARN("Illegal character in state transfer request: %i (%c).", - str[i], str[i]); - return true; - } - } - - return false; -} - int wsrep_sst_donate(const std::string& msg, const wsrep::gtid& current_gtid, const bool bypass) @@ -1956,7 +1967,7 @@ int wsrep_sst_donate(const std::string& msg, const char* method= msg.data(); size_t method_len= strlen (method); - if (check_request_str(method, filename_char)) + if (check_request_str(method, filename_char, true)) { WSREP_ERROR("Bad SST method name. SST canceled."); return WSREP_CB_FAILURE; @@ -1978,7 +1989,7 @@ int wsrep_sst_donate(const std::string& msg, addr= data; } - if (check_request_str(addr, address_char)) + if (check_request_str(addr, address_char, true)) { WSREP_ERROR("Bad SST address string. SST canceled."); return WSREP_CB_FAILURE; From fefea242226fe15255b50cd285afbd94cab2d44a Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sat, 21 Oct 2023 14:21:48 +1100 Subject: [PATCH 112/158] MDEV-32535 Update signal hander user info more compassion and correct url Blaming hardware and poor libraries seems on the rare end of the scale of things that go wrong. Accept the blame, apologize, and kindly request a bug report. Also url change on stack traces is changed to include mariadbd. Thanks Vlad for also raising that blaming was wrong. --- sql/signal_handler.cc | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index 96c067b717e..ade2eaa2a10 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -170,11 +170,8 @@ extern "C" sig_handler handle_fatal_signal(int sig) my_safe_printf_stderr("[ERROR] mysqld got " SIGNAL_FMT " ;\n",sig); my_safe_printf_stderr("%s", - "This could be because you hit a bug. It is also possible that this binary\n" - "or one of the libraries it was linked against is corrupt, improperly built,\n" - "or misconfigured. This error can also be caused by malfunctioning hardware.\n\n"); - - my_safe_printf_stderr("%s", + "Sorry, we probably made a mistake, and this is a bug.\n\n" + "Your assistance in bug reporting will enable us to fix this for the next release.\n" "To report this bug, see https://mariadb.com/kb/en/reporting-bugs\n\n"); my_safe_printf_stderr("%s", @@ -306,7 +303,7 @@ extern "C" sig_handler handle_fatal_signal(int sig) } my_safe_printf_stderr("%s", "The manual page at " - "https://mariadb.com/kb/en/how-to-produce-a-full-stack-trace-for-mysqld/ contains\n" + "https://mariadb.com/kb/en/how-to-produce-a-full-stack-trace-for-mariadbd/ contains\n" "information that should help you find out what is causing the crash.\n"); #endif /* HAVE_STACKTRACE */ From d2a867cdf08850563a39381aee09b4528442feb8 Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 23 Oct 2023 20:24:24 +0300 Subject: [PATCH 113/158] MDEV-32532 Assertion failure in ddl_log_increment_phase_no_lock upon .. The reason for the bug was that spider plugin does some ALTER TABLE commands before recovery is done, which was not expected. Fixed by resetting the ddl_log lists in create_ddl_log() --- sql/ddl_log.cc | 41 +++++++++++-------- .../mysql-test/spider/bugfix/r/ddl_log.result | 12 ++++++ .../mysql-test/spider/bugfix/t/ddl_log.test | 17 ++++++++ 3 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/ddl_log.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/ddl_log.test diff --git a/sql/ddl_log.cc b/sql/ddl_log.cc index 5e13a8663dc..30b15a95de1 100644 --- a/sql/ddl_log.cc +++ b/sql/ddl_log.cc @@ -181,6 +181,8 @@ static constexpr unsigned DDL_LOG_BACKUP_OFFSET_POS= 8; /* Sum of the above variables */ static constexpr unsigned DDL_LOG_HEADER_SIZE= 4+2+2+1; +static void ddl_log_free_lists(); + /** Sync the ddl log file. @@ -734,6 +736,7 @@ static bool create_ddl_log() char file_name[FN_REFLEN]; DBUG_ENTER("create_ddl_log"); + ddl_log_free_lists(); global_ddl_log.open= 0; global_ddl_log.created= 1; global_ddl_log.num_entries= 0; @@ -2826,24 +2829,11 @@ int ddl_log_execute_recovery() } -/** - Release all memory allocated to the ddl log and delete the ddl log -*/ - -void ddl_log_release() +static void ddl_log_free_lists() { - char file_name[FN_REFLEN]; - DDL_LOG_MEMORY_ENTRY *free_list; - DDL_LOG_MEMORY_ENTRY *used_list; - DBUG_ENTER("ddl_log_release"); + DDL_LOG_MEMORY_ENTRY *free_list= global_ddl_log.first_free; + DDL_LOG_MEMORY_ENTRY *used_list= global_ddl_log.first_used; - if (!global_ddl_log.initialized) - DBUG_VOID_RETURN; - - global_ddl_log.initialized= 0; - - free_list= global_ddl_log.first_free; - used_list= global_ddl_log.first_used; while (used_list) { DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry; @@ -2856,6 +2846,25 @@ void ddl_log_release() my_free(free_list); free_list= tmp; } + global_ddl_log.first_free= global_ddl_log.first_used= 0; +} + + +/** + Release all memory allocated to the ddl log and delete the ddl log +*/ + +void ddl_log_release() +{ + char file_name[FN_REFLEN]; + DBUG_ENTER("ddl_log_release"); + + if (!global_ddl_log.initialized) + DBUG_VOID_RETURN; + + global_ddl_log.initialized= 0; + ddl_log_free_lists(); + my_free(global_ddl_log.file_entry_buf); global_ddl_log.file_entry_buf= 0; close_ddl_log(); diff --git a/storage/spider/mysql-test/spider/bugfix/r/ddl_log.result b/storage/spider/mysql-test/spider/bugfix/r/ddl_log.result new file mode 100644 index 00000000000..2abbcc6bc30 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/ddl_log.result @@ -0,0 +1,12 @@ +# restart: --plugin-load-add=ha_spider +# +# MDEV-32532 Assertion failure in ddl_log_increment_phase_no_lock upon +# partition operations with spider plugin loaded +# +CREATE TABLE t1 (a INT) PARTITION BY HASH (a) PARTITIONS 2; +ALTER TABLE t1 REBUILD PARTITION p0; +drop table t1; +# +# End of 10.10 +# +uninstall plugin spider; diff --git a/storage/spider/mysql-test/spider/bugfix/t/ddl_log.test b/storage/spider/mysql-test/spider/bugfix/t/ddl_log.test new file mode 100644 index 00000000000..4fe45b83dea --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/ddl_log.test @@ -0,0 +1,17 @@ +--source include/have_partition.inc +--let $restart_parameters= --plugin-load-add=ha_spider +--source include/restart_mysqld.inc + +--echo # +--echo # MDEV-32532 Assertion failure in ddl_log_increment_phase_no_lock upon +--echo # partition operations with spider plugin loaded +--echo # +CREATE TABLE t1 (a INT) PARTITION BY HASH (a) PARTITIONS 2; +ALTER TABLE t1 REBUILD PARTITION p0; +drop table t1; + +--echo # +--echo # End of 10.10 +--echo # + +uninstall plugin spider; From b78b77e77db22321e2fa49afaea5564c083ca66a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 24 Oct 2023 14:33:14 +0300 Subject: [PATCH 114/158] MDEV-32530 Race condition in lock_wait_rpl_report() After acquiring lock_sys.latch, always load trx->lock.wait_lock. It could have changed by another thread that did lock_rec_move() and released lock_sys.latch right before lock_sys.wr_lock_try() succeeded. This regression was introduced in commit e039720bf3494a35b34eb0ddc55af170a1807723 (MDEV-32096). Reviewed by: Vladislav Lesin --- storage/innobase/lock/lock0lock.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 31e02d2451a..df51ceb16d8 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1812,8 +1812,14 @@ func_exit: } else if (!wait_lock->is_waiting()) { - wait_lock= nullptr; - goto func_exit; + wait_lock= trx->lock.wait_lock; + if (!wait_lock) + goto func_exit; + if (!wait_lock->is_waiting()) + { + wait_lock= nullptr; + goto func_exit; + } } if (wait_lock->is_table()) From ea42c4baac0fbf213d26400ecff42a98d974ab34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Oct 2023 08:26:34 +0300 Subject: [PATCH 115/158] MDEV-32050 preparation: Simplify ROLLBACK undo_node_t::state: Replaced with bool is_temp. row_undo_rec_get(): Do not copy the undo log record. The motivation of the copying was to not hold latches on the undo pages and therefore to avoid deadlocks due to lock order inversion a.k.a. latching order violation: It is not allowed to wait for an index page latch while holding an undo page latch, because MVCC reads would first acquire an index page latch and then an undo page latch. But, in rollback, we do not actually need any latch on our own undo pages. The transaction that is being rolled back is the exclusive owner of its undo log records. They cannot be overwritten by other threads until the rollback is complete. Therefore, a buffer fix will protect the undo log record just fine, by preventing page eviction. We still must initially acquire a shared latch on each undo page, to avoid a race condition like the one that was fixed in commit b102872ad50cce5959ad95369740766d14e9e48c. row_undo_ins_parse_undo_rec(): The first two bytes of the undo log record now are the pointer to the next record within the page, not a length. Reviewed by: Vladislav Lesin --- storage/innobase/include/row0undo.h | 16 +------- storage/innobase/row/row0uins.cc | 6 +-- storage/innobase/row/row0umod.cc | 4 +- storage/innobase/row/row0undo.cc | 64 +++++++++++------------------ 4 files changed, 29 insertions(+), 61 deletions(-) diff --git a/storage/innobase/include/row0undo.h b/storage/innobase/include/row0undo.h index 4357a908ca3..fb872cbd979 100644 --- a/storage/innobase/include/row0undo.h +++ b/storage/innobase/include/row0undo.h @@ -78,24 +78,10 @@ just in the case where the transaction modified the same record several times and another thread is currently doing the undo for successive versions of that index record. */ -/** Execution state of an undo node */ -enum undo_exec { - UNDO_NODE_FETCH_NEXT = 1, /*!< we should fetch the next - undo log record */ - /** rollback an insert into persistent table */ - UNDO_INSERT_PERSISTENT, - /** rollback an update (or delete) in a persistent table */ - UNDO_UPDATE_PERSISTENT, - /** rollback an insert into temporary table */ - UNDO_INSERT_TEMPORARY, - /** rollback an update (or delete) in a temporary table */ - UNDO_UPDATE_TEMPORARY, -}; - /** Undo node structure */ struct undo_node_t{ que_common_t common; /*!< node type: QUE_NODE_UNDO */ - undo_exec state; /*!< rollback execution state */ + bool is_temp;/*!< whether this is a temporary table */ trx_t* trx; /*!< trx for which undo is done */ roll_ptr_t roll_ptr;/*!< roll pointer to undo log record */ trx_undo_rec_t* undo_rec;/*!< undo log record */ diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index ff1a34b46c3..20df11984e9 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -389,8 +389,6 @@ static bool row_undo_ins_parse_undo_rec(undo_node_t* node, bool dict_locked) ulint dummy; bool dummy_extern; - ut_ad(node->state == UNDO_INSERT_PERSISTENT - || node->state == UNDO_INSERT_TEMPORARY); ut_ad(node->trx->in_rollback); ut_ad(trx_undo_roll_ptr_is_insert(node->roll_ptr)); @@ -398,7 +396,7 @@ static bool row_undo_ins_parse_undo_rec(undo_node_t* node, bool dict_locked) &dummy_extern, &undo_no, &table_id); node->update = NULL; - if (node->state == UNDO_INSERT_PERSISTENT) { + if (!node->is_temp) { node->table = dict_table_open_on_id(table_id, dict_locked, DICT_TABLE_OP_NORMAL); } else if (!dict_locked) { @@ -428,7 +426,7 @@ static bool row_undo_ins_parse_undo_rec(undo_node_t* node, bool dict_locked) || dict_table_is_file_per_table(table) == !is_system_tablespace(table->space_id)); size_t len = mach_read_from_2(node->undo_rec) - + size_t(node->undo_rec - ptr) - 2; + - page_offset(ptr) - 2; const span name(reinterpret_cast(ptr), len); if (strlen(table->name.m_name) != len diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 50e15e03cc9..a546963617f 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -1085,8 +1085,6 @@ static bool row_undo_mod_parse_undo_rec(undo_node_t* node, bool dict_locked) ulint cmpl_info; bool dummy_extern; - ut_ad(node->state == UNDO_UPDATE_PERSISTENT - || node->state == UNDO_UPDATE_TEMPORARY); ut_ad(node->trx->in_rollback); ut_ad(!trx_undo_roll_ptr_is_insert(node->roll_ptr)); @@ -1095,7 +1093,7 @@ static bool row_undo_mod_parse_undo_rec(undo_node_t* node, bool dict_locked) &dummy_extern, &undo_no, &table_id); node->rec_type = type; - if (node->state == UNDO_UPDATE_PERSISTENT) { + if (!node->is_temp) { node->table = dict_table_open_on_id(table_id, dict_locked, DICT_TABLE_OP_NORMAL); } else if (!dict_locked) { diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc index 4d6d779eee6..8a1041c8576 100644 --- a/storage/innobase/row/row0undo.cc +++ b/storage/innobase/row/row0undo.cc @@ -140,7 +140,6 @@ row_undo_node_create( undo->common.type = QUE_NODE_UNDO; undo->common.parent = parent; - undo->state = UNDO_NODE_FETCH_NEXT; undo->trx = trx; btr_pcur_init(&(undo->pcur)); @@ -219,8 +218,7 @@ row_undo_search_clust_to_pcur( log, first mark them DATA_MISSING. So we will know if the value gets updated */ if (node->table->n_v_cols - && (node->state == UNDO_UPDATE_PERSISTENT - || node->state == UNDO_UPDATE_TEMPORARY) + && !trx_undo_roll_ptr_is_insert(node->roll_ptr) && !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { for (ulint i = 0; i < dict_table_get_n_v_cols(node->table); i++) { @@ -258,8 +256,9 @@ func_exit: /** Get the latest undo log record for rollback. @param[in,out] node rollback context -@return whether an undo log record was fetched */ -static bool row_undo_rec_get(undo_node_t* node) +@return undo block for the undo log record +@retval nullptr if no undo log record was fetched */ +static buf_block_t* row_undo_rec_get(undo_node_t* node) { trx_t* trx = node->trx; @@ -272,7 +271,7 @@ static bool row_undo_rec_get(undo_node_t* node) trx_undo_t* update = trx->rsegs.m_redo.undo; trx_undo_t* temp = trx->rsegs.m_noredo.undo; const undo_no_t limit = trx->roll_limit; - bool is_temp = false; + node->is_temp = false; ut_ad(!update || !temp || update->empty() || temp->empty() || update->top_undo_no != temp->top_undo_no); @@ -288,7 +287,7 @@ static bool row_undo_rec_get(undo_node_t* node) if (temp && !temp->empty() && temp->top_undo_no >= limit) { if (!undo || undo->top_undo_no < temp->top_undo_no) { undo = temp; - is_temp = true; + node->is_temp = true; } } @@ -299,14 +298,14 @@ static bool row_undo_rec_get(undo_node_t* node) later, we will default to a full ROLLBACK. */ trx->roll_limit = 0; trx->in_rollback = false; - return false; + return nullptr; } ut_ad(!undo->empty()); ut_ad(limit <= undo->top_undo_no); node->roll_ptr = trx_undo_build_roll_ptr( - false, trx_sys.rseg_id(undo->rseg, !is_temp), + false, trx_sys.rseg_id(undo->rseg, !node->is_temp), undo->top_page_no, undo->top_offset); mtr_t mtr; @@ -316,7 +315,7 @@ static bool row_undo_rec_get(undo_node_t* node) page_id_t(undo->rseg->space->id, undo->top_page_no), 0, RW_S_LATCH, &mtr); if (!undo_page) { - return false; + return nullptr; } uint16_t offset = undo->top_offset; @@ -338,12 +337,17 @@ static bool row_undo_rec_get(undo_node_t* node) ut_ad(undo->empty()); } - node->undo_rec = trx_undo_rec_copy(undo_page->page.frame + offset, - node->heap); + undo_page->fix(); mtr.commit(); - if (UNIV_UNLIKELY(!node->undo_rec)) { - return false; + node->undo_rec = undo_page->page.frame + offset; + + const size_t end = mach_read_from_2(node->undo_rec); + if (UNIV_UNLIKELY(end <= offset + || end >= srv_page_size - FIL_PAGE_DATA_END)) { + undo_page->unfix(); + node->undo_rec = nullptr; + return nullptr; } switch (node->undo_rec[2] & (TRX_UNDO_CMPL_INFO_MULT - 1)) { @@ -360,17 +364,11 @@ static bool row_undo_rec_get(undo_node_t* node) case TRX_UNDO_INSERT_REC: case TRX_UNDO_EMPTY: node->roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS; - node->state = is_temp - ? UNDO_INSERT_TEMPORARY : UNDO_INSERT_PERSISTENT; - break; - default: - node->state = is_temp - ? UNDO_UPDATE_TEMPORARY : UNDO_UPDATE_PERSISTENT; } trx->undo_no = node->undo_no = trx_undo_rec_get_undo_no( node->undo_rec); - return true; + return undo_page; } /***********************************************************//** @@ -387,29 +385,17 @@ row_undo( { ut_ad(node->trx->in_rollback); - if (node->state == UNDO_NODE_FETCH_NEXT && !row_undo_rec_get(node)) { + buf_block_t* undo_page = row_undo_rec_get(node); + + if (!undo_page) { /* Rollback completed for this query thread */ thr->run_node = que_node_get_parent(node); return DB_SUCCESS; } - dberr_t err; - - switch (node->state) { - case UNDO_INSERT_PERSISTENT: - case UNDO_INSERT_TEMPORARY: - err = row_undo_ins(node, thr); - break; - case UNDO_UPDATE_PERSISTENT: - case UNDO_UPDATE_TEMPORARY: - err = row_undo_mod(node, thr); - break; - default: - ut_ad("wrong state" == 0); - err = DB_CORRUPTION; - } - - node->state = UNDO_NODE_FETCH_NEXT; + dberr_t err = trx_undo_roll_ptr_is_insert(node->roll_ptr) + ? row_undo_ins(node, thr) : row_undo_mod(node, thr); + undo_page->unfix(); btr_pcur_close(&(node->pcur)); mem_heap_empty(node->heap); From 9bb5d9fe8b478d6d332afee17a21252d04f89f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Oct 2023 08:27:08 +0300 Subject: [PATCH 116/158] MDEV-32050: Clean up log parsing purge_node_t, undo_node_t: Change the type of rec_type and cmpl_info to byte, because this data is being extracted from a single byte. UndoRecApplier: Change type and cmpl_info to be of type byte, and move them next to the 16-bit offset field to minimize alignment bloat. row_purge_parse_undo_rec(): Remove some redundant code. Purge will be started by innodb_ddl_recovery_done(), at which point all necessary subsystems will have been initialized. trx_purge_rec_t::undo_rec: Point to const. Reviewed by: Vladislav Lesin --- storage/innobase/include/row0purge.h | 7 ++--- storage/innobase/include/row0undo.h | 2 +- storage/innobase/include/trx0rec.h | 4 +-- storage/innobase/include/trx0undo.h | 8 ++--- storage/innobase/row/row0purge.cc | 47 ++++++++-------------------- storage/innobase/row/row0uins.cc | 2 +- storage/innobase/row/row0umod.cc | 4 +-- storage/innobase/trx/trx0purge.cc | 23 +++++--------- storage/innobase/trx/trx0rec.cc | 10 +++--- storage/innobase/trx/trx0trx.cc | 4 +-- 10 files changed, 41 insertions(+), 70 deletions(-) diff --git a/storage/innobase/include/row0purge.h b/storage/innobase/include/row0purge.h index b1390fd1ef1..389a061cba0 100644 --- a/storage/innobase/include/row0purge.h +++ b/storage/innobase/include/row0purge.h @@ -84,7 +84,7 @@ row_purge_step( struct trx_purge_rec_t { /** Record to purge */ - trx_undo_rec_t *undo_rec; + const trx_undo_rec_t *undo_rec; /** File pointer to undo record */ roll_ptr_t roll_ptr; }; @@ -99,8 +99,9 @@ struct purge_node_t{ undo_no_t undo_no;/*!< undo number of the record */ - ulint rec_type;/*!< undo log record type: TRX_UNDO_INSERT_REC, + byte rec_type;/*!< undo log record type: TRX_UNDO_INSERT_REC, ... */ + byte cmpl_info;/* compiler analysis info of an update */ private: /** latest unavailable table ID (do not bother looking up again) */ table_id_t unavailable_table_id; @@ -110,8 +111,6 @@ private: public: dict_table_t* table; /*!< table where purge is done */ - ulint cmpl_info;/* compiler analysis info of an update */ - upd_t* update; /*!< update vector for a clustered index record */ const dtuple_t* ref; /*!< NULL, or row reference to the next row to diff --git a/storage/innobase/include/row0undo.h b/storage/innobase/include/row0undo.h index fb872cbd979..ae067a8af4f 100644 --- a/storage/innobase/include/row0undo.h +++ b/storage/innobase/include/row0undo.h @@ -86,7 +86,7 @@ struct undo_node_t{ roll_ptr_t roll_ptr;/*!< roll pointer to undo log record */ trx_undo_rec_t* undo_rec;/*!< undo log record */ undo_no_t undo_no;/*!< undo number of the record */ - ulint rec_type;/*!< undo log record type: TRX_UNDO_INSERT_REC, + byte rec_type;/*!< undo log record type: TRX_UNDO_INSERT_REC, ... */ trx_id_t new_trx_id; /*!< trx id to restore to clustered index record */ diff --git a/storage/innobase/include/trx0rec.h b/storage/innobase/include/trx0rec.h index 58ec5ab1707..3251316186d 100644 --- a/storage/innobase/include/trx0rec.h +++ b/storage/innobase/include/trx0rec.h @@ -74,9 +74,9 @@ const byte* trx_undo_rec_get_pars( /*==================*/ const trx_undo_rec_t* undo_rec, /*!< in: undo log record */ - ulint* type, /*!< out: undo record type: + byte* type, /*!< out: undo record type: TRX_UNDO_INSERT_REC, ... */ - ulint* cmpl_info, /*!< out: compiler info, relevant only + byte* cmpl_info, /*!< out: compiler info, relevant only for update type records */ bool* updated_extern, /*!< out: true if we updated an externally stored fild */ diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h index 1a5dfbd874f..de2ab51f844 100644 --- a/storage/innobase/include/trx0undo.h +++ b/storage/innobase/include/trx0undo.h @@ -310,14 +310,14 @@ class UndorecApplier page_id_t page_id; /** Undo log record pointer */ const trx_undo_rec_t *undo_rec; + /** Undo log record type */ + byte type; + /** compiler information */ + byte cmpl_info; /** Offset of the undo log record within the block */ uint16_t offset; /** Transaction id of the undo log */ const trx_id_t trx_id; - /** Undo log record type */ - ulint type; - /** compiler information */ - ulint cmpl_info; /** Update vector */ upd_t *update; /** memory heap which can be used to build previous version of diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index f9ce18c7166..2329877c355 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -48,7 +48,6 @@ Created 3/14/1997 Heikki Tuuri #include "ha_innodb.h" #include "fil0fil.h" #include "debug_sync.h" -#include /************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there @@ -748,7 +747,7 @@ row_purge_upd_exist_or_extern_func( const que_thr_t*thr, /*!< in: query thread */ #endif /* UNIV_DEBUG */ purge_node_t* node, /*!< in: row purge node */ - trx_undo_rec_t* undo_rec) /*!< in: record to purge */ + const trx_undo_rec_t* undo_rec) /*!< in: record to purge */ { mem_heap_t* heap; @@ -1023,7 +1022,7 @@ static bool row_purge_parse_undo_rec( purge_node_t* node, - trx_undo_rec_t* undo_rec, + const trx_undo_rec_t* undo_rec, que_thr_t* thr, bool* updated_extern) { @@ -1032,7 +1031,7 @@ row_purge_parse_undo_rec( table_id_t table_id; roll_ptr_t roll_ptr; byte info_bits; - ulint type; + byte type; const byte* ptr = trx_undo_rec_get_pars( undo_rec, &type, &node->cmpl_info, @@ -1097,27 +1096,6 @@ try_again: already_locked: ut_ad(!node->table->is_temporary()); - switch (type) { - case TRX_UNDO_INSERT_METADATA: - case TRX_UNDO_INSERT_REC: - break; - default: - if (!node->table->n_v_cols || node->table->vc_templ - || !dict_table_has_indexed_v_cols(node->table)) { - break; - } - /* Need server fully up for virtual column computation */ - if (!mysqld_server_started) { - - node->close_table(); - if (srv_shutdown_state > SRV_SHUTDOWN_NONE) { - return(false); - } - std::this_thread::sleep_for(std::chrono::seconds(1)); - goto try_again; - } - } - clust_index = dict_table_get_first_index(node->table); if (!clust_index || clust_index->is_corrupted()) { @@ -1133,15 +1111,16 @@ already_locked: err_exit: node->close_table(); node->skip(table_id, trx_id); - return(false); + return false; } node->last_table_id = table_id; - if (type == TRX_UNDO_INSERT_METADATA) { + switch (type) { + case TRX_UNDO_INSERT_METADATA: node->ref = &trx_undo_metadata; - return(true); - } else if (type == TRX_UNDO_EMPTY) { + return true; + case TRX_UNDO_EMPTY: node->ref = nullptr; return true; } @@ -1180,7 +1159,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result)) bool row_purge_record_func( purge_node_t* node, - trx_undo_rec_t* undo_rec, + const trx_undo_rec_t* undo_rec, #if defined UNIV_DEBUG || defined WITH_WSREP const que_thr_t*thr, #endif /* UNIV_DEBUG || WITH_WSREP */ @@ -1251,7 +1230,7 @@ void row_purge( /*======*/ purge_node_t* node, /*!< in: row purge node */ - trx_undo_rec_t* undo_rec, /*!< in: record to purge */ + const trx_undo_rec_t* undo_rec, /*!< in: record to purge */ que_thr_t* thr) /*!< in: query thread */ { if (undo_rec != reinterpret_cast(-1)) { @@ -1283,9 +1262,9 @@ inline void purge_node_t::start() ref= nullptr; index= nullptr; update= nullptr; - found_clust= FALSE; - rec_type= ULINT_UNDEFINED; - cmpl_info= ULINT_UNDEFINED; + found_clust= false; + rec_type= 0; + cmpl_info= 0; if (!purge_thd) purge_thd= current_thd; } diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index 20df11984e9..23255cc98f9 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -386,7 +386,7 @@ static bool row_undo_ins_parse_undo_rec(undo_node_t* node, bool dict_locked) const byte* ptr; undo_no_t undo_no; table_id_t table_id; - ulint dummy; + byte dummy; bool dummy_extern; ut_ad(node->trx->in_rollback); diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index a546963617f..b8dd59dda39 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -1081,8 +1081,8 @@ static bool row_undo_mod_parse_undo_rec(undo_node_t* node, bool dict_locked) trx_id_t trx_id; roll_ptr_t roll_ptr; byte info_bits; - ulint type; - ulint cmpl_info; + byte type; + byte cmpl_info; bool dummy_extern; ut_ad(node->trx->in_rollback); diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index ef727be7f03..a606d3852ad 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -1109,9 +1109,9 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) que_thr_t* thr; ulint i; ulint n_pages_handled = 0; - ulint n_thrs = UT_LIST_GET_LEN(purge_sys.query->thrs); ut_a(n_purge_threads > 0); + ut_a(UT_LIST_GET_LEN(purge_sys.query->thrs) >= n_purge_threads); purge_sys.head = purge_sys.tail; @@ -1141,7 +1141,6 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) /* Fetch and parse the UNDO records. The UNDO records are added to a per purge node vector. */ thr = UT_LIST_GET_FIRST(purge_sys.query->thrs); - ut_a(n_thrs > 0 && thr != NULL); ut_ad(purge_sys.head <= purge_sys.tail); @@ -1151,13 +1150,8 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) mem_heap_empty(purge_sys.heap); while (UNIV_LIKELY(srv_undo_sources) || !srv_fast_shutdown) { - purge_node_t* node; trx_purge_rec_t purge_rec; - /* Get the purge node. */ - node = (purge_node_t*) thr->child; - ut_a(que_node_get_type(node) == QUE_NODE_PURGE); - /* Track the max {trx_id, undo_no} for truncating the UNDO logs once we have purged the records. */ @@ -1170,7 +1164,7 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) &purge_rec.roll_ptr, &n_pages_handled, purge_sys.heap); - if (purge_rec.undo_rec == NULL) { + if (!purge_rec.undo_rec) { break; } else if (purge_rec.undo_rec == reinterpret_cast(-1)) { @@ -1182,9 +1176,7 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) purge_node_t *& table_node = table_id_map[table_id]; - if (table_node) { - node = table_node; - } else { + if (!table_node) { thr = UT_LIST_GET_NEXT(thrs, thr); if (!(++i % n_purge_threads)) { @@ -1192,11 +1184,11 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) purge_sys.query->thrs); } - ut_a(thr != NULL); - table_node = node; + table_node = static_cast(thr->child); + ut_a(que_node_get_type(table_node) == QUE_NODE_PURGE); } - node->undo_recs.push(purge_rec); + table_node->undo_recs.push(purge_rec); if (n_pages_handled >= srv_purge_batch_size) { break; @@ -1256,7 +1248,6 @@ Run a purge batch. @return number of undo log pages handled in the batch */ TRANSACTIONAL_TARGET ulint trx_purge(ulint n_tasks, ulint history_size) { - que_thr_t* thr = NULL; ulint n_pages_handled; ut_ad(n_tasks > 0); @@ -1290,6 +1281,8 @@ TRANSACTIONAL_TARGET ulint trx_purge(ulint n_tasks, ulint history_size) srv_dml_needed_delay = delay; } + que_thr_t* thr = nullptr; + /* Submit tasks to workers queue if using multi-threaded purge. */ for (ulint i = n_tasks; --i; ) { thr = que_fork_scheduler_round_robin(purge_sys.query, thr); diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 364877346c0..c6f8f01fa2c 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -484,9 +484,9 @@ const byte* trx_undo_rec_get_pars( /*==================*/ const trx_undo_rec_t* undo_rec, /*!< in: undo log record */ - ulint* type, /*!< out: undo record type: + byte* type, /*!< out: undo record type: TRX_UNDO_INSERT_REC, ... */ - ulint* cmpl_info, /*!< out: compiler info, relevant only + byte* cmpl_info, /*!< out: compiler info, relevant only for update type records */ bool* updated_extern, /*!< out: true if we updated an externally stored fild */ @@ -503,7 +503,7 @@ trx_undo_rec_get_pars( *type = type_cmpl & (TRX_UNDO_CMPL_INFO_MULT - 1); ut_ad(*type >= TRX_UNDO_RENAME_TABLE); ut_ad(*type <= TRX_UNDO_EMPTY); - *cmpl_info = type_cmpl / TRX_UNDO_CMPL_INFO_MULT; + *cmpl_info = byte(type_cmpl / TRX_UNDO_CMPL_INFO_MULT); *undo_no = mach_read_next_much_compressed(&ptr); *table_id = mach_read_next_much_compressed(&ptr); @@ -2153,14 +2153,14 @@ trx_undo_prev_version_build( { dtuple_t* entry; trx_id_t rec_trx_id; - ulint type; undo_no_t undo_no; table_id_t table_id; trx_id_t trx_id; roll_ptr_t roll_ptr; upd_t* update; + byte type; byte info_bits; - ulint cmpl_info; + byte cmpl_info; bool dummy_extern; byte* buf; diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index f35a96fe76f..1ffc8c76189 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -587,10 +587,10 @@ static dberr_t trx_resurrect_table_locks(trx_t *trx, const trx_undo_t &undo) do { - ulint type; + byte type; + byte cmpl_info; undo_no_t undo_no; table_id_t table_id; - ulint cmpl_info; bool updated_extern; if (undo_block != block) From 21bec970440ae94c66c5eb9a6e3524f45fe2bbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Oct 2023 08:27:27 +0300 Subject: [PATCH 117/158] MDEV-32050: Clean up online ALTER UndorecApplier::assign_rec(): Remove. We will pass the undo record to UndorecApplier::apply_undo_rec(). There is no need to copy the undo record, because nothing else can write to the undo log pages that belong to an active or incomplete transaction. trx_t::apply_log(): Buffer-fix the undo page across mini-transaction boundary in order to avoid repeated page lookups. Reviewed by: Vladislav Lesin --- storage/innobase/include/trx0undo.h | 18 ++++-------------- storage/innobase/row/row0log.cc | 11 ++++++++--- storage/innobase/row/row0umod.cc | 2 +- storage/innobase/row/row0upd.cc | 8 +++----- storage/innobase/trx/trx0rec.cc | 2 +- storage/innobase/trx/trx0undo.cc | 26 ++++++++++---------------- 6 files changed, 27 insertions(+), 40 deletions(-) diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h index de2ab51f844..adddfeac99a 100644 --- a/storage/innobase/include/trx0undo.h +++ b/storage/innobase/include/trx0undo.h @@ -308,13 +308,13 @@ class UndorecApplier { /** Undo log block page id */ page_id_t page_id; - /** Undo log record pointer */ + /** Pointer to within undo log record */ const trx_undo_rec_t *undo_rec; /** Undo log record type */ byte type; /** compiler information */ byte cmpl_info; - /** Offset of the undo log record within the block */ + /** page_offset(undo_rec) of the start of undo_rec */ uint16_t offset; /** Transaction id of the undo log */ const trx_id_t trx_id; @@ -338,15 +338,10 @@ public: page_id= next_page_id; } - /** Assign the undo log record and offset */ - inline void assign_rec(const buf_block_t &block, uint16_t offset); - - uint16_t get_offset() const { return offset; } - page_id_t get_page_id() const { return page_id; } /** Handle the DML undo log and apply it on online indexes */ - inline void apply_undo_rec(); + inline void apply_undo_rec(const trx_undo_rec_t *rec); ~UndorecApplier() { @@ -368,12 +363,7 @@ private: /** Check whether the given roll pointer is generated by the current undo log record information stored. @return true if roll pointer matches with current undo log info */ - bool is_same(roll_ptr_t roll_ptr) const - { - uint16_t offset= static_cast(roll_ptr); - uint32_t page_no= static_cast(roll_ptr >> 16); - return page_no == page_id.page_no() && offset == this->offset; - } + inline bool is_same(roll_ptr_t roll_ptr) const; /** Clear the undo log record information */ void clear_undo_rec() diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index a0931ddf7cf..e1ce8161a02 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -3825,6 +3825,12 @@ dberr_t dict_table_t::clear(que_thr_t *thr) return err; } +inline bool UndorecApplier::is_same(roll_ptr_t roll_ptr) const +{ + return uint16_t(roll_ptr) == offset && + uint32_t(roll_ptr >> 16) == page_id.page_no(); +} + const rec_t * UndorecApplier::get_old_rec(const dtuple_t &tuple, dict_index_t *index, const rec_t **clust_rec, rec_offs **offsets) @@ -3950,8 +3956,7 @@ void UndorecApplier::log_insert(const dtuple_t &tuple, /* Update the row with virtual column values present in the undo log or update vector */ if (type == TRX_UNDO_UPD_DEL_REC) - row_upd_replace_vcol(row, table, update, false, - nullptr, + row_upd_replace_vcol(row, table, update, false, nullptr, (cmpl_info & UPD_NODE_NO_ORD_CHANGE) ? nullptr : undo_rec); else @@ -4073,7 +4078,7 @@ void UndorecApplier::log_update(const dtuple_t &tuple, if (table->n_v_cols) row_upd_replace_vcol(row, table, update, false, nullptr, (cmpl_info & UPD_NODE_NO_ORD_CHANGE) - ? nullptr : this->undo_rec); + ? nullptr : undo_rec); bool success= true; dict_index_t *index= dict_table_get_next_index(clust_index); diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index b8dd59dda39..a01eaea516a 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -1192,7 +1192,7 @@ close_table: row_upd_replace_vcol(node->row, node->table, node->update, false, node->undo_row, (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE) - ? NULL : ptr); + ? nullptr : ptr); } return true; diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index fafe32d029f..bec5384144d 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1060,10 +1060,8 @@ row_upd_replace_vcol( bool is_undo_log = true; /* We will read those unchanged (but indexed) virtual columns in */ - if (ptr != NULL) { - const byte* end_ptr; - - end_ptr = ptr + mach_read_from_2(ptr); + if (ptr) { + const byte* const end_ptr = ptr + mach_read_from_2(ptr); ptr += 2; while (ptr != end_ptr) { @@ -1189,7 +1187,7 @@ row_upd_replace( *ext = NULL; } - row_upd_replace_vcol(row, table, update, true, NULL, NULL); + row_upd_replace_vcol(row, table, update, true, nullptr, nullptr); } /***********************************************************//** diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index c6f8f01fa2c..9b5159a1ad6 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -2335,7 +2335,7 @@ trx_undo_prev_version_build( update vector to dtuple vrow */ if (v_status & TRX_UNDO_GET_OLD_V_VALUE) { row_upd_replace_vcol((dtuple_t*)*vrow, index->table, update, - false, NULL, NULL); + false, nullptr, nullptr); } #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index 4625b5d6cd9..12e2d54b608 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -299,18 +299,13 @@ trx_undo_get_first_rec(const fil_space_t &space, uint32_t page_no, mtr); } -inline void UndorecApplier::assign_rec(const buf_block_t &block, - uint16_t offset) -{ - ut_ad(block.page.lock.have_s()); - this->offset= offset; - this->undo_rec= trx_undo_rec_copy(block.page.frame + offset, heap); -} - -inline void UndorecApplier::apply_undo_rec() +inline void UndorecApplier::apply_undo_rec(const trx_undo_rec_t *rec) { + undo_rec= rec; if (!undo_rec) return; + offset= page_offset(undo_rec); + bool updated_extern= false; undo_no_t undo_no= 0; table_id_t table_id= 0; @@ -382,14 +377,14 @@ ATTRIBUTE_COLD void trx_t::apply_log() undo->hdr_offset); while (rec) { - log_applier.assign_rec(*block, page_offset(rec)); + block->page.fix(); mtr.commit(); - log_applier.apply_undo_rec(); + /* Since we are the only thread who could write to this undo page, + it is safe to dereference rec while only holding a buffer-fix. */ + log_applier.apply_undo_rec(rec); mtr.start(); - block= buf_page_get(log_applier.get_page_id(), 0, RW_S_LATCH, &mtr); - if (UNIV_UNLIKELY(!block)) - goto func_exit; - rec= trx_undo_page_get_next_rec(block, log_applier.get_offset(), + mtr.page_lock(block, RW_S_LATCH); + rec= trx_undo_page_get_next_rec(block, page_offset(rec), page_id.page_no(), undo->hdr_offset); } @@ -406,7 +401,6 @@ ATTRIBUTE_COLD void trx_t::apply_log() break; log_applier.assign_next(next_page_id); } -func_exit: mtr.commit(); apply_online_log= false; } From 14685b10dffb8dd6045b7b4cceab05301606f5ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Oct 2023 09:11:58 +0300 Subject: [PATCH 118/158] MDEV-32050: Deprecate&ignore innodb_purge_rseg_truncate_frequency The motivation of introducing the parameter innodb_purge_rseg_truncate_frequency in mysql/mysql-server@28bbd66ea5f6acf80fcb381057bb7ca5b7b188d2 and mysql/mysql-server@8fc2120fed11d2498ecb3635d87f414c76985fce seems to have been to avoid stalls due to freeing undo log pages or truncating undo log tablespaces. In MariaDB Server, innodb_undo_log_truncate=ON should be a much lighter operation than in MySQL, because it will not involve any log checkpoint. Another source of performance stalls should be trx_purge_truncate_rseg_history(), which is shrinking the history list by freeing the undo log pages whose undo records have been purged. To alleviate that, we will introduce a purge_truncation_task that will offload this from the purge_coordinator_task. In that way, the next innodb_purge_batch_size pages may be parsed and purged while the pages from the previous batch are being freed and the history list being shrunk. The processing of innodb_undo_log_truncate=ON will still remain the responsibility of the purge_coordinator_task. purge_coordinator_state::count: Remove. We will ignore innodb_purge_rseg_truncate_frequency, and act as if it had been set to 1 (the maximum shrinking frequency). purge_coordinator_state::do_purge(): Invoke an asynchronous task purge_truncation_callback() to free the undo log pages. purge_sys_t::iterator::free_history(): Free those undo log pages that have been processed. This used to be a part of trx_purge_truncate_history(). purge_sys_t::clone_end_view(): Take a new value of purge_sys.head as a parameter, so that it will be updated while holding exclusive purge_sys.latch. This is needed for race-free access to the field in purge_truncation_callback(). Reviewed by: Vladislav Lesin --- extra/mariabackup/xtrabackup.cc | 4 +- .../encryption/t/innodb-bad-key-change.opt | 1 - .../encryption/t/innodb-bad-key-change2.opt | 1 - .../encryption/t/innodb-bad-key-change4.opt | 1 - .../encryption/t/innodb-compressed-blob.opt | 1 - .../t/innodb-encryption-disable.opt | 1 - .../encryption/t/innodb-force-corrupt.opt | 1 - .../suite/encryption/t/innodb-missing-key.opt | 1 - .../suite/encryption/t/innodb-redo-badkey.opt | 1 - .../suite/gcol/r/gcol_partition_innodb.result | 3 - mysql-test/suite/gcol/r/gcol_purge.result | 3 - mysql-test/suite/gcol/r/gcol_update.result | 3 - .../gcol/r/innodb_virtual_debug_purge.result | 3 - .../suite/gcol/r/innodb_virtual_index.result | 3 - .../suite/gcol/r/innodb_virtual_purge.result | 3 - .../suite/gcol/t/gcol_partition_innodb.test | 3 - mysql-test/suite/gcol/t/gcol_purge.test | 3 - mysql-test/suite/gcol/t/gcol_update.test | 5 -- .../gcol/t/innodb_virtual_debug_purge.test | 3 - .../suite/gcol/t/innodb_virtual_index.test | 5 -- .../suite/gcol/t/innodb_virtual_purge.test | 5 -- .../suite/innodb/include/wait_all_purged.inc | 1 - mysql-test/suite/innodb/r/alter_kill.result | 1 - .../innodb/r/cursor-restore-locking.result | 3 - mysql-test/suite/innodb/r/dml_purge.result | 4 - mysql-test/suite/innodb/r/foreign_key.result | 6 -- .../suite/innodb/r/gap_lock_split.result | 3 - .../innodb/r/index_merge_threshold.result | 3 - mysql-test/suite/innodb/r/innodb-16k.result | 3 - mysql-test/suite/innodb/r/innodb-32k.result | 1 - .../innodb/r/innodb-system-table-view.result | 3 - .../suite/innodb/r/innodb_bug14147491.result | 1 - .../suite/innodb/r/innodb_bug84958.result | 3 - .../innodb/r/innodb_stats_persistent.result | 3 - .../suite/innodb/r/instant_alter,4k.rdiff | 3 +- .../suite/innodb/r/instant_alter.result | 3 - .../suite/innodb/r/instant_alter_bugs.result | 5 -- .../suite/innodb/r/instant_alter_crash.result | 4 - .../suite/innodb/r/instant_alter_debug.result | 3 - .../r/instant_alter_purge,release.rdiff | 3 +- .../suite/innodb/r/instant_alter_purge.result | 3 - .../innodb/r/instant_alter_rollback.result | 3 - .../innodb/r/page_id_innochecksum.result | 1 - mysql-test/suite/innodb/r/purge.result | 3 - .../suite/innodb/r/purge_secondary.result | 3 - mysql-test/suite/innodb/r/scrub.result | 1 - mysql-test/suite/innodb/r/scrub_debug.result | 3 - .../suite/innodb/r/truncate_crash.result | 3 - .../suite/innodb/r/trx_id_future.result | 1 - mysql-test/suite/innodb/r/undo_log.result | 3 - .../suite/innodb/r/undo_space_dblwr.result | 1 - .../suite/innodb/r/undo_truncate.result | 2 - .../innodb/r/undo_truncate_recover.result | 1 - mysql-test/suite/innodb/t/alter_kill.test | 1 - .../innodb/t/cursor-restore-locking.test | 3 - mysql-test/suite/innodb/t/dml_purge.test | 5 -- mysql-test/suite/innodb/t/foreign_key.test | 8 -- mysql-test/suite/innodb/t/gap_lock_split.test | 4 - .../suite/innodb/t/index_merge_threshold.test | 4 - mysql-test/suite/innodb/t/innodb-16k.test | 3 - mysql-test/suite/innodb/t/innodb-32k.test | 2 - .../innodb/t/innodb-system-table-view.test | 3 - .../suite/innodb/t/innodb_bug14147491.test | 1 - .../suite/innodb/t/innodb_bug84958.test | 3 - .../innodb/t/innodb_stats_persistent.test | 3 - mysql-test/suite/innodb/t/instant_alter.test | 3 - .../suite/innodb/t/instant_alter_bugs.test | 7 -- .../suite/innodb/t/instant_alter_crash.test | 6 -- .../suite/innodb/t/instant_alter_debug.test | 5 -- .../suite/innodb/t/instant_alter_purge.test | 3 - .../innodb/t/instant_alter_rollback.test | 3 - .../suite/innodb/t/page_id_innochecksum.test | 1 - mysql-test/suite/innodb/t/purge.test | 4 - .../suite/innodb/t/purge_secondary.test | 6 -- mysql-test/suite/innodb/t/scrub.test | 1 - mysql-test/suite/innodb/t/scrub_debug.test | 3 - mysql-test/suite/innodb/t/table_flags.test | 1 - mysql-test/suite/innodb/t/truncate_crash.test | 3 - mysql-test/suite/innodb/t/trx_id_future.test | 1 - mysql-test/suite/innodb/t/undo_log.test | 3 - .../suite/innodb/t/undo_space_dblwr.test | 1 - mysql-test/suite/innodb/t/undo_truncate.test | 2 - .../suite/innodb/t/undo_truncate_recover.test | 1 - .../suite/innodb_fts/r/crash_recovery.result | 3 - .../suite/innodb_fts/t/crash_recovery.test | 4 - .../suite/innodb_gis/r/rtree_add_index.result | 3 - .../suite/innodb_gis/r/rtree_compress.result | 3 - .../suite/innodb_gis/r/rtree_purge.result | 3 - .../suite/innodb_gis/r/rtree_undo.result | 3 - .../suite/innodb_gis/t/rtree_add_index.test | 4 - .../suite/innodb_gis/t/rtree_compress.test | 4 - .../suite/innodb_gis/t/rtree_purge.test | 4 - mysql-test/suite/innodb_gis/t/rtree_undo.test | 5 -- mysql-test/suite/innodb_zip/r/blob.result | 3 - mysql-test/suite/innodb_zip/t/blob.test | 4 - .../unencrypted_page_compressed.result | 1 - .../unencrypted_page_compressed.test | 1 - ...purge_rseg_truncate_frequency_basic.result | 19 +++++ .../sys_vars/r/sysvars_innodb,32bit.rdiff | 2 +- .../suite/sys_vars/r/sysvars_innodb.result | 2 +- .../suite/versioning/r/delete_history.result | 3 - .../suite/versioning/t/delete_history.test | 5 -- storage/innobase/handler/ha_innodb.cc | 5 +- storage/innobase/include/trx0purge.h | 11 ++- storage/innobase/srv/srv0srv.cc | 23 +++++- storage/innobase/trx/trx0purge.cc | 82 +++++++++++-------- storage/innobase/trx/trx0undo.cc | 4 +- 107 files changed, 102 insertions(+), 331 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 6e31d6034e9..ef63f914343 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -1868,7 +1868,7 @@ static int prepare_export() IF_WIN("\"","") "\"%s\" --mysqld \"%s\"" " --defaults-extra-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=." " --innodb --innodb-fast-shutdown=0 --loose-partition" - " --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu" + " --innodb-buffer-pool-size=%llu" " --console --skip-log-error --skip-log-bin --bootstrap %s< " BOOTSTRAP_FILENAME IF_WIN("\"",""), mariabackup_exe, @@ -1882,7 +1882,7 @@ static int prepare_export() IF_WIN("\"","") "\"%s\" --mysqld" " --defaults-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=." " --innodb --innodb-fast-shutdown=0 --loose-partition" - " --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu" + " --innodb-buffer-pool-size=%llu" " --console --log-error= --skip-log-bin --bootstrap %s< " BOOTSTRAP_FILENAME IF_WIN("\"",""), mariabackup_exe, diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change.opt b/mysql-test/suite/encryption/t/innodb-bad-key-change.opt index d3f298d3335..d14f3bcbe59 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change.opt +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change.opt @@ -1,2 +1 @@ ---innodb-purge-rseg-truncate-frequency=1 --skip-innodb-fast-shutdown diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change2.opt b/mysql-test/suite/encryption/t/innodb-bad-key-change2.opt index d3f298d3335..d14f3bcbe59 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change2.opt +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change2.opt @@ -1,2 +1 @@ ---innodb-purge-rseg-truncate-frequency=1 --skip-innodb-fast-shutdown diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change4.opt b/mysql-test/suite/encryption/t/innodb-bad-key-change4.opt index d20d3b60913..ce4c31a5b34 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change4.opt +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change4.opt @@ -2,5 +2,4 @@ --loose-innodb-buffer-page --loose-innodb-buffer-page-lru --innodb-defragment=1 ---innodb-purge-rseg-truncate-frequency=1 --skip-innodb-fast-shutdown diff --git a/mysql-test/suite/encryption/t/innodb-compressed-blob.opt b/mysql-test/suite/encryption/t/innodb-compressed-blob.opt index 061212b3034..f44dcb1ef80 100644 --- a/mysql-test/suite/encryption/t/innodb-compressed-blob.opt +++ b/mysql-test/suite/encryption/t/innodb-compressed-blob.opt @@ -2,5 +2,4 @@ --innodb-tablespaces-encryption --innodb-encrypt-tables=on --innodb-encryption-threads=4 ---innodb-purge-rseg-truncate-frequency=1 --skip-innodb-fast-shutdown diff --git a/mysql-test/suite/encryption/t/innodb-encryption-disable.opt b/mysql-test/suite/encryption/t/innodb-encryption-disable.opt index d3f298d3335..d14f3bcbe59 100644 --- a/mysql-test/suite/encryption/t/innodb-encryption-disable.opt +++ b/mysql-test/suite/encryption/t/innodb-encryption-disable.opt @@ -1,2 +1 @@ ---innodb-purge-rseg-truncate-frequency=1 --skip-innodb-fast-shutdown diff --git a/mysql-test/suite/encryption/t/innodb-force-corrupt.opt b/mysql-test/suite/encryption/t/innodb-force-corrupt.opt index d3f298d3335..d14f3bcbe59 100644 --- a/mysql-test/suite/encryption/t/innodb-force-corrupt.opt +++ b/mysql-test/suite/encryption/t/innodb-force-corrupt.opt @@ -1,2 +1 @@ ---innodb-purge-rseg-truncate-frequency=1 --skip-innodb-fast-shutdown diff --git a/mysql-test/suite/encryption/t/innodb-missing-key.opt b/mysql-test/suite/encryption/t/innodb-missing-key.opt index 5e144bc2d3c..6a8ee144418 100644 --- a/mysql-test/suite/encryption/t/innodb-missing-key.opt +++ b/mysql-test/suite/encryption/t/innodb-missing-key.opt @@ -2,5 +2,4 @@ --innodb-encryption-rotate-key-age=15 --innodb-encryption-threads=4 --innodb-tablespaces-encryption ---innodb-purge-rseg-truncate-frequency=1 --skip-innodb-fast-shutdown diff --git a/mysql-test/suite/encryption/t/innodb-redo-badkey.opt b/mysql-test/suite/encryption/t/innodb-redo-badkey.opt index 2de0bdb3241..0efdc8a705d 100644 --- a/mysql-test/suite/encryption/t/innodb-redo-badkey.opt +++ b/mysql-test/suite/encryption/t/innodb-redo-badkey.opt @@ -3,5 +3,4 @@ --innodb-tablespaces-encryption --innodb-encryption-threads=2 --innodb-default-encryption-key-id=4 ---innodb-purge-rseg-truncate-frequency=1 --skip-innodb-fast-shutdown diff --git a/mysql-test/suite/gcol/r/gcol_partition_innodb.result b/mysql-test/suite/gcol/r/gcol_partition_innodb.result index e61c0a26417..2bff33054a2 100644 --- a/mysql-test/suite/gcol/r/gcol_partition_innodb.result +++ b/mysql-test/suite/gcol/r/gcol_partition_innodb.result @@ -1,6 +1,4 @@ SET @@session.default_storage_engine = 'InnoDB'; -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; drop table if exists t1; # Case 1. Partitioning by RANGE based on a non-stored generated column. CREATE TABLE t1 ( @@ -135,4 +133,3 @@ DROP FUNCTION IF EXISTS f1; DROP TRIGGER IF EXISTS trg1; DROP TRIGGER IF EXISTS trg2; set sql_warnings = 0; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/gcol/r/gcol_purge.result b/mysql-test/suite/gcol/r/gcol_purge.result index a130485f219..e16cf0dff54 100644 --- a/mysql-test/suite/gcol/r/gcol_purge.result +++ b/mysql-test/suite/gcol/r/gcol_purge.result @@ -1,6 +1,4 @@ -SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @save_dbug=@@GLOBAL.debug_dbug; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; CREATE TABLE t1(f1 INT NOT NULL, f2 int not null, f3 int generated always as (f2 * 2) VIRTUAL, primary key(f1), INDEX (f3))ENGINE=InnoDB; @@ -22,6 +20,5 @@ commit; disconnect con1; disconnect con2; connection default; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; SET GLOBAL debug_dbug=@save_dbug; DROP TABLE t1; diff --git a/mysql-test/suite/gcol/r/gcol_update.result b/mysql-test/suite/gcol/r/gcol_update.result index 720ff533bac..35e0b3e8219 100644 --- a/mysql-test/suite/gcol/r/gcol_update.result +++ b/mysql-test/suite/gcol/r/gcol_update.result @@ -1,5 +1,3 @@ -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; connect purge_control,localhost,root; START TRANSACTION WITH CONSISTENT SNAPSHOT; connection default; @@ -39,4 +37,3 @@ InnoDB 0 transactions not purged disconnect purge_control; connection default; drop table t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result b/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result index 89711a2d8bb..63ea5b1d418 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result @@ -1,7 +1,5 @@ set default_storage_engine=innodb; set @old_dbug=@@global.debug_dbug; -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; SET @saved_stats_persistent = @@GLOBAL.innodb_stats_persistent; SET GLOBAL innodb_stats_persistent = OFF; CREATE TABLE `t` ( @@ -204,5 +202,4 @@ disconnect truncate; connection default; DROP TABLE t1, t2; set debug_sync=reset; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; SET GLOBAL innodb_stats_persistent = @saved_stats_persistent; diff --git a/mysql-test/suite/gcol/r/innodb_virtual_index.result b/mysql-test/suite/gcol/r/innodb_virtual_index.result index b0c29da2f22..637d142b4cd 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_index.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_index.result @@ -1,6 +1,4 @@ SET default_storage_engine= innodb; -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; # # Bug 21922176 - PREBUILT->SEARCH_TUPLE CREATED WITHOUT INCLUDING # THE NUMBER OF VIRTUAL COLUMNS @@ -194,7 +192,6 @@ ALTER TABLE t1 ADD COLUMN col7a INT GENERATED ALWAYS AS (col1 % col2) VIRTUAL, ADD UNIQUE index idx (col1), algorithm=inplace; ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: INPLACE ADD or DROP of virtual columns cannot be combined with other ALTER TABLE actions. Try ALGORITHM=COPY DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; # # Bug 27122803 - BACKPORT FIX FOR BUG 25899959 TO MYSQL-5.7 # diff --git a/mysql-test/suite/gcol/r/innodb_virtual_purge.result b/mysql-test/suite/gcol/r/innodb_virtual_purge.result index 1fcbd05f354..7951bd0ee6b 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_purge.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_purge.result @@ -1,5 +1,3 @@ -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; # # Bug#21869656 UNDO LOG DOES NOT CONTAIN ENOUGH INFORMATION # ON INDEXED VIRTUAL COLUMNS @@ -173,4 +171,3 @@ CHECK TABLE t EXTENDED; Table Op Msg_type Msg_text test.t check status OK DROP TABLE t; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/gcol/t/gcol_partition_innodb.test b/mysql-test/suite/gcol/t/gcol_partition_innodb.test index 75e2f80af20..a8765970749 100644 --- a/mysql-test/suite/gcol/t/gcol_partition_innodb.test +++ b/mysql-test/suite/gcol/t/gcol_partition_innodb.test @@ -30,8 +30,6 @@ # Set the session storage engine --source include/have_innodb.inc eval SET @@session.default_storage_engine = 'InnoDB'; -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; ##### Workarounds for known open engine specific bugs # none @@ -63,4 +61,3 @@ DROP TABLE t1; #------------------------------------------------------------------------------# # Cleanup --source suite/gcol/inc/gcol_cleanup.inc -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/gcol/t/gcol_purge.test b/mysql-test/suite/gcol/t/gcol_purge.test index 8fff375cdc2..cfe20c4ad25 100644 --- a/mysql-test/suite/gcol/t/gcol_purge.test +++ b/mysql-test/suite/gcol/t/gcol_purge.test @@ -1,9 +1,7 @@ --source include/have_innodb.inc --source include/have_debug.inc -SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @save_dbug=@@GLOBAL.debug_dbug; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; CREATE TABLE t1(f1 INT NOT NULL, f2 int not null, f3 int generated always as (f2 * 2) VIRTUAL, primary key(f1), INDEX (f3))ENGINE=InnoDB; @@ -31,6 +29,5 @@ commit; disconnect con1; disconnect con2; connection default; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; SET GLOBAL debug_dbug=@save_dbug; DROP TABLE t1; diff --git a/mysql-test/suite/gcol/t/gcol_update.test b/mysql-test/suite/gcol/t/gcol_update.test index 8652ce7a638..2076632f28e 100644 --- a/mysql-test/suite/gcol/t/gcol_update.test +++ b/mysql-test/suite/gcol/t/gcol_update.test @@ -1,8 +1,5 @@ --source include/have_innodb.inc -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - connect (purge_control,localhost,root); START TRANSACTION WITH CONSISTENT SNAPSHOT; @@ -63,5 +60,3 @@ disconnect purge_control; connection default; drop table t1; - -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test index da49a5b6b43..09fba0285c7 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test @@ -6,8 +6,6 @@ set default_storage_engine=innodb; set @old_dbug=@@global.debug_dbug; # Ensure that the history list length will actually be decremented by purge. -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; SET @saved_stats_persistent = @@GLOBAL.innodb_stats_persistent; SET GLOBAL innodb_stats_persistent = OFF; @@ -267,5 +265,4 @@ DROP TABLE t1, t2; --source include/wait_until_count_sessions.inc set debug_sync=reset; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; SET GLOBAL innodb_stats_persistent = @saved_stats_persistent; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_index.test b/mysql-test/suite/gcol/t/innodb_virtual_index.test index d0e1951842e..83d9a6bdae5 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_index.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_index.test @@ -3,10 +3,6 @@ SET default_storage_engine= innodb; -# Ensure that the history list length will actually be decremented by purge. -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - --echo # --echo # Bug 21922176 - PREBUILT->SEARCH_TUPLE CREATED WITHOUT INCLUDING --echo # THE NUMBER OF VIRTUAL COLUMNS @@ -226,7 +222,6 @@ ALTER TABLE t1 ADD COLUMN col7a INT GENERATED ALWAYS AS (col1 % col2) VIRTUAL, ADD UNIQUE index idx (col1), algorithm=inplace; DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; --echo # --echo # Bug 27122803 - BACKPORT FIX FOR BUG 25899959 TO MYSQL-5.7 diff --git a/mysql-test/suite/gcol/t/innodb_virtual_purge.test b/mysql-test/suite/gcol/t/innodb_virtual_purge.test index 3db1b8757ff..99c7267c88b 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_purge.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_purge.test @@ -1,10 +1,6 @@ --source include/have_innodb.inc --source include/count_sessions.inc -# Ensure that the history list length will actually be decremented by purge. -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - --echo # --echo # Bug#21869656 UNDO LOG DOES NOT CONTAIN ENOUGH INFORMATION --echo # ON INDEXED VIRTUAL COLUMNS @@ -187,4 +183,3 @@ CHECK TABLE t EXTENDED; DROP TABLE t; --source include/wait_until_count_sessions.inc -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/include/wait_all_purged.inc b/mysql-test/suite/innodb/include/wait_all_purged.inc index e3a506c7622..e374a7c09f3 100644 --- a/mysql-test/suite/innodb/include/wait_all_purged.inc +++ b/mysql-test/suite/innodb/include/wait_all_purged.inc @@ -1,5 +1,4 @@ # Wait for everything to be purged. -# The user should have set innodb_purge_rseg_truncate_frequency=1. --disable_query_log if (!$wait_all_purged) diff --git a/mysql-test/suite/innodb/r/alter_kill.result b/mysql-test/suite/innodb/r/alter_kill.result index 36b582c6d76..ef13e996703 100644 --- a/mysql-test/suite/innodb/r/alter_kill.result +++ b/mysql-test/suite/innodb/r/alter_kill.result @@ -2,7 +2,6 @@ # Bug#16720368 INNODB CRASHES ON BROKEN #SQL*.IBD FILE AT STARTUP # SET GLOBAL innodb_file_per_table=1; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; CREATE TABLE bug16720368_1 (a INT PRIMARY KEY) ENGINE=InnoDB; connect con1,localhost,root; CREATE TABLE bug16720368 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; diff --git a/mysql-test/suite/innodb/r/cursor-restore-locking.result b/mysql-test/suite/innodb/r/cursor-restore-locking.result index 6259cfd58ca..d834146e44e 100644 --- a/mysql-test/suite/innodb/r/cursor-restore-locking.result +++ b/mysql-test/suite/innodb/r/cursor-restore-locking.result @@ -1,5 +1,3 @@ -SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB, STATS_PERSISTENT=0; InnoDB 0 transactions not purged connect prevent_purge,localhost,root,,; @@ -40,4 +38,3 @@ disconnect con_del_2; connection default; SET DEBUG_SYNC = 'RESET'; DROP TABLE t; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_freq; diff --git a/mysql-test/suite/innodb/r/dml_purge.result b/mysql-test/suite/innodb/r/dml_purge.result index 75a5f0fec6c..2b345089f8f 100644 --- a/mysql-test/suite/innodb/r/dml_purge.result +++ b/mysql-test/suite/innodb/r/dml_purge.result @@ -1,10 +1,7 @@ -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; # # MDEV-12288 Reset DB_TRX_ID when the history is removed, # to speed up MVCC # -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TABLE t1(a INT PRIMARY KEY, b INT NOT NULL) ROW_FORMAT=REDUNDANT ENGINE=InnoDB; InnoDB 0 transactions not purged @@ -49,4 +46,3 @@ a b c 1 2 NULL 3 -3 NULL DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index a439f6d7981..d2cb413eba2 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -165,8 +165,6 @@ ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fail ALTER TABLE child FORCE; DELETE FROM parent; DROP TABLE child,parent; -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; SELECT unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2'; unique_constraint_name @@ -730,7 +728,6 @@ CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; # # MDEV-17187 table doesn't exist in engine after ALTER other tables # with CONSTRAINTs @@ -1034,8 +1031,6 @@ DROP TABLE IF EXISTS t2, t1; # # MDEV-30531 Corrupt index(es) on busy table when using FOREIGN KEY # -SET @freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; CREATE TABLE collections ( id int(11) unsigned NOT NULL AUTO_INCREMENT, collectionhash varchar(255) NOT NULL DEFAULT '0', @@ -1061,7 +1056,6 @@ CHECK TABLE binaries, collections EXTENDED; Table Op Msg_type Msg_text test.binaries check status OK test.collections check status OK -SET GLOBAL innodb_purge_rseg_truncate_frequency=@freq; disconnect con1; DROP TABLE binaries, collections; # End of 10.6 tests diff --git a/mysql-test/suite/innodb/r/gap_lock_split.result b/mysql-test/suite/innodb/r/gap_lock_split.result index 7c10d8eed94..e607eda3dc9 100644 --- a/mysql-test/suite/innodb/r/gap_lock_split.result +++ b/mysql-test/suite/innodb/r/gap_lock_split.result @@ -1,5 +1,3 @@ -SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; CREATE TABLE t1(id INT PRIMARY key, val VARCHAR(16000)) ENGINE=InnoDB STATS_PERSISTENT=0; INSERT INTO t1 (id,val) SELECT 2*seq,'x' FROM seq_0_to_1023; @@ -29,4 +27,3 @@ disconnect con1; connection default; COMMIT; DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; diff --git a/mysql-test/suite/innodb/r/index_merge_threshold.result b/mysql-test/suite/innodb/r/index_merge_threshold.result index 989d31e90b1..41897b80a4e 100644 --- a/mysql-test/suite/innodb/r/index_merge_threshold.result +++ b/mysql-test/suite/innodb/r/index_merge_threshold.result @@ -1,5 +1,3 @@ -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TABLE tab(a BIGINT PRIMARY KEY,c1 TINYTEXT,c2 TEXT,c3 MEDIUMTEXT, c4 TINYBLOB,c5 BLOB,c6 MEDIUMBLOB,c7 LONGBLOB) ENGINE=InnoDB; CREATE INDEX index1 ON tab(c1(255)) COMMENT 'Check index level merge MERGE_THRESHOLD=51'; @@ -1309,4 +1307,3 @@ name count_reset index_page_merge_attempts 2 index_page_merge_successful 2 DROP TABLE tab1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/r/innodb-16k.result b/mysql-test/suite/innodb/r/innodb-16k.result index d46bea183c9..3d62a2f802c 100644 --- a/mysql-test/suite/innodb/r/innodb-16k.result +++ b/mysql-test/suite/innodb/r/innodb-16k.result @@ -9,9 +9,7 @@ variable_value # Each row format has its own amount of overhead that # varies depending on number of fields and other overhead. SET SESSION innodb_strict_mode = ON; -SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @save_level=@@GLOBAL.innodb_compression_level; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET GLOBAL innodb_compression_level=1; CREATE TABLE t1 ( c01 char(200), c02 char(200), c03 char(200), c04 char(200), c05 char(200), @@ -506,7 +504,6 @@ ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII; INSERT INTO t1 VALUES(REPEAT('A',512)),(REPEAT('B',512)); DROP TABLE t1; InnoDB 0 transactions not purged -SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; SET GLOBAL innodb_compression_level=@save_level; DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge; DROP TABLE tlong; diff --git a/mysql-test/suite/innodb/r/innodb-32k.result b/mysql-test/suite/innodb/r/innodb-32k.result index 7dd1df8cfc5..b64ff332084 100644 --- a/mysql-test/suite/innodb/r/innodb-32k.result +++ b/mysql-test/suite/innodb/r/innodb-32k.result @@ -1,4 +1,3 @@ -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; call mtr.add_suppression("Innodb: Cannot add field.*row size is"); # Test 1) Show the page size from Information Schema SELECT variable_value FROM information_schema.global_status diff --git a/mysql-test/suite/innodb/r/innodb-system-table-view.result b/mysql-test/suite/innodb/r/innodb-system-table-view.result index 580ed08e424..c770d106bdc 100644 --- a/mysql-test/suite/innodb/r/innodb-system-table-view.result +++ b/mysql-test/suite/innodb/r/innodb-system-table-view.result @@ -1,5 +1,3 @@ -SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SELECT table_id INTO @table_stats_id FROM information_schema.innodb_sys_tables WHERE name = 'mysql/innodb_table_stats'; SELECT table_id INTO @index_stats_id FROM information_schema.innodb_sys_tables @@ -168,7 +166,6 @@ name num_rows ref_count test/parent 1 2 DROP TABLE child; DROP TABLE parent; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; # # MDEV-29479 I_S.INNODB_SYS_TABLESPACES doesn't have # temporary tablespace information diff --git a/mysql-test/suite/innodb/r/innodb_bug14147491.result b/mysql-test/suite/innodb/r/innodb_bug14147491.result index 533eaeafeb8..9d2b8e1dfe3 100644 --- a/mysql-test/suite/innodb/r/innodb_bug14147491.result +++ b/mysql-test/suite/innodb/r/innodb_bug14147491.result @@ -1,5 +1,4 @@ # Ensure that purge will not crash on the table after we corrupt it. -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; SET GLOBAL innodb_fast_shutdown=0; # Create and populate the table to be corrupted set global innodb_file_per_table=ON; diff --git a/mysql-test/suite/innodb/r/innodb_bug84958.result b/mysql-test/suite/innodb/r/innodb_bug84958.result index 9a4129647b9..3375efb9184 100644 --- a/mysql-test/suite/innodb/r/innodb_bug84958.result +++ b/mysql-test/suite/innodb/r/innodb_bug84958.result @@ -4,8 +4,6 @@ # # Set up the test with a procedure and a function. # -SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency= 1; CREATE PROCEDURE insert_n(start int, end int) BEGIN DECLARE i INT DEFAULT start; @@ -84,7 +82,6 @@ test.t1 check status OK # disconnect con2; disconnect con3; -SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; DROP TABLE t1; DROP PROCEDURE insert_n; DROP FUNCTION num_pages_get; diff --git a/mysql-test/suite/innodb/r/innodb_stats_persistent.result b/mysql-test/suite/innodb/r/innodb_stats_persistent.result index e25ab2a8a24..a691ab19b30 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_persistent.result +++ b/mysql-test/suite/innodb/r/innodb_stats_persistent.result @@ -1,5 +1,3 @@ -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; SET @saved_include_delete_marked = @@GLOBAL.innodb_stats_include_delete_marked; SET GLOBAL innodb_stats_include_delete_marked = ON; SET @saved_traditional = @@GLOBAL.innodb_stats_traditional; @@ -105,4 +103,3 @@ DROP TABLE t1,t2; SET GLOBAL innodb_stats_include_delete_marked = @saved_include_delete_marked; SET GLOBAL innodb_stats_traditional = @saved_traditional; SET GLOBAL innodb_stats_modified_counter = @saved_modified_counter; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/r/instant_alter,4k.rdiff b/mysql-test/suite/innodb/r/instant_alter,4k.rdiff index a885eb260d6..ab12a24663e 100644 --- a/mysql-test/suite/innodb/r/instant_alter,4k.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter,4k.rdiff @@ -312,12 +312,11 @@ connection default; InnoDB 0 transactions not purged DROP TABLE t1,t2,t3,t4,big; -@@ -2836,7 +2868,7 @@ +@@ -2836,6 +2868,6 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -209 +211 - SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; SET GLOBAL innodb_instant_alter_column_allowed = @saved_allowance; # diff --git a/mysql-test/suite/innodb/r/instant_alter.result b/mysql-test/suite/innodb/r/instant_alter.result index 4a67e04205b..898981ef125 100644 --- a/mysql-test/suite/innodb/r/instant_alter.result +++ b/mysql-test/suite/innodb/r/instant_alter.result @@ -52,8 +52,6 @@ connect analyze, localhost, root; connection default; SET timestamp = 42; SET time_zone='+03:00'; -SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET @old_instant= (SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'); @@ -2873,7 +2871,6 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants 209 -SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; SET GLOBAL innodb_instant_alter_column_allowed = @saved_allowance; # # MDEV-18266: Changing an index comment unnecessarily rebuilds index diff --git a/mysql-test/suite/innodb/r/instant_alter_bugs.result b/mysql-test/suite/innodb/r/instant_alter_bugs.result index f56938550ac..feacaa6b40d 100644 --- a/mysql-test/suite/innodb/r/instant_alter_bugs.result +++ b/mysql-test/suite/innodb/r/instant_alter_bugs.result @@ -1,5 +1,3 @@ -SET @save_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; # # MDEV-17821 Assertion `!page_rec_is_supremum(rec)' failed # in btr_pcur_store_position @@ -208,7 +206,6 @@ DROP TABLE t1; # MDEV-23801 Assertion index->table->instant... failed # in btr_pcur_store_position() # -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TABLE t ( pk int auto_increment, c01 char(255) not null default repeat('a',255), @@ -232,7 +229,6 @@ INSERT INTO t () VALUES (),(); ROLLBACK; DELETE FROM t; InnoDB 0 transactions not purged -SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; CREATE TABLE tt ENGINE=InnoDB AS SELECT c FROM t; DROP TABLE t, tt; # End of 10.3 tests @@ -489,7 +485,6 @@ ALTER TABLE t1 ADD COLUMN(f2 INT NOT NULL, f3 INT NOT NULL, f4 INT NOT NULL, f5 INT NOT NULL), CHANGE COLUMN f1 f1 CHAR(10) DEFAULT NULL; DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; # # MDEV-26420 Buffer overflow on instant ADD/DROP of generated column # diff --git a/mysql-test/suite/innodb/r/instant_alter_crash.result b/mysql-test/suite/innodb/r/instant_alter_crash.result index 7855aa24264..c6f7d3898be 100644 --- a/mysql-test/suite/innodb/r/instant_alter_crash.result +++ b/mysql-test/suite/innodb/r/instant_alter_crash.result @@ -20,7 +20,6 @@ COMMIT; # Kill the server disconnect ddl; # restart -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SELECT * FROM t1; id c2 0 2 @@ -46,8 +45,6 @@ COMMIT; # Kill the server disconnect ddl; # restart -SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SELECT * FROM t1; id c2 0 3 @@ -76,7 +73,6 @@ COMMIT; # Kill the server disconnect ddl; # restart -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; FOUND 3 /\[Note\] InnoDB: Rolled back recovered transaction / in mysqld.1.err SELECT * FROM t1; id c2 diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index 7c378aa62e3..1bd362f35b5 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -1,5 +1,3 @@ -SET @save_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET @old_instant= (SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'); @@ -523,7 +521,6 @@ test.t1 check status OK DROP TABLE t1; SET DEBUG_SYNC=RESET; # End of 10.5 tests -SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; SELECT variable_value-@old_instant instants FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; diff --git a/mysql-test/suite/innodb/r/instant_alter_purge,release.rdiff b/mysql-test/suite/innodb/r/instant_alter_purge,release.rdiff index 8722b724c6e..23f6c9154ef 100644 --- a/mysql-test/suite/innodb/r/instant_alter_purge,release.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_purge,release.rdiff @@ -1,6 +1,6 @@ --- instant_alter_purge.result +++ instant_alter_purge,release.result -@@ -32,16 +32,11 @@ +@@ -32,15 +32,10 @@ START TRANSACTION WITH CONSISTENT SNAPSHOT; connection default; DELETE FROM t1; @@ -16,4 +16,3 @@ connection default; -SET DEBUG_SYNC=RESET; DROP TABLE t1; - SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/r/instant_alter_purge.result b/mysql-test/suite/innodb/r/instant_alter_purge.result index 261356bad12..61cffc9aec5 100644 --- a/mysql-test/suite/innodb/r/instant_alter_purge.result +++ b/mysql-test/suite/innodb/r/instant_alter_purge.result @@ -1,5 +1,3 @@ -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; InnoDB 0 transactions not purged # # MDEV-17793 Crash in purge after instant DROP and emptying the table @@ -22,4 +20,3 @@ ALTER TABLE t1 DROP extra; disconnect prevent_purge; InnoDB 0 transactions not purged DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/r/instant_alter_rollback.result b/mysql-test/suite/innodb/r/instant_alter_rollback.result index b51e067c647..dd427b625c1 100644 --- a/mysql-test/suite/innodb/r/instant_alter_rollback.result +++ b/mysql-test/suite/innodb/r/instant_alter_rollback.result @@ -47,11 +47,8 @@ CREATE TABLE foo(a INT PRIMARY KEY) ENGINE=InnoDB; # Kill the server disconnect to_be_killed; # restart -SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; DROP TABLE foo; InnoDB 0 transactions not purged -SET GLOBAL innodb_purge_rseg_truncate_frequency=@saved_frequency; SELECT * FROM empty; id c2 d1 SELECT * FROM once; diff --git a/mysql-test/suite/innodb/r/page_id_innochecksum.result b/mysql-test/suite/innodb/r/page_id_innochecksum.result index 7a5f44b21e6..7915a7babbe 100644 --- a/mysql-test/suite/innodb/r/page_id_innochecksum.result +++ b/mysql-test/suite/innodb/r/page_id_innochecksum.result @@ -3,7 +3,6 @@ create table t1(f1 int not null)engine=innodb; insert into t1 values(1), (2), (3); # Change the page offset FOUND 1 /page id mismatch/ in result.log -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; InnoDB 0 transactions not purged drop table t1; call mtr.add_suppression("InnoDB: Failed to read page 3 from file '.*test/t1\\.ibd': Page read from tablespace is corrupted\\."); diff --git a/mysql-test/suite/innodb/r/purge.result b/mysql-test/suite/innodb/r/purge.result index a71d0afdcbe..ed14fad74b1 100644 --- a/mysql-test/suite/innodb/r/purge.result +++ b/mysql-test/suite/innodb/r/purge.result @@ -1,5 +1,3 @@ -SET @save_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; # Bug #12429576 - Test an assertion failure on purge. CREATE TABLE t1_purge ( A int, @@ -118,4 +116,3 @@ t12963823 CREATE TABLE `t12963823` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC InnoDB 0 transactions not purged DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge, t12637786, t12963823; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; diff --git a/mysql-test/suite/innodb/r/purge_secondary.result b/mysql-test/suite/innodb/r/purge_secondary.result index 6c0612c7cfe..9801e985486 100644 --- a/mysql-test/suite/innodb/r/purge_secondary.result +++ b/mysql-test/suite/innodb/r/purge_secondary.result @@ -1,5 +1,3 @@ -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TABLE t1 ( a SERIAL, b CHAR(255) NOT NULL DEFAULT '', c BOOLEAN DEFAULT false, l LINESTRING NOT NULL DEFAULT ST_linefromtext('linestring(448 -689, @@ -169,4 +167,3 @@ page 5: N_RECS=0x0001 UNLOCK TABLES; DROP TABLE t1; # End of 10.3 tests -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/r/scrub.result b/mysql-test/suite/innodb/r/scrub.result index 0d977bc9e3a..4b976c32be3 100644 --- a/mysql-test/suite/innodb/r/scrub.result +++ b/mysql-test/suite/innodb/r/scrub.result @@ -1,6 +1,5 @@ SET GLOBAL innodb_file_per_table=OFF, -innodb_purge_rseg_truncate_frequency=1, innodb_immediate_scrub_data_uncompressed=ON; CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, f3 INT NOT NULL, INDEX(f1), diff --git a/mysql-test/suite/innodb/r/scrub_debug.result b/mysql-test/suite/innodb/r/scrub_debug.result index 5fbf1250b21..1e60fb73dad 100644 --- a/mysql-test/suite/innodb/r/scrub_debug.result +++ b/mysql-test/suite/innodb/r/scrub_debug.result @@ -1,7 +1,5 @@ SET @save_debug=@@GLOBAL.INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG; SET @save_scrub=@@GLOBAL.INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED; -SET @save_freq=@@GLOBAL.INNODB_PURGE_RSEG_TRUNCATE_FREQUENCY; -SET GLOBAL INNODB_PURGE_RSEG_TRUNCATE_FREQUENCY=1; SET GLOBAL INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED=1; SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=2; CREATE TABLE t1(f1 INT AUTO_INCREMENT PRIMARY KEY, @@ -19,4 +17,3 @@ UNLOCK TABLES; DROP TABLE t1; SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=@save_debug; SET GLOBAL INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED=@save_scrub; -SET GLOBAL INNODB_PURGE_RSEG_TRUNCATE_FREQUENCY = @save_freq; diff --git a/mysql-test/suite/innodb/r/truncate_crash.result b/mysql-test/suite/innodb/r/truncate_crash.result index ae3e6f6f4bf..5e7380e3286 100644 --- a/mysql-test/suite/innodb/r/truncate_crash.result +++ b/mysql-test/suite/innodb/r/truncate_crash.result @@ -8,10 +8,7 @@ connection default; SET DEBUG_SYNC='now WAIT_FOR c'; # restart disconnect wait; -SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; InnoDB 0 transactions not purged -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; SELECT COUNT(*) FROM t1; COUNT(*) 0 diff --git a/mysql-test/suite/innodb/r/trx_id_future.result b/mysql-test/suite/innodb/r/trx_id_future.result index 4f88b1d4783..c9beb17b81c 100644 --- a/mysql-test/suite/innodb/r/trx_id_future.result +++ b/mysql-test/suite/innodb/r/trx_id_future.result @@ -2,7 +2,6 @@ # Bug #20445525 ADD A CONSISTENCY CHECK AGAINST DB_TRX_ID BEING # IN THE FUTURE # -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; CREATE TABLE t1(a INT) row_format=redundant engine=innoDB; INSERT INTO t1 VALUES(1); InnoDB 0 transactions not purged diff --git a/mysql-test/suite/innodb/r/undo_log.result b/mysql-test/suite/innodb/r/undo_log.result index cda3b190ede..6e377951960 100644 --- a/mysql-test/suite/innodb/r/undo_log.result +++ b/mysql-test/suite/innodb/r/undo_log.result @@ -144,8 +144,6 @@ CHECK TABLE test_tab; Table Op Msg_type Msg_text test.test_tab check status OK DROP TABLE test_tab; -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TEMPORARY TABLE t2(i INT)ENGINE=InnoDB; CREATE TABLE t1(i TEXT NOT NULL) ENGINE=INNODB; BEGIN; @@ -156,4 +154,3 @@ ROLLBACK; InnoDB 0 transactions not purged DROP TABLE t1; DROP TABLE t2; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/r/undo_space_dblwr.result b/mysql-test/suite/innodb/r/undo_space_dblwr.result index 7954c426341..d6822b20eb7 100644 --- a/mysql-test/suite/innodb/r/undo_space_dblwr.result +++ b/mysql-test/suite/innodb/r/undo_space_dblwr.result @@ -4,7 +4,6 @@ Variable_name Value innodb_doublewrite ON create table t1(f1 int not null, f2 int not null)engine=innodb; insert into t1 values (1, 1); -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; InnoDB 0 transactions not purged set GLOBAL innodb_log_checkpoint_now=1; # Make the first page dirty for undo tablespace diff --git a/mysql-test/suite/innodb/r/undo_truncate.result b/mysql-test/suite/innodb/r/undo_truncate.result index 48b184f07c7..7a0125650e5 100644 --- a/mysql-test/suite/innodb/r/undo_truncate.result +++ b/mysql-test/suite/innodb/r/undo_truncate.result @@ -1,5 +1,4 @@ SET GLOBAL innodb_undo_log_truncate = 0; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; === information_schema.innodb_sys_tablespaces and innodb_sys_datafiles === Space_Name Page_Size Zip_Size Path innodb_undo001 DEFAULT DEFAULT MYSQLD_DATADIR//undo001 @@ -33,7 +32,6 @@ connection con2; commit; disconnect con2; connection default; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET GLOBAL innodb_max_purge_lag_wait=0; set global innodb_fast_shutdown=0; # restart diff --git a/mysql-test/suite/innodb/r/undo_truncate_recover.result b/mysql-test/suite/innodb/r/undo_truncate_recover.result index 909771e6a17..f9f020d12b3 100644 --- a/mysql-test/suite/innodb/r/undo_truncate_recover.result +++ b/mysql-test/suite/innodb/r/undo_truncate_recover.result @@ -1,5 +1,4 @@ SET GLOBAL innodb_undo_log_truncate = 1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; create table t1(keyc int primary key, c char(100)) engine = innodb; begin; commit; diff --git a/mysql-test/suite/innodb/t/alter_kill.test b/mysql-test/suite/innodb/t/alter_kill.test index 8f7e6371919..3e0152ec458 100644 --- a/mysql-test/suite/innodb/t/alter_kill.test +++ b/mysql-test/suite/innodb/t/alter_kill.test @@ -27,7 +27,6 @@ call mtr.add_suppression("InnoDB: Table `test`\\.`bug16720368` is corrupted"); -- echo # SET GLOBAL innodb_file_per_table=1; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; CREATE TABLE bug16720368_1 (a INT PRIMARY KEY) ENGINE=InnoDB; diff --git a/mysql-test/suite/innodb/t/cursor-restore-locking.test b/mysql-test/suite/innodb/t/cursor-restore-locking.test index b65d3773ba2..0f90055ff8b 100644 --- a/mysql-test/suite/innodb/t/cursor-restore-locking.test +++ b/mysql-test/suite/innodb/t/cursor-restore-locking.test @@ -3,8 +3,6 @@ source include/have_debug.inc; source include/have_debug_sync.inc; -SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB, STATS_PERSISTENT=0; --source include/wait_all_purged.inc @@ -86,5 +84,4 @@ INSERT INTO t VALUES(30, 20); # trx_4 SET DEBUG_SYNC = 'RESET'; DROP TABLE t; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_freq; --source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/dml_purge.test b/mysql-test/suite/innodb/t/dml_purge.test index c13ff22572b..463ae3908b9 100644 --- a/mysql-test/suite/innodb/t/dml_purge.test +++ b/mysql-test/suite/innodb/t/dml_purge.test @@ -2,16 +2,12 @@ let INNODB_PAGE_SIZE=`select @@innodb_page_size`; let MYSQLD_DATADIR=`select @@datadir`; -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; --echo # --echo # MDEV-12288 Reset DB_TRX_ID when the history is removed, --echo # to speed up MVCC --echo # -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - CREATE TABLE t1(a INT PRIMARY KEY, b INT NOT NULL) ROW_FORMAT=REDUNDANT ENGINE=InnoDB; --source include/wait_all_purged.inc @@ -80,4 +76,3 @@ EOF UNLOCK TABLES; SELECT * FROM t1; DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 31ab5168d06..8e98af3fc53 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -138,9 +138,6 @@ ALTER TABLE child FORCE; DELETE FROM parent; DROP TABLE child,parent; -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - SELECT unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2'; @@ -737,7 +734,6 @@ disconnect con1; --source include/wait_all_purged.inc CHECK TABLE t1; DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; --echo # --echo # MDEV-17187 table doesn't exist in engine after ALTER other tables @@ -1080,9 +1076,6 @@ DROP TABLE IF EXISTS t2, t1; --echo # MDEV-30531 Corrupt index(es) on busy table when using FOREIGN KEY --echo # -SET @freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; - CREATE TABLE collections ( id int(11) unsigned NOT NULL AUTO_INCREMENT, collectionhash varchar(255) NOT NULL DEFAULT '0', @@ -1111,7 +1104,6 @@ REPLACE INTO binaries (id) VALUES (NULL); SET GLOBAL innodb_max_purge_lag_wait=0; CHECK TABLE binaries, collections EXTENDED; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@freq; --disconnect con1 diff --git a/mysql-test/suite/innodb/t/gap_lock_split.test b/mysql-test/suite/innodb/t/gap_lock_split.test index e8202615c3f..c67e693fc0b 100644 --- a/mysql-test/suite/innodb/t/gap_lock_split.test +++ b/mysql-test/suite/innodb/t/gap_lock_split.test @@ -3,9 +3,6 @@ --source include/have_debug.inc --source include/have_debug_sync.inc -SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; - CREATE TABLE t1(id INT PRIMARY key, val VARCHAR(16000)) ENGINE=InnoDB STATS_PERSISTENT=0; INSERT INTO t1 (id,val) SELECT 2*seq,'x' FROM seq_0_to_1023; @@ -44,4 +41,3 @@ disconnect con1; connection default; COMMIT; DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; diff --git a/mysql-test/suite/innodb/t/index_merge_threshold.test b/mysql-test/suite/innodb/t/index_merge_threshold.test index a587e10db6c..a60ecf51dca 100644 --- a/mysql-test/suite/innodb/t/index_merge_threshold.test +++ b/mysql-test/suite/innodb/t/index_merge_threshold.test @@ -13,9 +13,6 @@ --source include/have_innodb_16k.inc --source include/have_partition.inc -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - # Check index merge threshold by create index on all datatypes CREATE TABLE tab(a BIGINT PRIMARY KEY,c1 TINYTEXT,c2 TEXT,c3 MEDIUMTEXT, @@ -189,4 +186,3 @@ CREATE INDEX index1 ON tab1(b(750)) COMMENT 'MERGE_THRESHOLD=45'; --source suite/innodb/include/innodb_merge_threshold_secondary.inc DROP TABLE tab1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/t/innodb-16k.test b/mysql-test/suite/innodb/t/innodb-16k.test index 56109543ee4..8bec62544c3 100644 --- a/mysql-test/suite/innodb/t/innodb-16k.test +++ b/mysql-test/suite/innodb/t/innodb-16k.test @@ -16,9 +16,7 @@ SELECT variable_value FROM information_schema.global_status --echo # varies depending on number of fields and other overhead. SET SESSION innodb_strict_mode = ON; -SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @save_level=@@GLOBAL.innodb_compression_level; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET GLOBAL innodb_compression_level=1; # Compressed table: compressBound() for the s390x DFLTCC instruction @@ -458,7 +456,6 @@ DROP TABLE t1; --source include/wait_all_purged.inc -SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; SET GLOBAL innodb_compression_level=@save_level; DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge; diff --git a/mysql-test/suite/innodb/t/innodb-32k.test b/mysql-test/suite/innodb/t/innodb-32k.test index 07c6c10d013..496977c1bda 100644 --- a/mysql-test/suite/innodb/t/innodb-32k.test +++ b/mysql-test/suite/innodb/t/innodb-32k.test @@ -3,8 +3,6 @@ --source include/have_innodb.inc --source include/have_innodb_32k.inc -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; - call mtr.add_suppression("Innodb: Cannot add field.*row size is"); let $MYSQLD_DATADIR= `select @@datadir`; diff --git a/mysql-test/suite/innodb/t/innodb-system-table-view.test b/mysql-test/suite/innodb/t/innodb-system-table-view.test index ea620b398e5..659c42f0e09 100644 --- a/mysql-test/suite/innodb/t/innodb-system-table-view.test +++ b/mysql-test/suite/innodb/t/innodb-system-table-view.test @@ -4,8 +4,6 @@ --source include/innodb_page_size_small.inc -SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; LET $MYSQLD_DATADIR = `select @@datadir`; LET $INNODB_PAGE_SIZE = `select @@innodb_page_size`; @@ -140,7 +138,6 @@ WHERE name LIKE "%parent"; DROP TABLE child; DROP TABLE parent; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; --echo # --echo # MDEV-29479 I_S.INNODB_SYS_TABLESPACES doesn't have diff --git a/mysql-test/suite/innodb/t/innodb_bug14147491.test b/mysql-test/suite/innodb/t/innodb_bug14147491.test index 3c37f1b7cce..10f3c98be9e 100644 --- a/mysql-test/suite/innodb/t/innodb_bug14147491.test +++ b/mysql-test/suite/innodb/t/innodb_bug14147491.test @@ -16,7 +16,6 @@ call mtr.add_suppression("InnoDB: File '.*test/t1\\.ibd' is corrupted"); --enable_query_log --echo # Ensure that purge will not crash on the table after we corrupt it. -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; SET GLOBAL innodb_fast_shutdown=0; --echo # Create and populate the table to be corrupted diff --git a/mysql-test/suite/innodb/t/innodb_bug84958.test b/mysql-test/suite/innodb/t/innodb_bug84958.test index b42f7bd639e..d4159dcc485 100644 --- a/mysql-test/suite/innodb/t/innodb_bug84958.test +++ b/mysql-test/suite/innodb/t/innodb_bug84958.test @@ -6,8 +6,6 @@ --echo # --source include/have_innodb.inc -SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency= 1; DELIMITER ~~; CREATE PROCEDURE insert_n(start int, end int) @@ -90,7 +88,6 @@ CHECK TABLE t1; --echo # disconnect con2; disconnect con3; -SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; DROP TABLE t1; DROP PROCEDURE insert_n; DROP FUNCTION num_pages_get; diff --git a/mysql-test/suite/innodb/t/innodb_stats_persistent.test b/mysql-test/suite/innodb/t/innodb_stats_persistent.test index f79ae37e8de..a8a311a60c9 100644 --- a/mysql-test/suite/innodb/t/innodb_stats_persistent.test +++ b/mysql-test/suite/innodb/t/innodb_stats_persistent.test @@ -1,8 +1,6 @@ --source include/have_innodb.inc --source include/have_sequence.inc -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; SET @saved_include_delete_marked = @@GLOBAL.innodb_stats_include_delete_marked; SET GLOBAL innodb_stats_include_delete_marked = ON; SET @saved_traditional = @@GLOBAL.innodb_stats_traditional; @@ -84,4 +82,3 @@ DROP TABLE t1,t2; SET GLOBAL innodb_stats_include_delete_marked = @saved_include_delete_marked; SET GLOBAL innodb_stats_traditional = @saved_traditional; SET GLOBAL innodb_stats_modified_counter = @saved_modified_counter; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/t/instant_alter.test b/mysql-test/suite/innodb/t/instant_alter.test index 8e333e3bb72..5b6d3f874c1 100644 --- a/mysql-test/suite/innodb/t/instant_alter.test +++ b/mysql-test/suite/innodb/t/instant_alter.test @@ -44,8 +44,6 @@ connect analyze, localhost, root; connection default; SET timestamp = 42; SET time_zone='+03:00'; -SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET @old_instant= (SELECT variable_value FROM information_schema.global_status @@ -906,7 +904,6 @@ DROP TABLE t1; SELECT variable_value-@old_instant instants FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; -SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; SET GLOBAL innodb_instant_alter_column_allowed = @saved_allowance; --echo # diff --git a/mysql-test/suite/innodb/t/instant_alter_bugs.test b/mysql-test/suite/innodb/t/instant_alter_bugs.test index 5c3c39d44e0..81d36849abd 100644 --- a/mysql-test/suite/innodb/t/instant_alter_bugs.test +++ b/mysql-test/suite/innodb/t/instant_alter_bugs.test @@ -1,8 +1,5 @@ --source include/have_innodb.inc -SET @save_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; - --echo # --echo # MDEV-17821 Assertion `!page_rec_is_supremum(rec)' failed --echo # in btr_pcur_store_position @@ -217,8 +214,6 @@ DROP TABLE t1; --echo # in btr_pcur_store_position() --echo # -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - CREATE TABLE t ( pk int auto_increment, c01 char(255) not null default repeat('a',255), @@ -245,7 +240,6 @@ ROLLBACK; DELETE FROM t; --source include/wait_all_purged.inc -SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; CREATE TABLE tt ENGINE=InnoDB AS SELECT c FROM t; DROP TABLE t, tt; @@ -524,7 +518,6 @@ ALTER TABLE t1 ADD COLUMN(f2 INT NOT NULL, f3 INT NOT NULL, f4 INT NOT NULL, f5 INT NOT NULL), CHANGE COLUMN f1 f1 CHAR(10) DEFAULT NULL; DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; --echo # --echo # MDEV-26420 Buffer overflow on instant ADD/DROP of generated column diff --git a/mysql-test/suite/innodb/t/instant_alter_crash.test b/mysql-test/suite/innodb/t/instant_alter_crash.test index 37cdb2862ad..b687664dbcc 100644 --- a/mysql-test/suite/innodb/t/instant_alter_crash.test +++ b/mysql-test/suite/innodb/t/instant_alter_crash.test @@ -36,7 +36,6 @@ COMMIT; disconnect ddl; --source include/start_mysqld.inc -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SELECT * FROM t1; SELECT * FROM t2; BEGIN; @@ -64,9 +63,6 @@ COMMIT; disconnect ddl; --source include/start_mysqld.inc -SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; - SELECT * FROM t1; SELECT * FROM t2; BEGIN; @@ -94,8 +90,6 @@ COMMIT; disconnect ddl; --source include/start_mysqld.inc -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; - let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; let SEARCH_PATTERN= \[Note\] InnoDB: Rolled back recovered transaction ; -- source include/search_pattern_in_file.inc diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index 11d6961f918..2b34d829738 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -3,9 +3,6 @@ --source include/have_debug_sync.inc --source include/have_sequence.inc -SET @save_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; - SET @old_instant= (SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'); @@ -607,8 +604,6 @@ SET DEBUG_SYNC=RESET; --echo # End of 10.5 tests -SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; - SELECT variable_value-@old_instant instants FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; diff --git a/mysql-test/suite/innodb/t/instant_alter_purge.test b/mysql-test/suite/innodb/t/instant_alter_purge.test index 88a56141a1f..445cae4d03e 100644 --- a/mysql-test/suite/innodb/t/instant_alter_purge.test +++ b/mysql-test/suite/innodb/t/instant_alter_purge.test @@ -4,8 +4,6 @@ if ($have_debug) { --source include/have_debug_sync.inc } -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; --source include/wait_all_purged.inc --echo # @@ -34,4 +32,3 @@ disconnect prevent_purge; let $wait_all_purged= 0; --source include/wait_all_purged.inc DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/t/instant_alter_rollback.test b/mysql-test/suite/innodb/t/instant_alter_rollback.test index cfece7e0738..a4608001a25 100644 --- a/mysql-test/suite/innodb/t/instant_alter_rollback.test +++ b/mysql-test/suite/innodb/t/instant_alter_rollback.test @@ -60,11 +60,8 @@ CREATE TABLE foo(a INT PRIMARY KEY) ENGINE=InnoDB; disconnect to_be_killed; --source include/start_mysqld.inc -SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; DROP TABLE foo; --source include/wait_all_purged.inc -SET GLOBAL innodb_purge_rseg_truncate_frequency=@saved_frequency; SELECT * FROM empty; SELECT * FROM once; diff --git a/mysql-test/suite/innodb/t/page_id_innochecksum.test b/mysql-test/suite/innodb/t/page_id_innochecksum.test index 2a2c14844fa..902d2aba2af 100644 --- a/mysql-test/suite/innodb/t/page_id_innochecksum.test +++ b/mysql-test/suite/innodb/t/page_id_innochecksum.test @@ -63,7 +63,6 @@ let SEARCH_PATTERN=page id mismatch; --remove_file $resultlog let $restart_parameters=--innodb-force-recovery=1; --source include/start_mysqld.inc -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; --source include/wait_all_purged.inc drop table t1; call mtr.add_suppression("InnoDB: Failed to read page 3 from file '.*test/t1\\.ibd': Page read from tablespace is corrupted\\."); diff --git a/mysql-test/suite/innodb/t/purge.test b/mysql-test/suite/innodb/t/purge.test index 63312e50fd8..97c0fb86105 100644 --- a/mysql-test/suite/innodb/t/purge.test +++ b/mysql-test/suite/innodb/t/purge.test @@ -1,9 +1,6 @@ --source include/have_innodb.inc --source include/have_innodb_16k.inc -SET @save_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; - --echo # Bug #12429576 - Test an assertion failure on purge. CREATE TABLE t1_purge ( A int, @@ -114,4 +111,3 @@ SHOW CREATE TABLE t12963823; -- source include/wait_all_purged.inc DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge, t12637786, t12963823; -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; diff --git a/mysql-test/suite/innodb/t/purge_secondary.test b/mysql-test/suite/innodb/t/purge_secondary.test index a7f75f56b53..4e664109e8b 100644 --- a/mysql-test/suite/innodb/t/purge_secondary.test +++ b/mysql-test/suite/innodb/t/purge_secondary.test @@ -5,10 +5,6 @@ call mtr.add_suppression("InnoDB: Difficult to find free blocks in the buffer pool"); --enable_query_log -# Ensure that the history list length will actually be decremented by purge. -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - CREATE TABLE t1 ( a SERIAL, b CHAR(255) NOT NULL DEFAULT '', c BOOLEAN DEFAULT false, l LINESTRING NOT NULL DEFAULT ST_linefromtext('linestring(448 -689, @@ -174,5 +170,3 @@ UNLOCK TABLES; DROP TABLE t1; --echo # End of 10.3 tests - -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/t/scrub.test b/mysql-test/suite/innodb/t/scrub.test index a2f4e5757f5..1c38637984a 100644 --- a/mysql-test/suite/innodb/t/scrub.test +++ b/mysql-test/suite/innodb/t/scrub.test @@ -4,7 +4,6 @@ SET GLOBAL innodb_file_per_table=OFF, - innodb_purge_rseg_truncate_frequency=1, innodb_immediate_scrub_data_uncompressed=ON; CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, f3 INT NOT NULL, INDEX(f1), diff --git a/mysql-test/suite/innodb/t/scrub_debug.test b/mysql-test/suite/innodb/t/scrub_debug.test index 141b0f0c5ba..a1f0b38e3ae 100644 --- a/mysql-test/suite/innodb/t/scrub_debug.test +++ b/mysql-test/suite/innodb/t/scrub_debug.test @@ -4,9 +4,7 @@ SET @save_debug=@@GLOBAL.INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG; SET @save_scrub=@@GLOBAL.INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED; -SET @save_freq=@@GLOBAL.INNODB_PURGE_RSEG_TRUNCATE_FREQUENCY; -SET GLOBAL INNODB_PURGE_RSEG_TRUNCATE_FREQUENCY=1; SET GLOBAL INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED=1; SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=2; let $MYSQLD_DATADIR=`select @@datadir`; @@ -28,4 +26,3 @@ UNLOCK TABLES; DROP TABLE t1; SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=@save_debug; SET GLOBAL INNODB_IMMEDIATE_SCRUB_DATA_UNCOMPRESSED=@save_scrub; -SET GLOBAL INNODB_PURGE_RSEG_TRUNCATE_FREQUENCY = @save_freq; diff --git a/mysql-test/suite/innodb/t/table_flags.test b/mysql-test/suite/innodb/t/table_flags.test index 6b2e6ee3ea6..34204ae11f4 100644 --- a/mysql-test/suite/innodb/t/table_flags.test +++ b/mysql-test/suite/innodb/t/table_flags.test @@ -34,7 +34,6 @@ let bugdir= $MYSQLTEST_VARDIR/tmp/table_flags; --let $d=--innodb-data-home-dir=$bugdir --innodb-log-group-home-dir=$bugdir --let $d=$d --innodb-data-file-path=ibdata1:1M:autoextend --let $d=$d --innodb-undo-tablespaces=0 ---let $d=$d --innodb-purge-rseg-truncate-frequency=1 --let $d=$d --skip-innodb-fast-shutdown --let $restart_noprint=1 --let $restart_parameters=$d --innodb-stats-persistent=0 diff --git a/mysql-test/suite/innodb/t/truncate_crash.test b/mysql-test/suite/innodb/t/truncate_crash.test index 27b8feea8a4..c5156b4b3fd 100644 --- a/mysql-test/suite/innodb/t/truncate_crash.test +++ b/mysql-test/suite/innodb/t/truncate_crash.test @@ -17,10 +17,7 @@ SET DEBUG_SYNC='now WAIT_FOR c'; --source include/restart_mysqld.inc disconnect wait; -SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; --source include/wait_all_purged.inc -SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; --replace_result 2 0 SELECT COUNT(*) FROM t1; diff --git a/mysql-test/suite/innodb/t/trx_id_future.test b/mysql-test/suite/innodb/t/trx_id_future.test index 18077549cf6..1aeb1372eed 100644 --- a/mysql-test/suite/innodb/t/trx_id_future.test +++ b/mysql-test/suite/innodb/t/trx_id_future.test @@ -6,7 +6,6 @@ --source include/have_innodb.inc --source include/not_embedded.inc -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; let PAGE_SIZE=`select @@innodb_page_size`; CREATE TABLE t1(a INT) row_format=redundant engine=innoDB; diff --git a/mysql-test/suite/innodb/t/undo_log.test b/mysql-test/suite/innodb/t/undo_log.test index 150d50c2e75..2dbc9191f33 100644 --- a/mysql-test/suite/innodb/t/undo_log.test +++ b/mysql-test/suite/innodb/t/undo_log.test @@ -141,8 +141,6 @@ SELECT COUNT(*) FROM test_tab; CHECK TABLE test_tab; DROP TABLE test_tab; -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TEMPORARY TABLE t2(i INT)ENGINE=InnoDB; CREATE TABLE t1(i TEXT NOT NULL) ENGINE=INNODB; BEGIN; @@ -153,4 +151,3 @@ ROLLBACK; --source include/wait_all_purged.inc DROP TABLE t1; DROP TABLE t2; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/t/undo_space_dblwr.test b/mysql-test/suite/innodb/t/undo_space_dblwr.test index c746f37ead7..b6fd6738a1c 100644 --- a/mysql-test/suite/innodb/t/undo_space_dblwr.test +++ b/mysql-test/suite/innodb/t/undo_space_dblwr.test @@ -9,7 +9,6 @@ show variables like 'innodb_doublewrite'; create table t1(f1 int not null, f2 int not null)engine=innodb; insert into t1 values (1, 1); -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; --source include/wait_all_purged.inc set GLOBAL innodb_log_checkpoint_now=1; diff --git a/mysql-test/suite/innodb/t/undo_truncate.test b/mysql-test/suite/innodb/t/undo_truncate.test index 496eccb002e..4abcae9a267 100644 --- a/mysql-test/suite/innodb/t/undo_truncate.test +++ b/mysql-test/suite/innodb/t/undo_truncate.test @@ -13,7 +13,6 @@ call mtr.add_suppression("InnoDB: Trying to delete tablespace.*pending operation --enable_query_log SET GLOBAL innodb_undo_log_truncate = 0; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; LET $MYSQLD_DATADIR = `select @@datadir`; LET $INNODB_PAGE_SIZE = `select @@innodb_page_size`; @@ -53,7 +52,6 @@ connection default; let $trx_before= `SHOW ENGINE INNODB STATUS`; let $trx_before= `select substr('$trx_before',9)+2`; -SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET GLOBAL innodb_max_purge_lag_wait=0; set global innodb_fast_shutdown=0; --source include/restart_mysqld.inc diff --git a/mysql-test/suite/innodb/t/undo_truncate_recover.test b/mysql-test/suite/innodb/t/undo_truncate_recover.test index e499ff3dfbe..8f55bafeeb6 100644 --- a/mysql-test/suite/innodb/t/undo_truncate_recover.test +++ b/mysql-test/suite/innodb/t/undo_truncate_recover.test @@ -13,7 +13,6 @@ --source include/not_embedded.inc SET GLOBAL innodb_undo_log_truncate = 1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err; diff --git a/mysql-test/suite/innodb_fts/r/crash_recovery.result b/mysql-test/suite/innodb_fts/r/crash_recovery.result index 83e5ddaea90..c6fc9dfaab9 100644 --- a/mysql-test/suite/innodb_fts/r/crash_recovery.result +++ b/mysql-test/suite/innodb_fts/r/crash_recovery.result @@ -33,10 +33,7 @@ connection default; disconnect ddl1; disconnect ddl2; disconnect ddl3; -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; InnoDB 0 transactions not purged -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; CHECK TABLE t1,t2,t3; Table Op Msg_type Msg_text test.t1 check status OK diff --git a/mysql-test/suite/innodb_fts/t/crash_recovery.test b/mysql-test/suite/innodb_fts/t/crash_recovery.test index cb53de4d595..dd8a07f8de9 100644 --- a/mysql-test/suite/innodb_fts/t/crash_recovery.test +++ b/mysql-test/suite/innodb_fts/t/crash_recovery.test @@ -111,13 +111,9 @@ disconnect ddl1; disconnect ddl2; disconnect ddl3; -# Ensure that the history list length will actually be decremented by purge. -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; # Wait for purge, so that any #sql-ib.ibd files from the previous kill # will be deleted. source ../../innodb/include/wait_all_purged.inc; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; CHECK TABLE t1,t2,t3; DROP TABLE t1,t2,t3; diff --git a/mysql-test/suite/innodb_gis/r/rtree_add_index.result b/mysql-test/suite/innodb_gis/r/rtree_add_index.result index dbd804b18bd..ba552e278d4 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_add_index.result +++ b/mysql-test/suite/innodb_gis/r/rtree_add_index.result @@ -1,5 +1,3 @@ -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TABLE t1 (g MULTIPOINT NOT NULL) ENGINE=InnoDB; INSERT INTO t1 VALUES (''); connect purge_control,localhost,root; @@ -10,4 +8,3 @@ ALTER TABLE t1 ADD SPATIAL INDEX (g); disconnect purge_control; InnoDB 0 transactions not purged DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb_gis/r/rtree_compress.result b/mysql-test/suite/innodb_gis/r/rtree_compress.result index a88f8b9fa9b..fce42319b55 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_compress.result +++ b/mysql-test/suite/innodb_gis/r/rtree_compress.result @@ -1,5 +1,3 @@ -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; create table t1 (c1 int, c2 geometry not null, spatial index (c2))engine=innodb ROW_FORMAT=COMPRESSED; insert into t1 values(1, Point(1,1)); insert into t1 values(2, Point(2,2)); @@ -51,4 +49,3 @@ count(*) SET debug_dbug = @saved_dbug; InnoDB 0 transactions not purged drop table t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb_gis/r/rtree_purge.result b/mysql-test/suite/innodb_gis/r/rtree_purge.result index 38c4f484504..4c39cc988c6 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_purge.result +++ b/mysql-test/suite/innodb_gis/r/rtree_purge.result @@ -1,8 +1,5 @@ -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; create table t ( b point not null,d point not null, spatial key (d),spatial key (b) ) engine=innodb; InnoDB 0 transactions not purged drop table t; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb_gis/r/rtree_undo.result b/mysql-test/suite/innodb_gis/r/rtree_undo.result index 589ccc3ff9a..d0e1564133f 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_undo.result +++ b/mysql-test/suite/innodb_gis/r/rtree_undo.result @@ -1,5 +1,3 @@ -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; connect control_purge,localhost,root,,; connection default; CREATE TABLE t1 ( @@ -136,4 +134,3 @@ SPATIAL KEY (g6) ) ENGINE=InnoDB; DROP TABLE t1,t2; disconnect control_purge; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb_gis/t/rtree_add_index.test b/mysql-test/suite/innodb_gis/t/rtree_add_index.test index cbc82f62a70..81755124a20 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_add_index.test +++ b/mysql-test/suite/innodb_gis/t/rtree_add_index.test @@ -1,8 +1,5 @@ --source include/have_innodb.inc -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - CREATE TABLE t1 (g MULTIPOINT NOT NULL) ENGINE=InnoDB; INSERT INTO t1 VALUES (''); @@ -17,4 +14,3 @@ ALTER TABLE t1 ADD SPATIAL INDEX (g); disconnect purge_control; --source ../../innodb/include/wait_all_purged.inc DROP TABLE t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb_gis/t/rtree_compress.test b/mysql-test/suite/innodb_gis/t/rtree_compress.test index a3d1e883a45..e667ec8e9f0 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_compress.test +++ b/mysql-test/suite/innodb_gis/t/rtree_compress.test @@ -10,9 +10,6 @@ # Valgrind takes too much time on PB2 even in the --big-test runs. --source include/not_valgrind.inc -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - create table t1 (c1 int, c2 geometry not null, spatial index (c2))engine=innodb ROW_FORMAT=COMPRESSED; # Insert enough values to let R-tree split. @@ -61,4 +58,3 @@ SET debug_dbug = @saved_dbug; # Clean up. drop table t1; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb_gis/t/rtree_purge.test b/mysql-test/suite/innodb_gis/t/rtree_purge.test index fc5ce2e14bc..cab86aa668f 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_purge.test +++ b/mysql-test/suite/innodb_gis/t/rtree_purge.test @@ -6,9 +6,6 @@ # This test often times out with MSAN --source include/not_msan.inc -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - create table t ( b point not null,d point not null, spatial key (d),spatial key (b) ) engine=innodb; @@ -29,4 +26,3 @@ dec $n; # Clean up. drop table t; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb_gis/t/rtree_undo.test b/mysql-test/suite/innodb_gis/t/rtree_undo.test index 2ae309a8f7e..962ff780fa0 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_undo.test +++ b/mysql-test/suite/innodb_gis/t/rtree_undo.test @@ -6,9 +6,6 @@ --source include/innodb_row_format.inc --source include/count_sessions.inc -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - connect (control_purge,localhost,root,,); connection default; @@ -100,5 +97,3 @@ dec $index; disconnect control_purge; --source include/wait_until_count_sessions.inc - -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb_zip/r/blob.result b/mysql-test/suite/innodb_zip/r/blob.result index bfe96b8a869..df3a49ed777 100644 --- a/mysql-test/suite/innodb_zip/r/blob.result +++ b/mysql-test/suite/innodb_zip/r/blob.result @@ -2,8 +2,6 @@ # MDEV-21259 Assertion 'w != NORMAL || mach_read_from_4(ptr) != val' # failed in mtr_t::write(), btr_free_externally_stored_field() # -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TABLE t1 (c TEXT, f2 INT PRIMARY KEY, f3 INT UNIQUE) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; SET @level= @@GLOBAL.innodb_compression_level; @@ -18,4 +16,3 @@ disconnect prevent_purge; InnoDB 0 transactions not purged DROP TABLE t1; SET GLOBAL innodb_compression_level = @level; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb_zip/t/blob.test b/mysql-test/suite/innodb_zip/t/blob.test index b85cf7313d0..4f9117f73ef 100644 --- a/mysql-test/suite/innodb_zip/t/blob.test +++ b/mysql-test/suite/innodb_zip/t/blob.test @@ -5,9 +5,6 @@ --echo # failed in mtr_t::write(), btr_free_externally_stored_field() --echo # -SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; - CREATE TABLE t1 (c TEXT, f2 INT PRIMARY KEY, f3 INT UNIQUE) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; @@ -26,4 +23,3 @@ REPLACE INTO t1 SELECT * FROM t1; DROP TABLE t1; SET GLOBAL innodb_compression_level = @level; -SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/mariabackup/unencrypted_page_compressed.result b/mysql-test/suite/mariabackup/unencrypted_page_compressed.result index 7edf66b027a..d995d1be364 100644 --- a/mysql-test/suite/mariabackup/unencrypted_page_compressed.result +++ b/mysql-test/suite/mariabackup/unencrypted_page_compressed.result @@ -1,5 +1,4 @@ call mtr.add_suppression("InnoDB: Table `test`.`t1` has an unreadable root page"); -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b TEXT, c char(200)) ENGINE=InnoDB page_compressed=yes; insert into t1(b, c) values("mariadb", "mariabackup"); InnoDB 0 transactions not purged diff --git a/mysql-test/suite/mariabackup/unencrypted_page_compressed.test b/mysql-test/suite/mariabackup/unencrypted_page_compressed.test index ce5c94a1c57..247a210a0e7 100644 --- a/mysql-test/suite/mariabackup/unencrypted_page_compressed.test +++ b/mysql-test/suite/mariabackup/unencrypted_page_compressed.test @@ -1,5 +1,4 @@ call mtr.add_suppression("InnoDB: Table `test`.`t1` has an unreadable root page"); -SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b TEXT, c char(200)) ENGINE=InnoDB page_compressed=yes; insert into t1(b, c) values("mariadb", "mariabackup"); --source ../innodb/include/wait_all_purged.inc diff --git a/mysql-test/suite/sys_vars/r/innodb_purge_rseg_truncate_frequency_basic.result b/mysql-test/suite/sys_vars/r/innodb_purge_rseg_truncate_frequency_basic.result index 65387032dc6..8b5ae0fae3e 100644 --- a/mysql-test/suite/sys_vars/r/innodb_purge_rseg_truncate_frequency_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_purge_rseg_truncate_frequency_basic.result @@ -4,7 +4,11 @@ SELECT @global_start_value; 128 '#--------------------FN_DYNVARS_046_01------------------------#' SET @@global.innodb_purge_rseg_truncate_frequency = 1; +Warnings: +Warning 1287 '@@innodb_purge_rseg_truncate_frequency' is deprecated and will be removed in a future release SET @@global.innodb_purge_rseg_truncate_frequency = DEFAULT; +Warnings: +Warning 1287 '@@innodb_purge_rseg_truncate_frequency' is deprecated and will be removed in a future release SELECT @@global.innodb_purge_rseg_truncate_frequency; @@global.innodb_purge_rseg_truncate_frequency 128 @@ -17,31 +21,41 @@ SELECT @@innodb_purge_rseg_truncate_frequency; SELECT local.innodb_purge_rseg_truncate_frequency; ERROR 42S02: Unknown table 'local' in field list SET global innodb_purge_rseg_truncate_frequency = 1; +Warnings: +Warning 1287 '@@innodb_purge_rseg_truncate_frequency' is deprecated and will be removed in a future release SELECT @@global.innodb_purge_rseg_truncate_frequency; @@global.innodb_purge_rseg_truncate_frequency 1 '#--------------------FN_DYNVARS_046_03------------------------#' SET @@global.innodb_purge_rseg_truncate_frequency = 1; +Warnings: +Warning 1287 '@@innodb_purge_rseg_truncate_frequency' is deprecated and will be removed in a future release SELECT @@global.innodb_purge_rseg_truncate_frequency; @@global.innodb_purge_rseg_truncate_frequency 1 SET @@global.innodb_purge_rseg_truncate_frequency = 1; +Warnings: +Warning 1287 '@@innodb_purge_rseg_truncate_frequency' is deprecated and will be removed in a future release SELECT @@global.innodb_purge_rseg_truncate_frequency; @@global.innodb_purge_rseg_truncate_frequency 1 SET @@global.innodb_purge_rseg_truncate_frequency = 128; +Warnings: +Warning 1287 '@@innodb_purge_rseg_truncate_frequency' is deprecated and will be removed in a future release SELECT @@global.innodb_purge_rseg_truncate_frequency; @@global.innodb_purge_rseg_truncate_frequency 128 '#--------------------FN_DYNVARS_046_05-------------------------#' SET @@global.innodb_purge_rseg_truncate_frequency = -1; Warnings: +Warning 1287 '@@innodb_purge_rseg_truncate_frequency' is deprecated and will be removed in a future release Warning 1292 Truncated incorrect innodb_purge_rseg_truncate_fr... value: '-1' SELECT @@global.innodb_purge_rseg_truncate_frequency; @@global.innodb_purge_rseg_truncate_frequency 1 SET @@global.innodb_purge_rseg_truncate_frequency = -1024; Warnings: +Warning 1287 '@@innodb_purge_rseg_truncate_frequency' is deprecated and will be removed in a future release Warning 1292 Truncated incorrect innodb_purge_rseg_truncate_fr... value: '-1024' SELECT @@global.innodb_purge_rseg_truncate_frequency; @@global.innodb_purge_rseg_truncate_frequency @@ -98,16 +112,21 @@ SELECT @@global.innodb_purge_rseg_truncate_frequency; 1 '#---------------------FN_DYNVARS_046_08----------------------#' SET @@global.innodb_purge_rseg_truncate_frequency = TRUE; +Warnings: +Warning 1287 '@@innodb_purge_rseg_truncate_frequency' is deprecated and will be removed in a future release SELECT @@global.innodb_purge_rseg_truncate_frequency; @@global.innodb_purge_rseg_truncate_frequency 1 SET @@global.innodb_purge_rseg_truncate_frequency = FALSE; Warnings: +Warning 1287 '@@innodb_purge_rseg_truncate_frequency' is deprecated and will be removed in a future release Warning 1292 Truncated incorrect innodb_purge_rseg_truncate_fr... value: '0' SELECT @@global.innodb_purge_rseg_truncate_frequency; @@global.innodb_purge_rseg_truncate_frequency 1 SET @@global.innodb_purge_rseg_truncate_frequency = @global_start_value; +Warnings: +Warning 1287 '@@innodb_purge_rseg_truncate_frequency' is deprecated and will be removed in a future release SELECT @@global.innodb_purge_rseg_truncate_frequency; @@global.innodb_purge_rseg_truncate_frequency 128 diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff index 7a524ba2c16..0442b2873dd 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff @@ -320,7 +320,7 @@ VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Dictates rate at which UNDO records are purged. Value N means purge rollback segment(s) on every Nth iteration of purge invocation + VARIABLE_COMMENT Deprecated parameter with no effect NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 128 @@ -1393,7 +1393,7 @@ diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 79f6dccefe3..5b728cee272 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -1308,7 +1308,7 @@ SESSION_VALUE NULL DEFAULT_VALUE 128 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Dictates rate at which UNDO records are purged. Value N means purge rollback segment(s) on every Nth iteration of purge invocation +VARIABLE_COMMENT Deprecated parameter with no effect NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 128 NUMERIC_BLOCK_SIZE 0 diff --git a/mysql-test/suite/versioning/r/delete_history.result b/mysql-test/suite/versioning/r/delete_history.result index d07c71ee9f5..16af01a5f0b 100644 --- a/mysql-test/suite/versioning/r/delete_history.result +++ b/mysql-test/suite/versioning/r/delete_history.result @@ -1,5 +1,3 @@ -set @saved_frequency= @@global.innodb_purge_rseg_truncate_frequency; -set global innodb_purge_rseg_truncate_frequency= 1; call mtr.add_suppression("need more HISTORY partitions"); create table t (a int); delete history from t before system_time now(); @@ -210,7 +208,6 @@ insert into t1 values (1, 'c'); delete from t1; alter table t1 add fulltext key(ftx); drop table t1; -set global innodb_purge_rseg_truncate_frequency= @saved_frequency; # # MDEV-28201 Server crashes upon SHOW ANALYZE/EXPLAIN FORMAT=JSON # diff --git a/mysql-test/suite/versioning/t/delete_history.test b/mysql-test/suite/versioning/t/delete_history.test index 042670bcfec..d3f7e1172f1 100644 --- a/mysql-test/suite/versioning/t/delete_history.test +++ b/mysql-test/suite/versioning/t/delete_history.test @@ -2,9 +2,6 @@ --source include/have_partition.inc --source suite/versioning/engines.inc -set @saved_frequency= @@global.innodb_purge_rseg_truncate_frequency; -set global innodb_purge_rseg_truncate_frequency= 1; - call mtr.add_suppression("need more HISTORY partitions"); create table t (a int); @@ -215,8 +212,6 @@ delete from t1; alter table t1 add fulltext key(ftx); drop table t1; -set global innodb_purge_rseg_truncate_frequency= @saved_frequency; - --echo # --echo # MDEV-28201 Server crashes upon SHOW ANALYZE/EXPLAIN FORMAT=JSON --echo # diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index f2bb09b9174..c356c4b9862 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -19378,9 +19378,8 @@ static MYSQL_SYSVAR_ULONGLONG(max_undo_log_size, srv_max_undo_log_size, static MYSQL_SYSVAR_ULONG(purge_rseg_truncate_frequency, srv_purge_rseg_truncate_frequency, - PLUGIN_VAR_OPCMDARG, - "Dictates rate at which UNDO records are purged. Value N means" - " purge rollback segment(s) on every Nth iteration of purge invocation", + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_DEPRECATED, + "Deprecated parameter with no effect", NULL, NULL, 128, 1, 128, 0); static void innodb_undo_log_truncate_update(THD *thd, struct st_mysql_sys_var*, diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 79b5c294e2a..29b1295dd4f 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -161,6 +161,9 @@ public: return undo_no <= other.undo_no; } + /** Free the undo pages up to this. */ + dberr_t free_history() const; + /** trx_t::no of the committed transaction */ trx_id_t trx_no; /** The record number within the committed transaction's undo @@ -172,7 +175,8 @@ public: committed transaction. */ iterator tail; /** The head of the purge queue; any older undo logs of committed - transactions may be discarded (history list truncation). */ + transactions may be discarded (history list truncation). + Protected by latch. */ iterator head; /*-----------------------------*/ bool next_stored; /*!< whether rseg holds the next record @@ -316,8 +320,9 @@ public: latch.wr_unlock(); } - /** Update end_view at the end of a purge batch. */ - inline void clone_end_view(); + /** Update end_view at the end of a purge batch. + @param head the new head of the purge queue */ + inline void clone_end_view(const iterator &head); struct view_guard { diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 4bd7df09fdc..4d813cbea48 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -509,7 +509,6 @@ struct purge_coordinator_state size_t m_history_length; Atomic_counter m_running; private: - ulint count; ulint n_use_threads; ulint n_threads; @@ -1284,6 +1283,13 @@ bool srv_any_background_activity() static void purge_worker_callback(void*); static void purge_coordinator_callback(void*); +static void purge_truncation_callback(void*) +{ + purge_sys.latch.rd_lock(SRW_LOCK_CALL); + const purge_sys_t::iterator head= purge_sys.head; + purge_sys.latch.rd_unlock(); + head.free_history(); +} static tpool::task_group purge_task_group; tpool::waitable_task purge_worker_task(purge_worker_callback, nullptr, @@ -1291,6 +1297,9 @@ tpool::waitable_task purge_worker_task(purge_worker_callback, nullptr, static tpool::task_group purge_coordinator_task_group(1); static tpool::waitable_task purge_coordinator_task (purge_coordinator_callback, nullptr, &purge_coordinator_task_group); +static tpool::task_group purge_truncation_task_group(1); +static tpool::waitable_task purge_truncation_task + (purge_truncation_callback, nullptr, &purge_truncation_task_group); static tpool::timer *purge_coordinator_timer; @@ -1693,15 +1702,20 @@ fewer_threads: if (!history_size) { srv_dml_needed_delay= 0; + purge_truncation_task.wait(); trx_purge_truncate_history(); } else { ulint n_pages_handled= trx_purge(n_use_threads, history_size); - if (!(++count % srv_purge_rseg_truncate_frequency) || - purge_sys.truncate.current || - (srv_shutdown_state != SRV_SHUTDOWN_NONE && srv_fast_shutdown == 0)) + if (purge_sys.truncate.current || + srv_shutdown_state != SRV_SHUTDOWN_NONE) + { + purge_truncation_task.wait(); trx_purge_truncate_history(); + } + else + srv_thread_pool->submit_task(&purge_truncation_task); if (n_pages_handled) continue; } @@ -1881,6 +1895,7 @@ static void srv_shutdown_purge_tasks() purge_thds.pop_front(); } n_purge_thds= 0; + purge_truncation_task.wait(); } /**********************************************************************//** diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index a606d3852ad..f8d97c1a14a 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -124,9 +124,15 @@ TRANSACTIONAL_INLINE inline bool TrxUndoRsegsIterator::set_next() #endif } - /* Only the purge coordinator task will access this object + /* Only the purge_coordinator_task will access this object purge_sys.rseg_iter, or any of purge_sys.hdr_page_no, - purge_sys.tail, purge_sys.head, or modify purge_sys.view. */ + purge_sys.tail. + The field purge_sys.head and purge_sys.view are only modified by + purge_sys_t::clone_end_view() + in the purge_coordinator_task + while holding exclusive purge_sys.latch. + The purge_sys.head may be read by + purge_truncation_callback(). */ ut_ad(last_trx_no == m_rsegs.trx_no); ut_a(purge_sys.hdr_page_no != FIL_NULL); ut_a(purge_sys.tail.trx_no <= last_trx_no); @@ -539,6 +545,24 @@ static void trx_purge_cleanse_purge_queue(const fil_space_t& space) mysql_mutex_unlock(&purge_sys.pq_mutex); } +dberr_t purge_sys_t::iterator::free_history() const +{ + for (auto &rseg : trx_sys.rseg_array) + if (rseg.space) + { + ut_ad(rseg.is_persistent()); + log_free_check(); + rseg.latch.wr_lock(SRW_LOCK_CALL); + dberr_t err= + trx_purge_truncate_rseg_history(rseg, *this, !rseg.is_referenced() && + purge_sys.sees(rseg.needs_purge)); + rseg.latch.wr_unlock(); + if (err) + return err; + } + return DB_SUCCESS; +} + #if defined __GNUC__ && __GNUC__ == 4 && !defined __clang__ # if defined __arm__ || defined __aarch64__ /* Work around an internal compiler error in GCC 4.8.5 */ @@ -547,7 +571,8 @@ __attribute__((optimize(0))) #endif /** Remove unnecessary history data from rollback segments. NOTE that when this -function is called, the caller (purge_coordinator_callback) +function is called, the caller +(purge_coordinator_callback or purge_truncation_callback) must not have any latches on undo log pages! */ TRANSACTIONAL_TARGET void trx_purge_truncate_history() @@ -563,22 +588,7 @@ TRANSACTIONAL_TARGET void trx_purge_truncate_history() head.undo_no= 0; } - dberr_t err= DB_SUCCESS; - for (auto &rseg : trx_sys.rseg_array) - if (rseg.space) - { - ut_ad(rseg.is_persistent()); - log_free_check(); - rseg.latch.wr_lock(SRW_LOCK_CALL); - if (dberr_t e= - trx_purge_truncate_rseg_history(rseg, head, - !rseg.is_referenced() && - purge_sys.sees(rseg.needs_purge))) - err= e; - rseg.latch.wr_unlock(); - } - - if (err != DB_SUCCESS || srv_undo_tablespaces_active < 2) + if (head.free_history() != DB_SUCCESS || srv_undo_tablespaces_active < 2) return; while (srv_undo_log_truncate) @@ -782,6 +792,7 @@ not_free: if trx_t::commit_empty() had been executed in the past, possibly before this server had been started up. */ + dberr_t err; buf_block_t *rblock= trx_rseg_header_create(&space, &rseg - trx_sys.rseg_array, trx_sys.get_max_trx_id(), @@ -1101,9 +1112,8 @@ trx_purge_fetch_next_rec( /** Run a purge batch. @param n_purge_threads number of purge threads -@return number of undo log pages handled in the batch */ -static -ulint +@return new purge_sys.head and the number of undo log pages handled */ +static std::pair trx_purge_attach_undo_recs(ulint n_purge_threads) { que_thr_t* thr; @@ -1113,7 +1123,7 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) ut_a(n_purge_threads > 0); ut_a(UT_LIST_GET_LEN(purge_sys.query->thrs) >= n_purge_threads); - purge_sys.head = purge_sys.tail; + purge_sys_t::iterator head = purge_sys.tail; #ifdef UNIV_DEBUG i = 0; @@ -1142,7 +1152,7 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) to a per purge node vector. */ thr = UT_LIST_GET_FIRST(purge_sys.query->thrs); - ut_ad(purge_sys.head <= purge_sys.tail); + ut_ad(head <= purge_sys.tail); i = 0; @@ -1155,8 +1165,8 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) /* Track the max {trx_id, undo_no} for truncating the UNDO logs once we have purged the records. */ - if (purge_sys.head <= purge_sys.tail) { - purge_sys.head = purge_sys.tail; + if (head <= purge_sys.tail) { + head = purge_sys.tail; } /* Fetch the next record, and advance the purge_sys.tail. */ @@ -1195,9 +1205,9 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) } } - ut_ad(purge_sys.head <= purge_sys.tail); + ut_ad(head <= purge_sys.tail); - return(n_pages_handled); + return std::make_pair(head, n_pages_handled); } extern tpool::waitable_task purge_worker_task; @@ -1221,7 +1231,8 @@ static void trx_purge_wait_for_workers_to_complete() } /** Update end_view at the end of a purge batch. */ -TRANSACTIONAL_INLINE void purge_sys_t::clone_end_view() +TRANSACTIONAL_INLINE +void purge_sys_t::clone_end_view(const purge_sys_t::iterator &head) { /* This is only invoked only by the purge coordinator, which is the only thread that can modify our inputs head, tail, view. @@ -1234,6 +1245,7 @@ TRANSACTIONAL_INLINE void purge_sys_t::clone_end_view() #else transactional_lock_guard g(end_latch); #endif + this->head= head; end_view= view; end_view.clamp_low_limit_id(trx_no); #ifdef SUX_LOCK_GENERIC @@ -1248,8 +1260,6 @@ Run a purge batch. @return number of undo log pages handled in the batch */ TRANSACTIONAL_TARGET ulint trx_purge(ulint n_tasks, ulint history_size) { - ulint n_pages_handled; - ut_ad(n_tasks > 0); purge_sys.clone_oldest_view(); @@ -1261,10 +1271,10 @@ TRANSACTIONAL_TARGET ulint trx_purge(ulint n_tasks, ulint history_size) #endif /* UNIV_DEBUG */ /* Fetch the UNDO recs that need to be purged. */ - n_pages_handled = trx_purge_attach_undo_recs(n_tasks); + const auto n = trx_purge_attach_undo_recs(n_tasks); { - ulint delay = n_pages_handled ? srv_max_purge_lag : 0; + ulint delay = n.second ? srv_max_purge_lag : 0; if (UNIV_UNLIKELY(delay)) { if (delay >= history_size) { no_throttle: @@ -1297,10 +1307,10 @@ TRANSACTIONAL_TARGET ulint trx_purge(ulint n_tasks, ulint history_size) trx_purge_wait_for_workers_to_complete(); - purge_sys.clone_end_view(); + purge_sys.clone_end_view(n.first); MONITOR_INC_VALUE(MONITOR_PURGE_INVOKED, 1); - MONITOR_INC_VALUE(MONITOR_PURGE_N_PAGE_HANDLED, n_pages_handled); + MONITOR_INC_VALUE(MONITOR_PURGE_N_PAGE_HANDLED, n.second); - return(n_pages_handled); + return n.second; } diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index 12e2d54b608..6827d693345 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -1256,8 +1256,8 @@ trx_undo_reuse_cached(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** pundo, ut_ad(rseg == trx->rsegs.m_redo.rseg); if (rseg->needs_purge <= trx->id) { - /* trx_purge_truncate_history() compares - rseg->needs_purge <= head.trx_no + /* trx_purge_truncate_history() checks + purge_sys.sees(rseg.needs_purge) so we need to compensate for that. The rseg->needs_purge after crash recovery would be at least trx->id + 1, From 44689eb7d85b05df9ffbc631735447ba96c92e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Oct 2023 09:38:21 +0300 Subject: [PATCH 119/158] MDEV-32050: Improve srv_wake_purge_thread_if_not_active() purge_sys_t::wake_if_not_active(): Replaces srv_wake_purge_thread_if_not_active(). innodb_ddl_recovery_done(): Move the wakeup call to srv_init_purge_tasks(). purge_coordinator_timer: Remove. The srv_master_callback() already invokes purge_sys.wake_if_not_active() once per second. Reviewed by: Vladislav Lesin and Vladislav Vaintroub --- storage/innobase/handler/ha_innodb.cc | 8 ++- storage/innobase/include/srv0srv.h | 4 -- storage/innobase/include/trx0purge.h | 7 ++- storage/innobase/row/row0mysql.cc | 2 +- storage/innobase/srv/srv0srv.cc | 74 ++++++++------------------- storage/innobase/trx/trx0purge.cc | 5 +- 6 files changed, 33 insertions(+), 67 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index c356c4b9862..0ebafa4c6dd 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -238,7 +238,7 @@ static void innodb_max_purge_lag_wait_update(THD *thd, st_mysql_sys_var *, const lsn_t lsn= log_sys.get_lsn(); if ((lsn - last) / 4 >= max_age / 5) buf_flush_ahead(last + max_age / 5, false); - srv_wake_purge_thread_if_not_active(); + purge_sys.wake_if_not_active(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } mysql_mutex_lock(&LOCK_global_system_variables); @@ -2159,8 +2159,6 @@ static void innodb_ddl_recovery_done(handlerton*) if (srv_start_after_restore && !high_level_read_only) drop_garbage_tables_after_restore(); srv_init_purge_tasks(); - purge_sys.coordinator_startup(); - srv_wake_purge_thread_if_not_active(); } } @@ -16274,7 +16272,7 @@ innodb_show_status( DBUG_RETURN(0); } - srv_wake_purge_thread_if_not_active(); + purge_sys.wake_if_not_active(); /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE bytes of text. */ @@ -19386,7 +19384,7 @@ static void innodb_undo_log_truncate_update(THD *thd, struct st_mysql_sys_var*, void*, const void *save) { if ((srv_undo_log_truncate= *static_cast(save))) - srv_wake_purge_thread_if_not_active(); + purge_sys.wake_if_not_active(); } static MYSQL_SYSVAR_BOOL(undo_log_truncate, srv_undo_log_truncate, diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 0052f015239..86d114e1a42 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -570,10 +570,6 @@ Frees the data structures created in srv_init(). */ void srv_free(void); -/** Wake up the purge if there is work to do. */ -void -srv_wake_purge_thread_if_not_active(); - /******************************************************************//** Outputs to a file the output of the InnoDB Monitor. @return FALSE if not all information printed diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 29b1295dd4f..86a3264e6b8 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -235,12 +235,12 @@ public: bool paused() { return m_paused != 0; } - /** Enable purge at startup. Not protected by latch; the main thread - will wait for purge_sys.enabled() in srv_start() */ + /** Enable purge at startup. */ void coordinator_startup() { ut_ad(!enabled()); m_enabled.store(true, std::memory_order_relaxed); + wake_if_not_active(); } /** Disable purge at shutdown */ @@ -320,6 +320,9 @@ public: latch.wr_unlock(); } + /** Wake up the purge threads if there is work to do. */ + void wake_if_not_active(); + /** Update end_view at the end of a purge batch. @param head the new head of the purge queue */ inline void clone_end_view(const iterator &head); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index f86cd0e18e2..21cd1974ee4 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -82,7 +82,7 @@ static void row_mysql_delay_if_needed() const lsn_t lsn= log_sys.get_lsn(); if ((lsn - last) / 4 >= max_age / 5) buf_flush_ahead(last + max_age / 5, false); - srv_wake_purge_thread_if_not_active(); + purge_sys.wake_if_not_active(); std::this_thread::sleep_for(std::chrono::microseconds(delay)); } } diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 4d813cbea48..d57d2bdd3f2 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1301,12 +1301,10 @@ static tpool::task_group purge_truncation_task_group(1); static tpool::waitable_task purge_truncation_task (purge_truncation_callback, nullptr, &purge_truncation_task_group); -static tpool::timer *purge_coordinator_timer; - /** Wake up the purge threads if there is work to do. */ -void srv_wake_purge_thread_if_not_active() +void purge_sys_t::wake_if_not_active() { - if (purge_sys.enabled() && !purge_sys.paused() && + if (enabled() && !paused() && !purge_state.m_running && (srv_undo_log_truncate || trx_sys.history_exists()) && ++purge_state.m_running == 1) srv_thread_pool->submit_task(&purge_coordinator_task); @@ -1389,8 +1387,8 @@ void purge_sys_t::resume() if (paused == 1) { ib::info() << "Resuming purge"; - purge_state.m_running = 0; - srv_wake_purge_thread_if_not_active(); + purge_state.m_running= 1; + srv_thread_pool->submit_task(&purge_coordinator_task); MONITOR_ATOMIC_INC(MONITOR_PURGE_RESUME_COUNT); } latch.wr_unlock(); @@ -1535,8 +1533,7 @@ void srv_master_callback(void*) ut_a(srv_shutdown_state <= SRV_SHUTDOWN_INITIATED); MONITOR_INC(MONITOR_MASTER_THREAD_SLEEP); - if (!purge_state.m_running) - srv_wake_purge_thread_if_not_active(); + purge_sys.wake_if_not_active(); ulonglong counter_time= microsecond_interval_timer(); srv_sync_log_buffer_in_background(); MONITOR_INC_TIME_IN_MICRO_SECS(MONITOR_SRV_LOG_FLUSH_MICROSECOND, @@ -1629,16 +1626,11 @@ inline void purge_coordinator_state::do_purge() ut_ad(!srv_read_only_mode); lazy_init(); ut_ad(n_threads); - bool wakeup= false; - - purge_coordinator_timer->disarm(); while (purge_sys.enabled() && !purge_sys.paused()) { loop: - wakeup= false; const auto now= my_interval_timer(); - const auto sigcount= m_running; if (now - start_time >= 1000000) { @@ -1683,10 +1675,7 @@ fewer_threads: lsn_hwm+= series[n_use_threads]; } else if (n_use_threads == 1 && lsn_age_factor >= 100 - safety_net) - { - wakeup= true; break; - } } else if (n_threads > n_use_threads && srv_max_purge_lag && m_history_length > srv_max_purge_lag) @@ -1701,50 +1690,30 @@ fewer_threads: if (!history_size) { + no_history: srv_dml_needed_delay= 0; purge_truncation_task.wait(); trx_purge_truncate_history(); + break; + } + + ulint n_pages_handled= trx_purge(n_use_threads, history_size); + if (!trx_sys.history_exists()) + goto no_history; + if (purge_sys.truncate.current || srv_shutdown_state != SRV_SHUTDOWN_NONE) + { + purge_truncation_task.wait(); + trx_purge_truncate_history(); } else - { - ulint n_pages_handled= trx_purge(n_use_threads, history_size); - if (purge_sys.truncate.current || - srv_shutdown_state != SRV_SHUTDOWN_NONE) - { - purge_truncation_task.wait(); - trx_purge_truncate_history(); - } - else - srv_thread_pool->submit_task(&purge_truncation_task); - if (n_pages_handled) - continue; - } - - if (srv_dml_needed_delay); - else if (m_running == sigcount) - { - /* Purge was not woken up by srv_wake_purge_thread_if_not_active() */ - - /* The magic number 5000 is an approximation for the case where we have - cached undo log records which prevent truncate of rollback segments. */ - wakeup= history_size >= 5000 || - (history_size && history_size != trx_sys.history_size_approx()); + srv_thread_pool->submit_task(&purge_truncation_task); + if (!n_pages_handled) break; - } - - if (!trx_sys.history_exists()) - { - srv_dml_needed_delay= 0; - break; - } if (!srv_purge_should_exit(history_size)) goto loop; } - if (wakeup) - purge_coordinator_timer->set_time(10, 0); - m_running= 0; } @@ -1878,15 +1847,12 @@ static void purge_coordinator_callback(void*) void srv_init_purge_tasks() { purge_create_background_thds(srv_n_purge_threads); - purge_coordinator_timer= srv_thread_pool->create_timer - (purge_coordinator_callback, nullptr); + purge_sys.coordinator_startup(); } static void srv_shutdown_purge_tasks() { purge_coordinator_task.disable(); - delete purge_coordinator_timer; - purge_coordinator_timer= nullptr; purge_worker_task.wait(); std::unique_lock lk(purge_thd_mutex); while (!purge_thds.empty()) @@ -1944,7 +1910,7 @@ void srv_purge_shutdown() { history_size= trx_sys.history_size(); ut_a(!purge_sys.paused()); - srv_wake_purge_thread_if_not_active(); + srv_thread_pool->submit_task(&purge_coordinator_task); purge_coordinator_task.wait(); } purge_sys.coordinator_shutdown(); diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index f8d97c1a14a..422aee921ff 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -127,10 +127,13 @@ TRANSACTIONAL_INLINE inline bool TrxUndoRsegsIterator::set_next() /* Only the purge_coordinator_task will access this object purge_sys.rseg_iter, or any of purge_sys.hdr_page_no, purge_sys.tail. - The field purge_sys.head and purge_sys.view are only modified by + The field purge_sys.head and purge_sys.view are modified by purge_sys_t::clone_end_view() in the purge_coordinator_task while holding exclusive purge_sys.latch. + The purge_sys.view may also be modified by + purge_sys_t::wake_if_not_active() while holding exclusive + purge_sys.latch. The purge_sys.head may be read by purge_truncation_callback(). */ ut_ad(last_trx_no == m_rsegs.trx_no); From 2027c482de0a75ff09fd08704cdbe36dcf5db91e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Oct 2023 09:38:49 +0300 Subject: [PATCH 120/158] MDEV-32050: Hold exclusive purge_sys.rseg->latch longer Let the purge_coordinator_task acquire purge_sys.rseg->latch less frequently and hold it longer at a time. This may throttle concurrent DML and prevent purge lag a little. Remove an unnecessary std::this_thread::yield(), because the trx_purge_attach_undo_recs() is supposed to terminate the scan when running out of undo log records. Ultimately, this will result in purge_coordinator_state::do_purge() and purge_coordinator_callback() returning control to the thread pool. Reviewed by: Vladislav Lesin and Vladislav Vaintroub --- storage/innobase/include/trx0purge.h | 3 +- storage/innobase/trx/trx0purge.cc | 201 +++++++++++++-------------- 2 files changed, 96 insertions(+), 108 deletions(-) diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 86a3264e6b8..277b5c0a04d 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -109,7 +109,8 @@ struct TrxUndoRsegsIterator { TrxUndoRsegsIterator(); /** Sets the next rseg to purge in purge_sys. Executed in the purge coordinator thread. - @return whether anything is to be purged */ + @retval false when nothing is to be purged + @retval true when purge_sys.rseg->latch was locked */ inline bool set_next(); private: diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 422aee921ff..4011a3dfe7c 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -66,9 +66,11 @@ TrxUndoRsegsIterator::TrxUndoRsegsIterator() /** Sets the next rseg to purge in purge_sys. Executed in the purge coordinator thread. -@return whether anything is to be purged */ -TRANSACTIONAL_INLINE inline bool TrxUndoRsegsIterator::set_next() +@retval false when nothing is to be purged +@retval true when purge_sys.rseg->latch was locked */ +inline bool TrxUndoRsegsIterator::set_next() { + ut_ad(!purge_sys.next_stored); mysql_mutex_lock(&purge_sys.pq_mutex); /* Only purge consumes events from the priority queue, user @@ -106,23 +108,10 @@ TRANSACTIONAL_INLINE inline bool TrxUndoRsegsIterator::set_next() ut_ad(purge_sys.rseg->space->id == TRX_SYS_SPACE || srv_is_undo_tablespace(purge_sys.rseg->space->id)); - trx_id_t last_trx_no; - { -#ifdef SUX_LOCK_GENERIC - purge_sys.rseg->latch.rd_lock(SRW_LOCK_CALL); -#else - transactional_shared_lock_guard rg - {purge_sys.rseg->latch}; -#endif - last_trx_no = purge_sys.rseg->last_trx_no(); - - purge_sys.hdr_offset = purge_sys.rseg->last_offset(); - purge_sys.hdr_page_no = purge_sys.rseg->last_page_no; - -#ifdef SUX_LOCK_GENERIC - purge_sys.rseg->latch.rd_unlock(); -#endif - } + purge_sys.rseg->latch.wr_lock(SRW_LOCK_CALL); + trx_id_t last_trx_no = purge_sys.rseg->last_trx_no(); + purge_sys.hdr_offset = purge_sys.rseg->last_offset(); + purge_sys.hdr_page_no = purge_sys.rseg->last_page_no; /* Only the purge_coordinator_task will access this object purge_sys.rseg_iter, or any of purge_sys.hdr_page_no, @@ -839,18 +828,17 @@ not_free: /***********************************************************************//** Updates the last not yet purged history log info in rseg when we have purged -a whole undo log. Advances also purge_sys.purge_trx_no past the purged log. */ -static void trx_purge_rseg_get_next_history_log( - ulint* n_pages_handled)/*!< in/out: number of UNDO pages - handled */ +a whole undo log. Advances also purge_sys.purge_trx_no past the purged log. + +@param n_pages_handled number of UNDO pages handled */ +static void trx_purge_rseg_get_next_history_log(ulint *n_pages_handled) { fil_addr_t prev_log_addr; mtr_t mtr; mtr.start(); - purge_sys.rseg->latch.wr_lock(SRW_LOCK_CALL); - + ut_ad(purge_sys.rseg->latch.is_write_locked()); ut_a(purge_sys.rseg->last_page_no != FIL_NULL); purge_sys.tail.trx_no= purge_sys.rseg->last_trx_no() + 1; @@ -874,50 +862,44 @@ static void trx_purge_rseg_get_next_history_log( else prev_log_addr.page= FIL_NULL; - const bool empty= prev_log_addr.page == FIL_NULL; - - if (empty) - /* No logs left in the history list */ - purge_sys.rseg->last_page_no= FIL_NULL; - - purge_sys.rseg->latch.wr_unlock(); mtr.commit(); - if (empty) - return; - - /* Read the previous log header. */ - mtr.start(); - - trx_id_t trx_no= 0; - - if (const buf_block_t* undo_page= - buf_page_get_gen(page_id_t(purge_sys.rseg->space->id, prev_log_addr.page), - 0, RW_S_LATCH, nullptr, BUF_GET_POSSIBLY_FREED, &mtr)) + if (prev_log_addr.page == FIL_NULL) + purge_sys.rseg->last_page_no= FIL_NULL; + else { - const byte *log_hdr= undo_page->page.frame + prev_log_addr.boffset; + /* Read the previous log header. */ + mtr.start(); - trx_no= mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO); - ut_ad(mach_read_from_2(log_hdr + TRX_UNDO_NEEDS_PURGE) <= 1); + trx_id_t trx_no= 0; + if (const buf_block_t* undo_page= + buf_page_get_gen(page_id_t(purge_sys.rseg->space->id, + prev_log_addr.page), + 0, RW_S_LATCH, nullptr, BUF_GET_POSSIBLY_FREED, &mtr)) + { + const byte *log_hdr= undo_page->page.frame + prev_log_addr.boffset; + trx_no= mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO); + ut_ad(mach_read_from_2(log_hdr + TRX_UNDO_NEEDS_PURGE) <= 1); + } + + mtr.commit(); + + if (UNIV_LIKELY(trx_no != 0)) + { + purge_sys.rseg->last_page_no= prev_log_addr.page; + purge_sys.rseg->set_last_commit(prev_log_addr.boffset, trx_no); + + /* Purge can also produce events, however these are already + ordered in the rollback segment and any user generated event + will be greater than the events that Purge produces. ie. Purge + can never produce events from an empty rollback segment. */ + + mysql_mutex_lock(&purge_sys.pq_mutex); + purge_sys.purge_queue.push(*purge_sys.rseg); + mysql_mutex_unlock(&purge_sys.pq_mutex); + } } - mtr.commit(); - - if (UNIV_UNLIKELY(!trx_no)) - return; - - purge_sys.rseg->latch.wr_lock(SRW_LOCK_CALL); - purge_sys.rseg->last_page_no= prev_log_addr.page; - purge_sys.rseg->set_last_commit(prev_log_addr.boffset, trx_no); - - /* Purge can also produce events, however these are already ordered - in the rollback segment and any user generated event will be greater - than the events that Purge produces. ie. Purge can never produce - events from an empty rollback segment. */ - - mysql_mutex_lock(&purge_sys.pq_mutex); - purge_sys.purge_queue.push(*purge_sys.rseg); - mysql_mutex_unlock(&purge_sys.pq_mutex); purge_sys.rseg->latch.wr_unlock(); } @@ -965,16 +947,16 @@ static void trx_purge_read_undo_rec() Chooses the next undo log to purge and updates the info in purge_sys. This function is used to initialize purge_sys when the next record to purge is not known, and also to update the purge system info on the next record when -purge has handled the whole undo log for a transaction. */ -TRANSACTIONAL_TARGET static void trx_purge_choose_next_log() +purge has handled the whole undo log for a transaction. +@retval false when nothing is to be purged +@retval true when purge_sys.rseg->latch was locked */ +static bool trx_purge_choose_next_log() { - ut_ad(!purge_sys.next_stored); - if (purge_sys.rseg_iter.set_next()) { trx_purge_read_undo_rec(); + return true; } else { - /* There is nothing to do yet. */ - std::this_thread::yield(); + return false; } } @@ -995,9 +977,11 @@ trx_purge_get_next_rec( ut_ad(purge_sys.next_stored); ut_ad(purge_sys.tail.trx_no < purge_sys.low_limit_no()); + ut_ad(purge_sys.rseg->latch.is_write_locked()); const page_id_t page_id{purge_sys.rseg->space->id, purge_sys.page_no}; const uint16_t offset = purge_sys.offset; + bool locked = true; if (offset == 0) { /* It is the dummy undo log record, which means that there is @@ -1007,19 +991,24 @@ trx_purge_get_next_rec( /* Look for the next undo log and record to purge */ - trx_purge_choose_next_log(); + if (trx_purge_choose_next_log()) { + purge_sys.rseg->latch.wr_unlock(); + } return reinterpret_cast(-1); } mtr.start(); - + trx_undo_rec_t *rec_copy = nullptr; const buf_block_t* undo_page = buf_page_get_gen(page_id, 0, RW_S_LATCH, nullptr, BUF_GET_POSSIBLY_FREED, &mtr); if (UNIV_UNLIKELY(!undo_page)) { -corrupted: +func_exit: + if (locked) { + purge_sys.rseg->latch.wr_unlock(); + } mtr.commit(); - return nullptr; + return rec_copy; } const buf_block_t* rec2_page = undo_page; @@ -1040,7 +1029,7 @@ corrupted: /* Look for the next undo log and record to purge */ - trx_purge_choose_next_log(); + locked = trx_purge_choose_next_log(); mtr_start(&mtr); @@ -1048,7 +1037,7 @@ corrupted: nullptr, BUF_GET_POSSIBLY_FREED, &mtr); if (UNIV_UNLIKELY(!undo_page)) { - goto corrupted; + goto func_exit; } } else { purge_sys.offset = page_offset(rec2); @@ -1061,11 +1050,8 @@ corrupted: } } - trx_undo_rec_t* rec_copy = trx_undo_rec_copy(undo_page->page.frame - + offset, heap); - - mtr.commit(); - return rec_copy; + rec_copy = trx_undo_rec_copy(undo_page->page.frame + offset, heap); + goto func_exit; } /********************************************************************//** @@ -1083,34 +1069,35 @@ trx_purge_fetch_next_rec( handled */ mem_heap_t* heap) /*!< in: memory heap where copied */ { - if (!purge_sys.next_stored) { - trx_purge_choose_next_log(); + if (!purge_sys.next_stored) + { + bool locked= trx_purge_choose_next_log(); + ut_ad(locked == purge_sys.next_stored); + if (!locked) + return nullptr; + if (purge_sys.tail.trx_no >= purge_sys.low_limit_no()) + { + purge_sys.rseg->latch.wr_unlock(); + return nullptr; + } + /* row_purge_record_func() will later set ROLL_PTR_INSERT_FLAG for + TRX_UNDO_INSERT_REC */ + *roll_ptr= trx_undo_build_roll_ptr(false, + trx_sys.rseg_id(purge_sys.rseg, true), + purge_sys.page_no, purge_sys.offset); + } + else if (purge_sys.tail.trx_no >= purge_sys.low_limit_no()) + return nullptr; + else + { + *roll_ptr= trx_undo_build_roll_ptr(false, + trx_sys.rseg_id(purge_sys.rseg, true), + purge_sys.page_no, purge_sys.offset); + purge_sys.rseg->latch.wr_lock(SRW_LOCK_CALL); + } - if (!purge_sys.next_stored) { - DBUG_PRINT("ib_purge", - ("no logs left in the history list")); - return nullptr; - } - } - - if (purge_sys.tail.trx_no >= purge_sys.low_limit_no()) { - return nullptr; - } - - /* fprintf(stderr, "Thread %lu purging trx %llu undo record %llu\n", - pthread_self(), iter->trx_no, iter->undo_no); */ - - *roll_ptr = trx_undo_build_roll_ptr( - /* row_purge_record_func() will later set - ROLL_PTR_INSERT_FLAG for TRX_UNDO_INSERT_REC */ - false, - trx_sys.rseg_id(purge_sys.rseg, true), - purge_sys.page_no, purge_sys.offset); - - /* The following call will advance the stored values of the - purge iterator. */ - - return trx_purge_get_next_rec(n_pages_handled, heap); + /* The following will advance the purge iterator. */ + return trx_purge_get_next_rec(n_pages_handled, heap); } /** Run a purge batch. From d70a98ae06562eee75d20dbdd78c7a1c935cfbb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Oct 2023 09:42:38 +0300 Subject: [PATCH 121/158] MDEV-32050: Revert the throttling of MDEV-26356 purge_coordinator_state::do_purge(): Simply use all innodb_purge_threads, no matter what the LSN age is. During shutdown with innodb_fast_shutdown=0 this code could degrade to using only 1 thread. Also, restore periodical "InnoDB: to purge" messages that were accidentally disabled in commit 80585c9d6f13496baf2d4328f9fe1cac5ed6f665. Reviewed by: Vladislav Lesin and Vladislav Vaintroub --- storage/innobase/include/srv0srv.h | 10 -- storage/innobase/srv/srv0srv.cc | 170 +++++------------------------ 2 files changed, 27 insertions(+), 153 deletions(-) diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 86d114e1a42..ce91020464c 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -610,16 +610,6 @@ srv_que_task_enqueue_low( /*=====================*/ que_thr_t* thr); /*!< in: query thread */ -/** -Flag which is set, whenever innodb_purge_threads changes. -It is read and reset in srv_do_purge(). - -Thus it is Atomic_counter, not bool, since unprotected -reads are used. We just need an atomic with relaxed memory -order, to please Thread Sanitizer. -*/ -extern Atomic_counter srv_purge_thread_count_changed; - #ifdef UNIV_DEBUG /** @return whether purge or master task is active */ bool srv_any_background_activity(); diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index d57d2bdd3f2..dffc412c560 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -506,25 +506,8 @@ static srv_sys_t srv_sys; struct purge_coordinator_state { /** Snapshot of the last history length before the purge call.*/ - size_t m_history_length; + size_t history_size; Atomic_counter m_running; -private: - ulint n_use_threads; - ulint n_threads; - - ulint lsn_lwm; - ulint lsn_hwm; - ulonglong start_time; - ulint lsn_age_factor; - - static constexpr ulint adaptive_purge_threshold= 20; - static constexpr ulint safety_net= 20; - ulint series[innodb_purge_threads_MAX + 1]; - - inline void compute_series(); - inline void lazy_init(); - void refresh(bool full); - public: inline void do_purge(); }; @@ -1610,83 +1593,50 @@ static bool srv_task_execute() static void purge_create_background_thds(int ); -std::mutex purge_thread_count_mtx; +/** Flag which is set, whenever innodb_purge_threads changes. */ +static Atomic_relaxed srv_purge_thread_count_changed; + +static std::mutex purge_thread_count_mtx; void srv_update_purge_thread_count(uint n) { std::lock_guard lk(purge_thread_count_mtx); purge_create_background_thds(n); srv_n_purge_threads = n; - srv_purge_thread_count_changed = 1; + srv_purge_thread_count_changed = true; } -Atomic_counter srv_purge_thread_count_changed; - inline void purge_coordinator_state::do_purge() { ut_ad(!srv_read_only_mode); - lazy_init(); - ut_ad(n_threads); - while (purge_sys.enabled() && !purge_sys.paused()) + if (!purge_sys.enabled() || purge_sys.paused()) + return; + + uint n_threads; + { -loop: - const auto now= my_interval_timer(); - - if (now - start_time >= 1000000) - { - refresh(false); - start_time= now; - } - - const auto old_activity_count= srv_sys.activity_count; - const auto history_size= trx_sys.history_size(); + std::lock_guard lk(purge_thread_count_mtx); + n_threads= srv_n_purge_threads; + srv_purge_thread_count_changed= false; + goto first_loop; + } + do + { if (UNIV_UNLIKELY(srv_purge_thread_count_changed)) { /* Read the fresh value of srv_n_purge_threads, reset - the changed flag. Both are protected by purge_thread_count_mtx. - - This code does not run concurrently, it is executed - by a single purge_coordinator thread, and no races - involving srv_purge_thread_count_changed are possible. */ + the changed flag. Both are protected by purge_thread_count_mtx. */ { std::lock_guard lk(purge_thread_count_mtx); - n_threads= n_use_threads= srv_n_purge_threads; - srv_purge_thread_count_changed= 0; + n_threads= srv_n_purge_threads; + srv_purge_thread_count_changed= false; } - refresh(true); - start_time= now; } - else if (history_size > m_history_length) - { - /* dynamically adjust the purge thread based on redo log fill factor */ - if (n_use_threads < n_threads && lsn_age_factor < lsn_lwm) - { -more_threads: - ++n_use_threads; - lsn_hwm= lsn_lwm; - lsn_lwm-= series[n_use_threads]; - } - else if (n_use_threads > 1 && lsn_age_factor >= lsn_hwm) - { -fewer_threads: - --n_use_threads; - lsn_lwm= lsn_hwm; - lsn_hwm+= series[n_use_threads]; - } - else if (n_use_threads == 1 && lsn_age_factor >= 100 - safety_net) - break; - } - else if (n_threads > n_use_threads && - srv_max_purge_lag && m_history_length > srv_max_purge_lag) - goto more_threads; - else if (n_use_threads > 1 && old_activity_count == srv_sys.activity_count) - goto fewer_threads; + first_loop: + ut_ad(n_threads); - ut_ad(n_use_threads); - ut_ad(n_use_threads <= n_threads); - - m_history_length= history_size; + history_size= trx_sys.history_size(); if (!history_size) { @@ -1697,7 +1647,7 @@ fewer_threads: break; } - ulint n_pages_handled= trx_purge(n_use_threads, history_size); + ulint n_pages_handled= trx_purge(n_threads, history_size); if (!trx_sys.history_exists()) goto no_history; if (purge_sys.truncate.current || srv_shutdown_state != SRV_SHUTDOWN_NONE) @@ -1709,79 +1659,13 @@ fewer_threads: srv_thread_pool->submit_task(&purge_truncation_task); if (!n_pages_handled) break; - - if (!srv_purge_should_exit(history_size)) - goto loop; } + while (purge_sys.enabled() && !purge_sys.paused() && + !srv_purge_should_exit(history_size)); m_running= 0; } -inline void purge_coordinator_state::compute_series() -{ - ulint points= n_threads; - memset(series, 0, sizeof series); - constexpr ulint spread= 100 - adaptive_purge_threshold - safety_net; - - /* We distribute spread across n_threads, - e.g.: spread of 60 is distributed across n_threads=4 as: 6+12+18+24 */ - - const ulint additional_points= (points * (points + 1)) / 2; - if (spread % additional_points == 0) - { - /* Arithmetic progression is possible. */ - const ulint delta= spread / additional_points; - ulint growth= delta; - do - { - series[points--]= growth; - growth += delta; - } - while (points); - return; - } - - /* Use average distribution to spread across the points */ - const ulint delta= spread / points; - ulint total= 0; - do - { - series[points--]= delta; - total+= delta; - } - while (points); - - for (points= 1; points <= n_threads && total++ < spread; ) - series[points++]++; -} - -inline void purge_coordinator_state::lazy_init() -{ - if (n_threads) - return; - n_threads= n_use_threads= srv_n_purge_threads; - refresh(true); - start_time= my_interval_timer(); -} - -void purge_coordinator_state::refresh(bool full) -{ - if (full) - { - compute_series(); - lsn_lwm= adaptive_purge_threshold; - lsn_hwm= adaptive_purge_threshold + series[n_threads]; - } - - mysql_mutex_lock(&log_sys.mutex); - const lsn_t last= log_sys.last_checkpoint_lsn, - max_age= log_sys.max_checkpoint_age; - mysql_mutex_unlock(&log_sys.mutex); - - lsn_age_factor= ulint(((log_sys.get_lsn() - last) * 100) / max_age); -} - - static std::list purge_thds; static std::mutex purge_thd_mutex; extern void* thd_attach_thd(THD*); From 39bb5ebb853be0f3695e97e7618227b407d0e904 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Thu, 12 Oct 2023 16:50:37 +0400 Subject: [PATCH 122/158] MDEV-32050: Allow table to be guarded by an MDL of another thread Add a debug-only field MDL_context::lock_warrant. This field can be set to the MDL context different from the one the current execution is done in. The lock warrantor has to hold an MDL for at least a duration of a table lifetime. This is needed in the subsequent commit so that the shared MDL acquired by the InnoDB purge_coordinator_task can be shared by purge_worker_task that access index records that include virtual columns. Reviewed by: Vladislav Vaintroub --- sql/mdl.h | 20 ++++++++++++++++++++ sql/sql_base.cc | 6 +++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/sql/mdl.h b/sql/mdl.h index 998f34ff2bb..cdd942f6772 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -1100,6 +1100,26 @@ private: /* metadata_lock_info plugin */ friend int i_s_metadata_lock_info_fill_row(MDL_ticket*, void*); +#ifndef DBUG_OFF +public: + /** + This is for the case when the thread opening the table does not acquire + the lock itself, but utilizes a lock guarantee from another MDL context. + + For example, in InnoDB, MDL is acquired by the purge_coordinator_task, + but the table may be opened and used in a purge_worker_task. + The coordinator thread holds the lock for the duration of worker's purge + job, or longer, possibly reusing shared MDL for different workers and jobs. + */ + MDL_context *lock_warrant= NULL; + + inline bool is_lock_warrantee(MDL_key::enum_mdl_namespace ns, + const char *db, const char *name, + enum_mdl_type mdl_type) const + { + return lock_warrant && lock_warrant->is_lock_owner(ns, db, name, mdl_type); + } +#endif }; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index fceafcb1a18..43f11000ada 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -978,7 +978,11 @@ void close_thread_table(THD *thd, TABLE **table_ptr) DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->s->db.str, table->s->table_name.str, - MDL_SHARED)); + MDL_SHARED) || + thd->mdl_context.is_lock_warrantee(MDL_key::TABLE, + table->s->db.str, + table->s->table_name.str, + MDL_SHARED)); table->vcol_cleanup_expr(thd); table->mdl_ticket= NULL; From 88733282fb15c80f0bd722df0041d06ad90c26b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Oct 2023 10:08:20 +0300 Subject: [PATCH 123/158] MDEV-32050: Look up tables in the purge coordinator The InnoDB table lookup in purge worker threads is a bottleneck that can degrade a slow shutdown to utilize less than 2 threads. Let us fix that bottleneck by constructing a local lookup table that does not require any synchronization while the undo log records of the current batch are being processed. TRX_PURGE_TABLE_BUCKETS: The initial number of std::unordered_map hash buckets used during a purge batch. This could avoid some resizing and rehashing in trx_purge_attach_undo_recs(). purge_node_t::tables: A lookup table from table ID to an already looked up and locked table. Replaces many fields. trx_purge_attach_undo_recs(): Look up each table in the purge batch only once. trx_purge(): Close all tables and release MDL at the end of the batch. trx_purge_table_open(), trx_purge_table_acquire(): Open a table in purge and acquire a metadata lock on it. This replaces dict_table_open_on_id() and dict_acquire_mdl_shared(). purge_sys_t::close_and_reopen(): In case of an MDL conflict, close and reopen all tables that are covered by the current purge batch. It may be that some of the tables have been dropped meanwhile and can be ignored. This replaces wait_SYS() and wait_FTS(). row_purge_parse_undo_rec(): Make purge_coordinator_task issue a MDL warrant to any purge_worker_task which might need it when innodb_purge_threads>1. purge_node_t::end(): Clear the MDL warrant. Reviewed by: Vladislav Lesin and Vladislav Vaintroub --- .../suite/innodb/r/innodb-index-debug.result | 5 + .../suite/innodb/r/innodb-index-online.result | 1 + .../suite/innodb/r/innodb-table-online.result | 1 + .../innodb/r/row_format_redundant.result | 4 +- .../suite/innodb/t/innodb-index-debug.test | 5 + .../suite/innodb/t/innodb-index-online.test | 2 + .../suite/innodb/t/innodb-table-online.test | 1 + .../suite/innodb/t/row_format_redundant.test | 2 +- .../parts/r/partition_special_innodb.result | 2 + .../parts/t/partition_special_innodb.test | 4 + storage/innobase/dict/dict0dict.cc | 56 +---- storage/innobase/fts/fts0fts.cc | 3 +- storage/innobase/include/dict0dict.h | 3 +- storage/innobase/include/row0purge.h | 187 +++++---------- storage/innobase/include/trx0purge.h | 27 ++- storage/innobase/include/trx0types.h | 5 + storage/innobase/row/row0purge.cc | 90 ++------ storage/innobase/srv/srv0srv.cc | 39 ++-- storage/innobase/trx/trx0purge.cc | 215 +++++++++++++++++- 19 files changed, 344 insertions(+), 308 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-index-debug.result b/mysql-test/suite/innodb/r/innodb-index-debug.result index 8c200109aa4..0995b526821 100644 --- a/mysql-test/suite/innodb/r/innodb-index-debug.result +++ b/mysql-test/suite/innodb/r/innodb-index-debug.result @@ -1,3 +1,7 @@ +SET GLOBAL innodb_max_purge_lag_wait=0; +connect stop_purge,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; CREATE TABLE t1(c1 INT NOT NULL, c2 INT, PRIMARY KEY(c1)) Engine=InnoDB; SHOW CREATE TABLE t1; Table Create Table @@ -143,6 +147,7 @@ ERROR 23000: Duplicate entry '0' for key 'i' SET DEBUG_SYNC='now SIGNAL log2'; connection con1; disconnect con1; +disconnect stop_purge; connection default; SET DEBUG_SYNC='RESET'; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb-index-online.result b/mysql-test/suite/innodb/r/innodb-index-online.result index 7138c5d7a18..e6b69f8f5cc 100644 --- a/mysql-test/suite/innodb/r/innodb-index-online.result +++ b/mysql-test/suite/innodb/r/innodb-index-online.result @@ -437,6 +437,7 @@ COUNT(c22f) CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK +SET GLOBAL innodb_max_purge_lag_wait=0; ALTER TABLE t1 ADD UNIQUE INDEX c3p5(c3(5)); ERROR 23000: Duplicate entry 'NULL' for key 'c3p5' UPDATE t1 SET c3 = NULL WHERE c3 = ''; diff --git a/mysql-test/suite/innodb/r/innodb-table-online.result b/mysql-test/suite/innodb/r/innodb-table-online.result index caefcce47f1..9296fded0fd 100644 --- a/mysql-test/suite/innodb/r/innodb-table-online.result +++ b/mysql-test/suite/innodb/r/innodb-table-online.result @@ -274,6 +274,7 @@ WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SET @rowlog_decrypt_1= (SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_decrypted'); +SET GLOBAL innodb_max_purge_lag_wait=0; SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL rebuilt3 WAIT_FOR dml3_done'; ALTER TABLE t1 ADD PRIMARY KEY(c22f), CHANGE c2 c22f INT; ERROR 42000: Multiple primary key defined diff --git a/mysql-test/suite/innodb/r/row_format_redundant.result b/mysql-test/suite/innodb/r/row_format_redundant.result index b798832e96f..d95c37f18cc 100644 --- a/mysql-test/suite/innodb/r/row_format_redundant.result +++ b/mysql-test/suite/innodb/r/row_format_redundant.result @@ -42,14 +42,14 @@ TRUNCATE TABLE t2; ERROR HY000: Table 't2' is read only TRUNCATE TABLE t3; ERROR HY000: Table 't3' is read only -# restart: --innodb-data-home-dir=MYSQLTEST_VARDIR/tmp/row_format_redundant --innodb-log-group-home-dir=MYSQLTEST_VARDIR/tmp/row_format_redundant --innodb-data-file-path=ibdata1:1M:autoextend --innodb-undo-tablespaces=0 --innodb-stats-persistent=0 +# restart: --innodb-data-home-dir=MYSQLTEST_VARDIR/tmp/row_format_redundant --innodb-log-group-home-dir=MYSQLTEST_VARDIR/tmp/row_format_redundant --innodb-data-file-path=ibdata1:1M:autoextend --innodb-undo-tablespaces=0 --innodb-stats-persistent=0 --skip-innodb-fast-shutdown TRUNCATE TABLE t1; TRUNCATE TABLE t2; TRUNCATE TABLE t3; corrupted SYS_TABLES.MIX_LEN for test/t1 corrupted SYS_TABLES.MIX_LEN for test/t2 corrupted SYS_TABLES.MIX_LEN for test/t3 -# restart: --innodb-data-home-dir=MYSQLTEST_VARDIR/tmp/row_format_redundant --innodb-log-group-home-dir=MYSQLTEST_VARDIR/tmp/row_format_redundant --innodb-data-file-path=ibdata1:1M:autoextend --innodb-undo-tablespaces=0 --innodb-stats-persistent=0 +# restart: --innodb-data-home-dir=MYSQLTEST_VARDIR/tmp/row_format_redundant --innodb-log-group-home-dir=MYSQLTEST_VARDIR/tmp/row_format_redundant --innodb-data-file-path=ibdata1:1M:autoextend --innodb-undo-tablespaces=0 --innodb-stats-persistent=0 --skip-innodb-fast-shutdown TRUNCATE TABLE t1; ERROR 42S02: Table 'test.t1' doesn't exist in engine TRUNCATE TABLE t2; diff --git a/mysql-test/suite/innodb/t/innodb-index-debug.test b/mysql-test/suite/innodb/t/innodb-index-debug.test index f03ef061769..736e129584c 100644 --- a/mysql-test/suite/innodb/t/innodb-index-debug.test +++ b/mysql-test/suite/innodb/t/innodb-index-debug.test @@ -6,6 +6,10 @@ --source include/big_test.inc let $MYSQLD_DATADIR= `select @@datadir`; +SET GLOBAL innodb_max_purge_lag_wait=0; +connect (stop_purge,localhost,root); +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; # # Test for BUG# 12739098, check whether trx->error_status is reset on error. @@ -155,6 +159,7 @@ SET DEBUG_SYNC='now SIGNAL log2'; --connection con1 reap; --disconnect con1 +--disconnect stop_purge --connection default SET DEBUG_SYNC='RESET'; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb-index-online.test b/mysql-test/suite/innodb/t/innodb-index-online.test index ab4f5a965da..f8eb8957911 100644 --- a/mysql-test/suite/innodb/t/innodb-index-online.test +++ b/mysql-test/suite/innodb/t/innodb-index-online.test @@ -369,6 +369,8 @@ SELECT connection con1; SELECT COUNT(c22f) FROM t1; CHECK TABLE t1; +# Avoid a strange DEBUG_SYNC timeout on c3p5_created. +SET GLOBAL innodb_max_purge_lag_wait=0; # Create a column prefix index. --error ER_DUP_ENTRY diff --git a/mysql-test/suite/innodb/t/innodb-table-online.test b/mysql-test/suite/innodb/t/innodb-table-online.test index 90c8dc2095d..551b71c4883 100644 --- a/mysql-test/suite/innodb/t/innodb-table-online.test +++ b/mysql-test/suite/innodb/t/innodb-table-online.test @@ -255,6 +255,7 @@ SET @rowlog_decrypt_1= (SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_decrypted'); +SET GLOBAL innodb_max_purge_lag_wait=0; # Accumulate and apply some modification log. SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL rebuilt3 WAIT_FOR dml3_done'; --error ER_MULTIPLE_PRI_KEY diff --git a/mysql-test/suite/innodb/t/row_format_redundant.test b/mysql-test/suite/innodb/t/row_format_redundant.test index 6de7597e983..fa3a104af13 100644 --- a/mysql-test/suite/innodb/t/row_format_redundant.test +++ b/mysql-test/suite/innodb/t/row_format_redundant.test @@ -78,7 +78,7 @@ TRUNCATE TABLE t2; --error ER_OPEN_AS_READONLY TRUNCATE TABLE t3; ---let $restart_parameters= $d +--let $restart_parameters= $d --skip-innodb-fast-shutdown --source include/restart_mysqld.inc TRUNCATE TABLE t1; diff --git a/mysql-test/suite/parts/r/partition_special_innodb.result b/mysql-test/suite/parts/r/partition_special_innodb.result index 27f8f0a9d5c..1d0c075d661 100644 --- a/mysql-test/suite/parts/r/partition_special_innodb.result +++ b/mysql-test/suite/parts/r/partition_special_innodb.result @@ -269,6 +269,7 @@ Table Op Msg_type Msg_text test.t1 check status OK connection default; UNLOCK TABLES; +SET GLOBAL innodb_max_purge_lag_wait=0; connection con2; DROP TABLE t1; connection default; @@ -348,6 +349,7 @@ SELECT * FROM t1; ERROR HY000: Lock wait timeout exceeded; try restarting transaction connection default; UNLOCK TABLES; +SET GLOBAL innodb_max_purge_lag_wait=0; connection con2; DROP TABLE t1; disconnect con2; diff --git a/mysql-test/suite/parts/t/partition_special_innodb.test b/mysql-test/suite/parts/t/partition_special_innodb.test index 6273cc5cb2a..836b7048ccf 100644 --- a/mysql-test/suite/parts/t/partition_special_innodb.test +++ b/mysql-test/suite/parts/t/partition_special_innodb.test @@ -114,6 +114,8 @@ CHECK TABLE t1; --connection default UNLOCK TABLES; +# Avoid a MDL conflict between purge and the DROP TABLE below +SET GLOBAL innodb_max_purge_lag_wait=0; --connection con2 DROP TABLE t1; @@ -222,6 +224,8 @@ SELECT * FROM t1; --connection default UNLOCK TABLES; +# Avoid a MDL conflict between purge and the DROP TABLE below +SET GLOBAL innodb_max_purge_lag_wait=0; --connection con2 DROP TABLE t1; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index d1c719d2090..0680e60d81c 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -662,7 +662,7 @@ dict_table_t::parse_name<>(char(&)[NAME_LEN + 1], char(&)[NAME_LEN + 1], @param[in] table_op operation to perform when opening @return table object after locking MDL shared @retval nullptr if the table is not readable, or if trylock && MDL blocked */ -template +template dict_table_t* dict_acquire_mdl_shared(dict_table_t *table, THD *thd, @@ -678,7 +678,6 @@ dict_acquire_mdl_shared(dict_table_t *table, if (trylock) { - static_assert(!trylock || !purge_thd, "usage"); dict_sys.freeze(SRW_LOCK_CALL); db_len= dict_get_db_name_len(table->name.m_name); dict_sys.unfreeze(); @@ -749,13 +748,7 @@ retry: } } -retry_table_open: dict_sys.freeze(SRW_LOCK_CALL); - if (purge_thd && purge_sys.must_wait_FTS()) - { - not_found= reinterpret_cast(-1); - goto return_without_mdl; - } table= dict_sys.find_table(table_id); if (table) table->acquire(); @@ -763,11 +756,6 @@ retry_table_open: { dict_sys.unfreeze(); dict_sys.lock(SRW_LOCK_CALL); - if (purge_thd && purge_sys.must_wait_FTS()) - { - dict_sys.unlock(); - goto retry_table_open; - } table= dict_load_table_on_id(table_id, table_op == DICT_TABLE_OP_LOAD_TABLESPACE ? DICT_ERR_IGNORE_RECOVER_LOCK @@ -826,24 +814,21 @@ return_without_mdl: goto retry; } -template dict_table_t* dict_acquire_mdl_shared +template dict_table_t* dict_acquire_mdl_shared (dict_table_t*,THD*,MDL_ticket**,dict_table_op_t); -template dict_table_t* dict_acquire_mdl_shared +template dict_table_t* dict_acquire_mdl_shared (dict_table_t*,THD*,MDL_ticket**,dict_table_op_t); /** Look up a table by numeric identifier. -@tparam purge_thd Whether the function is called by purge thread @param[in] table_id table identifier @param[in] dict_locked data dictionary locked @param[in] table_op operation to perform when opening @param[in,out] thd background thread, or NULL to not acquire MDL @param[out] mdl mdl ticket, or NULL @return table, NULL if does not exist */ -template -dict_table_t* -dict_table_open_on_id(table_id_t table_id, bool dict_locked, - dict_table_op_t table_op, THD *thd, - MDL_ticket **mdl) +dict_table_t *dict_table_open_on_id(table_id_t table_id, bool dict_locked, + dict_table_op_t table_op, THD *thd, + MDL_ticket **mdl) { if (!dict_locked) dict_sys.freeze(SRW_LOCK_CALL); @@ -852,16 +837,9 @@ dict_table_open_on_id(table_id_t table_id, bool dict_locked, if (table) { - if (purge_thd && purge_sys.must_wait_FTS()) - { - table= reinterpret_cast(-1); - goto func_exit; - } - table->acquire(); if (thd && !dict_locked) - table= dict_acquire_mdl_shared( - table, thd, mdl, table_op); + table= dict_acquire_mdl_shared(table, thd, mdl, table_op); } else if (table_op != DICT_TABLE_OP_OPEN_ONLY_IF_CACHED) { @@ -875,44 +853,26 @@ dict_table_open_on_id(table_id_t table_id, bool dict_locked, ? DICT_ERR_IGNORE_RECOVER_LOCK : DICT_ERR_IGNORE_FK_NOKEY); if (table) - { - if (purge_thd && purge_sys.must_wait_FTS()) - { - dict_sys.unlock(); - return reinterpret_cast(-1); - } table->acquire(); - } if (!dict_locked) { dict_sys.unlock(); if (table && thd) { dict_sys.freeze(SRW_LOCK_CALL); - table= dict_acquire_mdl_shared( - table, thd, mdl, table_op); + table= dict_acquire_mdl_shared(table, thd, mdl, table_op); dict_sys.unfreeze(); } return table; } } -func_exit: if (!dict_locked) dict_sys.unfreeze(); return table; } -template dict_table_t* dict_table_open_on_id -(table_id_t table_id, bool dict_locked, - dict_table_op_t table_op, THD *thd, - MDL_ticket **mdl); -template dict_table_t* dict_table_open_on_id -(table_id_t table_id, bool dict_locked, - dict_table_op_t table_op, THD *thd, - MDL_ticket **mdl); - /********************************************************************//** Looks for column n position in the clustered index. @return position in internal representation of the clustered index */ diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index f94aed58d21..769ce416325 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1609,10 +1609,11 @@ and common table associated with the fts table. already stopped*/ void purge_sys_t::stop_FTS(const dict_table_t &table, bool already_stopped) { - dict_sys.lock(SRW_LOCK_CALL); if (!already_stopped) purge_sys.stop_FTS(); + dict_sys.lock(SRW_LOCK_CALL); + fts_table_t fts_table; char table_name[MAX_FULL_NAME_LEN]; diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index e54a138cc02..895743be84b 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -132,7 +132,7 @@ enum dict_table_op_t { @param[in] table_op operation to perform when opening @return table object after locking MDL shared @retval NULL if the table is not readable, or if trylock && MDL blocked */ -template +template dict_table_t* dict_acquire_mdl_shared(dict_table_t *table, THD *thd, @@ -146,7 +146,6 @@ dict_acquire_mdl_shared(dict_table_t *table, @param[in,out] thd background thread, or NULL to not acquire MDL @param[out] mdl mdl ticket, or NULL @return table, NULL if does not exist */ -template dict_table_t* dict_table_open_on_id(table_id_t table_id, bool dict_locked, dict_table_op_t table_op, THD *thd= nullptr, diff --git a/storage/innobase/include/row0purge.h b/storage/innobase/include/row0purge.h index 389a061cba0..99d2f484241 100644 --- a/storage/innobase/include/row0purge.h +++ b/storage/innobase/include/row0purge.h @@ -24,8 +24,7 @@ Purge obsolete records Created 3/14/1997 Heikki Tuuri *******************************************************/ -#ifndef row0purge_h -#define row0purge_h +#pragma once #include "que0types.h" #include "btr0types.h" @@ -35,6 +34,7 @@ Created 3/14/1997 Heikki Tuuri #include "row0mysql.h" #include "mysqld.h" #include +#include class MDL_ticket; /** Determines if it is possible to remove a secondary index entry. @@ -89,155 +89,70 @@ struct trx_purge_rec_t roll_ptr_t roll_ptr; }; -/* Purge node structure */ +/** Purge worker context */ +struct purge_node_t +{ + /** node type: QUE_NODE_PURGE */ + que_common_t common; -struct purge_node_t{ - que_common_t common; /*!< node type: QUE_NODE_PURGE */ - /*----------------------*/ - /* Local storage for this graph node */ - roll_ptr_t roll_ptr;/* roll pointer to undo log record */ + /** DB_TRX_ID of the undo log record */ + trx_id_t trx_id; + /** DB_ROLL_PTR pointing to undo log record */ + roll_ptr_t roll_ptr; - undo_no_t undo_no;/*!< undo number of the record */ + /** undo number of the record */ + undo_no_t undo_no; - byte rec_type;/*!< undo log record type: TRX_UNDO_INSERT_REC, - ... */ - byte cmpl_info;/* compiler analysis info of an update */ -private: - /** latest unavailable table ID (do not bother looking up again) */ - table_id_t unavailable_table_id; - /** the latest modification of the table definition identified by - unavailable_table_id, or TRX_ID_MAX */ - trx_id_t def_trx_id; -public: - dict_table_t* table; /*!< table where purge is done */ - - upd_t* update; /*!< update vector for a clustered index - record */ - const dtuple_t* ref; /*!< NULL, or row reference to the next row to - handle */ - dtuple_t* row; /*!< NULL, or a copy (also fields copied to - heap) of the indexed fields of the row to - handle */ - dict_index_t* index; /*!< NULL, or the next index whose record should - be handled */ - mem_heap_t* heap; /*!< memory heap used as auxiliary storage for - row; this must be emptied after a successful - purge of a row */ - ibool found_clust;/*!< whether the clustered index record - determined by ref was found in the clustered - index, and we were able to position pcur on - it */ - btr_pcur_t pcur; /*!< persistent cursor used in searching the - clustered index record */ + /** record type: TRX_UNDO_INSERT_REC, ... */ + byte rec_type; + /** compiler analysis info of an update */ + byte cmpl_info; + /** whether the clustered index record determined by ref was found + in the clustered index of the table, and we were able to position + pcur on it */ + bool found_clust; #ifdef UNIV_DEBUG - /** whether the operation is in progress */ - bool in_progress; + /** whether the operation is in progress */ + bool in_progress= false; #endif - trx_id_t trx_id; /*!< trx id for this purging record */ + /** table where purge is done */ + dict_table_t *table= nullptr; + /** update vector for a clustered index record */ + upd_t *update; + /** row reference to the next row to handle, or nullptr */ + const dtuple_t *ref; + /** nullptr, or a deep copy of the indexed fields of the row to handle */ + dtuple_t *row; + /** nullptr, or the next index of table whose record should be handled */ + dict_index_t *index; + /** memory heap used as auxiliary storage; must be emptied between rows */ + mem_heap_t *heap; + /** persistent cursor to the clustered index record */ + btr_pcur_t pcur; - /** meta-data lock for the table name */ - MDL_ticket* mdl_ticket; + /** Undo recs to purge */ + std::queue undo_recs; - /** table id of the previous undo log record */ - table_id_t last_table_id; + /** map of table identifiers to table handles and meta-data locks */ + std::unordered_map> tables; - /** purge thread */ - THD* purge_thd; - - /** metadata lock holds for this number of undo log recs */ - int mdl_hold_recs; - - /** Undo recs to purge */ - std::queue undo_recs; - - /** Constructor */ - explicit purge_node_t(que_thr_t* parent) : - common(QUE_NODE_PURGE, parent), - unavailable_table_id(0), - table(NULL), - heap(mem_heap_create(256)), -#ifdef UNIV_DEBUG - in_progress(false), -#endif - mdl_ticket(NULL), - last_table_id(0), - purge_thd(NULL), - mdl_hold_recs(0) - { - } + /** Constructor */ + explicit purge_node_t(que_thr_t *parent) : + common(QUE_NODE_PURGE, parent), heap(mem_heap_create(256)), + tables(TRX_PURGE_TABLE_BUCKETS) {} #ifdef UNIV_DEBUG - /***********************************************************//** - Validate the persisent cursor. The purge node has two references - to the clustered index record - one via the ref member, and the - other via the persistent cursor. These two references must match - each other if the found_clust flag is set. - @return true if the persistent cursor is consistent with - the ref member.*/ - bool validate_pcur(); + /** Validate the persistent cursor. The purge node has two references + to the clustered index record: ref and pcur, which must match + each other if found_clust. + @return whether pcur is consistent with ref */ + bool validate_pcur(); #endif - /** Determine if a table should be skipped in purge. - @param[in] table_id table identifier - @return whether to skip the table lookup and processing */ - bool is_skipped(table_id_t id) const - { - return id == unavailable_table_id && trx_id <= def_trx_id; - } - - /** Remember that a table should be skipped in purge. - @param[in] id table identifier - @param[in] limit last transaction for which to skip */ - void skip(table_id_t id, trx_id_t limit) - { - DBUG_ASSERT(limit >= trx_id); - unavailable_table_id = id; - def_trx_id = limit; - } - /** Start processing an undo log record. */ inline void start(); - - /** Close the existing table and release the MDL for it. */ - void close_table() - { - last_table_id= 0; - if (!table) - { - ut_ad(!mdl_ticket); - return; - } - - innobase_reset_background_thd(purge_thd); - dict_table_close(table, false, purge_thd, mdl_ticket); - table= nullptr; - mdl_ticket= nullptr; - } - - - /** Retail mdl for the table id. - @param[in] table_id table id to be processed - @return true if retain mdl */ - bool retain_mdl(table_id_t table_id) - { - ut_ad(table_id); - if (last_table_id == table_id && mdl_hold_recs < 100) - { - ut_ad(table); - mdl_hold_recs++; - return true; - } - - mdl_hold_recs= 0; - close_table(); - return false; - } - - /** Reset the state at end @return the query graph parent */ - inline que_node_t *end(); + inline que_node_t *end(THD *); }; - -#endif diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 277b5c0a04d..bcac02ccce1 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -135,7 +135,11 @@ private: that are older than view will be removed. */ ReadViewBase view; /** whether purge is enabled; protected by latch and std::atomic */ - std::atomic m_enabled; + std::atomic m_enabled{false}; +public: + /** whether purge is active (may hold table handles) */ + std::atomic m_active{false}; +private: /** number of pending stop() calls without resume() */ Atomic_counter m_paused; /** number of stop_SYS() calls without resume_SYS() */ @@ -252,33 +256,30 @@ public: } /** @return whether the purge tasks are active */ - bool running() const; + static bool running(); + /** Stop purge during FLUSH TABLES FOR EXPORT. */ void stop(); /** Resume purge at UNLOCK TABLES after FLUSH TABLES FOR EXPORT */ void resume(); + /** Close and reopen all tables in case of a MDL conflict with DDL */ + dict_table_t *close_and_reopen(table_id_t id, THD *thd, MDL_ticket **mdl); private: - void wait_SYS(); - void wait_FTS(); + /** Suspend purge during a DDL operation on FULLTEXT INDEX tables */ + void wait_FTS(bool also_sys); public: /** Suspend purge in data dictionary tables */ - void stop_SYS(); + void stop_SYS() { m_SYS_paused++; } /** Resume purge in data dictionary tables */ static void resume_SYS(void *); - /** @return whether stop_SYS() is in effect */ - bool must_wait_SYS() const { return m_SYS_paused; } - /** check stop_SYS() */ - void check_stop_SYS() { if (must_wait_SYS()) wait_SYS(); } /** Pause purge during a DDL operation that could drop FTS_ tables. */ - void stop_FTS() { m_FTS_paused++; } + void stop_FTS(); /** Resume purge after stop_FTS(). */ void resume_FTS() { ut_d(const auto p=) m_FTS_paused--; ut_ad(p); } /** @return whether stop_SYS() is in effect */ bool must_wait_FTS() const { return m_FTS_paused; } - /** check stop_SYS() */ - void check_stop_FTS() { if (must_wait_FTS()) wait_FTS(); } /** Determine if the history of a transaction is purgeable. @param trx_id transaction identifier @@ -313,6 +314,8 @@ public: template void clone_oldest_view() { + if (!also_end_view) + wait_FTS(true); latch.wr_lock(SRW_LOCK_CALL); trx_sys.clone_oldest_view(&view); if (also_end_view) diff --git a/storage/innobase/include/trx0types.h b/storage/innobase/include/trx0types.h index 07c1c6a756b..071ea385cf7 100644 --- a/storage/innobase/include/trx0types.h +++ b/storage/innobase/include/trx0types.h @@ -109,6 +109,11 @@ typedef byte trx_undo_rec_t; typedef std::vector > trx_ids_t; +/** Number of std::unordered_map hash buckets expected to be needed +for table IDs in a purge batch. GNU libstdc++ would default to 1 and +enlarge and rehash on demand. */ +static constexpr size_t TRX_PURGE_TABLE_BUCKETS= 128; + /** The number of rollback segments; rollback segment id must fit in the 7 bits reserved for it in DB_ROLL_PTR. */ static constexpr unsigned TRX_SYS_N_RSEGS= 128; diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 2329877c355..c380c4901b9 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -48,6 +48,7 @@ Created 3/14/1997 Heikki Tuuri #include "ha_innodb.h" #include "fil0fil.h" #include "debug_sync.h" +#include /************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there @@ -114,7 +115,6 @@ row_purge_remove_clust_if_poss_low( if (table_id) { retry: - purge_sys.check_stop_FTS(); dict_sys.lock(SRW_LOCK_CALL); table = dict_sys.find_table(table_id); if (!table) { @@ -189,7 +189,6 @@ close_and_exit: ibuf_delete_for_discarded_space(space_id); } - purge_sys.check_stop_SYS(); mtr.start(); index->set_modified(mtr); @@ -640,25 +639,12 @@ row_purge_del_mark( return result; } -void purge_sys_t::wait_SYS() -{ - while (must_wait_SYS()) - std::this_thread::sleep_for(std::chrono::seconds(1)); -} - -void purge_sys_t::wait_FTS() -{ - while (must_wait_FTS()) - std::this_thread::sleep_for(std::chrono::seconds(1)); -} - /** Reset DB_TRX_ID, DB_ROLL_PTR of a clustered index record whose old history can no longer be observed. @param[in,out] node purge node @param[in,out] mtr mini-transaction (will be started and committed) */ static void row_purge_reset_trx_id(purge_node_t* node, mtr_t* mtr) { -retry: /* Reset DB_TRX_ID, DB_ROLL_PTR for old records. */ mtr->start(); @@ -694,17 +680,6 @@ retry: ut_ad(!rec_get_deleted_flag( rec, rec_offs_comp(offsets)) || rec_is_alter_metadata(rec, *index)); - switch (node->table->id) { - case DICT_TABLES_ID: - case DICT_COLUMNS_ID: - case DICT_INDEXES_ID: - if (purge_sys.must_wait_SYS()) { - mtr->commit(); - purge_sys.check_stop_SYS(); - goto retry; - } - } - DBUG_LOG("purge", "reset DB_TRX_ID=" << ib::hex(row_get_rec_trx_id( rec, index, offsets))); @@ -1045,10 +1020,7 @@ row_purge_parse_undo_rec( case TRX_UNDO_EMPTY: case TRX_UNDO_INSERT_METADATA: case TRX_UNDO_INSERT_REC: - /* These records do not store any transaction identifier. - - FIXME: Update SYS_TABLES.ID on both DISCARD TABLESPACE - and IMPORT TABLESPACE to get rid of the repeated lookups! */ + /* These records do not store any transaction identifier. */ node->trx_id = TRX_ID_MAX; break; default: @@ -1064,58 +1036,30 @@ row_purge_parse_undo_rec( break; } - if (node->is_skipped(table_id)) { + auto &tables_entry= node->tables[table_id]; + node->table = tables_entry.first; + if (!node->table) { return false; } - trx_id_t trx_id = TRX_ID_MAX; - - if (node->retain_mdl(table_id)) { - ut_ad(node->table != NULL); - goto already_locked; +#ifndef DBUG_OFF + if (MDL_ticket* mdl = tables_entry.second) { + static_cast(thd_mdl_context(current_thd)) + ->lock_warrant = mdl->get_ctx(); } - -try_again: - purge_sys.check_stop_FTS(); - - node->table = dict_table_open_on_id( - table_id, false, DICT_TABLE_OP_NORMAL, node->purge_thd, - &node->mdl_ticket); - - if (node->table == reinterpret_cast(-1)) { - /* purge stop signal */ - goto try_again; - } - - if (!node->table) { - /* The table has been dropped: no need to do purge and - release mdl happened as a part of open process itself */ - goto err_exit; - } - -already_locked: +#endif ut_ad(!node->table->is_temporary()); clust_index = dict_table_get_first_index(node->table); - if (!clust_index || clust_index->is_corrupted()) { + if (clust_index->is_corrupted()) { /* The table was corrupt in the data dictionary. dict_set_corrupted() works on an index, and we do not have an index to call it with. */ DBUG_ASSERT(table_id == node->table->id); - trx_id = node->table->def_trx_id; - if (!trx_id) { - trx_id = TRX_ID_MAX; - } - -err_exit: - node->close_table(); - node->skip(table_id, trx_id); return false; } - node->last_table_id = table_id; - switch (type) { case TRX_UNDO_INSERT_METADATA: node->ref = &trx_undo_metadata; @@ -1265,19 +1209,19 @@ inline void purge_node_t::start() found_clust= false; rec_type= 0; cmpl_info= 0; - if (!purge_thd) - purge_thd= current_thd; } /** Reset the state at end @return the query graph parent */ -inline que_node_t *purge_node_t::end() +inline que_node_t *purge_node_t::end(THD *thd) { DBUG_ASSERT(common.type == QUE_NODE_PURGE); - close_table(); ut_ad(undo_recs.empty()); ut_d(in_progress= false); - purge_thd= nullptr; + innobase_reset_background_thd(thd); +#ifndef DBUG_OFF + static_cast(thd_mdl_context(thd))->lock_warrant= nullptr; +#endif mem_heap_empty(heap); return common.parent; } @@ -1305,7 +1249,7 @@ row_purge_step( row_purge(node, purge_rec.undo_rec, thr); } - thr->run_node = node->end(); + thr->run_node = node->end(current_thd); return(thr); } diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index dffc412c560..dfb97bf6134 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1294,43 +1294,35 @@ void purge_sys_t::wake_if_not_active() } /** @return whether the purge tasks are active */ -bool purge_sys_t::running() const +bool purge_sys_t::running() { return purge_coordinator_task.is_running(); } -/** Suspend purge in data dictionary tables */ -void purge_sys_t::stop_SYS() +void purge_sys_t::stop_FTS() { latch.rd_lock(SRW_LOCK_CALL); - ++m_SYS_paused; + m_FTS_paused++; latch.rd_unlock(); + while (m_active) + std::this_thread::sleep_for(std::chrono::seconds(1)); } /** Stop purge during FLUSH TABLES FOR EXPORT */ void purge_sys_t::stop() { - for (;;) + latch.wr_lock(SRW_LOCK_CALL); + + if (!enabled()) { - latch.wr_lock(SRW_LOCK_CALL); - - if (!enabled()) - { - /* Shutdown must have been initiated during FLUSH TABLES FOR EXPORT. */ - ut_ad(!srv_undo_sources); - latch.wr_unlock(); - return; - } - - ut_ad(srv_n_purge_threads > 0); - - if (!must_wait_SYS()) - break; - + /* Shutdown must have been initiated during FLUSH TABLES FOR EXPORT. */ + ut_ad(!srv_undo_sources); latch.wr_unlock(); - std::this_thread::sleep_for(std::chrono::seconds(1)); + return; } + ut_ad(srv_n_purge_threads > 0); + const auto paused= m_paused++; latch.wr_unlock(); @@ -1346,9 +1338,8 @@ void purge_sys_t::stop() /** Resume purge in data dictionary tables */ void purge_sys_t::resume_SYS(void *) { - ut_d(const auto s=) - purge_sys.m_SYS_paused--; - ut_ad(s); + ut_d(auto paused=) purge_sys.m_SYS_paused--; + ut_ad(paused); } /** Resume purge at UNLOCK TABLES after FLUSH TABLES FOR EXPORT */ diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 4011a3dfe7c..a62b0635e49 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -38,10 +38,10 @@ Created 3/26/1996 Heikki Tuuri #include "trx0roll.h" #include "trx0rseg.h" #include "trx0trx.h" +#include "dict0load.h" +#include #include -#include - /** Maximum allowable purge history length. <=0 means 'infinite'. */ ulong srv_max_purge_lag = 0; @@ -169,7 +169,6 @@ void purge_sys_t::create() ut_ad(!heap); ut_ad(!enabled()); m_paused= 0; - m_SYS_paused= 0; query= purge_graph_build(); next_stored= false; rseg= NULL; @@ -1100,11 +1099,177 @@ trx_purge_fetch_next_rec( return trx_purge_get_next_rec(n_pages_handled, heap); } +/** Close all tables that were opened in a purge batch for a worker. +@param node purge task context +@param thd purge coordinator thread handle */ +static void trx_purge_close_tables(purge_node_t *node, THD *thd) +{ + for (auto &t : node->tables) + { + if (!t.second.first); + else if (t.second.first == reinterpret_cast(-1)); + else + { + dict_table_close(t.second.first, false, thd, t.second.second); + t.second.first= reinterpret_cast(-1); + } + } +} + +void purge_sys_t::wait_FTS(bool also_sys) +{ + bool paused; + do + { + latch.wr_lock(SRW_LOCK_CALL); + paused= m_FTS_paused || (also_sys && m_SYS_paused); + latch.wr_unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + while (paused); +} + +__attribute__((nonnull)) +/** Aqcuire a metadata lock on a table. +@param table table handle +@param mdl_context metadata lock acquisition context +@param mdl metadata lcok +@return table handle +@retval nullptr if the table is not found or accessible +@retval -1 if the purge of history must be suspended due to DDL */ +static dict_table_t *trx_purge_table_acquire(dict_table_t *table, + MDL_context *mdl_context, + MDL_ticket **mdl) +{ + ut_ad(dict_sys.frozen_not_locked()); + *mdl= nullptr; + + if (!table->is_readable() || table->corrupted) + { + table->release(); + return nullptr; + } + + size_t db_len= dict_get_db_name_len(table->name.m_name); + if (db_len == 0) + return table; /* InnoDB system tables are not covered by MDL */ + + if (purge_sys.must_wait_FTS()) + { + must_wait: + table->release(); + return reinterpret_cast(-1); + } + + char db_buf[NAME_LEN + 1]; + char tbl_buf[NAME_LEN + 1]; + size_t tbl_len; + + if (!table->parse_name(db_buf, tbl_buf, &db_len, &tbl_len)) + /* The name of an intermediate table starts with #sql */ + return table; + + { + MDL_request request; + MDL_REQUEST_INIT(&request,MDL_key::TABLE, db_buf, tbl_buf, MDL_SHARED, + MDL_EXPLICIT); + if (mdl_context->try_acquire_lock(&request)) + goto must_wait; + *mdl= request.ticket; + if (!*mdl) + goto must_wait; + } + + return table; +} + +/** Open a table handle for the purge of committed transaction history +@param table_id InnoDB table identifier +@param mdl_context metadata lock acquisition context +@param mdl metadata lcok +@return table handle +@retval nullptr if the table is not found or accessible +@retval -1 if the purge of history must be suspended due to DDL */ +static dict_table_t *trx_purge_table_open(table_id_t table_id, + MDL_context *mdl_context, + MDL_ticket **mdl) +{ + dict_sys.freeze(SRW_LOCK_CALL); + + dict_table_t *table= dict_sys.find_table(table_id); + + if (table) + table->acquire(); + else + { + dict_sys.unfreeze(); + dict_sys.lock(SRW_LOCK_CALL); + table= dict_load_table_on_id(table_id, DICT_ERR_IGNORE_FK_NOKEY); + if (table) + table->acquire(); + dict_sys.unlock(); + if (!table) + return nullptr; + dict_sys.freeze(SRW_LOCK_CALL); + } + + table= trx_purge_table_acquire(table, mdl_context, mdl); + dict_sys.unfreeze(); + return table; +} + +ATTRIBUTE_COLD +dict_table_t *purge_sys_t::close_and_reopen(table_id_t id, THD *thd, + MDL_ticket **mdl) +{ + MDL_context *mdl_context= static_cast(thd_mdl_context(thd)); + ut_ad(mdl_context); + retry: + ut_ad(m_active); + + for (que_thr_t *thr= UT_LIST_GET_FIRST(purge_sys.query->thrs); thr; + thr= UT_LIST_GET_NEXT(thrs, thr)) + { + purge_node_t *node= static_cast(thr->child); + trx_purge_close_tables(node, thd); + } + + m_active= false; + wait_FTS(false); + m_active= true; + + dict_table_t *table= trx_purge_table_open(id, mdl_context, mdl); + if (table == reinterpret_cast(-1)) + goto retry; + + for (que_thr_t *thr= UT_LIST_GET_FIRST(purge_sys.query->thrs); thr; + thr= UT_LIST_GET_NEXT(thrs, thr)) + { + purge_node_t *node= static_cast(thr->child); + for (auto &t : node->tables) + { + if (t.second.first) + { + t.second.first= trx_purge_table_open(t.first, mdl_context, + &t.second.second); + if (t.second.first == reinterpret_cast(-1)) + { + if (table) + dict_table_close(table, false, thd, *mdl); + goto retry; + } + } + } + } + + return table; +} + /** Run a purge batch. @param n_purge_threads number of purge threads @return new purge_sys.head and the number of undo log pages handled */ static std::pair -trx_purge_attach_undo_recs(ulint n_purge_threads) +trx_purge_attach_undo_recs(ulint n_purge_threads, THD *thd) { que_thr_t* thr; ulint i; @@ -1146,8 +1311,14 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) i = 0; - std::unordered_map table_id_map; + std::unordered_map + table_id_map(TRX_PURGE_TABLE_BUCKETS); mem_heap_empty(purge_sys.heap); + purge_sys.m_active = true; + + MDL_context* const mdl_context + = static_cast(thd_mdl_context(thd)); + ut_ad(mdl_context); while (UNIV_LIKELY(srv_undo_sources) || !srv_fast_shutdown) { trx_purge_rec_t purge_rec; @@ -1174,9 +1345,17 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) table_id_t table_id = trx_undo_rec_get_table_id( purge_rec.undo_rec); - purge_node_t *& table_node = table_id_map[table_id]; + purge_node_t*& table_node = table_id_map[table_id]; if (!table_node) { + std::pair p; + p.first = trx_purge_table_open(table_id, mdl_context, + &p.second); + if (p.first == reinterpret_cast(-1)) { + p.first = purge_sys.close_and_reopen( + table_id, thd, &p.second); + } + thr = UT_LIST_GET_NEXT(thrs, thr); if (!(++i % n_purge_threads)) { @@ -1186,15 +1365,24 @@ trx_purge_attach_undo_recs(ulint n_purge_threads) table_node = static_cast(thr->child); ut_a(que_node_get_type(table_node) == QUE_NODE_PURGE); + ut_d(auto i=) + table_node->tables.emplace(table_id, p); + ut_ad(i.second); + if (p.first) { + goto enqueue; + } + } else if (table_node->tables[table_id].first) { +enqueue: + table_node->undo_recs.push(purge_rec); } - table_node->undo_recs.push(purge_rec); - if (n_pages_handled >= srv_purge_batch_size) { break; } } + purge_sys.m_active = false; + ut_ad(head <= purge_sys.tail); return std::make_pair(head, n_pages_handled); @@ -1260,8 +1448,10 @@ TRANSACTIONAL_TARGET ulint trx_purge(ulint n_tasks, ulint history_size) } #endif /* UNIV_DEBUG */ + THD* const thd = current_thd; + /* Fetch the UNDO recs that need to be purged. */ - const auto n = trx_purge_attach_undo_recs(n_tasks); + const auto n = trx_purge_attach_undo_recs(n_tasks, thd); { ulint delay = n.second ? srv_max_purge_lag : 0; @@ -1297,6 +1487,13 @@ TRANSACTIONAL_TARGET ulint trx_purge(ulint n_tasks, ulint history_size) trx_purge_wait_for_workers_to_complete(); + for (thr = UT_LIST_GET_FIRST(purge_sys.query->thrs); thr; + thr = UT_LIST_GET_NEXT(thrs, thr)) { + purge_node_t* node = static_cast(thr->child); + trx_purge_close_tables(node, thd); + node->tables.clear(); + } + purge_sys.clone_end_view(n.first); MONITOR_INC_VALUE(MONITOR_PURGE_INVOKED, 1); From aa719b5010c929132b4460b78113fbd07497d9c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Oct 2023 10:19:17 +0300 Subject: [PATCH 124/158] MDEV-32050: Do not copy undo records in purge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, default to innodb_purge_batch_size=1000, replacing the old default value of processing 300 undo log pages in a batch. Axel Schwenke found this value to help reduce purge lag without having a significant impact on workload throughput. In purge, we can simply acquire a shared latch on the undo log page (to avoid a race condition like the one that was fixed in commit b102872ad50cce5959ad95369740766d14e9e48c) and retain a buffer-fix after releasing the latch. The buffer-fix will prevent the undo log page from being evicted from the buffer pool. Concurrent modification is prevented by design. Only the purge_coordinator_task (or its accomplice purge_truncation_task) may free the undo log pages, after any purge_worker_task have completed execution. Hence, we do not have to worry about any overwriting or reuse of the undo log records. trx_undo_rec_copy(): Remove. The only remaining caller would have been trx_undo_get_undo_rec_low(), which is where the logic was merged. purge_sys_t::m_initialized: Replaces heap. purge_sys_t::pages: A cache of buffer-fixed pages that have been looked up from buf_pool.page_hash. purge_sys_t::get_page(): Return a buffer-fixed undo page, using the pages cache. trx_purge_t::batch_cleanup(): Renamed from clone_end_view(). Clear the pages cache and clone the end_view at the end of a batch. purge_sys_t::n_pages_handled(): Return pages.size(). This determines if innodb_purge_batch_size was exceeded. purge_sys_t::rseg_get_next_history_log(): Replaces trx_purge_rseg_get_next_history_log(). purge_sys_t::choose_next_log(): Replaces trx_purge_choose_next_log() and trx_purge_read_undo_rec(). purge_sys_t::get_next_rec(): Replaces trx_purge_get_next_rec() and trx_undo_get_next_rec(). purge_sys_t::fetch_next_rec(): Replaces trx_purge_fetch_next_rec() and some use of trx_undo_get_first_rec(). trx_purge_attach_undo_recs(): Do not allow purge_sys.n_pages_handled() exceed the innodb_purge_batch_size or ¾ of the buffer pool, whichever is smaller. Reviewed by: Vladislav Lesin Tested by: Matthias Leich and Axel Schwenke --- .../r/innodb_purge_batch_size_basic.result | 8 +- .../sys_vars/r/sysvars_innodb,32bit.rdiff | 2 +- .../suite/sys_vars/r/sysvars_innodb.result | 2 +- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/include/row0purge.h | 9 - storage/innobase/include/trx0purge.h | 78 ++- storage/innobase/include/trx0rec.h | 23 - storage/innobase/include/trx0types.h | 9 + storage/innobase/include/trx0undo.h | 31 +- storage/innobase/trx/trx0purge.cc | 464 +++++++++--------- storage/innobase/trx/trx0rec.cc | 23 +- storage/innobase/trx/trx0undo.cc | 25 +- 12 files changed, 327 insertions(+), 349 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/innodb_purge_batch_size_basic.result b/mysql-test/suite/sys_vars/r/innodb_purge_batch_size_basic.result index 6279cd143cf..442d44e7fb2 100644 --- a/mysql-test/suite/sys_vars/r/innodb_purge_batch_size_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_purge_batch_size_basic.result @@ -1,19 +1,19 @@ SET @global_start_value = @@global.innodb_purge_batch_size; SELECT @global_start_value; @global_start_value -300 +1000 '#--------------------FN_DYNVARS_046_01------------------------#' SET @@global.innodb_purge_batch_size = 1; SET @@global.innodb_purge_batch_size = DEFAULT; SELECT @@global.innodb_purge_batch_size; @@global.innodb_purge_batch_size -300 +1000 '#---------------------FN_DYNVARS_046_02-------------------------#' SET innodb_purge_batch_size = 1; ERROR HY000: Variable 'innodb_purge_batch_size' is a GLOBAL variable and should be set with SET GLOBAL SELECT @@innodb_purge_batch_size; @@innodb_purge_batch_size -300 +1000 SELECT local.innodb_purge_batch_size; ERROR 42S02: Unknown table 'local' in field list SET global innodb_purge_batch_size = 1; @@ -112,4 +112,4 @@ SELECT @@global.innodb_purge_batch_size; SET @@global.innodb_purge_batch_size = @global_start_value; SELECT @@global.innodb_purge_batch_size; @@global.innodb_purge_batch_size -300 +1000 diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff index 0442b2873dd..71e745369e3 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff @@ -307,7 +307,7 @@ NUMERIC_MAX_VALUE 65536 @@ -1345,7 +1345,7 @@ SESSION_VALUE NULL - DEFAULT_VALUE 300 + DEFAULT_VALUE 1000 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 5b728cee272..8cc23f696b1 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -1293,7 +1293,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_PURGE_BATCH_SIZE SESSION_VALUE NULL -DEFAULT_VALUE 300 +DEFAULT_VALUE 1000 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Number of UNDO log pages to purge in one batch from the history list. diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 0ebafa4c6dd..a672b38098e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -18852,7 +18852,7 @@ static MYSQL_SYSVAR_ULONG(purge_batch_size, srv_purge_batch_size, PLUGIN_VAR_OPCMDARG, "Number of UNDO log pages to purge in one batch from the history list.", NULL, NULL, - 300, /* Default setting */ + 1000, /* Default setting */ 1, /* Minimum value */ 5000, 0); /* Maximum value */ diff --git a/storage/innobase/include/row0purge.h b/storage/innobase/include/row0purge.h index 99d2f484241..1daf4d4abe7 100644 --- a/storage/innobase/include/row0purge.h +++ b/storage/innobase/include/row0purge.h @@ -80,15 +80,6 @@ row_purge_step( que_thr_t* thr) /*!< in: query thread */ MY_ATTRIBUTE((nonnull, warn_unused_result)); -/** Info required to purge a record */ -struct trx_purge_rec_t -{ - /** Record to purge */ - const trx_undo_rec_t *undo_rec; - /** File pointer to undo record */ - roll_ptr_t roll_ptr; -}; - /** Purge worker context */ struct purge_node_t { diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index bcac02ccce1..3ddd2e98fee 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -31,6 +31,7 @@ Created 3/26/1996 Heikki Tuuri #include "srw_lock.h" #include +#include /** Prepend the history list with an undo log. Remove the undo log segment from the rseg slot if it is too big for reuse. @@ -127,6 +128,7 @@ private: /** The control structure used in the purge operation */ class purge_sys_t { + friend TrxUndoRsegsIterator; public: /** latch protecting view, m_enabled */ alignas(CPU_LEVEL1_DCACHE_LINESIZE) mutable srw_spin_lock latch; @@ -134,6 +136,8 @@ private: /** Read view at the start of a purge batch. Any encountered index records that are older than view will be removed. */ ReadViewBase view; + /** whether the subsystem has been initialized */ + bool m_initialized{false}; /** whether purge is enabled; protected by latch and std::atomic */ std::atomic m_enabled{false}; public: @@ -152,7 +156,34 @@ private: /** Read view at the end of a purge batch (copied from view). Any undo pages containing records older than end_view may be freed. */ ReadViewBase end_view; + + struct hasher + { + size_t operator()(const page_id_t &id) const { return size_t(id.raw()); } + }; + + using unordered_map = + std::unordered_map= 8 + std::equal_to + /* GCC 4.8.5 would fail to find a matching allocator */ +#else + std::equal_to, + ut_allocator> +#endif + >; + /** map of buffer-fixed undo log pages processed during a purge batch */ + unordered_map pages; public: + /** @return the number of processed undo pages */ + size_t n_pages_handled() const { return pages.size(); } + + /** Look up an undo log page. + @param id undo page identifier + @return undo page + @retval nullptr in case the page is corrupted */ + buf_block_t *get_page(page_id_t id); + que_t* query; /*!< The query graph which will do the parallelized purge operation */ @@ -188,6 +219,7 @@ public: to purge */ trx_rseg_t* rseg; /*!< Rollback segment for the next undo record to purge */ +private: uint32_t page_no; /*!< Page number for the next undo record to purge, page number of the log header, if dummy record */ @@ -202,7 +234,7 @@ public: TrxUndoRsegsIterator rseg_iter; /*!< Iterator to get the next rseg to process */ - +public: purge_pq_t purge_queue; /*!< Binary min-heap, ordered on TrxUndoRsegs::trx_no. It is protected by the pq_mutex */ @@ -217,17 +249,6 @@ public: fil_space_t* last; } truncate; - /** Heap for reading the undo log records */ - mem_heap_t* heap; - /** - Constructor. - - Some members may require late initialisation, thus we just mark object as - uninitialised. Real initialisation happens in create(). - */ - - purge_sys_t(): m_enabled(false), heap(nullptr) {} - /** Create the instance */ void create(); @@ -281,6 +302,32 @@ public: /** @return whether stop_SYS() is in effect */ bool must_wait_FTS() const { return m_FTS_paused; } +private: + /** + Get the next record to purge and update the info in the purge system. + @param roll_ptr undo log pointer to the record + @return buffer-fixed reference to undo log record + @retval {nullptr,1} if the whole undo log can skipped in purge + @retval {nullptr,0} if nothing is left, or on corruption */ + inline trx_purge_rec_t get_next_rec(roll_ptr_t roll_ptr); + + /** Choose the next undo log to purge. + @return whether anything is to be purged */ + bool choose_next_log(); + + /** Update the last not yet purged history log info in rseg when + we have purged a whole undo log. Advances also purge_trx_no + past the purged log. */ + void rseg_get_next_history_log(); + +public: + /** + Fetch the next undo log record from the history list to purge. + @return buffer-fixed reference to undo log record + @retval {nullptr,1} if the whole undo log can skipped in purge + @retval {nullptr,0} if nothing is left, or on corruption */ + inline trx_purge_rec_t fetch_next_rec(); + /** Determine if the history of a transaction is purgeable. @param trx_id transaction identifier @return whether the history is purgeable */ @@ -327,9 +374,10 @@ public: /** Wake up the purge threads if there is work to do. */ void wake_if_not_active(); - /** Update end_view at the end of a purge batch. - @param head the new head of the purge queue */ - inline void clone_end_view(const iterator &head); + /** Release undo pages and update end_view at the end of a purge batch. + @retval false when nothing is to be purged + @retval true when purge_sys.rseg->latch was locked */ + inline void batch_cleanup(const iterator &head); struct view_guard { diff --git a/storage/innobase/include/trx0rec.h b/storage/innobase/include/trx0rec.h index 3251316186d..8d70b61517a 100644 --- a/storage/innobase/include/trx0rec.h +++ b/storage/innobase/include/trx0rec.h @@ -28,32 +28,9 @@ Created 3/26/1996 Heikki Tuuri #include "trx0types.h" #include "row0types.h" -#include "mtr0mtr.h" -#include "rem0types.h" #include "page0types.h" -#include "row0log.h" #include "que0types.h" -/***********************************************************************//** -Copies the undo record to the heap. -@param undo_rec record in an undo log page -@param heap memory heap -@return copy of undo_rec -@retval nullptr if the undo log record is corrupted */ -inline trx_undo_rec_t* trx_undo_rec_copy(const trx_undo_rec_t *undo_rec, - mem_heap_t *heap) -{ - const size_t offset= ut_align_offset(undo_rec, srv_page_size); - const size_t end= mach_read_from_2(undo_rec); - if (end <= offset || end >= srv_page_size - FIL_PAGE_DATA_END) - return nullptr; - const size_t len= end - offset; - trx_undo_rec_t *rec= static_cast - (mem_heap_dup(heap, undo_rec, len)); - mach_write_to_2(rec, len); - return rec; -} - /**********************************************************************//** Reads the undo log record number. @return undo no */ diff --git a/storage/innobase/include/trx0types.h b/storage/innobase/include/trx0types.h index 071ea385cf7..69d5329216e 100644 --- a/storage/innobase/include/trx0types.h +++ b/storage/innobase/include/trx0types.h @@ -107,6 +107,15 @@ typedef byte trx_undo_rec_t; /* @} */ +/** Info required to purge a record */ +struct trx_purge_rec_t +{ + /** Undo log record, or nullptr (roll_ptr!=0 if the log can be skipped) */ + const trx_undo_rec_t *undo_rec; + /** File pointer to undo_rec */ + roll_ptr_t roll_ptr; +}; + typedef std::vector > trx_ids_t; /** Number of std::unordered_map hash buckets expected to be needed diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h index adddfeac99a..3d22a33e780 100644 --- a/storage/innobase/include/trx0undo.h +++ b/storage/innobase/include/trx0undo.h @@ -116,31 +116,16 @@ trx_undo_page_get_next_rec(const buf_block_t *undo_page, uint16_t rec, trx_undo_rec_t* trx_undo_get_prev_rec(buf_block_t *&block, uint16_t rec, uint32_t page_no, uint16_t offset, bool shared, mtr_t *mtr); -/** Get the next record in an undo log. -@param[in,out] block undo log page -@param[in] rec undo record offset in the page -@param[in] page_no undo log header page number -@param[in] offset undo log header offset on page -@param[in,out] mtr mini-transaction -@return undo log record, the page latched, NULL if none */ -trx_undo_rec_t* -trx_undo_get_next_rec(const buf_block_t *&block, uint16_t rec, - uint32_t page_no, uint16_t offset, mtr_t *mtr); -/** Get the first record in an undo log. -@param[in] space undo log header space -@param[in] page_no undo log header page number -@param[in] offset undo log header offset on page -@param[in] mode latching mode: RW_S_LATCH or RW_X_LATCH -@param[out] block undo log page -@param[in,out] mtr mini-transaction -@param[out] err error code -@return undo log record, the page latched -@retval nullptr if none */ +/** Get the first undo log record on a page. +@param[in] block undo log page +@param[in] page_no undo log header page number +@param[in] offset undo log header page offset +@return pointer to first record +@retval nullptr if none exists */ trx_undo_rec_t* -trx_undo_get_first_rec(const fil_space_t &space, uint32_t page_no, - uint16_t offset, ulint mode, const buf_block_t*& block, - mtr_t *mtr, dberr_t *err); +trx_undo_page_get_first_rec(const buf_block_t *block, uint32_t page_no, + uint16_t offset); /** Initialize an undo log page. NOTE: This corresponds to a redo log record and must not be changed! diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index a62b0635e49..592b8a5371c 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -166,7 +166,7 @@ purge_graph_build() void purge_sys_t::create() { ut_ad(this == &purge_sys); - ut_ad(!heap); + ut_ad(!m_initialized); ut_ad(!enabled()); m_paused= 0; query= purge_graph_build(); @@ -181,18 +181,18 @@ void purge_sys_t::create() mysql_mutex_init(purge_sys_pq_mutex_key, &pq_mutex, nullptr); truncate.current= NULL; truncate.last= NULL; - heap= mem_heap_create(4096); + m_initialized= true; } /** Close the purge subsystem on shutdown. */ void purge_sys_t::close() { ut_ad(this == &purge_sys); - if (!heap) + if (!m_initialized) return; ut_ad(!enabled()); - trx_t* trx = query->trx; + trx_t *trx= query->trx; que_graph_free(query); ut_ad(!trx->id); ut_ad(trx->state == TRX_STATE_ACTIVE); @@ -201,8 +201,7 @@ void purge_sys_t::close() latch.destroy(); end_latch.destroy(); mysql_mutex_destroy(&pq_mutex); - mem_heap_free(heap); - heap= nullptr; + m_initialized= false; } /** Determine if the history of a transaction is purgeable. @@ -825,35 +824,45 @@ not_free: } } -/***********************************************************************//** -Updates the last not yet purged history log info in rseg when we have purged -a whole undo log. Advances also purge_sys.purge_trx_no past the purged log. +buf_block_t *purge_sys_t::get_page(page_id_t id) +{ + buf_block_t*& undo_page= pages[id]; -@param n_pages_handled number of UNDO pages handled */ -static void trx_purge_rseg_get_next_history_log(ulint *n_pages_handled) + if (undo_page) + return undo_page; + + mtr_t mtr; + mtr.start(); + undo_page= + buf_page_get_gen(id, 0, RW_S_LATCH, nullptr, BUF_GET_POSSIBLY_FREED, &mtr); + + if (UNIV_LIKELY(undo_page != nullptr)) + { + undo_page->fix(); + mtr.commit(); + return undo_page; + } + + mtr.commit(); + pages.erase(id); + return nullptr; +} + +void purge_sys_t::rseg_get_next_history_log() { fil_addr_t prev_log_addr; - mtr_t mtr; - mtr.start(); + ut_ad(rseg->latch.is_write_locked()); + ut_a(rseg->last_page_no != FIL_NULL); - ut_ad(purge_sys.rseg->latch.is_write_locked()); - ut_a(purge_sys.rseg->last_page_no != FIL_NULL); + tail.trx_no= rseg->last_trx_no() + 1; + tail.undo_no= 0; + next_stored= false; - purge_sys.tail.trx_no= purge_sys.rseg->last_trx_no() + 1; - purge_sys.tail.undo_no= 0; - purge_sys.next_stored= false; - - if (const buf_block_t* undo_page= - buf_page_get_gen(page_id_t(purge_sys.rseg->space->id, - purge_sys.rseg->last_page_no), - 0, RW_S_LATCH, nullptr, - BUF_GET_POSSIBLY_FREED, &mtr)) + if (buf_block_t *undo_page= + get_page(page_id_t(rseg->space->id, rseg->last_page_no))) { - const trx_ulogf_t *log_hdr= - undo_page->page.frame + purge_sys.rseg->last_offset(); - /* Increase the purge page count by one for every handled log */ - ++*n_pages_handled; + const byte *log_hdr= undo_page->page.frame + rseg->last_offset(); prev_log_addr= flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE); prev_log_addr.boffset = static_cast(prev_log_addr.boffset - TRX_UNDO_HISTORY_NODE); @@ -861,242 +870,204 @@ static void trx_purge_rseg_get_next_history_log(ulint *n_pages_handled) else prev_log_addr.page= FIL_NULL; - mtr.commit(); - if (prev_log_addr.page == FIL_NULL) - purge_sys.rseg->last_page_no= FIL_NULL; + rseg->last_page_no= FIL_NULL; else { /* Read the previous log header. */ - mtr.start(); - trx_id_t trx_no= 0; if (const buf_block_t* undo_page= - buf_page_get_gen(page_id_t(purge_sys.rseg->space->id, - prev_log_addr.page), - 0, RW_S_LATCH, nullptr, BUF_GET_POSSIBLY_FREED, &mtr)) + get_page(page_id_t(rseg->space->id, + prev_log_addr.page))) { const byte *log_hdr= undo_page->page.frame + prev_log_addr.boffset; trx_no= mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO); ut_ad(mach_read_from_2(log_hdr + TRX_UNDO_NEEDS_PURGE) <= 1); } - mtr.commit(); - if (UNIV_LIKELY(trx_no != 0)) { - purge_sys.rseg->last_page_no= prev_log_addr.page; - purge_sys.rseg->set_last_commit(prev_log_addr.boffset, trx_no); + rseg->last_page_no= prev_log_addr.page; + rseg->set_last_commit(prev_log_addr.boffset, trx_no); /* Purge can also produce events, however these are already ordered in the rollback segment and any user generated event will be greater than the events that Purge produces. ie. Purge can never produce events from an empty rollback segment. */ - mysql_mutex_lock(&purge_sys.pq_mutex); - purge_sys.purge_queue.push(*purge_sys.rseg); - mysql_mutex_unlock(&purge_sys.pq_mutex); + mysql_mutex_lock(&pq_mutex); + purge_queue.push(*rseg); + mysql_mutex_unlock(&pq_mutex); } } - purge_sys.rseg->latch.wr_unlock(); + rseg->latch.wr_unlock(); } -/** Position the purge sys "iterator" on the undo record to use for purging. */ -static void trx_purge_read_undo_rec() -{ - uint16_t offset; - uint32_t page_no; - ib_uint64_t undo_no; - - purge_sys.hdr_offset = purge_sys.rseg->last_offset(); - page_no = purge_sys.hdr_page_no = purge_sys.rseg->last_page_no; - - if (purge_sys.rseg->needs_purge) { - mtr_t mtr; - mtr.start(); - const buf_block_t* undo_page; - if (trx_undo_rec_t* undo_rec = trx_undo_get_first_rec( - *purge_sys.rseg->space, purge_sys.hdr_page_no, - purge_sys.hdr_offset, RW_S_LATCH, - undo_page, &mtr, nullptr)) { - - offset = page_offset(undo_rec); - undo_no = trx_undo_rec_get_undo_no(undo_rec); - page_no = undo_page->page.id().page_no(); - } else { - offset = 0; - undo_no = 0; - } - - mtr.commit(); - } else { - offset = 0; - undo_no = 0; - } - - purge_sys.offset = offset; - purge_sys.page_no = page_no; - purge_sys.tail.undo_no = undo_no; - - purge_sys.next_stored = true; -} - -/***********************************************************************//** -Chooses the next undo log to purge and updates the info in purge_sys. This -function is used to initialize purge_sys when the next record to purge is -not known, and also to update the purge system info on the next record when -purge has handled the whole undo log for a transaction. +/** Position the purge sys "iterator" on the undo record to use for purging. @retval false when nothing is to be purged @retval true when purge_sys.rseg->latch was locked */ -static bool trx_purge_choose_next_log() +bool purge_sys_t::choose_next_log() { - if (purge_sys.rseg_iter.set_next()) { - trx_purge_read_undo_rec(); - return true; - } else { - return false; - } -} + if (!rseg_iter.set_next()) + return false; -/***********************************************************************//** -Gets the next record to purge and updates the info in the purge system. -@return copy of an undo log record -@retval -1 if there is nothing to purge -@retval nullptr on corruption */ -static -trx_undo_rec_t* -trx_purge_get_next_rec( -/*===================*/ - ulint* n_pages_handled,/*!< in/out: number of UNDO pages - handled */ - mem_heap_t* heap) /*!< in: memory heap where copied */ -{ - mtr_t mtr; + hdr_offset= rseg->last_offset(); + hdr_page_no= rseg->last_page_no; - ut_ad(purge_sys.next_stored); - ut_ad(purge_sys.tail.trx_no < purge_sys.low_limit_no()); - ut_ad(purge_sys.rseg->latch.is_write_locked()); - - const page_id_t page_id{purge_sys.rseg->space->id, purge_sys.page_no}; - const uint16_t offset = purge_sys.offset; - bool locked = true; - - if (offset == 0) { - /* It is the dummy undo log record, which means that there is - no need to purge this undo log */ - - trx_purge_rseg_get_next_history_log(n_pages_handled); - - /* Look for the next undo log and record to purge */ - - if (trx_purge_choose_next_log()) { - purge_sys.rseg->latch.wr_unlock(); - } - return reinterpret_cast(-1); - } - - mtr.start(); - trx_undo_rec_t *rec_copy = nullptr; - const buf_block_t* undo_page - = buf_page_get_gen(page_id, 0, RW_S_LATCH, nullptr, - BUF_GET_POSSIBLY_FREED, &mtr); - if (UNIV_UNLIKELY(!undo_page)) { -func_exit: - if (locked) { - purge_sys.rseg->latch.wr_unlock(); - } - mtr.commit(); - return rec_copy; - } - - const buf_block_t* rec2_page = undo_page; - - const trx_undo_rec_t* rec2 = trx_undo_page_get_next_rec( - undo_page, offset, purge_sys.hdr_page_no, purge_sys.hdr_offset); - - if (rec2 == NULL) { - rec2 = trx_undo_get_next_rec(rec2_page, offset, - purge_sys.hdr_page_no, - purge_sys.hdr_offset, &mtr); - } - - if (rec2 == NULL) { - mtr_commit(&mtr); - - trx_purge_rseg_get_next_history_log(n_pages_handled); - - /* Look for the next undo log and record to purge */ - - locked = trx_purge_choose_next_log(); - - mtr_start(&mtr); - - undo_page = buf_page_get_gen(page_id, 0, RW_S_LATCH, - nullptr, BUF_GET_POSSIBLY_FREED, - &mtr); - if (UNIV_UNLIKELY(!undo_page)) { - goto func_exit; - } - } else { - purge_sys.offset = page_offset(rec2); - purge_sys.page_no = rec2_page->page.id().page_no(); - purge_sys.tail.undo_no = trx_undo_rec_get_undo_no(rec2); - - if (undo_page != rec2_page) { - /* We advance to a new page of the undo log: */ - (*n_pages_handled)++; - } - } - - rec_copy = trx_undo_rec_copy(undo_page->page.frame + offset, heap); - goto func_exit; -} - -/********************************************************************//** -Fetches the next undo log record from the history list to purge. It must be -released with the corresponding release function. -@return copy of an undo log record -@retval -1 if the whole undo log can skipped in purge -@retval nullptr if nothing is left, or on corruption */ -static MY_ATTRIBUTE((warn_unused_result)) -trx_undo_rec_t* -trx_purge_fetch_next_rec( -/*=====================*/ - roll_ptr_t* roll_ptr, /*!< out: roll pointer to undo record */ - ulint* n_pages_handled,/*!< in/out: number of UNDO log pages - handled */ - mem_heap_t* heap) /*!< in: memory heap where copied */ -{ - if (!purge_sys.next_stored) + if (!rseg->needs_purge) { - bool locked= trx_purge_choose_next_log(); - ut_ad(locked == purge_sys.next_stored); - if (!locked) - return nullptr; - if (purge_sys.tail.trx_no >= purge_sys.low_limit_no()) + purge_nothing: + page_no= hdr_page_no; + offset= 0; + tail.undo_no= 0; + } + else + { + page_id_t id{rseg->space->id, hdr_page_no}; + buf_block_t *b= get_page(id); + if (!b) + goto purge_nothing; + const trx_undo_rec_t *undo_rec= + trx_undo_page_get_first_rec(b, hdr_page_no, hdr_offset); + if (!undo_rec) { - purge_sys.rseg->latch.wr_unlock(); - return nullptr; + if (mach_read_from_2(b->page.frame + hdr_offset + TRX_UNDO_NEXT_LOG)) + goto purge_nothing; + const uint32_t next= + mach_read_from_4(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE + + FLST_NEXT + FIL_ADDR_PAGE + b->page.frame); + if (next == FIL_NULL) + goto purge_nothing; + id.set_page_no(next); + b= get_page(id); + if (!b) + goto purge_nothing; + undo_rec= + trx_undo_page_get_first_rec(b, page_no, hdr_offset); + if (!undo_rec) + goto purge_nothing; + } + + offset= page_offset(undo_rec); + tail.undo_no= trx_undo_rec_get_undo_no(undo_rec); + page_no= id.page_no(); + } + + next_stored= true; + return true; +} + +/** +Get the next record to purge and update the info in the purge system. +@param roll_ptr undo log pointer to the record +@return buffer-fixed reference to undo log record +@retval {nullptr,1} if the whole undo log can skipped in purge +@retval {nullptr,0} if nothing is left, or on corruption */ +inline trx_purge_rec_t purge_sys_t::get_next_rec(roll_ptr_t roll_ptr) +{ + ut_ad(next_stored); + ut_ad(tail.trx_no < low_limit_no()); + ut_ad(rseg->latch.is_write_locked()); + + if (!offset) + { + /* It is the dummy undo log record, which means that there is no + need to purge this undo log */ + rseg_get_next_history_log(); + + /* Look for the next undo log and record to purge */ + if (choose_next_log()) + rseg->latch.wr_unlock(); + return {nullptr, 1}; + } + + ut_ad(offset == uint16_t(roll_ptr)); + + page_id_t page_id{rseg->space->id, page_no}; + bool locked= true; + buf_block_t *b= get_page(page_id); + if (UNIV_UNLIKELY(!b)) + { + if (locked) + rseg->latch.wr_unlock(); + return {nullptr, 0}; + } + + if (const trx_undo_rec_t *rec2= + trx_undo_page_get_next_rec(b, offset, hdr_page_no, hdr_offset)) + { + got_rec: + ut_ad(page_no == page_id.page_no()); + offset= page_offset(rec2); + tail.undo_no= trx_undo_rec_get_undo_no(rec2); + } + else if (hdr_page_no != page_no || + !mach_read_from_2(b->page.frame + hdr_offset + TRX_UNDO_NEXT_LOG)) + { + uint32_t next= mach_read_from_4(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE + + FLST_NEXT + FIL_ADDR_PAGE + b->page.frame); + if (next != FIL_NULL) + { + page_id.set_page_no(next); + if (buf_block_t *next_page= get_page(page_id)) + { + rec2= trx_undo_page_get_first_rec(next_page, hdr_page_no, hdr_offset); + if (rec2) + { + page_no= next; + goto got_rec; + } + } + } + goto got_no_rec; + } + else + { + got_no_rec: + rseg_get_next_history_log(); + /* Look for the next undo log and record to purge */ + locked= choose_next_log(); + } + + if (locked) + rseg->latch.wr_unlock(); + + return {b->page.frame + uint16_t(roll_ptr), roll_ptr}; +} + +inline trx_purge_rec_t purge_sys_t::fetch_next_rec() +{ + roll_ptr_t roll_ptr; + + if (!next_stored) + { + bool locked= choose_next_log(); + ut_ad(locked == next_stored); + if (!locked) + goto got_nothing; + if (tail.trx_no >= low_limit_no()) + { + rseg->latch.wr_unlock(); + goto got_nothing; } /* row_purge_record_func() will later set ROLL_PTR_INSERT_FLAG for TRX_UNDO_INSERT_REC */ - *roll_ptr= trx_undo_build_roll_ptr(false, - trx_sys.rseg_id(purge_sys.rseg, true), - purge_sys.page_no, purge_sys.offset); + roll_ptr= trx_undo_build_roll_ptr(false, trx_sys.rseg_id(rseg, true), + page_no, offset); } - else if (purge_sys.tail.trx_no >= purge_sys.low_limit_no()) - return nullptr; + else if (tail.trx_no >= low_limit_no()) + got_nothing: + return {nullptr, 0}; else { - *roll_ptr= trx_undo_build_roll_ptr(false, - trx_sys.rseg_id(purge_sys.rseg, true), - purge_sys.page_no, purge_sys.offset); - purge_sys.rseg->latch.wr_lock(SRW_LOCK_CALL); + roll_ptr= trx_undo_build_roll_ptr(false, trx_sys.rseg_id(rseg, true), + page_no, offset); + rseg->latch.wr_lock(SRW_LOCK_CALL); } /* The following will advance the purge iterator. */ - return trx_purge_get_next_rec(n_pages_handled, heap); + return get_next_rec(roll_ptr); } /** Close all tables that were opened in a purge batch for a worker. @@ -1267,13 +1238,12 @@ dict_table_t *purge_sys_t::close_and_reopen(table_id_t id, THD *thd, /** Run a purge batch. @param n_purge_threads number of purge threads -@return new purge_sys.head and the number of undo log pages handled */ -static std::pair +@return new purge_sys.head */ +static purge_sys_t::iterator trx_purge_attach_undo_recs(ulint n_purge_threads, THD *thd) { que_thr_t* thr; ulint i; - ulint n_pages_handled = 0; ut_a(n_purge_threads > 0); ut_a(UT_LIST_GET_LEN(purge_sys.query->thrs) >= n_purge_threads); @@ -1313,16 +1283,16 @@ trx_purge_attach_undo_recs(ulint n_purge_threads, THD *thd) std::unordered_map table_id_map(TRX_PURGE_TABLE_BUCKETS); - mem_heap_empty(purge_sys.heap); purge_sys.m_active = true; MDL_context* const mdl_context = static_cast(thd_mdl_context(thd)); ut_ad(mdl_context); - while (UNIV_LIKELY(srv_undo_sources) || !srv_fast_shutdown) { - trx_purge_rec_t purge_rec; + const size_t max_pages = std::min(buf_pool.curr_size * 3 / 4, + size_t{srv_purge_batch_size}); + while (UNIV_LIKELY(srv_undo_sources) || !srv_fast_shutdown) { /* Track the max {trx_id, undo_no} for truncating the UNDO logs once we have purged the records. */ @@ -1331,14 +1301,13 @@ trx_purge_attach_undo_recs(ulint n_purge_threads, THD *thd) } /* Fetch the next record, and advance the purge_sys.tail. */ - purge_rec.undo_rec = trx_purge_fetch_next_rec( - &purge_rec.roll_ptr, &n_pages_handled, - purge_sys.heap); + trx_purge_rec_t purge_rec = purge_sys.fetch_next_rec(); if (!purge_rec.undo_rec) { - break; - } else if (purge_rec.undo_rec - == reinterpret_cast(-1)) { + if (!purge_rec.roll_ptr) { + break; + } + ut_ad(purge_rec.roll_ptr == 1); continue; } @@ -1376,7 +1345,7 @@ enqueue: table_node->undo_recs.push(purge_rec); } - if (n_pages_handled >= srv_purge_batch_size) { + if (purge_sys.n_pages_handled() >= max_pages) { break; } } @@ -1385,7 +1354,7 @@ enqueue: ut_ad(head <= purge_sys.tail); - return std::make_pair(head, n_pages_handled); + return head; } extern tpool::waitable_task purge_worker_task; @@ -1408,10 +1377,15 @@ static void trx_purge_wait_for_workers_to_complete() ut_ad(srv_get_task_queue_length() == 0); } -/** Update end_view at the end of a purge batch. */ TRANSACTIONAL_INLINE -void purge_sys_t::clone_end_view(const purge_sys_t::iterator &head) +void purge_sys_t::batch_cleanup(const purge_sys_t::iterator &head) { + /* Release the undo pages. */ + for (auto p : pages) + p.second->unfix(); + pages.clear(); + pages.reserve(srv_purge_batch_size); + /* This is only invoked only by the purge coordinator, which is the only thread that can modify our inputs head, tail, view. Therefore, we only need to protect end_view from concurrent reads. */ @@ -1451,10 +1425,12 @@ TRANSACTIONAL_TARGET ulint trx_purge(ulint n_tasks, ulint history_size) THD* const thd = current_thd; /* Fetch the UNDO recs that need to be purged. */ - const auto n = trx_purge_attach_undo_recs(n_tasks, thd); + const purge_sys_t::iterator head + = trx_purge_attach_undo_recs(n_tasks, thd); + const size_t n_pages = purge_sys.n_pages_handled(); { - ulint delay = n.second ? srv_max_purge_lag : 0; + ulint delay = n_pages ? srv_max_purge_lag : 0; if (UNIV_UNLIKELY(delay)) { if (delay >= history_size) { no_throttle: @@ -1494,10 +1470,10 @@ TRANSACTIONAL_TARGET ulint trx_purge(ulint n_tasks, ulint history_size) node->tables.clear(); } - purge_sys.clone_end_view(n.first); + purge_sys.batch_cleanup(head); MONITOR_INC_VALUE(MONITOR_PURGE_INVOKED, 1); - MONITOR_INC_VALUE(MONITOR_PURGE_N_PAGE_HANDLED, n.second); + MONITOR_INC_VALUE(MONITOR_PURGE_N_PAGE_HANDLED, n_pages); - return n.second; + return n_pages; } diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 9b5159a1ad6..511bad1fb47 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -2061,12 +2061,23 @@ trx_undo_get_undo_rec_low( mtr.start(); - const buf_block_t* undo_page= - buf_page_get(page_id_t(rseg->space->id, page_no), 0, RW_S_LATCH, &mtr); - - trx_undo_rec_t *undo_rec= undo_page - ? trx_undo_rec_copy(undo_page->page.frame + offset, heap) - : nullptr; + trx_undo_rec_t *undo_rec= nullptr; + if (const buf_block_t* undo_page= + buf_page_get(page_id_t(rseg->space->id, page_no), 0, RW_S_LATCH, &mtr)) + { + undo_rec= undo_page->page.frame + offset; + const size_t end= mach_read_from_2(undo_rec); + if (UNIV_UNLIKELY(end <= offset || + end >= srv_page_size - FIL_PAGE_DATA_END)) + undo_rec= nullptr; + else + { + size_t len{end - offset}; + undo_rec= + static_cast(mem_heap_dup(heap, undo_rec, len)); + mach_write_to_2(undo_rec, len); + } + } mtr.commit(); return undo_rec; diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index 6827d693345..203edd9f537 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -128,8 +128,8 @@ uint16_t trx_undo_page_get_start(const buf_block_t *block, uint32_t page_no, @param[in] page_no undo log header page number @param[in] offset undo log header page offset @return pointer to first record -@retval NULL if none exists */ -static trx_undo_rec_t* +@retval nullptr if none exists */ +trx_undo_rec_t* trx_undo_page_get_first_rec(const buf_block_t *block, uint32_t page_no, uint16_t offset) { @@ -253,25 +253,6 @@ trx_undo_get_next_rec_from_next_page(const buf_block_t *&block, return block ? trx_undo_page_get_first_rec(block, page_no, offset) : nullptr; } -/** Get the next record in an undo log. -@param[in,out] block undo log page -@param[in] rec undo record offset in the page -@param[in] page_no undo log header page number -@param[in] offset undo log header offset on page -@param[in,out] mtr mini-transaction -@return undo log record, the page latched, NULL if none */ -trx_undo_rec_t* -trx_undo_get_next_rec(const buf_block_t *&block, uint16_t rec, - uint32_t page_no, uint16_t offset, mtr_t *mtr) -{ - if (trx_undo_rec_t *next= trx_undo_page_get_next_rec(block, rec, page_no, - offset)) - return next; - - return trx_undo_get_next_rec_from_next_page(block, page_no, offset, - RW_S_LATCH, mtr); -} - /** Get the first record in an undo log. @param[in] space undo log header space @param[in] page_no undo log header page number @@ -282,7 +263,7 @@ trx_undo_get_next_rec(const buf_block_t *&block, uint16_t rec, @param[out] err error code @return undo log record, the page latched @retval nullptr if none */ -trx_undo_rec_t* +static trx_undo_rec_t* trx_undo_get_first_rec(const fil_space_t &space, uint32_t page_no, uint16_t offset, ulint mode, const buf_block_t*& block, mtr_t *mtr, dberr_t *err) From 2ba9702163a908d5fd195620c1d8dfc5c121b893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Oct 2023 10:21:49 +0300 Subject: [PATCH 125/158] MDEV-32050: Boost innodb_purge_batch_size on slow shutdown A slow shutdown using the previous default innodb_purge_batch_size=300 could be extremely slow, employing at most a few CPU cores on the average. Let us use the maximum batch size in order to increase throughput. Reviewed by: Vladislav Lesin --- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/include/trx0types.h | 1 + storage/innobase/srv/srv0srv.cc | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a672b38098e..d58df24fa72 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -18854,7 +18854,7 @@ static MYSQL_SYSVAR_ULONG(purge_batch_size, srv_purge_batch_size, NULL, NULL, 1000, /* Default setting */ 1, /* Minimum value */ - 5000, 0); /* Maximum value */ + innodb_purge_batch_size_MAX, 0); static MYSQL_SYSVAR_UINT(purge_threads, srv_n_purge_threads, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, diff --git a/storage/innobase/include/trx0types.h b/storage/innobase/include/trx0types.h index 69d5329216e..86e1f67bc02 100644 --- a/storage/innobase/include/trx0types.h +++ b/storage/innobase/include/trx0types.h @@ -47,6 +47,7 @@ static const ulint TRX_SYS_SPACE = 0; static const ulint TRX_MAGIC_N = 91118598; constexpr uint innodb_purge_threads_MAX= 32; +constexpr uint innodb_purge_batch_size_MAX= 5000; /** Transaction states (trx_t::state) */ enum trx_state_t { diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index dfb97bf6134..5fdcd91b63b 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1779,7 +1779,10 @@ void srv_purge_shutdown() if (purge_sys.enabled()) { if (!srv_fast_shutdown && !opt_bootstrap) + { + srv_purge_batch_size= innodb_purge_batch_size_MAX; srv_update_purge_thread_count(innodb_purge_threads_MAX); + } size_t history_size= trx_sys.history_size(); while (!srv_purge_should_exit(history_size)) { From 680f732fb8b4045872c08ec5b615c5611ba924b7 Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Sat, 14 Oct 2023 12:58:29 +0700 Subject: [PATCH 126/158] MDEV-32475: Skip sorting if we will read one row test_if_skip_sort_order() should catch the join types JT_EQ_REF, JT_CONST and JT_SYSTEM and skip sort order for these. Such join types imply retrieving of a single row of data, and sorting of a single row can always be skipped. --- mysql-test/main/order_by.result | 21 ++++++++++++++++++++- mysql-test/main/order_by.test | 16 ++++++++++++++++ sql/sql_select.cc | 8 ++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result index 2aab272eca2..9d83805c9c3 100644 --- a/mysql-test/main/order_by.result +++ b/mysql-test/main/order_by.result @@ -3446,7 +3446,7 @@ CREATE TABLE t2 SELECT * FROM t1; EXPLAIN SELECT (SELECT 1 FROM t1 WHERE t1.a=t2.b ORDER BY t1.b LIMIT 1) AS c FROM t2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 -2 DEPENDENT SUBQUERY t1 index PRIMARY b 5 NULL 1 Using where +2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.t2.b 1 Using where SELECT (SELECT 1 FROM t1 WHERE t1.a=t2.b ORDER BY t1.b LIMIT 1) AS c FROM t2; c 1 @@ -3706,4 +3706,23 @@ drop table t1,t2,t3,t4; SELECT 1.000000 two UNION SELECT 1 ORDER BY ( SELECT two LIMIT 1 OFFSET 1 ) ; two 1.000000 +# MDEV-32475: test_if_skip_sort_order() should catch the join types +# JT_EQ_REF, JT_CONST and JT_SYSTEM and skip sort order for these +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, KEY(b)); +CREATE TABLE t2 (a INT, b INT); +INSERT INTO t1 SELECT seq, seq+1 FROM seq_1_to_100; +INSERT INTO t2 VALUES (0, 1),(1, 2); +ANALYZE TABLE t1, t2 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +# Table t1 must use eq_ref, not index below: +EXPLAIN SELECT (SELECT 1 FROM t1 WHERE t1.a=t2.b ORDER BY t1.b LIMIT 1) AS c FROM t2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 +2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.t2.b 1 Using where +DROP TABLE t1,t2; # End of 10.4 tests diff --git a/mysql-test/main/order_by.test b/mysql-test/main/order_by.test index 9b63cbf64f0..ec10375e57c 100644 --- a/mysql-test/main/order_by.test +++ b/mysql-test/main/order_by.test @@ -2452,4 +2452,20 @@ drop table t1,t2,t3,t4; --echo # SELECT 1.000000 two UNION SELECT 1 ORDER BY ( SELECT two LIMIT 1 OFFSET 1 ) ; +--echo # MDEV-32475: test_if_skip_sort_order() should catch the join types +--echo # JT_EQ_REF, JT_CONST and JT_SYSTEM and skip sort order for these +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, KEY(b)); +CREATE TABLE t2 (a INT, b INT); +INSERT INTO t1 SELECT seq, seq+1 FROM seq_1_to_100; +INSERT INTO t2 VALUES (0, 1),(1, 2); + +ANALYZE TABLE t1, t2 PERSISTENT FOR ALL; + +--echo # Table t1 must use eq_ref, not index below: +EXPLAIN SELECT (SELECT 1 FROM t1 WHERE t1.a=t2.b ORDER BY t1.b LIMIT 1) AS c FROM t2; + +DROP TABLE t1,t2; + --echo # End of 10.4 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d7badbc59a5..f3ebf830301 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -23613,6 +23613,14 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, /* Check that we are always called with first non-const table */ DBUG_ASSERT(tab == tab->join->join_tab + tab->join->const_tables); + /* Sorting a single row can always be skipped */ + if (tab->type == JT_EQ_REF || + tab->type == JT_CONST || + tab->type == JT_SYSTEM) + { + DBUG_RETURN(1); + } + /* Keys disabled by ALTER TABLE ... DISABLE KEYS should have already been taken into account. From 68542caea1734c8ca89682c8d0740f896eab8e46 Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Wed, 18 Oct 2023 16:27:56 +0700 Subject: [PATCH 127/158] MDEV-32475 Add logging of test_if_skip_sort_order to optimizer trace --- mysql-test/main/opt_trace.result | 293 +++++++++++++++++-------------- sql/sql_select.cc | 6 + 2 files changed, 165 insertions(+), 134 deletions(-) diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result index 62643c60bc7..3b7961c2349 100644 --- a/mysql-test/main/opt_trace.result +++ b/mysql-test/main/opt_trace.result @@ -468,6 +468,9 @@ select * from v2 { } ] } + }, + { + "test_if_skip_sort_order": [] } ] } @@ -796,6 +799,9 @@ explain select * from v1 { } ] } + }, + { + "test_if_skip_sort_order": [] } ] } @@ -1290,6 +1296,9 @@ EXPLAIN SELECT DISTINCT a FROM t1 { } ] } + }, + { + "test_if_skip_sort_order": [] } ] } @@ -1485,23 +1494,27 @@ EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a { } }, { - "reconsidering_access_paths_for_index_ordering": { - "clause": "GROUP BY", - "fanout": 1, - "read_time": 3.3131, - "table": "t1", - "rows_estimation": 7, - "possible_keys": [ - { - "index": "a", - "can_resolve_order": true, - "updated_limit": 7, - "index_scan_time": 7, - "records": 7, - "chosen": true + "test_if_skip_sort_order": [ + { + "reconsidering_access_paths_for_index_ordering": { + "clause": "GROUP BY", + "fanout": 1, + "read_time": 3.3131, + "table": "t1", + "rows_estimation": 7, + "possible_keys": [ + { + "index": "a", + "can_resolve_order": true, + "updated_limit": 7, + "index_scan_time": 7, + "records": 7, + "chosen": true + } + ] } - ] - } + } + ] } ] } @@ -1687,23 +1700,27 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id { } }, { - "reconsidering_access_paths_for_index_ordering": { - "clause": "GROUP BY", - "fanout": 1, - "read_time": 2.0322, - "table": "t1", - "rows_estimation": 9, - "possible_keys": [ - { - "index": "id", - "can_resolve_order": true, - "updated_limit": 16, - "index_scan_time": 16, - "records": 16, - "chosen": true + "test_if_skip_sort_order": [ + { + "reconsidering_access_paths_for_index_ordering": { + "clause": "GROUP BY", + "fanout": 1, + "read_time": 2.0322, + "table": "t1", + "rows_estimation": 9, + "possible_keys": [ + { + "index": "id", + "can_resolve_order": true, + "updated_limit": 16, + "index_scan_time": 16, + "records": 16, + "chosen": true + } + ] } - ] - } + } + ] } ] } @@ -1878,23 +1895,27 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id { } }, { - "reconsidering_access_paths_for_index_ordering": { - "clause": "GROUP BY", - "fanout": 1, - "read_time": 2.0322, - "table": "t1", - "rows_estimation": 9, - "possible_keys": [ - { - "index": "id", - "can_resolve_order": true, - "updated_limit": 16, - "index_scan_time": 16, - "records": 16, - "chosen": true + "test_if_skip_sort_order": [ + { + "reconsidering_access_paths_for_index_ordering": { + "clause": "GROUP BY", + "fanout": 1, + "read_time": 2.0322, + "table": "t1", + "rows_estimation": 9, + "possible_keys": [ + { + "index": "id", + "can_resolve_order": true, + "updated_limit": 16, + "index_scan_time": 16, + "records": 16, + "chosen": true + } + ] } - ] - } + } + ] } ] } @@ -2176,97 +2197,101 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 { } }, { - "reconsidering_access_paths_for_index_ordering": { - "clause": "ORDER BY", - "fanout": 1, - "read_time": 22.001, - "table": "t1", - "rows_estimation": 21, - "possible_keys": [ - { - "index": "a_a", - "can_resolve_order": true, - "updated_limit": 47, - "index_scan_time": 47, - "usable": false, - "cause": "cost" - }, - { - "index": "a_c", - "can_resolve_order": true, - "updated_limit": 47, - "range_scan_time": 4.324, - "index_scan_time": 4.324, - "records": 180, - "chosen": true - }, - { - "index": "a_b", - "can_resolve_order": false, - "cause": "not usable index for the query" + "test_if_skip_sort_order": [ + { + "reconsidering_access_paths_for_index_ordering": { + "clause": "ORDER BY", + "fanout": 1, + "read_time": 22.001, + "table": "t1", + "rows_estimation": 21, + "possible_keys": [ + { + "index": "a_a", + "can_resolve_order": true, + "updated_limit": 47, + "index_scan_time": 47, + "usable": false, + "cause": "cost" + }, + { + "index": "a_c", + "can_resolve_order": true, + "updated_limit": 47, + "range_scan_time": 4.324, + "index_scan_time": 4.324, + "records": 180, + "chosen": true + }, + { + "index": "a_b", + "can_resolve_order": false, + "cause": "not usable index for the query" + } + ] } - ] - } - }, - { - "table": "t1", - "range_analysis": { - "table_scan": { - "rows": 1000, - "cost": 2e308 }, - "potential_range_indexes": [ - { - "index": "a_a", - "usable": false, - "cause": "not applicable" - }, - { - "index": "a_c", - "usable": true, - "key_parts": ["a", "c"] - }, - { - "index": "a_b", - "usable": false, - "cause": "not applicable" - } - ], - "setup_range_conditions": [], - "group_index_range": { - "chosen": false, - "cause": "no group by or distinct" - }, - "analyzing_range_alternatives": { - "range_scan_alternatives": [ - { - "index": "a_c", - "ranges": ["(1) <= (a) <= (1)"], - "rowid_ordered": false, - "using_mrr": false, - "index_only": false, - "rows": 180, - "cost": 229.72, + { + "table": "t1", + "range_analysis": { + "table_scan": { + "rows": 1000, + "cost": 2e308 + }, + "potential_range_indexes": [ + { + "index": "a_a", + "usable": false, + "cause": "not applicable" + }, + { + "index": "a_c", + "usable": true, + "key_parts": ["a", "c"] + }, + { + "index": "a_b", + "usable": false, + "cause": "not applicable" + } + ], + "setup_range_conditions": [], + "group_index_range": { + "chosen": false, + "cause": "no group by or distinct" + }, + "analyzing_range_alternatives": { + "range_scan_alternatives": [ + { + "index": "a_c", + "ranges": ["(1) <= (a) <= (1)"], + "rowid_ordered": false, + "using_mrr": false, + "index_only": false, + "rows": 180, + "cost": 229.72, + "chosen": true + } + ], + "analyzing_roworder_intersect": { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": [] + }, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "range_scan", + "index": "a_c", + "rows": 180, + "ranges": ["(1) <= (a) <= (1)"] + }, + "rows_for_plan": 180, + "cost_for_plan": 229.72, "chosen": true } - ], - "analyzing_roworder_intersect": { - "cause": "too few roworder scans" - }, - "analyzing_index_merge_union": [] - }, - "chosen_range_access_summary": { - "range_access_plan": { - "type": "range_scan", - "index": "a_c", - "rows": 180, - "ranges": ["(1) <= (a) <= (1)"] - }, - "rows_for_plan": 180, - "cost_for_plan": 229.72, - "chosen": true + } } - } + ] } ] } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f3ebf830301..e3a3a33a7c1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -23608,8 +23608,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, bool orig_cond_saved= false; int best_key= -1; bool changed_key= false; + THD *thd= tab->join->thd; DBUG_ENTER("test_if_skip_sort_order"); + Json_writer_object trace_wrapper(thd); + Json_writer_array trace_arr(thd, "test_if_skip_sort_order"); + /* Check that we are always called with first non-const table */ DBUG_ASSERT(tab == tab->join->join_tab + tab->join->const_tables); @@ -23618,6 +23622,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, tab->type == JT_CONST || tab->type == JT_SYSTEM) { + Json_writer_object trace_skip(thd); + trace_skip.add("skipped", "single row access method"); DBUG_RETURN(1); } From 818a9f38b64de60b154ad941d3a0bc0f5586825f Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 25 Oct 2023 14:34:43 +0200 Subject: [PATCH 128/158] MDEV-32574 main.winservice_basic sporadically fails on buildbot This commits only adds --verbose-bootstrap to mysql_install_db.exe call to have more error information dumped in case of an error. --- mysql-test/main/winservice.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/main/winservice.inc b/mysql-test/main/winservice.inc index d77856f6b5b..2e81c75d039 100644 --- a/mysql-test/main/winservice.inc +++ b/mysql-test/main/winservice.inc @@ -21,7 +21,7 @@ exec $sc_exe delete $service_name; source include/shutdown_mysqld.inc; echo # run mysql_install_db with --service parameter; --disable_result_log -exec $MYSQL_INSTALL_DB_EXE --datadir=$ddir --port=$MASTER_MYPORT --password=$password --service=$service_name -R; +exec $MYSQL_INSTALL_DB_EXE --datadir=$ddir --port=$MASTER_MYPORT --password=$password --service=$service_name --verbose-bootstrap -R; --enable_result_log echo # Start service; From ec2574fd8fd46da765fd60b0ca9650b729073401 Mon Sep 17 00:00:00 2001 From: Rex Date: Fri, 15 Sep 2023 08:44:49 +1100 Subject: [PATCH 129/158] MDEV-31983 jointable materialization subquery optimization ignoring ...errors, then failing ASSERT. UPDATE queries treat warnings as errors. In this case, an invalid condition "datetime_key_col >= '2012-01'" caused warning-as-error inside SQL_SELECT::test_quick_select(). The code that called test_quick_select() ignored this error and continued join optimization. Then it eventually reached a thd->is_error() check and failed to setup SJ-Materialization which failed an assert. Fixed this by making SQL_SELECT::test_quick_select() return error in its return value, and making any code that calls it to check for error condition and abort the query if the error is returned. Places in the code that didn't check for errors from SQL_SELECT::test_quick_select but now do: - get_quick_record_count() call in make_join_statistics(), - test_if_skip_sort_order(), - "Range checked for each record" code. Extra error handling fixes and commit text wording by Sergei Petrunia, Reviewed-by: Sergei Petrunia, Oleg Smirnov --- mysql-test/main/subselect_mat.result | 13 ++ mysql-test/main/subselect_sj_mat.result | 13 ++ mysql-test/main/subselect_sj_mat.test | 18 ++ sql/opt_range.cc | 50 +++-- sql/opt_range.h | 31 ++- sql/sql_select.cc | 254 ++++++++++++++++-------- 6 files changed, 278 insertions(+), 101 deletions(-) diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result index bbe81cec319..c5b201c6f46 100644 --- a/mysql-test/main/subselect_mat.result +++ b/mysql-test/main/subselect_mat.result @@ -2687,6 +2687,19 @@ i1 i2 1 4 2 6 DROP TABLE t1; +# +# MDEV-31983 jointable materialization subquery optimization ignoring errors, then failing ASSERT. +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (3),(4); +CREATE TABLE t3 (c DATETIME, d INT, KEY(c)); +INSERT INTO t3 VALUES ('2012-11-11',5),('2012-12-12',6); +UPDATE t1, t2 SET t1.a = 26 WHERE t2.b IN (SELECT MIN(d) FROM t3 WHERE c >= '2012-01'); +ERROR 22007: Incorrect datetime value: '2012-01' for column `test`.`t3`.`c` at row 1 +DROP TABLE t1, t2, t3; +# end of 10.6 tests set @subselect_mat_test_optimizer_switch_value=null; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off'; set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on'; diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result index fe232009f42..5d09af61892 100644 --- a/mysql-test/main/subselect_sj_mat.result +++ b/mysql-test/main/subselect_sj_mat.result @@ -2729,3 +2729,16 @@ i1 i2 1 4 2 6 DROP TABLE t1; +# +# MDEV-31983 jointable materialization subquery optimization ignoring errors, then failing ASSERT. +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (3),(4); +CREATE TABLE t3 (c DATETIME, d INT, KEY(c)); +INSERT INTO t3 VALUES ('2012-11-11',5),('2012-12-12',6); +UPDATE t1, t2 SET t1.a = 26 WHERE t2.b IN (SELECT MIN(d) FROM t3 WHERE c >= '2012-01'); +ERROR 22007: Incorrect datetime value: '2012-01' for column `test`.`t3`.`c` at row 1 +DROP TABLE t1, t2, t3; +# end of 10.6 tests diff --git a/mysql-test/main/subselect_sj_mat.test b/mysql-test/main/subselect_sj_mat.test index 000581d5758..0b5cfd6ab7b 100644 --- a/mysql-test/main/subselect_sj_mat.test +++ b/mysql-test/main/subselect_sj_mat.test @@ -2419,3 +2419,21 @@ WHERE alias1.i1 IN ( ); DROP TABLE t1; +--echo # +--echo # MDEV-31983 jointable materialization subquery optimization ignoring errors, then failing ASSERT. +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (3),(4); +CREATE TABLE t3 (c DATETIME, d INT, KEY(c)); +INSERT INTO t3 VALUES ('2012-11-11',5),('2012-12-12',6); + +--error ER_TRUNCATED_WRONG_VALUE +UPDATE t1, t2 SET t1.a = 26 WHERE t2.b IN (SELECT MIN(d) FROM t3 WHERE c >= '2012-01'); + +# Cleanup +DROP TABLE t1, t2, t3; + +--echo # end of 10.6 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 1180b2acda2..9e49f800204 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2671,24 +2671,34 @@ static int fill_used_fields_bitmap(PARAM *param) force_quick_range is really needed. RETURN - -1 if error or impossible select (i.e. certainly no rows will be selected) - 0 if can't use quick_select - 1 if found usable ranges and quick select has been successfully created. + SQL_SELECT:: + IMPOSSIBLE_RANGE, + impossible select (i.e. certainly no rows will be selected) + ERROR, + an error occurred, either memory or in evaluating conditions + OK = 1, + either + found usable ranges and quick select has been successfully created. + or can't use quick_select */ -int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, - table_map prev_tables, - ha_rows limit, bool force_quick_range, - bool ordered_output, - bool remove_false_parts_of_where, - bool only_single_index_range_scan, - bool suppress_unusable_key_notes) +quick_select_return +SQL_SELECT::test_quick_select(THD *thd, + key_map keys_to_use, + table_map prev_tables, + ha_rows limit, bool force_quick_range, + bool ordered_output, + bool remove_false_parts_of_where, + bool only_single_index_range_scan, + bool suppress_unusable_key_notes) { uint idx; double scan_time; Item *notnull_cond= NULL; TABLE_READ_PLAN *best_trp= NULL; SEL_ARG **backup_keys= 0; + quick_select_return returnval= OK; + DBUG_ENTER("SQL_SELECT::test_quick_select"); DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu", (ulong) keys_to_use.to_ulonglong(), (ulong) prev_tables, @@ -2701,7 +2711,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, head->with_impossible_ranges.clear_all(); DBUG_ASSERT(!head->is_filled_at_execution()); if (keys_to_use.is_clear_all() || head->is_filled_at_execution()) - DBUG_RETURN(0); + DBUG_RETURN(OK); records= head->stat_records(); notnull_cond= head->notnull_cond; if (!records) @@ -2754,7 +2764,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, bool force_group_by = false; if (check_stack_overrun(thd, 2*STACK_MIN_SIZE + sizeof(PARAM), buff)) - DBUG_RETURN(0); // Fatal error flag is set + DBUG_RETURN(ERROR); // Fatal error flag is set /* set up parameter that is passed to all functions */ bzero((void*) ¶m, sizeof(param)); @@ -2790,7 +2800,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, { thd->no_errors=0; free_root(&alloc,MYF(0)); // Return memory & allocator - DBUG_RETURN(-1); // Error + DBUG_RETURN(ERROR); } key_parts= param.key_parts; @@ -2858,7 +2868,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, { thd->no_errors=0; free_root(&alloc,MYF(0)); // Return memory & allocator - DBUG_RETURN(-1); // Error + DBUG_RETURN(ERROR); } thd->mem_root= &alloc; @@ -2910,7 +2920,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, { if (tree->type == SEL_TREE::IMPOSSIBLE) { - records=0L; /* Return -1 from this function. */ + records=0L; + returnval= IMPOSSIBLE_RANGE; read_time= (double) HA_POS_ERROR; trace_range.add("impossible_range", true); goto free_mem; @@ -2930,7 +2941,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, thd->no_errors=0; thd->mem_root= param.old_root; free_root(&alloc, MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(ERROR); } } @@ -3081,9 +3092,14 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, delete quick; quick= NULL; } + if (quick && records) + returnval= OK; } possible_keys= param.possible_keys; + if (!records) + returnval= IMPOSSIBLE_RANGE; + free_mem: if (unlikely(quick && best_trp && thd->trace_started())) { @@ -3109,7 +3125,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, Assume that if the user is using 'limit' we will only need to scan limit rows if we are using a key */ - DBUG_RETURN(records ? MY_TEST(quick) : -1); + DBUG_RETURN(returnval); } /**************************************************************************** diff --git a/sql/opt_range.h b/sql/opt_range.h index b98e6fd061e..de9a9464447 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -1712,13 +1712,20 @@ class SQL_SELECT :public Sql_alloc { ~SQL_SELECT(); void cleanup(); void set_quick(QUICK_SELECT_I *new_quick) { delete quick; quick= new_quick; } + + /* + @return + true - for ERROR and IMPOSSIBLE_RANGE + false - Ok + */ bool check_quick(THD *thd, bool force_quick_range, ha_rows limit) { key_map tmp; tmp.set_all(); return test_quick_select(thd, tmp, 0, limit, force_quick_range, - FALSE, FALSE, FALSE) < 0; + FALSE, FALSE, FALSE) != OK; } + /* RETURN 0 if record must be skipped <-> (cond && cond->val_int() == 0) @@ -1732,13 +1739,25 @@ class SQL_SELECT :public Sql_alloc { rc= -1; return rc; } - int test_quick_select(THD *thd, key_map keys, table_map prev_tables, - ha_rows limit, bool force_quick_range, - bool ordered_output, bool remove_false_parts_of_where, - bool only_single_index_range_scan, - bool suppress_unusable_key_notes = 0); + + enum quick_select_return_type { + IMPOSSIBLE_RANGE = -1, + ERROR, + OK + }; + + enum quick_select_return_type + test_quick_select(THD *thd, key_map keys, table_map prev_tables, + ha_rows limit, + bool force_quick_range, + bool ordered_output, + bool remove_false_parts_of_where, + bool only_single_index_range_scan, + bool suppress_unusable_key_notes = 0); }; +typedef enum SQL_SELECT::quick_select_return_type quick_select_return; + class SQL_SELECT_auto { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9f2e65cb59f..0c8432afd91 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -105,9 +105,10 @@ static int sort_keyuse(KEYUSE *a,KEYUSE *b); static bool are_tables_local(JOIN_TAB *jtab, table_map used_tables); static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, bool allow_full_scan, table_map used_tables); -static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, +static bool get_quick_record_count(THD *thd, SQL_SELECT *select, TABLE *table, - const key_map *keys,ha_rows limit); + const key_map *keys,ha_rows limit, + ha_rows *quick_count); static void optimize_straight_join(JOIN *join, table_map join_tables); static bool greedy_search(JOIN *join, table_map remaining_tables, uint depth, uint prune_level, @@ -204,8 +205,8 @@ static int join_read_last_key(JOIN_TAB *tab); static int join_no_more_records(READ_RECORD *info); static int join_read_next(READ_RECORD *info); static int join_init_quick_read_record(JOIN_TAB *tab); -static int test_if_quick_select(JOIN_TAB *tab); -static bool test_if_use_dynamic_range_scan(JOIN_TAB *join_tab); +static quick_select_return test_if_quick_select(JOIN_TAB *tab); +static int test_if_use_dynamic_range_scan(JOIN_TAB *join_tab); static int join_read_first(JOIN_TAB *tab); static int join_read_next(READ_RECORD *info); static int join_read_next_same(READ_RECORD *info); @@ -245,7 +246,8 @@ static int test_if_order_by_key(JOIN *join, uint *used_key_parts); static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order, ha_rows select_limit, bool no_changes, - const key_map *map); + const key_map *map, + bool *fatal_error); static bool list_contains_unique_index(TABLE *table, bool (*find_func) (Field *, void *), void *data); static bool find_field_in_item_list (Field *field, void *data); @@ -1891,7 +1893,8 @@ int JOIN::optimize() object a pointer to which is set in the field JOIN_TAB::rowid_filter of the joined table. - @retval false always + @retval false Ok + @retval true Error */ bool JOIN::make_range_rowid_filters() @@ -1934,18 +1937,21 @@ bool JOIN::make_range_rowid_filters() filter_map.merge(tab->table->with_impossible_ranges); bool force_index_save= tab->table->force_index; tab->table->force_index= true; - int rc= sel->test_quick_select(thd, filter_map, (table_map) 0, - (ha_rows) HA_POS_ERROR, - true, false, true, true); + quick_select_return rc; + rc= sel->test_quick_select(thd, filter_map, (table_map) 0, + (ha_rows) HA_POS_ERROR, true, false, true, + true); tab->table->force_index= force_index_save; - if (thd->is_error()) - goto no_filter; + if (rc == SQL_SELECT::ERROR || thd->is_error()) + { + DBUG_RETURN(true); /* Fatal error */ + } /* If SUBS_IN_TO_EXISTS strtrategy is chosen for the subquery then additional conditions are injected into WHERE/ON/HAVING and it may happen that the call of test_quick_select() discovers impossible range. */ - if (rc == -1) + if (rc == SQL_SELECT::IMPOSSIBLE_RANGE) { const_table_map|= tab->table->map; goto no_filter; @@ -2959,20 +2965,29 @@ int JOIN::optimize_stage2() tab= &join_tab[const_tables]; if (order) { + bool fatal_err; skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, true, // no_changes - &tab->table->keys_in_use_for_order_by); + &tab->table->keys_in_use_for_order_by, + &fatal_err); + if (fatal_err) + DBUG_RETURN(1); } if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array, order, fields_list, all_fields, &all_order_fields_used))) { + bool fatal_err= 0; const bool skip_group= skip_sort_order && test_if_skip_sort_order(tab, group_list, select_limit, - true, // no_changes - &tab->table->keys_in_use_for_group_by); + true, // no_changes + &tab->table->keys_in_use_for_group_by, + &fatal_err); + if (fatal_err) + DBUG_RETURN(1); + count_field_types(select_lex, &tmp_table_param, all_fields, 0); if ((skip_group && all_order_fields_used) || select_limit == HA_POS_ERROR || @@ -3235,12 +3250,16 @@ int JOIN::optimize_stage2() 'need_tmp' implies that there will be more postprocessing so the specified 'limit' should not be enforced yet. */ + bool fatal_err; const ha_rows limit = need_tmp ? HA_POS_ERROR : select_limit; if (test_if_skip_sort_order(tab, group_list, limit, false, - &tab->table->keys_in_use_for_group_by)) + &tab->table->keys_in_use_for_group_by, + &fatal_err)) { ordered_index_usage= ordered_index_group_by; } + if (fatal_err) + DBUG_RETURN(1); } /* @@ -3263,11 +3282,15 @@ int JOIN::optimize_stage2() else if (order && // ORDER BY wo/ preceding GROUP BY (simple_order || skip_sort_order)) // which is possibly skippable { + bool fatal_err; if (test_if_skip_sort_order(tab, order, select_limit, false, - &tab->table->keys_in_use_for_order_by)) + &tab->table->keys_in_use_for_order_by, + &fatal_err)) { ordered_index_usage= ordered_index_order_by; } + if (fatal_err) + DBUG_RETURN(1); } } @@ -5114,40 +5137,59 @@ err: } -/***************************************************************************** - Create JOIN_TABS, make a guess about the table types, - Approximate how many records will be used in each table -*****************************************************************************/ +/** + Approximate how many records are going to be returned by this table in this + select with this key. -static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, + @param thd Thread handle + @param select Select to be examined + @param table The table of interest + @param keys The keys of interest + @param limit Maximum number of rows of interest + @param quick_count Pointer to where we want the estimate written + + @return Status + @retval false Success + @retval true Error + +*/ + +static bool get_quick_record_count(THD *thd, SQL_SELECT *select, TABLE *table, - const key_map *keys,ha_rows limit) + const key_map *keys,ha_rows limit, + ha_rows *quick_count) { - int error; + quick_select_return error; DBUG_ENTER("get_quick_record_count"); uchar buff[STACK_BUFF_ALLOC]; if (unlikely(check_stack_overrun(thd, STACK_MIN_SIZE, buff))) - DBUG_RETURN(0); // Fatal error flag is set + DBUG_RETURN(false); // Fatal error flag is set if (select) - { + { select->head=table; table->reginfo.impossible_range=0; - if (likely((error= - select->test_quick_select(thd, *(key_map *)keys, - (table_map) 0, - limit, 0, FALSE, - TRUE, /* remove_where_parts*/ - FALSE, TRUE)) == - 1)) - DBUG_RETURN(select->quick->records); - if (unlikely(error == -1)) + error= select->test_quick_select(thd, *(key_map *)keys, (table_map) 0, + limit, 0, FALSE, + TRUE, /* remove_where_parts*/ + FALSE, TRUE); + + if (error == SQL_SELECT::OK && select->quick) + { + *quick_count= select->quick->records; + DBUG_RETURN(false); + } + if (error == SQL_SELECT::IMPOSSIBLE_RANGE) { table->reginfo.impossible_range=1; - DBUG_RETURN(0); + DBUG_RETURN(false); } + if (unlikely(error == SQL_SELECT::ERROR)) + DBUG_RETURN(true); + DBUG_PRINT("warning",("Couldn't use record count on const keypart")); } - DBUG_RETURN(HA_POS_ERROR); /* This shouldn't happend */ + *quick_count= HA_POS_ERROR; + DBUG_RETURN(false); /* This shouldn't happen */ } /* @@ -5860,11 +5902,10 @@ make_join_statistics(JOIN *join, List &tables_list, (SORT_INFO*) 0, 1, &error); if (!select) goto error; - records= get_quick_record_count(join->thd, select, s->table, - &s->const_keys, join->row_limit); - if (join->thd->is_error()) + if (get_quick_record_count(join->thd, select, s->table, + &s->const_keys, join->row_limit, &records)) { - /* get_quick_record_count generated an error */ + /* There was an error in test_quick_select */ delete select; goto error; } @@ -12634,15 +12675,18 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) */ if (sel->cond && !sel->cond->fixed()) sel->cond->quick_fix_field(); + quick_select_return res; - if (sel->test_quick_select(thd, tab->keys, - ((used_tables & ~ current_map) | - OUTER_REF_TABLE_BIT), - (join->select_options & - OPTION_FOUND_ROWS ? - HA_POS_ERROR : - join->unit->lim.get_select_limit()), 0, - FALSE, FALSE, FALSE) < 0) + if ((res= sel->test_quick_select(thd, tab->keys, + ((used_tables & ~ current_map) | + OUTER_REF_TABLE_BIT), + (join->select_options & + OPTION_FOUND_ROWS ? + HA_POS_ERROR : + join->unit->lim.get_select_limit()), + 0, + FALSE, FALSE, FALSE)) == + SQL_SELECT::IMPOSSIBLE_RANGE) { /* Before reporting "Impossible WHERE" for the whole query @@ -12650,18 +12694,22 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) */ sel->cond=orig_cond; if (!*tab->on_expr_ref || - sel->test_quick_select(thd, tab->keys, - used_tables & ~ current_map, - (join->select_options & - OPTION_FOUND_ROWS ? - HA_POS_ERROR : - join->unit->lim.get_select_limit()),0, - FALSE, FALSE, FALSE, TRUE) < 0) + (res= sel->test_quick_select(thd, tab->keys, + used_tables & ~ current_map, + (join->select_options & + OPTION_FOUND_ROWS ? + HA_POS_ERROR : + join->unit->lim.get_select_limit()), + 0, FALSE, FALSE, FALSE, TRUE)) == + SQL_SELECT::IMPOSSIBLE_RANGE) DBUG_RETURN(1); // Impossible WHERE } else sel->cond=orig_cond; + if (res == SQL_SELECT::ERROR) + DBUG_RETURN(1); /* Some error in one of test_quick_select calls */ + /* Fix for EXPLAIN */ if (sel->quick) join->best_positions[i].records_read= (double)sel->quick->records; @@ -21472,6 +21520,7 @@ sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool end_of_records) { enum_nested_loop_state rc; JOIN_CACHE *cache= join_tab->cache; + int err; DBUG_ENTER("sub_select_cache"); /* @@ -21497,7 +21546,7 @@ sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool end_of_records) } join_tab->jbuf_loops_tracker->on_scan_init(); - if (!test_if_use_dynamic_range_scan(join_tab)) + if (!(err= test_if_use_dynamic_range_scan(join_tab))) { if (!cache->put_record()) DBUG_RETURN(NESTED_LOOP_OK); @@ -21509,6 +21558,10 @@ sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool end_of_records) rc= cache->join_records(FALSE); DBUG_RETURN(rc); } + + if (err < 0) + DBUG_RETURN(NESTED_LOOP_ERROR); + /* TODO: Check whether we really need the call below and we can't do without it. If it's not the case remove it. @@ -22609,8 +22662,18 @@ join_read_prev_same(READ_RECORD *info) static int join_init_quick_read_record(JOIN_TAB *tab) { - if (test_if_quick_select(tab) == -1) - return -1; /* No possible records */ + quick_select_return res= test_if_quick_select(tab); + + if (res == SQL_SELECT::ERROR) + return 1; /* Fatal error */ + + if (res == SQL_SELECT::IMPOSSIBLE_RANGE) + return -1; /* No possible records */ + + /* + Proceed to read rows. If we've created a quick select, use it, otherwise + do a full scan. + */ return join_init_read_record(tab); } @@ -22622,7 +22685,13 @@ int read_first_record_seq(JOIN_TAB *tab) return tab->read_record.read_record(); } -static int + +/* + @brief + Create a new (dynamic) quick select. +*/ + +static quick_select_return test_if_quick_select(JOIN_TAB *tab) { DBUG_EXECUTE_IF("show_explain_probe_test_if_quick_select", @@ -22639,11 +22708,11 @@ test_if_quick_select(JOIN_TAB *tab) if (tab->table->file->inited != handler::NONE) tab->table->file->ha_index_or_rnd_end(); - int res= tab->select->test_quick_select(tab->join->thd, tab->keys, - (table_map) 0, HA_POS_ERROR, 0, - FALSE, /*remove where parts*/FALSE, - FALSE, - /* no warnings */ TRUE); + quick_select_return res; + res= tab->select->test_quick_select(tab->join->thd, tab->keys, + (table_map) 0, HA_POS_ERROR, 0, + FALSE, /*remove where parts*/FALSE, + FALSE, /* no warnings */ TRUE); if (tab->explain_plan && tab->explain_plan->range_checked_fer) tab->explain_plan->range_checked_fer->collect_data(tab->select->quick); @@ -22651,10 +22720,29 @@ test_if_quick_select(JOIN_TAB *tab) } -static -bool test_if_use_dynamic_range_scan(JOIN_TAB *join_tab) +/* + @return + 1 - Yes, use dynamically built range + 0 - No, don't use dynamic range (but there's no error) + -1 - Fatal error +*/ + +static +int test_if_use_dynamic_range_scan(JOIN_TAB *join_tab) { - return (join_tab->use_quick == 2 && test_if_quick_select(join_tab) > 0); + if (unlikely(join_tab->use_quick == 2)) + { + quick_select_return res= test_if_quick_select(join_tab); + if (res == SQL_SELECT::ERROR) + return -1; + else + { + /* Both OK and IMPOSSIBLE_RANGE go here */ + return join_tab->select->quick ? 1 : 0; + } + } + else + return 0; } int join_init_read_record(JOIN_TAB *tab) @@ -24477,7 +24565,8 @@ void compute_part_of_sort_key_for_equals(JOIN *join, TABLE *table, The index must cover all fields in , or it will not be considered. - @param no_changes No changes will be made to the query plan. + @param no_changes No changes will be made to the query plan. + @param fatal_error OUT A fatal error occurred @todo - sergeyp: Results of all index merge selects actually are ordered @@ -24491,7 +24580,7 @@ void compute_part_of_sort_key_for_equals(JOIN *join, TABLE *table, static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, - bool no_changes, const key_map *map) + bool no_changes, const key_map *map, bool *fatal_error) { int ref_key; uint UNINIT_VAR(ref_key_parts); @@ -24507,6 +24596,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, bool changed_key= false; DBUG_ENTER("test_if_skip_sort_order"); + *fatal_error= false; /* Check that we are always called with first non-const table */ DBUG_ASSERT(tab == tab->join->join_tab + tab->join->const_tables); @@ -24644,7 +24734,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, */ key_map new_ref_key_map; COND *save_cond; - bool res; + quick_select_return res; new_ref_key_map.clear_all(); // Force the creation of quick select new_ref_key_map.set_bit(new_ref_key); // only for new_ref_key. @@ -24659,9 +24749,11 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, HA_POS_ERROR : tab->join->unit-> lim.get_select_limit(), - TRUE, TRUE, FALSE, FALSE) <= 0; - if (res) + TRUE, TRUE, FALSE, FALSE); + if (res != SQL_SELECT::OK) { + if (res == SQL_SELECT::ERROR) + *fatal_error= true; select->cond= save_cond; goto use_filesort; } @@ -24757,11 +24849,17 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, cond_saved= true; } - select->test_quick_select(join->thd, tmp_map, 0, - join->select_options & OPTION_FOUND_ROWS ? - HA_POS_ERROR : - join->unit->lim.get_select_limit(), - TRUE, FALSE, FALSE, FALSE); + quick_select_return res; + res = select->test_quick_select(join->thd, tmp_map, 0, + join->select_options & OPTION_FOUND_ROWS ? + HA_POS_ERROR : + join->unit->lim.get_select_limit(), + TRUE, FALSE, FALSE, FALSE); + if (res == SQL_SELECT::ERROR) + { + *fatal_error= true; + goto use_filesort; + } if (cond_saved) select->cond= saved_cond; From cb4c2713553c5f522d2a4ebf186c6505384c748d Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 26 Oct 2023 13:39:22 +0200 Subject: [PATCH 130/158] Fix --view-protocol failures --- mysql-test/include/empty_string_literal.inc | 4 ++++ mysql-test/main/mdl.test | 2 ++ mysql-test/main/sql_mode.test | 2 ++ 3 files changed, 8 insertions(+) diff --git a/mysql-test/include/empty_string_literal.inc b/mysql-test/include/empty_string_literal.inc index 9ccedde6dce..5857c26d4ee 100644 --- a/mysql-test/include/empty_string_literal.inc +++ b/mysql-test/include/empty_string_literal.inc @@ -1,6 +1,8 @@ SET SESSION character_set_connection=latin2; SET SESSION character_set_client=cp1250; +--disable_service_connection + --echo # --echo # Test litteral --echo # @@ -129,3 +131,5 @@ EXPLAIN EXTENDED SELECT ''; EXPLAIN EXTENDED SELECT _latin1''; EXPLAIN EXTENDED SELECT N''; EXPLAIN EXTENDED SELECT '' ''; + +--enable_service_connection diff --git a/mysql-test/main/mdl.test b/mysql-test/main/mdl.test index b0ce408ec13..5d794e2b9d9 100644 --- a/mysql-test/main/mdl.test +++ b/mysql-test/main/mdl.test @@ -84,6 +84,7 @@ DROP TABLE t1,t3; --echo # --echo # MDEV-28820 MyISAM wrong server status flags --echo # +--disable_service_connection # MyISAM alone doesn't start a transaction or takes transactional MDL create table t1 (a int); set autocommit=0; @@ -119,6 +120,7 @@ disconnect foo; connection default; set autocommit=default; drop table t2; +--enable_service_connection --echo # --echo # End of 10.4 tests diff --git a/mysql-test/main/sql_mode.test b/mysql-test/main/sql_mode.test index b1c5f05e618..e5ad61ef0e3 100644 --- a/mysql-test/main/sql_mode.test +++ b/mysql-test/main/sql_mode.test @@ -575,7 +575,9 @@ DELIMITER ;$$ SET sql_mode='ORACLE,EMPTY_STRING_IS_NULL'; SELECT @@sql_mode; +--disable_service_connection SELECT '' AS empty; +--enable_service_connection SET sql_mode=''; SELECT @@sql_mode; SET sql_mode=DEFAULT; From 39e3ca8bd25fc539ed08ff464e8a3189ff9f7fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 26 Oct 2023 15:07:59 +0300 Subject: [PATCH 131/158] MDEV-31826 InnoDB may fail to recover after being killed in fil_delete_tablespace() InnoDB was violating the write-ahead-logging protocol when a file was being deleted, like this: 1. fil_delete_tablespace() set the fil_space_t::STOPPING flag 2. The buf_flush_page_cleaner() thread discards some changed pages for this tablespace advances the log checkpoint a little. 3. The server process is killed before fil_delete_tablespace() wrote a FILE_DELETE record. 4. Recovery will try to apply log to pages of the tablespace, because there was no FILE_DELETE record. This will fail, because some pages that had been modified since the latest checkpoint had not been written by the page cleaner. Page writes must not be stopped before a FILE_DELETE record has been durably written. fil_space_t::drop(): Replaces fil_space_t::check_pending_operations(). Add the parameter detached_handle, and return a tablespace pointer if this thread was the first one to stop I/O on the tablespace. mtr_t::commit_file(): Remove the parameter detached_handle, and move some handling to fil_space_t::drop(). fil_space_t: STOPPING_READS, STOPPING_WRITES: Separate flags for STOPPING. We want to stop reads (and encryption) before stopping page writes. fil_space_t::is_stopping_writes(), fil_space_t::get_for_write(): Special accessors for the write path. fil_space_t::flush_low(): Ignore the STOPPING_READS flag and only stop if STOPPING_WRITES is set, to avoid an infinite loop in fil_flush_file_spaces(), which was occasionally repeated by running the test encryption.create_or_replace. Reviewed by: Vladislav Lesin Tested by: Matthias Leich --- storage/innobase/buf/buf0dblwr.cc | 2 +- storage/innobase/buf/buf0flu.cc | 31 ++++++-- storage/innobase/fil/fil0fil.cc | 124 ++++++++++++++++------------- storage/innobase/include/fil0fil.h | 109 ++++++++++++------------- storage/innobase/include/mtr0mtr.h | 8 +- storage/innobase/mtr/mtr0mtr.cc | 43 +--------- 6 files changed, 151 insertions(+), 166 deletions(-) diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index eac63e2e3a6..2503b1a81dd 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -530,7 +530,7 @@ static void buf_dblwr_check_page_lsn(const page_t* page, const fil_space_t& s) static void buf_dblwr_check_page_lsn(const buf_page_t &b, const byte *page) { - if (fil_space_t *space= fil_space_t::get(b.id().space())) + if (fil_space_t *space= fil_space_t::get_for_write(b.id().space())) { buf_dblwr_check_page_lsn(page, *space); space->release(); diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 52665037e87..0273837eb1a 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1110,7 +1110,7 @@ static ulint buf_flush_try_neighbors(fil_space_t *space, for (ulint id_fold= id.fold(); id < high; ++id, ++id_fold) { - if (UNIV_UNLIKELY(space->is_stopping())) + if (UNIV_UNLIKELY(space->is_stopping_writes())) { if (bpage) bpage->lock.u_unlock(true); @@ -1215,12 +1215,31 @@ static ulint buf_free_from_unzip_LRU_list_batch() return(count); } +/** Acquire a tablespace reference for writing. +@param id tablespace identifier +@return tablespace +@retval nullptr if the tablespace is missing or inaccessible */ +fil_space_t *fil_space_t::get_for_write(ulint id) +{ + mysql_mutex_lock(&fil_system.mutex); + fil_space_t *space= fil_space_get_by_id(id); + const uint32_t n= space ? space->acquire_low(STOPPING_WRITES) : 0; + + if (n & STOPPING_WRITES) + space= nullptr; + else if ((n & CLOSING) && !space->prepare_acquired()) + space= nullptr; + + mysql_mutex_unlock(&fil_system.mutex); + return space; +} + /** Start writing out pages for a tablespace. @param id tablespace identifier @return tablespace and number of pages written */ static std::pair buf_flush_space(const uint32_t id) { - if (fil_space_t *space= fil_space_t::get(id)) + if (fil_space_t *space= fil_space_t::get_for_write(id)) return {space, space->flush_freed(true)}; return {nullptr, 0}; } @@ -1349,7 +1368,7 @@ static void buf_flush_LRU_list_batch(ulint max, bool evict, goto no_space; } } - else if (space->is_stopping()) + else if (space->is_stopping_writes()) { space->release(); space= nullptr; @@ -1501,7 +1520,7 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn) else ut_ad(!space); } - else if (space->is_stopping()) + else if (space->is_stopping_writes()) { space->release(); space= nullptr; @@ -1633,7 +1652,7 @@ bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed) ulint max_n_flush= srv_io_capacity; ulint n_flush= 0; - bool acquired= space->acquire(); + bool acquired= space->acquire_for_write(); { const uint32_t written{space->flush_freed(acquired)}; mysql_mutex_lock(&buf_pool.mutex); @@ -1676,7 +1695,7 @@ bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed) buf_flush_discard_page(bpage); else { - if (space->is_stopping()) + if (space->is_stopping_writes()) { space->release(); acquired= false; diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 942eb94a56c..b24e4d0cb9e 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -99,11 +99,9 @@ bool fil_space_t::try_to_close(bool print_info) if (!node->is_open()) continue; - /* Other thread is trying to do fil_delete_tablespace() - concurrently for the same tablespace. So ignore this - tablespace and try to close the other one */ const auto n= space.set_closing(); if (n & STOPPING) + /* Let fil_space_t::drop() in another thread handle this. */ continue; if (n & (PENDING | NEEDS_FSYNC)) { @@ -508,7 +506,7 @@ void fil_space_t::flush_low() std::memory_order_relaxed)) { ut_ad(n & PENDING); - if (n & STOPPING) + if (n & STOPPING_WRITES) return; if (n & NEEDS_FSYNC) break; @@ -1582,7 +1580,7 @@ fil_name_write( mtr->log_file_op(FILE_MODIFY, space_id, name); } -fil_space_t *fil_space_t::check_pending_operations(ulint id) +fil_space_t *fil_space_t::drop(ulint id, pfs_os_file_t *detached_handle) { ut_a(!is_system_tablespace(id)); mysql_mutex_lock(&fil_system.mutex); @@ -1596,7 +1594,6 @@ fil_space_t *fil_space_t::check_pending_operations(ulint id) if (space->pending() & STOPPING) { -being_deleted: /* A thread executing DDL and another thread executing purge may be executing fil_delete_tablespace() concurrently for the same tablespace. Wait for the other thread to complete the operation. */ @@ -1615,34 +1612,73 @@ being_deleted: mysql_mutex_lock(&fil_system.mutex); } } - else - { - if (space->crypt_data) - { - space->reacquire(); - mysql_mutex_unlock(&fil_system.mutex); - fil_space_crypt_close_tablespace(space); - mysql_mutex_lock(&fil_system.mutex); - space->release(); - } - if (space->set_stopping_check()) - goto being_deleted; - } + /* We must be the first one to set either STOPPING flag on the .ibd file, + because the flags are only being set here, within a critical section of + fil_system.mutex. */ + unsigned pending; + ut_d(pending=) + space->n_pending.fetch_add(STOPPING_READS + 1, std::memory_order_relaxed); + ut_ad(!(pending & STOPPING)); mysql_mutex_unlock(&fil_system.mutex); - for (ulint count= 0;; count++) + if (space->crypt_data) + fil_space_crypt_close_tablespace(space); + + if (space->purpose == FIL_TYPE_TABLESPACE) { - const unsigned pending= space->referenced(); - if (!pending) - return space; - /* Issue a warning every 10.24 seconds, starting after 2.56 seconds */ - if ((count & 511) == 128) - sql_print_warning("InnoDB: Trying to delete tablespace '%s' " - "but there are %u pending operations", - space->chain.start->name, id); - std::this_thread::sleep_for(std::chrono::milliseconds(20)); + /* Before deleting the file, persistently write a log record. */ + mtr_t mtr; + mtr.start(); + mtr.log_file_op(FILE_DELETE, id, space->chain.start->name); + mtr.commit_file(*space, nullptr); + + if (FSP_FLAGS_HAS_DATA_DIR(space->flags)) + RemoteDatafile::delete_link_file(space->name()); + + os_file_delete(innodb_data_file_key, space->chain.start->name); } + else + ut_ad(space->purpose == FIL_TYPE_IMPORT); + + if (char *cfg_name= fil_make_filepath(space->chain.start->name, + fil_space_t::name_type{}, CFG, false)) + { + os_file_delete_if_exists(innodb_data_file_key, cfg_name, nullptr); + ut_free(cfg_name); + } + + mysql_mutex_lock(&fil_system.mutex); + ut_ad(space == fil_space_get_by_id(id)); + pending= + space->n_pending.fetch_add(STOPPING_WRITES - 1, std::memory_order_relaxed); + ut_ad((pending & STOPPING) == STOPPING_READS); + ut_ad(pending & PENDING); + pending&= PENDING; + if (--pending) + { + for (ulint count= 0;; count++) + { + ut_ad(space == fil_space_get_by_id(id)); + pending= space->n_pending.load(std::memory_order_relaxed) & PENDING; + if (!pending) + break; + mysql_mutex_unlock(&fil_system.mutex); + /* Issue a warning every 10.24 seconds, starting after 2.56 seconds */ + if ((count & 511) == 128) + sql_print_warning("InnoDB: Trying to delete tablespace '%s' " + "but there are %u pending operations", + space->chain.start->name, pending); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + mysql_mutex_lock(&fil_system.mutex); + } + } + + pfs_os_file_t handle= fil_system.detach(space, true); + mysql_mutex_unlock(&fil_system.mutex); + if (detached_handle) + *detached_handle = handle; + return space; } /** Close a single-table tablespace on failed IMPORT TABLESPACE. @@ -1651,34 +1687,22 @@ Free all pages used by the tablespace. */ void fil_close_tablespace(ulint id) { ut_ad(!is_system_tablespace(id)); - fil_space_t* space = fil_space_t::check_pending_operations(id); + fil_space_t* space = fil_space_t::drop(id, nullptr); if (!space) { return; } space->x_lock(); + ut_ad(space->is_stopping()); /* Invalidate in the buffer pool all pages belonging to the - tablespace. Since we have invoked space->set_stopping(), readahead + tablespace. Since space->is_stopping() holds, readahead can no longer read more pages of this tablespace to buf_pool. Thus we can clean the tablespace out of buf_pool completely and permanently. */ while (buf_flush_list_space(space)); - ut_ad(space->is_stopping()); - - /* If it is a delete then also delete any generated files, otherwise - when we drop the database the remove directory will fail. */ - - if (char* cfg_name = fil_make_filepath(space->chain.start->name, - fil_space_t::name_type{}, - CFG, false)) { - os_file_delete_if_exists(innodb_data_file_key, cfg_name, NULL); - ut_free(cfg_name); - } - - /* If the free is successful, the wrlock will be released before - the space memory data structure is freed. */ + /* If the free is successful, the latch will be released there. */ if (!fil_space_free(id, true)) { space->x_unlock(); } @@ -1692,16 +1716,8 @@ pfs_os_file_t fil_delete_tablespace(ulint id) { ut_ad(!is_system_tablespace(id)); pfs_os_file_t handle= OS_FILE_CLOSED; - if (fil_space_t *space= fil_space_t::check_pending_operations(id)) - { - /* Before deleting the file(s), persistently write a log record. */ - mtr_t mtr; - mtr.start(); - mtr.log_file_op(FILE_DELETE, id, space->chain.start->name); - mtr.commit_file(*space, nullptr, &handle); + if (fil_space_t *space= fil_space_t::drop(id, &handle)) fil_space_free_low(space); - } - return handle; } diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 7deec35d986..8c822f5871c 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -397,16 +397,22 @@ private: /** Number of pending operations on the file. The tablespace cannot be freed while (n_pending & PENDING) != 0. */ std::atomic n_pending; + /** Flag in n_pending that indicates that the tablespace is about to be + deleted, and no further operations should be performed */ + static constexpr uint32_t STOPPING_READS= 1U << 31; /** Flag in n_pending that indicates that the tablespace is being deleted, and no further operations should be performed */ - static constexpr uint32_t STOPPING= 1U << 31; + static constexpr uint32_t STOPPING_WRITES= 1U << 30; + /** Flags in n_pending that indicate that the tablespace is being + deleted, and no further operations should be performed */ + static constexpr uint32_t STOPPING= STOPPING_READS | STOPPING_WRITES; /** Flag in n_pending that indicates that the tablespace is a candidate for being closed, and fil_node_t::is_open() can only be trusted after acquiring fil_system.mutex and resetting the flag */ - static constexpr uint32_t CLOSING= 1U << 30; + static constexpr uint32_t CLOSING= 1U << 29; /** Flag in n_pending that indicates that the tablespace needs fsync(). This must be the least significant flag bit; @see release_flush() */ - static constexpr uint32_t NEEDS_FSYNC= 1U << 29; + static constexpr uint32_t NEEDS_FSYNC= 1U << 28; /** The reference count */ static constexpr uint32_t PENDING= ~(STOPPING | CLOSING | NEEDS_FSYNC); /** latch protecting all page allocation bitmap pages */ @@ -517,20 +523,19 @@ public: /** Close each file. Only invoked on fil_system.temp_space. */ void close(); - /** Note that operations on the tablespace must stop. - @return whether the operations were already stopped */ - inline bool set_stopping_check(); /** Note that operations on the tablespace must stop. */ inline void set_stopping(); /** Note that operations on the tablespace can resume after truncation */ inline void clear_stopping(); - /** Look up the tablespace and wait for pending operations to cease - @param id tablespace identifier - @return tablespace - @retval nullptr if no tablespace was found */ - static fil_space_t *check_pending_operations(ulint id); + /** Drop the tablespace and wait for any pending operations to cease + @param id tablespace identifier + @param detached_handle pointer to file to be closed later, or nullptr + @return tablespace to invoke fil_space_free() on + @retval nullptr if no tablespace was found, or it was deleted by + another concurrent thread */ + static fil_space_t *drop(ulint id, pfs_os_file_t *detached_handle); private: MY_ATTRIBUTE((warn_unused_result)) @@ -554,13 +559,19 @@ public: MY_ATTRIBUTE((warn_unused_result)) /** Acquire a tablespace reference for I/O. + @param avoid when these flags are set, nothing will be acquired @return whether the file is usable */ - bool acquire() + bool acquire(uint32_t avoid= STOPPING | CLOSING) { - const auto flags= acquire_low(STOPPING | CLOSING) & (STOPPING | CLOSING); + const auto flags= acquire_low(avoid) & (avoid); return UNIV_LIKELY(!flags) || (flags == CLOSING && acquire_and_prepare()); } + /** Acquire a tablespace reference for writing. + @param avoid when these flags are set, nothing will be acquired + @return whether the file is writable */ + bool acquire_for_write() { return acquire(STOPPING_WRITES | CLOSING); } + /** Acquire another tablespace reference for I/O. */ inline void reacquire(); @@ -577,12 +588,12 @@ public: void clear_flush() { #if defined __GNUC__ && (defined __i386__ || defined __x86_64__) - static_assert(NEEDS_FSYNC == 1U << 29, "compatibility"); - __asm__ __volatile__("lock btrl $29, %0" : "+m" (n_pending)); + static_assert(NEEDS_FSYNC == 1U << 28, "compatibility"); + __asm__ __volatile__("lock btrl $28, %0" : "+m" (n_pending)); #elif defined _MSC_VER && (defined _M_IX86 || defined _M_X64) - static_assert(NEEDS_FSYNC == 1U << 29, "compatibility"); + static_assert(NEEDS_FSYNC == 1U << 28, "compatibility"); _interlockedbittestandreset(reinterpret_cast - (&n_pending), 29); + (&n_pending), 28); #else n_pending.fetch_and(~NEEDS_FSYNC, std::memory_order_release); #endif @@ -593,12 +604,12 @@ private: void clear_closing() { #if defined __GNUC__ && (defined __i386__ || defined __x86_64__) - static_assert(CLOSING == 1U << 30, "compatibility"); - __asm__ __volatile__("lock btrl $30, %0" : "+m" (n_pending)); + static_assert(CLOSING == 1U << 29, "compatibility"); + __asm__ __volatile__("lock btrl $29, %0" : "+m" (n_pending)); #elif defined _MSC_VER && (defined _M_IX86 || defined _M_X64) - static_assert(CLOSING == 1U << 30, "compatibility"); + static_assert(CLOSING == 1U << 29, "compatibility"); _interlockedbittestandreset(reinterpret_cast - (&n_pending), 30); + (&n_pending), 29); #else n_pending.fetch_and(~CLOSING, std::memory_order_relaxed); #endif @@ -609,8 +620,10 @@ private: public: /** @return whether close() of the file handle has been requested */ bool is_closing() const { return pending() & CLOSING; } - /** @return whether the tablespace is going to be dropped */ + /** @return whether the tablespace is about to be dropped */ bool is_stopping() const { return pending() & STOPPING; } + /** @return whether the tablespace is going to be dropped */ + bool is_stopping_writes() const { return pending() & STOPPING_WRITES; } /** @return number of pending operations */ bool is_ready_to_close() const { return (pending() & (PENDING | CLOSING)) == CLOSING; } @@ -619,7 +632,7 @@ public: /** @return whether fsync() or similar is needed, and the tablespace is not being dropped */ bool needs_flush_not_stopping() const - { return (pending() & (NEEDS_FSYNC | STOPPING)) == NEEDS_FSYNC; } + { return (pending() & (NEEDS_FSYNC | STOPPING_WRITES)) == NEEDS_FSYNC; } uint32_t referenced() const { return pending() & PENDING; } private: @@ -657,7 +670,7 @@ public: std::memory_order_relaxed)) { ut_ad(n & PENDING); - if (n & (NEEDS_FSYNC | STOPPING)) + if (n & (NEEDS_FSYNC | STOPPING_WRITES)) return false; } @@ -969,6 +982,11 @@ public: @return tablespace @retval nullptr if the tablespace is missing or inaccessible */ static fil_space_t *get(ulint id); + /** Acquire a tablespace reference for writing. + @param id tablespace identifier + @return tablespace + @retval nullptr if the tablespace is missing or inaccessible */ + static fil_space_t *get_for_write(ulint id); /** Add/remove the free page in the freed ranges list. @param[in] offset page number to be added @@ -1592,52 +1610,27 @@ inline void fil_space_t::reacquire() #endif /* SAFE_MUTEX */ } -/** Note that operations on the tablespace must stop. -@return whether the operations were already stopped */ -inline bool fil_space_t::set_stopping_check() -{ - mysql_mutex_assert_owner(&fil_system.mutex); -#if (defined __clang_major__ && __clang_major__ < 10) || defined __APPLE_CC__ - /* Only clang-10 introduced support for asm goto */ - return n_pending.fetch_or(STOPPING, std::memory_order_relaxed) & STOPPING; -#elif defined __GNUC__ && (defined __i386__ || defined __x86_64__) - static_assert(STOPPING == 1U << 31, "compatibility"); - __asm__ goto("lock btsl $31, %0\t\njnc %l1" : : "m" (n_pending) - : "cc", "memory" : not_stopped); - return true; -not_stopped: - return false; -#elif defined _MSC_VER && (defined _M_IX86 || defined _M_X64) - static_assert(STOPPING == 1U << 31, "compatibility"); - return _interlockedbittestandset(reinterpret_cast - (&n_pending), 31); -#else - return n_pending.fetch_or(STOPPING, std::memory_order_relaxed) & STOPPING; -#endif -} - -/** Note that operations on the tablespace must stop. -@return whether the operations were already stopped */ +/** Note that operations on the tablespace must stop. */ inline void fil_space_t::set_stopping() { mysql_mutex_assert_owner(&fil_system.mutex); #if defined __GNUC__ && (defined __i386__ || defined __x86_64__) - static_assert(STOPPING == 1U << 31, "compatibility"); - __asm__ __volatile__("lock btsl $31, %0" : "+m" (n_pending)); + static_assert(STOPPING_WRITES == 1U << 30, "compatibility"); + __asm__ __volatile__("lock btsl $30, %0" : "+m" (n_pending)); #elif defined _MSC_VER && (defined _M_IX86 || defined _M_X64) - static_assert(STOPPING == 1U << 31, "compatibility"); - _interlockedbittestandset(reinterpret_cast(&n_pending), 31); + static_assert(STOPPING_WRITES == 1U << 30, "compatibility"); + _interlockedbittestandset(reinterpret_cast(&n_pending), 30); #else - n_pending.fetch_or(STOPPING, std::memory_order_relaxed); + n_pending.fetch_or(STOPPING_WRITES, std::memory_order_relaxed); #endif } inline void fil_space_t::clear_stopping() { mysql_mutex_assert_owner(&fil_system.mutex); - static_assert(STOPPING == 1U << 31, "compatibility"); - ut_d(auto n=) n_pending.fetch_sub(STOPPING, std::memory_order_relaxed); - ut_ad(n & STOPPING); + static_assert(STOPPING_WRITES == 1U << 30, "compatibility"); + ut_d(auto n=) n_pending.fetch_sub(STOPPING_WRITES, std::memory_order_relaxed); + ut_ad((n & STOPPING) == STOPPING_WRITES); } /** Flush pending writes from the file system cache to the file. */ diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 5ce297ba5c9..dbd8ae76be0 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -95,14 +95,8 @@ struct mtr_t { /** Commit a mini-transaction that is deleting or renaming a file. @param space tablespace that is being renamed or deleted @param name new file name (nullptr=the file will be deleted) - @param detached_handle if detached_handle != nullptr and if space is detached - during the function execution the file handle if its - node will be set to OS_FILE_CLOSED, and the previous - value of the file handle will be assigned to the - address, pointed by detached_handle. @return whether the operation succeeded */ - ATTRIBUTE_COLD bool commit_file(fil_space_t &space, const char *name, - pfs_os_file_t *detached_handle= nullptr); + ATTRIBUTE_COLD bool commit_file(fil_space_t &space, const char *name); /** Commit a mini-transaction that did not modify any pages, but generated some redo log on a higher level, such as diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 2211ce01f8f..7ce54a9b04d 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -327,7 +327,7 @@ void mtr_t::commit_shrink(fil_space_t &space) mysql_mutex_lock(&fil_system.mutex); ut_ad(space.is_being_truncated); - ut_ad(space.is_stopping()); + ut_ad(space.is_stopping_writes()); space.clear_stopping(); space.is_being_truncated= false; mysql_mutex_unlock(&fil_system.mutex); @@ -340,14 +340,8 @@ void mtr_t::commit_shrink(fil_space_t &space) /** Commit a mini-transaction that is deleting or renaming a file. @param space tablespace that is being renamed or deleted @param name new file name (nullptr=the file will be deleted) -@param detached_handle if detached_handle != nullptr and if space is detached - during the function execution the file handle if its - node will be set to OS_FILE_CLOSED, and the previous - value of the file handle will be assigned to the - address, pointed by detached_handle. @return whether the operation succeeded */ -bool mtr_t::commit_file(fil_space_t &space, const char *name, - pfs_os_file_t *detached_handle) +bool mtr_t::commit_file(fil_space_t &space, const char *name) { ut_ad(is_active()); ut_ad(!is_inside_ibuf()); @@ -377,7 +371,7 @@ bool mtr_t::commit_file(fil_space_t &space, const char *name, log_write_and_flush(); char *old_name= space.chain.start->name; - bool success; + bool success= true; if (name) { @@ -391,37 +385,6 @@ bool mtr_t::commit_file(fil_space_t &space, const char *name, mysql_mutex_unlock(&fil_system.mutex); ut_free(old_name); } - else - { - /* Remove any additional files. */ - if (char *cfg_name= fil_make_filepath(old_name, - fil_space_t::name_type{}, CFG, - false)) - { - os_file_delete_if_exists(innodb_data_file_key, cfg_name, nullptr); - ut_free(cfg_name); - } - - if (FSP_FLAGS_HAS_DATA_DIR(space.flags)) - RemoteDatafile::delete_link_file(space.name()); - - /* Remove the directory entry. The file will actually be deleted - when our caller closes the handle. */ - os_file_delete(innodb_data_file_key, old_name); - - mysql_mutex_lock(&fil_system.mutex); - /* Sanity checks after reacquiring fil_system.mutex */ - ut_ad(&space == fil_space_get_by_id(space.id)); - ut_ad(!space.referenced()); - ut_ad(space.is_stopping()); - - pfs_os_file_t handle = fil_system.detach(&space, true); - if (detached_handle) - *detached_handle = handle; - mysql_mutex_unlock(&fil_system.mutex); - - success= true; - } mysql_mutex_unlock(&buf_pool.flush_list_mutex); release_resources(); From 5b53342a6a59ae1141b2a46467954fc3836f8e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 26 Oct 2023 15:10:53 +0300 Subject: [PATCH 132/158] MDEV-32588 InnoDB may hang when running out of buffer pool buf_flush_LRU_list_batch(): Do not skip pages that are actually clean but in buf_pool.flush_list due to the "lazy removal" optimization of commit 22b62edaedddb1cabd5b855cdd39a5e90a5695a2, but try to evict them. After acquiring buf_pool.flush_list_mutex, reread oldest_modification to ensure that the block still remains in buf_pool.flush_list. In addition to server hangs, this bug could also cause InnoDB: Failing assertion: list.count > 0 in invocations of UT_LIST_REMOVE(flush_list, ...). This fixes a regression that was caused by commit a55b951e6082a4ce9a1f2ed5ee176ea7dbbaf1f2 and possibly made more likely to hit due to commit aa719b5010c929132b4460b78113fbd07497d9c8. --- storage/innobase/buf/buf0flu.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 0273837eb1a..52ef5c2f9ac 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1304,16 +1304,14 @@ static void buf_flush_LRU_list_batch(ulint max, bool evict, ut_ad(state >= buf_page_t::FREED); ut_ad(bpage->in_LRU_list); - switch (bpage->oldest_modification()) { - case 0: + if (!bpage->oldest_modification()) + { evict: if (state != buf_page_t::FREED && (state >= buf_page_t::READ_FIX || (~buf_page_t::LRU_MASK & state))) continue; buf_LRU_free_page(bpage, true); ++n->evicted; - /* fall through */ - case 1: if (UNIV_LIKELY(scanned & 31)) continue; mysql_mutex_unlock(&buf_pool.mutex); @@ -1329,7 +1327,11 @@ static void buf_flush_LRU_list_batch(ulint max, bool evict, switch (bpage->oldest_modification()) { case 1: mysql_mutex_lock(&buf_pool.flush_list_mutex); - buf_pool.delete_from_flush_list(bpage); + if (ut_d(lsn_t lsn=) bpage->oldest_modification()) + { + ut_ad(lsn == 1); /* It must be clean while we hold bpage->lock */ + buf_pool.delete_from_flush_list(bpage); + } mysql_mutex_unlock(&buf_pool.flush_list_mutex); /* fall through */ case 0: From 9c43343213d6f972a7c32a956a09f27afa96ed11 Mon Sep 17 00:00:00 2001 From: Andrei Date: Thu, 26 Oct 2023 20:24:44 +0300 Subject: [PATCH 133/158] MDEV-32365 detailize the semisync replication magic number error Semisync ack (master side) receiver thread is made to report details of faced errors. In case of 'magic byte' error, a hexdump of the received packet is always (level) NOTEd into the error log. In other cases an exact server level error is print out as a warning (as it may not be critical) under log_warnings > 2. An MTR test added for the magic byte error. For others existing mtr tests cover that, provided log_warnings > 2 is set. --- .../rpl/r/rpl_semi_sync_shutdown_await_ack.result | 1 + .../rpl/r/rpl_semi_sync_slave_reply_fail.result | 7 +++++++ .../rpl/t/rpl_semi_sync_shutdown_await_ack.test | 1 + .../rpl/t/rpl_semi_sync_slave_reply_fail.test | 10 ++++++++++ sql/semisync_master.cc | 13 +++++++++++++ sql/semisync_master_ack_receiver.cc | 14 ++++++++++++-- 6 files changed, 44 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result b/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result index 719b61b796b..394a7acad41 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result @@ -8,6 +8,7 @@ connection server_1; # Slaves which simulate an error will produce a timeout on the primary call mtr.add_suppression("Timeout waiting"); call mtr.add_suppression("did not exit"); +call mtr.add_suppression("Got an error reading communication packets"); # Suppress slave errors related to the simulated error connection server_2; call mtr.add_suppression("reply failed"); diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_slave_reply_fail.result b/mysql-test/suite/rpl/r/rpl_semi_sync_slave_reply_fail.result index 6b39b296cdf..f026a1c9db4 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_slave_reply_fail.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_slave_reply_fail.result @@ -31,6 +31,13 @@ connection slave; # Compare the tables on master and slave. include/diff_tables.inc [master:t1, slave:t1] connection master; +set statement sql_log_bin=0 for call mtr.add_suppression("Read semi-sync reply magic number error"); +SET @save_debug_master= @@global.debug; +SET GLOBAL debug_dbug="+d,semisync_corrupt_magic"; +insert into t1 values (11); +connection slave; +connection master; +SET GLOBAL debug_dbug= @save_debug_master; drop table t1; connection slave; set global rpl_semi_sync_slave_enabled = OFF; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test index 2ee7d0aa052..6c088c571f2 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test @@ -67,6 +67,7 @@ --echo # Slaves which simulate an error will produce a timeout on the primary call mtr.add_suppression("Timeout waiting"); call mtr.add_suppression("did not exit"); +call mtr.add_suppression("Got an error reading communication packets"); --let $sav_master_timeout= `SELECT @@global.rpl_semi_sync_master_timeout` --let $sav_enabled_master= `SELECT @@GLOBAL.rpl_semi_sync_master_enabled` diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test index f0eb474f00e..948537997dd 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test @@ -77,6 +77,16 @@ insert into t1 values (10); --source include/diff_tables.inc --connection master +set statement sql_log_bin=0 for call mtr.add_suppression("Read semi-sync reply magic number error"); +SET @save_debug_master= @@global.debug; +SET GLOBAL debug_dbug="+d,semisync_corrupt_magic"; +insert into t1 values (11); + +--sync_slave_with_master + +--connection master +SET GLOBAL debug_dbug= @save_debug_master; + drop table t1; --sync_slave_with_master set global rpl_semi_sync_slave_enabled = OFF; diff --git a/sql/semisync_master.cc b/sql/semisync_master.cc index 63a50539e50..62e1d37f590 100644 --- a/sql/semisync_master.cc +++ b/sql/semisync_master.cc @@ -18,6 +18,8 @@ #include #include "semisync_master.h" +#include +#include #define TIME_THOUSAND 1000 #define TIME_MILLION 1000000 @@ -562,6 +564,8 @@ int Repl_semi_sync_master::report_reply_packet(uint32 server_id, DBUG_ENTER("Repl_semi_sync_master::report_reply_packet"); + DBUG_EXECUTE_IF("semisync_corrupt_magic", + const_cast(packet)[REPLY_MAGIC_NUM_OFFSET]= 0;); if (unlikely(packet[REPLY_MAGIC_NUM_OFFSET] != Repl_semi_sync_master::k_packet_magic_num)) { @@ -593,9 +597,18 @@ int Repl_semi_sync_master::report_reply_packet(uint32 server_id, rpl_semi_sync_master_get_ack++; report_reply_binlog(server_id, log_file_name, log_file_pos); + result= 0; l_end: + if (result == -1) + { + char buf[256]; + octet2hex(buf, (const char*) packet, std::min(static_cast(sizeof(buf)-1), + packet_len)); + sql_print_information("First bytes of the packet from semisync slave " + "server-id %d: %s", server_id, buf); + } DBUG_RETURN(result); } diff --git a/sql/semisync_master_ack_receiver.cc b/sql/semisync_master_ack_receiver.cc index b24d6452480..e78bd77b9a7 100644 --- a/sql/semisync_master_ack_receiver.cc +++ b/sql/semisync_master_ack_receiver.cc @@ -277,8 +277,18 @@ void Ack_receiver::run() if (likely(len != packet_error)) repl_semisync_master.report_reply_packet(slave->server_id(), net.read_pos, len); - else if (net.last_errno == ER_NET_READ_ERROR) - listener.clear_socket_info(slave); + else + { + if (net.last_errno == ER_NET_READ_ERROR) + { + listener.clear_socket_info(slave); + } + if (net.last_errno > 0 && global_system_variables.log_warnings > 2) + sql_print_warning("Semisync ack receiver got error %d \"%s\" " + "from slave server-id %d", + net.last_errno, ER_DEFAULT(net.last_errno), + slave->server_id()); + } } } mysql_mutex_unlock(&m_mutex); From c9f87b881315af80e73da3b0b74b4ca36f1cab18 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 26 Oct 2023 11:00:26 +0200 Subject: [PATCH 134/158] MDEV-32586 incorrect error about cyclic reference about JSON type virtual column remove the hack where NO_DEFAULT_VALUE_FLAG was temporarily removed from a field to initialize DEFAULT() functions in CHECK constraints while disabling self-reference field checks. Instead, initialize DEFAULT() functions in CHECK explicitly, don't call check_field_expression_processor() for CHECK at all. --- mysql-test/main/check_constraint.result | 10 ++++++++++ mysql-test/main/check_constraint.test | 13 +++++++++++++ sql/item.cc | 5 +++++ sql/item.h | 2 ++ sql/table.cc | 15 +++++---------- 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/mysql-test/main/check_constraint.result b/mysql-test/main/check_constraint.result index 01a71bf36a5..e3986dcf75b 100644 --- a/mysql-test/main/check_constraint.result +++ b/mysql-test/main/check_constraint.result @@ -308,5 +308,15 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; # +# MDEV-32586 incorrect error about cyclic reference about JSON type virtual column +# +create table t1 (a int, b json as (a)); +drop table t1; +create table t1 (a int, b int as (a) check (b > 0)); +insert t1 (a) values (1); +insert t1 (a) values (-1); +ERROR 23000: CONSTRAINT `t1.b` failed for `test`.`t1` +drop table t1; +# # End of 10.4 tests # diff --git a/mysql-test/main/check_constraint.test b/mysql-test/main/check_constraint.test index cfdddcab3a1..e12468e9013 100644 --- a/mysql-test/main/check_constraint.test +++ b/mysql-test/main/check_constraint.test @@ -231,6 +231,19 @@ alter table t1 force; show create table t1; drop table t1; +--echo # +--echo # MDEV-32586 incorrect error about cyclic reference about JSON type virtual column +--echo # + +create table t1 (a int, b json as (a)); +drop table t1; + +create table t1 (a int, b int as (a) check (b > 0)); +insert t1 (a) values (1); +--error ER_CONSTRAINT_FAILED +insert t1 (a) values (-1); +drop table t1; + --echo # --echo # End of 10.4 tests --echo # diff --git a/sql/item.cc b/sql/item.cc index 34272156aad..723552e6b35 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9412,6 +9412,11 @@ bool Item_default_value::eq(const Item *item, bool binary_cmp) const bool Item_default_value::check_field_expression_processor(void *) +{ + return Item_default_value::update_func_default_processor(0); +} + +bool Item_default_value::update_func_default_processor(void *) { field->default_value= ((Item_field *)(arg->real_item()))->field->default_value; return 0; diff --git a/sql/item.h b/sql/item.h index d04d77da666..cefd23df0f1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2080,6 +2080,7 @@ public: } virtual bool check_field_expression_processor(void *arg) { return 0; } virtual bool check_func_default_processor(void *arg) { return 0; } + virtual bool update_func_default_processor(void *arg) { return 0; } /* Check if an expression value has allowed arguments, like DATE/DATETIME for date functions. Also used by partitioning code to reject @@ -6544,6 +6545,7 @@ public: bool update_vcol_processor(void *arg) { return 0; } bool check_field_expression_processor(void *arg); bool check_func_default_processor(void *arg) { return true; } + bool update_func_default_processor(void *arg); bool register_field_in_read_map(void *arg); bool walk(Item_processor processor, bool walk_subquery, void *args) diff --git a/sql/table.cc b/sql/table.cc index e6684cd1c72..eafeb6185a3 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1074,19 +1074,9 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, return vcol && vcol->expr->walk(&Item::check_field_expression_processor, 0, field); } - static bool check_constraint(Field *field, Virtual_column_info *vcol) - { - uint32 flags= field->flags; - /* Check constraints can refer it itself */ - field->flags|= NO_DEFAULT_VALUE_FLAG; - const bool res= check(field, vcol); - field->flags= flags; - return res; - } static bool check(Field *field) { if (check(field, field->vcol_info) || - check_constraint(field, field->check_constraint) || check(field, field->default_value)) return true; return false; @@ -1300,11 +1290,16 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, /* Check that expressions aren't referring to not yet initialized fields */ for (field_ptr= table->field; *field_ptr; field_ptr++) + { if (check_vcol_forward_refs::check(*field_ptr)) { *error_reported= true; goto end; } + if ((*field_ptr)->check_constraint) + (*field_ptr)->check_constraint->expr-> + walk(&Item::update_func_default_processor, 0, *field_ptr); + } table->find_constraint_correlated_indexes(); From ef7fc586aea1048bc5526192158a8e8e935ddd1a Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Thu, 28 Sep 2023 15:11:07 +0300 Subject: [PATCH 135/158] MDEV-32282: Galera node remains paused after interleaving FTWRLs After two concurrent FTWRL/UNLOCK TABLES, the node stays in paused state and the following CREATE TABLE fails with ER_UNKNOWN_COM_ERROR (1047): Aborting TOI: Replication paused on node for FTWRL/BACKUP STAGE. The cause is the use of global `wsrep_locked_seqno` to determine if the node should be resumed on UNLOCK TABLES. In some executions the `wsrep_locked_seqno` is cleared by the first UNLOCK TABLES after the second FTWRL gets past `make_global_read_lock_block_commit()`. As a fix, use `thd->wsrep_desynced_backup_stage` to determine if the thread should resume the node on UNLOCK TABLES. Add MTR test galera.galera_ftwrl_concurrent to reproduce the race. The test contains also cases for BACKUP STAGE which uses similar mechanism for desyncing and pausing the node. Signed-off-by: Julius Goryavsky --- .../galera/r/galera_ftwrl_concurrent.result | 122 +++++++++++ .../galera/t/galera_ftwrl_concurrent.test | 193 ++++++++++++++++++ sql/backup.cc | 2 + sql/lock.cc | 7 +- 4 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera/r/galera_ftwrl_concurrent.result create mode 100644 mysql-test/suite/galera/t/galera_ftwrl_concurrent.test diff --git a/mysql-test/suite/galera/r/galera_ftwrl_concurrent.result b/mysql-test/suite/galera/r/galera_ftwrl_concurrent.result new file mode 100644 index 00000000000..d7b396bf6a5 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ftwrl_concurrent.result @@ -0,0 +1,122 @@ +connection node_2; +connection node_1; +connect node_1_ctrl, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET SESSION wsrep_sync_wait=0; +# +# Case 1: FTWRL +# +connection node_1; +SET SESSION wsrep_sync_wait=0; +FLUSH TABLES WITH READ LOCK; +SHOW STATUS LIKE 'wsrep_local_state_comment'; +Variable_name Value +wsrep_local_state_comment Donor/Desynced +SET SESSION debug_sync = "wsrep_unlock_global_read_lock_after_resume_and_resync SIGNAL unlock_ready WAIT_FOR unlock_continue"; +UNLOCK TABLES; +connection node_1_ctrl; +SET debug_sync = "now WAIT_FOR unlock_ready"; +connect node_1_a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1_a; +SET SESSION debug_sync = "wsrep_global_read_lock_block_commit_after_pause SIGNAL lock_ready WAIT_FOR lock_continue"; +FLUSH TABLES WITH READ LOCK; +connection node_1_ctrl; +SET debug_sync = "now WAIT_FOR lock_ready"; +SET debug_sync = "now SIGNAL unlock_continue"; +connection node_1; +connection node_1_ctrl; +SET debug_sync = "now SIGNAL lock_continue"; +connection node_1_a; +UNLOCK TABLES; +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +DROP TABLE t1; +connection node_1_ctrl; +SET debug_sync = "RESET"; +# +# Case 2: BACKUP STAGE +# +connection node_1; +SET SESSION wsrep_sync_wait=0; +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +SHOW STATUS LIKE 'wsrep_local_state_comment'; +Variable_name Value +wsrep_local_state_comment Donor/Desynced +SET SESSION debug_sync = "wsrep_backup_stage_after_resume_and_resync SIGNAL resume_and_resync_ready WAIT_FOR resume_and_resync_continue"; +BACKUP STAGE END; +connection node_1_ctrl; +SET debug_sync = "now WAIT_FOR resume_and_resync_ready"; +connection node_1_a; +BACKUP STAGE START; +SET SESSION debug_sync = "wsrep_backup_stage_after_desync_and_pause SIGNAL desync_and_pause_ready WAIT_FOR desync_and_pause_continue"; +BACKUP STAGE BLOCK_DDL; +connection node_1_ctrl; +SET debug_sync = "now WAIT_FOR desync_and_pause_ready"; +SET debug_sync = "now SIGNAL resume_and_resync_continue"; +connection node_1; +connection node_1_ctrl; +SET debug_sync = "now SIGNAL desync_and_pause_continue"; +connection node_1_a; +BACKUP STAGE END; +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +DROP TABLE t1; +connection node_1_ctrl; +SET debug_sync = "RESET"; +# +# Case 3: FTWRL first, BACKUP STAGE second +# +connection node_1; +SET SESSION wsrep_sync_wait=0; +SET SESSION wsrep_sync_wait=0; +FLUSH TABLES WITH READ LOCK; +SHOW STATUS LIKE 'wsrep_local_state_comment'; +Variable_name Value +wsrep_local_state_comment Donor/Desynced +SET SESSION debug_sync = "wsrep_unlock_global_read_lock_after_resume_and_resync SIGNAL unlock_ready WAIT_FOR unlock_continue"; +UNLOCK TABLES; +connection node_1_ctrl; +SET debug_sync = "now WAIT_FOR unlock_ready"; +connection node_1_a; +BACKUP STAGE START; +SET SESSION debug_sync = "wsrep_backup_stage_after_desync_and_pause SIGNAL desync_and_pause_ready WAIT_FOR desync_and_pause_continue"; +BACKUP STAGE BLOCK_DDL; +connection node_1_ctrl; +SET debug_sync = "now WAIT_FOR desync_and_pause_ready"; +SET debug_sync = "now SIGNAL unlock_continue"; +connection node_1; +connection node_1_ctrl; +SET debug_sync = "now SIGNAL desync_and_pause_continue"; +connection node_1_a; +BACKUP STAGE END; +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +DROP TABLE t1; +connection node_1_ctrl; +SET debug_sync = "RESET"; +# +# Case 4: BACKUP STAGE first, then FTWRL +# +connection node_1; +SET SESSION wsrep_sync_wait=0; +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +SHOW STATUS LIKE 'wsrep_local_state_comment'; +Variable_name Value +wsrep_local_state_comment Donor/Desynced +SET SESSION debug_sync = "wsrep_backup_stage_after_resume_and_resync SIGNAL resume_and_resync_ready WAIT_FOR resume_and_resync_continue"; +BACKUP STAGE END; +connection node_1_ctrl; +SET debug_sync = "now WAIT_FOR resume_and_resync_ready"; +connection node_1_a; +SET SESSION debug_sync = "wsrep_global_read_lock_block_commit_after_pause SIGNAL lock_ready WAIT_FOR lock_continue"; +FLUSH TABLES WITH READ LOCK; +connection node_1_ctrl; +SET debug_sync = "now WAIT_FOR lock_ready"; +SET debug_sync = "now SIGNAL resume_and_resync_continue"; +connection node_1; +connection node_1_ctrl; +SET debug_sync = "now SIGNAL lock_continue"; +connection node_1_a; +UNLOCK TABLES; +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +DROP TABLE t1; +connection node_1_ctrl; +SET debug_sync = "RESET"; diff --git a/mysql-test/suite/galera/t/galera_ftwrl_concurrent.test b/mysql-test/suite/galera/t/galera_ftwrl_concurrent.test new file mode 100644 index 00000000000..724160835d8 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ftwrl_concurrent.test @@ -0,0 +1,193 @@ +# +# MDEV-32282 +# +# A node remains in paused state after two interleaving FTWRLs, +# and the following CREATE TABLE fails with +# +# ER_UNKNOWN_COM_ERROR (1047): Aborting TOI: Replication paused on +# node for FTWRL/BACKUP STAGE. +# +# node_1 node_1_a +# ---------------------------------------------------------------------- +# FTWRL +# UNLOCK TABLES wait after resume_and_resync() +# FTWRL wait after desync_and_pause() +# continue +# continue +# UNLOCK TABLES +# CREATE TABLE fails +# +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc + +# Connection to control sync points +--connect node_1_ctrl, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET SESSION wsrep_sync_wait=0; + +--echo # +--echo # Case 1: FTWRL +--echo # + +--connection node_1 +SET SESSION wsrep_sync_wait=0; +FLUSH TABLES WITH READ LOCK; +SHOW STATUS LIKE 'wsrep_local_state_comment'; +SET SESSION debug_sync = "wsrep_unlock_global_read_lock_after_resume_and_resync SIGNAL unlock_ready WAIT_FOR unlock_continue"; +--send UNLOCK TABLES + +--connection node_1_ctrl +SET debug_sync = "now WAIT_FOR unlock_ready"; + +--connect node_1_a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1_a +SET SESSION debug_sync = "wsrep_global_read_lock_block_commit_after_pause SIGNAL lock_ready WAIT_FOR lock_continue"; +--send FLUSH TABLES WITH READ LOCK + +--connection node_1_ctrl +SET debug_sync = "now WAIT_FOR lock_ready"; +SET debug_sync = "now SIGNAL unlock_continue"; + +--connection node_1 +--reap + +--connection node_1_ctrl +SET debug_sync = "now SIGNAL lock_continue"; + +--connection node_1_a +--reap + +UNLOCK TABLES; +--let $wait_condition = SELECT VARIABLE_VALUE = "Synced" FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = "wsrep_local_state_comment" +--source include/wait_condition.inc + +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +DROP TABLE t1; +--connection node_1_ctrl +SET debug_sync = "RESET"; + +--echo # +--echo # Case 2: BACKUP STAGE +--echo # +# Although BACKUP STAGE was not involved in MDEV-32282, add a testcase +# as it uses similar mechanism to pause and desync the node. +# + +--connection node_1 +SET SESSION wsrep_sync_wait=0; +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +SHOW STATUS LIKE 'wsrep_local_state_comment'; +SET SESSION debug_sync = "wsrep_backup_stage_after_resume_and_resync SIGNAL resume_and_resync_ready WAIT_FOR resume_and_resync_continue"; +--send BACKUP STAGE END + +--connection node_1_ctrl +SET debug_sync = "now WAIT_FOR resume_and_resync_ready"; + +--connection node_1_a +BACKUP STAGE START; +SET SESSION debug_sync = "wsrep_backup_stage_after_desync_and_pause SIGNAL desync_and_pause_ready WAIT_FOR desync_and_pause_continue"; +--send BACKUP STAGE BLOCK_DDL + +--connection node_1_ctrl +SET debug_sync = "now WAIT_FOR desync_and_pause_ready"; +SET debug_sync = "now SIGNAL resume_and_resync_continue"; + +--connection node_1 +--reap + +--connection node_1_ctrl +SET debug_sync = "now SIGNAL desync_and_pause_continue"; + +--connection node_1_a +--reap +BACKUP STAGE END; +--let $wait_condition = SELECT VARIABLE_VALUE = "Synced" FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = "wsrep_local_state_comment" +--source include/wait_condition.inc + +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +DROP TABLE t1; + +--connection node_1_ctrl +SET debug_sync = "RESET"; + +--echo # +--echo # Case 3: FTWRL first, BACKUP STAGE second +--echo # + +--connection node_1 +SET SESSION wsrep_sync_wait=0; +SET SESSION wsrep_sync_wait=0; +FLUSH TABLES WITH READ LOCK; +SHOW STATUS LIKE 'wsrep_local_state_comment'; +SET SESSION debug_sync = "wsrep_unlock_global_read_lock_after_resume_and_resync SIGNAL unlock_ready WAIT_FOR unlock_continue"; +--send UNLOCK TABLES + +--connection node_1_ctrl +SET debug_sync = "now WAIT_FOR unlock_ready"; + +--connection node_1_a +BACKUP STAGE START; +SET SESSION debug_sync = "wsrep_backup_stage_after_desync_and_pause SIGNAL desync_and_pause_ready WAIT_FOR desync_and_pause_continue"; +--send BACKUP STAGE BLOCK_DDL + +--connection node_1_ctrl +SET debug_sync = "now WAIT_FOR desync_and_pause_ready"; +SET debug_sync = "now SIGNAL unlock_continue"; + +--connection node_1 +--reap + +--connection node_1_ctrl +SET debug_sync = "now SIGNAL desync_and_pause_continue"; + +--connection node_1_a +--reap +BACKUP STAGE END; +--let $wait_condition = SELECT VARIABLE_VALUE = "Synced" FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = "wsrep_local_state_comment" +--source include/wait_condition.inc + +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +DROP TABLE t1; + +--connection node_1_ctrl +SET debug_sync = "RESET"; + +--echo # +--echo # Case 4: BACKUP STAGE first, then FTWRL +--echo # +--connection node_1 +SET SESSION wsrep_sync_wait=0; +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +SHOW STATUS LIKE 'wsrep_local_state_comment'; +SET SESSION debug_sync = "wsrep_backup_stage_after_resume_and_resync SIGNAL resume_and_resync_ready WAIT_FOR resume_and_resync_continue"; +--send BACKUP STAGE END + +--connection node_1_ctrl +SET debug_sync = "now WAIT_FOR resume_and_resync_ready"; +--connection node_1_a +SET SESSION debug_sync = "wsrep_global_read_lock_block_commit_after_pause SIGNAL lock_ready WAIT_FOR lock_continue"; +--send FLUSH TABLES WITH READ LOCK + +--connection node_1_ctrl +SET debug_sync = "now WAIT_FOR lock_ready"; +SET debug_sync = "now SIGNAL resume_and_resync_continue"; + +--connection node_1 +--reap + +--connection node_1_ctrl +SET debug_sync = "now SIGNAL lock_continue"; + +--connection node_1_a +--reap + +UNLOCK TABLES; +--let $wait_condition = SELECT VARIABLE_VALUE = "Synced" FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = "wsrep_local_state_comment" +--source include/wait_condition.inc + +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +DROP TABLE t1; +--connection node_1_ctrl +SET debug_sync = "RESET"; diff --git a/sql/backup.cc b/sql/backup.cc index d45c18a3cdf..1f9b4035ad5 100644 --- a/sql/backup.cc +++ b/sql/backup.cc @@ -268,6 +268,7 @@ static bool backup_block_ddl(THD *thd) if (server_state.desync_and_pause().is_undefined()) { DBUG_RETURN(1); } + DEBUG_SYNC(thd, "wsrep_backup_stage_after_desync_and_pause"); thd->wsrep_desynced_backup_stage= true; } #endif /* WITH_WSREP */ @@ -341,6 +342,7 @@ bool backup_end(THD *thd) Wsrep_server_state &server_state= Wsrep_server_state::instance(); server_state.resume_and_resync(); thd->wsrep_desynced_backup_stage= false; + DEBUG_SYNC(thd, "wsrep_backup_stage_after_resume_and_resync"); } #endif /* WITH_WSREP */ } diff --git a/sql/lock.cc b/sql/lock.cc index 6483519e4e0..d3d837fd5f3 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -1106,7 +1106,7 @@ void Global_read_lock::unlock_global_read_lock(THD *thd) #ifdef WITH_WSREP if (m_state == GRL_ACQUIRED_AND_BLOCKS_COMMIT && - wsrep_locked_seqno != WSREP_SEQNO_UNDEFINED) + thd->wsrep_desynced_backup_stage) { Wsrep_server_state& server_state= Wsrep_server_state::instance(); if (server_state.state() == Wsrep_server_state::s_donor || @@ -1120,8 +1120,10 @@ void Global_read_lock::unlock_global_read_lock(THD *thd) server_state.state() == Wsrep_server_state::s_synced) { server_state.resume_and_resync(); + DEBUG_SYNC(thd, "wsrep_unlock_global_read_lock_after_resume_and_resync"); wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; } + thd->wsrep_desynced_backup_stage= false; } #endif /* WITH_WSREP */ @@ -1178,11 +1180,13 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) server_state.state() != Wsrep_server_state::s_synced)) { paused_seqno= server_state.pause(); + thd->wsrep_desynced_backup_stage= true; } else if (WSREP_NNULL(thd) && server_state.state() == Wsrep_server_state::s_synced) { paused_seqno= server_state.desync_and_pause(); + thd->wsrep_desynced_backup_stage= true; } else { @@ -1193,6 +1197,7 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) { wsrep_locked_seqno= paused_seqno.get(); } + DEBUG_SYNC(thd, "wsrep_global_read_lock_block_commit_after_pause"); #endif /* WITH_WSREP */ DBUG_RETURN(FALSE); } From 728bca44e892d70f2cbc2746b89389d561c0e710 Mon Sep 17 00:00:00 2001 From: Andrei Date: Fri, 27 Oct 2023 11:39:58 +0300 Subject: [PATCH 136/158] MDEV-32593 Assertion failure upon CREATE SEQUENCE A recently added by MDEV-32593 assert conditions are corrected. --- mysql-test/suite/rpl/r/rpl_parallel_seq.result | 5 ++++- mysql-test/suite/rpl/t/rpl_parallel_seq.test | 7 ++++++- sql/log_event.cc | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_parallel_seq.result b/mysql-test/suite/rpl/r/rpl_parallel_seq.result index fdb6bfef724..2746aaaf8a5 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_seq.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_seq.result @@ -121,7 +121,10 @@ SET @@global.debug_dbug = ""; SET @@global.gtid_strict_mode=0; include/start_slave.inc connection master; -DROP SEQUENCE s2,s3; +BEGIN; +INSERT INTO ti SET a=32593; +CREATE SEQUENCE s4; +DROP SEQUENCE s2,s3,s4; DROP TABLE ti; connection slave; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_seq.test b/mysql-test/suite/rpl/t/rpl_parallel_seq.test index ecc29de779b..4c4e8297587 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_seq.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_seq.test @@ -185,7 +185,12 @@ SET debug_sync = RESET; --source include/start_slave.inc --connection master -DROP SEQUENCE s2,s3; +# MDEV-32593 Assertion failure upon CREATE SEQUENCE +BEGIN; +INSERT INTO ti SET a=32593; +CREATE SEQUENCE s4; + +DROP SEQUENCE s2,s3,s4; DROP TABLE ti; --sync_slave_with_master diff --git a/sql/log_event.cc b/sql/log_event.cc index 7c791a4b6f5..10bf569d636 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8025,7 +8025,7 @@ Gtid_log_event::Gtid_log_event(THD *thd_arg, uint64 seq_no_arg, flags2|= (thd_arg->rgi_slave->gtid_ev_flags2 & (FL_DDL|FL_WAITED)); DBUG_ASSERT(thd_arg->lex->sql_command != SQLCOM_CREATE_SEQUENCE || - (flags2 & FL_DDL)); + (flags2 & FL_DDL) || thd_arg->in_multi_stmt_transaction_mode()); } From 15ae97b1c2c14f1263cdc853673c4129625323de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 27 Oct 2023 13:13:49 +0300 Subject: [PATCH 137/158] MDEV-32578 row_merge_fts_doc_tokenize() handles parser plugin inconsistently When mysql/mysql-server@0c954c2289a75d90d1088356b1092437ebf45a1d added a plugin interface for FULLTEXT INDEX tokenization to MySQL 5.7, fts_tokenize_ctx::processed_len got a second meaning, which is only partly implemented in row_merge_fts_doc_tokenize(). This inconsistency could cause a crash when using FULLTEXT...WITH PARSER. A test case that would crash MySQL 8.0 when using an n-gram parser and single-character words would fail to crash in MySQL 5.7, because the buf_full condition in row_merge_fts_doc_tokenize() was not met. This change is inspired by mysql/mysql-server@38e9a0779aeea2d197c727e306a910c56b26a47c that appeared in MySQL 5.7.44. --- storage/innobase/include/row0ftsort.h | 6 +++++- storage/innobase/row/row0ftsort.cc | 11 ++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/storage/innobase/include/row0ftsort.h b/storage/innobase/include/row0ftsort.h index 0189bb7a4ff..fec5226c593 100644 --- a/storage/innobase/include/row0ftsort.h +++ b/storage/innobase/include/row0ftsort.h @@ -108,7 +108,10 @@ typedef UT_LIST_BASE_NODE_T(row_fts_token_t) fts_token_list_t; /** Structure stores information from string tokenization operation */ struct fts_tokenize_ctx { - ulint processed_len; /*!< processed string length */ + /** the processed string length in bytes + (when using the built-in tokenizer), + or the number of row_merge_fts_doc_tokenize_by_parser() calls */ + ulint processed_len; ulint init_pos; /*!< doc start position */ ulint buf_used; /*!< the sort buffer (ID) when tokenization stops, which @@ -119,6 +122,7 @@ struct fts_tokenize_ctx { ib_rbt_t* cached_stopword;/*!< in: stopword list */ dfield_t sort_field[FTS_NUM_FIELDS_SORT]; /*!< in: sort field */ + /** parsed tokens (when using an external parser) */ fts_token_list_t fts_token_list; fts_tokenize_ctx() : diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 8d1dbad22cb..53148647442 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -506,7 +506,10 @@ row_merge_fts_doc_tokenize( /* Tokenize the data and add each word string, its corresponding doc id and position to sort buffer */ - while (t_ctx->processed_len < doc->text.f_len) { + while (parser + ? (!t_ctx->processed_len + || UT_LIST_GET_LEN(t_ctx->fts_token_list)) + : t_ctx->processed_len < doc->text.f_len) { ulint idx = 0; ulint cur_len; doc_id_t write_doc_id; @@ -847,7 +850,8 @@ loop: /* Not yet finish processing the "doc" on hand, continue processing it */ ut_ad(doc.text.f_str); - ut_ad(t_ctx.processed_len < doc.text.f_len); + ut_ad(buf[0]->index->parser + || t_ctx.processed_len < doc.text.f_len); } processed = row_merge_fts_doc_tokenize( @@ -857,7 +861,8 @@ loop: /* Current sort buffer full, need to recycle */ if (!processed) { - ut_ad(t_ctx.processed_len < doc.text.f_len); + ut_ad(buf[0]->index->parser + || t_ctx.processed_len < doc.text.f_len); ut_ad(t_ctx.rows_added[t_ctx.buf_used]); break; } From 11abc2191149a76702ef5d919e2e8940e47e5ef9 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 27 Oct 2023 15:14:42 +0200 Subject: [PATCH 138/158] fixed typo --- mysql-test/main/mdl.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/mdl.test b/mysql-test/main/mdl.test index 5d794e2b9d9..d55d2c81f9b 100644 --- a/mysql-test/main/mdl.test +++ b/mysql-test/main/mdl.test @@ -84,7 +84,7 @@ DROP TABLE t1,t3; --echo # --echo # MDEV-28820 MyISAM wrong server status flags --echo # ---disable_service_connection +--disable_view_protocol # MyISAM alone doesn't start a transaction or takes transactional MDL create table t1 (a int); set autocommit=0; @@ -120,7 +120,7 @@ disconnect foo; connection default; set autocommit=default; drop table t2; ---enable_service_connection +--enable_view_protocol --echo # --echo # End of 10.4 tests From 954a6decd415c31856a32e3b5e75fd2504285c4d Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Thu, 19 Oct 2023 12:09:41 -0700 Subject: [PATCH 139/158] MDEV-32351 Significant slowdown for query with many outer joins This patch fixes a performance regression introduced in the patch for the bug MDEV-21104. The performance regression could affect queries for which join buffer was used for an outer join such that its on expression from which a conjunctive condition depended only on outer tables can be extracted. If the number of records in the join buffer for which this condition was false greatly exceeded the number of other records the slowdown could be significant. If there is a conjunctive condition extracted from the ON expression depending only on outer tables this condition is evaluated when interesting fields of each survived record of outer tables are put into the join buffer. Each such set of fields for any join operation is supplied with a match flag field used to generate null complemented rows. If the result of the evaluation of the condition is false the flag is set to MATCH_IMPOSSIBLE. When looking in the join buffer for records matching a record of the right operand of the outer join operation the records with such flags are not needed to be unpacked into record buffers for evaluation of on expressions. The patch for MDEV-21104 fixing some problem of wrong results when 'not exists' optimization by mistake broke the code that allowed to ignore records with the match flag set to MATCH_IMPOSSIBLE when looking for matching records. As a result such records were unpacked for each record of the right operand of the outer join operation. This caused significant execution penalty in some cases. One of the test cases added in the patch can be used only for demonstration of the restored performance for the reported query. The second test case is needed to demonstrate the validity of the fix. --- mysql-test/main/join_cache.result | 126 ++++++++++++++++++++++++++++++ mysql-test/main/join_cache.test | 58 ++++++++++++++ sql/sql_join_cache.cc | 26 +++--- sql/sql_join_cache.h | 4 + 4 files changed, 202 insertions(+), 12 deletions(-) diff --git a/mysql-test/main/join_cache.result b/mysql-test/main/join_cache.result index 92c04bb002b..c07a8b1bf6b 100644 --- a/mysql-test/main/join_cache.result +++ b/mysql-test/main/join_cache.result @@ -6270,5 +6270,131 @@ ERROR HY001: Could not create a join buffer. Please check and adjust the value o SET JOIN_buffer_size=16384; SELECT * FROM information_schema.statistics JOIN information_schema.COLUMNS USING (table_name,column_name); # +# MDEV-32351: Join buffer used for outer join with ON condition +# depending only on outer tables +# +CREATE TABLE t1 (b int NOT NULL, PRIMARY KEY (b)) ENGINE=MYISAM; +INSERT INTO t1 select seq from seq_1_to_10000; +CREATE TABLE t2 (b int NOT NULL, d varchar(255), KEY (b)) ENGINE=MYISAM ; +INSERT INTO t2 VALUES (1,1),(2,2),(3,3); +CREATE TABLE t3 (c int NOT NULL, PRIMARY KEY (c)) ENGINE=MYISAM ; +INSERT INTO t3 select seq from seq_1_to_3000; +CREATE TABLE t4 (c int NOT NULL, PRIMARY KEY (c)) ENGINE=MYISAM; +INSERT INTO t4 select seq from seq_1_to_3000; +ANALYZE TABLE t1,t2,t3,t4; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected +test.t3 analyze status OK +test.t4 analyze status Engine-independent statistics collected +test.t4 analyze status OK +set join_cache_level=0; +EXPLAIN SELECT COUNT(*) +FROM t1 +LEFT JOIN t2 ON t1.b = t2.b +LEFT JOIN t3 ON t2.d = t3.c +LEFT JOIN t4 ON t3.c=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 10000 Using index +1 SIMPLE t2 ref b b 4 test.t1.b 1 +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.d 1 Using where; Using index +1 SIMPLE t4 index NULL PRIMARY 4 NULL 3000 Using where; Using index +SELECT COUNT(*) +FROM t1 +LEFT JOIN t2 ON t1.b = t2.b +LEFT JOIN t3 ON t2.d = t3.c +LEFT JOIN t4 ON t3.c=1; +COUNT(*) +12999 +set join_cache_level=default; +EXPLAIN SELECT COUNT(*) +FROM t1 +LEFT JOIN t2 ON t1.b = t2.b +LEFT JOIN t3 ON t2.d = t3.c +LEFT JOIN t4 ON t3.c=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 10000 Using index +1 SIMPLE t2 ref b b 4 test.t1.b 1 +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.d 1 Using where; Using index +1 SIMPLE t4 index NULL PRIMARY 4 NULL 3000 Using where; Using index; Using join buffer (flat, BNL join) +SELECT COUNT(*) +FROM t1 +LEFT JOIN t2 ON t1.b = t2.b +LEFT JOIN t3 ON t2.d = t3.c +LEFT JOIN t4 ON t3.c=1; +COUNT(*) +12999 +DROP TABLE t1,t2,t3,t4; +CREATE TABLE t1 (b int NOT NULL, PRIMARY KEY (b)); +INSERT INTO t1 select seq from seq_1_to_10; +CREATE TABLE t2 (b int NOT NULL, d varchar(255), KEY (b)) ; +INSERT INTO t2 VALUES (1,1),(2,2),(3,3); +CREATE TABLE t3 (c int NOT NULL, PRIMARY KEY (c)) ; +INSERT INTO t3 select seq from seq_1_to_3; +CREATE TABLE t4 (c int NOT NULL, PRIMARY KEY (c)) ; +INSERT INTO t4 select seq from seq_1_to_3; +set join_cache_level=0; +EXPLAIN SELECT * +FROM t1 +LEFT JOIN t2 ON t1.b = t2.b +LEFT JOIN t3 ON t2.d = t3.c +LEFT JOIN t4 ON t3.c=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 10 Using index +1 SIMPLE t2 ALL b NULL NULL NULL 3 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.d 1 Using where; Using index +1 SIMPLE t4 index NULL PRIMARY 4 NULL 3 Using where; Using index +SELECT * +FROM t1 +LEFT JOIN t2 ON t1.b = t2.b +LEFT JOIN t3 ON t2.d = t3.c +LEFT JOIN t4 ON t3.c=1; +b b d c c +1 1 1 1 1 +1 1 1 1 2 +1 1 1 1 3 +2 2 2 2 NULL +3 3 3 3 NULL +4 NULL NULL NULL NULL +5 NULL NULL NULL NULL +6 NULL NULL NULL NULL +7 NULL NULL NULL NULL +8 NULL NULL NULL NULL +9 NULL NULL NULL NULL +10 NULL NULL NULL NULL +set join_cache_level=default; +EXPLAIN SELECT * +FROM t1 +LEFT JOIN t2 ON t1.b = t2.b +LEFT JOIN t3 ON t2.d = t3.c +LEFT JOIN t4 ON t3.c=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 10 Using index +1 SIMPLE t2 ALL b NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.d 1 Using where; Using index +1 SIMPLE t4 index NULL PRIMARY 4 NULL 3 Using where; Using index; Using join buffer (flat, BNL join) +SELECT * +FROM t1 +LEFT JOIN t2 ON t1.b = t2.b +LEFT JOIN t3 ON t2.d = t3.c +LEFT JOIN t4 ON t3.c=1; +b b d c c +1 1 1 1 1 +1 1 1 1 2 +1 1 1 1 3 +2 2 2 2 NULL +3 3 3 3 NULL +4 NULL NULL NULL NULL +5 NULL NULL NULL NULL +6 NULL NULL NULL NULL +7 NULL NULL NULL NULL +8 NULL NULL NULL NULL +9 NULL NULL NULL NULL +10 NULL NULL NULL NULL +DROP TABLE t1,t2,t3,t4; +# # End of 10.4 tests # diff --git a/mysql-test/main/join_cache.test b/mysql-test/main/join_cache.test index f8723447efe..868fc3f7e8a 100644 --- a/mysql-test/main/join_cache.test +++ b/mysql-test/main/join_cache.test @@ -4247,6 +4247,64 @@ SET JOIN_buffer_size=16384; SELECT * FROM information_schema.statistics JOIN information_schema.COLUMNS USING (table_name,column_name); --enable_result_log +--echo # +--echo # MDEV-32351: Join buffer used for outer join with ON condition +--echo # depending only on outer tables +--echo # + +--source include/have_sequence.inc + +CREATE TABLE t1 (b int NOT NULL, PRIMARY KEY (b)) ENGINE=MYISAM; +INSERT INTO t1 select seq from seq_1_to_10000; +CREATE TABLE t2 (b int NOT NULL, d varchar(255), KEY (b)) ENGINE=MYISAM ; +INSERT INTO t2 VALUES (1,1),(2,2),(3,3); +CREATE TABLE t3 (c int NOT NULL, PRIMARY KEY (c)) ENGINE=MYISAM ; +INSERT INTO t3 select seq from seq_1_to_3000; +CREATE TABLE t4 (c int NOT NULL, PRIMARY KEY (c)) ENGINE=MYISAM; +INSERT INTO t4 select seq from seq_1_to_3000; +ANALYZE TABLE t1,t2,t3,t4; + +let $q1= +SELECT COUNT(*) +FROM t1 + LEFT JOIN t2 ON t1.b = t2.b + LEFT JOIN t3 ON t2.d = t3.c + LEFT JOIN t4 ON t3.c=1; + +set join_cache_level=0; +eval EXPLAIN $q1; +eval $q1; +set join_cache_level=default; +eval EXPLAIN $q1; +eval $q1; + +DROP TABLE t1,t2,t3,t4; + +CREATE TABLE t1 (b int NOT NULL, PRIMARY KEY (b)); +INSERT INTO t1 select seq from seq_1_to_10; +CREATE TABLE t2 (b int NOT NULL, d varchar(255), KEY (b)) ; +INSERT INTO t2 VALUES (1,1),(2,2),(3,3); +CREATE TABLE t3 (c int NOT NULL, PRIMARY KEY (c)) ; +INSERT INTO t3 select seq from seq_1_to_3; +CREATE TABLE t4 (c int NOT NULL, PRIMARY KEY (c)) ; +INSERT INTO t4 select seq from seq_1_to_3; + +let $q2= +SELECT * +FROM t1 + LEFT JOIN t2 ON t1.b = t2.b + LEFT JOIN t3 ON t2.d = t3.c + LEFT JOIN t4 ON t3.c=1; + +set join_cache_level=0; +eval EXPLAIN $q2; +eval $q2; +set join_cache_level=default; +eval EXPLAIN $q2; +eval $q2; + +DROP TABLE t1,t2,t3,t4; + --echo # --echo # End of 10.4 tests --echo # diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index e7b096b420b..26716a4a5c4 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -2054,10 +2054,11 @@ bool JOIN_CACHE::skip_if_matched() - In the case of a semi-nest the match flag may be in two states {MATCH_NOT_FOUND, MATCH_FOUND}. The record is skipped if the flag is set to MATCH_FOUND. - - In the case of a outer join nest when not_exists optimization is applied - the match may be in three states {MATCH_NOT_FOUND, MATCH_IMPOSSIBLE, - MATCH_FOUND. The record is skipped if the flag is set to MATCH_FOUND or - to MATCH_IMPOSSIBLE. + - In the case of an outer join the match may be in three states + {MATCH_NOT_FOUND, MATCH_IMPOSSIBLE, MATCH_FOUND}. + If not_exists optimization is applied the record is skipped when + the flag is set to MATCH_FOUND or to MATCH_IMPOSSIBLE. Otherwise + the record is skipped only when the flag is set to MATCH_IMPOSSIBLE. If the record is skipped the value of 'pos' is set to point to the position right after the record. @@ -2080,13 +2081,13 @@ bool JOIN_CACHE::skip_if_not_needed_match() if (prev_cache) offset+= prev_cache->get_size_of_rec_offset(); - if (!join_tab->check_only_first_match()) - return FALSE; - match_fl= get_match_flag_by_pos(pos+offset); skip= join_tab->first_sj_inner_tab ? - match_fl == MATCH_FOUND : // the case of semi-join - match_fl != MATCH_NOT_FOUND; // the case of outer-join + match_fl == MATCH_FOUND : // the case of semi-join + not_exists_opt_is_applicable && + join_tab->table->reginfo.not_exists_optimize ? + match_fl != MATCH_NOT_FOUND : // the case of not exist opt + match_fl == MATCH_IMPOSSIBLE; if (skip) { @@ -2383,7 +2384,7 @@ enum_nested_loop_state JOIN_CACHE::join_matching_records(bool skip_last) as candidates for matches. */ - bool not_exists_opt_is_applicable= true; + not_exists_opt_is_applicable= true; if (check_only_first_match && join_tab->first_inner) { /* @@ -2408,8 +2409,9 @@ enum_nested_loop_state JOIN_CACHE::join_matching_records(bool skip_last) } } - if (!check_only_first_match || - (join_tab->first_inner && !not_exists_opt_is_applicable) || + if ((!join_tab->on_precond && + (!check_only_first_match || + (join_tab->first_inner && !not_exists_opt_is_applicable))) || !skip_next_candidate_for_match(rec_ptr)) { read_next_candidate_for_match(rec_ptr); diff --git a/sql/sql_join_cache.h b/sql/sql_join_cache.h index b0cfb674ef9..7b5e221b104 100644 --- a/sql/sql_join_cache.h +++ b/sql/sql_join_cache.h @@ -340,6 +340,9 @@ protected: /* The length of an embedded key value */ uint emb_key_length; + /* This flag is used only when 'not exists' optimization can be applied */ + bool not_exists_opt_is_applicable; + /* This object provides the methods to iterate over records of the joined table join_tab when looking for join matches between @@ -536,6 +539,7 @@ protected: prev_cache= next_cache= 0; buff= 0; min_buff_size= max_buff_size= 0; // Caches + not_exists_opt_is_applicable= false; } /* From 4ed59006265945a104b8b259103143b6d6c93254 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Fri, 10 Mar 2023 18:02:14 +0300 Subject: [PATCH 140/158] ANALYZE FORMAT=JSON: Backport block-nl-join.r_unpack_time_ms from 11.0 +fix MDEV-30830. Also fix it to work with hashed join (MDEV-30830). Reviewed by: Monty --- mysql-test/include/analyze-format.inc | 2 +- mysql-test/main/analyze_format_json.result | 15 ++-- .../main/analyze_format_json_timings.result | 85 +++++++++++++++++++ .../main/analyze_format_json_timings.test | 77 +++++++++++++++++ mysql-test/main/analyze_stmt_orderby.result | 6 +- mysql-test/main/derived_split_innodb.result | 3 +- mysql-test/main/except.result | 12 ++- mysql-test/main/except.test | 2 + mysql-test/main/explain_json.result | 3 +- mysql-test/main/intersect.result | 6 +- mysql-test/main/rowid_filter_innodb.result | 6 +- sql/sql_explain.cc | 3 + sql/sql_explain.h | 10 ++- sql/sql_join_cache.cc | 6 +- sql/sql_select.cc | 4 +- sql/sql_select.h | 1 + 16 files changed, 218 insertions(+), 23 deletions(-) create mode 100644 mysql-test/main/analyze_format_json_timings.result create mode 100644 mysql-test/main/analyze_format_json_timings.test diff --git a/mysql-test/include/analyze-format.inc b/mysql-test/include/analyze-format.inc index 08006e26c79..330be82ef96 100644 --- a/mysql-test/include/analyze-format.inc +++ b/mysql-test/include/analyze-format.inc @@ -1,3 +1,3 @@ # The time on ANALYSE FORMAT=JSON is rather variable ---replace_regex /("(r_total_time_ms|r_buffer_size|r_filling_time_ms)": )[^, \n]*/\1"REPLACED"/ +--replace_regex /("(r_[a-z_]*_time_ms|r_buffer_size)": )[^, \n]*/\1"REPLACED"/ diff --git a/mysql-test/main/analyze_format_json.result b/mysql-test/main/analyze_format_json.result index c306c2fc1b3..48a12125f98 100644 --- a/mysql-test/main/analyze_format_json.result +++ b/mysql-test/main/analyze_format_json.result @@ -145,7 +145,8 @@ ANALYZE "buffer_type": "flat", "buffer_size": "1Kb", "join_type": "BNL", - "r_filtered": 100 + "r_filtered": 100, + "r_unpack_time_ms": "REPLACED" } } } @@ -184,7 +185,8 @@ ANALYZE "buffer_size": "1Kb", "join_type": "BNL", "attached_condition": "tbl1.c > tbl2.c", - "r_filtered": 15.833 + "r_filtered": 15.833, + "r_unpack_time_ms": "REPLACED" } } } @@ -628,7 +630,8 @@ ANALYZE "buffer_size": "65", "join_type": "BNL", "attached_condition": "(t2.b,t2.b in (subquery#2))", - "r_filtered": null + "r_filtered": null, + "r_unpack_time_ms": "REPLACED" }, "subqueries": [ { @@ -713,7 +716,8 @@ ANALYZE "buffer_type": "flat", "buffer_size": "1", "join_type": "BNL", - "r_filtered": null + "r_filtered": null, + "r_unpack_time_ms": "REPLACED" }, "subqueries": [ { @@ -745,7 +749,8 @@ ANALYZE "buffer_size": "65", "join_type": "BNL", "attached_condition": "t2.f2 = t3.f3", - "r_filtered": null + "r_filtered": null, + "r_unpack_time_ms": "REPLACED" } } } diff --git a/mysql-test/main/analyze_format_json_timings.result b/mysql-test/main/analyze_format_json_timings.result new file mode 100644 index 00000000000..f00833b40eb --- /dev/null +++ b/mysql-test/main/analyze_format_json_timings.result @@ -0,0 +1,85 @@ +# +# MDEV-30830: ANALYZE FORMAT=JSON: r_unpack_time_ms is empty for the hashed joins +# +# +# First, check a regular BNL-join +# +create table t1 ( +a int, +b int +); +insert into t1 select seq, seq/3 from seq_0_to_99; +create table t2 ( +a int, +b int +); +insert into t2 select seq, seq/5 from seq_0_to_99; +set @js='$out'; +set @out=(select json_extract(@js,'$**.block-nl-join.r_unpack_time_ms')); +select cast(json_extract(@out,'$[0]') as DOUBLE) > 0; +cast(json_extract(@out,'$[0]') as DOUBLE) > 0 +1 +drop table t1,t2; +# +# Now, check the hashed, BNL-H join +# +create table t1 ( +a int, +b int +); +insert into t1 select seq, seq/3 from seq_0_to_499; +create table t2 ( +a int, +b int +); +insert into t2 select seq, seq/5 from seq_0_to_499; +set @tmp=@@join_cache_level, join_cache_level=6; +select '$out' as X; +X +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 500, + "r_rows": 500, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100, + "attached_condition": "t1.a < 700 and t1.b is not null" + }, + "block-nl-join": { + "table": { + "table_name": "t2", + "access_type": "hash_ALL", + "key": "#hash#$hj", + "key_length": "5", + "used_key_parts": ["b"], + "ref": ["test.t1.b"], + "r_loops": 1, + "rows": 500, + "r_rows": 500, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 20, + "attached_condition": "t2.a < 100" + }, + "buffer_type": "flat", + "buffer_size": "18Kb", + "join_type": "BNLH", + "attached_condition": "t2.b = t1.b", + "r_filtered": 100, + "r_unpack_time_ms": "REPLACED" + } + } +} +set @out=(select json_extract(@js,'$**.block-nl-join.r_unpack_time_ms')); +select cast(json_extract(@out,'$[0]') as DOUBLE) > 0; +cast(json_extract(@out,'$[0]') as DOUBLE) > 0 +1 +set join_cache_level=@tmp; +drop table t1, t2; diff --git a/mysql-test/main/analyze_format_json_timings.test b/mysql-test/main/analyze_format_json_timings.test new file mode 100644 index 00000000000..fdb4c8d5989 --- /dev/null +++ b/mysql-test/main/analyze_format_json_timings.test @@ -0,0 +1,77 @@ +# +# Tests to check that r_something_time_ms is non-zero in +# ANALYZE FORMAT=JSON +# +--source include/default_optimizer_switch.inc +--source include/have_sequence.inc + +# The tests here are large so that we get non-zero timings +--source include/big_test.inc + +--echo # +--echo # MDEV-30830: ANALYZE FORMAT=JSON: r_unpack_time_ms is empty for the hashed joins +--echo # + +--echo # +--echo # First, check a regular BNL-join +--echo # +create table t1 ( + a int, + b int +); +insert into t1 select seq, seq/3 from seq_0_to_99; + +create table t2 ( + a int, + b int +); +insert into t2 select seq, seq/5 from seq_0_to_99; + +let $out=` +analyze format=json +select * from t1, t2 +where + t1.a < 700 and + t2.a < 100 + and t1.b=t2.b +`; + +evalp set @js='$out'; +set @out=(select json_extract(@js,'$**.block-nl-join.r_unpack_time_ms')); +select cast(json_extract(@out,'$[0]') as DOUBLE) > 0; +drop table t1,t2; + +--echo # +--echo # Now, check the hashed, BNL-H join +--echo # +create table t1 ( + a int, + b int +); +insert into t1 select seq, seq/3 from seq_0_to_499; + +create table t2 ( + a int, + b int +); +insert into t2 select seq, seq/5 from seq_0_to_499; +set @tmp=@@join_cache_level, join_cache_level=6; + +let $out=` +analyze format=json +select * from t1, t2 +where + t1.a < 700 and + t2.a < 100 + and t1.b=t2.b +`; + +--source include/analyze-format.inc +evalp select '$out' as X; + +set @out=(select json_extract(@js,'$**.block-nl-join.r_unpack_time_ms')); +select cast(json_extract(@out,'$[0]') as DOUBLE) > 0; + +set join_cache_level=@tmp; +drop table t1, t2; + diff --git a/mysql-test/main/analyze_stmt_orderby.result b/mysql-test/main/analyze_stmt_orderby.result index 23f4c39dd5b..fbd57078b8e 100644 --- a/mysql-test/main/analyze_stmt_orderby.result +++ b/mysql-test/main/analyze_stmt_orderby.result @@ -429,7 +429,8 @@ ANALYZE "buffer_size": "65", "join_type": "BNL", "attached_condition": "t3.a = t0.a", - "r_filtered": 10 + "r_filtered": 10, + "r_unpack_time_ms": "REPLACED" } } } @@ -500,7 +501,8 @@ ANALYZE "buffer_size": "119", "join_type": "BNL", "attached_condition": "t5.a = t6.a", - "r_filtered": 21.429 + "r_filtered": 21.429, + "r_unpack_time_ms": "REPLACED" } } } diff --git a/mysql-test/main/derived_split_innodb.result b/mysql-test/main/derived_split_innodb.result index bea2271eaf3..22974251c56 100644 --- a/mysql-test/main/derived_split_innodb.result +++ b/mysql-test/main/derived_split_innodb.result @@ -461,7 +461,8 @@ ANALYZE "buffer_size": "1Kb", "join_type": "BNL", "attached_condition": "trigcond(t11.col1 = t10.col1)", - "r_filtered": 10 + "r_filtered": 10, + "r_unpack_time_ms": "REPLACED" } } } diff --git a/mysql-test/main/except.result b/mysql-test/main/except.result index c96ba62a215..6b629cb6a0f 100644 --- a/mysql-test/main/except.result +++ b/mysql-test/main/except.result @@ -327,7 +327,8 @@ ANALYZE "buffer_type": "flat", "buffer_size": "119", "join_type": "BNL", - "r_filtered": 100 + "r_filtered": 100, + "r_unpack_time_ms": 0.0012 } } }, @@ -361,7 +362,8 @@ ANALYZE "buffer_type": "flat", "buffer_size": "119", "join_type": "BNL", - "r_filtered": 100 + "r_filtered": 100, + "r_unpack_time_ms": 5.4e-4 } } } @@ -423,7 +425,8 @@ ANALYZE "buffer_type": "flat", "buffer_size": "119", "join_type": "BNL", - "r_filtered": 100 + "r_filtered": 100, + "r_unpack_time_ms": 0.0011 } } }, @@ -457,7 +460,8 @@ ANALYZE "buffer_type": "flat", "buffer_size": "119", "join_type": "BNL", - "r_filtered": 100 + "r_filtered": 100, + "r_unpack_time_ms": 6.1e-4 } } } diff --git a/mysql-test/main/except.test b/mysql-test/main/except.test index 4eaae1a3888..80df958c354 100644 --- a/mysql-test/main/except.test +++ b/mysql-test/main/except.test @@ -14,8 +14,10 @@ EXPLAIN extended select * from ((select a,b from t1) except (select c,d from t2) EXPLAIN format=json (select a,b from t1) except (select c,d from t2); --replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/ +--source include/analyze-format.inc ANALYZE format=json (select a,b from t1) except (select c,d from t2); --replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/ +--source include/analyze-format.inc ANALYZE format=json select * from ((select a,b from t1) except (select c,d from t2)) a; select * from ((select a,b from t1) except (select c,d from t2)) a; diff --git a/mysql-test/main/explain_json.result b/mysql-test/main/explain_json.result index 17f83fe5362..b0ea1d273fb 100644 --- a/mysql-test/main/explain_json.result +++ b/mysql-test/main/explain_json.result @@ -1536,7 +1536,8 @@ ANALYZE "buffer_size": "400", "join_type": "BKA", "mrr_type": "Rowid-ordered scan", - "r_filtered": 100 + "r_filtered": 100, + "r_unpack_time_ms": "REPLACED" } } } diff --git a/mysql-test/main/intersect.result b/mysql-test/main/intersect.result index e4a8300ec74..a32a79c0043 100644 --- a/mysql-test/main/intersect.result +++ b/mysql-test/main/intersect.result @@ -385,7 +385,8 @@ ANALYZE "buffer_type": "flat", "buffer_size": "256Kb", "join_type": "BNL", - "r_filtered": 100 + "r_filtered": 100, + "r_unpack_time_ms": 6.1e-4 } } } @@ -464,7 +465,8 @@ ANALYZE "buffer_type": "flat", "buffer_size": "256Kb", "join_type": "BNL", - "r_filtered": 100 + "r_filtered": 100, + "r_unpack_time_ms": 5.8e-4 } } } diff --git a/mysql-test/main/rowid_filter_innodb.result b/mysql-test/main/rowid_filter_innodb.result index 6bc00da6f4c..6248932d666 100644 --- a/mysql-test/main/rowid_filter_innodb.result +++ b/mysql-test/main/rowid_filter_innodb.result @@ -3634,7 +3634,8 @@ ANALYZE "join_type": "BKA", "mrr_type": "Rowid-ordered scan", "attached_condition": "a.atp = 1", - "r_filtered": 100 + "r_filtered": 100, + "r_unpack_time_ms": "REPLACED" }, "block-nl-join": { "table": { @@ -3657,7 +3658,8 @@ ANALYZE "join_type": "BKA", "mrr_type": "Rowid-ordered scan", "attached_condition": "fi.fh in (6311439873746261694,-397087483897438286,8518228073041491534,-5420422472375069774)", - "r_filtered": 40 + "r_filtered": 40, + "r_unpack_time_ms": "REPLACED" } } } diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 6b76db8139e..78f2d5e9254 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -1904,6 +1904,9 @@ void Explain_table_access::print_explain_json(Explain_query *query, writer->add_double(jbuf_tracker.get_filtered_after_where()*100.0); else writer->add_null(); + + writer->add_member("r_unpack_time_ms"); + writer->add_double(jbuf_unpack_tracker.get_time_ms()); } } diff --git a/sql/sql_explain.h b/sql/sql_explain.h index 3add40419cf..2be6390e2cf 100644 --- a/sql/sql_explain.h +++ b/sql/sql_explain.h @@ -721,7 +721,7 @@ public: class Explain_table_access : public Sql_alloc { public: - Explain_table_access(MEM_ROOT *root) : + Explain_table_access(MEM_ROOT *root, bool timed) : derived_select_number(0), non_merged_sjm_number(0), extra_tags(root), @@ -734,6 +734,7 @@ public: pushed_index_cond(NULL), sjm_nest(NULL), pre_join_sort(NULL), + jbuf_unpack_tracker(timed), rowid_filter(NULL) {} ~Explain_table_access() { delete sjm_nest; } @@ -840,7 +841,12 @@ public: Table_access_tracker tracker; Exec_time_tracker op_tracker; Table_access_tracker jbuf_tracker; - + + /* + Track the time to unpack rows from the join buffer. + */ + Time_and_counter_tracker jbuf_unpack_tracker; + Explain_rowid_filter *rowid_filter; int print_explain(select_result_sink *output, uint8 explain_flags, diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 26716a4a5c4..41d7dd89f55 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -1638,7 +1638,7 @@ bool JOIN_CACHE::get_record() pos+= referenced_fields*size_of_fld_ofs; if (prev_cache) prev_cache->get_record_by_pos(prev_rec_ptr); - } + } return res; } @@ -2414,7 +2414,9 @@ enum_nested_loop_state JOIN_CACHE::join_matching_records(bool skip_last) (join_tab->first_inner && !not_exists_opt_is_applicable))) || !skip_next_candidate_for_match(rec_ptr)) { - read_next_candidate_for_match(rec_ptr); + ANALYZE_START_TRACKING(join_tab->jbuf_unpack_tracker); + read_next_candidate_for_match(rec_ptr); + ANALYZE_STOP_TRACKING(join_tab->jbuf_unpack_tracker); rc= generate_full_extensions(rec_ptr); if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS) goto finish; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e3a3a33a7c1..ec66d0baf31 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -26906,6 +26906,7 @@ bool JOIN_TAB::save_explain_data(Explain_table_access *eta, // psergey-todo: data for filtering! tracker= &eta->tracker; jbuf_tracker= &eta->jbuf_tracker; + jbuf_unpack_tracker= &eta->jbuf_unpack_tracker; /* Enable the table access time tracker only for "ANALYZE stmt" */ if (thd->lex->analyze_stmt) @@ -27536,7 +27537,8 @@ int JOIN::save_explain_data_intern(Explain_query *output, Explain_table_access *eta= (new (output->mem_root) - Explain_table_access(output->mem_root)); + Explain_table_access(output->mem_root, + thd->lex->analyze_stmt)); if (!eta) DBUG_RETURN(1); diff --git a/sql/sql_select.h b/sql/sql_select.h index b0fa0b66b62..7282a83ef09 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -309,6 +309,7 @@ typedef struct st_join_table { Table_access_tracker *tracker; Table_access_tracker *jbuf_tracker; + Time_and_counter_tracker *jbuf_unpack_tracker; /* Bitmap of TAB_INFO_* bits that encodes special line for EXPLAIN 'Extra' column, or 0 if there is no info. From 9bf2e5e3fecee6adeb8b54580319219e3ae4ae2e Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Thu, 26 Oct 2023 20:44:10 +0300 Subject: [PATCH 141/158] MDEV-32351: Significant slowdown with outer joins: Test coverage Make ANALYZE FORMAT=JSON print block-nl-join.r_unpack_ops when analyze_print_r_unpack_ops debug flag is set. Then, add a testcase. --- mysql-test/main/join_cache_debug.result | 101 ++++++++++++++++++++++++ mysql-test/main/join_cache_debug.test | 44 +++++++++++ sql/sql_explain.cc | 5 ++ 3 files changed, 150 insertions(+) create mode 100644 mysql-test/main/join_cache_debug.result create mode 100644 mysql-test/main/join_cache_debug.test diff --git a/mysql-test/main/join_cache_debug.result b/mysql-test/main/join_cache_debug.result new file mode 100644 index 00000000000..f6c450ed3a5 --- /dev/null +++ b/mysql-test/main/join_cache_debug.result @@ -0,0 +1,101 @@ +# +# MDEV-32351: Significant slowdown for query with many outer joins +# +CREATE TABLE t1 (b int NOT NULL, PRIMARY KEY (b)) ENGINE=MYISAM; +INSERT INTO t1 select seq from seq_1_to_10000; +CREATE TABLE t2 (b int NOT NULL, d varchar(255), KEY (b)) ENGINE=MYISAM ; +INSERT INTO t2 VALUES (1,1),(2,2),(3,3); +CREATE TABLE t3 (c int NOT NULL, PRIMARY KEY (c)) ENGINE=MYISAM ; +INSERT INTO t3 select seq from seq_1_to_3000; +CREATE TABLE t4 (c int NOT NULL, PRIMARY KEY (c)) ENGINE=MYISAM; +INSERT INTO t4 select seq from seq_1_to_3000; +ANALYZE TABLE t1,t2,t3,t4; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected +test.t3 analyze status OK +test.t4 analyze status Engine-independent statistics collected +test.t4 analyze status OK +create table t1_t2 as +select +t1.b as t1_b, t2.b as t2_b, t2.d as t2_d +FROM t1 +LEFT JOIN t2 ON t1.b = t2.b; +SET @old_debug=@@debug_dbug; +SET debug_dbug='+d,analyze_print_r_unpack_ops'; +analyze +format=json +SELECT COUNT(*) +FROM t1_t2 +LEFT JOIN t3 ON t2_d = t3.c +LEFT JOIN t4 ON t3.c=1 +select '$js' as JSON; +JSON +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "const_condition": "1", + "table": { + "table_name": "t1_t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 10000, + "r_rows": 10000, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + }, + "table": { + "table_name": "t3", + "access_type": "eq_ref", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["c"], + "ref": ["test.t1_t2.t2_d"], + "r_loops": 10000, + "rows": 1, + "r_rows": 0.0003, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100, + "attached_condition": "trigcond(t1_t2.t2_d = t3.c and trigcond(t1_t2.t2_d is not null))", + "using_index": true + }, + "block-nl-join": { + "table": { + "table_name": "t4", + "access_type": "index", + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["c"], + "r_loops": 1, + "rows": 3000, + "r_rows": 3000, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100, + "using_index": true + }, + "buffer_type": "flat", + "buffer_size": "256Kb", + "join_type": "BNL", + "attached_condition": "trigcond(trigcond(t3.c = 1))", + "r_filtered": 0.0433, + "r_unpack_time_ms": "REPLACED", + "r_unpack_ops": 3000 + } + } +} +# This must show 3000, not 30000000: +select json_extract('$js', '\$**.r_unpack_ops') as R_UNPACK_OPS; +R_UNPACK_OPS +[3000] +SET debug_dbug=@old_debug; +drop table t1,t2,t3,t4; +drop table t1_t2; diff --git a/mysql-test/main/join_cache_debug.test b/mysql-test/main/join_cache_debug.test new file mode 100644 index 00000000000..6179daaf947 --- /dev/null +++ b/mysql-test/main/join_cache_debug.test @@ -0,0 +1,44 @@ +--source include/have_sequence.inc +--source include/have_debug.inc + +--echo # +--echo # MDEV-32351: Significant slowdown for query with many outer joins +--echo # +CREATE TABLE t1 (b int NOT NULL, PRIMARY KEY (b)) ENGINE=MYISAM; +INSERT INTO t1 select seq from seq_1_to_10000; +CREATE TABLE t2 (b int NOT NULL, d varchar(255), KEY (b)) ENGINE=MYISAM ; +INSERT INTO t2 VALUES (1,1),(2,2),(3,3); +CREATE TABLE t3 (c int NOT NULL, PRIMARY KEY (c)) ENGINE=MYISAM ; +INSERT INTO t3 select seq from seq_1_to_3000; +CREATE TABLE t4 (c int NOT NULL, PRIMARY KEY (c)) ENGINE=MYISAM; +INSERT INTO t4 select seq from seq_1_to_3000; +ANALYZE TABLE t1,t2,t3,t4; + +create table t1_t2 as +select + t1.b as t1_b, t2.b as t2_b, t2.d as t2_d +FROM t1 + LEFT JOIN t2 ON t1.b = t2.b; + +SET @old_debug=@@debug_dbug; +SET debug_dbug='+d,analyze_print_r_unpack_ops'; + +let $q= analyze +format=json +SELECT COUNT(*) +FROM t1_t2 + LEFT JOIN t3 ON t2_d = t3.c + LEFT JOIN t4 ON t3.c=1; + +echo $q; +let $js=`$q`; + +--source include/analyze-format.inc +evalp select '$js' as JSON; + +--echo # This must show 3000, not 30000000: +evalp select json_extract('$js', '\$**.r_unpack_ops') as R_UNPACK_OPS; +SET debug_dbug=@old_debug; + +drop table t1,t2,t3,t4; +drop table t1_t2; diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 78f2d5e9254..986d3f16bdf 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -1907,6 +1907,11 @@ void Explain_table_access::print_explain_json(Explain_query *query, writer->add_member("r_unpack_time_ms"); writer->add_double(jbuf_unpack_tracker.get_time_ms()); + DBUG_EXECUTE_IF("analyze_print_r_unpack_ops", + { + writer->add_member("r_unpack_ops"); + writer->add_ull(jbuf_unpack_tracker.get_loops()); + }); } } From 1cd8a5ef5130ed1e2491d6069bb68d94b8c68beb Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 27 Oct 2023 16:44:58 +0200 Subject: [PATCH 142/158] Fix of Backport block-nl-join.r_unpack_time_ms. --- mysql-test/main/except.result | 8 ++++---- mysql-test/main/except.test | 6 ++---- mysql-test/main/intersect.result | 4 ++-- mysql-test/main/intersect.test | 8 ++++---- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/mysql-test/main/except.result b/mysql-test/main/except.result index 6b629cb6a0f..bdc40d93214 100644 --- a/mysql-test/main/except.result +++ b/mysql-test/main/except.result @@ -328,7 +328,7 @@ ANALYZE "buffer_size": "119", "join_type": "BNL", "r_filtered": 100, - "r_unpack_time_ms": 0.0012 + "r_unpack_time_ms": "REPLACED" } } }, @@ -363,7 +363,7 @@ ANALYZE "buffer_size": "119", "join_type": "BNL", "r_filtered": 100, - "r_unpack_time_ms": 5.4e-4 + "r_unpack_time_ms": "REPLACED" } } } @@ -426,7 +426,7 @@ ANALYZE "buffer_size": "119", "join_type": "BNL", "r_filtered": 100, - "r_unpack_time_ms": 0.0011 + "r_unpack_time_ms": "REPLACED" } } }, @@ -461,7 +461,7 @@ ANALYZE "buffer_size": "119", "join_type": "BNL", "r_filtered": 100, - "r_unpack_time_ms": 6.1e-4 + "r_unpack_time_ms": "REPLACED" } } } diff --git a/mysql-test/main/except.test b/mysql-test/main/except.test index 80df958c354..8b6dba0a7b1 100644 --- a/mysql-test/main/except.test +++ b/mysql-test/main/except.test @@ -13,10 +13,8 @@ EXPLAIN extended (select a,b from t1) except (select c,d from t2); EXPLAIN extended select * from ((select a,b from t1) except (select c,d from t2)) a; EXPLAIN format=json (select a,b from t1) except (select c,d from t2); ---replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/ --source include/analyze-format.inc ANALYZE format=json (select a,b from t1) except (select c,d from t2); ---replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/ --source include/analyze-format.inc ANALYZE format=json select * from ((select a,b from t1) except (select c,d from t2)) a; select * from ((select a,b from t1) except (select c,d from t2)) a; @@ -47,9 +45,9 @@ EXPLAIN (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4); EXPLAIN extended select * from ((select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4)) a; EXPLAIN format=json (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4); ---replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/ +--source include/analyze-format.inc ANALYZE format=json (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4); ---replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/ +--source include/analyze-format.inc ANALYZE format=json select * from ((select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4)) a; select * from ((select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4)) a; diff --git a/mysql-test/main/intersect.result b/mysql-test/main/intersect.result index a32a79c0043..4c12395b463 100644 --- a/mysql-test/main/intersect.result +++ b/mysql-test/main/intersect.result @@ -386,7 +386,7 @@ ANALYZE "buffer_size": "256Kb", "join_type": "BNL", "r_filtered": 100, - "r_unpack_time_ms": 6.1e-4 + "r_unpack_time_ms": "REPLACED" } } } @@ -466,7 +466,7 @@ ANALYZE "buffer_size": "256Kb", "join_type": "BNL", "r_filtered": 100, - "r_unpack_time_ms": 5.8e-4 + "r_unpack_time_ms": "REPLACED" } } } diff --git a/mysql-test/main/intersect.test b/mysql-test/main/intersect.test index 31cfcf00c5f..f20a2d6a635 100644 --- a/mysql-test/main/intersect.test +++ b/mysql-test/main/intersect.test @@ -24,9 +24,9 @@ EXPLAIN (select a,b from t1) intersect (select c,d from t2) intersect (select e, EXPLAIN extended (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3); EXPLAIN extended select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a; EXPLAIN format=json (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3); ---replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/ +--source include/analyze-format.inc ANALYZE format=json (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3); ---replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/ +--source include/analyze-format.inc ANALYZE format=json select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a; select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a; @@ -44,9 +44,9 @@ EXPLAIN extended (select a,b from t1) intersect (select c,e from t2,t3); EXPLAIN extended select * from ((select a,b from t1) intersect (select c,e from t2,t3)) a; set @@optimizer_switch='optimize_join_buffer_size=off'; EXPLAIN format=json (select a,b from t1) intersect (select c,e from t2,t3); ---replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/ +--source include/analyze-format.inc ANALYZE format=json (select a,b from t1) intersect (select c,e from t2,t3); ---replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/ +--source include/analyze-format.inc ANALYZE format=json select * from ((select a,b from t1) intersect (select c,e from t2,t3)) a; set @@optimizer_switch=@save_optimizer_switch; select * from ((select a,b from t1) intersect (select c,e from t2,t3)) a; From b9e210bbf389d52ee320508e348f61a40b826965 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 24 Oct 2023 23:50:26 +0200 Subject: [PATCH 143/158] MDEV-32555 wrong result with an index and a partially null-rejecting condition ref->null_rejecting is a key_part_map. we need to check the bit corresponding to the particular store_key. Note that there are no store_key objects for const ref parts. --- mysql-test/main/subselect_nulls.result | 37 ++++++++++++++++++++-- mysql-test/main/subselect_nulls.test | 44 ++++++++++++++++++++------ sql/sql_expression_cache.cc | 1 + sql/sql_select.cc | 7 ++-- 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/mysql-test/main/subselect_nulls.result b/mysql-test/main/subselect_nulls.result index 08982371269..9d3b7b2cfd5 100644 --- a/mysql-test/main/subselect_nulls.result +++ b/mysql-test/main/subselect_nulls.result @@ -1,5 +1,3 @@ -drop table if exists x1; -drop table if exists x2; set @tmp_subselect_nulls=@@optimizer_switch; set optimizer_switch='semijoin=off'; create table x1(k int primary key, d1 int, d2 int); @@ -115,9 +113,44 @@ k d1 d2 set optimizer_switch= @tmp_subselect_nulls; drop table x1; drop table x2; +# +# MDEV-7339 Server crashes in Item_func_trig_cond::val_int +# select (select 1, 2) in (select 3, 4); (select 1, 2) in (select 3, 4) 0 select (select NULL, NULL) in (select 3, 4); (select NULL, NULL) in (select 3, 4) NULL +# +# End of 5.5 tests +# +# +# MDEV-32555 wrong result with an index and a partially null-rejecting condition +# +create table t1 (a int primary key); +insert t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t2 ( +b int not null, +c int default null, +d int not null, +e int not null, +unique key (d,b,c) +); +insert t2 values (1,null,1,1),(1,null,2,2),(1,null,3,3),(1,null,4,4),(2,null,1,2),(3,null,1,3),(4,null,2,2),(4,null,1,4); +select ( +select sum(t2_.e) from t2 t2_ where t2_.b = a and t2_.c <=> t2.c and t2_.d = 1 +) x from t2 left join t1 on a = b; +x +1 +2 +3 +4 +1 +4 +1 +1 +drop table t1, t2; +# +# End of 10.10 tests +# diff --git a/mysql-test/main/subselect_nulls.test b/mysql-test/main/subselect_nulls.test index 3e7b2189ed5..68575eca9e7 100644 --- a/mysql-test/main/subselect_nulls.test +++ b/mysql-test/main/subselect_nulls.test @@ -1,10 +1,3 @@ -# Initialize tables for the test - ---disable_warnings -drop table if exists x1; -drop table if exists x2; ---enable_warnings - set @tmp_subselect_nulls=@@optimizer_switch; set optimizer_switch='semijoin=off'; @@ -98,8 +91,39 @@ set optimizer_switch= @tmp_subselect_nulls; drop table x1; drop table x2; -# -# MDEV-7339 Server crashes in Item_func_trig_cond::val_int -# +--echo # +--echo # MDEV-7339 Server crashes in Item_func_trig_cond::val_int +--echo # select (select 1, 2) in (select 3, 4); select (select NULL, NULL) in (select 3, 4); + +--echo # +--echo # End of 5.5 tests +--echo # + +--echo # +--echo # MDEV-32555 wrong result with an index and a partially null-rejecting condition +--echo # + +create table t1 (a int primary key); +insert t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t2 ( + b int not null, + c int default null, + d int not null, + e int not null, + unique key (d,b,c) +); + +insert t2 values (1,null,1,1),(1,null,2,2),(1,null,3,3),(1,null,4,4),(2,null,1,2),(3,null,1,3),(4,null,2,2),(4,null,1,4); + +select ( + select sum(t2_.e) from t2 t2_ where t2_.b = a and t2_.c <=> t2.c and t2_.d = 1 +) x from t2 left join t1 on a = b; + +drop table t1, t2; + +--echo # +--echo # End of 10.10 tests +--echo # diff --git a/sql/sql_expression_cache.cc b/sql/sql_expression_cache.cc index 69d85f3343d..8681e08e014 100644 --- a/sql/sql_expression_cache.cc +++ b/sql/sql_expression_cache.cc @@ -151,6 +151,7 @@ void Expression_cache_tmptable::init() } cache_table->s->keys= 1; ref.null_rejecting= 1; + ref.const_ref_part_map= 0; ref.disable_cache= FALSE; ref.has_record= 0; ref.use_count= 0; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4fadd2b433d..4b053d3d742 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -26078,12 +26078,15 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) enum_check_fields org_count_cuted_fields= thd->count_cuted_fields; MY_BITMAP *old_map= dbug_tmp_use_all_columns(table, &table->write_set); bool result= 0; + key_part_map map= 1; thd->count_cuted_fields= CHECK_FIELD_IGNORE; - for (store_key **copy=ref->key_copy ; *copy ; copy++) + for (store_key **copy=ref->key_copy ; *copy ; copy++, map <<= 1) { + while (map & ref->const_ref_part_map) // skip const ref parts + map <<= 1; // no store_key objects for them if ((*copy)->copy(thd) & 1 || - (ref->null_rejecting && (*copy)->null_key)) + ((ref->null_rejecting & map) && (*copy)->null_key)) { result= 1; break; From 86351f5eda559b9d14f17672c33f07043a96a0a7 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Sat, 28 Oct 2023 12:47:55 +0300 Subject: [PATCH 144/158] MDEV-32351: Significant slowdown with outer joins: fix embedded. For some reason, in embedded server, a command let $a=`$query` ignores local context. Make a workaround: use SET STATEMENT to set debug_dbug in the same statement. --- mysql-test/main/join_cache_debug.result | 3 +-- mysql-test/main/join_cache_debug.test | 7 +++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/mysql-test/main/join_cache_debug.result b/mysql-test/main/join_cache_debug.result index f6c450ed3a5..c0769d5117d 100644 --- a/mysql-test/main/join_cache_debug.result +++ b/mysql-test/main/join_cache_debug.result @@ -24,8 +24,7 @@ select t1.b as t1_b, t2.b as t2_b, t2.d as t2_d FROM t1 LEFT JOIN t2 ON t1.b = t2.b; -SET @old_debug=@@debug_dbug; -SET debug_dbug='+d,analyze_print_r_unpack_ops'; +SET statement debug_dbug='+d,analyze_print_r_unpack_ops' for analyze format=json SELECT COUNT(*) diff --git a/mysql-test/main/join_cache_debug.test b/mysql-test/main/join_cache_debug.test index 6179daaf947..aba36b14f29 100644 --- a/mysql-test/main/join_cache_debug.test +++ b/mysql-test/main/join_cache_debug.test @@ -20,10 +20,9 @@ select FROM t1 LEFT JOIN t2 ON t1.b = t2.b; -SET @old_debug=@@debug_dbug; -SET debug_dbug='+d,analyze_print_r_unpack_ops'; - -let $q= analyze +let $q= +SET statement debug_dbug='+d,analyze_print_r_unpack_ops' for +analyze format=json SELECT COUNT(*) FROM t1_t2 From ab6139ddc09b28df94016ac1e7345d623b08de8e Mon Sep 17 00:00:00 2001 From: Rex Date: Sat, 28 Oct 2023 06:05:25 +1200 Subject: [PATCH 145/158] MDEV-32612 Assertion `tab->select->quick' failed in test_if_skip_sort_order Fixup for MDEV-31983, incorrect test for checking ability to use quick select. Approved by Sergei Petrunia --- mysql-test/main/subselect_mat.result | 13 +++++++++++++ mysql-test/main/subselect_sj_mat.result | 13 +++++++++++++ mysql-test/main/subselect_sj_mat.test | 14 ++++++++++++++ sql/sql_select.cc | 4 ++-- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result index c5b201c6f46..286b3d40ac1 100644 --- a/mysql-test/main/subselect_mat.result +++ b/mysql-test/main/subselect_mat.result @@ -2699,6 +2699,19 @@ INSERT INTO t3 VALUES ('2012-11-11',5),('2012-12-12',6); UPDATE t1, t2 SET t1.a = 26 WHERE t2.b IN (SELECT MIN(d) FROM t3 WHERE c >= '2012-01'); ERROR 22007: Incorrect datetime value: '2012-01' for column `test`.`t3`.`c` at row 1 DROP TABLE t1, t2, t3; +# +# MDEV-32612 Assertion `tab->select->quick' failed in test_if_skip_sort_order +# +CREATE TABLE t1 (l_orderkey int, l_linenumber int, l_quantity double, +PRIMARY KEY (l_orderkey,l_linenumber), KEY (l_orderkey), +KEY (l_orderkey,l_quantity)) engine=MyISAM; +INSERT INTO t1 VALUES (290,1,35),(290,2,2); +SELECT * FROM t1 +WHERE l_quantity = 31 +AND (l_quantity = 50 OR l_orderkey = 41) +ORDER BY l_orderkey, l_linenumber; +l_orderkey l_linenumber l_quantity +DROP TABLE t1; # end of 10.6 tests set @subselect_mat_test_optimizer_switch_value=null; set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off'; diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result index 5d09af61892..277ce9a4408 100644 --- a/mysql-test/main/subselect_sj_mat.result +++ b/mysql-test/main/subselect_sj_mat.result @@ -2741,4 +2741,17 @@ INSERT INTO t3 VALUES ('2012-11-11',5),('2012-12-12',6); UPDATE t1, t2 SET t1.a = 26 WHERE t2.b IN (SELECT MIN(d) FROM t3 WHERE c >= '2012-01'); ERROR 22007: Incorrect datetime value: '2012-01' for column `test`.`t3`.`c` at row 1 DROP TABLE t1, t2, t3; +# +# MDEV-32612 Assertion `tab->select->quick' failed in test_if_skip_sort_order +# +CREATE TABLE t1 (l_orderkey int, l_linenumber int, l_quantity double, +PRIMARY KEY (l_orderkey,l_linenumber), KEY (l_orderkey), +KEY (l_orderkey,l_quantity)) engine=MyISAM; +INSERT INTO t1 VALUES (290,1,35),(290,2,2); +SELECT * FROM t1 +WHERE l_quantity = 31 +AND (l_quantity = 50 OR l_orderkey = 41) +ORDER BY l_orderkey, l_linenumber; +l_orderkey l_linenumber l_quantity +DROP TABLE t1; # end of 10.6 tests diff --git a/mysql-test/main/subselect_sj_mat.test b/mysql-test/main/subselect_sj_mat.test index 0b5cfd6ab7b..7a218bde172 100644 --- a/mysql-test/main/subselect_sj_mat.test +++ b/mysql-test/main/subselect_sj_mat.test @@ -2436,4 +2436,18 @@ UPDATE t1, t2 SET t1.a = 26 WHERE t2.b IN (SELECT MIN(d) FROM t3 WHERE c >= '201 # Cleanup DROP TABLE t1, t2, t3; +--echo # +--echo # MDEV-32612 Assertion `tab->select->quick' failed in test_if_skip_sort_order +--echo # + +CREATE TABLE t1 (l_orderkey int, l_linenumber int, l_quantity double, + PRIMARY KEY (l_orderkey,l_linenumber), KEY (l_orderkey), + KEY (l_orderkey,l_quantity)) engine=MyISAM; +INSERT INTO t1 VALUES (290,1,35),(290,2,2); +SELECT * FROM t1 +WHERE l_quantity = 31 +AND (l_quantity = 50 OR l_orderkey = 41) +ORDER BY l_orderkey, l_linenumber; +DROP TABLE t1; + --echo # end of 10.6 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0c8432afd91..a351322e76b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -24750,14 +24750,14 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, tab->join->unit-> lim.get_select_limit(), TRUE, TRUE, FALSE, FALSE); - if (res != SQL_SELECT::OK) + // if we cannot use quick select + if (res != SQL_SELECT::OK || !tab->select->quick) { if (res == SQL_SELECT::ERROR) *fatal_error= true; select->cond= save_cond; goto use_filesort; } - DBUG_ASSERT(tab->select->quick); tab->type= JT_ALL; tab->ref.key= -1; tab->ref.key_parts= 0; From 5436b5ddd7abfb8dd2e802c50f93db77040e0a6e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 28 Oct 2023 14:43:10 +0200 Subject: [PATCH 146/158] cleanup: UUID * modify the test to use different and not monotonous timestamps * rename methods to be unambiguous (for IDE challenged devs) * move byte swap checks into helpers --- .../mysql-test/type_uuid/order.result | 1351 +++++++++-------- .../type_uuid/mysql-test/type_uuid/order.test | 7 +- .../type_uuid/std_data/mdev-29959.MYD | Bin 1344 -> 1344 bytes .../type_uuid/std_data/mdev-29959.MYI | Bin 2048 -> 2048 bytes .../type_uuid/std_data/mdev-29959.frm | Bin 967 -> 967 bytes plugin/type_uuid/sql_type_uuid.h | 36 +- 6 files changed, 702 insertions(+), 692 deletions(-) diff --git a/plugin/type_uuid/mysql-test/type_uuid/order.result b/plugin/type_uuid/mysql-test/type_uuid/order.result index 2f6ae3ed47c..d71d0eb3ad8 100644 --- a/plugin/type_uuid/mysql-test/type_uuid/order.result +++ b/plugin/type_uuid/mysql-test/type_uuid/order.result @@ -1,80 +1,81 @@ create table t1 (a uuid, b int not null, index (a)); -insert t1 select sformat('11223344-5566-{:x}777-{}888-99aabbccddee', seq div 4, elt(1+(seq % 4),0,8,'c','e')),seq from seq_0_to_63; +insert t1 select sformat('{:03}01234-5566-{:x}777-{}888-99aabbccddee', +(seq % 2)*100 + seq, seq div 4, elt(1+(seq % 4),0,8,'c','e')),seq from seq_0_to_63; Warnings: -Warning 1292 Incorrect uuid value: '11223344-5566-8777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 33 -Warning 1292 Incorrect uuid value: '11223344-5566-9777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 37 -Warning 1292 Incorrect uuid value: '11223344-5566-a777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 41 -Warning 1292 Incorrect uuid value: '11223344-5566-b777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 45 -Warning 1292 Incorrect uuid value: '11223344-5566-c777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 49 -Warning 1292 Incorrect uuid value: '11223344-5566-d777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 53 -Warning 1292 Incorrect uuid value: '11223344-5566-e777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 57 -Warning 1292 Incorrect uuid value: '11223344-5566-f777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 61 -select * from t1; +Warning 1292 Incorrect uuid value: '03201234-5566-8777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 33 +Warning 1292 Incorrect uuid value: '03601234-5566-9777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 37 +Warning 1292 Incorrect uuid value: '04001234-5566-a777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 41 +Warning 1292 Incorrect uuid value: '04401234-5566-b777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 45 +Warning 1292 Incorrect uuid value: '04801234-5566-c777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 49 +Warning 1292 Incorrect uuid value: '05201234-5566-d777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 53 +Warning 1292 Incorrect uuid value: '05601234-5566-e777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 57 +Warning 1292 Incorrect uuid value: '06001234-5566-f777-0888-99aabbccddee' for column `test`.`t1`.`a` at row 61 +select * from t1 order by b; a b -11223344-5566-0777-0888-99aabbccddee 0 -11223344-5566-0777-8888-99aabbccddee 1 -11223344-5566-0777-c888-99aabbccddee 2 -11223344-5566-0777-e888-99aabbccddee 3 -11223344-5566-1777-0888-99aabbccddee 4 -11223344-5566-1777-8888-99aabbccddee 5 -11223344-5566-1777-c888-99aabbccddee 6 -11223344-5566-1777-e888-99aabbccddee 7 -11223344-5566-2777-0888-99aabbccddee 8 -11223344-5566-2777-8888-99aabbccddee 9 -11223344-5566-2777-c888-99aabbccddee 10 -11223344-5566-2777-e888-99aabbccddee 11 -11223344-5566-3777-0888-99aabbccddee 12 -11223344-5566-3777-8888-99aabbccddee 13 -11223344-5566-3777-c888-99aabbccddee 14 -11223344-5566-3777-e888-99aabbccddee 15 -11223344-5566-4777-0888-99aabbccddee 16 -11223344-5566-4777-8888-99aabbccddee 17 -11223344-5566-4777-c888-99aabbccddee 18 -11223344-5566-4777-e888-99aabbccddee 19 -11223344-5566-5777-0888-99aabbccddee 20 -11223344-5566-5777-8888-99aabbccddee 21 -11223344-5566-5777-c888-99aabbccddee 22 -11223344-5566-5777-e888-99aabbccddee 23 -11223344-5566-6777-0888-99aabbccddee 24 -11223344-5566-6777-8888-99aabbccddee 25 -11223344-5566-6777-c888-99aabbccddee 26 -11223344-5566-6777-e888-99aabbccddee 27 -11223344-5566-7777-0888-99aabbccddee 28 -11223344-5566-7777-8888-99aabbccddee 29 -11223344-5566-7777-c888-99aabbccddee 30 -11223344-5566-7777-e888-99aabbccddee 31 +00001234-5566-0777-0888-99aabbccddee 0 +10101234-5566-0777-8888-99aabbccddee 1 +00201234-5566-0777-c888-99aabbccddee 2 +10301234-5566-0777-e888-99aabbccddee 3 +00401234-5566-1777-0888-99aabbccddee 4 +10501234-5566-1777-8888-99aabbccddee 5 +00601234-5566-1777-c888-99aabbccddee 6 +10701234-5566-1777-e888-99aabbccddee 7 +00801234-5566-2777-0888-99aabbccddee 8 +10901234-5566-2777-8888-99aabbccddee 9 +01001234-5566-2777-c888-99aabbccddee 10 +11101234-5566-2777-e888-99aabbccddee 11 +01201234-5566-3777-0888-99aabbccddee 12 +11301234-5566-3777-8888-99aabbccddee 13 +01401234-5566-3777-c888-99aabbccddee 14 +11501234-5566-3777-e888-99aabbccddee 15 +01601234-5566-4777-0888-99aabbccddee 16 +11701234-5566-4777-8888-99aabbccddee 17 +01801234-5566-4777-c888-99aabbccddee 18 +11901234-5566-4777-e888-99aabbccddee 19 +02001234-5566-5777-0888-99aabbccddee 20 +12101234-5566-5777-8888-99aabbccddee 21 +02201234-5566-5777-c888-99aabbccddee 22 +12301234-5566-5777-e888-99aabbccddee 23 +02401234-5566-6777-0888-99aabbccddee 24 +12501234-5566-6777-8888-99aabbccddee 25 +02601234-5566-6777-c888-99aabbccddee 26 +12701234-5566-6777-e888-99aabbccddee 27 +02801234-5566-7777-0888-99aabbccddee 28 +12901234-5566-7777-8888-99aabbccddee 29 +03001234-5566-7777-c888-99aabbccddee 30 +13101234-5566-7777-e888-99aabbccddee 31 NULL 32 -11223344-5566-8777-8888-99aabbccddee 33 -11223344-5566-8777-c888-99aabbccddee 34 -11223344-5566-8777-e888-99aabbccddee 35 +13301234-5566-8777-8888-99aabbccddee 33 +03401234-5566-8777-c888-99aabbccddee 34 +13501234-5566-8777-e888-99aabbccddee 35 NULL 36 -11223344-5566-9777-8888-99aabbccddee 37 -11223344-5566-9777-c888-99aabbccddee 38 -11223344-5566-9777-e888-99aabbccddee 39 +13701234-5566-9777-8888-99aabbccddee 37 +03801234-5566-9777-c888-99aabbccddee 38 +13901234-5566-9777-e888-99aabbccddee 39 NULL 40 -11223344-5566-a777-8888-99aabbccddee 41 -11223344-5566-a777-c888-99aabbccddee 42 -11223344-5566-a777-e888-99aabbccddee 43 +14101234-5566-a777-8888-99aabbccddee 41 +04201234-5566-a777-c888-99aabbccddee 42 +14301234-5566-a777-e888-99aabbccddee 43 NULL 44 -11223344-5566-b777-8888-99aabbccddee 45 -11223344-5566-b777-c888-99aabbccddee 46 -11223344-5566-b777-e888-99aabbccddee 47 +14501234-5566-b777-8888-99aabbccddee 45 +04601234-5566-b777-c888-99aabbccddee 46 +14701234-5566-b777-e888-99aabbccddee 47 NULL 48 -11223344-5566-c777-8888-99aabbccddee 49 -11223344-5566-c777-c888-99aabbccddee 50 -11223344-5566-c777-e888-99aabbccddee 51 +14901234-5566-c777-8888-99aabbccddee 49 +05001234-5566-c777-c888-99aabbccddee 50 +15101234-5566-c777-e888-99aabbccddee 51 NULL 52 -11223344-5566-d777-8888-99aabbccddee 53 -11223344-5566-d777-c888-99aabbccddee 54 -11223344-5566-d777-e888-99aabbccddee 55 +15301234-5566-d777-8888-99aabbccddee 53 +05401234-5566-d777-c888-99aabbccddee 54 +15501234-5566-d777-e888-99aabbccddee 55 NULL 56 -11223344-5566-e777-8888-99aabbccddee 57 -11223344-5566-e777-c888-99aabbccddee 58 -11223344-5566-e777-e888-99aabbccddee 59 +15701234-5566-e777-8888-99aabbccddee 57 +05801234-5566-e777-c888-99aabbccddee 58 +15901234-5566-e777-e888-99aabbccddee 59 NULL 60 -11223344-5566-f777-8888-99aabbccddee 61 -11223344-5566-f777-c888-99aabbccddee 62 -11223344-5566-f777-e888-99aabbccddee 63 +16101234-5566-f777-8888-99aabbccddee 61 +06201234-5566-f777-c888-99aabbccddee 62 +16301234-5566-f777-e888-99aabbccddee 63 select * from t1 order by a; a b NULL 40 @@ -85,62 +86,62 @@ NULL 48 NULL 52 NULL 56 NULL 60 -11223344-5566-0777-0888-99aabbccddee 0 -11223344-5566-1777-0888-99aabbccddee 4 -11223344-5566-2777-0888-99aabbccddee 8 -11223344-5566-3777-0888-99aabbccddee 12 -11223344-5566-4777-0888-99aabbccddee 16 -11223344-5566-5777-0888-99aabbccddee 20 -11223344-5566-6777-0888-99aabbccddee 24 -11223344-5566-6777-8888-99aabbccddee 25 -11223344-5566-6777-c888-99aabbccddee 26 -11223344-5566-6777-e888-99aabbccddee 27 -11223344-5566-7777-0888-99aabbccddee 28 -11223344-5566-7777-8888-99aabbccddee 29 -11223344-5566-7777-c888-99aabbccddee 30 -11223344-5566-7777-e888-99aabbccddee 31 -11223344-5566-8777-8888-99aabbccddee 33 -11223344-5566-8777-c888-99aabbccddee 34 -11223344-5566-8777-e888-99aabbccddee 35 -11223344-5566-9777-8888-99aabbccddee 37 -11223344-5566-9777-c888-99aabbccddee 38 -11223344-5566-9777-e888-99aabbccddee 39 -11223344-5566-a777-8888-99aabbccddee 41 -11223344-5566-a777-c888-99aabbccddee 42 -11223344-5566-a777-e888-99aabbccddee 43 -11223344-5566-b777-8888-99aabbccddee 45 -11223344-5566-b777-c888-99aabbccddee 46 -11223344-5566-b777-e888-99aabbccddee 47 -11223344-5566-c777-8888-99aabbccddee 49 -11223344-5566-c777-c888-99aabbccddee 50 -11223344-5566-c777-e888-99aabbccddee 51 -11223344-5566-d777-8888-99aabbccddee 53 -11223344-5566-d777-c888-99aabbccddee 54 -11223344-5566-d777-e888-99aabbccddee 55 -11223344-5566-e777-8888-99aabbccddee 57 -11223344-5566-e777-c888-99aabbccddee 58 -11223344-5566-e777-e888-99aabbccddee 59 -11223344-5566-f777-8888-99aabbccddee 61 -11223344-5566-f777-c888-99aabbccddee 62 -11223344-5566-f777-e888-99aabbccddee 63 -11223344-5566-0777-8888-99aabbccddee 1 -11223344-5566-1777-8888-99aabbccddee 5 -11223344-5566-2777-8888-99aabbccddee 9 -11223344-5566-3777-8888-99aabbccddee 13 -11223344-5566-4777-8888-99aabbccddee 17 -11223344-5566-5777-8888-99aabbccddee 21 -11223344-5566-0777-c888-99aabbccddee 2 -11223344-5566-1777-c888-99aabbccddee 6 -11223344-5566-2777-c888-99aabbccddee 10 -11223344-5566-3777-c888-99aabbccddee 14 -11223344-5566-4777-c888-99aabbccddee 18 -11223344-5566-5777-c888-99aabbccddee 22 -11223344-5566-0777-e888-99aabbccddee 3 -11223344-5566-1777-e888-99aabbccddee 7 -11223344-5566-2777-e888-99aabbccddee 11 -11223344-5566-3777-e888-99aabbccddee 15 -11223344-5566-4777-e888-99aabbccddee 19 -11223344-5566-5777-e888-99aabbccddee 23 +00001234-5566-0777-0888-99aabbccddee 0 +00401234-5566-1777-0888-99aabbccddee 4 +00801234-5566-2777-0888-99aabbccddee 8 +01201234-5566-3777-0888-99aabbccddee 12 +01601234-5566-4777-0888-99aabbccddee 16 +02001234-5566-5777-0888-99aabbccddee 20 +02401234-5566-6777-0888-99aabbccddee 24 +02601234-5566-6777-c888-99aabbccddee 26 +02801234-5566-7777-0888-99aabbccddee 28 +03001234-5566-7777-c888-99aabbccddee 30 +03401234-5566-8777-c888-99aabbccddee 34 +03801234-5566-9777-c888-99aabbccddee 38 +04201234-5566-a777-c888-99aabbccddee 42 +04601234-5566-b777-c888-99aabbccddee 46 +05001234-5566-c777-c888-99aabbccddee 50 +05401234-5566-d777-c888-99aabbccddee 54 +05801234-5566-e777-c888-99aabbccddee 58 +06201234-5566-f777-c888-99aabbccddee 62 +12501234-5566-6777-8888-99aabbccddee 25 +12701234-5566-6777-e888-99aabbccddee 27 +12901234-5566-7777-8888-99aabbccddee 29 +13101234-5566-7777-e888-99aabbccddee 31 +13301234-5566-8777-8888-99aabbccddee 33 +13501234-5566-8777-e888-99aabbccddee 35 +13701234-5566-9777-8888-99aabbccddee 37 +13901234-5566-9777-e888-99aabbccddee 39 +14101234-5566-a777-8888-99aabbccddee 41 +14301234-5566-a777-e888-99aabbccddee 43 +14501234-5566-b777-8888-99aabbccddee 45 +14701234-5566-b777-e888-99aabbccddee 47 +14901234-5566-c777-8888-99aabbccddee 49 +15101234-5566-c777-e888-99aabbccddee 51 +15301234-5566-d777-8888-99aabbccddee 53 +15501234-5566-d777-e888-99aabbccddee 55 +15701234-5566-e777-8888-99aabbccddee 57 +15901234-5566-e777-e888-99aabbccddee 59 +16101234-5566-f777-8888-99aabbccddee 61 +16301234-5566-f777-e888-99aabbccddee 63 +10101234-5566-0777-8888-99aabbccddee 1 +10501234-5566-1777-8888-99aabbccddee 5 +10901234-5566-2777-8888-99aabbccddee 9 +11301234-5566-3777-8888-99aabbccddee 13 +11701234-5566-4777-8888-99aabbccddee 17 +12101234-5566-5777-8888-99aabbccddee 21 +00201234-5566-0777-c888-99aabbccddee 2 +00601234-5566-1777-c888-99aabbccddee 6 +01001234-5566-2777-c888-99aabbccddee 10 +01401234-5566-3777-c888-99aabbccddee 14 +01801234-5566-4777-c888-99aabbccddee 18 +02201234-5566-5777-c888-99aabbccddee 22 +10301234-5566-0777-e888-99aabbccddee 3 +10701234-5566-1777-e888-99aabbccddee 7 +11101234-5566-2777-e888-99aabbccddee 11 +11501234-5566-3777-e888-99aabbccddee 15 +11901234-5566-4777-e888-99aabbccddee 19 +12301234-5566-5777-e888-99aabbccddee 23 show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -149,138 +150,138 @@ t1 CREATE TABLE `t1` ( KEY `a` (`a`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci # now let's use the table as above, but created in 10.11.4 -select * from t2; +select * from t2 order by b; a b -11223344-5566-0777-0888-99aabbccddee 0 -11223344-5566-0777-8888-99aabbccddee 1 -11223344-5566-0777-c888-99aabbccddee 2 -11223344-5566-0777-e888-99aabbccddee 3 -11223344-5566-1777-0888-99aabbccddee 4 -11223344-5566-1777-8888-99aabbccddee 5 -11223344-5566-1777-c888-99aabbccddee 6 -11223344-5566-1777-e888-99aabbccddee 7 -11223344-5566-2777-0888-99aabbccddee 8 -11223344-5566-2777-8888-99aabbccddee 9 -11223344-5566-2777-c888-99aabbccddee 10 -11223344-5566-2777-e888-99aabbccddee 11 -11223344-5566-3777-0888-99aabbccddee 12 -11223344-5566-3777-8888-99aabbccddee 13 -11223344-5566-3777-c888-99aabbccddee 14 -11223344-5566-3777-e888-99aabbccddee 15 -11223344-5566-4777-0888-99aabbccddee 16 -11223344-5566-4777-8888-99aabbccddee 17 -11223344-5566-4777-c888-99aabbccddee 18 -11223344-5566-4777-e888-99aabbccddee 19 -11223344-5566-5777-0888-99aabbccddee 20 -11223344-5566-5777-8888-99aabbccddee 21 -11223344-5566-5777-c888-99aabbccddee 22 -11223344-5566-5777-e888-99aabbccddee 23 -11223344-5566-6777-0888-99aabbccddee 24 -11223344-5566-6777-8888-99aabbccddee 25 -11223344-5566-6777-c888-99aabbccddee 26 -11223344-5566-6777-e888-99aabbccddee 27 -11223344-5566-7777-0888-99aabbccddee 28 -11223344-5566-7777-8888-99aabbccddee 29 -11223344-5566-7777-c888-99aabbccddee 30 -11223344-5566-7777-e888-99aabbccddee 31 -11223344-5566-8777-0888-99aabbccddee 32 -11223344-5566-8777-8888-99aabbccddee 33 -11223344-5566-8777-c888-99aabbccddee 34 -11223344-5566-8777-e888-99aabbccddee 35 -11223344-5566-9777-0888-99aabbccddee 36 -11223344-5566-9777-8888-99aabbccddee 37 -11223344-5566-9777-c888-99aabbccddee 38 -11223344-5566-9777-e888-99aabbccddee 39 -11223344-5566-a777-0888-99aabbccddee 40 -11223344-5566-a777-8888-99aabbccddee 41 -11223344-5566-a777-c888-99aabbccddee 42 -11223344-5566-a777-e888-99aabbccddee 43 -11223344-5566-b777-0888-99aabbccddee 44 -11223344-5566-b777-8888-99aabbccddee 45 -11223344-5566-b777-c888-99aabbccddee 46 -11223344-5566-b777-e888-99aabbccddee 47 -11223344-5566-c777-0888-99aabbccddee 48 -11223344-5566-c777-8888-99aabbccddee 49 -11223344-5566-c777-c888-99aabbccddee 50 -11223344-5566-c777-e888-99aabbccddee 51 -11223344-5566-d777-0888-99aabbccddee 52 -11223344-5566-d777-8888-99aabbccddee 53 -11223344-5566-d777-c888-99aabbccddee 54 -11223344-5566-d777-e888-99aabbccddee 55 -11223344-5566-e777-0888-99aabbccddee 56 -11223344-5566-e777-8888-99aabbccddee 57 -11223344-5566-e777-c888-99aabbccddee 58 -11223344-5566-e777-e888-99aabbccddee 59 -11223344-5566-f777-0888-99aabbccddee 60 -11223344-5566-f777-8888-99aabbccddee 61 -11223344-5566-f777-c888-99aabbccddee 62 -11223344-5566-f777-e888-99aabbccddee 63 +00001234-5566-0777-0888-99aabbccddee 0 +10101234-5566-0777-8888-99aabbccddee 1 +00201234-5566-0777-c888-99aabbccddee 2 +10301234-5566-0777-e888-99aabbccddee 3 +00401234-5566-1777-0888-99aabbccddee 4 +10501234-5566-1777-8888-99aabbccddee 5 +00601234-5566-1777-c888-99aabbccddee 6 +10701234-5566-1777-e888-99aabbccddee 7 +00801234-5566-2777-0888-99aabbccddee 8 +10901234-5566-2777-8888-99aabbccddee 9 +01001234-5566-2777-c888-99aabbccddee 10 +11101234-5566-2777-e888-99aabbccddee 11 +01201234-5566-3777-0888-99aabbccddee 12 +11301234-5566-3777-8888-99aabbccddee 13 +01401234-5566-3777-c888-99aabbccddee 14 +11501234-5566-3777-e888-99aabbccddee 15 +01601234-5566-4777-0888-99aabbccddee 16 +11701234-5566-4777-8888-99aabbccddee 17 +01801234-5566-4777-c888-99aabbccddee 18 +11901234-5566-4777-e888-99aabbccddee 19 +02001234-5566-5777-0888-99aabbccddee 20 +12101234-5566-5777-8888-99aabbccddee 21 +02201234-5566-5777-c888-99aabbccddee 22 +12301234-5566-5777-e888-99aabbccddee 23 +02401234-5566-6777-0888-99aabbccddee 24 +12501234-5566-6777-8888-99aabbccddee 25 +02601234-5566-6777-c888-99aabbccddee 26 +12701234-5566-6777-e888-99aabbccddee 27 +02801234-5566-7777-0888-99aabbccddee 28 +12901234-5566-7777-8888-99aabbccddee 29 +03001234-5566-7777-c888-99aabbccddee 30 +13101234-5566-7777-e888-99aabbccddee 31 +03201234-5566-8777-0888-99aabbccddee 32 +13301234-5566-8777-8888-99aabbccddee 33 +03401234-5566-8777-c888-99aabbccddee 34 +13501234-5566-8777-e888-99aabbccddee 35 +03601234-5566-9777-0888-99aabbccddee 36 +13701234-5566-9777-8888-99aabbccddee 37 +03801234-5566-9777-c888-99aabbccddee 38 +13901234-5566-9777-e888-99aabbccddee 39 +04001234-5566-a777-0888-99aabbccddee 40 +14101234-5566-a777-8888-99aabbccddee 41 +04201234-5566-a777-c888-99aabbccddee 42 +14301234-5566-a777-e888-99aabbccddee 43 +04401234-5566-b777-0888-99aabbccddee 44 +14501234-5566-b777-8888-99aabbccddee 45 +04601234-5566-b777-c888-99aabbccddee 46 +14701234-5566-b777-e888-99aabbccddee 47 +04801234-5566-c777-0888-99aabbccddee 48 +14901234-5566-c777-8888-99aabbccddee 49 +05001234-5566-c777-c888-99aabbccddee 50 +15101234-5566-c777-e888-99aabbccddee 51 +05201234-5566-d777-0888-99aabbccddee 52 +15301234-5566-d777-8888-99aabbccddee 53 +05401234-5566-d777-c888-99aabbccddee 54 +15501234-5566-d777-e888-99aabbccddee 55 +05601234-5566-e777-0888-99aabbccddee 56 +15701234-5566-e777-8888-99aabbccddee 57 +05801234-5566-e777-c888-99aabbccddee 58 +15901234-5566-e777-e888-99aabbccddee 59 +06001234-5566-f777-0888-99aabbccddee 60 +16101234-5566-f777-8888-99aabbccddee 61 +06201234-5566-f777-c888-99aabbccddee 62 +16301234-5566-f777-e888-99aabbccddee 63 select * from t2 order by a; a b -11223344-5566-0777-0888-99aabbccddee 0 -11223344-5566-1777-0888-99aabbccddee 4 -11223344-5566-2777-0888-99aabbccddee 8 -11223344-5566-3777-0888-99aabbccddee 12 -11223344-5566-4777-0888-99aabbccddee 16 -11223344-5566-5777-0888-99aabbccddee 20 -11223344-5566-6777-0888-99aabbccddee 24 -11223344-5566-7777-0888-99aabbccddee 28 -11223344-5566-8777-0888-99aabbccddee 32 -11223344-5566-9777-0888-99aabbccddee 36 -11223344-5566-a777-0888-99aabbccddee 40 -11223344-5566-b777-0888-99aabbccddee 44 -11223344-5566-c777-0888-99aabbccddee 48 -11223344-5566-d777-0888-99aabbccddee 52 -11223344-5566-e777-0888-99aabbccddee 56 -11223344-5566-f777-0888-99aabbccddee 60 -11223344-5566-0777-8888-99aabbccddee 1 -11223344-5566-1777-8888-99aabbccddee 5 -11223344-5566-2777-8888-99aabbccddee 9 -11223344-5566-3777-8888-99aabbccddee 13 -11223344-5566-4777-8888-99aabbccddee 17 -11223344-5566-5777-8888-99aabbccddee 21 -11223344-5566-6777-8888-99aabbccddee 25 -11223344-5566-7777-8888-99aabbccddee 29 -11223344-5566-8777-8888-99aabbccddee 33 -11223344-5566-9777-8888-99aabbccddee 37 -11223344-5566-a777-8888-99aabbccddee 41 -11223344-5566-b777-8888-99aabbccddee 45 -11223344-5566-c777-8888-99aabbccddee 49 -11223344-5566-d777-8888-99aabbccddee 53 -11223344-5566-e777-8888-99aabbccddee 57 -11223344-5566-f777-8888-99aabbccddee 61 -11223344-5566-0777-c888-99aabbccddee 2 -11223344-5566-1777-c888-99aabbccddee 6 -11223344-5566-2777-c888-99aabbccddee 10 -11223344-5566-3777-c888-99aabbccddee 14 -11223344-5566-4777-c888-99aabbccddee 18 -11223344-5566-5777-c888-99aabbccddee 22 -11223344-5566-6777-c888-99aabbccddee 26 -11223344-5566-7777-c888-99aabbccddee 30 -11223344-5566-8777-c888-99aabbccddee 34 -11223344-5566-9777-c888-99aabbccddee 38 -11223344-5566-a777-c888-99aabbccddee 42 -11223344-5566-b777-c888-99aabbccddee 46 -11223344-5566-c777-c888-99aabbccddee 50 -11223344-5566-d777-c888-99aabbccddee 54 -11223344-5566-e777-c888-99aabbccddee 58 -11223344-5566-f777-c888-99aabbccddee 62 -11223344-5566-0777-e888-99aabbccddee 3 -11223344-5566-1777-e888-99aabbccddee 7 -11223344-5566-2777-e888-99aabbccddee 11 -11223344-5566-3777-e888-99aabbccddee 15 -11223344-5566-4777-e888-99aabbccddee 19 -11223344-5566-5777-e888-99aabbccddee 23 -11223344-5566-6777-e888-99aabbccddee 27 -11223344-5566-7777-e888-99aabbccddee 31 -11223344-5566-8777-e888-99aabbccddee 35 -11223344-5566-9777-e888-99aabbccddee 39 -11223344-5566-a777-e888-99aabbccddee 43 -11223344-5566-b777-e888-99aabbccddee 47 -11223344-5566-c777-e888-99aabbccddee 51 -11223344-5566-d777-e888-99aabbccddee 55 -11223344-5566-e777-e888-99aabbccddee 59 -11223344-5566-f777-e888-99aabbccddee 63 +00001234-5566-0777-0888-99aabbccddee 0 +00401234-5566-1777-0888-99aabbccddee 4 +00801234-5566-2777-0888-99aabbccddee 8 +01201234-5566-3777-0888-99aabbccddee 12 +01601234-5566-4777-0888-99aabbccddee 16 +02001234-5566-5777-0888-99aabbccddee 20 +02401234-5566-6777-0888-99aabbccddee 24 +02801234-5566-7777-0888-99aabbccddee 28 +03201234-5566-8777-0888-99aabbccddee 32 +03601234-5566-9777-0888-99aabbccddee 36 +04001234-5566-a777-0888-99aabbccddee 40 +04401234-5566-b777-0888-99aabbccddee 44 +04801234-5566-c777-0888-99aabbccddee 48 +05201234-5566-d777-0888-99aabbccddee 52 +05601234-5566-e777-0888-99aabbccddee 56 +06001234-5566-f777-0888-99aabbccddee 60 +10101234-5566-0777-8888-99aabbccddee 1 +10501234-5566-1777-8888-99aabbccddee 5 +10901234-5566-2777-8888-99aabbccddee 9 +11301234-5566-3777-8888-99aabbccddee 13 +11701234-5566-4777-8888-99aabbccddee 17 +12101234-5566-5777-8888-99aabbccddee 21 +12501234-5566-6777-8888-99aabbccddee 25 +12901234-5566-7777-8888-99aabbccddee 29 +13301234-5566-8777-8888-99aabbccddee 33 +13701234-5566-9777-8888-99aabbccddee 37 +14101234-5566-a777-8888-99aabbccddee 41 +14501234-5566-b777-8888-99aabbccddee 45 +14901234-5566-c777-8888-99aabbccddee 49 +15301234-5566-d777-8888-99aabbccddee 53 +15701234-5566-e777-8888-99aabbccddee 57 +16101234-5566-f777-8888-99aabbccddee 61 +00201234-5566-0777-c888-99aabbccddee 2 +00601234-5566-1777-c888-99aabbccddee 6 +01001234-5566-2777-c888-99aabbccddee 10 +01401234-5566-3777-c888-99aabbccddee 14 +01801234-5566-4777-c888-99aabbccddee 18 +02201234-5566-5777-c888-99aabbccddee 22 +02601234-5566-6777-c888-99aabbccddee 26 +03001234-5566-7777-c888-99aabbccddee 30 +03401234-5566-8777-c888-99aabbccddee 34 +03801234-5566-9777-c888-99aabbccddee 38 +04201234-5566-a777-c888-99aabbccddee 42 +04601234-5566-b777-c888-99aabbccddee 46 +05001234-5566-c777-c888-99aabbccddee 50 +05401234-5566-d777-c888-99aabbccddee 54 +05801234-5566-e777-c888-99aabbccddee 58 +06201234-5566-f777-c888-99aabbccddee 62 +10301234-5566-0777-e888-99aabbccddee 3 +10701234-5566-1777-e888-99aabbccddee 7 +11101234-5566-2777-e888-99aabbccddee 11 +11501234-5566-3777-e888-99aabbccddee 15 +11901234-5566-4777-e888-99aabbccddee 19 +12301234-5566-5777-e888-99aabbccddee 23 +12701234-5566-6777-e888-99aabbccddee 27 +13101234-5566-7777-e888-99aabbccddee 31 +13501234-5566-8777-e888-99aabbccddee 35 +13901234-5566-9777-e888-99aabbccddee 39 +14301234-5566-a777-e888-99aabbccddee 43 +14701234-5566-b777-e888-99aabbccddee 47 +15101234-5566-c777-e888-99aabbccddee 51 +15501234-5566-d777-e888-99aabbccddee 55 +15901234-5566-e777-e888-99aabbccddee 59 +16301234-5566-f777-e888-99aabbccddee 63 show create table t2; Table Create Table t2 CREATE TABLE `t2` ( @@ -294,62 +295,62 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref a a 17 test.t1.a 1 Using where select * from t1 left join t2 on (t1.a=t2.a); a b a b -11223344-5566-0777-0888-99aabbccddee 0 11223344-5566-0777-0888-99aabbccddee 0 -11223344-5566-0777-8888-99aabbccddee 1 11223344-5566-0777-8888-99aabbccddee 1 -11223344-5566-0777-c888-99aabbccddee 2 11223344-5566-0777-c888-99aabbccddee 2 -11223344-5566-0777-e888-99aabbccddee 3 11223344-5566-0777-e888-99aabbccddee 3 -11223344-5566-1777-0888-99aabbccddee 4 11223344-5566-1777-0888-99aabbccddee 4 -11223344-5566-1777-8888-99aabbccddee 5 11223344-5566-1777-8888-99aabbccddee 5 -11223344-5566-1777-c888-99aabbccddee 6 11223344-5566-1777-c888-99aabbccddee 6 -11223344-5566-1777-e888-99aabbccddee 7 11223344-5566-1777-e888-99aabbccddee 7 -11223344-5566-2777-0888-99aabbccddee 8 11223344-5566-2777-0888-99aabbccddee 8 -11223344-5566-2777-8888-99aabbccddee 9 11223344-5566-2777-8888-99aabbccddee 9 -11223344-5566-2777-c888-99aabbccddee 10 11223344-5566-2777-c888-99aabbccddee 10 -11223344-5566-2777-e888-99aabbccddee 11 11223344-5566-2777-e888-99aabbccddee 11 -11223344-5566-3777-0888-99aabbccddee 12 11223344-5566-3777-0888-99aabbccddee 12 -11223344-5566-3777-8888-99aabbccddee 13 11223344-5566-3777-8888-99aabbccddee 13 -11223344-5566-3777-c888-99aabbccddee 14 11223344-5566-3777-c888-99aabbccddee 14 -11223344-5566-3777-e888-99aabbccddee 15 11223344-5566-3777-e888-99aabbccddee 15 -11223344-5566-4777-0888-99aabbccddee 16 11223344-5566-4777-0888-99aabbccddee 16 -11223344-5566-4777-8888-99aabbccddee 17 11223344-5566-4777-8888-99aabbccddee 17 -11223344-5566-4777-c888-99aabbccddee 18 11223344-5566-4777-c888-99aabbccddee 18 -11223344-5566-4777-e888-99aabbccddee 19 11223344-5566-4777-e888-99aabbccddee 19 -11223344-5566-5777-0888-99aabbccddee 20 11223344-5566-5777-0888-99aabbccddee 20 -11223344-5566-5777-8888-99aabbccddee 21 11223344-5566-5777-8888-99aabbccddee 21 -11223344-5566-5777-c888-99aabbccddee 22 11223344-5566-5777-c888-99aabbccddee 22 -11223344-5566-5777-e888-99aabbccddee 23 11223344-5566-5777-e888-99aabbccddee 23 -11223344-5566-6777-0888-99aabbccddee 24 11223344-5566-6777-0888-99aabbccddee 24 -11223344-5566-6777-8888-99aabbccddee 25 11223344-5566-6777-8888-99aabbccddee 25 -11223344-5566-6777-c888-99aabbccddee 26 11223344-5566-6777-c888-99aabbccddee 26 -11223344-5566-6777-e888-99aabbccddee 27 11223344-5566-6777-e888-99aabbccddee 27 -11223344-5566-7777-0888-99aabbccddee 28 11223344-5566-7777-0888-99aabbccddee 28 -11223344-5566-7777-8888-99aabbccddee 29 11223344-5566-7777-8888-99aabbccddee 29 -11223344-5566-7777-c888-99aabbccddee 30 11223344-5566-7777-c888-99aabbccddee 30 -11223344-5566-7777-e888-99aabbccddee 31 11223344-5566-7777-e888-99aabbccddee 31 -11223344-5566-8777-8888-99aabbccddee 33 11223344-5566-8777-8888-99aabbccddee 33 -11223344-5566-8777-c888-99aabbccddee 34 11223344-5566-8777-c888-99aabbccddee 34 -11223344-5566-8777-e888-99aabbccddee 35 11223344-5566-8777-e888-99aabbccddee 35 -11223344-5566-9777-8888-99aabbccddee 37 11223344-5566-9777-8888-99aabbccddee 37 -11223344-5566-9777-c888-99aabbccddee 38 11223344-5566-9777-c888-99aabbccddee 38 -11223344-5566-9777-e888-99aabbccddee 39 11223344-5566-9777-e888-99aabbccddee 39 -11223344-5566-a777-8888-99aabbccddee 41 11223344-5566-a777-8888-99aabbccddee 41 -11223344-5566-a777-c888-99aabbccddee 42 11223344-5566-a777-c888-99aabbccddee 42 -11223344-5566-a777-e888-99aabbccddee 43 11223344-5566-a777-e888-99aabbccddee 43 -11223344-5566-b777-8888-99aabbccddee 45 11223344-5566-b777-8888-99aabbccddee 45 -11223344-5566-b777-c888-99aabbccddee 46 11223344-5566-b777-c888-99aabbccddee 46 -11223344-5566-b777-e888-99aabbccddee 47 11223344-5566-b777-e888-99aabbccddee 47 -11223344-5566-c777-8888-99aabbccddee 49 11223344-5566-c777-8888-99aabbccddee 49 -11223344-5566-c777-c888-99aabbccddee 50 11223344-5566-c777-c888-99aabbccddee 50 -11223344-5566-c777-e888-99aabbccddee 51 11223344-5566-c777-e888-99aabbccddee 51 -11223344-5566-d777-8888-99aabbccddee 53 11223344-5566-d777-8888-99aabbccddee 53 -11223344-5566-d777-c888-99aabbccddee 54 11223344-5566-d777-c888-99aabbccddee 54 -11223344-5566-d777-e888-99aabbccddee 55 11223344-5566-d777-e888-99aabbccddee 55 -11223344-5566-e777-8888-99aabbccddee 57 11223344-5566-e777-8888-99aabbccddee 57 -11223344-5566-e777-c888-99aabbccddee 58 11223344-5566-e777-c888-99aabbccddee 58 -11223344-5566-e777-e888-99aabbccddee 59 11223344-5566-e777-e888-99aabbccddee 59 -11223344-5566-f777-8888-99aabbccddee 61 11223344-5566-f777-8888-99aabbccddee 61 -11223344-5566-f777-c888-99aabbccddee 62 11223344-5566-f777-c888-99aabbccddee 62 -11223344-5566-f777-e888-99aabbccddee 63 11223344-5566-f777-e888-99aabbccddee 63 +00001234-5566-0777-0888-99aabbccddee 0 00001234-5566-0777-0888-99aabbccddee 0 +00201234-5566-0777-c888-99aabbccddee 2 00201234-5566-0777-c888-99aabbccddee 2 +00401234-5566-1777-0888-99aabbccddee 4 00401234-5566-1777-0888-99aabbccddee 4 +00601234-5566-1777-c888-99aabbccddee 6 00601234-5566-1777-c888-99aabbccddee 6 +00801234-5566-2777-0888-99aabbccddee 8 00801234-5566-2777-0888-99aabbccddee 8 +01001234-5566-2777-c888-99aabbccddee 10 01001234-5566-2777-c888-99aabbccddee 10 +01201234-5566-3777-0888-99aabbccddee 12 01201234-5566-3777-0888-99aabbccddee 12 +01401234-5566-3777-c888-99aabbccddee 14 01401234-5566-3777-c888-99aabbccddee 14 +01601234-5566-4777-0888-99aabbccddee 16 01601234-5566-4777-0888-99aabbccddee 16 +01801234-5566-4777-c888-99aabbccddee 18 01801234-5566-4777-c888-99aabbccddee 18 +02001234-5566-5777-0888-99aabbccddee 20 02001234-5566-5777-0888-99aabbccddee 20 +02201234-5566-5777-c888-99aabbccddee 22 02201234-5566-5777-c888-99aabbccddee 22 +02401234-5566-6777-0888-99aabbccddee 24 02401234-5566-6777-0888-99aabbccddee 24 +02601234-5566-6777-c888-99aabbccddee 26 02601234-5566-6777-c888-99aabbccddee 26 +02801234-5566-7777-0888-99aabbccddee 28 02801234-5566-7777-0888-99aabbccddee 28 +03001234-5566-7777-c888-99aabbccddee 30 03001234-5566-7777-c888-99aabbccddee 30 +03401234-5566-8777-c888-99aabbccddee 34 03401234-5566-8777-c888-99aabbccddee 34 +03801234-5566-9777-c888-99aabbccddee 38 03801234-5566-9777-c888-99aabbccddee 38 +04201234-5566-a777-c888-99aabbccddee 42 04201234-5566-a777-c888-99aabbccddee 42 +04601234-5566-b777-c888-99aabbccddee 46 04601234-5566-b777-c888-99aabbccddee 46 +05001234-5566-c777-c888-99aabbccddee 50 05001234-5566-c777-c888-99aabbccddee 50 +05401234-5566-d777-c888-99aabbccddee 54 05401234-5566-d777-c888-99aabbccddee 54 +05801234-5566-e777-c888-99aabbccddee 58 05801234-5566-e777-c888-99aabbccddee 58 +06201234-5566-f777-c888-99aabbccddee 62 06201234-5566-f777-c888-99aabbccddee 62 +10101234-5566-0777-8888-99aabbccddee 1 10101234-5566-0777-8888-99aabbccddee 1 +10301234-5566-0777-e888-99aabbccddee 3 10301234-5566-0777-e888-99aabbccddee 3 +10501234-5566-1777-8888-99aabbccddee 5 10501234-5566-1777-8888-99aabbccddee 5 +10701234-5566-1777-e888-99aabbccddee 7 10701234-5566-1777-e888-99aabbccddee 7 +10901234-5566-2777-8888-99aabbccddee 9 10901234-5566-2777-8888-99aabbccddee 9 +11101234-5566-2777-e888-99aabbccddee 11 11101234-5566-2777-e888-99aabbccddee 11 +11301234-5566-3777-8888-99aabbccddee 13 11301234-5566-3777-8888-99aabbccddee 13 +11501234-5566-3777-e888-99aabbccddee 15 11501234-5566-3777-e888-99aabbccddee 15 +11701234-5566-4777-8888-99aabbccddee 17 11701234-5566-4777-8888-99aabbccddee 17 +11901234-5566-4777-e888-99aabbccddee 19 11901234-5566-4777-e888-99aabbccddee 19 +12101234-5566-5777-8888-99aabbccddee 21 12101234-5566-5777-8888-99aabbccddee 21 +12301234-5566-5777-e888-99aabbccddee 23 12301234-5566-5777-e888-99aabbccddee 23 +12501234-5566-6777-8888-99aabbccddee 25 12501234-5566-6777-8888-99aabbccddee 25 +12701234-5566-6777-e888-99aabbccddee 27 12701234-5566-6777-e888-99aabbccddee 27 +12901234-5566-7777-8888-99aabbccddee 29 12901234-5566-7777-8888-99aabbccddee 29 +13101234-5566-7777-e888-99aabbccddee 31 13101234-5566-7777-e888-99aabbccddee 31 +13301234-5566-8777-8888-99aabbccddee 33 13301234-5566-8777-8888-99aabbccddee 33 +13501234-5566-8777-e888-99aabbccddee 35 13501234-5566-8777-e888-99aabbccddee 35 +13701234-5566-9777-8888-99aabbccddee 37 13701234-5566-9777-8888-99aabbccddee 37 +13901234-5566-9777-e888-99aabbccddee 39 13901234-5566-9777-e888-99aabbccddee 39 +14101234-5566-a777-8888-99aabbccddee 41 14101234-5566-a777-8888-99aabbccddee 41 +14301234-5566-a777-e888-99aabbccddee 43 14301234-5566-a777-e888-99aabbccddee 43 +14501234-5566-b777-8888-99aabbccddee 45 14501234-5566-b777-8888-99aabbccddee 45 +14701234-5566-b777-e888-99aabbccddee 47 14701234-5566-b777-e888-99aabbccddee 47 +14901234-5566-c777-8888-99aabbccddee 49 14901234-5566-c777-8888-99aabbccddee 49 +15101234-5566-c777-e888-99aabbccddee 51 15101234-5566-c777-e888-99aabbccddee 51 +15301234-5566-d777-8888-99aabbccddee 53 15301234-5566-d777-8888-99aabbccddee 53 +15501234-5566-d777-e888-99aabbccddee 55 15501234-5566-d777-e888-99aabbccddee 55 +15701234-5566-e777-8888-99aabbccddee 57 15701234-5566-e777-8888-99aabbccddee 57 +15901234-5566-e777-e888-99aabbccddee 59 15901234-5566-e777-e888-99aabbccddee 59 +16101234-5566-f777-8888-99aabbccddee 61 16101234-5566-f777-8888-99aabbccddee 61 +16301234-5566-f777-e888-99aabbccddee 63 16301234-5566-f777-e888-99aabbccddee 63 NULL 32 NULL NULL NULL 36 NULL NULL NULL 40 NULL NULL @@ -364,62 +365,62 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref a a 17 test.t1.a 1 Using where select * from t1 left join t2 on (t1.a<=>t2.a); a b a b -11223344-5566-0777-0888-99aabbccddee 0 11223344-5566-0777-0888-99aabbccddee 0 -11223344-5566-0777-8888-99aabbccddee 1 11223344-5566-0777-8888-99aabbccddee 1 -11223344-5566-0777-c888-99aabbccddee 2 11223344-5566-0777-c888-99aabbccddee 2 -11223344-5566-0777-e888-99aabbccddee 3 11223344-5566-0777-e888-99aabbccddee 3 -11223344-5566-1777-0888-99aabbccddee 4 11223344-5566-1777-0888-99aabbccddee 4 -11223344-5566-1777-8888-99aabbccddee 5 11223344-5566-1777-8888-99aabbccddee 5 -11223344-5566-1777-c888-99aabbccddee 6 11223344-5566-1777-c888-99aabbccddee 6 -11223344-5566-1777-e888-99aabbccddee 7 11223344-5566-1777-e888-99aabbccddee 7 -11223344-5566-2777-0888-99aabbccddee 8 11223344-5566-2777-0888-99aabbccddee 8 -11223344-5566-2777-8888-99aabbccddee 9 11223344-5566-2777-8888-99aabbccddee 9 -11223344-5566-2777-c888-99aabbccddee 10 11223344-5566-2777-c888-99aabbccddee 10 -11223344-5566-2777-e888-99aabbccddee 11 11223344-5566-2777-e888-99aabbccddee 11 -11223344-5566-3777-0888-99aabbccddee 12 11223344-5566-3777-0888-99aabbccddee 12 -11223344-5566-3777-8888-99aabbccddee 13 11223344-5566-3777-8888-99aabbccddee 13 -11223344-5566-3777-c888-99aabbccddee 14 11223344-5566-3777-c888-99aabbccddee 14 -11223344-5566-3777-e888-99aabbccddee 15 11223344-5566-3777-e888-99aabbccddee 15 -11223344-5566-4777-0888-99aabbccddee 16 11223344-5566-4777-0888-99aabbccddee 16 -11223344-5566-4777-8888-99aabbccddee 17 11223344-5566-4777-8888-99aabbccddee 17 -11223344-5566-4777-c888-99aabbccddee 18 11223344-5566-4777-c888-99aabbccddee 18 -11223344-5566-4777-e888-99aabbccddee 19 11223344-5566-4777-e888-99aabbccddee 19 -11223344-5566-5777-0888-99aabbccddee 20 11223344-5566-5777-0888-99aabbccddee 20 -11223344-5566-5777-8888-99aabbccddee 21 11223344-5566-5777-8888-99aabbccddee 21 -11223344-5566-5777-c888-99aabbccddee 22 11223344-5566-5777-c888-99aabbccddee 22 -11223344-5566-5777-e888-99aabbccddee 23 11223344-5566-5777-e888-99aabbccddee 23 -11223344-5566-6777-0888-99aabbccddee 24 11223344-5566-6777-0888-99aabbccddee 24 -11223344-5566-6777-8888-99aabbccddee 25 11223344-5566-6777-8888-99aabbccddee 25 -11223344-5566-6777-c888-99aabbccddee 26 11223344-5566-6777-c888-99aabbccddee 26 -11223344-5566-6777-e888-99aabbccddee 27 11223344-5566-6777-e888-99aabbccddee 27 -11223344-5566-7777-0888-99aabbccddee 28 11223344-5566-7777-0888-99aabbccddee 28 -11223344-5566-7777-8888-99aabbccddee 29 11223344-5566-7777-8888-99aabbccddee 29 -11223344-5566-7777-c888-99aabbccddee 30 11223344-5566-7777-c888-99aabbccddee 30 -11223344-5566-7777-e888-99aabbccddee 31 11223344-5566-7777-e888-99aabbccddee 31 -11223344-5566-8777-8888-99aabbccddee 33 11223344-5566-8777-8888-99aabbccddee 33 -11223344-5566-8777-c888-99aabbccddee 34 11223344-5566-8777-c888-99aabbccddee 34 -11223344-5566-8777-e888-99aabbccddee 35 11223344-5566-8777-e888-99aabbccddee 35 -11223344-5566-9777-8888-99aabbccddee 37 11223344-5566-9777-8888-99aabbccddee 37 -11223344-5566-9777-c888-99aabbccddee 38 11223344-5566-9777-c888-99aabbccddee 38 -11223344-5566-9777-e888-99aabbccddee 39 11223344-5566-9777-e888-99aabbccddee 39 -11223344-5566-a777-8888-99aabbccddee 41 11223344-5566-a777-8888-99aabbccddee 41 -11223344-5566-a777-c888-99aabbccddee 42 11223344-5566-a777-c888-99aabbccddee 42 -11223344-5566-a777-e888-99aabbccddee 43 11223344-5566-a777-e888-99aabbccddee 43 -11223344-5566-b777-8888-99aabbccddee 45 11223344-5566-b777-8888-99aabbccddee 45 -11223344-5566-b777-c888-99aabbccddee 46 11223344-5566-b777-c888-99aabbccddee 46 -11223344-5566-b777-e888-99aabbccddee 47 11223344-5566-b777-e888-99aabbccddee 47 -11223344-5566-c777-8888-99aabbccddee 49 11223344-5566-c777-8888-99aabbccddee 49 -11223344-5566-c777-c888-99aabbccddee 50 11223344-5566-c777-c888-99aabbccddee 50 -11223344-5566-c777-e888-99aabbccddee 51 11223344-5566-c777-e888-99aabbccddee 51 -11223344-5566-d777-8888-99aabbccddee 53 11223344-5566-d777-8888-99aabbccddee 53 -11223344-5566-d777-c888-99aabbccddee 54 11223344-5566-d777-c888-99aabbccddee 54 -11223344-5566-d777-e888-99aabbccddee 55 11223344-5566-d777-e888-99aabbccddee 55 -11223344-5566-e777-8888-99aabbccddee 57 11223344-5566-e777-8888-99aabbccddee 57 -11223344-5566-e777-c888-99aabbccddee 58 11223344-5566-e777-c888-99aabbccddee 58 -11223344-5566-e777-e888-99aabbccddee 59 11223344-5566-e777-e888-99aabbccddee 59 -11223344-5566-f777-8888-99aabbccddee 61 11223344-5566-f777-8888-99aabbccddee 61 -11223344-5566-f777-c888-99aabbccddee 62 11223344-5566-f777-c888-99aabbccddee 62 -11223344-5566-f777-e888-99aabbccddee 63 11223344-5566-f777-e888-99aabbccddee 63 +00001234-5566-0777-0888-99aabbccddee 0 00001234-5566-0777-0888-99aabbccddee 0 +00201234-5566-0777-c888-99aabbccddee 2 00201234-5566-0777-c888-99aabbccddee 2 +00401234-5566-1777-0888-99aabbccddee 4 00401234-5566-1777-0888-99aabbccddee 4 +00601234-5566-1777-c888-99aabbccddee 6 00601234-5566-1777-c888-99aabbccddee 6 +00801234-5566-2777-0888-99aabbccddee 8 00801234-5566-2777-0888-99aabbccddee 8 +01001234-5566-2777-c888-99aabbccddee 10 01001234-5566-2777-c888-99aabbccddee 10 +01201234-5566-3777-0888-99aabbccddee 12 01201234-5566-3777-0888-99aabbccddee 12 +01401234-5566-3777-c888-99aabbccddee 14 01401234-5566-3777-c888-99aabbccddee 14 +01601234-5566-4777-0888-99aabbccddee 16 01601234-5566-4777-0888-99aabbccddee 16 +01801234-5566-4777-c888-99aabbccddee 18 01801234-5566-4777-c888-99aabbccddee 18 +02001234-5566-5777-0888-99aabbccddee 20 02001234-5566-5777-0888-99aabbccddee 20 +02201234-5566-5777-c888-99aabbccddee 22 02201234-5566-5777-c888-99aabbccddee 22 +02401234-5566-6777-0888-99aabbccddee 24 02401234-5566-6777-0888-99aabbccddee 24 +02601234-5566-6777-c888-99aabbccddee 26 02601234-5566-6777-c888-99aabbccddee 26 +02801234-5566-7777-0888-99aabbccddee 28 02801234-5566-7777-0888-99aabbccddee 28 +03001234-5566-7777-c888-99aabbccddee 30 03001234-5566-7777-c888-99aabbccddee 30 +03401234-5566-8777-c888-99aabbccddee 34 03401234-5566-8777-c888-99aabbccddee 34 +03801234-5566-9777-c888-99aabbccddee 38 03801234-5566-9777-c888-99aabbccddee 38 +04201234-5566-a777-c888-99aabbccddee 42 04201234-5566-a777-c888-99aabbccddee 42 +04601234-5566-b777-c888-99aabbccddee 46 04601234-5566-b777-c888-99aabbccddee 46 +05001234-5566-c777-c888-99aabbccddee 50 05001234-5566-c777-c888-99aabbccddee 50 +05401234-5566-d777-c888-99aabbccddee 54 05401234-5566-d777-c888-99aabbccddee 54 +05801234-5566-e777-c888-99aabbccddee 58 05801234-5566-e777-c888-99aabbccddee 58 +06201234-5566-f777-c888-99aabbccddee 62 06201234-5566-f777-c888-99aabbccddee 62 +10101234-5566-0777-8888-99aabbccddee 1 10101234-5566-0777-8888-99aabbccddee 1 +10301234-5566-0777-e888-99aabbccddee 3 10301234-5566-0777-e888-99aabbccddee 3 +10501234-5566-1777-8888-99aabbccddee 5 10501234-5566-1777-8888-99aabbccddee 5 +10701234-5566-1777-e888-99aabbccddee 7 10701234-5566-1777-e888-99aabbccddee 7 +10901234-5566-2777-8888-99aabbccddee 9 10901234-5566-2777-8888-99aabbccddee 9 +11101234-5566-2777-e888-99aabbccddee 11 11101234-5566-2777-e888-99aabbccddee 11 +11301234-5566-3777-8888-99aabbccddee 13 11301234-5566-3777-8888-99aabbccddee 13 +11501234-5566-3777-e888-99aabbccddee 15 11501234-5566-3777-e888-99aabbccddee 15 +11701234-5566-4777-8888-99aabbccddee 17 11701234-5566-4777-8888-99aabbccddee 17 +11901234-5566-4777-e888-99aabbccddee 19 11901234-5566-4777-e888-99aabbccddee 19 +12101234-5566-5777-8888-99aabbccddee 21 12101234-5566-5777-8888-99aabbccddee 21 +12301234-5566-5777-e888-99aabbccddee 23 12301234-5566-5777-e888-99aabbccddee 23 +12501234-5566-6777-8888-99aabbccddee 25 12501234-5566-6777-8888-99aabbccddee 25 +12701234-5566-6777-e888-99aabbccddee 27 12701234-5566-6777-e888-99aabbccddee 27 +12901234-5566-7777-8888-99aabbccddee 29 12901234-5566-7777-8888-99aabbccddee 29 +13101234-5566-7777-e888-99aabbccddee 31 13101234-5566-7777-e888-99aabbccddee 31 +13301234-5566-8777-8888-99aabbccddee 33 13301234-5566-8777-8888-99aabbccddee 33 +13501234-5566-8777-e888-99aabbccddee 35 13501234-5566-8777-e888-99aabbccddee 35 +13701234-5566-9777-8888-99aabbccddee 37 13701234-5566-9777-8888-99aabbccddee 37 +13901234-5566-9777-e888-99aabbccddee 39 13901234-5566-9777-e888-99aabbccddee 39 +14101234-5566-a777-8888-99aabbccddee 41 14101234-5566-a777-8888-99aabbccddee 41 +14301234-5566-a777-e888-99aabbccddee 43 14301234-5566-a777-e888-99aabbccddee 43 +14501234-5566-b777-8888-99aabbccddee 45 14501234-5566-b777-8888-99aabbccddee 45 +14701234-5566-b777-e888-99aabbccddee 47 14701234-5566-b777-e888-99aabbccddee 47 +14901234-5566-c777-8888-99aabbccddee 49 14901234-5566-c777-8888-99aabbccddee 49 +15101234-5566-c777-e888-99aabbccddee 51 15101234-5566-c777-e888-99aabbccddee 51 +15301234-5566-d777-8888-99aabbccddee 53 15301234-5566-d777-8888-99aabbccddee 53 +15501234-5566-d777-e888-99aabbccddee 55 15501234-5566-d777-e888-99aabbccddee 55 +15701234-5566-e777-8888-99aabbccddee 57 15701234-5566-e777-8888-99aabbccddee 57 +15901234-5566-e777-e888-99aabbccddee 59 15901234-5566-e777-e888-99aabbccddee 59 +16101234-5566-f777-8888-99aabbccddee 61 16101234-5566-f777-8888-99aabbccddee 61 +16301234-5566-f777-e888-99aabbccddee 63 16301234-5566-f777-e888-99aabbccddee 63 NULL 32 NULL NULL NULL 36 NULL NULL NULL 40 NULL NULL @@ -434,319 +435,319 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref a a 17 test.t2.a 1 Using where select * from t2 left join t1 on (t1.a=t2.a); a b a b -11223344-5566-0777-0888-99aabbccddee 0 11223344-5566-0777-0888-99aabbccddee 0 -11223344-5566-0777-8888-99aabbccddee 1 11223344-5566-0777-8888-99aabbccddee 1 -11223344-5566-0777-c888-99aabbccddee 2 11223344-5566-0777-c888-99aabbccddee 2 -11223344-5566-0777-e888-99aabbccddee 3 11223344-5566-0777-e888-99aabbccddee 3 -11223344-5566-1777-0888-99aabbccddee 4 11223344-5566-1777-0888-99aabbccddee 4 -11223344-5566-1777-8888-99aabbccddee 5 11223344-5566-1777-8888-99aabbccddee 5 -11223344-5566-1777-c888-99aabbccddee 6 11223344-5566-1777-c888-99aabbccddee 6 -11223344-5566-1777-e888-99aabbccddee 7 11223344-5566-1777-e888-99aabbccddee 7 -11223344-5566-2777-0888-99aabbccddee 8 11223344-5566-2777-0888-99aabbccddee 8 -11223344-5566-2777-8888-99aabbccddee 9 11223344-5566-2777-8888-99aabbccddee 9 -11223344-5566-2777-c888-99aabbccddee 10 11223344-5566-2777-c888-99aabbccddee 10 -11223344-5566-2777-e888-99aabbccddee 11 11223344-5566-2777-e888-99aabbccddee 11 -11223344-5566-3777-0888-99aabbccddee 12 11223344-5566-3777-0888-99aabbccddee 12 -11223344-5566-3777-8888-99aabbccddee 13 11223344-5566-3777-8888-99aabbccddee 13 -11223344-5566-3777-c888-99aabbccddee 14 11223344-5566-3777-c888-99aabbccddee 14 -11223344-5566-3777-e888-99aabbccddee 15 11223344-5566-3777-e888-99aabbccddee 15 -11223344-5566-4777-0888-99aabbccddee 16 11223344-5566-4777-0888-99aabbccddee 16 -11223344-5566-4777-8888-99aabbccddee 17 11223344-5566-4777-8888-99aabbccddee 17 -11223344-5566-4777-c888-99aabbccddee 18 11223344-5566-4777-c888-99aabbccddee 18 -11223344-5566-4777-e888-99aabbccddee 19 11223344-5566-4777-e888-99aabbccddee 19 -11223344-5566-5777-0888-99aabbccddee 20 11223344-5566-5777-0888-99aabbccddee 20 -11223344-5566-5777-8888-99aabbccddee 21 11223344-5566-5777-8888-99aabbccddee 21 -11223344-5566-5777-c888-99aabbccddee 22 11223344-5566-5777-c888-99aabbccddee 22 -11223344-5566-5777-e888-99aabbccddee 23 11223344-5566-5777-e888-99aabbccddee 23 -11223344-5566-6777-0888-99aabbccddee 24 11223344-5566-6777-0888-99aabbccddee 24 -11223344-5566-6777-8888-99aabbccddee 25 11223344-5566-6777-8888-99aabbccddee 25 -11223344-5566-6777-c888-99aabbccddee 26 11223344-5566-6777-c888-99aabbccddee 26 -11223344-5566-6777-e888-99aabbccddee 27 11223344-5566-6777-e888-99aabbccddee 27 -11223344-5566-7777-0888-99aabbccddee 28 11223344-5566-7777-0888-99aabbccddee 28 -11223344-5566-7777-8888-99aabbccddee 29 11223344-5566-7777-8888-99aabbccddee 29 -11223344-5566-7777-c888-99aabbccddee 30 11223344-5566-7777-c888-99aabbccddee 30 -11223344-5566-7777-e888-99aabbccddee 31 11223344-5566-7777-e888-99aabbccddee 31 -11223344-5566-8777-0888-99aabbccddee 32 NULL NULL -11223344-5566-8777-8888-99aabbccddee 33 11223344-5566-8777-8888-99aabbccddee 33 -11223344-5566-8777-c888-99aabbccddee 34 11223344-5566-8777-c888-99aabbccddee 34 -11223344-5566-8777-e888-99aabbccddee 35 11223344-5566-8777-e888-99aabbccddee 35 -11223344-5566-9777-0888-99aabbccddee 36 NULL NULL -11223344-5566-9777-8888-99aabbccddee 37 11223344-5566-9777-8888-99aabbccddee 37 -11223344-5566-9777-c888-99aabbccddee 38 11223344-5566-9777-c888-99aabbccddee 38 -11223344-5566-9777-e888-99aabbccddee 39 11223344-5566-9777-e888-99aabbccddee 39 -11223344-5566-a777-0888-99aabbccddee 40 NULL NULL -11223344-5566-a777-8888-99aabbccddee 41 11223344-5566-a777-8888-99aabbccddee 41 -11223344-5566-a777-c888-99aabbccddee 42 11223344-5566-a777-c888-99aabbccddee 42 -11223344-5566-a777-e888-99aabbccddee 43 11223344-5566-a777-e888-99aabbccddee 43 -11223344-5566-b777-0888-99aabbccddee 44 NULL NULL -11223344-5566-b777-8888-99aabbccddee 45 11223344-5566-b777-8888-99aabbccddee 45 -11223344-5566-b777-c888-99aabbccddee 46 11223344-5566-b777-c888-99aabbccddee 46 -11223344-5566-b777-e888-99aabbccddee 47 11223344-5566-b777-e888-99aabbccddee 47 -11223344-5566-c777-0888-99aabbccddee 48 NULL NULL -11223344-5566-c777-8888-99aabbccddee 49 11223344-5566-c777-8888-99aabbccddee 49 -11223344-5566-c777-c888-99aabbccddee 50 11223344-5566-c777-c888-99aabbccddee 50 -11223344-5566-c777-e888-99aabbccddee 51 11223344-5566-c777-e888-99aabbccddee 51 -11223344-5566-d777-0888-99aabbccddee 52 NULL NULL -11223344-5566-d777-8888-99aabbccddee 53 11223344-5566-d777-8888-99aabbccddee 53 -11223344-5566-d777-c888-99aabbccddee 54 11223344-5566-d777-c888-99aabbccddee 54 -11223344-5566-d777-e888-99aabbccddee 55 11223344-5566-d777-e888-99aabbccddee 55 -11223344-5566-e777-0888-99aabbccddee 56 NULL NULL -11223344-5566-e777-8888-99aabbccddee 57 11223344-5566-e777-8888-99aabbccddee 57 -11223344-5566-e777-c888-99aabbccddee 58 11223344-5566-e777-c888-99aabbccddee 58 -11223344-5566-e777-e888-99aabbccddee 59 11223344-5566-e777-e888-99aabbccddee 59 -11223344-5566-f777-0888-99aabbccddee 60 NULL NULL -11223344-5566-f777-8888-99aabbccddee 61 11223344-5566-f777-8888-99aabbccddee 61 -11223344-5566-f777-c888-99aabbccddee 62 11223344-5566-f777-c888-99aabbccddee 62 -11223344-5566-f777-e888-99aabbccddee 63 11223344-5566-f777-e888-99aabbccddee 63 +00001234-5566-0777-0888-99aabbccddee 0 00001234-5566-0777-0888-99aabbccddee 0 +00201234-5566-0777-c888-99aabbccddee 2 00201234-5566-0777-c888-99aabbccddee 2 +00401234-5566-1777-0888-99aabbccddee 4 00401234-5566-1777-0888-99aabbccddee 4 +00601234-5566-1777-c888-99aabbccddee 6 00601234-5566-1777-c888-99aabbccddee 6 +00801234-5566-2777-0888-99aabbccddee 8 00801234-5566-2777-0888-99aabbccddee 8 +01001234-5566-2777-c888-99aabbccddee 10 01001234-5566-2777-c888-99aabbccddee 10 +01201234-5566-3777-0888-99aabbccddee 12 01201234-5566-3777-0888-99aabbccddee 12 +01401234-5566-3777-c888-99aabbccddee 14 01401234-5566-3777-c888-99aabbccddee 14 +01601234-5566-4777-0888-99aabbccddee 16 01601234-5566-4777-0888-99aabbccddee 16 +01801234-5566-4777-c888-99aabbccddee 18 01801234-5566-4777-c888-99aabbccddee 18 +02001234-5566-5777-0888-99aabbccddee 20 02001234-5566-5777-0888-99aabbccddee 20 +02201234-5566-5777-c888-99aabbccddee 22 02201234-5566-5777-c888-99aabbccddee 22 +02401234-5566-6777-0888-99aabbccddee 24 02401234-5566-6777-0888-99aabbccddee 24 +02601234-5566-6777-c888-99aabbccddee 26 02601234-5566-6777-c888-99aabbccddee 26 +02801234-5566-7777-0888-99aabbccddee 28 02801234-5566-7777-0888-99aabbccddee 28 +03001234-5566-7777-c888-99aabbccddee 30 03001234-5566-7777-c888-99aabbccddee 30 +03201234-5566-8777-0888-99aabbccddee 32 NULL NULL +03401234-5566-8777-c888-99aabbccddee 34 03401234-5566-8777-c888-99aabbccddee 34 +03601234-5566-9777-0888-99aabbccddee 36 NULL NULL +03801234-5566-9777-c888-99aabbccddee 38 03801234-5566-9777-c888-99aabbccddee 38 +04001234-5566-a777-0888-99aabbccddee 40 NULL NULL +04201234-5566-a777-c888-99aabbccddee 42 04201234-5566-a777-c888-99aabbccddee 42 +04401234-5566-b777-0888-99aabbccddee 44 NULL NULL +04601234-5566-b777-c888-99aabbccddee 46 04601234-5566-b777-c888-99aabbccddee 46 +04801234-5566-c777-0888-99aabbccddee 48 NULL NULL +05001234-5566-c777-c888-99aabbccddee 50 05001234-5566-c777-c888-99aabbccddee 50 +05201234-5566-d777-0888-99aabbccddee 52 NULL NULL +05401234-5566-d777-c888-99aabbccddee 54 05401234-5566-d777-c888-99aabbccddee 54 +05601234-5566-e777-0888-99aabbccddee 56 NULL NULL +05801234-5566-e777-c888-99aabbccddee 58 05801234-5566-e777-c888-99aabbccddee 58 +06001234-5566-f777-0888-99aabbccddee 60 NULL NULL +06201234-5566-f777-c888-99aabbccddee 62 06201234-5566-f777-c888-99aabbccddee 62 +10101234-5566-0777-8888-99aabbccddee 1 10101234-5566-0777-8888-99aabbccddee 1 +10301234-5566-0777-e888-99aabbccddee 3 10301234-5566-0777-e888-99aabbccddee 3 +10501234-5566-1777-8888-99aabbccddee 5 10501234-5566-1777-8888-99aabbccddee 5 +10701234-5566-1777-e888-99aabbccddee 7 10701234-5566-1777-e888-99aabbccddee 7 +10901234-5566-2777-8888-99aabbccddee 9 10901234-5566-2777-8888-99aabbccddee 9 +11101234-5566-2777-e888-99aabbccddee 11 11101234-5566-2777-e888-99aabbccddee 11 +11301234-5566-3777-8888-99aabbccddee 13 11301234-5566-3777-8888-99aabbccddee 13 +11501234-5566-3777-e888-99aabbccddee 15 11501234-5566-3777-e888-99aabbccddee 15 +11701234-5566-4777-8888-99aabbccddee 17 11701234-5566-4777-8888-99aabbccddee 17 +11901234-5566-4777-e888-99aabbccddee 19 11901234-5566-4777-e888-99aabbccddee 19 +12101234-5566-5777-8888-99aabbccddee 21 12101234-5566-5777-8888-99aabbccddee 21 +12301234-5566-5777-e888-99aabbccddee 23 12301234-5566-5777-e888-99aabbccddee 23 +12501234-5566-6777-8888-99aabbccddee 25 12501234-5566-6777-8888-99aabbccddee 25 +12701234-5566-6777-e888-99aabbccddee 27 12701234-5566-6777-e888-99aabbccddee 27 +12901234-5566-7777-8888-99aabbccddee 29 12901234-5566-7777-8888-99aabbccddee 29 +13101234-5566-7777-e888-99aabbccddee 31 13101234-5566-7777-e888-99aabbccddee 31 +13301234-5566-8777-8888-99aabbccddee 33 13301234-5566-8777-8888-99aabbccddee 33 +13501234-5566-8777-e888-99aabbccddee 35 13501234-5566-8777-e888-99aabbccddee 35 +13701234-5566-9777-8888-99aabbccddee 37 13701234-5566-9777-8888-99aabbccddee 37 +13901234-5566-9777-e888-99aabbccddee 39 13901234-5566-9777-e888-99aabbccddee 39 +14101234-5566-a777-8888-99aabbccddee 41 14101234-5566-a777-8888-99aabbccddee 41 +14301234-5566-a777-e888-99aabbccddee 43 14301234-5566-a777-e888-99aabbccddee 43 +14501234-5566-b777-8888-99aabbccddee 45 14501234-5566-b777-8888-99aabbccddee 45 +14701234-5566-b777-e888-99aabbccddee 47 14701234-5566-b777-e888-99aabbccddee 47 +14901234-5566-c777-8888-99aabbccddee 49 14901234-5566-c777-8888-99aabbccddee 49 +15101234-5566-c777-e888-99aabbccddee 51 15101234-5566-c777-e888-99aabbccddee 51 +15301234-5566-d777-8888-99aabbccddee 53 15301234-5566-d777-8888-99aabbccddee 53 +15501234-5566-d777-e888-99aabbccddee 55 15501234-5566-d777-e888-99aabbccddee 55 +15701234-5566-e777-8888-99aabbccddee 57 15701234-5566-e777-8888-99aabbccddee 57 +15901234-5566-e777-e888-99aabbccddee 59 15901234-5566-e777-e888-99aabbccddee 59 +16101234-5566-f777-8888-99aabbccddee 61 16101234-5566-f777-8888-99aabbccddee 61 +16301234-5566-f777-e888-99aabbccddee 63 16301234-5566-f777-e888-99aabbccddee 63 explain select * from t2 left join t1 on (t1.a<=>t2.a); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 64 1 SIMPLE t1 ref a a 17 test.t2.a 1 Using where select * from t2 left join t1 on (t1.a<=>t2.a); a b a b -11223344-5566-0777-0888-99aabbccddee 0 11223344-5566-0777-0888-99aabbccddee 0 -11223344-5566-0777-8888-99aabbccddee 1 11223344-5566-0777-8888-99aabbccddee 1 -11223344-5566-0777-c888-99aabbccddee 2 11223344-5566-0777-c888-99aabbccddee 2 -11223344-5566-0777-e888-99aabbccddee 3 11223344-5566-0777-e888-99aabbccddee 3 -11223344-5566-1777-0888-99aabbccddee 4 11223344-5566-1777-0888-99aabbccddee 4 -11223344-5566-1777-8888-99aabbccddee 5 11223344-5566-1777-8888-99aabbccddee 5 -11223344-5566-1777-c888-99aabbccddee 6 11223344-5566-1777-c888-99aabbccddee 6 -11223344-5566-1777-e888-99aabbccddee 7 11223344-5566-1777-e888-99aabbccddee 7 -11223344-5566-2777-0888-99aabbccddee 8 11223344-5566-2777-0888-99aabbccddee 8 -11223344-5566-2777-8888-99aabbccddee 9 11223344-5566-2777-8888-99aabbccddee 9 -11223344-5566-2777-c888-99aabbccddee 10 11223344-5566-2777-c888-99aabbccddee 10 -11223344-5566-2777-e888-99aabbccddee 11 11223344-5566-2777-e888-99aabbccddee 11 -11223344-5566-3777-0888-99aabbccddee 12 11223344-5566-3777-0888-99aabbccddee 12 -11223344-5566-3777-8888-99aabbccddee 13 11223344-5566-3777-8888-99aabbccddee 13 -11223344-5566-3777-c888-99aabbccddee 14 11223344-5566-3777-c888-99aabbccddee 14 -11223344-5566-3777-e888-99aabbccddee 15 11223344-5566-3777-e888-99aabbccddee 15 -11223344-5566-4777-0888-99aabbccddee 16 11223344-5566-4777-0888-99aabbccddee 16 -11223344-5566-4777-8888-99aabbccddee 17 11223344-5566-4777-8888-99aabbccddee 17 -11223344-5566-4777-c888-99aabbccddee 18 11223344-5566-4777-c888-99aabbccddee 18 -11223344-5566-4777-e888-99aabbccddee 19 11223344-5566-4777-e888-99aabbccddee 19 -11223344-5566-5777-0888-99aabbccddee 20 11223344-5566-5777-0888-99aabbccddee 20 -11223344-5566-5777-8888-99aabbccddee 21 11223344-5566-5777-8888-99aabbccddee 21 -11223344-5566-5777-c888-99aabbccddee 22 11223344-5566-5777-c888-99aabbccddee 22 -11223344-5566-5777-e888-99aabbccddee 23 11223344-5566-5777-e888-99aabbccddee 23 -11223344-5566-6777-0888-99aabbccddee 24 11223344-5566-6777-0888-99aabbccddee 24 -11223344-5566-6777-8888-99aabbccddee 25 11223344-5566-6777-8888-99aabbccddee 25 -11223344-5566-6777-c888-99aabbccddee 26 11223344-5566-6777-c888-99aabbccddee 26 -11223344-5566-6777-e888-99aabbccddee 27 11223344-5566-6777-e888-99aabbccddee 27 -11223344-5566-7777-0888-99aabbccddee 28 11223344-5566-7777-0888-99aabbccddee 28 -11223344-5566-7777-8888-99aabbccddee 29 11223344-5566-7777-8888-99aabbccddee 29 -11223344-5566-7777-c888-99aabbccddee 30 11223344-5566-7777-c888-99aabbccddee 30 -11223344-5566-7777-e888-99aabbccddee 31 11223344-5566-7777-e888-99aabbccddee 31 -11223344-5566-8777-0888-99aabbccddee 32 NULL 32 -11223344-5566-8777-0888-99aabbccddee 32 NULL 36 -11223344-5566-8777-0888-99aabbccddee 32 NULL 40 -11223344-5566-8777-0888-99aabbccddee 32 NULL 44 -11223344-5566-8777-0888-99aabbccddee 32 NULL 48 -11223344-5566-8777-0888-99aabbccddee 32 NULL 52 -11223344-5566-8777-0888-99aabbccddee 32 NULL 56 -11223344-5566-8777-0888-99aabbccddee 32 NULL 60 -11223344-5566-8777-8888-99aabbccddee 33 11223344-5566-8777-8888-99aabbccddee 33 -11223344-5566-8777-c888-99aabbccddee 34 11223344-5566-8777-c888-99aabbccddee 34 -11223344-5566-8777-e888-99aabbccddee 35 11223344-5566-8777-e888-99aabbccddee 35 -11223344-5566-9777-0888-99aabbccddee 36 NULL 32 -11223344-5566-9777-0888-99aabbccddee 36 NULL 36 -11223344-5566-9777-0888-99aabbccddee 36 NULL 40 -11223344-5566-9777-0888-99aabbccddee 36 NULL 44 -11223344-5566-9777-0888-99aabbccddee 36 NULL 48 -11223344-5566-9777-0888-99aabbccddee 36 NULL 52 -11223344-5566-9777-0888-99aabbccddee 36 NULL 56 -11223344-5566-9777-0888-99aabbccddee 36 NULL 60 -11223344-5566-9777-8888-99aabbccddee 37 11223344-5566-9777-8888-99aabbccddee 37 -11223344-5566-9777-c888-99aabbccddee 38 11223344-5566-9777-c888-99aabbccddee 38 -11223344-5566-9777-e888-99aabbccddee 39 11223344-5566-9777-e888-99aabbccddee 39 -11223344-5566-a777-0888-99aabbccddee 40 NULL 32 -11223344-5566-a777-0888-99aabbccddee 40 NULL 36 -11223344-5566-a777-0888-99aabbccddee 40 NULL 40 -11223344-5566-a777-0888-99aabbccddee 40 NULL 44 -11223344-5566-a777-0888-99aabbccddee 40 NULL 48 -11223344-5566-a777-0888-99aabbccddee 40 NULL 52 -11223344-5566-a777-0888-99aabbccddee 40 NULL 56 -11223344-5566-a777-0888-99aabbccddee 40 NULL 60 -11223344-5566-a777-8888-99aabbccddee 41 11223344-5566-a777-8888-99aabbccddee 41 -11223344-5566-a777-c888-99aabbccddee 42 11223344-5566-a777-c888-99aabbccddee 42 -11223344-5566-a777-e888-99aabbccddee 43 11223344-5566-a777-e888-99aabbccddee 43 -11223344-5566-b777-0888-99aabbccddee 44 NULL 32 -11223344-5566-b777-0888-99aabbccddee 44 NULL 36 -11223344-5566-b777-0888-99aabbccddee 44 NULL 40 -11223344-5566-b777-0888-99aabbccddee 44 NULL 44 -11223344-5566-b777-0888-99aabbccddee 44 NULL 48 -11223344-5566-b777-0888-99aabbccddee 44 NULL 52 -11223344-5566-b777-0888-99aabbccddee 44 NULL 56 -11223344-5566-b777-0888-99aabbccddee 44 NULL 60 -11223344-5566-b777-8888-99aabbccddee 45 11223344-5566-b777-8888-99aabbccddee 45 -11223344-5566-b777-c888-99aabbccddee 46 11223344-5566-b777-c888-99aabbccddee 46 -11223344-5566-b777-e888-99aabbccddee 47 11223344-5566-b777-e888-99aabbccddee 47 -11223344-5566-c777-0888-99aabbccddee 48 NULL 32 -11223344-5566-c777-0888-99aabbccddee 48 NULL 36 -11223344-5566-c777-0888-99aabbccddee 48 NULL 40 -11223344-5566-c777-0888-99aabbccddee 48 NULL 44 -11223344-5566-c777-0888-99aabbccddee 48 NULL 48 -11223344-5566-c777-0888-99aabbccddee 48 NULL 52 -11223344-5566-c777-0888-99aabbccddee 48 NULL 56 -11223344-5566-c777-0888-99aabbccddee 48 NULL 60 -11223344-5566-c777-8888-99aabbccddee 49 11223344-5566-c777-8888-99aabbccddee 49 -11223344-5566-c777-c888-99aabbccddee 50 11223344-5566-c777-c888-99aabbccddee 50 -11223344-5566-c777-e888-99aabbccddee 51 11223344-5566-c777-e888-99aabbccddee 51 -11223344-5566-d777-0888-99aabbccddee 52 NULL 32 -11223344-5566-d777-0888-99aabbccddee 52 NULL 36 -11223344-5566-d777-0888-99aabbccddee 52 NULL 40 -11223344-5566-d777-0888-99aabbccddee 52 NULL 44 -11223344-5566-d777-0888-99aabbccddee 52 NULL 48 -11223344-5566-d777-0888-99aabbccddee 52 NULL 52 -11223344-5566-d777-0888-99aabbccddee 52 NULL 56 -11223344-5566-d777-0888-99aabbccddee 52 NULL 60 -11223344-5566-d777-8888-99aabbccddee 53 11223344-5566-d777-8888-99aabbccddee 53 -11223344-5566-d777-c888-99aabbccddee 54 11223344-5566-d777-c888-99aabbccddee 54 -11223344-5566-d777-e888-99aabbccddee 55 11223344-5566-d777-e888-99aabbccddee 55 -11223344-5566-e777-0888-99aabbccddee 56 NULL 32 -11223344-5566-e777-0888-99aabbccddee 56 NULL 36 -11223344-5566-e777-0888-99aabbccddee 56 NULL 40 -11223344-5566-e777-0888-99aabbccddee 56 NULL 44 -11223344-5566-e777-0888-99aabbccddee 56 NULL 48 -11223344-5566-e777-0888-99aabbccddee 56 NULL 52 -11223344-5566-e777-0888-99aabbccddee 56 NULL 56 -11223344-5566-e777-0888-99aabbccddee 56 NULL 60 -11223344-5566-e777-8888-99aabbccddee 57 11223344-5566-e777-8888-99aabbccddee 57 -11223344-5566-e777-c888-99aabbccddee 58 11223344-5566-e777-c888-99aabbccddee 58 -11223344-5566-e777-e888-99aabbccddee 59 11223344-5566-e777-e888-99aabbccddee 59 -11223344-5566-f777-0888-99aabbccddee 60 NULL 32 -11223344-5566-f777-0888-99aabbccddee 60 NULL 36 -11223344-5566-f777-0888-99aabbccddee 60 NULL 40 -11223344-5566-f777-0888-99aabbccddee 60 NULL 44 -11223344-5566-f777-0888-99aabbccddee 60 NULL 48 -11223344-5566-f777-0888-99aabbccddee 60 NULL 52 -11223344-5566-f777-0888-99aabbccddee 60 NULL 56 -11223344-5566-f777-0888-99aabbccddee 60 NULL 60 -11223344-5566-f777-8888-99aabbccddee 61 11223344-5566-f777-8888-99aabbccddee 61 -11223344-5566-f777-c888-99aabbccddee 62 11223344-5566-f777-c888-99aabbccddee 62 -11223344-5566-f777-e888-99aabbccddee 63 11223344-5566-f777-e888-99aabbccddee 63 -Warning 1292 Incorrect uuid value: '11223344-5566-8777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-8777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-8777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-8777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-8777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-8777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-8777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-8777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-8777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-9777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-9777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-9777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-9777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-9777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-9777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-9777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-9777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-9777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-a777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-a777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-a777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-a777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-a777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-a777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-a777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-a777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-a777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-b777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-b777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-b777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-b777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-b777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-b777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-b777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-b777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-b777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-c777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-c777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-c777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-c777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-c777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-c777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-c777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-c777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-c777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-d777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-d777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-d777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-d777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-d777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-d777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-d777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-d777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-d777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-e777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-e777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-e777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-e777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-e777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-e777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-e777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-e777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-e777-0888-99aabbccddee' -Warning 1292 Incorrect uuid value: '11223344-5566-f777-0888-99aabbccddee' +00001234-5566-0777-0888-99aabbccddee 0 00001234-5566-0777-0888-99aabbccddee 0 +00201234-5566-0777-c888-99aabbccddee 2 00201234-5566-0777-c888-99aabbccddee 2 +00401234-5566-1777-0888-99aabbccddee 4 00401234-5566-1777-0888-99aabbccddee 4 +00601234-5566-1777-c888-99aabbccddee 6 00601234-5566-1777-c888-99aabbccddee 6 +00801234-5566-2777-0888-99aabbccddee 8 00801234-5566-2777-0888-99aabbccddee 8 +01001234-5566-2777-c888-99aabbccddee 10 01001234-5566-2777-c888-99aabbccddee 10 +01201234-5566-3777-0888-99aabbccddee 12 01201234-5566-3777-0888-99aabbccddee 12 +01401234-5566-3777-c888-99aabbccddee 14 01401234-5566-3777-c888-99aabbccddee 14 +01601234-5566-4777-0888-99aabbccddee 16 01601234-5566-4777-0888-99aabbccddee 16 +01801234-5566-4777-c888-99aabbccddee 18 01801234-5566-4777-c888-99aabbccddee 18 +02001234-5566-5777-0888-99aabbccddee 20 02001234-5566-5777-0888-99aabbccddee 20 +02201234-5566-5777-c888-99aabbccddee 22 02201234-5566-5777-c888-99aabbccddee 22 +02401234-5566-6777-0888-99aabbccddee 24 02401234-5566-6777-0888-99aabbccddee 24 +02601234-5566-6777-c888-99aabbccddee 26 02601234-5566-6777-c888-99aabbccddee 26 +02801234-5566-7777-0888-99aabbccddee 28 02801234-5566-7777-0888-99aabbccddee 28 +03001234-5566-7777-c888-99aabbccddee 30 03001234-5566-7777-c888-99aabbccddee 30 +03201234-5566-8777-0888-99aabbccddee 32 NULL 32 +03201234-5566-8777-0888-99aabbccddee 32 NULL 36 +03201234-5566-8777-0888-99aabbccddee 32 NULL 40 +03201234-5566-8777-0888-99aabbccddee 32 NULL 44 +03201234-5566-8777-0888-99aabbccddee 32 NULL 48 +03201234-5566-8777-0888-99aabbccddee 32 NULL 52 +03201234-5566-8777-0888-99aabbccddee 32 NULL 56 +03201234-5566-8777-0888-99aabbccddee 32 NULL 60 +03401234-5566-8777-c888-99aabbccddee 34 03401234-5566-8777-c888-99aabbccddee 34 +03601234-5566-9777-0888-99aabbccddee 36 NULL 32 +03601234-5566-9777-0888-99aabbccddee 36 NULL 36 +03601234-5566-9777-0888-99aabbccddee 36 NULL 40 +03601234-5566-9777-0888-99aabbccddee 36 NULL 44 +03601234-5566-9777-0888-99aabbccddee 36 NULL 48 +03601234-5566-9777-0888-99aabbccddee 36 NULL 52 +03601234-5566-9777-0888-99aabbccddee 36 NULL 56 +03601234-5566-9777-0888-99aabbccddee 36 NULL 60 +03801234-5566-9777-c888-99aabbccddee 38 03801234-5566-9777-c888-99aabbccddee 38 +04001234-5566-a777-0888-99aabbccddee 40 NULL 32 +04001234-5566-a777-0888-99aabbccddee 40 NULL 36 +04001234-5566-a777-0888-99aabbccddee 40 NULL 40 +04001234-5566-a777-0888-99aabbccddee 40 NULL 44 +04001234-5566-a777-0888-99aabbccddee 40 NULL 48 +04001234-5566-a777-0888-99aabbccddee 40 NULL 52 +04001234-5566-a777-0888-99aabbccddee 40 NULL 56 +04001234-5566-a777-0888-99aabbccddee 40 NULL 60 +04201234-5566-a777-c888-99aabbccddee 42 04201234-5566-a777-c888-99aabbccddee 42 +04401234-5566-b777-0888-99aabbccddee 44 NULL 32 +04401234-5566-b777-0888-99aabbccddee 44 NULL 36 +04401234-5566-b777-0888-99aabbccddee 44 NULL 40 +04401234-5566-b777-0888-99aabbccddee 44 NULL 44 +04401234-5566-b777-0888-99aabbccddee 44 NULL 48 +04401234-5566-b777-0888-99aabbccddee 44 NULL 52 +04401234-5566-b777-0888-99aabbccddee 44 NULL 56 +04401234-5566-b777-0888-99aabbccddee 44 NULL 60 +04601234-5566-b777-c888-99aabbccddee 46 04601234-5566-b777-c888-99aabbccddee 46 +04801234-5566-c777-0888-99aabbccddee 48 NULL 32 +04801234-5566-c777-0888-99aabbccddee 48 NULL 36 +04801234-5566-c777-0888-99aabbccddee 48 NULL 40 +04801234-5566-c777-0888-99aabbccddee 48 NULL 44 +04801234-5566-c777-0888-99aabbccddee 48 NULL 48 +04801234-5566-c777-0888-99aabbccddee 48 NULL 52 +04801234-5566-c777-0888-99aabbccddee 48 NULL 56 +04801234-5566-c777-0888-99aabbccddee 48 NULL 60 +05001234-5566-c777-c888-99aabbccddee 50 05001234-5566-c777-c888-99aabbccddee 50 +05201234-5566-d777-0888-99aabbccddee 52 NULL 32 +05201234-5566-d777-0888-99aabbccddee 52 NULL 36 +05201234-5566-d777-0888-99aabbccddee 52 NULL 40 +05201234-5566-d777-0888-99aabbccddee 52 NULL 44 +05201234-5566-d777-0888-99aabbccddee 52 NULL 48 +05201234-5566-d777-0888-99aabbccddee 52 NULL 52 +05201234-5566-d777-0888-99aabbccddee 52 NULL 56 +05201234-5566-d777-0888-99aabbccddee 52 NULL 60 +05401234-5566-d777-c888-99aabbccddee 54 05401234-5566-d777-c888-99aabbccddee 54 +05601234-5566-e777-0888-99aabbccddee 56 NULL 32 +05601234-5566-e777-0888-99aabbccddee 56 NULL 36 +05601234-5566-e777-0888-99aabbccddee 56 NULL 40 +05601234-5566-e777-0888-99aabbccddee 56 NULL 44 +05601234-5566-e777-0888-99aabbccddee 56 NULL 48 +05601234-5566-e777-0888-99aabbccddee 56 NULL 52 +05601234-5566-e777-0888-99aabbccddee 56 NULL 56 +05601234-5566-e777-0888-99aabbccddee 56 NULL 60 +05801234-5566-e777-c888-99aabbccddee 58 05801234-5566-e777-c888-99aabbccddee 58 +06001234-5566-f777-0888-99aabbccddee 60 NULL 32 +06001234-5566-f777-0888-99aabbccddee 60 NULL 36 +06001234-5566-f777-0888-99aabbccddee 60 NULL 40 +06001234-5566-f777-0888-99aabbccddee 60 NULL 44 +06001234-5566-f777-0888-99aabbccddee 60 NULL 48 +06001234-5566-f777-0888-99aabbccddee 60 NULL 52 +06001234-5566-f777-0888-99aabbccddee 60 NULL 56 +06001234-5566-f777-0888-99aabbccddee 60 NULL 60 +06201234-5566-f777-c888-99aabbccddee 62 06201234-5566-f777-c888-99aabbccddee 62 +10101234-5566-0777-8888-99aabbccddee 1 10101234-5566-0777-8888-99aabbccddee 1 +10301234-5566-0777-e888-99aabbccddee 3 10301234-5566-0777-e888-99aabbccddee 3 +10501234-5566-1777-8888-99aabbccddee 5 10501234-5566-1777-8888-99aabbccddee 5 +10701234-5566-1777-e888-99aabbccddee 7 10701234-5566-1777-e888-99aabbccddee 7 +10901234-5566-2777-8888-99aabbccddee 9 10901234-5566-2777-8888-99aabbccddee 9 +11101234-5566-2777-e888-99aabbccddee 11 11101234-5566-2777-e888-99aabbccddee 11 +11301234-5566-3777-8888-99aabbccddee 13 11301234-5566-3777-8888-99aabbccddee 13 +11501234-5566-3777-e888-99aabbccddee 15 11501234-5566-3777-e888-99aabbccddee 15 +11701234-5566-4777-8888-99aabbccddee 17 11701234-5566-4777-8888-99aabbccddee 17 +11901234-5566-4777-e888-99aabbccddee 19 11901234-5566-4777-e888-99aabbccddee 19 +12101234-5566-5777-8888-99aabbccddee 21 12101234-5566-5777-8888-99aabbccddee 21 +12301234-5566-5777-e888-99aabbccddee 23 12301234-5566-5777-e888-99aabbccddee 23 +12501234-5566-6777-8888-99aabbccddee 25 12501234-5566-6777-8888-99aabbccddee 25 +12701234-5566-6777-e888-99aabbccddee 27 12701234-5566-6777-e888-99aabbccddee 27 +12901234-5566-7777-8888-99aabbccddee 29 12901234-5566-7777-8888-99aabbccddee 29 +13101234-5566-7777-e888-99aabbccddee 31 13101234-5566-7777-e888-99aabbccddee 31 +13301234-5566-8777-8888-99aabbccddee 33 13301234-5566-8777-8888-99aabbccddee 33 +13501234-5566-8777-e888-99aabbccddee 35 13501234-5566-8777-e888-99aabbccddee 35 +13701234-5566-9777-8888-99aabbccddee 37 13701234-5566-9777-8888-99aabbccddee 37 +13901234-5566-9777-e888-99aabbccddee 39 13901234-5566-9777-e888-99aabbccddee 39 +14101234-5566-a777-8888-99aabbccddee 41 14101234-5566-a777-8888-99aabbccddee 41 +14301234-5566-a777-e888-99aabbccddee 43 14301234-5566-a777-e888-99aabbccddee 43 +14501234-5566-b777-8888-99aabbccddee 45 14501234-5566-b777-8888-99aabbccddee 45 +14701234-5566-b777-e888-99aabbccddee 47 14701234-5566-b777-e888-99aabbccddee 47 +14901234-5566-c777-8888-99aabbccddee 49 14901234-5566-c777-8888-99aabbccddee 49 +15101234-5566-c777-e888-99aabbccddee 51 15101234-5566-c777-e888-99aabbccddee 51 +15301234-5566-d777-8888-99aabbccddee 53 15301234-5566-d777-8888-99aabbccddee 53 +15501234-5566-d777-e888-99aabbccddee 55 15501234-5566-d777-e888-99aabbccddee 55 +15701234-5566-e777-8888-99aabbccddee 57 15701234-5566-e777-8888-99aabbccddee 57 +15901234-5566-e777-e888-99aabbccddee 59 15901234-5566-e777-e888-99aabbccddee 59 +16101234-5566-f777-8888-99aabbccddee 61 16101234-5566-f777-8888-99aabbccddee 61 +16301234-5566-f777-e888-99aabbccddee 63 16301234-5566-f777-e888-99aabbccddee 63 +Warning 1292 Incorrect uuid value: '03201234-5566-8777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03201234-5566-8777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03201234-5566-8777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03201234-5566-8777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03201234-5566-8777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03201234-5566-8777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03201234-5566-8777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03201234-5566-8777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03201234-5566-8777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03601234-5566-9777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03601234-5566-9777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03601234-5566-9777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03601234-5566-9777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03601234-5566-9777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03601234-5566-9777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03601234-5566-9777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03601234-5566-9777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '03601234-5566-9777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04001234-5566-a777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04001234-5566-a777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04001234-5566-a777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04001234-5566-a777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04001234-5566-a777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04001234-5566-a777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04001234-5566-a777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04001234-5566-a777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04001234-5566-a777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04401234-5566-b777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04401234-5566-b777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04401234-5566-b777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04401234-5566-b777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04401234-5566-b777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04401234-5566-b777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04401234-5566-b777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04401234-5566-b777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04401234-5566-b777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04801234-5566-c777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04801234-5566-c777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04801234-5566-c777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04801234-5566-c777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04801234-5566-c777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04801234-5566-c777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04801234-5566-c777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04801234-5566-c777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '04801234-5566-c777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05201234-5566-d777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05201234-5566-d777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05201234-5566-d777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05201234-5566-d777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05201234-5566-d777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05201234-5566-d777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05201234-5566-d777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05201234-5566-d777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05201234-5566-d777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05601234-5566-e777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05601234-5566-e777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05601234-5566-e777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05601234-5566-e777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05601234-5566-e777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05601234-5566-e777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05601234-5566-e777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05601234-5566-e777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '05601234-5566-e777-0888-99aabbccddee' +Warning 1292 Incorrect uuid value: '06001234-5566-f777-0888-99aabbccddee' Warnings: select * from t1 union select * from t2; a b -11223344-5566-0777-0888-99aabbccddee 0 -11223344-5566-0777-8888-99aabbccddee 1 -11223344-5566-0777-c888-99aabbccddee 2 -11223344-5566-0777-e888-99aabbccddee 3 -11223344-5566-1777-0888-99aabbccddee 4 -11223344-5566-1777-8888-99aabbccddee 5 -11223344-5566-1777-c888-99aabbccddee 6 -11223344-5566-1777-e888-99aabbccddee 7 -11223344-5566-2777-0888-99aabbccddee 8 -11223344-5566-2777-8888-99aabbccddee 9 -11223344-5566-2777-c888-99aabbccddee 10 -11223344-5566-2777-e888-99aabbccddee 11 -11223344-5566-3777-0888-99aabbccddee 12 -11223344-5566-3777-8888-99aabbccddee 13 -11223344-5566-3777-c888-99aabbccddee 14 -11223344-5566-3777-e888-99aabbccddee 15 -11223344-5566-4777-0888-99aabbccddee 16 -11223344-5566-4777-8888-99aabbccddee 17 -11223344-5566-4777-c888-99aabbccddee 18 -11223344-5566-4777-e888-99aabbccddee 19 -11223344-5566-5777-0888-99aabbccddee 20 -11223344-5566-5777-8888-99aabbccddee 21 -11223344-5566-5777-c888-99aabbccddee 22 -11223344-5566-5777-e888-99aabbccddee 23 -11223344-5566-6777-0888-99aabbccddee 24 -11223344-5566-6777-8888-99aabbccddee 25 -11223344-5566-6777-c888-99aabbccddee 26 -11223344-5566-6777-e888-99aabbccddee 27 -11223344-5566-7777-0888-99aabbccddee 28 -11223344-5566-7777-8888-99aabbccddee 29 -11223344-5566-7777-c888-99aabbccddee 30 -11223344-5566-7777-e888-99aabbccddee 31 -11223344-5566-8777-8888-99aabbccddee 33 -11223344-5566-8777-c888-99aabbccddee 34 -11223344-5566-8777-e888-99aabbccddee 35 -11223344-5566-9777-8888-99aabbccddee 37 -11223344-5566-9777-c888-99aabbccddee 38 -11223344-5566-9777-e888-99aabbccddee 39 -11223344-5566-a777-8888-99aabbccddee 41 -11223344-5566-a777-c888-99aabbccddee 42 -11223344-5566-a777-e888-99aabbccddee 43 -11223344-5566-b777-8888-99aabbccddee 45 -11223344-5566-b777-c888-99aabbccddee 46 -11223344-5566-b777-e888-99aabbccddee 47 -11223344-5566-c777-8888-99aabbccddee 49 -11223344-5566-c777-c888-99aabbccddee 50 -11223344-5566-c777-e888-99aabbccddee 51 -11223344-5566-d777-8888-99aabbccddee 53 -11223344-5566-d777-c888-99aabbccddee 54 -11223344-5566-d777-e888-99aabbccddee 55 -11223344-5566-e777-8888-99aabbccddee 57 -11223344-5566-e777-c888-99aabbccddee 58 -11223344-5566-e777-e888-99aabbccddee 59 -11223344-5566-f777-8888-99aabbccddee 61 -11223344-5566-f777-c888-99aabbccddee 62 -11223344-5566-f777-e888-99aabbccddee 63 +00001234-5566-0777-0888-99aabbccddee 0 +00201234-5566-0777-c888-99aabbccddee 2 +00401234-5566-1777-0888-99aabbccddee 4 +00601234-5566-1777-c888-99aabbccddee 6 +00801234-5566-2777-0888-99aabbccddee 8 +01001234-5566-2777-c888-99aabbccddee 10 +01201234-5566-3777-0888-99aabbccddee 12 +01401234-5566-3777-c888-99aabbccddee 14 +01601234-5566-4777-0888-99aabbccddee 16 +01801234-5566-4777-c888-99aabbccddee 18 +02001234-5566-5777-0888-99aabbccddee 20 +02201234-5566-5777-c888-99aabbccddee 22 +02401234-5566-6777-0888-99aabbccddee 24 +02601234-5566-6777-c888-99aabbccddee 26 +02801234-5566-7777-0888-99aabbccddee 28 +03001234-5566-7777-c888-99aabbccddee 30 +03401234-5566-8777-c888-99aabbccddee 34 +03801234-5566-9777-c888-99aabbccddee 38 +04201234-5566-a777-c888-99aabbccddee 42 +04601234-5566-b777-c888-99aabbccddee 46 +05001234-5566-c777-c888-99aabbccddee 50 +05401234-5566-d777-c888-99aabbccddee 54 +05801234-5566-e777-c888-99aabbccddee 58 +06201234-5566-f777-c888-99aabbccddee 62 +10101234-5566-0777-8888-99aabbccddee 1 +10301234-5566-0777-e888-99aabbccddee 3 +10501234-5566-1777-8888-99aabbccddee 5 +10701234-5566-1777-e888-99aabbccddee 7 +10901234-5566-2777-8888-99aabbccddee 9 +11101234-5566-2777-e888-99aabbccddee 11 +11301234-5566-3777-8888-99aabbccddee 13 +11501234-5566-3777-e888-99aabbccddee 15 +11701234-5566-4777-8888-99aabbccddee 17 +11901234-5566-4777-e888-99aabbccddee 19 +12101234-5566-5777-8888-99aabbccddee 21 +12301234-5566-5777-e888-99aabbccddee 23 +12501234-5566-6777-8888-99aabbccddee 25 +12701234-5566-6777-e888-99aabbccddee 27 +12901234-5566-7777-8888-99aabbccddee 29 +13101234-5566-7777-e888-99aabbccddee 31 +13301234-5566-8777-8888-99aabbccddee 33 +13501234-5566-8777-e888-99aabbccddee 35 +13701234-5566-9777-8888-99aabbccddee 37 +13901234-5566-9777-e888-99aabbccddee 39 +14101234-5566-a777-8888-99aabbccddee 41 +14301234-5566-a777-e888-99aabbccddee 43 +14501234-5566-b777-8888-99aabbccddee 45 +14701234-5566-b777-e888-99aabbccddee 47 +14901234-5566-c777-8888-99aabbccddee 49 +15101234-5566-c777-e888-99aabbccddee 51 +15301234-5566-d777-8888-99aabbccddee 53 +15501234-5566-d777-e888-99aabbccddee 55 +15701234-5566-e777-8888-99aabbccddee 57 +15901234-5566-e777-e888-99aabbccddee 59 +16101234-5566-f777-8888-99aabbccddee 61 +16301234-5566-f777-e888-99aabbccddee 63 NULL 32 NULL 36 NULL 40 @@ -757,12 +758,12 @@ NULL 56 NULL 60 alter ignore table t2 force; Warnings: -Warning 1292 Incorrect uuid value: '11223344-5566-8777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 33 -Warning 1292 Incorrect uuid value: '11223344-5566-9777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 37 -Warning 1292 Incorrect uuid value: '11223344-5566-a777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 41 -Warning 1292 Incorrect uuid value: '11223344-5566-b777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 45 -Warning 1292 Incorrect uuid value: '11223344-5566-c777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 49 -Warning 1292 Incorrect uuid value: '11223344-5566-d777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 53 -Warning 1292 Incorrect uuid value: '11223344-5566-e777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 57 -Warning 1292 Incorrect uuid value: '11223344-5566-f777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 61 +Warning 1292 Incorrect uuid value: '03201234-5566-8777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 33 +Warning 1292 Incorrect uuid value: '03601234-5566-9777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 37 +Warning 1292 Incorrect uuid value: '04001234-5566-a777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 41 +Warning 1292 Incorrect uuid value: '04401234-5566-b777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 45 +Warning 1292 Incorrect uuid value: '04801234-5566-c777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 49 +Warning 1292 Incorrect uuid value: '05201234-5566-d777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 53 +Warning 1292 Incorrect uuid value: '05601234-5566-e777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 57 +Warning 1292 Incorrect uuid value: '06001234-5566-f777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 61 drop table t1, t2; diff --git a/plugin/type_uuid/mysql-test/type_uuid/order.test b/plugin/type_uuid/mysql-test/type_uuid/order.test index 46f76da98e3..058b6644a51 100644 --- a/plugin/type_uuid/mysql-test/type_uuid/order.test +++ b/plugin/type_uuid/mysql-test/type_uuid/order.test @@ -2,8 +2,9 @@ source include/have_sequence.inc; create table t1 (a uuid, b int not null, index (a)); -insert t1 select sformat('11223344-5566-{:x}777-{}888-99aabbccddee', seq div 4, elt(1+(seq % 4),0,8,'c','e')),seq from seq_0_to_63; -select * from t1; +insert t1 select sformat('{:03}01234-5566-{:x}777-{}888-99aabbccddee', + (seq % 2)*100 + seq, seq div 4, elt(1+(seq % 4),0,8,'c','e')),seq from seq_0_to_63; +select * from t1 order by b; select * from t1 order by a; show create table t1; @@ -12,7 +13,7 @@ let $datadir= `select @@datadir`; --copy_file $MTR_SUITE_DIR/std_data/mdev-29959.frm $datadir/test/t2.frm --copy_file $MTR_SUITE_DIR/std_data/mdev-29959.MYI $datadir/test/t2.MYI --copy_file $MTR_SUITE_DIR/std_data/mdev-29959.MYD $datadir/test/t2.MYD -select * from t2; +select * from t2 order by b; select * from t2 order by a; show create table t2; diff --git a/plugin/type_uuid/mysql-test/type_uuid/std_data/mdev-29959.MYD b/plugin/type_uuid/mysql-test/type_uuid/std_data/mdev-29959.MYD index 138a08deeb789c0e9c5fc59c0292687f8bea95df..1e0594674f52d8b9b1e3dcb20d948efcc6c5c7e8 100644 GIT binary patch literal 1344 zcmYM!yKWOv6ouh&94CkSc-c<4GhD-+0TzUN+|jy0w636amv%aKIUV8&kaz(K9)MHO zQ&Dp&TB=CQoGr0-`RUgx_ra$x-+ui16Kr$;&AXxii|!5_En``N17Y;C0@sAe%NiUC zgKhVlb8uZ~8OsGY5=JkV;D#`HxdJzZ!FKx11`I;WShnCHVazxvz{A3naa@8&gu!;Z z%|Qho6c>mxRg71$bE)>|?*V1g{7!<75S1 z6-F-`@R~4r*@8R5V4u6q^#Z&uw2addydjKUR^Uxx^0EeR34?v@H|OAOp=F#dz&pa| zGixlw>GgqCru1YZiH PmlgO*n7pjPy$=5Y9b`l; literal 1344 zcmYMsw@m{85QSl~kBmts2NO)rIW|a4fY<;=@CdvO5ECG=00jeZ1w9otSJ6^g!V;(V z{_-pS+SAM1$JdXcP`$Y;mUpij>ec=c#73bLn}k7Z78*+VY!QOkDs*C-Fo*@Ap^{G% zg4ix}Vuvt@okGK5KD&e6@p%bTsL7WyE9`ZRO1aVgA#Ii7mb3(&oKIerX zE(o2tC=6mnXn4-&k`TmYp%YhxL0lCYUh}yo1aV#H#0_B(H-(1xd~OLr+!i`-Y!D%Sk@~ diff --git a/plugin/type_uuid/mysql-test/type_uuid/std_data/mdev-29959.MYI b/plugin/type_uuid/mysql-test/type_uuid/std_data/mdev-29959.MYI index 6dde55b27da5d211f3332e10d771faa6dcf78da1..b85c5d61dd6e280da3b111dfeb53dacc154cee3d 100644 GIT binary patch literal 2048 zcmeIyxsTI86bA4&b{u;+Cyu@0#+=KIfrW4_I~|m65Cx43E{Vq7HWcpI(jDS2K%%0f zphbd$hKhYOE+w_vsBip!cN6y%KjMD%bqc zZI+K42fKz%h7!y~cH@*keN)fe%oMZy6rutBem|mzi%;*&o-<<}p0RZU>-WJmfBVSY z3A69aIrJ9|Be~UpsPLZMl%gkYeB$>Y3H+3C`}))SUtxI4h1%RUSKvQbf$%e_m#^P_ z`uZbTiI?v_B1#wJXX}Zl1qXWGvjr19byNkoP2cvcL8I?E1_WmMv8M%h>1EFr+^3&A zh6PyY7oIhERKIc@5O_kr^|as_{lT*ZOZ~+$D!>K(&9ert>Yt870&m7EoY)u)C{AoD zFyh3f12rcemEd+xJZiuZCr%BRbK{aS0yc#N!4$#)&fnp5(+?1)k-^ zSqEO=#CZu`=EQjeUgN}b23(9kO2_>I1=4Z9KtoQf`UTn|9a~(zLppB3R5~ueIqA3t z_i*Bnzys2;1rJNdEqGiyF2GaLaSfj1#1VlPrDF?Tk&avNx^!HCx8m>8alb&Jblfjc z%!x<+0&SI!D_p%(I_|)+bX9_&+a^kT84@$=sctkqxz literal 2048 zcmeIyJ5Rz;6bJBgTcABYK|y?=B0lgfii&SKnD_~dgDX)7cRqq7egNa>U`(9c99&Iw zaB*^S*2&ckye$>Ze=x?;gxmJE|9ft4`|Hqh*-~VveY&9n-IF4{+qx&pRNP)S$Ls5z zQ}J7M$o4Bir#|JUtHi0U680AA5ySXT1f=^^j@|lbyd?n*J-^w`64>D%> zMaD&blW~PVW!$hzC{`#AqL@+KisA^0V<_%HaX*TOP&|s_2^7zucpk+|C|*VJruB$o z1H~Z}H=(!<#T_W_LUAvO2T+_s@feCHQ9O&{1r#r%cn!r{);o$#6k8~6MsYieJ5d}* eaUY5YQ9O*|G>WHCJcr^eigPGlM{)j-|C}$K_sPlt diff --git a/plugin/type_uuid/mysql-test/type_uuid/std_data/mdev-29959.frm b/plugin/type_uuid/mysql-test/type_uuid/std_data/mdev-29959.frm index d03c730aff7d01664b41d0747200e8b67c72120e..ebefe982d95889b032501c9b6e255af1be11178c 100644 GIT binary patch delta 21 dcmX@kew=-R6IbF*#doFW1m88E+vrox3;<~<3D5ul delta 21 dcmX@kew=-R6W8S>g4?A{1>fy9+UQfw3; 0 && version < 6 && variant != 0 + static bool mem_need_swap(const char *s) + { return s[6] > 0 && s[6] < 0x60 && s[8] & 0x80; } + + // s[6] & 0x80 && s[8] > 0: this means a swapped uuid + static bool rec_need_swap(const char *s) + { return s[6] & -s[8] & 0x80; } + // Convert the in-memory representation to the in-record representation static void memory_to_record(char *to, const char *from) { - if (force_swap || (from[6] > 0 && from[6] < 0x60 && from[8] & 0x80)) + if (force_swap || mem_need_swap(from)) { - segment(0).memory_to_record(to, from); - segment(1).memory_to_record(to, from); - segment(2).memory_to_record(to, from); - segment(3).memory_to_record(to, from); - segment(4).memory_to_record(to, from); + segment(0).mem2rec(to, from); + segment(1).mem2rec(to, from); + segment(2).mem2rec(to, from); + segment(3).mem2rec(to, from); + segment(4).mem2rec(to, from); } else memcpy(to, from, binary_length()); @@ -191,13 +199,13 @@ public: // Convert the in-record representation to the in-memory representation static void record_to_memory(char *to, const char *from) { - if (force_swap || (from[6] & -from[8] & 0x80)) + if (force_swap || rec_need_swap(from)) { - segment(0).record_to_memory(to, from); - segment(1).record_to_memory(to, from); - segment(2).record_to_memory(to, from); - segment(3).record_to_memory(to, from); - segment(4).record_to_memory(to, from); + segment(0).rec2mem(to, from); + segment(1).rec2mem(to, from); + segment(2).rec2mem(to, from); + segment(3).rec2mem(to, from); + segment(4).rec2mem(to, from); } else memcpy(to, from, binary_length()); From d9752d85a34d8bae0df85997762284b21aa08d7b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 28 Oct 2023 23:13:06 +0200 Subject: [PATCH 147/158] MDEV-31926 UUID v7 are compared incorrectly According to the standart draft UUIDv6 and UUIDv7 values must be compared as opaque raw bytes. Let's only compare with byte-swapping if both values need byte swapping. --- .../mysql-test/type_uuid/order.result | 66 ++++++++++++++++++- .../type_uuid/mysql-test/type_uuid/order.test | 23 ++++++- .../mysql-test/type_uuid/type_uuid.result | 4 +- plugin/type_uuid/sql_type_uuid.h | 22 ++++--- 4 files changed, 103 insertions(+), 12 deletions(-) diff --git a/plugin/type_uuid/mysql-test/type_uuid/order.result b/plugin/type_uuid/mysql-test/type_uuid/order.result index d71d0eb3ad8..3dd799b6ae2 100644 --- a/plugin/type_uuid/mysql-test/type_uuid/order.result +++ b/plugin/type_uuid/mysql-test/type_uuid/order.result @@ -756,6 +756,36 @@ NULL 48 NULL 52 NULL 56 NULL 60 +select * from t1, t1 t where t1.b div 4 in (6,7) and t.b div 4 in (6,7) and t1.a > t.a; +a b a b +02601234-5566-6777-c888-99aabbccddee 26 02401234-5566-6777-0888-99aabbccddee 24 +02801234-5566-7777-0888-99aabbccddee 28 02401234-5566-6777-0888-99aabbccddee 24 +02801234-5566-7777-0888-99aabbccddee 28 02601234-5566-6777-c888-99aabbccddee 26 +03001234-5566-7777-c888-99aabbccddee 30 02401234-5566-6777-0888-99aabbccddee 24 +03001234-5566-7777-c888-99aabbccddee 30 02601234-5566-6777-c888-99aabbccddee 26 +03001234-5566-7777-c888-99aabbccddee 30 02801234-5566-7777-0888-99aabbccddee 28 +12501234-5566-6777-8888-99aabbccddee 25 02401234-5566-6777-0888-99aabbccddee 24 +12501234-5566-6777-8888-99aabbccddee 25 02601234-5566-6777-c888-99aabbccddee 26 +12501234-5566-6777-8888-99aabbccddee 25 02801234-5566-7777-0888-99aabbccddee 28 +12501234-5566-6777-8888-99aabbccddee 25 03001234-5566-7777-c888-99aabbccddee 30 +12701234-5566-6777-e888-99aabbccddee 27 02401234-5566-6777-0888-99aabbccddee 24 +12701234-5566-6777-e888-99aabbccddee 27 02601234-5566-6777-c888-99aabbccddee 26 +12701234-5566-6777-e888-99aabbccddee 27 02801234-5566-7777-0888-99aabbccddee 28 +12701234-5566-6777-e888-99aabbccddee 27 03001234-5566-7777-c888-99aabbccddee 30 +12701234-5566-6777-e888-99aabbccddee 27 12501234-5566-6777-8888-99aabbccddee 25 +12901234-5566-7777-8888-99aabbccddee 29 02401234-5566-6777-0888-99aabbccddee 24 +12901234-5566-7777-8888-99aabbccddee 29 02601234-5566-6777-c888-99aabbccddee 26 +12901234-5566-7777-8888-99aabbccddee 29 02801234-5566-7777-0888-99aabbccddee 28 +12901234-5566-7777-8888-99aabbccddee 29 03001234-5566-7777-c888-99aabbccddee 30 +12901234-5566-7777-8888-99aabbccddee 29 12501234-5566-6777-8888-99aabbccddee 25 +12901234-5566-7777-8888-99aabbccddee 29 12701234-5566-6777-e888-99aabbccddee 27 +13101234-5566-7777-e888-99aabbccddee 31 02401234-5566-6777-0888-99aabbccddee 24 +13101234-5566-7777-e888-99aabbccddee 31 02601234-5566-6777-c888-99aabbccddee 26 +13101234-5566-7777-e888-99aabbccddee 31 02801234-5566-7777-0888-99aabbccddee 28 +13101234-5566-7777-e888-99aabbccddee 31 03001234-5566-7777-c888-99aabbccddee 30 +13101234-5566-7777-e888-99aabbccddee 31 12501234-5566-6777-8888-99aabbccddee 25 +13101234-5566-7777-e888-99aabbccddee 31 12701234-5566-6777-e888-99aabbccddee 27 +13101234-5566-7777-e888-99aabbccddee 31 12901234-5566-7777-8888-99aabbccddee 29 alter ignore table t2 force; Warnings: Warning 1292 Incorrect uuid value: '03201234-5566-8777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 33 @@ -766,4 +796,38 @@ Warning 1292 Incorrect uuid value: '04801234-5566-c777-0888-99aabbccddee' for co Warning 1292 Incorrect uuid value: '05201234-5566-d777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 53 Warning 1292 Incorrect uuid value: '05601234-5566-e777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 57 Warning 1292 Incorrect uuid value: '06001234-5566-f777-0888-99aabbccddee' for column `test`.`t2`.`a` at row 61 -drop table t1, t2; +drop table t2; +# +# MDEV-31926 UUID v7 are compared incorrectly +# +select * from t1, t1 t where t1.b div 4 in (6,7) and t.b div 4 in (6,7) and concat(t1.a) > concat(t.a); +a b a b +02601234-5566-6777-c888-99aabbccddee 26 02401234-5566-6777-0888-99aabbccddee 24 +02801234-5566-7777-0888-99aabbccddee 28 02401234-5566-6777-0888-99aabbccddee 24 +02801234-5566-7777-0888-99aabbccddee 28 02601234-5566-6777-c888-99aabbccddee 26 +03001234-5566-7777-c888-99aabbccddee 30 02401234-5566-6777-0888-99aabbccddee 24 +03001234-5566-7777-c888-99aabbccddee 30 02601234-5566-6777-c888-99aabbccddee 26 +03001234-5566-7777-c888-99aabbccddee 30 02801234-5566-7777-0888-99aabbccddee 28 +12501234-5566-6777-8888-99aabbccddee 25 02401234-5566-6777-0888-99aabbccddee 24 +12501234-5566-6777-8888-99aabbccddee 25 02601234-5566-6777-c888-99aabbccddee 26 +12501234-5566-6777-8888-99aabbccddee 25 02801234-5566-7777-0888-99aabbccddee 28 +12501234-5566-6777-8888-99aabbccddee 25 03001234-5566-7777-c888-99aabbccddee 30 +12701234-5566-6777-e888-99aabbccddee 27 02401234-5566-6777-0888-99aabbccddee 24 +12701234-5566-6777-e888-99aabbccddee 27 02601234-5566-6777-c888-99aabbccddee 26 +12701234-5566-6777-e888-99aabbccddee 27 02801234-5566-7777-0888-99aabbccddee 28 +12701234-5566-6777-e888-99aabbccddee 27 03001234-5566-7777-c888-99aabbccddee 30 +12701234-5566-6777-e888-99aabbccddee 27 12501234-5566-6777-8888-99aabbccddee 25 +12901234-5566-7777-8888-99aabbccddee 29 02401234-5566-6777-0888-99aabbccddee 24 +12901234-5566-7777-8888-99aabbccddee 29 02601234-5566-6777-c888-99aabbccddee 26 +12901234-5566-7777-8888-99aabbccddee 29 02801234-5566-7777-0888-99aabbccddee 28 +12901234-5566-7777-8888-99aabbccddee 29 03001234-5566-7777-c888-99aabbccddee 30 +12901234-5566-7777-8888-99aabbccddee 29 12501234-5566-6777-8888-99aabbccddee 25 +12901234-5566-7777-8888-99aabbccddee 29 12701234-5566-6777-e888-99aabbccddee 27 +13101234-5566-7777-e888-99aabbccddee 31 02401234-5566-6777-0888-99aabbccddee 24 +13101234-5566-7777-e888-99aabbccddee 31 02601234-5566-6777-c888-99aabbccddee 26 +13101234-5566-7777-e888-99aabbccddee 31 02801234-5566-7777-0888-99aabbccddee 28 +13101234-5566-7777-e888-99aabbccddee 31 03001234-5566-7777-c888-99aabbccddee 30 +13101234-5566-7777-e888-99aabbccddee 31 12501234-5566-6777-8888-99aabbccddee 25 +13101234-5566-7777-e888-99aabbccddee 31 12701234-5566-6777-e888-99aabbccddee 27 +13101234-5566-7777-e888-99aabbccddee 31 12901234-5566-7777-8888-99aabbccddee 29 +drop table t1; diff --git a/plugin/type_uuid/mysql-test/type_uuid/order.test b/plugin/type_uuid/mysql-test/type_uuid/order.test index 058b6644a51..18854e85fbf 100644 --- a/plugin/type_uuid/mysql-test/type_uuid/order.test +++ b/plugin/type_uuid/mysql-test/type_uuid/order.test @@ -36,6 +36,27 @@ select * from t2 left join t1 on (t1.a<=>t2.a); --sorted_result select * from t1 union select * from t2; +--sorted_result +select * from t1, t1 t where t1.b div 4 in (6,7) and t.b div 4 in (6,7) and t1.a > t.a; + alter ignore table t2 force; -drop table t1, t2; +drop table t2; + +--echo # +--echo # MDEV-31926 UUID v7 are compared incorrectly +--echo # + +# for v6 and v7 string comparison should produce the same result. +# Quoting the standard draft: +# +# 6.11. Sorting +# +# UUIDv6 and UUIDv7 are designed so that implementations that require +# sorting (e.g., database indexes) sort as opaque raw bytes, without +# need for parsing or introspection. +# +--sorted_result +select * from t1, t1 t where t1.b div 4 in (6,7) and t.b div 4 in (6,7) and concat(t1.a) > concat(t.a); + +drop table t1; diff --git a/plugin/type_uuid/mysql-test/type_uuid/type_uuid.result b/plugin/type_uuid/mysql-test/type_uuid/type_uuid.result index 62612354f7f..de17d6fb2c5 100644 --- a/plugin/type_uuid/mysql-test/type_uuid/type_uuid.result +++ b/plugin/type_uuid/mysql-test/type_uuid/type_uuid.result @@ -3182,10 +3182,10 @@ d 11111111-0000-0000-0000-000000000000 SELECT * FROM t1 WHERE d <= ALL (SELECT * FROM t1); d -11111111-0000-0000-0000-000000000000 +00000000-0000-0000-0000-111111111111 SELECT * FROM t1 WHERE d >= ALL (SELECT * FROM t1); d -00000000-0000-0000-0000-111111111111 +11111111-0000-0000-0000-000000000000 DROP TABLE t1; # # MDEV-31719 Wrong result of: WHERE inet6_column IN ('','::1') diff --git a/plugin/type_uuid/sql_type_uuid.h b/plugin/type_uuid/sql_type_uuid.h index 453dda01036..67d7471d4d2 100644 --- a/plugin/type_uuid/sql_type_uuid.h +++ b/plugin/type_uuid/sql_type_uuid.h @@ -241,14 +241,20 @@ public: { DBUG_ASSERT(a.length == binary_length()); DBUG_ASSERT(b.length == binary_length()); - int res; - if ((res= segment(4).cmp_memory(a.str, b.str)) || - (res= segment(3).cmp_memory(a.str, b.str)) || - (res= segment(2).cmp_memory(a.str, b.str)) || - (res= segment(1).cmp_memory(a.str, b.str)) || - (res= segment(0).cmp_memory(a.str, b.str))) - return res; - return 0; + bool swap_a= force_swap || mem_need_swap(a.str); + bool swap_b= force_swap || mem_need_swap(b.str); + if (swap_a && swap_b) + { + int res; + if ((res= segment(4).cmp_memory(a.str, b.str)) || + (res= segment(3).cmp_memory(a.str, b.str)) || + (res= segment(2).cmp_memory(a.str, b.str)) || + (res= segment(1).cmp_memory(a.str, b.str)) || + (res= segment(0).cmp_memory(a.str, b.str))) + return res; + return 0; + } + return memcmp(a.str, b.str, binary_length()); } static ulong KEY_pack_flags(uint column_nr) From c4143f909528e3fab0677a28631d10389354c491 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 30 Oct 2023 13:27:58 +0100 Subject: [PATCH 148/158] Make the test more stable --- mysql-test/main/subselect.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test index a17fc408500..57cbefb4812 100644 --- a/mysql-test/main/subselect.test +++ b/mysql-test/main/subselect.test @@ -1166,6 +1166,7 @@ DROP TABLE t1; # Bug#2198 SELECT INTO OUTFILE (with Sub-Select) Problem # +--disable_service_connection --disable_ps2_protocol create table t1 (a int, b decimal(13, 3)); insert into t1 values (1, 0.123); @@ -1180,6 +1181,7 @@ eval load data infile "$outfile_rel" into table t1; select * from t1; drop table t1; --enable_ps2_protocol +--enable_service_connection # # Bug#2479 dependant subquery with limit crash From 6f091434f313996436b4f01d7e7d62a9f3786958 Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 30 Oct 2023 14:44:26 +0200 Subject: [PATCH 149/158] MDEV-32531 MSAN / Valgrind errors in Item_func_like::get_mm_leaf with temporal field Added missing initializer --- mysql-test/main/analyze.result | 16 +++++++++++++--- mysql-test/main/analyze.test | 12 +++++++++++- sql/opt_range.cc | 1 + 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/mysql-test/main/analyze.result b/mysql-test/main/analyze.result index af39315d2b4..8819f15f27b 100644 --- a/mysql-test/main/analyze.result +++ b/mysql-test/main/analyze.result @@ -429,9 +429,6 @@ SET join_cache_level=3; SET optimizer_switch='join_cache_hashed=on'; SET optimizer_switch='join_cache_bka=on'; set optimizer_switch='hash_join_cardinality=on'; -select benchmark(1,1); -benchmark(1,1) -0 EXPLAIN SELECT * FROM t1, t2 WHERE b=a; id select_type table type possible_keys key key_len ref rows Extra @@ -443,5 +440,18 @@ DROP TABLE t1,t2; set @@optimizer_switch=@save_optimizer_switch; set @@join_cache_level=@save_join_cache_level; # +# MDEV-32531 MSAN / Valgrind errors in Item_func_like::get_mm_leaf with +# temporal field +# +CREATE TABLE t1 (f DATE); +INSERT INTO t1 VALUES ('1978-08-27'),('1906-04-30'); +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * FROM t1 WHERE f LIKE '2023%'; +f +DROP TABLE t1; +# # End of 10.6 tests # diff --git a/mysql-test/main/analyze.test b/mysql-test/main/analyze.test index 357d5c503d3..fb07e11b0c6 100644 --- a/mysql-test/main/analyze.test +++ b/mysql-test/main/analyze.test @@ -287,7 +287,6 @@ SET optimizer_switch='join_cache_hashed=on'; SET optimizer_switch='join_cache_bka=on'; set optimizer_switch='hash_join_cardinality=on'; -select benchmark(1,1); EXPLAIN SELECT * FROM t1, t2 WHERE b=a; SELECT * FROM t1, t2 WHERE b=a; @@ -296,6 +295,17 @@ DROP TABLE t1,t2; set @@optimizer_switch=@save_optimizer_switch; set @@join_cache_level=@save_join_cache_level; +--echo # +--echo # MDEV-32531 MSAN / Valgrind errors in Item_func_like::get_mm_leaf with +--echo # temporal field +--echo # + +CREATE TABLE t1 (f DATE); +INSERT INTO t1 VALUES ('1978-08-27'),('1906-04-30'); +ANALYZE TABLE t1 PERSISTENT FOR ALL; +SELECT * FROM t1 WHERE f LIKE '2023%'; +DROP TABLE t1; + --echo # --echo # End of 10.6 tests --echo # diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 9e49f800204..b7800e83bd8 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3532,6 +3532,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) init_sql_alloc(key_memory_quick_range_select_root, &alloc, thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC)); + bzero((void*) ¶m, sizeof(param)); param.thd= thd; param.mem_root= &alloc; param.old_root= thd->mem_root; From 0cc809f91bb2787a884234f6a7c209b5140be851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 31 Oct 2023 12:48:20 +0200 Subject: [PATCH 150/158] MDEV-31826: Memory leak on failed IMPORT TABLESPACE fil_delete_tablespace(): Invoke fil_space_free_low() directly. This fixes up commit 39e3ca8bd25fc539ed08ff464e8a3189ff9f7fa3 --- storage/innobase/fil/fil0fil.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index b24e4d0cb9e..a1cf1fd5c47 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1702,10 +1702,14 @@ void fil_close_tablespace(ulint id) completely and permanently. */ while (buf_flush_list_space(space)); - /* If the free is successful, the latch will be released there. */ - if (!fil_space_free(id, true)) { - space->x_unlock(); + space->x_unlock(); + mysql_mutex_lock(&log_sys.mutex); + if (space->max_lsn != 0) { + ut_d(space->max_lsn = 0); + fil_system.named_spaces.remove(*space); } + mysql_mutex_unlock(&log_sys.mutex); + fil_space_free_low(space); } /** Delete a tablespace and associated .ibd file. From 90e11488ac1eafaede6e921133059bd2e08da2be Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 1 Nov 2023 11:29:12 +0100 Subject: [PATCH 151/158] update C/C - compilation failure with gcc7 on s390x-sles-12 --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index 64f9d88f306..458a4396b44 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 64f9d88f3061352f3b368d9d73073ebf6c80cbb1 +Subproject commit 458a4396b443dcefedcf464067560078aa09d8b4 From 1fc2843eeece8500e20bd4f0a814996fc25b3e01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Sat, 4 Nov 2023 16:04:21 +0200 Subject: [PATCH 152/158] MDEV-31826: File handle leak on failed IMPORT TABLESPACE fil_space_t::drop(): If the caller is not interested in a detached handle, close it immediately. --- storage/innobase/fil/fil0fil.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index a1cf1fd5c47..02203ba3d7b 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1678,6 +1678,8 @@ fil_space_t *fil_space_t::drop(ulint id, pfs_os_file_t *detached_handle) mysql_mutex_unlock(&fil_system.mutex); if (detached_handle) *detached_handle = handle; + else + os_file_close(handle); return space; } From b52b7b41296fa8857bcd2abc42f9ab6721b86f8b Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 6 Nov 2023 19:16:16 +0530 Subject: [PATCH 153/158] MDEV-31851 Doublewrite recovery fixup recv_dblwr_t::find_page(): Tablespace flags validity should be checked only for page 0. --- storage/innobase/log/log0recv.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 060d5edcd09..d76ad863861 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -4794,10 +4794,13 @@ byte *recv_dblwr_t::find_page(const page_id_t page_id, if (page_get_page_no(page) != page_id.page_no() || page_get_space_id(page) != page_id.space()) continue; - uint32_t flags= mach_read_from_4( - FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); - if (!fil_space_t::is_valid_flags(flags, page_id.space())) - continue; + if (page_id.page_no() == 0) + { + uint32_t flags= mach_read_from_4( + FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); + if (!fil_space_t::is_valid_flags(flags, page_id.space())) + continue; + } const lsn_t lsn= mach_read_from_8(page + FIL_PAGE_LSN); if (lsn <= max_lsn || From 21822625aa675b36a5c2548f78e8d3d8cde8b7cd Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 7 Nov 2023 11:00:49 +0100 Subject: [PATCH 154/158] MDEV-32683 Spider engine does not load with non-default alter-algorithm specify algorithm/lock explicitly, don't depend on server settings --- .../spider/bugfix/r/mdev_32683.result | 16 +++ .../spider/bugfix/t/mdev_32683.test | 14 ++ storage/spider/spd_init_query.h | 135 ++++++++++++------ 3 files changed, 120 insertions(+), 45 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_32683.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_32683.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_32683.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_32683.result new file mode 100644 index 00000000000..350a723f6b1 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_32683.result @@ -0,0 +1,16 @@ +# +# MDEV-32683 Spider engine does not load with non-default alter-algorithm +# +set global alter_algorithm=INSTANT; +install plugin spider soname 'ha_spider'; +select plugin_name, plugin_status, plugin_type, plugin_license, load_option from information_schema.plugins where plugin_name like 'spider'; +plugin_name plugin_status plugin_type plugin_license load_option +SPIDER ACTIVE STORAGE ENGINE GPL ON +uninstall plugin spider; +drop table mysql.spider_link_failed_log, mysql.spider_link_mon_servers, mysql.spider_tables, mysql.spider_table_crd, mysql.spider_table_position_for_recovery, mysql.spider_table_sts, mysql.spider_xa, mysql.spider_xa_failed_log, mysql.spider_xa_member; +drop function spider_direct_sql; +drop function spider_bg_direct_sql; +drop function spider_ping_table; +drop function spider_copy_tables; +drop function spider_flush_table_mon_cache; +set global alter_algorithm=DEFAULT; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32683.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_32683.test new file mode 100644 index 00000000000..d208957f048 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32683.test @@ -0,0 +1,14 @@ +--echo # +--echo # MDEV-32683 Spider engine does not load with non-default alter-algorithm +--echo # +set global alter_algorithm=INSTANT; +install plugin spider soname 'ha_spider'; +select plugin_name, plugin_status, plugin_type, plugin_license, load_option from information_schema.plugins where plugin_name like 'spider'; +uninstall plugin spider; +drop table mysql.spider_link_failed_log, mysql.spider_link_mon_servers, mysql.spider_tables, mysql.spider_table_crd, mysql.spider_table_position_for_recovery, mysql.spider_table_sts, mysql.spider_xa, mysql.spider_xa_failed_log, mysql.spider_xa_member; +drop function spider_direct_sql; +drop function spider_bg_direct_sql; +drop function spider_ping_table; +drop function spider_copy_tables; +drop function spider_flush_table_mon_cache; +set global alter_algorithm=DEFAULT; diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h index 001268164d5..fdf6b22fe27 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -210,7 +210,8 @@ static LEX_STRING spider_init_queries[] = { " add if not exists username char(64) default null," " add if not exists password char(64) default null," " add if not exists tgt_db_name char(64) default null," - " add if not exists tgt_table_name char(64) default null;" + " add if not exists tgt_table_name char(64) default null," + " algorithm=copy, lock=shared;" )}, /* Fix for version 0.17 @@ -224,7 +225,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @col_type != 'binary(128)' then" " alter table mysql.spider_xa" - " modify data binary(128) not null default '';" + " modify data binary(128) not null default ''," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -236,7 +238,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @col_type != 'binary(128)' then" " alter table mysql.spider_xa_member" - " modify data binary(128) not null default '';" + " modify data binary(128) not null default ''," + " algorithm=copy, lock=shared;" "end if;" )}, /* @@ -246,14 +249,16 @@ static LEX_STRING spider_init_queries[] = { "alter table mysql.spider_tables" " add column if not exists link_id int not null default 0 after table_name," " drop primary key," - " add primary key (db_name, table_name, link_id);" + " add primary key (db_name, table_name, link_id)," + " algorithm=copy, lock=shared;" )}, /* Fix for version 2.8 */ {C_STRING_WITH_LEN( "alter table mysql.spider_tables" - " add column if not exists link_status tinyint not null default 1;" + " add column if not exists link_status tinyint not null default 1," + " algorithm=copy, lock=shared;" )}, /* Fix for version 2.10 @@ -269,7 +274,8 @@ static LEX_STRING spider_init_queries[] = { " after ssl_key," " add column if not exists default_file char(64) default null" " after ssl_verify_server_cert," - " add column if not exists default_group char(64) default null after default_file;" + " add column if not exists default_group char(64) default null after default_file," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_tables" @@ -282,7 +288,8 @@ static LEX_STRING spider_init_queries[] = { " after ssl_key," " add column if not exists default_file char(64) default null" " after ssl_verify_server_cert," - " add column if not exists default_group char(64) default null after default_file;" + " add column if not exists default_group char(64) default null after default_file," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_link_mon_servers" @@ -295,7 +302,8 @@ static LEX_STRING spider_init_queries[] = { " after ssl_key," " add column if not exists default_file char(64) default null" " after ssl_verify_server_cert," - " add column if not exists default_group char(64) default null after default_file;" + " add column if not exists default_group char(64) default null after default_file," + " algorithm=copy, lock=shared;" )}, /* Fix for version 2.28 @@ -309,7 +317,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @col_type != 'int(10) unsigned' then" " alter table mysql.spider_link_mon_servers" - " modify sid int unsigned not null default 0;" + " modify sid int unsigned not null default 0," + " algorithm=copy, lock=shared;" "end if;" )}, /* @@ -331,7 +340,8 @@ static LEX_STRING spider_init_queries[] = { " modify ssl_capath text," " modify ssl_cert text," " modify ssl_key text," - " modify default_file text;" + " modify default_file text," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -348,7 +358,8 @@ static LEX_STRING spider_init_queries[] = { " modify ssl_capath text," " modify ssl_cert text," " modify ssl_key text," - " modify default_file text;" + " modify default_file text," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -365,7 +376,8 @@ static LEX_STRING spider_init_queries[] = { " modify ssl_capath text," " modify ssl_cert text," " modify ssl_key text," - " modify default_file text;" + " modify default_file text," + " algorithm=copy, lock=shared;" "end if;" )}, /* @@ -374,7 +386,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "alter table mysql.spider_tables" " add if not exists monitoring_binlog_pos_at_failing tinyint not null default 0" - " after ssl_verify_server_cert;" + " after ssl_verify_server_cert," + " algorithm=copy, lock=shared;" )}, /* Fix for version 3.3.6 @@ -382,12 +395,14 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "alter table mysql.spider_tables" " add column if not exists block_status tinyint not null default 0" - " after link_status;" + " after link_status," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_tables" " add column if not exists static_link_id char(64) default null after block_status," - " add unique index if not exists uidx1 (db_name, table_name, static_link_id);" + " add unique index if not exists uidx1 (db_name, table_name, static_link_id)," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" @@ -398,7 +413,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @col_type != 'char(64)' then" " alter table mysql.spider_link_mon_servers" - " modify link_id char(64) not null default '';" + " modify link_id char(64) not null default ''," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -410,7 +426,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @col_type != 'char(64)' then" " alter table mysql.spider_link_failed_log" - " modify link_id char(64) not null default '';" + " modify link_id char(64) not null default ''," + " algorithm=copy, lock=shared;" "end if;" )}, /* @@ -425,7 +442,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @col_type != 'char(199)' then" " alter table mysql.spider_tables" - " modify table_name char(199) not null default '';" + " modify table_name char(199) not null default ''," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -437,7 +455,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @col_type != 'char(199)' then" " alter table mysql.spider_link_mon_servers" - " modify table_name char(199) not null default '';" + " modify table_name char(199) not null default ''," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -449,7 +468,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @col_type != 'char(199)' then" " alter table mysql.spider_link_failed_log" - " modify table_name char(199) not null default '';" + " modify table_name char(199) not null default ''," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -461,7 +481,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @col_type != 'char(199)' then" " alter table mysql.spider_table_position_for_recovery" - " modify table_name char(199) not null default '';" + " modify table_name char(199) not null default ''," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -473,7 +494,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @col_type != 'char(199)' then" " alter table mysql.spider_table_sts" - " modify table_name char(199) not null default '';" + " modify table_name char(199) not null default ''," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -485,7 +507,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @col_type != 'char(199)' then" " alter table mysql.spider_table_crd" - " modify table_name char(199) not null default '';" + " modify table_name char(199) not null default ''," + " algorithm=copy, lock=shared;" "end if;" )}, /* @@ -493,7 +516,8 @@ static LEX_STRING spider_init_queries[] = { */ {C_STRING_WITH_LEN( "alter table mysql.spider_table_sts" - " add column if not exists checksum bigint unsigned default null after update_time;" + " add column if not exists checksum bigint unsigned default null after update_time," + " algorithm=copy, lock=shared;" )}, /* Fix for MariaDB 10.4: Crash-Safe system tables @@ -506,7 +530,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @engine_name != 'Aria' then" " alter table mysql.spider_link_failed_log" - " engine=Aria transactional=1;" + " engine=Aria transactional=1," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -517,7 +542,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @engine_name != 'Aria' then" " alter table mysql.spider_link_mon_servers" - " engine=Aria transactional=1;" + " engine=Aria transactional=1," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -528,7 +554,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @engine_name != 'Aria' then" " alter table mysql.spider_table_crd" - " engine=Aria transactional=1;" + " engine=Aria transactional=1," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -539,7 +566,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @engine_name != 'Aria' then" " alter table mysql.spider_table_position_for_recovery" - " engine=Aria transactional=1;" + " engine=Aria transactional=1," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -550,7 +578,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @engine_name != 'Aria' then" " alter table mysql.spider_table_sts" - " engine=Aria transactional=1;" + " engine=Aria transactional=1," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -561,7 +590,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @engine_name != 'Aria' then" " alter table mysql.spider_tables" - " engine=Aria transactional=1;" + " engine=Aria transactional=1," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -572,7 +602,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @engine_name != 'Aria' then" " alter table mysql.spider_xa" - " engine=Aria transactional=1;" + " engine=Aria transactional=1," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -583,7 +614,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @engine_name != 'Aria' then" " alter table mysql.spider_xa_failed_log" - " engine=Aria transactional=1;" + " engine=Aria transactional=1," + " algorithm=copy, lock=shared;" "end if;" )}, {C_STRING_WITH_LEN( @@ -594,7 +626,8 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "if @engine_name != 'Aria' then" " alter table mysql.spider_xa_member" - " engine=Aria transactional=1;" + " engine=Aria transactional=1," + " algorithm=copy, lock=shared;" "end if;" )}, /* @@ -602,51 +635,63 @@ static LEX_STRING spider_init_queries[] = { */ {C_STRING_WITH_LEN( "alter table mysql.spider_link_mon_servers" - " add column if not exists dsn char(64) default null after default_group;" + " add column if not exists dsn char(64) default null after default_group," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_tables" - " add column if not exists dsn char(64) default null after default_group;" + " add column if not exists dsn char(64) default null after default_group," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_xa_failed_log" - " add column if not exists dsn char(64) default null after default_group;" + " add column if not exists dsn char(64) default null after default_group," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_xa_member" - " add column if not exists dsn char(64) default null after default_group;" + " add column if not exists dsn char(64) default null after default_group," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_link_mon_servers" - " add column if not exists filedsn text default null after dsn;" + " add column if not exists filedsn text default null after dsn," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_tables" - " add column if not exists filedsn text default null after dsn;" + " add column if not exists filedsn text default null after dsn," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_xa_failed_log" - " add column if not exists filedsn text default null after dsn;" + " add column if not exists filedsn text default null after dsn," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_xa_member" - " add column if not exists filedsn text default null after dsn;" + " add column if not exists filedsn text default null after dsn," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_link_mon_servers" - " add column if not exists driver char(64) default null after filedsn;" + " add column if not exists driver char(64) default null after filedsn," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_tables" - " add column if not exists driver char(64) default null after filedsn;" + " add column if not exists driver char(64) default null after filedsn," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_xa_failed_log" - " add column if not exists driver char(64) default null after filedsn;" + " add column if not exists driver char(64) default null after filedsn," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "alter table mysql.spider_xa_member" - " add column if not exists driver char(64) default null after filedsn;" + " add column if not exists driver char(64) default null after filedsn," + " algorithm=copy, lock=shared;" )}, {C_STRING_WITH_LEN( "set @win_plugin := IF(@@version_compile_os like 'Win%', 1, 0);" From 169774746112228acde0dcf9fe7861866bd0eacc Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Tue, 7 Nov 2023 12:20:02 +0300 Subject: [PATCH 155/158] MDEV-32682: Assertion `range->rows >= s->found_records' failed in best_access_path Fix the issue introduced in ec2574fd8f, fix for MDEV-31983: get_quick_record_count() must set quick_count=0 when it got IMPOSSIBLE_RANGE from test_quick_select. Failure to do so will cause an assertion in 11.0, when the number of quick select rows (0) is checked to be lower than the number of found_records (which is capped up to 1). --- mysql-test/main/subselect_mat.result | 16 ++++++++++++++++ mysql-test/main/subselect_sj_mat.result | 16 ++++++++++++++++ mysql-test/main/subselect_sj_mat.test | 13 +++++++++++++ sql/sql_select.cc | 1 + 4 files changed, 46 insertions(+) diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result index 286b3d40ac1..8054dbbd21d 100644 --- a/mysql-test/main/subselect_mat.result +++ b/mysql-test/main/subselect_mat.result @@ -2700,6 +2700,22 @@ UPDATE t1, t2 SET t1.a = 26 WHERE t2.b IN (SELECT MIN(d) FROM t3 WHERE c >= '201 ERROR 22007: Incorrect datetime value: '2012-01' for column `test`.`t3`.`c` at row 1 DROP TABLE t1, t2, t3; # +# a followup fix: +# MDEV-32682: Assertion `range->rows >= s->found_records' failed in best_access_path +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b VARCHAR(10), pk INT, PRIMARY KEY (pk)) ENGINE=MyISAM; +ANALYZE TABLE t1, t2 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status Table is already up to date +SELECT STRAIGHT_JOIN t2.* FROM t1 JOIN t2 WHERE t2.b IS NULL AND t2.pk > 1; +b pk +DROP TABLE t1, t2; +# # MDEV-32612 Assertion `tab->select->quick' failed in test_if_skip_sort_order # CREATE TABLE t1 (l_orderkey int, l_linenumber int, l_quantity double, diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result index 277ce9a4408..9a3b69da6fa 100644 --- a/mysql-test/main/subselect_sj_mat.result +++ b/mysql-test/main/subselect_sj_mat.result @@ -2742,6 +2742,22 @@ UPDATE t1, t2 SET t1.a = 26 WHERE t2.b IN (SELECT MIN(d) FROM t3 WHERE c >= '201 ERROR 22007: Incorrect datetime value: '2012-01' for column `test`.`t3`.`c` at row 1 DROP TABLE t1, t2, t3; # +# a followup fix: +# MDEV-32682: Assertion `range->rows >= s->found_records' failed in best_access_path +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b VARCHAR(10), pk INT, PRIMARY KEY (pk)) ENGINE=MyISAM; +ANALYZE TABLE t1, t2 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status Table is already up to date +SELECT STRAIGHT_JOIN t2.* FROM t1 JOIN t2 WHERE t2.b IS NULL AND t2.pk > 1; +b pk +DROP TABLE t1, t2; +# # MDEV-32612 Assertion `tab->select->quick' failed in test_if_skip_sort_order # CREATE TABLE t1 (l_orderkey int, l_linenumber int, l_quantity double, diff --git a/mysql-test/main/subselect_sj_mat.test b/mysql-test/main/subselect_sj_mat.test index 7a218bde172..19c78aea659 100644 --- a/mysql-test/main/subselect_sj_mat.test +++ b/mysql-test/main/subselect_sj_mat.test @@ -2436,6 +2436,19 @@ UPDATE t1, t2 SET t1.a = 26 WHERE t2.b IN (SELECT MIN(d) FROM t3 WHERE c >= '201 # Cleanup DROP TABLE t1, t2, t3; +--echo # +--echo # a followup fix: +--echo # MDEV-32682: Assertion `range->rows >= s->found_records' failed in best_access_path +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b VARCHAR(10), pk INT, PRIMARY KEY (pk)) ENGINE=MyISAM; + +ANALYZE TABLE t1, t2 PERSISTENT FOR ALL; +SELECT STRAIGHT_JOIN t2.* FROM t1 JOIN t2 WHERE t2.b IS NULL AND t2.pk > 1; +DROP TABLE t1, t2; + --echo # --echo # MDEV-32612 Assertion `tab->select->quick' failed in test_if_skip_sort_order --echo # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a351322e76b..6dd7f44e7e3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5181,6 +5181,7 @@ static bool get_quick_record_count(THD *thd, SQL_SELECT *select, if (error == SQL_SELECT::IMPOSSIBLE_RANGE) { table->reginfo.impossible_range=1; + *quick_count= 0; DBUG_RETURN(false); } if (unlikely(error == SQL_SELECT::ERROR)) From fefd6d55593f7f29b5d4a074ecaceb22c6907e39 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 8 Nov 2023 12:06:34 +0100 Subject: [PATCH 156/158] MDEV-32656: ASAN errors in base_list_iterator::next / setup_table_map upon 2nd execution of PS Correctly supress error issuing when saving value in field for comporison --- mysql-test/main/subselect.result | 21 +++++++++++++++ mysql-test/main/subselect.test | 27 +++++++++++++++++++ mysql-test/main/subselect_mat.result | 2 +- .../main/subselect_no_exists_to_in.result | 21 +++++++++++++++ mysql-test/main/subselect_no_mat.result | 21 +++++++++++++++ mysql-test/main/subselect_no_opts.result | 21 +++++++++++++++ mysql-test/main/subselect_no_scache.result | 21 +++++++++++++++ mysql-test/main/subselect_no_semijoin.result | 21 +++++++++++++++ mysql-test/main/subselect_sj_mat.result | 2 +- sql/item_cmpfunc.cc | 3 ++- sql/sql_class.h | 6 +++-- 11 files changed, 161 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result index 0c877b03b97..32652244353 100644 --- a/mysql-test/main/subselect.result +++ b/mysql-test/main/subselect.result @@ -7497,3 +7497,24 @@ ERROR HY000: Illegal parameter data types row and boolean for operation '=' # # End of 10.4 tests # +# +# MDEV-32656: ASAN errors in base_list_iterator::next / +# setup_table_map upon 2nd execution of PS +# (10.6 part) +# +CREATE TABLE t1 (id BIGINT); +INSERT INTO t1 VALUES (1),(2); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (2),(3); +CREATE TABLE t3 (b INT); +INSERT INTO t3 VALUES (3),(4); +insert into t2 select (('e','e') IN (SELECT v1.id, v1.id FROM v1 JOIN t3)); +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +drop view v1; +drop table t1, t2, t3; +# +# End of 10.6 tests +# diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test index 18ae20c44da..b301d4f584b 100644 --- a/mysql-test/main/subselect.test +++ b/mysql-test/main/subselect.test @@ -6351,3 +6351,30 @@ SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); --echo # --echo # End of 10.4 tests --echo # + + + +--echo # +--echo # MDEV-32656: ASAN errors in base_list_iterator::next / +--echo # setup_table_map upon 2nd execution of PS +--echo # (10.6 part) +--echo # + +CREATE TABLE t1 (id BIGINT); +INSERT INTO t1 VALUES (1),(2); +CREATE VIEW v1 AS SELECT * FROM t1; + +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (2),(3); + +CREATE TABLE t3 (b INT); +INSERT INTO t3 VALUES (3),(4); + +insert into t2 select (('e','e') IN (SELECT v1.id, v1.id FROM v1 JOIN t3)); + +drop view v1; +drop table t1, t2, t3; + +--echo # +--echo # End of 10.6 tests +--echo # diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result index 8054dbbd21d..cf3d1671532 100644 --- a/mysql-test/main/subselect_mat.result +++ b/mysql-test/main/subselect_mat.result @@ -2697,7 +2697,7 @@ INSERT INTO t2 VALUES (3),(4); CREATE TABLE t3 (c DATETIME, d INT, KEY(c)); INSERT INTO t3 VALUES ('2012-11-11',5),('2012-12-12',6); UPDATE t1, t2 SET t1.a = 26 WHERE t2.b IN (SELECT MIN(d) FROM t3 WHERE c >= '2012-01'); -ERROR 22007: Incorrect datetime value: '2012-01' for column `test`.`t3`.`c` at row 1 +ERROR 22007: Truncated incorrect datetime value: '2012-01' DROP TABLE t1, t2, t3; # # a followup fix: diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result index c7fc78ce28e..2f9b36d19f6 100644 --- a/mysql-test/main/subselect_no_exists_to_in.result +++ b/mysql-test/main/subselect_no_exists_to_in.result @@ -7497,6 +7497,27 @@ ERROR HY000: Illegal parameter data types row and boolean for operation '=' # # End of 10.4 tests # +# +# MDEV-32656: ASAN errors in base_list_iterator::next / +# setup_table_map upon 2nd execution of PS +# (10.6 part) +# +CREATE TABLE t1 (id BIGINT); +INSERT INTO t1 VALUES (1),(2); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (2),(3); +CREATE TABLE t3 (b INT); +INSERT INTO t3 VALUES (3),(4); +insert into t2 select (('e','e') IN (SELECT v1.id, v1.id FROM v1 JOIN t3)); +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +drop view v1; +drop table t1, t2, t3; +# +# End of 10.6 tests +# set optimizer_switch=default; select @@optimizer_switch like '%exists_to_in=off%'; @@optimizer_switch like '%exists_to_in=off%' diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result index 5998be62535..7e692c1a5e1 100644 --- a/mysql-test/main/subselect_no_mat.result +++ b/mysql-test/main/subselect_no_mat.result @@ -7490,6 +7490,27 @@ ERROR HY000: Illegal parameter data types row and boolean for operation '=' # # End of 10.4 tests # +# +# MDEV-32656: ASAN errors in base_list_iterator::next / +# setup_table_map upon 2nd execution of PS +# (10.6 part) +# +CREATE TABLE t1 (id BIGINT); +INSERT INTO t1 VALUES (1),(2); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (2),(3); +CREATE TABLE t3 (b INT); +INSERT INTO t3 VALUES (3),(4); +insert into t2 select (('e','e') IN (SELECT v1.id, v1.id FROM v1 JOIN t3)); +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +drop view v1; +drop table t1, t2, t3; +# +# End of 10.6 tests +# set optimizer_switch=default; select @@optimizer_switch like '%materialization=on%'; @@optimizer_switch like '%materialization=on%' diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result index 4d3ecfd70e1..790e0f847ee 100644 --- a/mysql-test/main/subselect_no_opts.result +++ b/mysql-test/main/subselect_no_opts.result @@ -7488,4 +7488,25 @@ ERROR HY000: Illegal parameter data types row and boolean for operation '=' # # End of 10.4 tests # +# +# MDEV-32656: ASAN errors in base_list_iterator::next / +# setup_table_map upon 2nd execution of PS +# (10.6 part) +# +CREATE TABLE t1 (id BIGINT); +INSERT INTO t1 VALUES (1),(2); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (2),(3); +CREATE TABLE t3 (b INT); +INSERT INTO t3 VALUES (3),(4); +insert into t2 select (('e','e') IN (SELECT v1.id, v1.id FROM v1 JOIN t3)); +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +drop view v1; +drop table t1, t2, t3; +# +# End of 10.6 tests +# set @optimizer_switch_for_subselect_test=null; diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result index 7991829cd49..96d68a94a14 100644 --- a/mysql-test/main/subselect_no_scache.result +++ b/mysql-test/main/subselect_no_scache.result @@ -7503,6 +7503,27 @@ ERROR HY000: Illegal parameter data types row and boolean for operation '=' # # End of 10.4 tests # +# +# MDEV-32656: ASAN errors in base_list_iterator::next / +# setup_table_map upon 2nd execution of PS +# (10.6 part) +# +CREATE TABLE t1 (id BIGINT); +INSERT INTO t1 VALUES (1),(2); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (2),(3); +CREATE TABLE t3 (b INT); +INSERT INTO t3 VALUES (3),(4); +insert into t2 select (('e','e') IN (SELECT v1.id, v1.id FROM v1 JOIN t3)); +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +drop view v1; +drop table t1, t2, t3; +# +# End of 10.6 tests +# set optimizer_switch=default; select @@optimizer_switch like '%subquery_cache=on%'; @@optimizer_switch like '%subquery_cache=on%' diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result index aeac9d4c1ed..5a460281e44 100644 --- a/mysql-test/main/subselect_no_semijoin.result +++ b/mysql-test/main/subselect_no_semijoin.result @@ -7489,6 +7489,27 @@ ERROR HY000: Illegal parameter data types row and boolean for operation '=' # End of 10.4 tests # # +# MDEV-32656: ASAN errors in base_list_iterator::next / +# setup_table_map upon 2nd execution of PS +# (10.6 part) +# +CREATE TABLE t1 (id BIGINT); +INSERT INTO t1 VALUES (1),(2); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (2),(3); +CREATE TABLE t3 (b INT); +INSERT INTO t3 VALUES (3),(4); +insert into t2 select (('e','e') IN (SELECT v1.id, v1.id FROM v1 JOIN t3)); +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +drop view v1; +drop table t1, t2, t3; +# +# End of 10.6 tests +# +# # MDEV-19714: JOIN::pseudo_bits_cond is not visible in EXPLAIN FORMAT=JSON # CREATE TABLE t1 ( a INT ); diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result index 9a3b69da6fa..5275a39d018 100644 --- a/mysql-test/main/subselect_sj_mat.result +++ b/mysql-test/main/subselect_sj_mat.result @@ -2739,7 +2739,7 @@ INSERT INTO t2 VALUES (3),(4); CREATE TABLE t3 (c DATETIME, d INT, KEY(c)); INSERT INTO t3 VALUES ('2012-11-11',5),('2012-12-12',6); UPDATE t1, t2 SET t1.a = 26 WHERE t2.b IN (SELECT MIN(d) FROM t3 WHERE c >= '2012-01'); -ERROR 22007: Incorrect datetime value: '2012-01' for column `test`.`t3`.`c` at row 1 +ERROR 22007: Truncated incorrect datetime value: '2012-01' DROP TABLE t1, t2, t3; # # a followup fix: diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index ed6417a4747..d63db33edb3 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -333,6 +333,7 @@ static bool convert_const_to_int(THD *thd, Item_field *field_item, !(*item)->with_sum_func()) { TABLE *table= field->table; + Use_relaxed_field_copy urfc(thd); MY_BITMAP *old_maps[2] = { NULL, NULL }; ulonglong UNINIT_VAR(orig_field_val); /* original field value if valid */ bool save_field_value; @@ -351,7 +352,7 @@ static bool convert_const_to_int(THD *thd, Item_field *field_item, !(field->table->status & STATUS_NO_RECORD)); if (save_field_value) orig_field_val= field->val_int(); - if (!(*item)->save_in_field_no_warnings(field, 1) && !field->is_null()) + if (!(*item)->save_in_field(field, 1) && !field->is_null()) { int field_cmp= 0; // If item is a decimal value, we must reject it if it was truncated. diff --git a/sql/sql_class.h b/sql/sql_class.h index e6580d2432c..1c7839fc266 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -7723,11 +7723,13 @@ public: class Use_relaxed_field_copy: public Sql_mode_save, - public Check_level_instant_set + public Check_level_instant_set, + public Abort_on_warning_instant_set { public: Use_relaxed_field_copy(THD *thd) : - Sql_mode_save(thd), Check_level_instant_set(thd, CHECK_FIELD_IGNORE) + Sql_mode_save(thd), Check_level_instant_set(thd, CHECK_FIELD_IGNORE), + Abort_on_warning_instant_set(thd, 0) { thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); thd->variables.sql_mode|= MODE_INVALID_DATES; From a44869d8426f7008c686dcdef2919998a472dbed Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 7 Nov 2023 10:55:55 +0530 Subject: [PATCH 157/158] MDEV-31851 Doublewrite recovery fixup recv_dblwr_t::find_page(): Tablespace flags validity should be checked only for page 0. --- storage/innobase/log/log0recv.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index a213b4842ce..8c10e5277d5 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3820,10 +3820,13 @@ byte *recv_dblwr_t::find_page(const page_id_t page_id, if (page_get_page_no(page) != page_id.page_no() || page_get_space_id(page) != page_id.space()) continue; - uint32_t flags= mach_read_from_4( - FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); - if (!fil_space_t::is_valid_flags(flags, page_id.space())) - continue; + if (page_id.page_no() == 0) + { + uint32_t flags= mach_read_from_4( + FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); + if (!fil_space_t::is_valid_flags(flags, page_id.space())) + continue; + } const lsn_t lsn= mach_read_from_8(page + FIL_PAGE_LSN); if (lsn <= max_lsn || From 2a4c57333910345b312f305f00dd1f90228e49fc Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Wed, 8 Nov 2023 13:55:03 +0100 Subject: [PATCH 158/158] MDEV-32728: Wrong mutex usage 'LOCK_thd_data' and 'wait_mutex' Checking for kill with thd_kill_level() or check_killed() runs apc requests, which takes the LOCK_thd_kill mutex. But this is dangerous, as checking for kill needs to be called while holding many different mutexes, and can lead to cyclic mutex dependency and deadlock. But running apc is only "best effort", so skip running the apc if the LOCK_thd_kill is not available. The apc will then be run on next check of kill signal. Signed-off-by: Kristian Nielsen --- sql/my_apc.cc | 9 ++++++--- sql/my_apc.h | 4 ++-- sql/sql_class.cc | 2 +- sql/sql_class.h | 2 +- unittest/sql/my_apc-t.cc | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/sql/my_apc.cc b/sql/my_apc.cc index e0feabab8e2..5a4d2b653ec 100644 --- a/sql/my_apc.cc +++ b/sql/my_apc.cc @@ -197,13 +197,16 @@ bool Apc_target::make_apc_call(THD *caller_thd, Apc_call *call, This should be called periodically by the APC target thread. */ -void Apc_target::process_apc_requests() +void Apc_target::process_apc_requests(bool force) { while (1) { Call_request *request; - - mysql_mutex_lock(LOCK_thd_kill_ptr); + + if (force) + mysql_mutex_lock(LOCK_thd_kill_ptr); + else if (mysql_mutex_trylock(LOCK_thd_kill_ptr)) + break; // Mutex is blocked, try again later if (!(request= get_first_in_queue())) { /* No requests in the queue */ diff --git a/sql/my_apc.h b/sql/my_apc.h index 2c0a9ade314..29fa3172a12 100644 --- a/sql/my_apc.h +++ b/sql/my_apc.h @@ -70,10 +70,10 @@ public: bool process= !--enabled && have_apc_requests(); mysql_mutex_unlock(LOCK_thd_kill_ptr); if (unlikely(process)) - process_apc_requests(); + process_apc_requests(true); } - void process_apc_requests(); + void process_apc_requests(bool force); /* A lightweight function, intended to be used in frequent checks like this: diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 1b78f88bd3c..70e4ae88e3c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -4724,7 +4724,7 @@ extern "C" enum thd_kill_levels thd_kill_level(const MYSQL_THD thd) if (unlikely(apc_target->have_apc_requests())) { if (thd == current_thd) - apc_target->process_apc_requests(); + apc_target->process_apc_requests(false); } return THD_IS_NOT_KILLED; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 1c7839fc266..611b51ff974 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3606,7 +3606,7 @@ public: return TRUE; } if (apc_target.have_apc_requests()) - apc_target.process_apc_requests(); + apc_target.process_apc_requests(false); return FALSE; } diff --git a/unittest/sql/my_apc-t.cc b/unittest/sql/my_apc-t.cc index c08e7281c92..9edb209b1f6 100644 --- a/unittest/sql/my_apc-t.cc +++ b/unittest/sql/my_apc-t.cc @@ -100,7 +100,7 @@ void *test_apc_service_thread(void *ptr) //apc_target.enable(); for (int i = 0; i < 10 && !service_should_exit; i++) { - apc_target.process_apc_requests(); + apc_target.process_apc_requests(true); my_sleep(int_rand(30)); } }