From 275f434392d6e04ece74ddec70abde75c6d86603 Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Tue, 12 Sep 2023 22:17:13 +0300 Subject: [PATCH 001/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] ./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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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/477] 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 eb8053b37756fe99e8ca12bbd966726d9f21c91a Mon Sep 17 00:00:00 2001 From: Rex Date: Mon, 25 Sep 2023 12:56:30 +1100 Subject: [PATCH 146/477] MDEV-31995 Bogus error executing PS for query using CTE with renaming of columns This commit addresses column naming issues with CTEs in the use of prepared statements and stored procedures. Usage of either prepared statements or procedures with Common Table Expressions and column renaming may be affected. There are three related but different issues addressed here. 1) First execution issue. Consider the following prepare s from "with cte (col1, col2) as (select a as c1, b as c2 from t order by c1) select col1, col2 from cte"; execute s; After parsing, items in the select are named (c1,c2), order by (and group by) resolution is performed, then item names are set to (col1, col2). When the statement is executed, context analysis is again performed, but resolution of elements in the order by statement will not be able to find c1, because it was renamed to col1 and remains this way. The solution is to save the names of these items during context resolution before they have been renamed. We can then reset item names back to those after parsing so first execution can resolve items referred to in order and group by clauses. 2) Second Execution Issue When the derived table contains more than one select 'unioned' together we could reasonably think that dealing with only items in the first select (which determines names in the resultant table) would be sufficient. This can lead to a different problem. Consider prepare st from "with cte (c1,c2) as (select a as col1, sum(b) as col2 from t1 where a > 0 group by col1 union select a as col3, sum(b) as col4 from t2 where b > 2 group by col3) select * from cte where c1=1"; When the optimizer (only run during the first execution) pushes the outside condition "c1=1" into every select in the derived table union, it renames the items to make the condition valid. In this example, this leaves the first item in the second select named 'c1'. The second execution will now fail 'group by' resolution. Again, the solution is to save the names during context analysis, resetting before subsequent resolution, but making sure that we save/reset the item names in all the selects in this union. 3) Memory Leak During parsing Item::set_name() is used to allocate memory in the statement arena. We cannot use this call during statement execution as this represents a memory leak. We directly set the item list names to those in the column list of this CTE (also allocated during parsing). Approved by Igor Babaev --- mysql-test/main/cte_nonrecursive.result | 260 ++++++++++++++++++++++++ mysql-test/main/cte_nonrecursive.test | 158 ++++++++++++++ sql/sql_cte.cc | 2 +- sql/sql_derived.cc | 7 + sql/sql_lex.cc | 67 ++++++ sql/sql_lex.h | 8 + sql/sql_select.cc | 20 ++ 7 files changed, 521 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result index f6cb180f4a5..e5ea67aa37f 100644 --- a/mysql-test/main/cte_nonrecursive.result +++ b/mysql-test/main/cte_nonrecursive.result @@ -2339,4 +2339,264 @@ set sql_mode="oracle"; with data as (select 1 as id) select id into @myid from data; set sql_mode= @save_sql_mode; +# +# MDEV-31995 CTE column name specification inconsistency +# +create table t1 (a int, b int); +insert into t1 values (1,1),(1,2),(1,3),(2,1),(2,2); +create table t2 (a int, b int); +insert into t2 values (3,1),(3,2),(3,3),(4,1),(4,2); +with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 group by col1) +select * from cte; +c1 c2 +1 6 +2 3 +prepare st from "with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 group by col1) +select * from cte"; +execute st; +c1 c2 +1 6 +2 3 +execute st; +c1 c2 +1 6 +2 3 +drop prepare st; +create procedure sp() with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 group by col1) +select * from cte; +call sp(); +c1 c2 +1 6 +2 3 +call sp(); +c1 c2 +1 6 +2 3 +drop procedure sp; +with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 order by col1) +select * from cte; +c1 c2 +1 9 +prepare st from "with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 order by col1) +select * from cte"; +execute st; +c1 c2 +1 9 +execute st; +c1 c2 +1 9 +drop prepare st; +create procedure sp() with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 order by col1) +select * from cte; +call sp(); +c1 c2 +1 9 +call sp(); +c1 c2 +1 9 +drop procedure sp; +with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 where a > 1 group by col1 +union select a as col3, sum(b) as col4 from t2 where b > 2 group by col3), +cte2 (c3, c4) as +(select a as col5, sum(b) as col6 from t1 where a <= 1 group by col5 +union select a as col7, sum(b) as col8 from t2 where b <= 2 group by col7) +select * from cte where c1=1 union select * from cte2 where c3=3; +c1 c2 +3 3 +prepare st from "with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 where a > 1 group by col1 +union select a as col3, sum(b) as col4 from t2 where b > 2 group by col3), +cte2 (c3, c4) as +(select a as col5, sum(b) as col6 from t1 where a <= 1 group by col5 +union select a as col7, sum(b) as col8 from t2 where b <= 2 group by col7) +select * from cte where c1=1 union select * from cte2 where c3=3"; +execute st; +c1 c2 +3 3 +execute st; +c1 c2 +3 3 +drop prepare st; +create procedure sp() with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 where a > 1 group by col1 +union select a as col3, sum(b) as col4 from t2 where b > 2 group by col3), +cte2 (c3, c4) as +(select a as col5, sum(b) as col6 from t1 where a <= 1 group by col5 +union select a as col7, sum(b) as col8 from t2 where b <= 2 group by col7) +select * from cte where c1=1 union select * from cte2 where c3=3; +call sp(); +c1 c2 +3 3 +call sp(); +c1 c2 +3 3 +drop procedure sp; +with cte (c1,c2) as (select * from t1) +select cte.c1+1 as col1 , cte.c2 as col2 from cte where cte.c1 > 1 +union +select cte.c1 as col3, cte.c2+1 as col4 from cte where cte.c1 < 0; +col1 col2 +3 1 +3 2 +prepare st from "with cte (c1,c2) as (select * from t1) +select cte.c1+1 as col1 , cte.c2 as col2 from cte where cte.c1 > 1 +union +select cte.c1 as col3, cte.c2+1 as col4 from cte where cte.c1 < 0"; +execute st; +col1 col2 +3 1 +3 2 +execute st; +col1 col2 +3 1 +3 2 +save this to the end to test errors >drop prepare st; +create procedure sp() with cte (c1,c2) as (select * from t1) +select cte.c1+1 as col1 , cte.c2 as col2 from cte where cte.c1 > 1 +union +select cte.c1 as col3, cte.c2+1 as col4 from cte where cte.c1 < 0; +call sp(); +col1 col2 +3 1 +3 2 +call sp(); +col1 col2 +3 1 +3 2 +drop procedure sp; +insert into t1 select * from t2; +with cte (c1, c2) +as (select a, sum(b) from t1 where b > 1 group by a having sum(b) < 5) +select * from cte where c1 < 4 and c2 > 1; +c1 c2 +2 2 +# Check pushdown conditions in JSON output +explain format=json with cte (c1, c2) +as (select a, sum(b) from t1 where b > 1 group by a having sum(b) < 5) +select * from cte where c1 < 4 and c2 > 1; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 10, + "filtered": 100, + "attached_condition": "cte.c1 < 4 and cte.c2 > 1", + "materialized": { + "query_block": { + "select_id": 2, + "having_condition": "sum(t1.b) < 5 and c2 > 1", + "filesort": { + "sort_key": "t1.a", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 10, + "filtered": 100, + "attached_condition": "t1.b > 1 and t1.a < 4" + } + } + } + } + } + } + } +} +alter table t1 add column c int; +execute st; +ERROR HY000: WITH column list and SELECT field list have different column counts +drop prepare st; +drop table t1,t2; +Test out recursive CTEs +create table distances (src char(1), dest char(1), distance int); +create table city_population (city char(1), population int); +INSERT INTO `distances` VALUES ('A','A',0),('B','A',593),('C','A',800), +('D','A',221),('E','A',707),('F','A',869),('G','A',225),('H','A',519), +('A','B',919),('B','B',0),('C','B',440),('D','B',79),('E','B',79), +('F','B',154),('G','B',537),('H','B',220),('A','C',491),('B','C',794), +('C','C',0),('D','C',100),('E','C',350),('F','C',748),('G','C',712), +('H','C',315),('A','D',440),('B','D',256),('C','D',958),('D','D',0), +('E','D',255),('F','D',161),('G','D',63),('H','D',831),('A','E',968), +('B','E',345),('C','E',823),('D','E',81),('E','E',0),('F','E',436), +('G','E',373),('H','E',558),('A','F',670),('B','F',677),('C','F',375), +('D','F',843),('E','F',90),('F','F',0),('G','F',328),('H','F',881), +('A','G',422),('B','G',467),('C','G',67),('D','G',936),('E','G',480), +('F','G',592),('G','G',0),('H','G',819),('A','H',537),('B','H',229), +('C','H',534),('D','H',984),('E','H',319),('F','H',643),('G','H',257), +('H','H',0); +insert into city_population values ('A', 5000), ('B', 6000), ('C', 100000), +('D', 80000), ('E', 7000), ('F', 1000), ('G', 100), ('H', -80000); +#find the biggest city within 300 kellikams of 'E' +with recursive travel (src, path, dest, distance, population) as ( +select city, cast('' as varchar(10)), city, +0, population +from city_population where city='E' + union all +select src.src, concat(src.path, dst.dest), dst.dest, +src.distance + dst.distance, dstc.population +from travel src +join distances dst on src.dest != dst.dest +join city_population dstc on dst.dest = dstc.city +where dst.src = src.dest and src.distance + dst.distance < 300 +and length(path) < 10 +) +select * from travel where dest != 'E' order by population desc, distance +limit 1; +src path dest distance population +E FD D 251 80000 +prepare st from "with recursive travel (src, path, dest, distance, population) as ( +select city, cast('' as varchar(10)), city, +0, population +from city_population where city='E' + union all +select src.src, concat(src.path, dst.dest), dst.dest, +src.distance + dst.distance, dstc.population +from travel src +join distances dst on src.dest != dst.dest +join city_population dstc on dst.dest = dstc.city +where dst.src = src.dest and src.distance + dst.distance < 300 +and length(path) < 10 +) +select * from travel where dest != 'E' order by population desc, distance +limit 1"; +execute st; +src path dest distance population +E FD D 251 80000 +execute st; +src path dest distance population +E FD D 251 80000 +drop prepare st; +create procedure sp() with recursive travel (src, path, dest, distance, population) as ( +select city, cast('' as varchar(10)), city, +0, population +from city_population where city='E' + union all +select src.src, concat(src.path, dst.dest), dst.dest, +src.distance + dst.distance, dstc.population +from travel src +join distances dst on src.dest != dst.dest +join city_population dstc on dst.dest = dstc.city +where dst.src = src.dest and src.distance + dst.distance < 300 +and length(path) < 10 +) +select * from travel where dest != 'E' order by population desc, distance +limit 1; +call sp(); +src path dest distance population +E FD D 251 80000 +call sp(); +src path dest distance population +E FD D 251 80000 +drop procedure sp; +drop table distances, city_population; # End of 10.4 tests diff --git a/mysql-test/main/cte_nonrecursive.test b/mysql-test/main/cte_nonrecursive.test index 3c758f3526e..2919415a0a7 100644 --- a/mysql-test/main/cte_nonrecursive.test +++ b/mysql-test/main/cte_nonrecursive.test @@ -1784,4 +1784,162 @@ with data as (select 1 as id) select id into @myid from data; set sql_mode= @save_sql_mode; + + +--echo # +--echo # MDEV-31995 CTE column name specification inconsistency +--echo # + +create table t1 (a int, b int); +insert into t1 values (1,1),(1,2),(1,3),(2,1),(2,2); +create table t2 (a int, b int); +insert into t2 values (3,1),(3,2),(3,3),(4,1),(4,2); + +let $q= +with cte (c1,c2) as + (select a as col1, sum(b) as col2 from t1 group by col1) +select * from cte; + +eval $q; + +eval prepare st from "$q"; +execute st; +execute st; +drop prepare st; + +eval create procedure sp() $q; +call sp(); +call sp(); +drop procedure sp; + +let $q= +with cte (c1,c2) as + (select a as col1, sum(b) as col2 from t1 order by col1) +select * from cte; + +eval $q; + +eval prepare st from "$q"; +execute st; +execute st; +drop prepare st; + +eval create procedure sp() $q; +call sp(); +call sp(); +drop procedure sp; + +let $q= +with cte (c1,c2) as + (select a as col1, sum(b) as col2 from t1 where a > 1 group by col1 + union select a as col3, sum(b) as col4 from t2 where b > 2 group by col3), +cte2 (c3, c4) as + (select a as col5, sum(b) as col6 from t1 where a <= 1 group by col5 + union select a as col7, sum(b) as col8 from t2 where b <= 2 group by col7) +select * from cte where c1=1 union select * from cte2 where c3=3; + +eval $q; + +eval prepare st from "$q"; +execute st; +execute st; +drop prepare st; + +eval create procedure sp() $q; +call sp(); +call sp(); +drop procedure sp; + +let $q= +with cte (c1,c2) as (select * from t1) +select cte.c1+1 as col1 , cte.c2 as col2 from cte where cte.c1 > 1 +union +select cte.c1 as col3, cte.c2+1 as col4 from cte where cte.c1 < 0; + +eval $q; + +eval prepare st from "$q"; +execute st; +execute st; +--echo save this to the end to test errors >drop prepare st; + +eval create procedure sp() $q; +call sp(); +call sp(); +drop procedure sp; + +insert into t1 select * from t2; + +let $q= +with cte (c1, c2) + as (select a, sum(b) from t1 where b > 1 group by a having sum(b) < 5) +select * from cte where c1 < 4 and c2 > 1; + +eval $q; + +--echo # Check pushdown conditions in JSON output +--source include/analyze-format.inc +eval explain format=json $q; + +alter table t1 add column c int; + +--error ER_WITH_COL_WRONG_LIST +execute st; + +drop prepare st; +drop table t1,t2; + +--echo Test out recursive CTEs + +create table distances (src char(1), dest char(1), distance int); +create table city_population (city char(1), population int); +INSERT INTO `distances` VALUES ('A','A',0),('B','A',593),('C','A',800), +('D','A',221),('E','A',707),('F','A',869),('G','A',225),('H','A',519), +('A','B',919),('B','B',0),('C','B',440),('D','B',79),('E','B',79), +('F','B',154),('G','B',537),('H','B',220),('A','C',491),('B','C',794), +('C','C',0),('D','C',100),('E','C',350),('F','C',748),('G','C',712), +('H','C',315),('A','D',440),('B','D',256),('C','D',958),('D','D',0), +('E','D',255),('F','D',161),('G','D',63),('H','D',831),('A','E',968), +('B','E',345),('C','E',823),('D','E',81),('E','E',0),('F','E',436), +('G','E',373),('H','E',558),('A','F',670),('B','F',677),('C','F',375), +('D','F',843),('E','F',90),('F','F',0),('G','F',328),('H','F',881), +('A','G',422),('B','G',467),('C','G',67),('D','G',936),('E','G',480), +('F','G',592),('G','G',0),('H','G',819),('A','H',537),('B','H',229), +('C','H',534),('D','H',984),('E','H',319),('F','H',643),('G','H',257), +('H','H',0); +insert into city_population values ('A', 5000), ('B', 6000), ('C', 100000), +('D', 80000), ('E', 7000), ('F', 1000), ('G', 100), ('H', -80000); + +--echo #find the biggest city within 300 kellikams of 'E' +let $q= +with recursive travel (src, path, dest, distance, population) as ( + select city, cast('' as varchar(10)), city, + 0, population + from city_population where city='E' + union all + select src.src, concat(src.path, dst.dest), dst.dest, + src.distance + dst.distance, dstc.population + from travel src + join distances dst on src.dest != dst.dest + join city_population dstc on dst.dest = dstc.city + where dst.src = src.dest and src.distance + dst.distance < 300 + and length(path) < 10 + ) +select * from travel where dest != 'E' order by population desc, distance +limit 1; + +eval $q; + +eval prepare st from "$q"; +execute st; +execute st; +drop prepare st; + +eval create procedure sp() $q; +call sp(); +call sp(); +drop procedure sp; + +drop table distances, city_population; + --echo # End of 10.4 tests diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 2e672591d09..da8eb4b79d7 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -1198,7 +1198,7 @@ With_element::rename_columns_of_derived_unit(THD *thd, /* Rename the columns of the first select in the unit */ while ((item= it++, name= nm++)) { - item->set_name(thd, name->str, (uint) name->length, system_charset_info); + lex_string_set(&item->name, name->str); item->is_autogenerated_name= false; } diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 107ac31cd4e..5ed39430f06 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1335,6 +1335,13 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) (derived->alias.str ? derived->alias.str : ""), derived->get_unit())); st_select_lex_unit *unit= derived->get_unit(); + st_select_lex *sl= unit->first_select(); + + // reset item names to that saved after wildcard expansion in JOIN::prepare + do + { + sl->restore_item_list_names(); + } while ((sl= sl->next_select())); derived->merged_for_insert= FALSE; unit->unclean(); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 583322618f9..65a3c44eb58 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2445,6 +2445,7 @@ void st_select_lex::init_query() in_tvc= false; versioned_tables= 0; pushdown_select= 0; + orig_names_of_item_list_elems= 0; } void st_select_lex::init_select() @@ -2491,6 +2492,7 @@ void st_select_lex::init_select() in_tvc= false; versioned_tables= 0; is_tvc_wrapper= false; + orig_names_of_item_list_elems= 0; } /* @@ -10419,6 +10421,71 @@ exit: } +/** + @brief + Save the original names of items from the item list. + + @retval + true - if an error occurs + false - otherwise +*/ + +bool st_select_lex::save_item_list_names(THD *thd) +{ + if (orig_names_of_item_list_elems) + return false; + + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); + + if (unlikely(!(orig_names_of_item_list_elems= new(thd->mem_root) + List))) + return true; + + List_iterator_fast li(item_list); + Item *item; + + while ((item= li++)) + { + if (unlikely(orig_names_of_item_list_elems->push_back( + new Lex_ident_sys(item->name.str, item->name.length)))) + { + if (arena) + thd->restore_active_arena(arena, &backup); + orig_names_of_item_list_elems= 0; + return true; + } + } + + if (arena) + thd->restore_active_arena(arena, &backup); + + return false; +} + + +/** + @brief + Restore the name of each item in the item_list of this st_select_lex + from orig_names_of_item_list_elems. +*/ + +void st_select_lex::restore_item_list_names() +{ + if (!orig_names_of_item_list_elems) + return; + + DBUG_ASSERT(item_list.elements == orig_names_of_item_list_elems->elements); + + List_iterator_fast it(*orig_names_of_item_list_elems); + Lex_ident_sys *new_name; + List_iterator_fast li(item_list); + Item *item; + + while ((item= li++) && (new_name= it++)) + lex_string_set( &item->name, new_name->str); +} + bool LEX::stmt_install_plugin(const DDL_options_st &opt, const Lex_ident_sys_st &name, const LEX_CSTRING &soname) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 1208d63d7f0..6bcfd1bb5a9 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1381,6 +1381,9 @@ public: bool straight_fl); TABLE_LIST *convert_right_join(); List* get_item_list(); + bool save_item_list_names(THD *thd); + void restore_item_list_names(); + ulong get_table_join_options(); void set_lock_for_tables(thr_lock_type lock_type, bool for_update); /* @@ -1568,6 +1571,11 @@ private: index_clause_map current_index_hint_clause; /* a list of USE/FORCE/IGNORE INDEX */ List *index_hints; + /* + This list is used to restore the names of items + from item_list after each execution of the statement. + */ + List *orig_names_of_item_list_elems; public: inline void add_where_field(st_select_lex *sel) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ec66d0baf31..a871faec99e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1311,6 +1311,26 @@ JOIN::prepare(TABLE_LIST *tables_init, &select_lex->hidden_bit_fields)) DBUG_RETURN(-1); + /* + If the select_lex is immediately contained within a derived table + AND this derived table is a CTE + WITH supplied column names + AND we have the correct number of elements in both lists + (mismatches found in mysql_derived_prepare/rename_columns_of_derived_unit) + THEN NOW is the time to take a copy of these item_names for + later restoration if required. + */ + TABLE_LIST *derived= select_lex->master_unit()->derived; + + if (derived && + derived->with && + derived->with->column_list.elements && + (derived->with->column_list.elements == select_lex->item_list.elements)) + { + if (select_lex->save_item_list_names(thd)) + DBUG_RETURN(-1); + } + if (thd->lex->current_select->first_cond_optimization) { if ( conds && ! thd->lex->current_select->merged_into) From 5436b5ddd7abfb8dd2e802c50f93db77040e0a6e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 28 Oct 2023 14:43:10 +0200 Subject: [PATCH 147/477] 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 148/477] 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 149/477] 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 150/477] 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 e52777f1a4df20ffd3ae743b7b64f5e645090cd8 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 7 Jun 2023 07:48:58 -0600 Subject: [PATCH 151/477] MDEV-26272: The macro MASTER_INFO_VAR invokes undefined behaviour MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates to specific replication system variables need to target the active primary connection to support multi-source replication. These variables use the Sys_var_multi_source_ulonglong type. This class uses offsets of the Master_info C++ class to generalize access to its member variables. The problem is that the Master_info class is not of standard layout, and neither are many of its member variables, e.g. rli and rli->relay_log. Because the class is not of standard layout, using offsets to access member variables invokes undefined behavior. This patch changes how Sys_var_multi_source_ulonglong accesses the member variables of Master_info from using parameterized memory offsets to “getter†function pointers. Note that the size parameter and assertion are removed, as they are no longer needed because the condition is guaranteed by compiler type-safety checks. Reviewed By: ============ Kristian Nielsen --- sql/rpl_mi.h | 10 ++++++++++ sql/sys_vars.cc | 8 ++++---- sql/sys_vars.inl | 17 +++++++---------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index b6ff69d1f64..27a8ae98678 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -210,6 +210,16 @@ class Master_info : public Slave_reporting_capability void lock_slave_threads(); void unlock_slave_threads(); + ulonglong get_slave_skip_counter() + { + return rli.slave_skip_counter; + } + + ulonglong get_max_relay_log_size() + { + return rli.max_relay_log_size; + } + /* the variables below are needed because we can change masters on the fly */ char master_log_name[FN_REFLEN+6]; /* Room for multi-*/ char host[HOSTNAME_LENGTH*SYSTEM_CHARSET_MBMAXLEN+1]; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index a2101b94a24..5cd33a5bf81 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5199,7 +5199,7 @@ static Sys_var_uint Sys_slave_net_timeout( */ ulonglong Sys_var_multi_source_ulonglong:: -get_master_info_ulonglong_value(THD *thd, ptrdiff_t offset) const +get_master_info_ulonglong_value(THD *thd) const { Master_info *mi; ulonglong res= 0; // Default value @@ -5207,7 +5207,7 @@ get_master_info_ulonglong_value(THD *thd, ptrdiff_t offset) const if ((mi= get_master_info(&thd->variables.default_master_connection, Sql_condition::WARN_LEVEL_WARN))) { - res= *((ulonglong*) (((uchar*) mi) + master_info_offset)); + res= (mi->*mi_accessor_func)(); mi->release(); } mysql_mutex_lock(&LOCK_global_system_variables); @@ -5277,7 +5277,7 @@ static bool update_slave_skip_counter(sys_var *self, THD *thd, Master_info *mi) static Sys_var_multi_source_ulonglong Sys_slave_skip_counter( "sql_slave_skip_counter", "Skip the next N events from the master log", SESSION_VAR(slave_skip_counter), NO_CMD_LINE, - MASTER_INFO_VAR(rli.slave_skip_counter), + &Master_info::get_slave_skip_counter, VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1), ON_UPDATE(update_slave_skip_counter)); @@ -5293,7 +5293,7 @@ static Sys_var_multi_source_ulonglong Sys_max_relay_log_size( "relay log will be rotated automatically when the size exceeds this " "value. If 0 at startup, it's set to max_binlog_size", SESSION_VAR(max_relay_log_size), CMD_LINE(REQUIRED_ARG), - MASTER_INFO_VAR(rli.max_relay_log_size), + &Master_info::get_max_relay_log_size, VALID_RANGE(0, 1024L*1024*1024), DEFAULT(0), BLOCK_SIZE(IO_SIZE), ON_UPDATE(update_max_relay_log_size)); diff --git a/sql/sys_vars.inl b/sql/sys_vars.inl index 3e282de439a..20d7214709e 100644 --- a/sql/sys_vars.inl +++ b/sql/sys_vars.inl @@ -2322,10 +2322,10 @@ public: like sql_slave_skip_counter are GLOBAL. */ -#define MASTER_INFO_VAR(X) my_offsetof(Master_info, X), sizeof(((Master_info *)0x10)->X) class Sys_var_multi_source_ulonglong; class Master_info; +typedef ulonglong (Master_info::*mi_ulonglong_accessor_function)(void); typedef bool (*on_multi_source_update_function)(sys_var *self, THD *thd, Master_info *mi); bool update_multi_source_variable(sys_var *self, @@ -2334,26 +2334,23 @@ bool update_multi_source_variable(sys_var *self, class Sys_var_multi_source_ulonglong :public Sys_var_ulonglong { - ptrdiff_t master_info_offset; + mi_ulonglong_accessor_function mi_accessor_func; on_multi_source_update_function update_multi_source_variable_func; public: Sys_var_multi_source_ulonglong(const char *name_arg, const char *comment, int flag_args, ptrdiff_t off, size_t size, CMD_LINE getopt, - ptrdiff_t master_info_offset_arg, - size_t master_info_arg_size, + mi_ulonglong_accessor_function mi_accessor_arg, ulonglong min_val, ulonglong max_val, ulonglong def_val, uint block_size, on_multi_source_update_function on_update_func) :Sys_var_ulonglong(name_arg, comment, flag_args, off, size, getopt, min_val, max_val, def_val, block_size, 0, VARIABLE_NOT_IN_BINLOG, 0, update_multi_source_variable), - master_info_offset(master_info_offset_arg), + mi_accessor_func(mi_accessor_arg), update_multi_source_variable_func(on_update_func) - { - SYSVAR_ASSERT(master_info_arg_size == size); - } + { } bool global_update(THD *thd, set_var *var) { return session_update(thd, var); @@ -2367,7 +2364,7 @@ public: { ulonglong *tmp, res; tmp= (ulonglong*) (((uchar*)&(thd->variables)) + offset); - res= get_master_info_ulonglong_value(thd, master_info_offset); + res= get_master_info_ulonglong_value(thd); *tmp= res; return (uchar*) tmp; } @@ -2375,7 +2372,7 @@ public: { return session_value_ptr(thd, base); } - ulonglong get_master_info_ulonglong_value(THD *thd, ptrdiff_t offset) const; + ulonglong get_master_info_ulonglong_value(THD *thd) const; bool update_variable(THD *thd, Master_info *mi) { return update_multi_source_variable_func(this, thd, mi); From ee773753778e741c1aff1449fcd41b775701a4db Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Wed, 7 Dec 2022 14:14:24 +0100 Subject: [PATCH 152/477] MDEV-26875: Wrong user in SET DEFAULT ROLE error - Regression introduced in 957cb7b7ba35 - Patch 4abb8216a054 change `mysql.user` to `mysql.global_priv` for `add_anonymous.inc`, update `delete_anonymous.inc`. - Added test case with `--skip-name-resolve` - Add test case with anonymous user - Disable this test for windows, assignes current user to anonymous user. Reviewed by: --- mysql-test/include/delete_anonymous_users.inc | 2 +- .../suite/roles/set_default_role_for.result | 2 +- .../roles/set_default_role_invalid.result | 6 +- .../suite/roles/set_default_role_invalid.test | 1 - ..._role_invalid_skip_name_resolve-master.opt | 1 + ...ault_role_invalid_skip_name_resolve.result | 85 +++++++++++++++++++ ...efault_role_invalid_skip_name_resolve.test | 78 +++++++++++++++++ sql/sql_acl.cc | 16 +++- 8 files changed, 181 insertions(+), 10 deletions(-) create mode 100644 mysql-test/suite/roles/set_default_role_invalid_skip_name_resolve-master.opt create mode 100644 mysql-test/suite/roles/set_default_role_invalid_skip_name_resolve.result create mode 100644 mysql-test/suite/roles/set_default_role_invalid_skip_name_resolve.test diff --git a/mysql-test/include/delete_anonymous_users.inc b/mysql-test/include/delete_anonymous_users.inc index 704e74ae4a3..cc44a01fe8d 100644 --- a/mysql-test/include/delete_anonymous_users.inc +++ b/mysql-test/include/delete_anonymous_users.inc @@ -1,7 +1,7 @@ # Remove anonymous users added by add_anonymous_users.inc disable_warnings; disable_query_log; -DELETE FROM mysql.user where host='localhost' and user=''; +DELETE FROM mysql.global_priv where host='localhost' and user=''; FLUSH PRIVILEGES; enable_query_log; enable_warnings; diff --git a/mysql-test/suite/roles/set_default_role_for.result b/mysql-test/suite/roles/set_default_role_for.result index 57a1471126c..1b133b1baae 100644 --- a/mysql-test/suite/roles/set_default_role_for.result +++ b/mysql-test/suite/roles/set_default_role_for.result @@ -14,7 +14,7 @@ set default role role_a for user_a@localhost; set default role invalid_role for user_a@localhost; ERROR OP000: Invalid role specification `invalid_role` set default role role_b for user_a@localhost; -ERROR OP000: User `root`@`localhost` has not been granted role `role_b` +ERROR OP000: User `user_a`@`localhost` has not been granted role `role_b` set default role role_b for user_b@localhost; show grants; Grants for user_a@localhost diff --git a/mysql-test/suite/roles/set_default_role_invalid.result b/mysql-test/suite/roles/set_default_role_invalid.result index 12e2c035a7d..2cd84cf2ff0 100644 --- a/mysql-test/suite/roles/set_default_role_invalid.result +++ b/mysql-test/suite/roles/set_default_role_invalid.result @@ -48,7 +48,7 @@ CREATE USER b; CREATE ROLE r1; CREATE ROLE r2; SET DEFAULT ROLE r1 FOR a; -ERROR OP000: User `root`@`localhost` has not been granted role `r1` +ERROR OP000: User `a`@`%` has not been granted role `r1` GRANT r1 TO b; GRANT r2 TO b; SET DEFAULT ROLE r1 FOR b; @@ -100,7 +100,7 @@ GRANT USAGE ON *.* TO `b`@`%` GRANT SELECT, UPDATE ON `mysql`.* TO `b`@`%` SET DEFAULT ROLE `r2` FOR `b`@`%` SET DEFAULT ROLE r1 FOR a; -ERROR OP000: User `b`@`%` has not been granted role `r1` +ERROR OP000: User `a`@`%` has not been granted role `r1` SET DEFAULT ROLE invalid_role; ERROR OP000: Invalid role specification `invalid_role` SET DEFAULT ROLE invalid_role FOR a; @@ -117,7 +117,7 @@ SET DEFAULT ROLE None; # Change user b (session 3: role granted to user a) SET DEFAULT ROLE r1 FOR a; SET DEFAULT ROLE r2 FOR a; -ERROR OP000: User `b`@`%` has not been granted role `r2` +ERROR OP000: User `a`@`%` has not been granted role `r2` SET DEFAULT ROLE invalid_role; ERROR OP000: Invalid role specification `invalid_role` SET DEFAULT ROLE invalid_role FOR a; diff --git a/mysql-test/suite/roles/set_default_role_invalid.test b/mysql-test/suite/roles/set_default_role_invalid.test index 02fca1107e2..d2ef01b8f88 100644 --- a/mysql-test/suite/roles/set_default_role_invalid.test +++ b/mysql-test/suite/roles/set_default_role_invalid.test @@ -70,7 +70,6 @@ CREATE USER a; CREATE USER b; CREATE ROLE r1; CREATE ROLE r2; -# Role has not been granted to user a, but the role is visible to current_user --error ER_INVALID_ROLE SET DEFAULT ROLE r1 FOR a; # Granting roles to user b diff --git a/mysql-test/suite/roles/set_default_role_invalid_skip_name_resolve-master.opt b/mysql-test/suite/roles/set_default_role_invalid_skip_name_resolve-master.opt new file mode 100644 index 00000000000..ec008a812ce --- /dev/null +++ b/mysql-test/suite/roles/set_default_role_invalid_skip_name_resolve-master.opt @@ -0,0 +1 @@ +--skip-name-resolve \ No newline at end of file diff --git a/mysql-test/suite/roles/set_default_role_invalid_skip_name_resolve.result b/mysql-test/suite/roles/set_default_role_invalid_skip_name_resolve.result new file mode 100644 index 00000000000..a267e114012 --- /dev/null +++ b/mysql-test/suite/roles/set_default_role_invalid_skip_name_resolve.result @@ -0,0 +1,85 @@ +# +# MDEV-26875: Wrong user in SET DEFAULT ROLE error +# +create user test_user; +create role test_role; +show grants for test_user; +Grants for test_user@% +GRANT USAGE ON *.* TO `test_user`@`%` +set default role test_role for test_user; +ERROR OP000: User `test_user`@`%` has not been granted role `test_role` +grant test_role to test_user; +set default role test_role for test_user; +show grants for test_user; +Grants for test_user@% +GRANT `test_role` TO `test_user`@`%` +GRANT USAGE ON *.* TO `test_user`@`%` +SET DEFAULT ROLE `test_role` FOR `test_user`@`%` +set default role none for test_user; +# +# Try to set default role to role(`test_role`). +-------------------------------------------------------------- +show grants for test_role; +Grants for test_role +GRANT USAGE ON *.* TO `test_role` +create role new_role; +grant new_role to test_role; +show grants for test_role; +Grants for test_role +GRANT `new_role` TO `test_role` +GRANT USAGE ON *.* TO `test_role` +GRANT USAGE ON *.* TO `new_role` +set default role new_role for test_role; +ERROR OP000: User `test_role`@`%` has not been granted role `new_role` +# +# Test of errors, where hostname cannot be resolved `test_user` +-------------------------------------------------------------- +grant test_role to test_user@'%'; +set default role test_role for test_user@'%'; +connect con_test_user,127.0.0.1,test_user,,,$MASTER_MYPORT; +show grants; +Grants for test_user@% +GRANT `test_role` TO `test_user`@`%` +GRANT USAGE ON *.* TO `test_user`@`%` +GRANT `new_role` TO `test_role` +GRANT USAGE ON *.* TO `test_role` +GRANT USAGE ON *.* TO `new_role` +SET DEFAULT ROLE `test_role` FOR `test_user`@`%` +select current_role; +current_role +test_role +set role `new_role`; +ERROR OP000: User `test_user`@`%` has not been granted role `new_role` +connection default; +set default role none for test_user; +disconnect con_test_user; +connect con_test_user,127.0.0.1,test_user,,,$MASTER_MYPORT; +select current_role; +current_role +NULL +set role `new_role`; +ERROR OP000: User `test_user`@`%` has not been granted role `new_role` +connection default; +disconnect con_test_user; +# +# Test of anonymous user connection +-------------------------------------------------------------- +grant test_role to ''@localhost; +connect con1,localhost,'',,,$MASTER_MYPORT; +SELECT CURRENT_ROLE; +CURRENT_ROLE +NULL +SET role test_role; +SELECT CURRENT_ROLE; +CURRENT_ROLE +test_role +SET role new_role; +ERROR OP000: User ``@`localhost` has not been granted role `new_role` +set default role test_role for ''@localhost; +ERROR 42000: You are using MariaDB as an anonymous user and anonymous users are not allowed to modify user settings +connection default; +disconnect con1; +REVOKE all privileges, grant option from ''@localhost; +drop role new_role; +drop role test_role; +drop user test_user; diff --git a/mysql-test/suite/roles/set_default_role_invalid_skip_name_resolve.test b/mysql-test/suite/roles/set_default_role_invalid_skip_name_resolve.test new file mode 100644 index 00000000000..5b4b14d3377 --- /dev/null +++ b/mysql-test/suite/roles/set_default_role_invalid_skip_name_resolve.test @@ -0,0 +1,78 @@ +source include/not_embedded.inc; + +--echo # +--echo # MDEV-26875: Wrong user in SET DEFAULT ROLE error +--echo # +create user test_user; +create role test_role; +show grants for test_user; +--error ER_INVALID_ROLE +set default role test_role for test_user; +grant test_role to test_user; +set default role test_role for test_user; +show grants for test_user; +set default role none for test_user; + +--echo # +--echo # Try to set default role to role(`test_role`). +--echo -------------------------------------------------------------- +show grants for test_role; +create role new_role; +grant new_role to test_role; +show grants for test_role; +# One can not set role to a role +--error ER_INVALID_ROLE +set default role new_role for test_role; + +--echo # +--echo # Test of errors, where hostname cannot be resolved `test_user` +--echo -------------------------------------------------------------- +# `new_role` is granted to `test_role` +grant test_role to test_user@'%'; +set default role test_role for test_user@'%'; + +connect con_test_user,127.0.0.1,test_user,,,$MASTER_MYPORT; +show grants; +select current_role; +# `test_user` indirectly granted `new_role` +--error ER_INVALID_ROLE +set role `new_role`; + +connection default; +set default role none for test_user; +disconnect con_test_user; + +connect con_test_user,127.0.0.1,test_user,,,$MASTER_MYPORT; +select current_role; +--error ER_INVALID_ROLE +set role `new_role`; + +connection default; +disconnect con_test_user; + +--echo # +--echo # Test of anonymous user connection +--echo -------------------------------------------------------------- +--source include/add_anonymous_users.inc +# Skip windows, since it uses current user `Administrator` in buildbot. +--source include/not_windows.inc +grant test_role to ''@localhost; + +connect(con1,localhost,'',,,$MASTER_MYPORT); +SELECT CURRENT_ROLE; +SET role test_role; +SELECT CURRENT_ROLE; +# user cannot set subset role, since it is not granted explicitly +--error ER_INVALID_ROLE +SET role new_role; +--error ER_PASSWORD_ANONYMOUS_USER +set default role test_role for ''@localhost; + +connection default; +disconnect con1; +REVOKE all privileges, grant option from ''@localhost; +--source include/delete_anonymous_users.inc + +drop role new_role; +drop role test_role; +drop user test_user; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 5468c19f531..3735d9e965d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3339,10 +3339,18 @@ end: check_role_is_granted_callback, NULL) == -1)) { - /* Role is not granted but current user can see the role */ - my_printf_error(ER_INVALID_ROLE, "User %`s@%`s has not been granted role %`s", - MYF(0), thd->security_ctx->priv_user, - thd->security_ctx->priv_host, rolename); + /* This happens for SET ROLE case and when `--skip-name-resolve` option + is used. In that situation host can be NULL and current user is always + target user, so printing `priv_user@priv_host` is not incorrect. + */ + if (!host) + my_printf_error(ER_INVALID_ROLE, "User %`s@%`s has not been granted role %`s", + MYF(0), thd->security_ctx->priv_user, + thd->security_ctx->priv_host, rolename); + else + /* Role is not granted but current user can see the role */ + my_printf_error(ER_INVALID_ROLE, "User %`s@%`s has not been granted role %`s", + MYF(0), user, host, rolename); } else { From 4eb8aeee8e15f0267b19487bc0953f27136f6737 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Tue, 17 Oct 2023 15:41:52 +0200 Subject: [PATCH 153/477] MDEV-32462: mysql_upgrade -s still checks for non system tables - Prevent opening of any user tables in case `upgrade-system-table` option is used. - Still there may be uninstalled data types in `mysql` system table so allow it to perform. - Closes PR #2790 - Reviewer: , --- client/mysql_upgrade.c | 2 + ...ql_json_mysql_upgrade_system_tables.result | 93 +++++++++++++++++++ ...ysql_json_mysql_upgrade_system_tables.test | 52 +++++++++++ 3 files changed, 147 insertions(+) create mode 100644 mysql-test/main/mysql_json_mysql_upgrade_system_tables.result create mode 100644 mysql-test/main/mysql_json_mysql_upgrade_system_tables.test diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 60eb61938d4..617d5464e34 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1155,6 +1155,8 @@ static int install_used_plugin_data_types(void) DYNAMIC_STRING ds_result; const char *query = "SELECT table_comment FROM information_schema.tables" " WHERE table_comment LIKE 'Unknown data type: %'"; + if (opt_systables_only) + return 0; if (init_dynamic_string(&ds_result, "", 512, 512)) die("Out of memory"); run_query(query, &ds_result, TRUE); diff --git a/mysql-test/main/mysql_json_mysql_upgrade_system_tables.result b/mysql-test/main/mysql_json_mysql_upgrade_system_tables.result new file mode 100644 index 00000000000..95ca68f43a6 --- /dev/null +++ b/mysql-test/main/mysql_json_mysql_upgrade_system_tables.result @@ -0,0 +1,93 @@ +# +# MDEV-32462: mysql_upgrade -s still checks for non system tables +# +call mtr.add_suppression("Table rebuild required"); +SET NAMES utf8; +# mariadb_upgrade on system and user table +show tables from mysql like '%json%'; +Tables_in_mysql (%json%) +mysql_json_test +use mysql; +show create table mysql.mysql_json_test; +ERROR HY000: Unknown data type: 'MYSQL_JSON' +show create table test.mysql_json_test; +ERROR HY000: Unknown data type: 'MYSQL_JSON' +SET @old_general_log= @@global.general_log; +SET @old_log_output= @@global.log_output; +SET @@global.general_log = ON; +SET @@global.log_output = "TABLE"; +The --upgrade-system-tables option was used, user tables won't be touched. +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 +Error : Unknown storage engine 'InnoDB' +error : Corrupt +mysql.innodb_table_stats +Error : Unknown storage engine 'InnoDB' +error : Corrupt +mysql.mysql_json_test +Error : Unknown data type: 'MYSQL_JSON' +error : Corrupt +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 +Error : Unknown storage engine 'InnoDB' +error : Corrupt + +Repairing tables +mysql.innodb_index_stats +Error : Unknown storage engine 'InnoDB' +error : Corrupt +mysql.innodb_table_stats +Error : Unknown storage engine 'InnoDB' +error : Corrupt +mysql.mysql_json_test +Error : Unknown data type: 'MYSQL_JSON' +error : Corrupt +mysql.transaction_registry +Error : Unknown storage engine 'InnoDB' +error : Corrupt +Phase 2/7: Installing used storage engines... Skipped +Phase 3/7: Fixing views... Skipped +Phase 4/7: Running 'mysql_fix_privilege_tables' +Phase 5/7: Fixing table and database names ... Skipped +Phase 6/7: Checking and upgrading tables... Skipped +Phase 7/7: Running 'FLUSH PRIVILEGES' +OK +SET @@global.general_log = @old_general_log; +SET @@global.log_output = @old_log_output; +select command_type, argument from mysql.general_log where argument like "%SELECT table_comment FROM information_schema.tables%"; +command_type argument +show create table mysql.mysql_json_test; +ERROR HY000: Unknown data type: 'MYSQL_JSON' +show create table test.mysql_json_test; +ERROR HY000: Unknown data type: 'MYSQL_JSON' +drop table mysql.mysql_json_test; +drop table test.mysql_json_test; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/mysql_json_mysql_upgrade_system_tables.test b/mysql-test/main/mysql_json_mysql_upgrade_system_tables.test new file mode 100644 index 00000000000..6ae3e8ddea1 --- /dev/null +++ b/mysql-test/main/mysql_json_mysql_upgrade_system_tables.test @@ -0,0 +1,52 @@ +--echo # +--echo # MDEV-32462: mysql_upgrade -s still checks for non system tables +--echo # + +# Let's now load plugin first +--source include/have_utf8.inc +--source include/not_embedded.inc + +--source include/mysql_upgrade_preparation.inc +call mtr.add_suppression("Table rebuild required"); + +SET NAMES utf8; + +let $MYSQLD_DATADIR= `select @@datadir`; + +--echo # mariadb_upgrade on system and user table +--copy_file std_data/mysql_json/mysql_json_test.frm $MYSQLD_DATADIR/mysql/mysql_json_test.frm +--copy_file std_data/mysql_json/mysql_json_test.MYI $MYSQLD_DATADIR/mysql/mysql_json_test.MYI +--copy_file std_data/mysql_json/mysql_json_test.MYD $MYSQLD_DATADIR/mysql/mysql_json_test.MYD +--copy_file std_data/mysql_json/mysql_json_test.frm $MYSQLD_DATADIR/test/mysql_json_test.frm +--copy_file std_data/mysql_json/mysql_json_test.MYI $MYSQLD_DATADIR/test/mysql_json_test.MYI +--copy_file std_data/mysql_json/mysql_json_test.MYD $MYSQLD_DATADIR/test/mysql_json_test.MYD + +show tables from mysql like '%json%'; +use mysql; +--error ER_UNKNOWN_DATA_TYPE +show create table mysql.mysql_json_test; +--error ER_UNKNOWN_DATA_TYPE +show create table test.mysql_json_test; + +SET @old_general_log= @@global.general_log; +SET @old_log_output= @@global.log_output; +SET @@global.general_log = ON; +SET @@global.log_output = "TABLE"; +--exec $MYSQL_UPGRADE -s --force 2>&1 +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info +SET @@global.general_log = @old_general_log; +SET @@global.log_output = @old_log_output; + +select command_type, argument from mysql.general_log where argument like "%SELECT table_comment FROM information_schema.tables%"; + +# User table is not upgraded in `mysql\test` DB, so we cannot see it. +--error ER_UNKNOWN_DATA_TYPE +show create table mysql.mysql_json_test; +--error ER_UNKNOWN_DATA_TYPE +show create table test.mysql_json_test; +drop table mysql.mysql_json_test; +drop table test.mysql_json_test; + +--echo # +--echo # End of 10.5 tests +--echo # From b06ac9a8cd2146e89270cc2150d306d8ed1b33fb Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Thu, 19 Oct 2023 09:21:18 +0200 Subject: [PATCH 154/477] MDEV-32462: mysql_upgrade -s still checks for non system tables - Rename files as requested by Vicentiu: ``` mysql_json_mysql_upgrade.test -> mysql_upgrade_mysql_json.test mysql_json_mysql_upgrade_with_plugin_loaded.test -> mysql_upgrade_mysql_json_with_plugin_loaded.test mysql_json_mysql_upgrade_system_tables.test -> mysql_upgrade_mysql_json_system_tables.test ``` - Related to PR #2790 - Reviewer: , --- ..._json_mysql_upgrade.result => mysql_upgrade_mysql_json.result} | 0 ...ysql_json_mysql_upgrade.test => mysql_upgrade_mysql_json.test} | 0 ...ables.result => mysql_upgrade_mysql_json_system_tables.result} | 0 ...em_tables.test => mysql_upgrade_mysql_json_system_tables.test} | 0 ....result => mysql_upgrade_mysql_json_with_plugin_loaded.result} | 0 ...aded.test => mysql_upgrade_mysql_json_with_plugin_loaded.test} | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename mysql-test/main/{mysql_json_mysql_upgrade.result => mysql_upgrade_mysql_json.result} (100%) rename mysql-test/main/{mysql_json_mysql_upgrade.test => mysql_upgrade_mysql_json.test} (100%) rename mysql-test/main/{mysql_json_mysql_upgrade_system_tables.result => mysql_upgrade_mysql_json_system_tables.result} (100%) rename mysql-test/main/{mysql_json_mysql_upgrade_system_tables.test => mysql_upgrade_mysql_json_system_tables.test} (100%) rename mysql-test/main/{mysql_json_mysql_upgrade_with_plugin_loaded.result => mysql_upgrade_mysql_json_with_plugin_loaded.result} (100%) rename mysql-test/main/{mysql_json_mysql_upgrade_with_plugin_loaded.test => mysql_upgrade_mysql_json_with_plugin_loaded.test} (100%) diff --git a/mysql-test/main/mysql_json_mysql_upgrade.result b/mysql-test/main/mysql_upgrade_mysql_json.result similarity index 100% rename from mysql-test/main/mysql_json_mysql_upgrade.result rename to mysql-test/main/mysql_upgrade_mysql_json.result diff --git a/mysql-test/main/mysql_json_mysql_upgrade.test b/mysql-test/main/mysql_upgrade_mysql_json.test similarity index 100% rename from mysql-test/main/mysql_json_mysql_upgrade.test rename to mysql-test/main/mysql_upgrade_mysql_json.test diff --git a/mysql-test/main/mysql_json_mysql_upgrade_system_tables.result b/mysql-test/main/mysql_upgrade_mysql_json_system_tables.result similarity index 100% rename from mysql-test/main/mysql_json_mysql_upgrade_system_tables.result rename to mysql-test/main/mysql_upgrade_mysql_json_system_tables.result diff --git a/mysql-test/main/mysql_json_mysql_upgrade_system_tables.test b/mysql-test/main/mysql_upgrade_mysql_json_system_tables.test similarity index 100% rename from mysql-test/main/mysql_json_mysql_upgrade_system_tables.test rename to mysql-test/main/mysql_upgrade_mysql_json_system_tables.test diff --git a/mysql-test/main/mysql_json_mysql_upgrade_with_plugin_loaded.result b/mysql-test/main/mysql_upgrade_mysql_json_with_plugin_loaded.result similarity index 100% rename from mysql-test/main/mysql_json_mysql_upgrade_with_plugin_loaded.result rename to mysql-test/main/mysql_upgrade_mysql_json_with_plugin_loaded.result diff --git a/mysql-test/main/mysql_json_mysql_upgrade_with_plugin_loaded.test b/mysql-test/main/mysql_upgrade_mysql_json_with_plugin_loaded.test similarity index 100% rename from mysql-test/main/mysql_json_mysql_upgrade_with_plugin_loaded.test rename to mysql-test/main/mysql_upgrade_mysql_json_with_plugin_loaded.test From 6fa69ad7477d4a1a1f9031959b633fcdbf2981a7 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Tue, 24 Oct 2023 13:06:45 +0200 Subject: [PATCH 155/477] MDEV-27436: binlog corruption (/tmp no space left on device at the same moment) This commit fixes several bugs in error handling around disk full when writing the statement/transaction binlog caches: 1. If the error occurs during a non-transactional statement, the code attempts to binlog the partially executed statement (as it cannot roll back). The stmt_cache->error was still set from the disk full error. This caused MYSQL_BIN_LOG::write_cache() to get an error while trying to read the cache to copy it to the binlog. This was then wrongly interpreted as a disk full error writing to the binlog file. As a result, a partial event group containing just a GTID event (no query or commit) was binlogged. Fixed by checking if an error is set in the statement cache, and if so binlog an INCIDENT event instead of a corrupt event group, as for other errors. 2. For LOAD DATA LOCAL INFILE, if a disk full error occured while writing to the statement cache, the code would attempt to abort and read-and-discard any remaining data sent by the client. The discard code would however continue trying to write data to the statement cache, and wrongly interpret another disk full error as end-of-file from the client. This left the client connection with extra data which corrupts the communication for the next command, as well as again causing an corrupt/incomplete event to be binlogged. Fixed by restoring the default read function before reading any remaining data from the client connection. Reviewed-by: Andrei Elkin Signed-off-by: Kristian Nielsen --- ...rpl_binlog_cache_disk_full_loaddata.result | 38 ++++++++++++ .../r/rpl_binlog_cache_disk_full_row.result | 51 ++++++++++++++++ .../rpl_binlog_cache_disk_full_loaddata.test | 47 ++++++++++++++ .../rpl/t/rpl_binlog_cache_disk_full_row.test | 61 +++++++++++++++++++ sql/log.cc | 58 ++++++++++++++++-- sql/log.h | 1 + sql/sql_load.cc | 4 ++ sql/sql_repl.cc | 34 ++++++++++- 8 files changed, 286 insertions(+), 8 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_binlog_cache_disk_full_loaddata.result create mode 100644 mysql-test/suite/rpl/r/rpl_binlog_cache_disk_full_row.result create mode 100644 mysql-test/suite/rpl/t/rpl_binlog_cache_disk_full_loaddata.test create mode 100644 mysql-test/suite/rpl/t/rpl_binlog_cache_disk_full_row.test diff --git a/mysql-test/suite/rpl/r/rpl_binlog_cache_disk_full_loaddata.result b/mysql-test/suite/rpl/r/rpl_binlog_cache_disk_full_loaddata.result new file mode 100644 index 00000000000..a876a597aea --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_binlog_cache_disk_full_loaddata.result @@ -0,0 +1,38 @@ +include/master-slave.inc +[connection master] +connection master; +SET @save_binlog_stmt_cache_size= @@GLOBAL.binlog_stmt_cache_size; +SET GLOBAL binlog_stmt_cache_size= 4096; +CALL mtr.add_suppression('"No space left on device".*An incident event is written to binary log'); +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=MyISAM; +FLUSH STATUS; +SHOW STATUS LIKE "binlog_stmt_cache%"; +Variable_name Value +Binlog_stmt_cache_disk_use 0 +Binlog_stmt_cache_use 0 +SET @old_dbug= @@SESSION.debug_dbug; +SET SESSION debug_dbug="+d,load_data_binlog_cache_error"; +LOAD DATA CONCURRENT LOCAL INFILE 'std_data/bug30435_5k.txt' + REPLACE INTO TABLE t1 (a); +ERROR HY000: Error writing file '' (Errcode: 28 "No space left on device") +SET SESSION debug_dbug= @old_dbug; +SHOW STATUS LIKE "binlog_stmt_cache%"; +Variable_name Value +Binlog_stmt_cache_disk_use 1 +Binlog_stmt_cache_use 1 +SELECT IF(COUNT(*) > 0 AND COUNT(*) < 5000, +"ok", +CONCAT("ERROR! Row count ", COUNT(*), " not as expected for partially executed query")) +AS check_result +FROM t1; +check_result +ok +connection slave; +include/wait_for_slave_sql_error_and_skip.inc [errno=1590] +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +connection master; +SET GLOBAL binlog_stmt_cache_size= @save_binlog_stmt_cache_size; +DROP TABLE t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_binlog_cache_disk_full_row.result b/mysql-test/suite/rpl/r/rpl_binlog_cache_disk_full_row.result new file mode 100644 index 00000000000..753fdaa4e6b --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_binlog_cache_disk_full_row.result @@ -0,0 +1,51 @@ +include/master-slave.inc +[connection master] +connection master; +SET @save_binlog_stmt_cache_size= @@GLOBAL.binlog_stmt_cache_size; +SET GLOBAL binlog_stmt_cache_size= 4096; +CALL mtr.add_suppression('"No space left on device".*An incident event is written to binary log'); +CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(255)) ENGINE=MyISAM; +FLUSH STATUS; +SHOW STATUS LIKE "binlog_stmt_cache%"; +Variable_name Value +Binlog_stmt_cache_disk_use 0 +Binlog_stmt_cache_use 0 +INSERT INTO t1 VALUES (0, CONCAT("?", "-", REPEAT("x", 200))); +INSERT INTO t1 SELECT a+1, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+2, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+4, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+8, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+16, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+32, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+64, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+128, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +SHOW STATUS LIKE "binlog_stmt_cache%"; +Variable_name Value +Binlog_stmt_cache_disk_use 2 +Binlog_stmt_cache_use 9 +SET @old_dbug= @@SESSION.debug_dbug; +SET SESSION debug_dbug="+d,simulate_disk_full_at_flush_pending"; +INSERT INTO t1 SELECT a+256, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +ERROR HY000: Error writing file '' (Errcode: 28 "No space left on device") +SET SESSION debug_dbug= @old_dbug; +SHOW STATUS LIKE "binlog_stmt_cache%"; +Variable_name Value +Binlog_stmt_cache_disk_use 3 +Binlog_stmt_cache_use 10 +SELECT IF(COUNT(*) > 256 AND COUNT(*) < 512, +"ok", +CONCAT("ERROR! Row count ", COUNT(*), " not as expected for partially executed query")) +AS check_result +FROM t1; +check_result +ok +ALTER TABLE t1 COMMENT ''; +connection slave; +include/wait_for_slave_sql_error_and_skip.inc [errno=1590] +SELECT COUNT(*) FROM t1; +COUNT(*) +256 +connection master; +SET GLOBAL binlog_stmt_cache_size= @save_binlog_stmt_cache_size; +DROP TABLE t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_cache_disk_full_loaddata.test b/mysql-test/suite/rpl/t/rpl_binlog_cache_disk_full_loaddata.test new file mode 100644 index 00000000000..50a67532501 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_cache_disk_full_loaddata.test @@ -0,0 +1,47 @@ +--source include/have_binlog_format_statement.inc +--source include/have_debug.inc +--source include/master-slave.inc + +--connection master +# Set minimal cache size so smaller transaction can trigger spill to disk. +SET @save_binlog_stmt_cache_size= @@GLOBAL.binlog_stmt_cache_size; +SET GLOBAL binlog_stmt_cache_size= 4096; + +CALL mtr.add_suppression('"No space left on device".*An incident event is written to binary log'); +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=MyISAM; + +FLUSH STATUS; +SHOW STATUS LIKE "binlog_stmt_cache%"; +SET @old_dbug= @@SESSION.debug_dbug; +SET SESSION debug_dbug="+d,load_data_binlog_cache_error"; +--replace_regex /Error writing file '[^']+'/Error writing file ''/ +--error 3 +LOAD DATA CONCURRENT LOCAL INFILE 'std_data/bug30435_5k.txt' + REPLACE INTO TABLE t1 (a); +SET SESSION debug_dbug= @old_dbug; +SHOW STATUS LIKE "binlog_stmt_cache%"; +# The actual number of rows left after the disk full error may change as +# binlog event sizes are modified. So here we just test that we get partial +# update from the last INSERT..SELECT that gets disk full error. +SELECT IF(COUNT(*) > 0 AND COUNT(*) < 5000, + "ok", + CONCAT("ERROR! Row count ", COUNT(*), " not as expected for partially executed query")) + AS check_result + FROM t1; + +--save_master_pos + +--connection slave +--let $slave_sql_errno= 1590 +--source include/wait_for_slave_sql_error_and_skip.inc + +--sync_with_master +SELECT COUNT(*) FROM t1; + +# Cleanup + +--connection master +SET GLOBAL binlog_stmt_cache_size= @save_binlog_stmt_cache_size; +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_cache_disk_full_row.test b/mysql-test/suite/rpl/t/rpl_binlog_cache_disk_full_row.test new file mode 100644 index 00000000000..2c5813bb53e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_cache_disk_full_row.test @@ -0,0 +1,61 @@ +--source include/have_binlog_format_row.inc +--source include/have_debug.inc +--source include/master-slave.inc + +--connection master +# Set minimal cache size so smaller transaction can trigger spill to disk. +SET @save_binlog_stmt_cache_size= @@GLOBAL.binlog_stmt_cache_size; +SET GLOBAL binlog_stmt_cache_size= 4096; + +CALL mtr.add_suppression('"No space left on device".*An incident event is written to binary log'); +CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(255)) ENGINE=MyISAM; + +FLUSH STATUS; +SHOW STATUS LIKE "binlog_stmt_cache%"; +INSERT INTO t1 VALUES (0, CONCAT("?", "-", REPEAT("x", 200))); +INSERT INTO t1 SELECT a+1, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+2, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+4, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+8, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+16, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+32, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+64, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +INSERT INTO t1 SELECT a+128, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +SHOW STATUS LIKE "binlog_stmt_cache%"; + +SET @old_dbug= @@SESSION.debug_dbug; +SET SESSION debug_dbug="+d,simulate_disk_full_at_flush_pending"; +--replace_regex /Error writing file '[^']+'/Error writing file ''/ +--error 3 +INSERT INTO t1 SELECT a+256, CONCAT(a, "-", REPEAT("x", 200)) FROM t1; +SET SESSION debug_dbug= @old_dbug; +SHOW STATUS LIKE "binlog_stmt_cache%"; +# The actual number of rows left after the disk full error may change as +# binlog event sizes are modified. So here we just test that we get partial +# update from the last INSERT..SELECT that gets disk full error. +SELECT IF(COUNT(*) > 256 AND COUNT(*) < 512, + "ok", + CONCAT("ERROR! Row count ", COUNT(*), " not as expected for partially executed query")) + AS check_result + FROM t1; + +# A random extra event that helped show the bug that a partial event +# group was binlogged. +ALTER TABLE t1 COMMENT ''; + +--save_master_pos + +--connection slave +--let $slave_sql_errno= 1590 +--source include/wait_for_slave_sql_error_and_skip.inc + +--sync_with_master +SELECT COUNT(*) FROM t1; + +# Cleanup + +--connection master +SET GLOBAL binlog_stmt_cache_size= @save_binlog_stmt_cache_size; +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/sql/log.cc b/sql/log.cc index e7292064747..59730c3205a 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2228,6 +2228,23 @@ bool MYSQL_BIN_LOG::check_write_error(THD *thd) } +/* + Check if there was an error while writing the statement cache. + If the cache content is corrupt due to an error, we should write an incident + event to the binlog rather than write corrupt data to it. +*/ +bool +MYSQL_BIN_LOG::check_cache_error(THD *thd, binlog_cache_data *cache_data) +{ + if (!cache_data) + return false; + if (check_write_error(thd)) + return true; + if (!cache_data->empty() && cache_data->cache_log.error) + return true; + return false; +} + /** @note How do we handle this (unlikely but legal) case: @@ -5874,7 +5891,7 @@ write_err: engines, data is written to table but writing to binary log failed. In these scenarios rollback is not possible. Hence report an incident. */ - if (mysql_bin_log.check_write_error(this) && cache_data && + if (mysql_bin_log.check_cache_error(this, cache_data) && lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) && table->current_lock == F_WRLCK) cache_data->set_incident(); @@ -6005,20 +6022,37 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd, /* Write pending event to the cache. */ +#ifndef DBUG_OFF + bool clear_dbug= false; +#endif DBUG_EXECUTE_IF("simulate_disk_full_at_flush_pending", - {DBUG_SET("+d,simulate_file_write_error");}); + { + if (my_b_tell(&cache_data->cache_log) > 10000) + { + DBUG_SET("+d,simulate_file_write_error"); + clear_dbug= true; + } + }); if (writer.write(pending)) { set_write_error(thd, is_transactional); - if (check_write_error(thd) && cache_data && + if (check_cache_error(thd, cache_data) && stmt_has_updated_non_trans_table(thd)) cache_data->set_incident(); delete pending; cache_data->set_pending(NULL); DBUG_EXECUTE_IF("simulate_disk_full_at_flush_pending", - {DBUG_SET("-d,simulate_file_write_error");}); + { + if (clear_dbug) + DBUG_SET("-d,simulate_file_write_error"); + }); DBUG_RETURN(1); } + DBUG_EXECUTE_IF("simulate_disk_full_at_flush_pending", + { + if (clear_dbug) + DBUG_SET("-d,simulate_file_write_error"); + }); delete pending; } @@ -6613,7 +6647,7 @@ err: if (unlikely(error)) { set_write_error(thd, is_trans_cache); - if (check_write_error(thd) && cache_data && + if (check_cache_error(thd, cache_data) && stmt_has_updated_non_trans_table(thd)) cache_data->set_incident(); } @@ -8337,6 +8371,20 @@ MYSQL_BIN_LOG::write_transaction_or_stmt(group_commit_entry *entry, binlog_cache_mngr *mngr= entry->cache_mngr; DBUG_ENTER("MYSQL_BIN_LOG::write_transaction_or_stmt"); + /* + An error in the trx_cache will truncate the cache to the last good + statement, it won't leave a lingering error. Assert that this holds. + */ + DBUG_ASSERT(!(entry->using_trx_cache && !mngr->trx_cache.empty() && + mngr->get_binlog_cache_log(TRUE)->error)); + /* + An error in the stmt_cache would be caught on the higher level and result + in an incident event being written over a (possibly corrupt) cache content. + Assert that this holds. + */ + DBUG_ASSERT(!(entry->using_stmt_cache && !mngr->stmt_cache.empty() && + mngr->get_binlog_cache_log(FALSE)->error)); + if (write_gtid_event(entry->thd, false, entry->using_trx_cache, commit_id)) DBUG_RETURN(ER_ERROR_ON_WRITE); diff --git a/sql/log.h b/sql/log.h index deeb5ca83ba..48169be0d68 100644 --- a/sql/log.h +++ b/sql/log.h @@ -815,6 +815,7 @@ public: int write_cache(THD *thd, IO_CACHE *cache); void set_write_error(THD *thd, bool is_transactional); bool check_write_error(THD *thd); + bool check_cache_error(THD *thd, binlog_cache_data *cache_data); void start_union_events(THD *thd, query_id_t query_id_param); void stop_union_events(THD *thd); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 8264286a022..cc4361b0472 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -253,6 +253,10 @@ public: */ void skip_data_till_eof() { +#ifndef EMBEDDED_LIBRARY + if (mysql_bin_log.is_open()) + cache.read_function= cache.real_read_function; +#endif while (GET != my_b_EOF) ; } diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index d9b93742195..0d2e61f7f59 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -4499,6 +4499,10 @@ int log_loaded_block(IO_CACHE* file, uchar *Buffer, size_t Count) /* buffer contains position where we started last read */ uchar* buffer= (uchar*) my_b_get_buffer_start(file); uint max_event_size= lf_info->thd->variables.max_allowed_packet; + int res; +#ifndef DBUG_OFF + bool did_dbug_inject= false; +#endif if (lf_info->thd->is_current_stmt_binlog_format_row()) goto ret; @@ -4506,6 +4510,19 @@ int log_loaded_block(IO_CACHE* file, uchar *Buffer, size_t Count) lf_info->last_pos_in_file >= my_b_get_pos_in_file(file)) goto ret; + DBUG_EXECUTE_IF("load_data_binlog_cache_error", + { + /* + Simulate "disk full" error in the middle of writing to + the binlog cache. + */ + if (lf_info->last_pos_in_file >= 2*4096) + { + DBUG_SET("+d,simulate_file_write_error"); + did_dbug_inject= true; + } + };); + for (block_len= (uint) (my_b_get_bytes_in_buffer(file)); block_len > 0; buffer += MY_MIN(block_len, max_event_size), block_len -= MY_MIN(block_len, max_event_size)) @@ -4517,7 +4534,10 @@ int log_loaded_block(IO_CACHE* file, uchar *Buffer, size_t Count) MY_MIN(block_len, max_event_size), lf_info->log_delayed); if (mysql_bin_log.write(&a)) - DBUG_RETURN(1); + { + res= 1; + goto err; + } } else { @@ -4526,12 +4546,20 @@ int log_loaded_block(IO_CACHE* file, uchar *Buffer, size_t Count) MY_MIN(block_len, max_event_size), lf_info->log_delayed); if (mysql_bin_log.write(&b)) - DBUG_RETURN(1); + { + res= 1; + goto err; + } lf_info->wrote_create_file= 1; } } ret: - int res= Buffer ? lf_info->real_read_function(file, Buffer, Count) : 0; + res= Buffer ? lf_info->real_read_function(file, Buffer, Count) : 0; +err: +#ifndef DBUG_OFF + if (did_dbug_inject) + DBUG_SET("-d,simulate_file_write_error"); +#endif DBUG_RETURN(res); } 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 156/477] 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 edabb8191bb19c1c95decf21b7b3143ae64b6eba Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 31 Oct 2023 13:34:17 +0100 Subject: [PATCH 157/477] galera: disabled tests cleanup --- mysql-test/suite/galera/disabled.def | 5 ++--- mysql-test/suite/galera_3nodes/disabled.def | 4 ++-- mysql-test/suite/galera_3nodes_sr/disabled.def | 2 +- mysql-test/suite/galera_sr/disabled.def | 3 +-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 348f8948bbd..2bf4db335f4 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -14,6 +14,5 @@ galera_as_slave_ctas : MDEV-28378 timeout galera_pc_recovery : MDEV-25199 cluster fails to start up 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 +galera_sequences : MDEV-32561 WSREP FSM failure: no such a transition REPLICATING -> COMMITTED +galera_shutdown_nonprim : MDEV-32635 galera_shutdown_nonprim: mysql_shutdown failed diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index 97e4a215b04..00aaeccfb8d 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -10,5 +10,5 @@ # ############################################################################## -galera_2_cluster : MDEV-29877 Galera test failure on galera_2_cluster -galera_gtid_2_cluster : MDEV-29877 Galera test failure on galera_2_cluster +galera_2_cluster : MDEV-32631 galera_2_cluster: before_rollback(): Assertion `0' failed +galera_gtid_2_cluster : MDEV-32633 galera_gtid_2_cluster: Assertion `thd->wsrep_next_trx_id() != (0x7fffffffffffffffLL * 2ULL + 1)' diff --git a/mysql-test/suite/galera_3nodes_sr/disabled.def b/mysql-test/suite/galera_3nodes_sr/disabled.def index df2277fb8ad..4472d960d9f 100644 --- a/mysql-test/suite/galera_3nodes_sr/disabled.def +++ b/mysql-test/suite/galera_3nodes_sr/disabled.def @@ -10,4 +10,4 @@ # ############################################################################## -galera_sr_kill_slave_after_apply_rollback2 : MDEV-29892 Galera test failure on galera_sr_kill_slave_after_apply_rollback2 \ No newline at end of file +galera_sr_kill_slave_after_apply_rollback2 : MDEV-29892 Galera test failure on galera_sr_kill_slave_after_apply_rollback2 diff --git a/mysql-test/suite/galera_sr/disabled.def b/mysql-test/suite/galera_sr/disabled.def index 9f2cf27d5e7..0371f0f589f 100644 --- a/mysql-test/suite/galera_sr/disabled.def +++ b/mysql-test/suite/galera_sr/disabled.def @@ -10,5 +10,4 @@ # ############################################################################## -galera_sr_cc_master : MDEV-29882 Galera test failure on galera_sr_cc_master - +GCF-1060 : MDEV-32160 GCF-1060 test failure due to wsrep MDL conflict From 9b049266ea9eebaa93e24f4ec522f9b239c85c61 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 31 Oct 2023 09:59:39 -0700 Subject: [PATCH 158/477] MDEV-32569 Failure when executing PS for query using IN subquery This patch corrects the fix for MDEV-32369. No Item_direct_ref_to_item objects should be allocated at the optimizer phase after permanent rewritings have been done. The patch also adds another test case for MDEV-32369 that uses MyISAM with more than one row. Approved by Rex Johnston --- mysql-test/main/ps_mem_leaks.result | 32 +++++++++++++++++++++++++++ mysql-test/main/ps_mem_leaks.test | 34 +++++++++++++++++++++++++++++ sql/item.cc | 3 ++- 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/ps_mem_leaks.result b/mysql-test/main/ps_mem_leaks.result index 8d66a025c1a..df4a55b9ed2 100644 --- a/mysql-test/main/ps_mem_leaks.result +++ b/mysql-test/main/ps_mem_leaks.result @@ -3,6 +3,20 @@ # CREATE TABLE t1 (a VARCHAR(10)) ENGINE=MYISAM; CREATE TABLE t2 (b VARCHAR(10) CHARACTER SET utf8) ENGINE=MYISAM; +INSERT INTO t1 VALUES ('b'), ('a'), ('c'); +INSERT INTO t2 VALUES ('c'), ('d'), ('b'); +PREPARE stmt FROM "SELECT t1.a FROM t1 WHERE t1.a IN (SELECT t2.b FROM t2)"; +EXECUTE stmt; +a +c +b +EXECUTE stmt; +a +c +b +DEALLOCATE PREPARE stmt; +DELETE FROM t1; +DELETE FROM t2; 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)"; @@ -14,3 +28,21 @@ a b DEALLOCATE PREPARE stmt; DROP TABLE t1, t2; +# +# MDEV-32569: Failure when executing PS for query using 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 STRAIGHT_JOIN 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; +# End of 10.4 tests diff --git a/mysql-test/main/ps_mem_leaks.test b/mysql-test/main/ps_mem_leaks.test index 2e357f9400c..169631146fe 100644 --- a/mysql-test/main/ps_mem_leaks.test +++ b/mysql-test/main/ps_mem_leaks.test @@ -13,6 +13,19 @@ CREATE TABLE t1 (a VARCHAR(10)) ENGINE=MYISAM; CREATE TABLE t2 (b VARCHAR(10) CHARACTER SET utf8) ENGINE=MYISAM; +INSERT INTO t1 VALUES ('b'), ('a'), ('c'); +INSERT INTO t2 VALUES ('c'), ('d'), ('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; + +DELETE FROM t1; +DELETE FROM t2; + INSERT INTO t1 VALUES ('b'); INSERT INTO t2 VALUES ('b'); @@ -25,3 +38,24 @@ DEALLOCATE PREPARE stmt; DROP TABLE t1, t2; +--echo # +--echo # MDEV-32569: Failure when executing PS for query using 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 STRAIGHT_JOIN t1.a FROM t1 WHERE t1.a IN (SELECT t2.b FROM t2)"; + +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; + +DROP TABLE t1,t2; + +--echo # End of 10.4 tests diff --git a/sql/item.cc b/sql/item.cc index 723552e6b35..259c4bf8f4d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2585,7 +2585,8 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll, if (conv->fix_fields_if_needed(thd, arg)) return TRUE; - if (!thd->stmt_arena->is_conventional()) + if (!thd->stmt_arena->is_conventional() && + thd->lex->current_select->first_cond_optimization) { Query_arena *arena, backup; arena= thd->activate_stmt_arena_if_needed(&backup); From 90e11488ac1eafaede6e921133059bd2e08da2be Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 1 Nov 2023 11:29:12 +0100 Subject: [PATCH 159/477] 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 4b65859af6fb827d202f4aded276524adebbaf77 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 1 Nov 2023 11:28:18 +0400 Subject: [PATCH 160/477] MDEV-32645 CAST(AS UNSIGNED) fails with --view-protocol Item_char_typecast::print() did not print the "binary" keyword in such cases: CAST('a' AS CHAR CHARACTER SET latin1 BINARY) This caused a difference in "mtr" vs "mtr --view-protocol" --- mysql-test/main/cast.result | 2 +- mysql-test/main/cast.test | 29 ++++++++++++----------------- sql/item_timefunc.cc | 7 +++++++ 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/mysql-test/main/cast.result b/mysql-test/main/cast.result index f154db15bcc..276decb73c8 100644 --- a/mysql-test/main/cast.result +++ b/mysql-test/main/cast.result @@ -814,7 +814,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, - `b` char(5) GENERATED ALWAYS AS (cast('a' as char(10) charset latin1) + `a`) VIRTUAL + `b` char(5) GENERATED ALWAYS AS (cast('a' as char(10) charset latin1 binary) + `a`) VIRTUAL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; select collation(cast("a" as char(10) binary)); diff --git a/mysql-test/main/cast.test b/mysql-test/main/cast.test index 478c59a58f7..ce4b1f6a574 100644 --- a/mysql-test/main/cast.test +++ b/mysql-test/main/cast.test @@ -158,10 +158,9 @@ 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 +--disable_service_connection select cast(_koi8r'ÔÅÓÔ' as char character set cp1251); ---enable_view_protocol +--enable_service_connection create table t1 select cast(_koi8r'ÔÅÓÔ' as char character set cp1251) as t; show create table t1; drop table t1; @@ -169,8 +168,7 @@ drop table t1; # # CAST to CHAR with/without length # -#enable after MDEV-32461 fix ---disable_view_protocol +--disable_service_connection select cast(_latin1'ab' AS char) as c1, cast(_latin1'a ' AS char) as c2, @@ -178,7 +176,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 +--enable_service_connection SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR create table t1 select @@ -239,15 +237,14 @@ 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 +--disable_service_connection # 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 +--enable_service_connection DROP TABLE t1; # @@ -349,12 +346,11 @@ 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 +--disable_service_connection 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 +--enable_service_connection # # Bug#29898: Item_date_typecast::val_int doesn't reset the null_value flag. @@ -484,14 +480,13 @@ drop table t1; # # CAST (... BINARY) # -#enable after MDEV-32461 fix ---disable_view_protocol +--disable_service_connection 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 +--enable_service_connection --echo # --echo # MDEV-11030 Assertion `precision > 0' failed in decimal_bin_size @@ -773,14 +768,14 @@ INSERT INTO t1 VALUES (-1.0); SELECT * FROM t1; DROP TABLE t1; -#enable after MDEV-32461 fix +#enable after MDEV-32645 is fixed --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; DROP TABLE t1; +--enable_view_protocol SELECT CAST(-1e308 AS UNSIGNED); CREATE TABLE t1 (a BIGINT UNSIGNED); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 04176fb7bfb..4fe5029b640 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2268,6 +2268,13 @@ void Item_char_typecast::print(String *str, enum_query_type query_type) { str->append(STRING_WITH_LEN(" charset ")); str->append(cast_cs->csname); + /* + Print the "binary" keyword in cases like: + CAST('str' AS CHAR CHARACTER SET latin1 BINARY) + */ + if ((cast_cs->state & MY_CS_BINSORT) && + Charset(cast_cs).can_have_collate_clause()) + str->append(STRING_WITH_LEN(" binary")); } str->append(')'); } From c341743e83c1213251a67b50f67f19ee9ad91545 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 1 Nov 2023 06:50:25 -0600 Subject: [PATCH 161/477] MDEV-32651: Lost Debug_sync signal in rpl_sql_thd_start_errno_cleared The test rpl.rpl_sql_thd_start_errno_cleared can lose a debug_sync signal, as there is a RESET immediately following a SIGNAL. When the signal is lost, the sql_thread is stuck in a WAIT_FOR clause until it times out, resulting in long test times (albeit still successful). This patch extends the test to ensure the debug_sync signal was received before issuing the RESET --- mysql-test/suite/rpl/r/rpl_sql_thd_start_errno_cleared.result | 1 + mysql-test/suite/rpl/t/rpl_sql_thd_start_errno_cleared.test | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_sql_thd_start_errno_cleared.result b/mysql-test/suite/rpl/r/rpl_sql_thd_start_errno_cleared.result index b14f7b01541..a3e98afa775 100644 --- a/mysql-test/suite/rpl/r/rpl_sql_thd_start_errno_cleared.result +++ b/mysql-test/suite/rpl/r/rpl_sql_thd_start_errno_cleared.result @@ -34,6 +34,7 @@ set debug_sync= "now wait_for sql_thread_run_lock_released"; # Validating that Last_SQL_Errno is cleared.. # ..success set debug_sync= "now signal sql_thread_continue"; +# Wait for debug_sync signal to have been received before issuing RESET set @@global.debug_dbug= @saved_dbug; set debug_sync= "RESET"; # Cleanup diff --git a/mysql-test/suite/rpl/t/rpl_sql_thd_start_errno_cleared.test b/mysql-test/suite/rpl/t/rpl_sql_thd_start_errno_cleared.test index f6dcfd91409..8b096902143 100644 --- a/mysql-test/suite/rpl/t/rpl_sql_thd_start_errno_cleared.test +++ b/mysql-test/suite/rpl/t/rpl_sql_thd_start_errno_cleared.test @@ -76,6 +76,10 @@ if ($last_error) set debug_sync= "now signal sql_thread_continue"; +--echo # Wait for debug_sync signal to have been received before issuing RESET +let $wait_condition= select count(*)=0 from information_schema.processlist where state like "debug sync point%"; +source include/wait_condition.inc; + set @@global.debug_dbug= @saved_dbug; set debug_sync= "RESET"; From 80ea3590ded1f3ad583610d0261cd55321e837a0 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 1 Nov 2023 09:10:17 -0600 Subject: [PATCH 162/477] MDEV-32655: rpl_semi_sync_slave_compressed_protocol.test assert_only_after is wrong The MTR test rpl.rpl_semi_sync_slave_compressed_protocol scans the log file to ensure there is no magic number error. It attempts to only scan the log files of the current test; however, the variable which controls this, , is initialized incorrectly, and it thereby scans the entire log file, which includes output from prior tests. This causes it to fail if a test which expects this error runs previously on the same worker. This patch fixes the assert_only_after so the test only scans through its own log contents. --- .../suite/rpl/t/rpl_semi_sync_slave_compressed_protocol.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol.test b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol.test index bc05bec2a96..644e6517131 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol.test @@ -40,7 +40,7 @@ DROP TABLE t1; --let $assert_select=Read semi-sync reply magic number error --let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err --let $assert_count= 0 ---let $assert_only_after = CURRENT_TEST:rpl.rpl_semi_sync_slave_compressed_protocol.test +--let $assert_only_after = CURRENT_TEST: rpl.rpl_semi_sync_slave_compressed_protocol --source include/assert_grep.inc --connection master From 9e321a44ee9abb6fbbbbe4f50ca69bfce61398d8 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 27 Oct 2023 08:53:30 -0700 Subject: [PATCH 163/477] MDEV-28615 Crash caused by multi-table UPDATE over derived with hanging CTE This bug affected only multi-table update statements and in very rare cases: one of the tables used at the top level of the statement must be a derived table containg a row construct with a subquery including hanging CTE. Before this patch was applied the function prepare_unreferenced() of the class With_element when invoked for the the hangin CTE did not properly restored the value of thd->lex->context_analysis_only. As a result it became 0 after the call of this function. For a query affected by the bug this function is called when JOIN::prepare() is called for the subquery with a hanging CTE. This happens when Item_row::fix_fields() calls fix_fields() for the subquery. Setting the value of thd->lex->context_analysis_only forces the caller function Item_row::fix_fields() to invoke the virtual method is_null() for the subquery that leads to execution of it. It causes an assertion failure because the call of Item_row::fix_fields() happens during the invocation of Multiupdate_prelocking_strategy::handle_end() that calls the function mysql_derived_prepare() for the derived table used by the UPDATE at the time when proper locks for the statement tables has not been acquired yet. With this patch the value of thd->lex->context_analysis_only is restored to CONTEXT_ANALYSIS_ONLY_DERIVED that is set in the function mysql_multi_update_prepare(). Approved by Oleksandr Byelkin --- mysql-test/main/cte_nonrecursive.result | 25 +++++++++++++++++++++ mysql-test/main/cte_nonrecursive.test | 29 +++++++++++++++++++++++-- sql/sql_cte.cc | 4 ++-- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result index e5ea67aa37f..e86c101686c 100644 --- a/mysql-test/main/cte_nonrecursive.result +++ b/mysql-test/main/cte_nonrecursive.result @@ -2599,4 +2599,29 @@ src path dest distance population E FD D 251 80000 drop procedure sp; drop table distances, city_population; +# +# MDEV-28615: Multi-table UPDATE over derived table containing +# row that uses subquery with hanging CTE +# +CREATE TABLE t1 (a int) ENGINE=MYISAM; +INSERT INTO t1 VALUES (3), (7), (1); +UPDATE +(SELECT (5, (WITH cte AS (SELECT 1) SELECT a FROM t1))) dt +JOIN t1 t +ON t.a=dt.a +SET t.a = 1; +ERROR 21000: Operand should contain 1 column(s) +UPDATE +(SELECT a FROM t1 +WHERE (5, (WITH cte AS (SELECT 1) SELECT a FROM t1 WHERE a > 4)) <= +(5,a)) dt +JOIN t1 t +ON t.a=dt.a +SET t.a = 1; +SELECT * FROM t1; +a +3 +1 +1 +DROP TABLE t1; # End of 10.4 tests diff --git a/mysql-test/main/cte_nonrecursive.test b/mysql-test/main/cte_nonrecursive.test index 2919415a0a7..a666ed3a25f 100644 --- a/mysql-test/main/cte_nonrecursive.test +++ b/mysql-test/main/cte_nonrecursive.test @@ -1784,8 +1784,6 @@ with data as (select 1 as id) select id into @myid from data; set sql_mode= @save_sql_mode; - - --echo # --echo # MDEV-31995 CTE column name specification inconsistency --echo # @@ -1942,4 +1940,31 @@ drop procedure sp; drop table distances, city_population; +--echo # +--echo # MDEV-28615: Multi-table UPDATE over derived table containing +--echo # row that uses subquery with hanging CTE +--echo # + +CREATE TABLE t1 (a int) ENGINE=MYISAM; +INSERT INTO t1 VALUES (3), (7), (1); + +--error ER_OPERAND_COLUMNS +UPDATE + (SELECT (5, (WITH cte AS (SELECT 1) SELECT a FROM t1))) dt + JOIN t1 t + ON t.a=dt.a +SET t.a = 1; + +UPDATE + (SELECT a FROM t1 + WHERE (5, (WITH cte AS (SELECT 1) SELECT a FROM t1 WHERE a > 4)) <= + (5,a)) dt + JOIN t1 t + ON t.a=dt.a +SET t.a = 1; + +SELECT * FROM t1; + +DROP TABLE t1; + --echo # End of 10.4 tests diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index da8eb4b79d7..0e422b30216 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -1241,14 +1241,14 @@ bool With_element::prepare_unreferenced(THD *thd) sl= sl->next_select()) sl->context.outer_context= 0; + uint8 save_context_analysys_only= thd->lex->context_analysis_only; thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED; if (!spec->prepared && (spec->prepare(spec->derived, 0, 0) || rename_columns_of_derived_unit(thd, spec) || check_duplicate_names(thd, first_sl->item_list, 1))) rc= true; - - thd->lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED; + thd->lex->context_analysis_only= save_context_analysys_only; return rc; } From d5aff2d551b0d91ca3598af192d900639300978a Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 2 Nov 2023 07:07:55 +0400 Subject: [PATCH 164/477] MDEV-32465 dyncol changes under view protocol Dyncol functions like column_create() encode the current character set inside the value. So they cannot be used with --view-protocol. This patch changes only --disable_view_protocol to --disable_service_connection. --- mysql-test/main/dyncol.test | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/mysql-test/main/dyncol.test b/mysql-test/main/dyncol.test index 70f4d0f0c6d..630ed122347 100644 --- a/mysql-test/main/dyncol.test +++ b/mysql-test/main/dyncol.test @@ -670,18 +670,16 @@ 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 +--disable_service_connection select hex(column_create("адын", 1212)); ---enable_view_protocol +--enable_service_connection 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 +--disable_service_connection select hex(column_create("1212", 2, "адын", 1, 3, 3)); ---enable_view_protocol +--enable_service_connection set names latin1; --echo # fetching column test (names) @@ -708,15 +706,14 @@ select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "4") as ex; set names latin1; --echo # column changing test (names) -#enable after MDEV-32465 fix ---disable_view_protocol +--disable_service_connection 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 +--enable_service_connection 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; From df93b4f259515a5603e05b85d0acd45f0afd62c9 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 1 Nov 2023 11:56:24 +0100 Subject: [PATCH 165/477] Fix MDEV-30820 problem found by Monty --- mysql-test/main/log_slow_debug.result | 7 +++++-- mysql-test/main/log_slow_debug.test | 11 ++++++++--- sql/sql_class.cc | 2 -- sql/sql_class.h | 6 +++++- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/mysql-test/main/log_slow_debug.result b/mysql-test/main/log_slow_debug.result index 88019d87322..64397fbe3f5 100644 --- a/mysql-test/main/log_slow_debug.result +++ b/mysql-test/main/log_slow_debug.result @@ -231,15 +231,18 @@ SET @old_dbug= @@GLOBAL.debug_dbug; SET GLOBAL log_output= "TABLE"; SET GLOBAL slow_query_log= ON; SET SESSION long_query_time= 0; -SET GLOBAL debug_dbug="+d,debug_huge_number_of_examined_rows"; +SET debug_dbug="+d,debug_huge_number_of_examined_rows"; SELECT * FROM tab_MDEV_30820 ORDER BY 1; ID A 1 0 2 0 -SET GLOBAL debug_dbug=@old_dbug; +SET debug_dbug=@old_dbug; SET @@long_query_time= @old_long_query_time; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; +SELECT rows_examined, sql_text from mysql.slow_log where sql_text like "SELECT%FROM tab_MDEV_30820%"; +rows_examined sql_text +18446744073708551615 SELECT * FROM tab_MDEV_30820 ORDER BY 1 drop table tab_MDEV_30820; # # End of 10.4 test diff --git a/mysql-test/main/log_slow_debug.test b/mysql-test/main/log_slow_debug.test index 5c8385f2fc9..e93c4a9675a 100644 --- a/mysql-test/main/log_slow_debug.test +++ b/mysql-test/main/log_slow_debug.test @@ -104,16 +104,21 @@ SET GLOBAL log_output= "TABLE"; SET GLOBAL slow_query_log= ON; SET SESSION long_query_time= 0; -SET GLOBAL debug_dbug="+d,debug_huge_number_of_examined_rows"; +SET debug_dbug="+d,debug_huge_number_of_examined_rows"; +--disable_ps_protocol +--disable_view_protocol SELECT * FROM tab_MDEV_30820 ORDER BY 1; -SET GLOBAL debug_dbug=@old_dbug; - +--enable_view_protocol +--enable_ps_protocol +SET debug_dbug=@old_dbug; ## Reset to initial values SET @@long_query_time= @old_long_query_time; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; +SELECT rows_examined, sql_text from mysql.slow_log where sql_text like "SELECT%FROM tab_MDEV_30820%"; + drop table tab_MDEV_30820; --echo # diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 479ff0e68d0..93f42a462e5 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -5682,8 +5682,6 @@ void THD::set_examined_row_count(ha_rows count) void THD::inc_sent_row_count(ha_rows count) { m_sent_row_count+= count; - DBUG_EXECUTE_IF("debug_huge_number_of_examined_rows", - m_examined_row_count= (ULONGLONG_MAX - 1000000);); MYSQL_SET_STATEMENT_ROWS_SENT(m_statement_psi, m_sent_row_count); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 3e95b614756..c7f36ce3d8c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3013,7 +3013,11 @@ public: { return m_sent_row_count; } ha_rows get_examined_row_count() const - { return m_examined_row_count; } + { + DBUG_EXECUTE_IF("debug_huge_number_of_examined_rows", + return (ULONGLONG_MAX - 1000000);); + return m_examined_row_count; + } ulonglong get_affected_rows() const { return affected_rows; } From 855356ca6df6cf3c8c8d2feafb41c10824c33a6d Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Tue, 10 Oct 2023 13:29:04 +0700 Subject: [PATCH 166/477] MDEV-32382 FederatedX error on pushdown of statements having CTE Pushing down statements to FederatedX engine is implemented by printing either SELECT_LEX or SELECT_LEX_UNIT into a string and sending that string to the engine. In the case of pushing down a single SELECT having a CTE (WITH clause) there was a problem, because normally single SELECTs were printed using SELECT_LEX::print(). But CTEs are stored in the upper unit of the SELECT_LEX - SELECT_LEX_UNIT, so they were not unfolded in the string produced. The solution is to invoke SELECT_LEX_UNIT::print() when pushing down single SELECT statements (but not those which are parts of units), so the possible CTEs are unfolded and printed. Reviewed by Sergei Petrunia (sergey@mariadb.com) --- .../federatedx_create_handlers.result | 105 ++++++++++++++++++ .../federated/federatedx_create_handlers.test | 49 ++++++++ sql/select_handler.cc | 15 +++ sql/select_handler.h | 12 +- sql/sql_select.cc | 9 +- storage/federatedx/federatedx_pushdown.cc | 46 ++++---- storage/federatedx/federatedx_pushdown.h | 7 +- 7 files changed, 218 insertions(+), 25 deletions(-) diff --git a/mysql-test/suite/federated/federatedx_create_handlers.result b/mysql-test/suite/federated/federatedx_create_handlers.result index eaf9bda6f38..231862f76ad 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.result +++ b/mysql-test/suite/federated/federatedx_create_handlers.result @@ -1140,6 +1140,111 @@ t3_myisam2 t3_myisam3 SELECT * FROM federated.t1 UNION SELECT * FROM t3 ORDER BY 2; ERROR 42S22: Unknown column '2' in 'order clause' +# +# MDEV-32382 FederatedX error on pushdown of statement having CTE +# +# Single SELECT with CTE +WITH cte AS (SELECT * FROM federated.t1) +SELECT * FROM cte; +a +bcd +abc +cde +explain extended WITH cte AS (SELECT * FROM federated.t1) +SELECT * FROM cte; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 with cte as (/* select#2 */ select `federated`.`t1`.`a` AS `a` from `federated`.`t1`)/* select#1 */ select `cte`.`a` AS `a` from `cte` +# Pushdown of a UNION having CTE's +WITH cte AS (SELECT * FROM federated.t1), +cte2 AS (SELECT * FROM federated.t2) +SELECT * FROM cte +UNION +SELECT * FROM cte2; +a +abc +bcd +cde +def +efg +explain extended WITH cte AS (SELECT * FROM federated.t1), +cte2 AS (SELECT * FROM federated.t2) +SELECT * FROM cte +UNION +SELECT * FROM cte2; +id select_type table type possible_keys key key_len ref rows filtered Extra +NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 with cte as (/* select#2 */ select `federated`.`t1`.`a` AS `a` from `federated`.`t1`), cte2 as (/* select#3 */ select `federated`.`t2`.`a` AS `a` from `federated`.`t2`)/* select#1 */ select `cte`.`a` AS `a` from `cte` union /* select#4 */ select `cte2`.`a` AS `a` from `cte2` +# Partial pushdown is not allowed for unions with CTE's, however a CTE +# may be pushed down a derived table +WITH cte AS (SELECT * FROM federated.t1) +SELECT * FROM cte +UNION ALL +SELECT * FROM t3; +a +abc +bcd +cde +t3_myisam1 +t3_myisam2 +t3_myisam3 +explain extended WITH cte AS (SELECT * FROM federated.t1) +SELECT * FROM cte +UNION ALL +SELECT * FROM t3; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 +2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL +3 UNION t3 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 with cte as (/* select#2 */ select `federated`.`t1`.`a` AS `a` from `federated`.`t1`)/* select#1 */ select `cte`.`a` AS `a` from `cte` union all /* select#3 */ select `federated`.`t3`.`a` AS `a` from `federated`.`t3` +WITH cte AS (SELECT * FROM federated.t1 UNION SELECT * FROM t3) +SELECT * FROM cte; +a +abc +bcd +cde +t3_myisam1 +t3_myisam2 +t3_myisam3 +explain extended WITH cte AS (SELECT * FROM federated.t1 UNION SELECT * FROM t3) +SELECT * FROM cte; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 6 100.00 +2 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 +3 UNION t3 ALL NULL NULL NULL NULL 3 100.00 +NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 with cte as (/* select#2 */ select `federated`.`t1`.`a` AS `a` from `federated`.`t1` union /* select#3 */ select `federated`.`t3`.`a` AS `a` from `federated`.`t3`)/* select#1 */ select `cte`.`a` AS `a` from `cte` +# Two CTE's where one CTE refers to another +WITH cte AS (SELECT * FROM federated.t1), +cte2 AS (SELECT * FROM t3 +WHERE t3.a NOT IN (SELECT * FROM cte)) +SELECT * FROM cte JOIN cte2; +a a +abc t3_myisam1 +abc t3_myisam2 +abc t3_myisam3 +bcd t3_myisam1 +bcd t3_myisam2 +bcd t3_myisam3 +cde t3_myisam1 +cde t3_myisam2 +cde t3_myisam3 +explain extended WITH cte AS (SELECT * FROM federated.t1), +cte2 AS (SELECT * FROM t3 +WHERE t3.a NOT IN (SELECT * FROM cte)) +SELECT * FROM cte JOIN cte2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 +1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) +5 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL +4 MATERIALIZED ALL NULL NULL NULL NULL 3 100.00 +2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 with cte as (/* select#2 */ select `federated`.`t1`.`a` AS `a` from `federated`.`t1`), cte2 as (/* select#3 */ select `federated`.`t3`.`a` AS `a` from `federated`.`t3` where !<`federated`.`t3`.`a`>((`federated`.`t3`.`a`,`federated`.`t3`.`a` in ( (/* select#4 */ select `cte`.`a` from `cte` ), (`federated`.`t3`.`a` in on distinct_key where `federated`.`t3`.`a` = ``.`a`)))))/* select#1 */ select `cte`.`a` AS `a`,`federated`.`t3`.`a` AS `a` from `cte` join `federated`.`t3` where !<`federated`.`t3`.`a`>((`federated`.`t3`.`a`,`federated`.`t3`.`a` in ( (/* select#4 */ select `cte`.`a` from `cte` ), (`federated`.`t3`.`a` in on distinct_key where `federated`.`t3`.`a` = ``.`a`)))) connection master; DROP TABLES federated.t1, federated.t2, t3, t4, t5, t6, federated.t11, federated.t12, federated.t13, federated.t14; diff --git a/mysql-test/suite/federated/federatedx_create_handlers.test b/mysql-test/suite/federated/federatedx_create_handlers.test index f0cf3662023..e65972635e0 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.test +++ b/mysql-test/suite/federated/federatedx_create_handlers.test @@ -740,6 +740,55 @@ SELECT * FROM federated.t1 UNION SELECT * FROM t3 ORDER BY a; SELECT * FROM federated.t1 UNION SELECT * FROM t3 ORDER BY 2; +--echo # +--echo # MDEV-32382 FederatedX error on pushdown of statement having CTE +--echo # + +--echo # Single SELECT with CTE +let $query= WITH cte AS (SELECT * FROM federated.t1) + SELECT * FROM cte; +eval $query; +eval explain extended $query; + +--echo # Pushdown of a UNION having CTE's +let $query= WITH cte AS (SELECT * FROM federated.t1), + cte2 AS (SELECT * FROM federated.t2) + SELECT * FROM cte + UNION + SELECT * FROM cte2; +--sorted_result +eval $query; +eval explain extended $query; + +# CREATE TABLE t3 (a int); +# INSERT INTO t3 VALUES (101),(102),(103); + +--echo # Partial pushdown is not allowed for unions with CTE's, however a CTE +--echo # may be pushed down a derived table +let $query= WITH cte AS (SELECT * FROM federated.t1) + SELECT * FROM cte + UNION ALL + SELECT * FROM t3; +--sorted_result +eval $query; +eval explain extended $query; + +let $query= WITH cte AS (SELECT * FROM federated.t1 UNION SELECT * FROM t3) + SELECT * FROM cte; +--sorted_result +eval $query; +eval explain extended $query; + +--echo # Two CTE's where one CTE refers to another +let $query= WITH cte AS (SELECT * FROM federated.t1), + cte2 AS (SELECT * FROM t3 + WHERE t3.a NOT IN (SELECT * FROM cte)) + SELECT * FROM cte JOIN cte2; +--sorted_result +eval $query; +eval explain extended $query; + + # Cleanup connection master; DROP TABLES federated.t1, federated.t2, t3, t4, t5, t6, federated.t11, diff --git a/sql/select_handler.cc b/sql/select_handler.cc index e80e2548d5b..ab2a6850a6e 100644 --- a/sql/select_handler.cc +++ b/sql/select_handler.cc @@ -200,3 +200,18 @@ void select_handler::print_error(int error, myf errflag) { my_error(ER_GET_ERRNO, MYF(0), error, hton_name(ht)->str); } + +select_pushdown_type select_handler::get_pushdown_type() +{ + /* + In the case of single SELECT select_lex is initialized and lex_unit==NULL, + in the case of whole UNIT select_lex == NULL and lex_unit is initialized, + in the case of partial pushdown both select_lex and lex_unit + are initialized + */ + if(!lex_unit) + return select_pushdown_type::SINGLE_SELECT; + + return select_lex ? select_pushdown_type::PART_OF_UNIT : + select_pushdown_type::WHOLE_UNIT; +} diff --git a/sql/select_handler.h b/sql/select_handler.h index ea59eab4250..207af43f56c 100644 --- a/sql/select_handler.h +++ b/sql/select_handler.h @@ -20,6 +20,12 @@ #include "mariadb.h" #include "sql_priv.h" +enum class select_pushdown_type { + SINGLE_SELECT, + PART_OF_UNIT, + WHOLE_UNIT +}; + /** @class select_handler @@ -50,7 +56,7 @@ class select_handler virtual bool prepare(); /* - Select_handler processes one of + Select_handler processes these cases: - single SELECT - whole unit (multiple SELECTs combined with UNION/EXCEPT/INTERSECT) - single SELECT that is part of a unit (partial pushdown) @@ -60,7 +66,7 @@ class select_handler in the case of partial pushdown both select_lex and lex_unit are initialized */ - SELECT_LEX *select_lex; // Single select to be executed + SELECT_LEX *select_lex; // Single select/part of a unit to be executed SELECT_LEX_UNIT *lex_unit; // Unit to be executed /* @@ -99,6 +105,8 @@ protected: TABLE *create_tmp_table(THD *thd); + select_pushdown_type get_pushdown_type(); + THD *thd; handlerton *ht; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 05b788b6e1d..7414a8948a2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5054,8 +5054,15 @@ select_handler *find_select_handler_inner(THD *thd, SELECT_LEX *select_lex, SELECT_LEX_UNIT *select_lex_unit) { - if (select_lex->master_unit()->outer_select()) + if (select_lex->master_unit()->outer_select() || + (select_lex_unit && select_lex->master_unit()->with_clause)) + { + /* + Pushdown is not supported neither for non-top-level SELECTs nor for parts + of SELECT_LEX_UNITs that have CTEs (SELECT_LEX_UNIT::with_clause) + */ return 0; + } TABLE_LIST *tbl= nullptr; // For SQLCOM_INSERT_SELECT the server takes TABLE_LIST diff --git a/storage/federatedx/federatedx_pushdown.cc b/storage/federatedx/federatedx_pushdown.cc index 7615e61ae09..c4d77a73984 100644 --- a/storage/federatedx/federatedx_pushdown.cc +++ b/storage/federatedx/federatedx_pushdown.cc @@ -276,18 +276,6 @@ federatedx_handler_base::federatedx_handler_base(THD *thd_arg, TABLE *tbl_arg) query_table(tbl_arg) {} -ha_federatedx_select_handler::ha_federatedx_select_handler( - THD *thd, SELECT_LEX *select_lex, TABLE *tbl) - : select_handler(thd, federatedx_hton, select_lex), - federatedx_handler_base(thd, tbl) -{ - query.length(0); - select_lex->print(thd, &query, - enum_query_type(QT_VIEW_INTERNAL | - QT_ITEM_ORIGINAL_FUNC_NULLIF | - QT_PARSABLE)); -} - ha_federatedx_select_handler::~ha_federatedx_select_handler() = default; ha_federatedx_select_handler::ha_federatedx_select_handler( @@ -296,10 +284,7 @@ ha_federatedx_select_handler::ha_federatedx_select_handler( federatedx_handler_base(thd, tbl) { query.length(0); - lex_unit->print(&query, - enum_query_type(QT_VIEW_INTERNAL | QT_SELECT_ONLY | - QT_ITEM_ORIGINAL_FUNC_NULLIF | - QT_PARSABLE)); + lex_unit->print(&query, PRINT_QUERY_TYPE); } ha_federatedx_select_handler::ha_federatedx_select_handler( @@ -308,10 +293,31 @@ ha_federatedx_select_handler::ha_federatedx_select_handler( federatedx_handler_base(thd, tbl) { query.length(0); - select_lex->print(thd, &query, - enum_query_type(QT_VIEW_INTERNAL | QT_SELECT_ONLY | - QT_ITEM_ORIGINAL_FUNC_NULLIF | - QT_PARSABLE)); + if (get_pushdown_type() == select_pushdown_type::SINGLE_SELECT) + { + /* + Must use SELECT_LEX_UNIT::print() instead of SELECT_LEX::print() here + to print possible CTEs which are stored at SELECT_LEX_UNIT::with_clause + */ + select_lex->master_unit()->print(&query, PRINT_QUERY_TYPE); + } + else if (get_pushdown_type() == select_pushdown_type::PART_OF_UNIT) + { + /* + CTEs are not supported for partial select pushdown so use + SELECT_LEX::print() here + */ + select_lex->print(thd, &query, PRINT_QUERY_TYPE); + } + else + { + /* + Other select_pushdown_types are not allowed in this constructor. + The case of select_pushdown_type::WHOLE_UNIT is handled at another + overload of the constuctor + */ + DBUG_ASSERT(0); + } } int federatedx_handler_base::init_scan_() diff --git a/storage/federatedx/federatedx_pushdown.h b/storage/federatedx/federatedx_pushdown.h index c2ce80b0708..1d5bdab1378 100644 --- a/storage/federatedx/federatedx_pushdown.h +++ b/storage/federatedx/federatedx_pushdown.h @@ -62,8 +62,6 @@ public: class ha_federatedx_select_handler: public select_handler, public federatedx_handler_base { public: - ha_federatedx_select_handler(THD *thd_arg, SELECT_LEX *sel_lex, - TABLE *tbl); ha_federatedx_select_handler(THD *thd_arg, SELECT_LEX_UNIT *sel_unit, TABLE *tbl); ha_federatedx_select_handler(THD *thd_arg, SELECT_LEX *sel_lex, @@ -72,4 +70,9 @@ public: int init_scan() { return federatedx_handler_base::init_scan_(); } int next_row() { return federatedx_handler_base::next_row_(table); } int end_scan(); + +private: + static constexpr auto PRINT_QUERY_TYPE= + enum_query_type(QT_VIEW_INTERNAL | QT_SELECT_ONLY | + QT_ITEM_ORIGINAL_FUNC_NULLIF | QT_PARSABLE); }; From f9d2fd1f3fc2799158d950f827b1c6959b8a62f3 Mon Sep 17 00:00:00 2001 From: HaoZhang Date: Thu, 2 Nov 2023 11:33:48 +0800 Subject: [PATCH 167/477] typo fixed. HAVE_mi_uint8korr --- include/byte_order_generic_x86_64.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/byte_order_generic_x86_64.h b/include/byte_order_generic_x86_64.h index a25e6a2ab08..305ba2b430e 100644 --- a/include/byte_order_generic_x86_64.h +++ b/include/byte_order_generic_x86_64.h @@ -83,7 +83,7 @@ static inline ulonglong uint6korr(const void *p) #define HAVE_mi_uint5korr #define HAVE_mi_uint6korr #define HAVE_mi_uint7korr -#define HAVE_mi_uint78orr +#define HAVE_mi_uint8korr /* Read numbers stored in high-bytes-first order */ From b4de67da451b580989843fd63c0d248f7b8b3a53 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Thu, 2 Nov 2023 13:23:33 +0530 Subject: [PATCH 168/477] MDEV-32638 MariaDB crashes with foreign_key_checks=0 when changing a column and adding a foreign key at the same time Problem: ======= - InnoDB fails to find the foreign key index for the newly added foreign key relation. This is caused by commit 5f09b53bdb4e973e7c7ec2c53a24c98321223f98 (MDEV-31086). FIX: === In check_col_is_in_fk_indexes(), while iterating through the newly added 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 | 1 + 3 files changed, 28 insertions(+) diff --git a/mysql-test/suite/innodb/r/fk_col_alter.result b/mysql-test/suite/innodb/r/fk_col_alter.result index d58f68977ef..b0621ebff74 100644 --- a/mysql-test/suite/innodb/r/fk_col_alter.result +++ b/mysql-test/suite/innodb/r/fk_col_alter.result @@ -118,4 +118,17 @@ ALTER TABLE t2 DROP INDEX idx; ALTER TABLE t2 MODIFY f2 VARCHAR(1023); SET SESSION FOREIGN_KEY_CHECKS = ON; DROP TABLE t2, t1; +# +# MDEV-32638 MariaDB crashes with foreign_key_checks=0 +# when changing a column and adding a foreign +# key at the same time +# +CREATE TABLE t1(f1 VARCHAR(2) NOT NULL, PRIMARY KEY(f1))ENGINE=InnoDB; +CREATE TABLE t2(f1 INT NOT NULL PRIMARY KEY, +f2 VARCHAR(10) NOT NULL DEFAULT '')ENGINE=InnoDB; +SET SESSION FOREIGN_KEY_CHECKS = OFF; +ALTER TABLE t2 CHANGE COLUMN f2 f3 VARCHAR(20) NOT NULL, +ADD CONSTRAINT t2_fk FOREIGN KEY(f3) REFERENCES t1(f1); +DROP TABLE t2, t1; +SET SESSION FOREIGN_KEY_CHECKS = ON; # 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 6788c825b0f..1f3bf1ae5a1 100644 --- a/mysql-test/suite/innodb/t/fk_col_alter.test +++ b/mysql-test/suite/innodb/t/fk_col_alter.test @@ -153,4 +153,18 @@ ALTER TABLE t2 DROP INDEX idx; ALTER TABLE t2 MODIFY f2 VARCHAR(1023); SET SESSION FOREIGN_KEY_CHECKS = ON; DROP TABLE t2, t1; + +--echo # +--echo # MDEV-32638 MariaDB crashes with foreign_key_checks=0 +--echo # when changing a column and adding a foreign +--echo # key at the same time +--echo # +CREATE TABLE t1(f1 VARCHAR(2) NOT NULL, PRIMARY KEY(f1))ENGINE=InnoDB; +CREATE TABLE t2(f1 INT NOT NULL PRIMARY KEY, + f2 VARCHAR(10) NOT NULL DEFAULT '')ENGINE=InnoDB; +SET SESSION FOREIGN_KEY_CHECKS = OFF; +ALTER TABLE t2 CHANGE COLUMN f2 f3 VARCHAR(20) NOT NULL, + ADD CONSTRAINT t2_fk FOREIGN KEY(f3) REFERENCES t1(f1); +DROP TABLE t2, t1; +SET SESSION FOREIGN_KEY_CHECKS = ON; --echo # End of 10.4 tests diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index d3196c47ca2..6b2356ff6b3 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -7695,6 +7695,7 @@ bool check_col_is_in_fk_indexes( for (const auto &a : add_fk) { + if (!a->foreign_index) continue; for (ulint i= 0; i < a->n_fields; i++) { if (a->foreign_index->fields[i].col == col) From 5c5123dfe0ae0d162f135a43095dade008972b97 Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Tue, 4 Jul 2023 14:39:57 +0530 Subject: [PATCH 169/477] MDEV-31411: JSON_ARRAY_INTERSECT/JSON_OBJECT_FILTER_KEYS should fetch data from a table similar to other JSON functions Analysis: Since we are fetching values for every row ( because we are running SELECT for all rows of a table ), correct value can be only obtained at the time of calling val_int() because it is called to get value for each row. Fix: Set up hash for each row instead of doing it during fixing fields. --- mysql-test/main/func_json.result | 14 +++++++ mysql-test/main/func_json.test | 20 +++++++++ mysql-test/main/temp.test | 7 ++++ sql/item_jsonfunc.cc | 71 ++++++++++++++++++++++---------- sql/item_jsonfunc.h | 4 +- 5 files changed, 93 insertions(+), 23 deletions(-) create mode 100644 mysql-test/main/temp.test diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index ab35822a6ce..4d0bb7b840c 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -5126,5 +5126,19 @@ SELECT JSON_OBJECT_TO_ARRAY(@arr1); JSON_OBJECT_TO_ARRAY(@arr1) NULL # +# MDEV-31411: JSON_ARRAY_INTERSECT/JSON_OBJECT_FILTER_KEYS should fetch +# data from a table similar to other JSON functions +# +CREATE TABLE t1 ( +c1 longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(c1)), +c2 longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`c2`)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; +INSERT INTO t1 VALUES('[1,2,3]', '[2, 3, 4]'), ('[2 ,3, 4]', '[4, 5, 6]'); +SELECT JSON_ARRAY_INTERSECT(c1, c2) FROM t1; +JSON_ARRAY_INTERSECT(c1, c2) +[2, 3] +[4] +DROP TABLE t1; +# # End of 11.2 Test # diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index 494a681243a..8f672fb8725 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -1,3 +1,5 @@ +--source include/have_innodb.inc + select json_valid('[1, 2]'); select json_valid('"string"}'); select json_valid('{"key1":1, "key2":[2,3]}'); @@ -3947,6 +3949,24 @@ SELECT JSON_OBJECT_TO_ARRAY(@obj1); SET @arr1= '[1, 2, 3]'; SELECT JSON_OBJECT_TO_ARRAY(@arr1); + +--echo # +--echo # MDEV-31411: JSON_ARRAY_INTERSECT/JSON_OBJECT_FILTER_KEYS should fetch +--echo # data from a table similar to other JSON functions +--echo # + +CREATE TABLE t1 ( + c1 longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(c1)), + c2 longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`c2`)) + ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; + +INSERT INTO t1 VALUES('[1,2,3]', '[2, 3, 4]'), ('[2 ,3, 4]', '[4, 5, 6]'); + +SELECT JSON_ARRAY_INTERSECT(c1, c2) FROM t1; + +DROP TABLE t1; + + --echo # --echo # End of 11.2 Test --echo # diff --git a/mysql-test/main/temp.test b/mysql-test/main/temp.test new file mode 100644 index 00000000000..7e29df49b71 --- /dev/null +++ b/mysql-test/main/temp.test @@ -0,0 +1,7 @@ +CREATE TABLE t1 ( c1 longtext , c2 longtext ); + +INSERT INTO t1 VALUES('[1,2,3]', '[2, 3, 4]'), ('[1,2,3]', '[2, 3, 4]'); + +SELECT JSON_ARRAY_INTERSECT(c1, c2) FROM t1; + +DROP TABLE t1; diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 508ea9f644e..7a8a62034af 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -2081,7 +2081,7 @@ return_null: String *Item_func_json_array_insert::val_str(String *str) { json_engine_t je; - String *js= args[0]->val_json(&tmp_js); + String *js= args[0]->val_str(&tmp_js); uint n_arg, n_path; THD *thd= current_thd; @@ -5155,8 +5155,21 @@ String* Item_func_json_array_intersect::val_str(String *str) { DBUG_ASSERT(fixed()); - json_engine_t je2, res_je; - String *js2= args[1]->val_json(&tmp_js2); + json_engine_t je2, res_je, je1; + String *js2= args[1]->val_json(&tmp_js2), *js1= args[0]->val_json(&tmp_js1); + + if (parse_for_each_row) + { + if (args[0]->null_value) + goto null_return; + if (hash_inited) + my_hash_free(&items); + if (root_inited) + free_root(&hash_root, MYF(0)); + root_inited= false; + hash_inited= false; + prepare_json_and_create_hash(&je1, js1); + } if (null_value || args[1]->null_value) goto null_return; @@ -5197,18 +5210,10 @@ null_return: return NULL; } -bool Item_func_json_array_intersect::fix_length_and_dec(THD *thd) +void Item_func_json_array_intersect::prepare_json_and_create_hash(json_engine_t *je1, String *js) { - json_engine_t je1; - String *js1= args[0]->val_json(&tmp_js1); - - if (args[0]->null_value) - { - null_value= true; - return FALSE; - } - json_scan_start(&je1, js1->charset(), (const uchar *) js1->ptr(), - (const uchar *) js1->ptr() + js1->length()); + json_scan_start(je1, js->charset(), (const uchar *) js->ptr(), + (const uchar *) js->ptr() + js->length()); /* Scan value uses the hash table to get the intersection of two arrays. */ @@ -5217,18 +5222,40 @@ bool Item_func_json_array_intersect::fix_length_and_dec(THD *thd) init_alloc_root(PSI_NOT_INSTRUMENTED, &hash_root, 1024, 0, MYF(0)); root_inited= true; - if (json_read_value(&je1) || je1.value_type != JSON_VALUE_ARRAY || - create_hash(&je1, &items, hash_inited, &hash_root)) + if (json_read_value(je1) || je1->value_type != JSON_VALUE_ARRAY || + create_hash(je1, &items, hash_inited, &hash_root)) + { + if (je1->s.error) + report_json_error(js, je1, 0); + null_value= 1; + } + + max_length= (args[0]->max_length < args[1]->max_length) ? + args[0]->max_length : args[1]->max_length; +} + +bool Item_func_json_array_intersect::fix_length_and_dec(THD *thd) +{ + json_engine_t je1; + String *js1; + + if (!args[0]->const_item()) { - if (je1.s.error) - report_json_error(js1, &je1, 0); - null_value= 1; - return FALSE; + if (args[1]->const_item()) + { + std::swap(args[0], args[1]); + } + else + { + parse_for_each_row= true; + goto end; + } } - max_length= (args[0]->max_length < args[1]->max_length) ? - args[0]->max_length : args[1]->max_length; + js1= args[0]->val_json(&tmp_js1); + prepare_json_and_create_hash(&je1, js1); +end: set_maybe_null(); return FALSE; } diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h index 42255d8d6f6..6a643e72554 100644 --- a/sql/item_jsonfunc.h +++ b/sql/item_jsonfunc.h @@ -869,9 +869,10 @@ protected: bool hash_inited, root_inited; HASH items; MEM_ROOT hash_root; + bool parse_for_each_row; public: Item_func_json_array_intersect(THD *thd, Item *a, Item *b): - Item_str_func(thd, a, b) { hash_inited= root_inited= false; } + Item_str_func(thd, a, b) { hash_inited= root_inited= parse_for_each_row= false; } String *val_str(String *) override; bool fix_length_and_dec(THD *thd) override; LEX_CSTRING func_name_cstring() const override @@ -889,6 +890,7 @@ public: if (root_inited) free_root(&hash_root, MYF(0)); } + void prepare_json_and_create_hash(json_engine_t *je1, String *js); }; class Item_func_json_object_filter_keys: public Item_str_func From bfab4ab0009c7d1db257bf5487b96a58f23e5b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 2 Nov 2023 15:27:52 +0200 Subject: [PATCH 170/477] MDEV-18867 fixup: Remove DBUG injection In commit 75e82f71f16c3248387e00bc6e4fe4da02555325 the code to rename internal tables for FULLTEXT INDEX that had been created on Microsoft Windows using incompatible names was removed. Let us also remove the related fault injection. --- storage/innobase/dict/dict0crea.cc | 3 --- storage/innobase/handler/ha_innodb.cc | 2 -- storage/innobase/include/fts0priv.inl | 23 ----------------------- storage/innobase/pars/pars0pars.cc | 3 --- storage/innobase/row/row0ftsort.cc | 2 -- 5 files changed, 33 deletions(-) diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index fbcacf9d6ff..f7740f920d4 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -354,9 +354,6 @@ dict_build_table_def_step( /* Always set this bit for all new created tables */ DICT_TF2_FLAG_SET(table, DICT_TF2_FTS_AUX_HEX_NAME); - DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", - DICT_TF2_FLAG_UNSET(table, - DICT_TF2_FTS_AUX_HEX_NAME);); if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_USE_FILE_PER_TABLE)) { /* This table will need a new tablespace. */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 1c460a9ff85..086f30e119e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12185,8 +12185,6 @@ index_bad: /* Set the flags2 when create table or alter tables */ m_flags2 |= DICT_TF2_FTS_AUX_HEX_NAME; - DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", - m_flags2 &= ~DICT_TF2_FTS_AUX_HEX_NAME;); DBUG_RETURN(true); } diff --git a/storage/innobase/include/fts0priv.inl b/storage/innobase/include/fts0priv.inl index da14cfcb013..3cb09c924db 100644 --- a/storage/innobase/include/fts0priv.inl +++ b/storage/innobase/include/fts0priv.inl @@ -34,29 +34,6 @@ fts_write_object_id( ib_id_t id, /* in: a table/index id */ char* str) /* in: buffer to write the id to */ { - -#ifdef _WIN32 - - DBUG_EXECUTE_IF("innodb_test_wrong_non_windows_fts_aux_table_name", - return(sprintf(str, UINT64PFx, id));); - - /* Use this to construct old(5.6.14 and 5.7.3) windows - ambiguous aux table names */ - DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", - return(sprintf(str, "%016llu", (ulonglong) id));); - -#else /* _WIN32 */ - - /* Use this to construct old(5.6.14 and 5.7.3) windows - ambiguous aux table names */ - DBUG_EXECUTE_IF("innodb_test_wrong_windows_fts_aux_table_name", - return(sprintf(str, "%016llu", (ulonglong) id));); - - DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", - return(sprintf(str, "%016llx", (ulonglong) id));); - -#endif /* _WIN32 */ - return(sprintf(str, "%016llx", (ulonglong) id)); } diff --git a/storage/innobase/pars/pars0pars.cc b/storage/innobase/pars/pars0pars.cc index 9f1aae9aa07..522f33b4c2f 100644 --- a/storage/innobase/pars/pars0pars.cc +++ b/storage/innobase/pars/pars0pars.cc @@ -1777,9 +1777,6 @@ pars_create_table( ulint flags = 0; ulint flags2 = DICT_TF2_FTS_AUX_HEX_NAME; - DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", - flags2 &= ~DICT_TF2_FTS_AUX_HEX_NAME;); - n_cols = que_node_list_get_len(column_defs); table = dict_mem_table_create( diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 53148647442..256bb8460c3 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -1657,8 +1657,6 @@ row_fts_merge_insert( /* We should set the flags2 with aux_table_name here, in order to get the correct aux table names. */ index->table->flags2 |= DICT_TF2_FTS_AUX_HEX_NAME; - DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", - index->table->flags2 &= ~DICT_TF2_FTS_AUX_HEX_NAME;); fts_table.type = FTS_INDEX_TABLE; fts_table.index_id = index->id; fts_table.table_id = table->id; From 5d3e14d780a227d87ea2831481958ac4d5bbd905 Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Tue, 19 Sep 2023 00:54:19 +0530 Subject: [PATCH 171/477] MDEV-31599: Assertion `0' failed in Item_param::can_return_value from Item::val_json, UBSAN: member access within null pointer of type 'struct String' in sql/item_jsonfunc.cc Analysis: The first argument of json_schema_valid() needs to be a constant. Fix: Parse the schema if the item is constant otherwise set it to return null. --- mysql-test/main/func_json.result | 7 +++++++ mysql-test/main/func_json.test | 9 +++++++++ sql/item_jsonfunc.cc | 12 +++++++++--- sql/share/errmsg-utf8.txt | 2 ++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 23f1bd149fb..5cc2b6392bd 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -4762,4 +4762,11 @@ NULL SELECT JSON_SCHEMA_VALID(NULL, NULL); JSON_SCHEMA_VALID(NULL, NULL) NULL +# +# MDEV-31599: Assertion `0' failed in Item_param::can_return_value from Item::val_json, +# UBSAN: member access within null pointer of type 'struct String' in +# sql/item_jsonfunc.cc +# +PREPARE s FROM 'SELECT JSON_SCHEMA_VALID (?,''{}'') FROM DUAL'; +ERROR HY000: Variable schema is not supported. # End of 11.1 test diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index d03b744d5d4..5eca4929ca1 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -3647,4 +3647,13 @@ SELECT JSON_SCHEMA_VALID('{}', NULL); SELECT JSON_SCHEMA_VALID(NULL, '{}'); SELECT JSON_SCHEMA_VALID(NULL, NULL); +--echo # +--echo # MDEV-31599: Assertion `0' failed in Item_param::can_return_value from Item::val_json, +--echo # UBSAN: member access within null pointer of type 'struct String' in +--echo # sql/item_jsonfunc.cc +--echo # + +--error ER_JSON_NO_VARIABLE_SCHEMA +PREPARE s FROM 'SELECT JSON_SCHEMA_VALID (?,''{}'') FROM DUAL'; + --echo # End of 11.1 test diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index fa0a8cbec7f..284d4fb1813 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -4798,15 +4798,21 @@ If any of them fails, return false, else return true. bool Item_func_json_schema_valid::fix_length_and_dec(THD *thd) { json_engine_t je; - bool res= 0; + bool res= 0, is_schema_constant= args[0]->const_item(); - String *js= args[0]->val_json(&tmp_js); + String *js= NULL; - if ((null_value= args[0]->null_value)) + if (!is_schema_constant || (null_value= args[0]->null_value)) { + if (!is_schema_constant) + { + my_error(ER_JSON_NO_VARIABLE_SCHEMA, MYF(0)); + } null_value= 1; return 0; } + js= args[0]->val_json(&tmp_js); + json_scan_start(&je, js->charset(), (const uchar *) js->ptr(), (const uchar *) js->ptr() + js->length()); if (!create_object_and_handle_keyword(thd, &je, &keyword_list, diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 886b20749d7..66414db0992 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -11972,3 +11972,5 @@ ER_JSON_INVALID_VALUE_FOR_KEYWORD ER_JSON_SCHEMA_KEYWORD_UNSUPPORTED eng "%s keyword is not supported" sw "%s neno kuu halitumiki" +ER_JSON_NO_VARIABLE_SCHEMA + eng "Variable schema is not supported." From 01031f43d8918dc21bbf27f73a7e73e832ccb4d6 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 27 Sep 2023 10:28:44 +0200 Subject: [PATCH 172/477] MDEV-29180: Description of log_warnings incorrectly mentions "general log" --- mysql-test/main/mysqld--help.result | 5 ++--- mysql-test/suite/sys_vars/r/sysvars_server_embedded.result | 2 +- .../suite/sys_vars/r/sysvars_server_notembedded.result | 2 +- sql/sys_vars.cc | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 6ada7faeb10..020d7b27ce0 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -511,9 +511,8 @@ The following specify which files/extra groups are read (specified before remain when binary log is disabled). --log-tc-size=# Size of transaction coordinator log. -W, --log-warnings[=#] - Log some not critical warnings to the general log - file.Value can be between 0 and 11. Higher values mean - more verbosity + Log some non critical warnings to the error log.Value can + be between 0 and 11. Higher values mean more verbosity --long-query-time=# Log all queries that have taken more than long_query_time seconds to execute to the slow query log file. The argument will be treated as a decimal value with 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 c03181d0c63..b02f6436e08 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -1705,7 +1705,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_WARNINGS VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity +VARIABLE_COMMENT Log some non critical warnings to the error log.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 1 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 48b481b200c..3bad54432ea 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -1845,7 +1845,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_WARNINGS VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity +VARIABLE_COMMENT Log some non critical warnings to the error log.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 1 diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 5cd33a5bf81..7540858da32 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1384,7 +1384,7 @@ static Sys_var_bit Sys_log_slow_slave_statements( static Sys_var_ulong Sys_log_warnings( "log_warnings", - "Log some not critical warnings to the general log file." + "Log some non critical warnings to the error log." "Value can be between 0 and 11. Higher values mean more verbosity", SESSION_VAR(log_warnings), CMD_LINE(OPT_ARG, 'W'), From d914d09f58620937c20fa35279610d178d2ad03c Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 27 Sep 2023 13:55:39 +0200 Subject: [PATCH 173/477] MDEV-25329: Assertion `allocated_status_memory != __null' failed in void PROF_MEASUREMENT::set_label(const char*, const char*, const char*, unsigned int) Make profiler to play a bit better with memory allocators. Test suite can not be included because it lead to non free memory on shutdown (IMHO OK for memory shortage emulation) As alternetive all this should be rewritten and ability to return errors on upper level should be added. --- sql/sql_profile.cc | 7 ++++++- sql/sql_profile.h | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index f36805012b2..d6c07d48a6b 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -203,7 +203,8 @@ void PROF_MEASUREMENT::set_label(const char *status_arg, sizes[2]= (file_arg == NULL) ? 0 : strlen(file_arg) + 1; allocated_status_memory= (char *) my_malloc(sizes[0] + sizes[1] + sizes[2], MYF(0)); - DBUG_ASSERT(allocated_status_memory != NULL); + if (!allocated_status_memory) + return; cursor= allocated_status_memory; @@ -267,6 +268,8 @@ QUERY_PROFILE::QUERY_PROFILE(PROFILING *profiling_arg, const char *status_arg) { m_seq_counter= 1; PROF_MEASUREMENT *prof= new PROF_MEASUREMENT(this, status_arg); + if (!prof) + return; prof->m_seq= m_seq_counter++; m_start_time_usecs= prof->time_usecs; m_end_time_usecs= m_start_time_usecs; @@ -308,6 +311,8 @@ void QUERY_PROFILE::new_status(const char *status_arg, prof= new PROF_MEASUREMENT(this, status_arg, function_arg, base_name(file_arg), line_arg); else prof= new PROF_MEASUREMENT(this, status_arg); + if (!prof) + DBUG_VOID_RETURN; prof->m_seq= m_seq_counter++; m_end_time_usecs= prof->time_usecs; diff --git a/sql/sql_profile.h b/sql/sql_profile.h index 5b03acf59c0..f618d059e2e 100644 --- a/sql/sql_profile.h +++ b/sql/sql_profile.h @@ -98,6 +98,8 @@ public: struct queue_item *new_item; new_item= (struct queue_item *) my_malloc(sizeof(struct queue_item), MYF(0)); + if (!new_item) + return; new_item->payload= payload; @@ -291,7 +293,11 @@ public: { DBUG_ASSERT(!current); if (unlikely(enabled)) - current= new QUERY_PROFILE(this, initial_state); + { + QUERY_PROFILE *new_profile= new QUERY_PROFILE(this, initial_state); + if (new_profile) + current= new_profile; + } } void discard_current_query(); From 46ee272a10d7638922307fc67e6711fee6869c4e Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Mon, 11 Sep 2023 17:54:10 +0400 Subject: [PATCH 174/477] MDEV-32100 Online ALTER TABLE ends with 1032 under some isolation levels 1032 (Can't find record) could be emitted when ALTER TABLE is execued vs concurrent DELETE/UPDATE/other DML that would require search on the online ALTER's side. Innodb's INPLACE, in comparison, creates a new trx_t and uses it in scope of the alter table context. ALTER TABLE class of statements (i.g. CREATE INDEX, OPTIMIZE, etc.) is expected to be unaffected by the value of current session's transaction isolation. This patch save-and-restores thd->tx_isolation and sets in to ISO_REPEATABLE_READ for almost a whole mysql_alter_table duration, to avoid any possible side-effect of it. This should be primarily done before the lock_tables call, to initialize the storage engine's local value correctly during the store_lock() call. sql_table.cc: set thd->tx_isolation to ISO_REPEATABLE_READ in mysql_alter_table and then restore it to the original value in the end of the call. --- .../main/alter_table_online_debug.result | 62 +++++++++++++++++++ mysql-test/main/alter_table_online_debug.test | 41 ++++++++++++ sql/sql_table.cc | 7 +++ 3 files changed, 110 insertions(+) diff --git a/mysql-test/main/alter_table_online_debug.result b/mysql-test/main/alter_table_online_debug.result index 81fe415cf6f..3bb2bce8052 100644 --- a/mysql-test/main/alter_table_online_debug.result +++ b/mysql-test/main/alter_table_online_debug.result @@ -1456,6 +1456,68 @@ connection default; set old_mode= @old_old_mode; drop table t1; set debug_sync= reset; +# +# MDEV-32100 Online ALTER TABLE ends with 1032 under some isolation levels +# +create table iso_levels(id int, level text); +INSERT iso_levels VALUES (0, "READ UNCOMMITTED"), +(1, "READ COMMITTED"), +(2, "REPEATABLE READ"), +(3, "SERIALIZABLE"); +create table t1 (a int, b int, key(b)) engine=innodb; +connection con2; +insert into t1 values (1,1),(null,null),(3,3),(4,null),(null,5); +connection default; +set session transaction isolation level SERIALIZABLE; +set debug_sync= "alter_table_online_downgraded signal downgraded wait_for goalters"; +alter table t1 force, algorithm=copy; +connection con2; +set debug_sync= "now wait_for downgraded"; +delete from t1 where b is null; +set debug_sync= "now signal goalters"; +connection default; +drop table t1; +create table t1 (a int, b int, key(b)) engine=innodb; +connection con2; +insert into t1 values (1,1),(null,null),(3,3),(4,null),(null,5); +connection default; +set session transaction isolation level REPEATABLE READ; +set debug_sync= "alter_table_online_downgraded signal downgraded wait_for goalters"; +alter table t1 force, algorithm=copy; +connection con2; +set debug_sync= "now wait_for downgraded"; +delete from t1 where b is null; +set debug_sync= "now signal goalters"; +connection default; +drop table t1; +create table t1 (a int, b int, key(b)) engine=innodb; +connection con2; +insert into t1 values (1,1),(null,null),(3,3),(4,null),(null,5); +connection default; +set session transaction isolation level READ COMMITTED; +set debug_sync= "alter_table_online_downgraded signal downgraded wait_for goalters"; +alter table t1 force, algorithm=copy; +connection con2; +set debug_sync= "now wait_for downgraded"; +delete from t1 where b is null; +set debug_sync= "now signal goalters"; +connection default; +drop table t1; +create table t1 (a int, b int, key(b)) engine=innodb; +connection con2; +insert into t1 values (1,1),(null,null),(3,3),(4,null),(null,5); +connection default; +set session transaction isolation level READ UNCOMMITTED; +set debug_sync= "alter_table_online_downgraded signal downgraded wait_for goalters"; +alter table t1 force, algorithm=copy; +connection con2; +set debug_sync= "now wait_for downgraded"; +delete from t1 where b is null; +set debug_sync= "now signal goalters"; +connection default; +drop table t1; +set debug_sync= reset; +drop table iso_levels; disconnect con1; disconnect con2; # diff --git a/mysql-test/main/alter_table_online_debug.test b/mysql-test/main/alter_table_online_debug.test index e054c0218f5..a52e95f69ed 100644 --- a/mysql-test/main/alter_table_online_debug.test +++ b/mysql-test/main/alter_table_online_debug.test @@ -1695,6 +1695,47 @@ set old_mode= @old_old_mode; drop table t1; set debug_sync= reset; +--echo # +--echo # MDEV-32100 Online ALTER TABLE ends with 1032 under some isolation levels +--echo # + +let $tx_iso_id=4; + +create table iso_levels(id int, level text); +INSERT iso_levels VALUES (0, "READ UNCOMMITTED"), + (1, "READ COMMITTED"), + (2, "REPEATABLE READ"), + (3, "SERIALIZABLE"); + +while($tx_iso_id) { +dec $tx_iso_id; +let tx_iso= `select level from iso_levels where id = $tx_iso_id`; + +create table t1 (a int, b int, key(b)) engine=innodb; + +--connection con2 +insert into t1 values (1,1),(null,null),(3,3),(4,null),(null,5); + +--connection default + +eval set session transaction isolation level $tx_iso; +set debug_sync= "alter_table_online_downgraded signal downgraded wait_for goalters"; + +send alter table t1 force, algorithm=copy; + +--connection con2 +set debug_sync= "now wait_for downgraded"; +delete from t1 where b is null; +set debug_sync= "now signal goalters"; + +--connection default +--reap +drop table t1; +} +set debug_sync= reset; +drop table iso_levels; + + --disconnect con1 --disconnect con2 diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 25d72cfb2fb..453237dbb65 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -65,6 +65,7 @@ #include "rpl_rli.h" #include "log.h" #include "sql_debug.h" +#include "scope.h" #ifdef _WIN32 #include @@ -10236,6 +10237,12 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, table_list->lock_type= TL_READ; } + enum_tx_isolation iso_level_initial= thd->tx_isolation; + SCOPE_EXIT([thd, iso_level_initial](){ + thd->tx_isolation= iso_level_initial; + }); + thd->tx_isolation= ISO_REPEATABLE_READ; + DEBUG_SYNC(thd, "alter_table_before_open_tables"); thd->open_options|= HA_OPEN_FOR_ALTER; From a1019e93d6c6fbdcca74288ea5c32ff3b48c8e1b Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Fri, 22 Sep 2023 16:29:15 +0400 Subject: [PATCH 175/477] binlog_cache_data: add more consts --- sql/log.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index 227ce075c19..f47867c5a61 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -322,7 +322,7 @@ public: incident= TRUE; } - bool has_incident(void) + bool has_incident(void) const { return(incident); } @@ -349,7 +349,7 @@ public: return my_b_tell(&cache_log); } - my_off_t get_prev_position() + my_off_t get_prev_position() const { return(before_stmt_pos); } From 830bdfccbd9a9c5518e4b6f08f78c0d3126dc385 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Tue, 19 Sep 2023 18:19:10 +0400 Subject: [PATCH 176/477] MDEV-32126 Assertion fails upon online ALTER and binary log enabled Assertion `!writer.checksum_len || writer.remains == 0' fails upon concurrent online ALTER and transactions with failing statements and binary log enabled. Also another assertion, `pos != (~(my_off_t) 0)', fails in my_seek, upon reinit_io_cache, on a simplified test. This means that IO_CACHE wasn't properly initialized, or had an error before. The overall problem is a deep interference with the effect of an installed binlog_hton: the assumption about that thd->binlog_get_cache_mngr() is, sufficiently, NULL, when we shouldn't run the binlog part of binlog_commit/binlog_rollback, is wrong: as turns out, sometimes the binlog handlerton can be not installed in current thd, but binlog_commit can be called on behalf of binlog, as in the bug reported. One separate condition found is XA recovery of the orphaned transaction, when binlog_commit is also called, but it has nothing to do with online alter. Solution: Extract online alter operations into a separate handlerton. --- .../main/alter_table_online_debug.result | 45 +++++++++++ mysql-test/main/alter_table_online_debug.test | 54 +++++++++++++ sql/CMakeLists.txt | 2 + sql/handler.h | 9 ++- sql/log.cc | 78 +++++++++++++++---- sql/log.h | 1 + 6 files changed, 172 insertions(+), 17 deletions(-) diff --git a/mysql-test/main/alter_table_online_debug.result b/mysql-test/main/alter_table_online_debug.result index 3bb2bce8052..1ebb19965eb 100644 --- a/mysql-test/main/alter_table_online_debug.result +++ b/mysql-test/main/alter_table_online_debug.result @@ -1518,6 +1518,51 @@ connection default; drop table t1; set debug_sync= reset; drop table iso_levels; +# MDEV-32126 Assertion fails upon online ALTER and binary log enabled +create temporary table tmp (id int, primary key(id)) engine=innodb; +create table t1 (a int, b text) engine=innodb; +create table t2 (a int, b int, c char(8), d text, unique(a)) engine=innodb; +insert into t2 values (1,1,'f','e'),(1000,1000,'c','b'); +connection default; +set debug_sync= 'alter_table_online_before_lock signal go_trx wait_for go_alter'; +alter table t2 force, algorithm=copy, lock=none; +connection con2; +set debug_sync= 'now wait_for go_trx'; +start transaction; +insert into t1 values (3,'a'); +insert into t2 values (3,3,'a','x'), (3,3,'a','x'); +ERROR 23000: Duplicate entry '3' for key 'a' +insert into t2 values (3,3,'a','x'); +commit; +set debug_sync= 'now signal go_alter'; +connection default; +truncate t2; +set @@binlog_format=mixed; +connection con2; +start transaction; +create temporary table tmp (id int, primary key(id)) engine=innodb; +insert into t1 values (1, repeat('x',8000)),(2, repeat('x',8000)); +update t2 set b = null order by b limit 2; +insert into t1 values (3, repeat('x',8000)); +delete from t1; +insert into t2 values (1,1,'f','e'),(1000,1000,'c','b'); +commit; +connection default; +set debug_sync= 'alter_table_online_before_lock signal go_trx wait_for go_alter'; +alter table t2 force, algorithm=copy, lock=none; +connection con2; +set debug_sync= 'now wait_for go_trx'; +start transaction; +drop temporary table if exists tmp; +insert into t2 values (3,3,'a','x'), (3,3,'a','x'); +ERROR 23000: Duplicate entry '3' for key 'a' +insert into t2 values (3,3,'a','x'); +commit; +set debug_sync= 'now signal go_alter'; +connection default; +drop table t1, t2; +set @@binlog_format=default; +set debug_sync= reset; disconnect con1; disconnect con2; # diff --git a/mysql-test/main/alter_table_online_debug.test b/mysql-test/main/alter_table_online_debug.test index a52e95f69ed..0a0a9ab72fc 100644 --- a/mysql-test/main/alter_table_online_debug.test +++ b/mysql-test/main/alter_table_online_debug.test @@ -1736,6 +1736,60 @@ set debug_sync= reset; drop table iso_levels; +--echo # MDEV-32126 Assertion fails upon online ALTER and binary log enabled +create temporary table tmp (id int, primary key(id)) engine=innodb; +create table t1 (a int, b text) engine=innodb; +create table t2 (a int, b int, c char(8), d text, unique(a)) engine=innodb; +insert into t2 values (1,1,'f','e'),(1000,1000,'c','b'); +--connection default +set debug_sync= 'alter_table_online_before_lock signal go_trx wait_for go_alter'; +send alter table t2 force, algorithm=copy, lock=none; + +--connection con2 +set debug_sync= 'now wait_for go_trx'; +start transaction; +insert into t1 values (3,'a'); +--error ER_DUP_ENTRY +insert into t2 values (3,3,'a','x'), (3,3,'a','x'); +insert into t2 values (3,3,'a','x'); +commit; +set debug_sync= 'now signal go_alter'; +--connection default +--reap +truncate t2; +set @@binlog_format=mixed; +--connection con2 +start transaction; +create temporary table tmp (id int, primary key(id)) engine=innodb; +insert into t1 values (1, repeat('x',8000)),(2, repeat('x',8000)); +update t2 set b = null order by b limit 2; +insert into t1 values (3, repeat('x',8000)); +delete from t1; +insert into t2 values (1,1,'f','e'),(1000,1000,'c','b'); +commit; + + +--connection default +set debug_sync= 'alter_table_online_before_lock signal go_trx wait_for go_alter'; +send alter table t2 force, algorithm=copy, lock=none; + +--connection con2 +set debug_sync= 'now wait_for go_trx'; +start transaction; +drop temporary table if exists tmp; +--error ER_DUP_ENTRY +insert into t2 values (3,3,'a','x'), (3,3,'a','x'); +insert into t2 values (3,3,'a','x'); +commit; +set debug_sync= 'now signal go_alter'; + +--connection default +--reap + +drop table t1, t2; +set @@binlog_format=default; +set debug_sync= reset; + --disconnect con1 --disconnect con2 diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 181eccf9bc1..bf26e987eb5 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -218,6 +218,8 @@ MYSQL_ADD_PLUGIN(partition ha_partition.cc STORAGE_ENGINE DEFAULT STATIC_ONLY RECOMPILE_FOR_EMBEDDED) MYSQL_ADD_PLUGIN(sql_sequence ha_sequence.cc STORAGE_ENGINE MANDATORY STATIC_ONLY RECOMPILE_FOR_EMBEDDED) +MYSQL_ADD_PLUGIN(online_alter_log log.cc STORAGE_ENGINE MANDATORY STATIC_ONLY +NOT_EMBEDDED) ADD_LIBRARY(sql STATIC ${SQL_SOURCE}) MAYBE_DISABLE_IPO(sql) diff --git a/sql/handler.h b/sql/handler.h index 8dba8352c60..65b3ca2c5ff 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -557,6 +557,7 @@ enum legacy_db_type DB_TYPE_BLACKHOLE_DB=19, DB_TYPE_PARTITION_DB=20, DB_TYPE_BINLOG=21, + DB_TYPE_ONLINE_ALTER=22, DB_TYPE_PBXT=23, DB_TYPE_PERFORMANCE_SCHEMA=28, DB_TYPE_S3=41, @@ -1096,6 +1097,9 @@ enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX }; extern MYSQL_PLUGIN_IMPORT st_plugin_int *hton2plugin[MAX_HA]; struct handlerton; + +extern handlerton *online_alter_hton; + #define view_pseudo_hton ((handlerton *)1) /* @@ -1916,7 +1920,6 @@ struct THD_TRANS }; - /** Either statement transaction or normal transaction - related thread-specific storage engine data. @@ -1969,7 +1972,9 @@ public: bool is_trx_read_write() const { DBUG_ASSERT(is_started()); - return m_flags & (int) TRX_READ_WRITE; + bool result= m_flags & (int) TRX_READ_WRITE; + DBUG_ASSERT(!result || m_ht != online_alter_hton); + return result; } bool is_started() const { return m_ht != NULL; } /** Mark this transaction read-write if the argument is read-write. */ diff --git a/sql/log.cc b/sql/log.cc index f47867c5a61..34f8ac5cb2b 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2185,7 +2185,6 @@ int binlog_rollback_by_xid(handlerton *hton, XID *xid) DBUG_ASSERT(thd->lex->sql_command == SQLCOM_XA_ROLLBACK || (thd->transaction->xid_state.get_state_code() == XA_ROLLBACK_ONLY)); - rc= binlog_rollback(hton, thd, TRUE); thd->ha_data[hton->slot].ha_info[1].reset(); @@ -2276,9 +2275,9 @@ int binlog_log_row_online_alter(TABLE* table, const uchar *before_record, if (!table->online_alter_cache) { table->online_alter_cache= online_alter_binlog_get_cache_data(thd, table); - trans_register_ha(thd, false, binlog_hton, 0); + trans_register_ha(thd, false, online_alter_hton, 0); if (thd->in_multi_stmt_transaction_mode()) - trans_register_ha(thd, true, binlog_hton, 0); + trans_register_ha(thd, true, online_alter_hton, 0); } // We need to log all columns for the case if alter table changes primary key @@ -2339,12 +2338,7 @@ int binlog_commit(THD *thd, bool all, bool ro_1pc) PSI_stage_info org_stage; DBUG_ENTER("binlog_commit"); - IF_DBUG(bool commit_online= !thd->online_alter_cache_list.empty(),); - bool is_ending_transaction= ending_trans(thd, all); - error= binlog_online_alter_end_trans(thd, all, true); - if (error) - DBUG_RETURN(error); binlog_cache_mngr *const cache_mngr= thd->binlog_get_cache_mngr(); /* @@ -2352,7 +2346,7 @@ int binlog_commit(THD *thd, bool all, bool ro_1pc) */ if (!cache_mngr) { - DBUG_ASSERT(WSREP(thd) || commit_online || + DBUG_ASSERT(WSREP(thd) || (thd->lex->sql_command != SQLCOM_XA_PREPARE && !(thd->lex->sql_command == SQLCOM_XA_COMMIT && thd->lex->xa_opt == XA_ONE_PHASE))); @@ -2450,17 +2444,13 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) DBUG_ENTER("binlog_rollback"); bool is_ending_trans= ending_trans(thd, all); - - bool rollback_online= !thd->online_alter_cache_list.empty(); - if (rollback_online) - binlog_online_alter_end_trans(thd, all, 0); int error= 0; binlog_cache_mngr *const cache_mngr= thd->binlog_get_cache_mngr(); if (!cache_mngr) { - DBUG_ASSERT(WSREP(thd) || rollback_online); - DBUG_ASSERT(thd->lex->sql_command != SQLCOM_XA_ROLLBACK || rollback_online); + DBUG_ASSERT(WSREP(thd)); + DBUG_ASSERT(thd->lex->sql_command != SQLCOM_XA_ROLLBACK); DBUG_RETURN(0); } @@ -12538,3 +12528,61 @@ void wsrep_register_binlog_handler(THD *thd, bool trx) } #endif /* WITH_WSREP */ + +static int online_alter_close_connection(handlerton *hton, THD *thd) +{ + DBUG_ASSERT(thd->online_alter_cache_list.empty()); + return 0; +} + +handlerton *online_alter_hton; + +int online_alter_log_init(void *p) +{ + online_alter_hton= (handlerton *)p; + online_alter_hton->db_type= DB_TYPE_ONLINE_ALTER; + online_alter_hton->savepoint_offset= sizeof(my_off_t); + online_alter_hton->close_connection= online_alter_close_connection; + + online_alter_hton->savepoint_set= // Done by online_alter_savepoint_set + [](handlerton *, THD *, void *){ return 0; }; + online_alter_hton->savepoint_rollback= // Done by online_alter_savepoint_rollback + [](handlerton *, THD *, void *){ return 0; }; + online_alter_hton->savepoint_rollback_can_release_mdl= + [](handlerton *hton, THD *thd){ return true; }; + + online_alter_hton->commit= [](handlerton *, THD *thd, bool all) + { return binlog_online_alter_end_trans(thd, all, true); }; + online_alter_hton->rollback= [](handlerton *, THD *thd, bool all) + { return binlog_online_alter_end_trans(thd, all, false); }; + online_alter_hton->commit_by_xid= [](handlerton *hton, XID *xid) + { return binlog_online_alter_end_trans(current_thd, true, true); }; + online_alter_hton->rollback_by_xid= [](handlerton *hton, XID *xid) + { return binlog_online_alter_end_trans(current_thd, true, false); }; + + online_alter_hton->drop_table= [](handlerton *, const char*) { return -1; }; + online_alter_hton->flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN + | HTON_NO_ROLLBACK; + return 0; +} + +struct st_mysql_storage_engine online_alter_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION }; + +maria_declare_plugin(online_alter_log) +{ + MYSQL_STORAGE_ENGINE_PLUGIN, + &online_alter_storage_engine, + "online_alter_log", + "MariaDB PLC", + "This is a pseudo storage engine to represent the online alter log in a transaction", + PLUGIN_LICENSE_GPL, + online_alter_log_init, + NULL, + 0x0100, // 1.0 + NULL, // no status vars + NULL, // no sysvars + "1.0", + MariaDB_PLUGIN_MATURITY_STABLE +} +maria_declare_plugin_end; diff --git a/sql/log.h b/sql/log.h index f79305c174a..f617f23911e 100644 --- a/sql/log.h +++ b/sql/log.h @@ -1351,6 +1351,7 @@ binlog_cache_data* binlog_get_cache_data(binlog_cache_mngr *cache_mngr, extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log; extern handlerton *binlog_hton; +extern handlerton *online_alter_hton; extern LOGGER logger; extern const char *log_bin_index; From cb52174693801ae573aa21d78a9d49113cdd65cd Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Fri, 22 Sep 2023 17:09:21 +0400 Subject: [PATCH 177/477] online alter: extract the source to a separate file Move all the functions dedicated to online alter to a newly created online_alter.cc. With that, make many functions static and simplify the static functions naming. Also, rename binlog_log_row_online_alter -> online_alter_log_row. --- sql/CMakeLists.txt | 6 +- sql/handler.cc | 4 +- sql/handler.h | 6 +- sql/log.cc | 526 +------------------------------------------- sql/log.h | 6 +- sql/log_cache.h | 247 +++++++++++++++++++++ sql/online_alter.cc | 320 +++++++++++++++++++++++++++ 7 files changed, 577 insertions(+), 538 deletions(-) create mode 100644 sql/log_cache.h create mode 100644 sql/online_alter.cc diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index bf26e987eb5..72e906681fe 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -218,8 +218,9 @@ MYSQL_ADD_PLUGIN(partition ha_partition.cc STORAGE_ENGINE DEFAULT STATIC_ONLY RECOMPILE_FOR_EMBEDDED) MYSQL_ADD_PLUGIN(sql_sequence ha_sequence.cc STORAGE_ENGINE MANDATORY STATIC_ONLY RECOMPILE_FOR_EMBEDDED) -MYSQL_ADD_PLUGIN(online_alter_log log.cc STORAGE_ENGINE MANDATORY STATIC_ONLY -NOT_EMBEDDED) +MYSQL_ADD_PLUGIN(online_alter_log online_alter.cc STORAGE_ENGINE MANDATORY +STATIC_ONLY NOT_EMBEDDED) + ADD_LIBRARY(sql STATIC ${SQL_SOURCE}) MAYBE_DISABLE_IPO(sql) @@ -227,6 +228,7 @@ DTRACE_INSTRUMENT(sql) TARGET_LINK_LIBRARIES(sql mysys mysys_ssl dbug strings vio pcre2-8 tpool + online_alter_log ${LIBWRAP} ${LIBCRYPT} ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT} ${SSL_LIBRARIES} ${LIBSYSTEMD}) diff --git a/sql/handler.cc b/sql/handler.cc index 320d1d55292..a48c16c278c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7304,8 +7304,8 @@ int handler::binlog_log_row(const uchar *before_record, #ifdef HAVE_REPLICATION if (unlikely(!error && table->s->online_alter_binlog && is_root_handler())) - error= binlog_log_row_online_alter(table, before_record, after_record, - log_func); + error= online_alter_log_row(table, before_record, after_record, + log_func); #endif // HAVE_REPLICATION DBUG_RETURN(error); diff --git a/sql/handler.h b/sql/handler.h index 65b3ca2c5ff..07b392c010a 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1098,8 +1098,6 @@ extern MYSQL_PLUGIN_IMPORT st_plugin_int *hton2plugin[MAX_HA]; struct handlerton; -extern handlerton *online_alter_hton; - #define view_pseudo_hton ((handlerton *)1) /* @@ -1972,9 +1970,7 @@ public: bool is_trx_read_write() const { DBUG_ASSERT(is_started()); - bool result= m_flags & (int) TRX_READ_WRITE; - DBUG_ASSERT(!result || m_ht != online_alter_hton); - return result; + return m_flags & (int) TRX_READ_WRITE; } bool is_started() const { return m_ht != NULL; } /** Mark this transaction read-write if the argument is read-write. */ diff --git a/sql/log.cc b/sql/log.cc index 34f8ac5cb2b..aa71631155b 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -59,6 +59,7 @@ #include "sp_rcontext.h" #include "sp_head.h" #include "sql_table.h" +#include "log_cache.h" #include "wsrep_mysqld.h" #ifdef WITH_WSREP @@ -75,9 +76,6 @@ /* max size of the log message */ #define MAX_LOG_BUFFER_SIZE 1024 #define MAX_TIME_SIZE 32 -#define MY_OFF_T_UNDEF (~(my_off_t)0UL) -/* Truncate cache log files bigger than this */ -#define CACHE_FILE_TRUNC_SIZE 65536 #define FLAGSTR(V,F) ((V)&(F)?#F" ":"") @@ -104,8 +102,6 @@ static int binlog_flush_cache(THD *thd, binlog_cache_mngr *cache_mngr, Log_event *end_ev, bool all, bool using_stmt, bool using_trx, bool is_ro_1pc); -static int binlog_online_alter_end_trans(THD *thd, bool all, bool commit); - static const LEX_CSTRING write_error_msg= { STRING_WITH_LEN("error writing to the binary log") }; @@ -275,243 +271,7 @@ void make_default_log_name(char **out, const char* log_ext, bool once) Helper classes to store non-transactional and transactional data before copying it to the binary log. */ -class binlog_cache_data -{ -public: - binlog_cache_data(): before_stmt_pos(MY_OFF_T_UNDEF), m_pending(0), status(0), - incident(FALSE), saved_max_binlog_cache_size(0), ptr_binlog_cache_use(0), - ptr_binlog_cache_disk_use(0) - { } - - ~binlog_cache_data() - { - DBUG_ASSERT(empty()); - close_cached_file(&cache_log); - } - /* - Return 1 if there is no relevant entries in the cache - - This is: - - Cache is empty - - There are row or critical (DDL?) events in the cache - - The status test is needed to avoid writing entries with only - a table map entry, which would crash in do_apply_event() on the slave - as it assumes that there is always a row entry after a table map. - */ - bool empty() const - { - return (pending() == NULL && - (my_b_write_tell(&cache_log) == 0 || - ((status & (LOGGED_ROW_EVENT | LOGGED_CRITICAL)) == 0))); - } - - Rows_log_event *pending() const - { - return m_pending; - } - - void set_pending(Rows_log_event *const pending_arg) - { - m_pending= pending_arg; - } - - void set_incident(void) - { - incident= TRUE; - } - - bool has_incident(void) const - { - return(incident); - } - - void reset() - { - bool cache_was_empty= empty(); - bool truncate_file= (cache_log.file != -1 && - my_b_write_tell(&cache_log) > CACHE_FILE_TRUNC_SIZE); - truncate(0,1); // Forget what's in cache - if (!cache_was_empty) - compute_statistics(); - if (truncate_file) - my_chsize(cache_log.file, 0, 0, MYF(MY_WME)); - - status= 0; - incident= FALSE; - before_stmt_pos= MY_OFF_T_UNDEF; - DBUG_ASSERT(empty()); - } - - my_off_t get_byte_position() const - { - return my_b_tell(&cache_log); - } - - my_off_t get_prev_position() const - { - return(before_stmt_pos); - } - - void set_prev_position(my_off_t pos) - { - before_stmt_pos= pos; - } - - void restore_prev_position() - { - truncate(before_stmt_pos); - } - - void restore_savepoint(my_off_t pos) - { - truncate(pos); - if (pos < before_stmt_pos) - before_stmt_pos= MY_OFF_T_UNDEF; - } - - void set_binlog_cache_info(my_off_t param_max_binlog_cache_size, - ulong *param_ptr_binlog_cache_use, - ulong *param_ptr_binlog_cache_disk_use) - { - /* - The assertions guarantee that the set_binlog_cache_info is - called just once and information passed as parameters are - never zero. - - This is done while calling the constructor binlog_cache_mngr. - We cannot set information in the constructor binlog_cache_data - because the space for binlog_cache_mngr is allocated through - a placement new. - - In the future, we can refactor this and change it to avoid - the set_binlog_info. - */ - DBUG_ASSERT(saved_max_binlog_cache_size == 0); - DBUG_ASSERT(param_max_binlog_cache_size != 0); - DBUG_ASSERT(ptr_binlog_cache_use == 0); - DBUG_ASSERT(param_ptr_binlog_cache_use != 0); - DBUG_ASSERT(ptr_binlog_cache_disk_use == 0); - DBUG_ASSERT(param_ptr_binlog_cache_disk_use != 0); - - saved_max_binlog_cache_size= param_max_binlog_cache_size; - ptr_binlog_cache_use= param_ptr_binlog_cache_use; - ptr_binlog_cache_disk_use= param_ptr_binlog_cache_disk_use; - cache_log.end_of_file= saved_max_binlog_cache_size; - } - - void add_status(enum_logged_status status_arg) - { - status|= status_arg; - } - - /* - Cache to store data before copying it to the binary log. - */ - IO_CACHE cache_log; - -protected: - /* - Binlog position before the start of the current statement. - */ - my_off_t before_stmt_pos; - -private: - /* - Pending binrows event. This event is the event where the rows are currently - written. - */ - Rows_log_event *m_pending; - - /* - Bit flags for what has been writing to cache. Used to - discard logs without any data changes. - see enum_logged_status; - */ - uint32 status; - - /* - This indicates that some events did not get into the cache and most likely - it is corrupted. - */ - bool incident; - - /** - This function computes binlog cache and disk usage. - */ - void compute_statistics() - { - statistic_increment(*ptr_binlog_cache_use, &LOCK_status); - if (cache_log.disk_writes != 0) - { -#ifdef REAL_STATISTICS - statistic_add(*ptr_binlog_cache_disk_use, - cache_log.disk_writes, &LOCK_status); -#else - statistic_increment(*ptr_binlog_cache_disk_use, &LOCK_status); -#endif - cache_log.disk_writes= 0; - } - } - - /* - Stores the values of maximum size of the cache allowed when this cache - is configured. This corresponds to either - . max_binlog_cache_size or max_binlog_stmt_cache_size. - */ - my_off_t saved_max_binlog_cache_size; - - /* - Stores a pointer to the status variable that keeps track of the in-memory - cache usage. This corresponds to either - . binlog_cache_use or binlog_stmt_cache_use. - */ - ulong *ptr_binlog_cache_use; - - /* - Stores a pointer to the status variable that keeps track of the disk - cache usage. This corresponds to either - . binlog_cache_disk_use or binlog_stmt_cache_disk_use. - */ - ulong *ptr_binlog_cache_disk_use; - - /* - It truncates the cache to a certain position. This includes deleting the - pending event. - */ - void truncate(my_off_t pos, bool reset_cache=0) - { - DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos)); - cache_log.error=0; - if (pending()) - { - delete pending(); - set_pending(0); - } - my_bool res= reinit_io_cache(&cache_log, WRITE_CACHE, pos, 0, reset_cache); - DBUG_ASSERT(res == 0); - cache_log.end_of_file= saved_max_binlog_cache_size; - } - - binlog_cache_data& operator=(const binlog_cache_data& info); - binlog_cache_data(const binlog_cache_data& info); -}; - - -class online_alter_cache_data: public Sql_alloc, public ilist_node<>, - public binlog_cache_data -{ -public: - void store_prev_position() - { - before_stmt_pos= my_b_write_tell(&cache_log); - } - - handlerton *hton; - Cache_flip_event_log *sink_log; - SAVEPOINT *sv_list; -}; void Log_event_writer::add_status(enum_logged_status status) { @@ -2266,61 +2026,6 @@ static int binlog_commit_flush_xa_prepare(THD *thd, bool all, return (binlog_flush_cache(thd, cache_mngr, &end_evt, all, TRUE, TRUE)); } -#ifdef HAVE_REPLICATION -int binlog_log_row_online_alter(TABLE* table, const uchar *before_record, - const uchar *after_record, Log_func *log_func) -{ - THD *thd= table->in_use; - - if (!table->online_alter_cache) - { - table->online_alter_cache= online_alter_binlog_get_cache_data(thd, table); - trans_register_ha(thd, false, online_alter_hton, 0); - if (thd->in_multi_stmt_transaction_mode()) - trans_register_ha(thd, true, online_alter_hton, 0); - } - - // We need to log all columns for the case if alter table changes primary key - DBUG_ASSERT(!before_record || bitmap_is_set_all(table->read_set)); - MY_BITMAP *old_rpl_write_set= table->rpl_write_set; - table->rpl_write_set= &table->s->all_set; - - table->online_alter_cache->store_prev_position(); - int error= (*log_func)(thd, table, table->s->online_alter_binlog, - table->online_alter_cache, - table->file->has_transactions_and_rollback(), - BINLOG_ROW_IMAGE_FULL, - before_record, after_record); - - table->rpl_write_set= old_rpl_write_set; - - if (unlikely(error)) - { - table->online_alter_cache->restore_prev_position(); - return HA_ERR_RBR_LOGGING_FAILED; - } - - return 0; -} - -static void -binlog_online_alter_cleanup(ilist &list, bool ending_trans) -{ - if (ending_trans) - { - auto it= list.begin(); - while (it != list.end()) - { - auto &cache= *it++; - cache.sink_log->release(); - cache.reset(); - delete &cache; - } - list.clear(); - DBUG_ASSERT(list.empty()); - } -} -#endif // HAVE_REPLICATION /** This function is called once after each statement. @@ -6433,54 +6138,6 @@ write_err: } -#ifdef HAVE_REPLICATION -static online_alter_cache_data * -online_alter_binlog_setup_cache_data(MEM_ROOT *root, TABLE_SHARE *share) -{ - static ulong online_alter_cache_use= 0, online_alter_cache_disk_use= 0; - - auto cache= new (root) online_alter_cache_data(); - if (!cache || open_cached_file(&cache->cache_log, mysql_tmpdir, - LOG_PREFIX, (size_t)binlog_cache_size, MYF(MY_WME))) - { - delete cache; - return NULL; - } - - share->online_alter_binlog->acquire(); - cache->hton= share->db_type(); - cache->sink_log= share->online_alter_binlog; - - my_off_t binlog_max_size= SIZE_T_MAX; // maximum possible cache size - DBUG_EXECUTE_IF("online_alter_small_cache", binlog_max_size= 4096;); - - cache->set_binlog_cache_info(binlog_max_size, - &online_alter_cache_use, - &online_alter_cache_disk_use); - cache->store_prev_position(); - return cache; -} - - -online_alter_cache_data *online_alter_binlog_get_cache_data(THD *thd, TABLE *table) -{ - ilist &list= thd->online_alter_cache_list; - - /* we assume it's very rare to have more than one online ALTER running */ - for (auto &cache: list) - { - if (cache.sink_log == table->s->online_alter_binlog) - return &cache; - } - - MEM_ROOT *root= &thd->transaction->mem_root; - auto *new_cache_data= online_alter_binlog_setup_cache_data(root, table->s); - list.push_back(*new_cache_data); - - return new_cache_data; -} -#endif - binlog_cache_mngr *THD::binlog_get_cache_mngr() const { return (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton); @@ -7737,129 +7394,6 @@ private: bool first; }; -static int binlog_online_alter_end_trans(THD *thd, bool all, bool commit) -{ - DBUG_ENTER("binlog_online_alter_end_trans"); - int error= 0; -#ifdef HAVE_REPLICATION - if (thd->online_alter_cache_list.empty()) - DBUG_RETURN(0); - - bool is_ending_transaction= ending_trans(thd, all); - - for (auto &cache: thd->online_alter_cache_list) - { - auto *binlog= cache.sink_log; - DBUG_ASSERT(binlog); - bool non_trans= cache.hton->flags & HTON_NO_ROLLBACK // Aria - || !cache.hton->rollback; - bool do_commit= (commit && is_ending_transaction) || non_trans; - - if (commit || non_trans) - { - // Do not set STMT_END for last event to leave table open in altering thd - error= binlog_flush_pending_rows_event(thd, false, true, binlog, &cache); - } - - if (do_commit) - { - /* - If the cache wasn't reinited to write, then it remains empty after - the last write. - */ - if (my_b_bytes_in_cache(&cache.cache_log) && likely(!error)) - { - DBUG_ASSERT(cache.cache_log.type != READ_CACHE); - mysql_mutex_lock(binlog->get_log_lock()); - error= binlog->write_cache_raw(thd, &cache.cache_log); - mysql_mutex_unlock(binlog->get_log_lock()); - } - } - else if (!commit) // rollback - { - DBUG_ASSERT(!non_trans); - cache.restore_prev_position(); - } - else - { - DBUG_ASSERT(!is_ending_transaction); - cache.store_prev_position(); - } - - - if (error) - { - my_error(ER_ERROR_ON_WRITE, MYF(ME_ERROR_LOG), - binlog->get_name(), errno); - binlog_online_alter_cleanup(thd->online_alter_cache_list, - is_ending_transaction); - DBUG_RETURN(error); - } - } - - binlog_online_alter_cleanup(thd->online_alter_cache_list, - is_ending_transaction); - - for (TABLE *table= thd->open_tables; table; table= table->next) - table->online_alter_cache= NULL; -#endif // HAVE_REPLICATION - DBUG_RETURN(error); -} - -SAVEPOINT** find_savepoint_in_list(THD *thd, LEX_CSTRING name, - SAVEPOINT ** const list); - -SAVEPOINT* savepoint_add(THD *thd, LEX_CSTRING name, SAVEPOINT **list, - int (*release_old)(THD*, SAVEPOINT*)); - -int online_alter_savepoint_set(THD *thd, LEX_CSTRING name) -{ - - DBUG_ENTER("binlog_online_alter_savepoint"); -#ifdef HAVE_REPLICATION - if (thd->online_alter_cache_list.empty()) - DBUG_RETURN(0); - - if (savepoint_alloc_size < sizeof (SAVEPOINT) + sizeof(my_off_t)) - savepoint_alloc_size= sizeof (SAVEPOINT) + sizeof(my_off_t); - - for (auto &cache: thd->online_alter_cache_list) - { - if (cache.hton->savepoint_set == NULL) - continue; - - SAVEPOINT *sv= savepoint_add(thd, name, &cache.sv_list, NULL); - if(unlikely(sv == NULL)) - DBUG_RETURN(1); - my_off_t *pos= (my_off_t*)(sv+1); - *pos= cache.get_byte_position(); - - sv->prev= cache.sv_list; - cache.sv_list= sv; - } -#endif - DBUG_RETURN(0); -} - -int online_alter_savepoint_rollback(THD *thd, LEX_CSTRING name) -{ - DBUG_ENTER("online_alter_savepoint_rollback"); -#ifdef HAVE_REPLICATION - for (auto &cache: thd->online_alter_cache_list) - { - if (cache.hton->savepoint_set == NULL) - continue; - - SAVEPOINT **sv= find_savepoint_in_list(thd, name, &cache.sv_list); - // sv is null if savepoint was set up before online table was modified - my_off_t pos= *sv ? *(my_off_t*)(*sv+1) : 0; - - cache.restore_savepoint(pos); - } - -#endif - DBUG_RETURN(0); -} int Event_log::write_cache_raw(THD *thd, IO_CACHE *cache) { @@ -12528,61 +12062,3 @@ void wsrep_register_binlog_handler(THD *thd, bool trx) } #endif /* WITH_WSREP */ - -static int online_alter_close_connection(handlerton *hton, THD *thd) -{ - DBUG_ASSERT(thd->online_alter_cache_list.empty()); - return 0; -} - -handlerton *online_alter_hton; - -int online_alter_log_init(void *p) -{ - online_alter_hton= (handlerton *)p; - online_alter_hton->db_type= DB_TYPE_ONLINE_ALTER; - online_alter_hton->savepoint_offset= sizeof(my_off_t); - online_alter_hton->close_connection= online_alter_close_connection; - - online_alter_hton->savepoint_set= // Done by online_alter_savepoint_set - [](handlerton *, THD *, void *){ return 0; }; - online_alter_hton->savepoint_rollback= // Done by online_alter_savepoint_rollback - [](handlerton *, THD *, void *){ return 0; }; - online_alter_hton->savepoint_rollback_can_release_mdl= - [](handlerton *hton, THD *thd){ return true; }; - - online_alter_hton->commit= [](handlerton *, THD *thd, bool all) - { return binlog_online_alter_end_trans(thd, all, true); }; - online_alter_hton->rollback= [](handlerton *, THD *thd, bool all) - { return binlog_online_alter_end_trans(thd, all, false); }; - online_alter_hton->commit_by_xid= [](handlerton *hton, XID *xid) - { return binlog_online_alter_end_trans(current_thd, true, true); }; - online_alter_hton->rollback_by_xid= [](handlerton *hton, XID *xid) - { return binlog_online_alter_end_trans(current_thd, true, false); }; - - online_alter_hton->drop_table= [](handlerton *, const char*) { return -1; }; - online_alter_hton->flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN - | HTON_NO_ROLLBACK; - return 0; -} - -struct st_mysql_storage_engine online_alter_storage_engine= -{ MYSQL_HANDLERTON_INTERFACE_VERSION }; - -maria_declare_plugin(online_alter_log) -{ - MYSQL_STORAGE_ENGINE_PLUGIN, - &online_alter_storage_engine, - "online_alter_log", - "MariaDB PLC", - "This is a pseudo storage engine to represent the online alter log in a transaction", - PLUGIN_LICENSE_GPL, - online_alter_log_init, - NULL, - 0x0100, // 1.0 - NULL, // no status vars - NULL, // no sysvars - "1.0", - MariaDB_PLUGIN_MATURITY_STABLE -} -maria_declare_plugin_end; diff --git a/sql/log.h b/sql/log.h index f617f23911e..eb5c42d1bf2 100644 --- a/sql/log.h +++ b/sql/log.h @@ -1343,15 +1343,13 @@ int binlog_flush_pending_rows_event(THD *thd, bool stmt_end, binlog_cache_data *cache_data); Rows_log_event* binlog_get_pending_rows_event(binlog_cache_mngr *cache_mngr, bool use_trans_cache); -int binlog_log_row_online_alter(TABLE* table, const uchar *before_record, - const uchar *after_record, Log_func *log_func); -online_alter_cache_data *online_alter_binlog_get_cache_data(THD *thd, TABLE *table); +int online_alter_log_row(TABLE* table, const uchar *before_record, + const uchar *after_record, Log_func *log_func); binlog_cache_data* binlog_get_cache_data(binlog_cache_mngr *cache_mngr, bool use_trans_cache); extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log; extern handlerton *binlog_hton; -extern handlerton *online_alter_hton; extern LOGGER logger; extern const char *log_bin_index; diff --git a/sql/log_cache.h b/sql/log_cache.h new file mode 100644 index 00000000000..31342768942 --- /dev/null +++ b/sql/log_cache.h @@ -0,0 +1,247 @@ +/* + Copyright (c) 2023, MariaDB plc + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "log_event.h" + +static constexpr my_off_t MY_OFF_T_UNDEF= ~0ULL; +/** Truncate cache log files bigger than this */ +static constexpr my_off_t CACHE_FILE_TRUNC_SIZE = 65536; + + +class binlog_cache_data +{ +public: + binlog_cache_data(): before_stmt_pos(MY_OFF_T_UNDEF), m_pending(0), status(0), + incident(FALSE), saved_max_binlog_cache_size(0), ptr_binlog_cache_use(0), + ptr_binlog_cache_disk_use(0) + { } + + ~binlog_cache_data() + { + DBUG_ASSERT(empty()); + close_cached_file(&cache_log); + } + + /* + Return 1 if there is no relevant entries in the cache + + This is: + - Cache is empty + - There are row or critical (DDL?) events in the cache + + The status test is needed to avoid writing entries with only + a table map entry, which would crash in do_apply_event() on the slave + as it assumes that there is always a row entry after a table map. + */ + bool empty() const + { + return (pending() == NULL && + (my_b_write_tell(&cache_log) == 0 || + ((status & (LOGGED_ROW_EVENT | LOGGED_CRITICAL)) == 0))); + } + + Rows_log_event *pending() const + { + return m_pending; + } + + void set_pending(Rows_log_event *const pending_arg) + { + m_pending= pending_arg; + } + + void set_incident(void) + { + incident= TRUE; + } + + bool has_incident(void) const + { + return(incident); + } + + void reset() + { + bool cache_was_empty= empty(); + bool truncate_file= (cache_log.file != -1 && + my_b_write_tell(&cache_log) > CACHE_FILE_TRUNC_SIZE); + truncate(0,1); // Forget what's in cache + if (!cache_was_empty) + compute_statistics(); + if (truncate_file) + my_chsize(cache_log.file, 0, 0, MYF(MY_WME)); + + status= 0; + incident= FALSE; + before_stmt_pos= MY_OFF_T_UNDEF; + DBUG_ASSERT(empty()); + } + + my_off_t get_byte_position() const + { + return my_b_tell(&cache_log); + } + + my_off_t get_prev_position() const + { + return(before_stmt_pos); + } + + void set_prev_position(my_off_t pos) + { + before_stmt_pos= pos; + } + + void restore_prev_position() + { + truncate(before_stmt_pos); + } + + void restore_savepoint(my_off_t pos) + { + truncate(pos); + if (pos < before_stmt_pos) + before_stmt_pos= MY_OFF_T_UNDEF; + } + + void set_binlog_cache_info(my_off_t param_max_binlog_cache_size, + ulong *param_ptr_binlog_cache_use, + ulong *param_ptr_binlog_cache_disk_use) + { + /* + The assertions guarantee that the set_binlog_cache_info is + called just once and information passed as parameters are + never zero. + + This is done while calling the constructor binlog_cache_mngr. + We cannot set information in the constructor binlog_cache_data + because the space for binlog_cache_mngr is allocated through + a placement new. + + In the future, we can refactor this and change it to avoid + the set_binlog_info. + */ + DBUG_ASSERT(saved_max_binlog_cache_size == 0); + DBUG_ASSERT(param_max_binlog_cache_size != 0); + DBUG_ASSERT(ptr_binlog_cache_use == 0); + DBUG_ASSERT(param_ptr_binlog_cache_use != 0); + DBUG_ASSERT(ptr_binlog_cache_disk_use == 0); + DBUG_ASSERT(param_ptr_binlog_cache_disk_use != 0); + + saved_max_binlog_cache_size= param_max_binlog_cache_size; + ptr_binlog_cache_use= param_ptr_binlog_cache_use; + ptr_binlog_cache_disk_use= param_ptr_binlog_cache_disk_use; + cache_log.end_of_file= saved_max_binlog_cache_size; + } + + void add_status(enum_logged_status status_arg) + { + status|= status_arg; + } + + /* + Cache to store data before copying it to the binary log. + */ + IO_CACHE cache_log; + +protected: + /* + Binlog position before the start of the current statement. + */ + my_off_t before_stmt_pos; + +private: + /* + Pending binrows event. This event is the event where the rows are currently + written. + */ + Rows_log_event *m_pending; + + /* + Bit flags for what has been writing to cache. Used to + discard logs without any data changes. + see enum_logged_status; + */ + uint32 status; + + /* + This indicates that some events did not get into the cache and most likely + it is corrupted. + */ + bool incident; + + /** + This function computes binlog cache and disk usage. + */ + void compute_statistics() + { + statistic_increment(*ptr_binlog_cache_use, &LOCK_status); + if (cache_log.disk_writes != 0) + { +#ifdef REAL_STATISTICS + statistic_add(*ptr_binlog_cache_disk_use, + cache_log.disk_writes, &LOCK_status); +#else + statistic_increment(*ptr_binlog_cache_disk_use, &LOCK_status); +#endif + cache_log.disk_writes= 0; + } + } + + /* + Stores the values of maximum size of the cache allowed when this cache + is configured. This corresponds to either + . max_binlog_cache_size or max_binlog_stmt_cache_size. + */ + my_off_t saved_max_binlog_cache_size; + + /* + Stores a pointer to the status variable that keeps track of the in-memory + cache usage. This corresponds to either + . binlog_cache_use or binlog_stmt_cache_use. + */ + ulong *ptr_binlog_cache_use; + + /* + Stores a pointer to the status variable that keeps track of the disk + cache usage. This corresponds to either + . binlog_cache_disk_use or binlog_stmt_cache_disk_use. + */ + ulong *ptr_binlog_cache_disk_use; + + /* + It truncates the cache to a certain position. This includes deleting the + pending event. + */ + void truncate(my_off_t pos, bool reset_cache=0) + { + DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos)); + cache_log.error=0; + if (pending()) + { + delete pending(); + set_pending(0); + } + my_bool res= reinit_io_cache(&cache_log, WRITE_CACHE, pos, 0, reset_cache); + DBUG_ASSERT(res == 0); + cache_log.end_of_file= saved_max_binlog_cache_size; + } + + binlog_cache_data& operator=(const binlog_cache_data& info); + binlog_cache_data(const binlog_cache_data& info); +}; diff --git a/sql/online_alter.cc b/sql/online_alter.cc new file mode 100644 index 00000000000..ac4eb23a981 --- /dev/null +++ b/sql/online_alter.cc @@ -0,0 +1,320 @@ +/* + Copyright (c) 2023, MariaDB plc + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "my_global.h" +#include "handler.h" +#include "sql_class.h" +#include "log_cache.h" + + +static handlerton *online_alter_hton; + + +class online_alter_cache_data: public Sql_alloc, public ilist_node<>, + public binlog_cache_data +{ +public: + void store_prev_position() + { + before_stmt_pos= my_b_write_tell(&cache_log); + } + + handlerton *hton; + Cache_flip_event_log *sink_log; + SAVEPOINT *sv_list; +}; + + +static +online_alter_cache_data *setup_cache_data(MEM_ROOT *root, TABLE_SHARE *share) +{ + static ulong online_alter_cache_use= 0, online_alter_cache_disk_use= 0; + + auto cache= new (root) online_alter_cache_data(); + if (!cache || open_cached_file(&cache->cache_log, mysql_tmpdir, LOG_PREFIX, + (size_t)binlog_cache_size, MYF(MY_WME))) + { + delete cache; + return NULL; + } + + share->online_alter_binlog->acquire(); + cache->hton= share->db_type(); + cache->sink_log= share->online_alter_binlog; + + my_off_t binlog_max_size= SIZE_T_MAX; // maximum possible cache size + DBUG_EXECUTE_IF("online_alter_small_cache", binlog_max_size= 4096;); + + cache->set_binlog_cache_info(binlog_max_size, + &online_alter_cache_use, + &online_alter_cache_disk_use); + cache->store_prev_position(); + return cache; +} + + +static online_alter_cache_data *get_cache_data(THD *thd, TABLE *table) +{ + ilist &list= thd->online_alter_cache_list; + + /* we assume it's very rare to have more than one online ALTER running */ + for (auto &cache: list) + { + if (cache.sink_log == table->s->online_alter_binlog) + return &cache; + } + + MEM_ROOT *root= &thd->transaction->mem_root; + auto *new_cache_data= setup_cache_data(root, table->s); + list.push_back(*new_cache_data); + + return new_cache_data; +} + + +int online_alter_log_row(TABLE* table, const uchar *before_record, + const uchar *after_record, Log_func *log_func) +{ + THD *thd= table->in_use; + + if (!table->online_alter_cache) + { + table->online_alter_cache= get_cache_data(thd, table); + trans_register_ha(thd, false, online_alter_hton, 0); + if (thd->in_multi_stmt_transaction_mode()) + trans_register_ha(thd, true, online_alter_hton, 0); + } + + // We need to log all columns for the case if alter table changes primary key + DBUG_ASSERT(!before_record || bitmap_is_set_all(table->read_set)); + MY_BITMAP *old_rpl_write_set= table->rpl_write_set; + table->rpl_write_set= &table->s->all_set; + + table->online_alter_cache->store_prev_position(); + int error= (*log_func)(thd, table, table->s->online_alter_binlog, + table->online_alter_cache, + table->file->has_transactions_and_rollback(), + BINLOG_ROW_IMAGE_FULL, + before_record, after_record); + + table->rpl_write_set= old_rpl_write_set; + + if (unlikely(error)) + { + table->online_alter_cache->restore_prev_position(); + return HA_ERR_RBR_LOGGING_FAILED; + } + + return 0; +} + + +static void +cleanup_cache_list(ilist &list, bool ending_trans) +{ + if (ending_trans) + { + auto it= list.begin(); + while (it != list.end()) + { + auto &cache= *it++; + cache.sink_log->release(); + cache.reset(); + delete &cache; + } + list.clear(); + DBUG_ASSERT(list.empty()); + } +} + + +static +int online_alter_end_trans(handlerton *hton, THD *thd, bool all, bool commit) +{ + DBUG_ENTER("online_alter_end_trans"); + int error= 0; + if (thd->online_alter_cache_list.empty()) + DBUG_RETURN(0); + + bool is_ending_transaction= ending_trans(thd, all); + + for (auto &cache: thd->online_alter_cache_list) + { + auto *binlog= cache.sink_log; + DBUG_ASSERT(binlog); + bool non_trans= cache.hton->flags & HTON_NO_ROLLBACK // Aria + || !cache.hton->rollback; + bool do_commit= (commit && is_ending_transaction) || non_trans; + + if (commit || non_trans) + { + // Do not set STMT_END for last event to leave table open in altering thd + error= binlog_flush_pending_rows_event(thd, false, true, binlog, &cache); + } + + if (do_commit) + { + /* + If the cache wasn't reinited to write, then it remains empty after + the last write. + */ + if (my_b_bytes_in_cache(&cache.cache_log) && likely(!error)) + { + DBUG_ASSERT(cache.cache_log.type != READ_CACHE); + mysql_mutex_lock(binlog->get_log_lock()); + error= binlog->write_cache_raw(thd, &cache.cache_log); + mysql_mutex_unlock(binlog->get_log_lock()); + } + } + else if (!commit) // rollback + { + DBUG_ASSERT(!non_trans); + cache.restore_prev_position(); + } + else + { + DBUG_ASSERT(!is_ending_transaction); + cache.store_prev_position(); + } + + + if (error) + { + my_error(ER_ERROR_ON_WRITE, MYF(ME_ERROR_LOG), + binlog->get_name(), errno); + cleanup_cache_list(thd->online_alter_cache_list, + is_ending_transaction); + DBUG_RETURN(error); + } + } + + cleanup_cache_list(thd->online_alter_cache_list, + is_ending_transaction); + + for (TABLE *table= thd->open_tables; table; table= table->next) + table->online_alter_cache= NULL; + DBUG_RETURN(error); +} + +SAVEPOINT** find_savepoint_in_list(THD *thd, LEX_CSTRING name, + SAVEPOINT ** const list); + +SAVEPOINT* savepoint_add(THD *thd, LEX_CSTRING name, SAVEPOINT **list, + int (*release_old)(THD*, SAVEPOINT*)); + +int online_alter_savepoint_set(THD *thd, LEX_CSTRING name) +{ + DBUG_ENTER("binlog_online_alter_savepoint"); + if (thd->online_alter_cache_list.empty()) + DBUG_RETURN(0); + + if (savepoint_alloc_size < sizeof (SAVEPOINT) + sizeof(my_off_t)) + savepoint_alloc_size= sizeof (SAVEPOINT) + sizeof(my_off_t); + + for (auto &cache: thd->online_alter_cache_list) + { + if (cache.hton->savepoint_set == NULL) + continue; + + SAVEPOINT *sv= savepoint_add(thd, name, &cache.sv_list, NULL); + if(unlikely(sv == NULL)) + DBUG_RETURN(1); + my_off_t *pos= (my_off_t*)(sv+1); + *pos= cache.get_byte_position(); + + sv->prev= cache.sv_list; + cache.sv_list= sv; + } + DBUG_RETURN(0); +} + +int online_alter_savepoint_rollback(THD *thd, LEX_CSTRING name) +{ + DBUG_ENTER("online_alter_savepoint_rollback"); + for (auto &cache: thd->online_alter_cache_list) + { + if (cache.hton->savepoint_set == NULL) + continue; + + SAVEPOINT **sv= find_savepoint_in_list(thd, name, &cache.sv_list); + // sv is null if savepoint was set up before online table was modified + my_off_t pos= *sv ? *(my_off_t*)(*sv+1) : 0; + + cache.restore_savepoint(pos); + } + + DBUG_RETURN(0); +} + + +static int online_alter_close_connection(handlerton *hton, THD *thd) +{ + DBUG_ASSERT(thd->online_alter_cache_list.empty()); + return 0; +} + + +static int online_alter_log_init(void *p) +{ + online_alter_hton= (handlerton *)p; + online_alter_hton->db_type= DB_TYPE_ONLINE_ALTER; + online_alter_hton->savepoint_offset= sizeof(my_off_t); + online_alter_hton->close_connection= online_alter_close_connection; + + online_alter_hton->savepoint_set= // Done by online_alter_savepoint_set + [](handlerton *, THD *, void *){ return 0; }; + online_alter_hton->savepoint_rollback= // Done by online_alter_savepoint_rollback + [](handlerton *, THD *, void *){ return 0; }; + online_alter_hton->savepoint_rollback_can_release_mdl= + [](handlerton *hton, THD *thd){ return true; }; + + online_alter_hton->commit= [](handlerton *hton, THD *thd, bool all) + { return online_alter_end_trans(hton, thd, all, true); }; + online_alter_hton->rollback= [](handlerton *hton, THD *thd, bool all) + { return online_alter_end_trans(hton, thd, all, false); }; + online_alter_hton->commit_by_xid= [](handlerton *hton, XID *xid) + { return online_alter_end_trans(hton, current_thd, true, true); }; + online_alter_hton->rollback_by_xid= [](handlerton *hton, XID *xid) + { return online_alter_end_trans(hton, current_thd, true, false); }; + + online_alter_hton->drop_table= [](handlerton *, const char*) { return -1; }; + online_alter_hton->flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN + | HTON_NO_ROLLBACK; + return 0; +} + +struct st_mysql_storage_engine online_alter_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION }; + +maria_declare_plugin(online_alter_log) +{ + MYSQL_STORAGE_ENGINE_PLUGIN, + &online_alter_storage_engine, + "online_alter_log", + "MariaDB PLC", + "A pseudo storage engine for the online alter log", + PLUGIN_LICENSE_GPL, + online_alter_log_init, + NULL, + 0x0100, // 1.0 + NULL, // no status vars + NULL, // no sysvars + "1.0", + MariaDB_PLUGIN_MATURITY_STABLE +} +maria_declare_plugin_end; From 8311eae6013f66be85b117cee7c035320e314969 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Fri, 22 Sep 2023 19:27:23 +0400 Subject: [PATCH 178/477] online alter: use thd->ha_data to store cache_list --- sql/online_alter.cc | 54 +++++++++++++++++++++++++++++++++------------ sql/sql_class.h | 2 -- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/sql/online_alter.cc b/sql/online_alter.cc index ac4eb23a981..ac0316cdf59 100644 --- a/sql/online_alter.cc +++ b/sql/online_alter.cc @@ -24,6 +24,7 @@ static handlerton *online_alter_hton; +typedef ilist Online_alter_cache_list; class online_alter_cache_data: public Sql_alloc, public ilist_node<>, public binlog_cache_data @@ -68,12 +69,31 @@ online_alter_cache_data *setup_cache_data(MEM_ROOT *root, TABLE_SHARE *share) } -static online_alter_cache_data *get_cache_data(THD *thd, TABLE *table) +static Online_alter_cache_list &get_cache_list(handlerton *ht, THD *thd) { - ilist &list= thd->online_alter_cache_list; + void *data= thd_get_ha_data(thd, ht); + DBUG_ASSERT(data); + return *(Online_alter_cache_list*)data; +} + +static Online_alter_cache_list &get_or_create_cache_list(THD *thd) +{ + void *data= thd_get_ha_data(thd, online_alter_hton); + if (!data) + { + data= new Online_alter_cache_list(); + thd_set_ha_data(thd, online_alter_hton, data); + } + return *(Online_alter_cache_list*)data; +} + + +static online_alter_cache_data* get_cache_data(THD *thd, TABLE *table) +{ + auto &cache_list= get_or_create_cache_list(thd); /* we assume it's very rare to have more than one online ALTER running */ - for (auto &cache: list) + for (auto &cache: cache_list) { if (cache.sink_log == table->s->online_alter_binlog) return &cache; @@ -81,7 +101,7 @@ static online_alter_cache_data *get_cache_data(THD *thd, TABLE *table) MEM_ROOT *root= &thd->transaction->mem_root; auto *new_cache_data= setup_cache_data(root, table->s); - list.push_back(*new_cache_data); + cache_list.push_back(*new_cache_data); return new_cache_data; } @@ -148,12 +168,13 @@ int online_alter_end_trans(handlerton *hton, THD *thd, bool all, bool commit) { DBUG_ENTER("online_alter_end_trans"); int error= 0; - if (thd->online_alter_cache_list.empty()) + auto &cache_list= get_cache_list(hton, thd); + if (cache_list.empty()) DBUG_RETURN(0); bool is_ending_transaction= ending_trans(thd, all); - for (auto &cache: thd->online_alter_cache_list) + for (auto &cache: cache_list) { auto *binlog= cache.sink_log; DBUG_ASSERT(binlog); @@ -197,14 +218,12 @@ int online_alter_end_trans(handlerton *hton, THD *thd, bool all, bool commit) { my_error(ER_ERROR_ON_WRITE, MYF(ME_ERROR_LOG), binlog->get_name(), errno); - cleanup_cache_list(thd->online_alter_cache_list, - is_ending_transaction); + cleanup_cache_list(cache_list, is_ending_transaction); DBUG_RETURN(error); } } - cleanup_cache_list(thd->online_alter_cache_list, - is_ending_transaction); + cleanup_cache_list(cache_list, is_ending_transaction); for (TABLE *table= thd->open_tables; table; table= table->next) table->online_alter_cache= NULL; @@ -220,13 +239,14 @@ SAVEPOINT* savepoint_add(THD *thd, LEX_CSTRING name, SAVEPOINT **list, int online_alter_savepoint_set(THD *thd, LEX_CSTRING name) { DBUG_ENTER("binlog_online_alter_savepoint"); - if (thd->online_alter_cache_list.empty()) + auto &cache_list= get_cache_list(online_alter_hton, thd); + if (cache_list.empty()) DBUG_RETURN(0); if (savepoint_alloc_size < sizeof (SAVEPOINT) + sizeof(my_off_t)) savepoint_alloc_size= sizeof (SAVEPOINT) + sizeof(my_off_t); - for (auto &cache: thd->online_alter_cache_list) + for (auto &cache: cache_list) { if (cache.hton->savepoint_set == NULL) continue; @@ -246,7 +266,9 @@ int online_alter_savepoint_set(THD *thd, LEX_CSTRING name) int online_alter_savepoint_rollback(THD *thd, LEX_CSTRING name) { DBUG_ENTER("online_alter_savepoint_rollback"); - for (auto &cache: thd->online_alter_cache_list) + + auto &cache_list= get_cache_list(online_alter_hton, thd); + for (auto &cache: cache_list) { if (cache.hton->savepoint_set == NULL) continue; @@ -264,7 +286,11 @@ int online_alter_savepoint_rollback(THD *thd, LEX_CSTRING name) static int online_alter_close_connection(handlerton *hton, THD *thd) { - DBUG_ASSERT(thd->online_alter_cache_list.empty()); + auto *cache_list= (Online_alter_cache_list*)thd_get_ha_data(thd, hton); + + DBUG_ASSERT(!cache_list || cache_list->empty()); + delete cache_list; + thd_set_ha_data(thd, hton, NULL); return 0; } diff --git a/sql/sql_class.h b/sql/sql_class.h index d056054f28f..2e0b630ca67 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5634,8 +5634,6 @@ public: Item *sp_prepare_func_item(Item **it_addr, uint cols); bool sp_eval_expr(Field *result_field, Item **expr_item_ptr); - ilist online_alter_cache_list; - bool sql_parser(LEX *old_lex, LEX *lex, char *str, uint str_len, bool stmt_prepare_mode); From a569515a9d808ad82cac891964b27a9609866574 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Fri, 22 Sep 2023 20:16:32 +0400 Subject: [PATCH 179/477] online alter: rework savepoints Use standard handlerton functions for savepoint add/rollback. To identify the savepoint, the pointer passed is used. Every table that has online alter in progress maintains a list of savepoints independently. Also this removes setting a value to a global variable savepoint_alloc_size without any protection, which was a race condition bug. --- sql/log.cc | 6 ---- sql/log.h | 4 --- sql/online_alter.cc | 81 +++++++++++++++++++++++++++++---------------- sql/transaction.cc | 6 ---- 4 files changed, 53 insertions(+), 44 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index aa71631155b..9d47c173b35 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2348,9 +2348,6 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv) int error= 1; DBUG_ENTER("binlog_savepoint_set"); - if (!mysql_bin_log.is_open() && !thd->online_alter_cache_list.empty()) - DBUG_RETURN(0); - char buf[1024]; String log_query(buf, sizeof(buf), &my_charset_bin); @@ -2383,9 +2380,6 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv) { DBUG_ENTER("binlog_savepoint_rollback"); - if (!mysql_bin_log.is_open() && !thd->online_alter_cache_list.empty()) - DBUG_RETURN(0); - /* Write ROLLBACK TO SAVEPOINT to the binlog cache if we have updated some non-transactional table. Otherwise, truncate the binlog cache starting diff --git a/sql/log.h b/sql/log.h index eb5c42d1bf2..f6340623684 100644 --- a/sql/log.h +++ b/sql/log.h @@ -1438,8 +1438,4 @@ int binlog_commit_by_xid(handlerton *hton, XID *xid); int binlog_rollback_by_xid(handlerton *hton, XID *xid); bool write_bin_log_start_alter(THD *thd, bool& partial_alter, uint64 start_alter_id, bool log_if_exists); - -int online_alter_savepoint_set(THD *thd, LEX_CSTRING name); -int online_alter_savepoint_rollback(THD *thd, LEX_CSTRING name); - #endif /* LOG_H */ diff --git a/sql/online_alter.cc b/sql/online_alter.cc index ac0316cdf59..8b8c81319d1 100644 --- a/sql/online_alter.cc +++ b/sql/online_alter.cc @@ -24,7 +24,19 @@ static handlerton *online_alter_hton; -typedef ilist Online_alter_cache_list; +typedef void *sv_id_t; + +struct Online_alter_cache_list: ilist +{ + sv_id_t savepoint_id= 0; +}; + +struct table_savepoint: ilist_node<> +{ + sv_id_t id; + my_off_t log_prev_pos; + table_savepoint(sv_id_t id, my_off_t pos): id(id), log_prev_pos(pos){} +}; class online_alter_cache_data: public Sql_alloc, public ilist_node<>, public binlog_cache_data @@ -37,7 +49,32 @@ public: handlerton *hton; Cache_flip_event_log *sink_log; - SAVEPOINT *sv_list; + ilist sv_list; + /** + Finds savepoint with specified id and returns its associated data. + Cleans up all the savepoints up to the found one. + */ + my_off_t pop_sv_until(sv_id_t id) + { + my_off_t pos= 0; + auto it= sv_list.begin(); + auto sentinel= it->prev; + while (pos == 0 && it != sv_list.end()) + { + table_savepoint &sv= *it; + ++it; + if (sv.id == id) + pos= sv.log_prev_pos; + delete &sv; + } + sentinel->next= &*it; // drop the range from the list + it->prev= sentinel; + return pos; + } + void cleanup_sv() + { + pop_sv_until((sv_id_t)1); // Erase the whole list + } }; @@ -155,6 +192,7 @@ cleanup_cache_list(ilist &list, bool ending_trans) auto &cache= *it++; cache.sink_log->release(); cache.reset(); + cache.cleanup_sv(); delete &cache; } list.clear(); @@ -230,52 +268,41 @@ int online_alter_end_trans(handlerton *hton, THD *thd, bool all, bool commit) DBUG_RETURN(error); } -SAVEPOINT** find_savepoint_in_list(THD *thd, LEX_CSTRING name, - SAVEPOINT ** const list); -SAVEPOINT* savepoint_add(THD *thd, LEX_CSTRING name, SAVEPOINT **list, - int (*release_old)(THD*, SAVEPOINT*)); - -int online_alter_savepoint_set(THD *thd, LEX_CSTRING name) +int online_alter_savepoint_set(handlerton *hton, THD *thd, sv_id_t sv_id) { DBUG_ENTER("binlog_online_alter_savepoint"); - auto &cache_list= get_cache_list(online_alter_hton, thd); + auto &cache_list= get_cache_list(hton, thd); if (cache_list.empty()) DBUG_RETURN(0); - if (savepoint_alloc_size < sizeof (SAVEPOINT) + sizeof(my_off_t)) - savepoint_alloc_size= sizeof (SAVEPOINT) + sizeof(my_off_t); - for (auto &cache: cache_list) { if (cache.hton->savepoint_set == NULL) continue; - SAVEPOINT *sv= savepoint_add(thd, name, &cache.sv_list, NULL); + auto *sv= new table_savepoint(sv_id, cache.get_byte_position()); if(unlikely(sv == NULL)) DBUG_RETURN(1); - my_off_t *pos= (my_off_t*)(sv+1); - *pos= cache.get_byte_position(); - - sv->prev= cache.sv_list; - cache.sv_list= sv; + cache.sv_list.push_front(*sv); } DBUG_RETURN(0); } -int online_alter_savepoint_rollback(THD *thd, LEX_CSTRING name) + +int online_alter_savepoint_rollback(handlerton *hton, THD *thd, sv_id_t sv_id) { DBUG_ENTER("online_alter_savepoint_rollback"); - auto &cache_list= get_cache_list(online_alter_hton, thd); + auto &cache_list= get_cache_list(hton, thd); for (auto &cache: cache_list) { if (cache.hton->savepoint_set == NULL) continue; - SAVEPOINT **sv= find_savepoint_in_list(thd, name, &cache.sv_list); - // sv is null if savepoint was set up before online table was modified - my_off_t pos= *sv ? *(my_off_t*)(*sv+1) : 0; + // There's no savepoint if it was set up before online table was modified. + // In that case, restore to 0. + my_off_t pos= cache.pop_sv_until(sv_id); cache.restore_savepoint(pos); } @@ -299,13 +326,11 @@ static int online_alter_log_init(void *p) { online_alter_hton= (handlerton *)p; online_alter_hton->db_type= DB_TYPE_ONLINE_ALTER; - online_alter_hton->savepoint_offset= sizeof(my_off_t); + online_alter_hton->savepoint_offset= 0; online_alter_hton->close_connection= online_alter_close_connection; - online_alter_hton->savepoint_set= // Done by online_alter_savepoint_set - [](handlerton *, THD *, void *){ return 0; }; - online_alter_hton->savepoint_rollback= // Done by online_alter_savepoint_rollback - [](handlerton *, THD *, void *){ return 0; }; + online_alter_hton->savepoint_set= online_alter_savepoint_set; + online_alter_hton->savepoint_rollback= online_alter_savepoint_rollback; online_alter_hton->savepoint_rollback_can_release_mdl= [](handlerton *hton, THD *thd){ return true; }; diff --git a/sql/transaction.cc b/sql/transaction.cc index 85a18410304..8f7cda065d1 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -641,10 +641,6 @@ bool trans_savepoint(THD *thd, LEX_CSTRING name) if (unlikely(ha_savepoint(thd, newsv))) DBUG_RETURN(TRUE); - int error= online_alter_savepoint_set(thd, name); - if (unlikely(error)) - DBUG_RETURN(error); - newsv->prev= thd->transaction->savepoints; thd->transaction->savepoints= newsv; @@ -704,8 +700,6 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_CSTRING name) ER_WARNING_NOT_COMPLETE_ROLLBACK, ER_THD(thd, ER_WARNING_NOT_COMPLETE_ROLLBACK)); - res= res || online_alter_savepoint_rollback(thd, name); - thd->transaction->savepoints= sv; if (res) From 9cc179cc7e88908cfe560773aa8e8a36ff46da0c Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Mon, 25 Sep 2023 20:20:47 +0530 Subject: [PATCH 180/477] MDEV-32007: JSON_VALUE and JSON_EXTRACT doesn't handle dash (-) as first character in key Analysis: While parsing the path, if '-' is encountered as a part of the key, the state of the parser changes to error. Hence NULL is returned eventually. Fix: If '-' encountered as part of the key, change the state appropriately to continue scanning the key. --- mysql-test/main/func_json.result | 21 +++++++++++++++++++++ mysql-test/main/func_json.test | 23 +++++++++++++++++++++++ strings/json_lib.c | 2 +- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index e482acada77..2ca74c41736 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -2608,3 +2608,24 @@ SET @@collation_connection= @save_collation_connection; # # End of 10.9 Test # +# +# MDEV-32007: JSON_VALUE and JSON_EXTRACT doesn't handle dash (-) +# as first character in key +# +CREATE TEMPORARY TABLE IF NOT EXISTS jsonTest AS +SELECT '{ "-1234" : "something", + "12-34" : "else", + "1234-" : "and", + "1234" : "match" }' AS 'message'; +SELECT JSON_SEARCH(message, 'one', 'something') AS t1_path, +JSON_VALUE(message, JSON_UNQUOTE(JSON_SEARCH(message, 'one', 'something'))) AS t1_result, +JSON_SEARCH(message, 'one', 'else') AS t2_path, +JSON_VALUE(message, JSON_UNQUOTE(JSON_SEARCH(message, 'one', 'else'))) AS t2_result, +JSON_SEARCH(message, 'one', 'and') AS t3_path, +JSON_VALUE(message, JSON_UNQUOTE(JSON_SEARCH(message, 'one', 'and'))) AS t3_result, +JSON_SEARCH(message, 'one', 'match') AS t4_path, +JSON_VALUE(message, JSON_UNQUOTE(JSON_SEARCH(message, 'one', 'match'))) AS t4_result +FROM jsonTest; +t1_path t1_result t2_path t2_result t3_path t3_result t4_path t4_result +"$.-1234" something "$.12-34" else "$.1234-" and "$.1234" match +# End of 11.0 test diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index d940bec74d9..d9ebd7e18be 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -1809,3 +1809,26 @@ SET @@collation_connection= @save_collation_connection; --echo # --echo # End of 10.9 Test --echo # + +--echo # +--echo # MDEV-32007: JSON_VALUE and JSON_EXTRACT doesn't handle dash (-) +--echo # as first character in key +--echo # + +CREATE TEMPORARY TABLE IF NOT EXISTS jsonTest AS + SELECT '{ "-1234" : "something", + "12-34" : "else", + "1234-" : "and", + "1234" : "match" }' AS 'message'; + +SELECT JSON_SEARCH(message, 'one', 'something') AS t1_path, + JSON_VALUE(message, JSON_UNQUOTE(JSON_SEARCH(message, 'one', 'something'))) AS t1_result, + JSON_SEARCH(message, 'one', 'else') AS t2_path, + JSON_VALUE(message, JSON_UNQUOTE(JSON_SEARCH(message, 'one', 'else'))) AS t2_result, + JSON_SEARCH(message, 'one', 'and') AS t3_path, + JSON_VALUE(message, JSON_UNQUOTE(JSON_SEARCH(message, 'one', 'and'))) AS t3_result, + JSON_SEARCH(message, 'one', 'match') AS t4_path, + JSON_VALUE(message, JSON_UNQUOTE(JSON_SEARCH(message, 'one', 'match'))) AS t4_result +FROM jsonTest; + +--echo # End of 11.0 test diff --git a/strings/json_lib.c b/strings/json_lib.c index 52c173f3604..47e0843d627 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -1093,7 +1093,7 @@ static int json_path_transitions[N_PATH_STATES][N_PATH_CLASSES]= /* AS */ { JE_EOS, JE_SYN, JE_SYN, JE_SYN, PS_T, PS_PT, JE_SYN, PS_NEG, PS_Z, PS_INT, PS_LAST, PS_AS, JE_SYN, JE_SYN, JE_SYN, JE_NOT_JSON_CHR, JE_BAD_CHR}, -/* KEY */ { JE_EOS, PS_KNM, PS_KWD, JE_SYN, PS_KNM, PS_KNM, JE_SYN, JE_SYN, +/* KEY */ { JE_EOS, PS_KNM, PS_KWD, JE_SYN, PS_KNM, PS_KNM, JE_SYN, PS_KNM, PS_KNM, PS_KNM, PS_KNM, PS_KNM, PS_KNM, JE_SYN, PS_KEYX, PS_KNM, JE_NOT_JSON_CHR, JE_BAD_CHR}, /* KNM */ { PS_KOK, PS_KNM, PS_AST, PS_EAR, PS_KNM, PS_KNM, PS_EKY, PS_KNM, From 29df46f3a829006e92a58183f5ae2952ad7ac76c Mon Sep 17 00:00:00 2001 From: Gulshan Kumar Prasad Date: Mon, 30 Oct 2023 23:39:47 +0530 Subject: [PATCH 181/477] MDEV-29101 mariabackup --help output should mention that --compress is deprecated Deprecation versions taken from https://mariadb.com/kb/en/mariabackup-options/#-compress --- extra/mariabackup/xtrabackup.cc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 64a0f44e183..220fe450ec4 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -1226,22 +1226,25 @@ struct my_option xb_client_options[]= { {"compress", OPT_XTRA_COMPRESS, "Compress individual backup files using the " - "specified compression algorithm. Currently the only supported algorithm " - "is 'quicklz'. It is also the default algorithm, i.e. the one used when " - "--compress is used without an argument.", + "specified compression algorithm. It uses no longer maintained QuickLZ " + "library hence this option was deprecated with MariaDB 10.1.31 and 10.2.13.", (G_PTR *) &xtrabackup_compress_alg, (G_PTR *) &xtrabackup_compress_alg, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"compress-threads", OPT_XTRA_COMPRESS_THREADS, "Number of threads for parallel data compression. The default value is " - "1.", + "1. " + "This option was deprecated as it relies on the no longer " + "maintained QuickLZ library.", (G_PTR *) &xtrabackup_compress_threads, (G_PTR *) &xtrabackup_compress_threads, 0, GET_UINT, REQUIRED_ARG, 1, 1, UINT_MAX, 0, 0, 0}, {"compress-chunk-size", OPT_XTRA_COMPRESS_CHUNK_SIZE, "Size of working buffer(s) for compression threads in bytes. The default " - "value is 64K.", + "value is 64K. " + "This option was deprecated as it relies on the no longer " + "maintained QuickLZ library.", (G_PTR *) &xtrabackup_compress_chunk_size, (G_PTR *) &xtrabackup_compress_chunk_size, 0, GET_ULL, REQUIRED_ARG, (1 << 16), 1024, ULONGLONG_MAX, 0, 0, 0}, @@ -1362,7 +1365,9 @@ struct my_option xb_client_options[]= { {"decompress", OPT_DECOMPRESS, "Decompresses all files with the .qp " - "extension in a backup previously made with the --compress option.", + "extension in a backup previously made with the --compress option. " + "This option was deprecated as it relies on the no longer " + "maintained QuickLZ library.", (uchar *) &opt_decompress, (uchar *) &opt_decompress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, From e6953374480d8070ee0953d982cdb71788414d00 Mon Sep 17 00:00:00 2001 From: Rex Date: Fri, 3 Nov 2023 11:49:34 +1200 Subject: [PATCH 182/477] MDEV-31995-fix short fix for memory leak introduced in MDEV-31995 list elements not correctly allocated in push_back. --- sql/sql_lex.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 65a3c44eb58..79fb86fe14b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -10448,7 +10448,7 @@ bool st_select_lex::save_item_list_names(THD *thd) while ((item= li++)) { if (unlikely(orig_names_of_item_list_elems->push_back( - new Lex_ident_sys(item->name.str, item->name.length)))) + new Lex_ident_sys(item->name.str, item->name.length), thd->mem_root))) { if (arena) thd->restore_active_arena(arena, &backup); From 167fe6646db96422de1508000d56ba72224b9b12 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Mon, 14 Aug 2023 11:45:14 +0200 Subject: [PATCH 183/477] Restore getting InnoDB position from mariabackup --no-lock Revert the patch for MDEV-18917, which removed this functionality. This restores that mariabackup --prepare recovers the transactional binlog position from the redo log, and writes it to the file xtrabackup_binlog_pos_innodb. This position is updated only on every InnoDB commit. This means that if the last event in the binlog at the time of backup is a DDL or non-transactional update, the recovered position from --no-lock will be behind the state of the backup. Signed-off-by: Kristian Nielsen --- extra/mariabackup/xtrabackup.cc | 47 +++++++++++++++++++++++++++++++-- extra/mariabackup/xtrabackup.h | 2 +- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 220fe450ec4..103aee8b64f 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -421,6 +421,9 @@ uint opt_safe_slave_backup_timeout = 0; const char *opt_history = NULL; +/* Whether xtrabackup_binlog_info should be created on recovery */ +static bool recover_binlog_info; + char mariabackup_exe[FN_REFLEN]; char orig_argv1[FN_REFLEN]; @@ -2340,6 +2343,7 @@ xtrabackup_read_metadata(char *filename) { FILE *fp; my_bool r = TRUE; + int t; fp = fopen(filename,"r"); if(!fp) { @@ -2370,6 +2374,9 @@ xtrabackup_read_metadata(char *filename) } /* Optional fields */ + if (fscanf(fp, "recover_binlog_info = %d\n", &t) == 1) { + recover_binlog_info = (t == 1); + } end: fclose(fp); @@ -2388,11 +2395,13 @@ xtrabackup_print_metadata(char *buf, size_t buf_len) "backup_type = %s\n" "from_lsn = " UINT64PF "\n" "to_lsn = " UINT64PF "\n" - "last_lsn = " UINT64PF "\n", + "last_lsn = " UINT64PF "\n" + "recover_binlog_info = %d\n", metadata_type, metadata_from_lsn, metadata_to_lsn, - metadata_last_lsn); + metadata_last_lsn, + MY_TEST(opt_binlog_info == BINLOG_INFO_LOCKLESS)); } /*********************************************************************** @@ -6036,6 +6045,26 @@ static ibool prepare_handle_del_files(const char *datadir, const char *db, const return TRUE; } + +/************************************************************************** +Store the current binary log coordinates in a specified file. +@return 'false' on error. */ +static bool +store_binlog_info(const char *filename, const char* name, ulonglong pos) +{ + FILE *fp = fopen(filename, "w"); + + if (!fp) { + msg("mariabackup: failed to open '%s'\n", filename); + return(false); + } + + fprintf(fp, "%s\t%llu\n", name, pos); + fclose(fp); + + return(true); +} + /** Implement --prepare @return whether the operation succeeded */ static bool xtrabackup_prepare_func(char** argv) @@ -6275,6 +6304,20 @@ static bool xtrabackup_prepare_func(char** argv) msg("Last binlog file %s, position %lld", trx_sys.recovered_binlog_filename, longlong(trx_sys.recovered_binlog_offset)); + + /* output to xtrabackup_binlog_pos_innodb and (if + backup_safe_binlog_info was available on the server) to + xtrabackup_binlog_info. In the latter case + xtrabackup_binlog_pos_innodb becomes redundant and is created + only for compatibility. */ + ok = store_binlog_info( + "xtrabackup_binlog_pos_innodb", + trx_sys.recovered_binlog_filename, + trx_sys.recovered_binlog_offset) + && (!recover_binlog_info || store_binlog_info( + XTRABACKUP_BINLOG_INFO, + trx_sys.recovered_binlog_filename, + trx_sys.recovered_binlog_offset)); } /* Check whether the log is applied enough or not. */ diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h index df2f766aedb..fe8d36a2ed0 100644 --- a/extra/mariabackup/xtrabackup.h +++ b/extra/mariabackup/xtrabackup.h @@ -171,7 +171,7 @@ extern uint opt_safe_slave_backup_timeout; extern const char *opt_history; -enum binlog_info_enum { BINLOG_INFO_OFF, BINLOG_INFO_ON, +enum binlog_info_enum { BINLOG_INFO_OFF, BINLOG_INFO_LOCKLESS, BINLOG_INFO_ON, BINLOG_INFO_AUTO}; extern ulong opt_binlog_info; From e6bd4762fe25fa2cada83312dc5f8458ccea52d0 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Mon, 14 Aug 2023 20:35:24 +0200 Subject: [PATCH 184/477] Test case for provisioning a slave with mariabackup --no-lock Signed-off-by: Kristian Nielsen --- .../mariabackup/slave_provision_nolock.cnf | 13 ++ .../mariabackup/slave_provision_nolock.result | 41 +++++++ .../mariabackup/slave_provision_nolock.test | 112 ++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 mysql-test/suite/mariabackup/slave_provision_nolock.cnf create mode 100644 mysql-test/suite/mariabackup/slave_provision_nolock.result create mode 100644 mysql-test/suite/mariabackup/slave_provision_nolock.test diff --git a/mysql-test/suite/mariabackup/slave_provision_nolock.cnf b/mysql-test/suite/mariabackup/slave_provision_nolock.cnf new file mode 100644 index 00000000000..0e0bbd63f39 --- /dev/null +++ b/mysql-test/suite/mariabackup/slave_provision_nolock.cnf @@ -0,0 +1,13 @@ +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb + +[ENV] +SERVER_MYPORT_1= @mysqld.1.port +SERVER_MYSOCK_1= @mysqld.1.socket +SERVER_MYPORT_2= @mysqld.2.port +SERVER_MYSOCK_2= @mysqld.2.socket diff --git a/mysql-test/suite/mariabackup/slave_provision_nolock.result b/mysql-test/suite/mariabackup/slave_provision_nolock.result new file mode 100644 index 00000000000..c8124510385 --- /dev/null +++ b/mysql-test/suite/mariabackup/slave_provision_nolock.result @@ -0,0 +1,41 @@ +RESET MASTER; +CREATE TABLE t1(a varchar(60) PRIMARY KEY, b VARCHAR(60)) ENGINE INNODB; +INSERT INTO t1 VALUES(1, NULL); +CREATE TABLE t2 (val INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (0); +connect con1,localhost,root,,; +*** Start a background load... +CALL gen_load(); +connection default; +*** Doing backup... +*** Doing prepare... +*** Stop the background load... +UPDATE t2 SET val=1; +connection con1; +connection default; +disconnect con1; +*** Provision a new slave from the backup +connect server2,127.0.0.1,root,,,$SERVER_MYPORT_2; +*** Stopping provisioned server +*** Removing old datadir for provisioned server +*** Provision new server from backup +# restart +*** Configure slave position from xtrabackup_binlog_pos_innodb +CREATE TABLE t3 (file VARCHAR(255), pos INT) ENGINE=InnoDB; +LOAD DATA LOCAL INFILE "BASEDIR/xtrabackup_binlog_pos_innodb" + INTO TABLE t3 FIELDS ESCAPED BY '' (file, pos); +CHANGE MASTER TO +master_port=PORT, master_host='127.0.0.1', master_user='root', +master_log_file= "MASTER_FILE", +master_log_pos= MASTER_POS; +START SLAVE; +connection default; +connection server2; +connection server2; +STOP SLAVE; +RESET SLAVE ALL; +DROP PROCEDURE gen_load; +DROP TABLE t1, t2, t3; +connection default; +DROP PROCEDURE gen_load; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/mariabackup/slave_provision_nolock.test b/mysql-test/suite/mariabackup/slave_provision_nolock.test new file mode 100644 index 00000000000..9c47aebb0e6 --- /dev/null +++ b/mysql-test/suite/mariabackup/slave_provision_nolock.test @@ -0,0 +1,112 @@ +--source include/have_innodb.inc +--source include/have_log_bin.inc + +# Test provisioning a slave from an existing server, using mariabackup --no-lock +# and the binlog position recovered from InnoDB redo log. +let $basedir=$MYSQLTEST_VARDIR/tmp/backup; + +RESET MASTER; +CREATE TABLE t1(a varchar(60) PRIMARY KEY, b VARCHAR(60)) ENGINE INNODB; +INSERT INTO t1 VALUES(1, NULL); +CREATE TABLE t2 (val INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (0); + +--disable_query_log +--delimiter // +CREATE PROCEDURE gen_load() + MODIFIES SQL DATA + BEGIN + DECLARE i INT; + DECLARE flag TYPE OF t2.val; + SET i = 0; + load_loop: LOOP + SELECT val INTO flag FROM t2; + IF NOT (flag=0) THEN + LEAVE load_loop; + END IF; + START TRANSACTION; + INSERT INTO t1 VALUES (CONCAT("AbAdCaFe", LPAD(i, 6, "0")), @@SESSION.last_gtid); + COMMIT; + SET i = i + 1; + END LOOP; + END +// +--delimiter ; +--enable_query_log + +connect (con1,localhost,root,,); +--echo *** Start a background load... +send CALL gen_load(); + +--connection default +--echo *** Doing backup... +--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir --no-lock +--echo *** Doing prepare... +--exec $XTRABACKUP --prepare --rollback-xa --binlog-info=1 --target-dir=$basedir + +--echo *** Stop the background load... +UPDATE t2 SET val=1; +--connection con1 +reap; +--connection default +disconnect con1; +--let $count_master= `SELECT COUNT(*) FROM t1` + +--echo *** Provision a new slave from the backup +--connect (server2,127.0.0.1,root,,,$SERVER_MYPORT_2) +--let $datadir_2= `SELECT @@datadir` + +--echo *** Stopping provisioned server +--source include/shutdown_mysqld.inc + +--echo *** Removing old datadir for provisioned server +--rmdir $datadir_2 + +--echo *** Provision new server from backup +--exec $XTRABACKUP --copy-back --datadir=$datadir_2 --target-dir=$basedir + +--source include/start_mysqld.inc + +--echo *** Configure slave position from xtrabackup_binlog_pos_innodb +CREATE TABLE t3 (file VARCHAR(255), pos INT) ENGINE=InnoDB; +--replace_result $basedir BASEDIR +--disable_warnings +eval LOAD DATA LOCAL INFILE "$basedir/xtrabackup_binlog_pos_innodb" + INTO TABLE t3 FIELDS ESCAPED BY '' (file, pos); +--enable_warnings + +# Remove leading ./ from filename (leading .\ on windows). +--let provision_master_file= `SELECT REGEXP_REPLACE(file, "^[.].", "") FROM t3` +--let provision_master_pos= `SELECT pos FROM t3` + +--replace_result $SERVER_MYPORT_1 PORT $provision_master_file MASTER_FILE $provision_master_pos MASTER_POS +eval CHANGE MASTER TO + master_port=$SERVER_MYPORT_1, master_host='127.0.0.1', master_user='root', + master_log_file= "$provision_master_file", + master_log_pos= $provision_master_pos; +START SLAVE; + +--connection default +--save_master_pos + +--connection server2 +--sync_with_master +--let $count_slave= `SELECT COUNT(*) FROM t1` +if ($count_master != $count_slave) { + --echo *** ERROR: Table on master has $count_master rows, but table on provisioned slave has $count_slave rows + --die Row difference on provisioned slave. +} + +# Cleanup + +--connection server2 +STOP SLAVE; +RESET SLAVE ALL; +DROP PROCEDURE gen_load; +DROP TABLE t1, t2, t3; + +--connection default +DROP PROCEDURE gen_load; +DROP TABLE t1, t2; + +rmdir $basedir; From f8f5ed22805f7c269d812b95db3b159b8f2639a3 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Tue, 15 Aug 2023 12:19:34 +0200 Subject: [PATCH 185/477] Revert: MDEV-22351 InnoDB may recover wrong information after RESET MASTER This commit can cause the wrong (old) binlog position to be recovered by mariabackup --prepare. It implements that the value of the FIL_PAGE_LSN is compared to determine which binlog position is the last one and should be recoved. However, it is not guaranteed that the FIL_PAGE_LSN order matches the commit order, as is assumed by the code. This is because the page LSN could be modified by an unrelated update of the page after the commit. In one example, the recovery first encountered this in trx_rseg_mem_restore(): lsn=27282754 binlog position (./master-bin.000001, 472908) and then later: lsn=27282699 binlog position (./master-bin.000001, 477164) The last one 477164 is the correct position. However, because the LSN encountered for the first one is higher, that position is recovered instead. This results in too old binlog position, and a newly provisioned slave will start replicating too early and get duplicate key error or similar. Signed-off-by: Kristian Nielsen --- storage/innobase/include/trx0sys.h | 2 -- storage/innobase/trx/trx0rseg.cc | 45 +++++++++++++++++------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 0f12cd90495..5f518d799bd 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -867,8 +867,6 @@ public: uint64_t recovered_binlog_offset; /** Latest recovered binlog file name */ char recovered_binlog_filename[TRX_SYS_MYSQL_LOG_NAME_LEN]; - /** FIL_PAGE_LSN of the page with the latest recovered binlog metadata */ - lsn_t recovered_binlog_lsn; /** diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 49b93541620..10a863b0379 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -451,13 +451,8 @@ static dberr_t trx_undo_lists_init(trx_rseg_t *rseg, trx_id_t &max_trx_id, static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, trx_id_t &max_trx_id, mtr_t *mtr) { - /* This is based on trx_rsegf_get_new(). - We need to access buf_block_t. */ - buf_block_t *block = buf_page_get( - page_id_t(rseg->space->id, rseg->page_no), 0, RW_S_LATCH, mtr); - buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW); - - const trx_rsegf_t* rseg_header = TRX_RSEG + block->frame; + trx_rsegf_t* rseg_header = trx_rsegf_get_new( + rseg->space->id, rseg->page_no, mtr); if (mach_read_from_4(rseg_header + TRX_RSEG_FORMAT) == 0) { trx_id_t id = mach_read_from_8(rseg_header @@ -468,20 +463,32 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, trx_id_t &max_trx_id, } if (rseg_header[TRX_RSEG_BINLOG_NAME]) { - lsn_t lsn = std::max(block->page.newest_modification, - mach_read_from_8(FIL_PAGE_LSN - + block->frame)); + const char* binlog_name = reinterpret_cast + (rseg_header) + TRX_RSEG_BINLOG_NAME; compile_time_assert(TRX_RSEG_BINLOG_NAME_LEN == sizeof trx_sys.recovered_binlog_filename); - if (lsn > trx_sys.recovered_binlog_lsn) { - trx_sys.recovered_binlog_lsn = lsn; - trx_sys.recovered_binlog_offset - = mach_read_from_8( - rseg_header - + TRX_RSEG_BINLOG_OFFSET); - memcpy(trx_sys.recovered_binlog_filename, - rseg_header + TRX_RSEG_BINLOG_NAME, - TRX_RSEG_BINLOG_NAME_LEN); + + int cmp = *trx_sys.recovered_binlog_filename + ? strncmp(binlog_name, + trx_sys.recovered_binlog_filename, + TRX_RSEG_BINLOG_NAME_LEN) + : 1; + + if (cmp >= 0) { + uint64_t binlog_offset = mach_read_from_8( + rseg_header + TRX_RSEG_BINLOG_OFFSET); + if (cmp) { + memcpy(trx_sys. + recovered_binlog_filename, + binlog_name, + TRX_RSEG_BINLOG_NAME_LEN); + trx_sys.recovered_binlog_offset + = binlog_offset; + } else if (binlog_offset > + trx_sys.recovered_binlog_offset) { + trx_sys.recovered_binlog_offset + = binlog_offset; + } } #ifdef WITH_WSREP From 9fa718b1a144dc0d680becd2aabd8b620f444517 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 22 Sep 2023 13:10:58 +0200 Subject: [PATCH 186/477] Fix mariabackup InnoDB recovered binlog position on server upgrade Before MariaDB 10.3.5, the binlog position was stored in the TRX_SYS page, while after it is stored in rollback segments. There is code to read the legacy position from TRX_SYS to handle upgrades. The problem was if the legacy position happens to compare larger than the position found in rollback segments; in this case, the old TRX_SYS position would incorrectly be preferred over the newer position from rollback segments. Fixed by always preferring a position from rollback segments over a legacy position. Signed-off-by: Kristian Nielsen --- mysql-test/suite/innodb/include/crc32.pl | 23 ++++++++ .../suite/innodb/include/innodb-util.pl | 19 +++++++ .../mariabackup/slave_provision_nolock.result | 1 + .../mariabackup/slave_provision_nolock.test | 52 +++++++++++++++++++ storage/innobase/include/trx0sys.h | 2 + storage/innobase/trx/trx0rseg.cc | 8 ++- 6 files changed, 104 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/include/crc32.pl b/mysql-test/suite/innodb/include/crc32.pl index c2bce09dd36..b26f1057e2a 100644 --- a/mysql-test/suite/innodb/include/crc32.pl +++ b/mysql-test/suite/innodb/include/crc32.pl @@ -31,3 +31,26 @@ sub mycrc32 { return $crc; } + + +# Fix the checksum of an InnoDB tablespace page. +# Inputs: +# $page A bytestring with the page data. +# $full_crc32 Checksum type, see get_full_crc32() in innodb-util.pl +# Returns: the modified page as a bytestring. +sub fix_page_crc { + my ($page, $full_crc32)= @_; + my $ps= length($page); + my $polynomial = 0x82f63b78; # CRC-32C + if ($full_crc32) { + my $ck = mycrc32(substr($page, 0, $ps - 4), 0, $polynomial); + substr($page, $ps - 4, 4) = pack("N", $ck); + } else { + my $ck= pack("N", + mycrc32(substr($page, 4, 22), 0, $polynomial) ^ + mycrc32(substr($page, 38, $ps - 38 - 8), 0, $polynomial)); + substr($page, 0, 4)= $ck; + substr($page, $ps-8, 4)= $ck; + } + return $page; +} diff --git a/mysql-test/suite/innodb/include/innodb-util.pl b/mysql-test/suite/innodb/include/innodb-util.pl index 241545dac18..328ce5c7f36 100644 --- a/mysql-test/suite/innodb/include/innodb-util.pl +++ b/mysql-test/suite/innodb/include/innodb-util.pl @@ -124,3 +124,22 @@ sub ib_restore_ibd_files { ib_restore_ibd_file($tmpd, $datadir, $db, $table); } } + +# Read the flag whether a tablespace is using full_crc32. +# Input: filehandle opened on the tablespace. +sub get_full_crc32 { + my ($TBLSPC)= @_; + my $old_pos= sysseek($TBLSPC, 0, 1); + die "tell() failed on tablespace filehandle: $!\n" + unless defined($old_pos); + sysseek($TBLSPC, 0, 0) + or die "sysseek() failed on tablespace filehandle: $!\n"; + my $tblspc_hdr; + sysread($TBLSPC, $tblspc_hdr, 58) + or die "Cannot read tablespace header: $!\n"; + sysseek($TBLSPC, $old_pos, 0) + or die "sysseek() failed on tablespace filehandle: $!\n"; + my $full_crc32= + unpack("N", substr($tblspc_hdr, 54, 4)) & 0x10; # FIL_SPACE_FLAGS + return $full_crc32; +} diff --git a/mysql-test/suite/mariabackup/slave_provision_nolock.result b/mysql-test/suite/mariabackup/slave_provision_nolock.result index c8124510385..0273686f704 100644 --- a/mysql-test/suite/mariabackup/slave_provision_nolock.result +++ b/mysql-test/suite/mariabackup/slave_provision_nolock.result @@ -1,3 +1,4 @@ +# restart RESET MASTER; CREATE TABLE t1(a varchar(60) PRIMARY KEY, b VARCHAR(60)) ENGINE INNODB; INSERT INTO t1 VALUES(1, NULL); diff --git a/mysql-test/suite/mariabackup/slave_provision_nolock.test b/mysql-test/suite/mariabackup/slave_provision_nolock.test index 9c47aebb0e6..49c2d0d66d1 100644 --- a/mysql-test/suite/mariabackup/slave_provision_nolock.test +++ b/mysql-test/suite/mariabackup/slave_provision_nolock.test @@ -3,6 +3,58 @@ # Test provisioning a slave from an existing server, using mariabackup --no-lock # and the binlog position recovered from InnoDB redo log. + +# Update the InnoDB system tablespace to simulate a pre-10.3.5 +# position in TRX_SYS. There was a bug that the wrong position could +# be recovered if the old filename in TRX_SYS compares newer than the +# newer filenames stored in rseg headers. +let MYSQLD_DATADIR=`select @@datadir`; +let INNODB_PAGE_SIZE=`select @@innodb_page_size`; + +--source include/shutdown_mysqld.inc + +--perl +use strict; +use warnings; +use Fcntl qw(:DEFAULT :seek); +do "$ENV{MTR_SUITE_DIR}/../innodb/include/crc32.pl"; +do "$ENV{MTR_SUITE_DIR}/../innodb/include/innodb-util.pl"; + +my $ps = $ENV{INNODB_PAGE_SIZE}; + +sysopen IBD_FILE, "$ENV{MYSQLD_DATADIR}/ibdata1", O_RDWR + or die "Cannot open ibdata1: $!\n"; + +# Read the TRX_SYS page. +my $page; +sysseek(IBD_FILE, $ps * 5, SEEK_SET) + or die "Cannot seek ibdata1: $!\n"; +sysread(IBD_FILE, $page, $ps) + or die "Cannot read ibdata1: $!\n"; + +# Put in an old binlog position that will compare larger than master-bin.000001 +my $old_name= '~~~-bin.999999' . chr(0); +my $old_off= 0xffff0000; +my $old_magic= 873422344; +my $binlog_offset= $ps - 1000 + 38; +substr($page, $binlog_offset, 4)= pack('N', $old_magic); +substr($page, $binlog_offset + 4, 4)= pack('N', ($old_off >> 32)); +substr($page, $binlog_offset + 8, 4)= pack('N', ($old_off & 0xffffffff)); +substr($page, $binlog_offset + 12, length($old_name))= $old_name; + +# Write back the modified page. +my $full_crc32= get_full_crc32(\*IBD_FILE); +my $page= fix_page_crc($page, $full_crc32); +sysseek(IBD_FILE, $ps * 5, SEEK_SET) + or die "Cannot seek ibdata1: $!\n"; +syswrite(IBD_FILE, $page, $ps) == $ps + or die "Cannot write ibdata1: $!\n"; +close IBD_FILE; +EOF + +--source include/start_mysqld.inc + + let $basedir=$MYSQLTEST_VARDIR/tmp/backup; RESET MASTER; diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 5f518d799bd..41cc7934d43 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -867,6 +867,8 @@ public: uint64_t recovered_binlog_offset; /** Latest recovered binlog file name */ char recovered_binlog_filename[TRX_SYS_MYSQL_LOG_NAME_LEN]; + /** Set when latest position is from pre-version 10.3.5 TRX_SYS. */ + bool recovered_binlog_is_legacy_pos; /** diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 10a863b0379..be52373d03b 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -468,7 +468,10 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, trx_id_t &max_trx_id, compile_time_assert(TRX_RSEG_BINLOG_NAME_LEN == sizeof trx_sys.recovered_binlog_filename); - int cmp = *trx_sys.recovered_binlog_filename + /* Always prefer a position from rollback segment over + a legacy position from before version 10.3.5. */ + int cmp = *trx_sys.recovered_binlog_filename && + !trx_sys.recovered_binlog_is_legacy_pos ? strncmp(binlog_name, trx_sys.recovered_binlog_filename, TRX_RSEG_BINLOG_NAME_LEN) @@ -489,6 +492,7 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, trx_id_t &max_trx_id, trx_sys.recovered_binlog_offset = binlog_offset; } + trx_sys.recovered_binlog_is_legacy_pos= false; } #ifdef WITH_WSREP @@ -564,6 +568,7 @@ static void trx_rseg_init_binlog_info(const page_t* page) trx_sys.recovered_binlog_offset = mach_read_from_8( TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_OFFSET + TRX_SYS + page); + trx_sys.recovered_binlog_is_legacy_pos= true; } #ifdef WITH_WSREP @@ -578,6 +583,7 @@ dberr_t trx_rseg_array_init() *trx_sys.recovered_binlog_filename = '\0'; trx_sys.recovered_binlog_offset = 0; + trx_sys.recovered_binlog_is_legacy_pos= false; #ifdef WITH_WSREP trx_sys.recovered_wsrep_xid.null(); XID wsrep_sys_xid; From 7533062f17912424e1f859c5becaf3bf36bff7ac Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 19 Oct 2023 16:55:14 +0300 Subject: [PATCH 187/477] MDEV-32518 Test failure: ./mtr --no-reorder main.log_slow_debug main.subselect There where two errors left from the previous fix. - subselect.test assumes that mysql.slow_log is empty. This was not enforced. - subselect.test dropped a file that does not exists (for safety). This was fixed by ensuring we don't get a warning if the file does not exist. --- mysql-test/main/subselect.result | 1 + mysql-test/main/subselect.test | 4 ++++ mysql-test/main/subselect_no_exists_to_in.result | 1 + mysql-test/main/subselect_no_mat.result | 1 + mysql-test/main/subselect_no_opts.result | 1 + mysql-test/main/subselect_no_scache.result | 1 + mysql-test/main/subselect_no_semijoin.result | 1 + 7 files changed, 10 insertions(+) diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result index d2ae34029be..61742b0289c 100644 --- a/mysql-test/main/subselect.result +++ b/mysql-test/main/subselect.result @@ -7163,6 +7163,7 @@ drop table t1; # # MDEV-7565: Server crash with Signal 6 (part 2) # +truncate table mysql.slow_log; Select (Select Sum(`TestCase`.Revenue) From mysql.slow_log E Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test index a17fc408500..7a0b77bcee5 100644 --- a/mysql-test/main/subselect.test +++ b/mysql-test/main/subselect.test @@ -1171,8 +1171,10 @@ create table t1 (a int, b decimal(13, 3)); insert into t1 values (1, 0.123); let $outfile_abs= $MYSQLTEST_VARDIR/tmp/subselect.out.file.1; let $outfile_rel= ../../tmp/subselect.out.file.1; +--disable_warnings --error 0,1 --remove_file $outfile_abs +--enable_warnings eval select a, (select max(b) from t1) into outfile "$outfile_rel" from t1; delete from t1; eval load data infile "$outfile_rel" into table t1; @@ -5990,6 +5992,8 @@ drop table t1; --echo # --echo # MDEV-7565: Server crash with Signal 6 (part 2) --echo # + +truncate table mysql.slow_log; Select (Select Sum(`TestCase`.Revenue) From mysql.slow_log E Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result index f508cb259bb..c3b7f803838 100644 --- a/mysql-test/main/subselect_no_exists_to_in.result +++ b/mysql-test/main/subselect_no_exists_to_in.result @@ -7163,6 +7163,7 @@ drop table t1; # # MDEV-7565: Server crash with Signal 6 (part 2) # +truncate table mysql.slow_log; Select (Select Sum(`TestCase`.Revenue) From mysql.slow_log E Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result index 02cb92fde08..1b02363588b 100644 --- a/mysql-test/main/subselect_no_mat.result +++ b/mysql-test/main/subselect_no_mat.result @@ -7156,6 +7156,7 @@ drop table t1; # # MDEV-7565: Server crash with Signal 6 (part 2) # +truncate table mysql.slow_log; Select (Select Sum(`TestCase`.Revenue) From mysql.slow_log E Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result index 72b148b59d4..040b3fbf150 100644 --- a/mysql-test/main/subselect_no_opts.result +++ b/mysql-test/main/subselect_no_opts.result @@ -7154,6 +7154,7 @@ drop table t1; # # MDEV-7565: Server crash with Signal 6 (part 2) # +truncate table mysql.slow_log; Select (Select Sum(`TestCase`.Revenue) From mysql.slow_log E Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result index 4717eb9bd15..5d09a9cb52e 100644 --- a/mysql-test/main/subselect_no_scache.result +++ b/mysql-test/main/subselect_no_scache.result @@ -7169,6 +7169,7 @@ drop table t1; # # MDEV-7565: Server crash with Signal 6 (part 2) # +truncate table mysql.slow_log; Select (Select Sum(`TestCase`.Revenue) From mysql.slow_log E Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result index 9450cf4fe9c..50625b2e1b5 100644 --- a/mysql-test/main/subselect_no_semijoin.result +++ b/mysql-test/main/subselect_no_semijoin.result @@ -7154,6 +7154,7 @@ drop table t1; # # MDEV-7565: Server crash with Signal 6 (part 2) # +truncate table mysql.slow_log; Select (Select Sum(`TestCase`.Revenue) From mysql.slow_log E Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) From e5a5573f782723e40c372f38346a60b1ccc644d6 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 2 Nov 2023 11:49:03 +0200 Subject: [PATCH 188/477] rpl.rpl_invoked_features fails sporadically with "Duplicate key error" The reason was that Event e11 was re-executed before "ALTER EVENT e11 DISABLE" had been executed. Fixed by increasing re-schedule time Other things: - Removed double accounting of 'execution_count'. It was incremented in top->mark_last_executed(thd) that was executed a few lines earlier. --- mysql-test/suite/rpl/r/rpl_invoked_features.result | 4 ++-- mysql-test/suite/rpl/t/rpl_invoked_features.test | 9 ++++++--- sql/event_queue.cc | 1 - 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_invoked_features.result b/mysql-test/suite/rpl/r/rpl_invoked_features.result index 43a8e8625de..3cfd40d5a0e 100644 --- a/mysql-test/suite/rpl/r/rpl_invoked_features.result +++ b/mysql-test/suite/rpl/r/rpl_invoked_features.result @@ -45,14 +45,14 @@ BEGIN UPDATE t12 SET c = ''; UPDATE t13 SET c = ''; END| -CREATE EVENT e1 ON SCHEDULE EVERY 1 SECOND DISABLE DO +CREATE EVENT e1 ON SCHEDULE EVERY 10 SECOND DISABLE DO BEGIN ALTER EVENT e1 DISABLE; CALL p1(10, ''); END| Warnings: Warning 1105 Event scheduler is switched off, use SET GLOBAL event_scheduler=ON to enable it. -CREATE EVENT e11 ON SCHEDULE EVERY 1 SECOND DISABLE DO +CREATE EVENT e11 ON SCHEDULE EVERY 10 SECOND DISABLE DO BEGIN ALTER EVENT e11 DISABLE; CALL p11(10, ''); diff --git a/mysql-test/suite/rpl/t/rpl_invoked_features.test b/mysql-test/suite/rpl/t/rpl_invoked_features.test index 91391cf8372..cd2b770c419 100644 --- a/mysql-test/suite/rpl/t/rpl_invoked_features.test +++ b/mysql-test/suite/rpl/t/rpl_invoked_features.test @@ -102,14 +102,17 @@ BEGIN UPDATE t13 SET c = ''; END| -# Create events which will run every 1 sec -CREATE EVENT e1 ON SCHEDULE EVERY 1 SECOND DISABLE DO +# Create events which will run every 10 sec +# It cannot be much shorter as we have to ensure that a new +# event is not scheduled before the DISABLE has been +# executed. +CREATE EVENT e1 ON SCHEDULE EVERY 10 SECOND DISABLE DO BEGIN ALTER EVENT e1 DISABLE; CALL p1(10, ''); END| -CREATE EVENT e11 ON SCHEDULE EVERY 1 SECOND DISABLE DO +CREATE EVENT e11 ON SCHEDULE EVERY 10 SECOND DISABLE DO BEGIN ALTER EVENT e11 DISABLE; CALL p11(10, ''); diff --git a/sql/event_queue.cc b/sql/event_queue.cc index 516bdc9158f..0298e7746ad 100644 --- a/sql/event_queue.cc +++ b/sql/event_queue.cc @@ -650,7 +650,6 @@ Event_queue::get_top_for_execution_if_time(THD *thd, top->status= Event_parse_data::DISABLED; DBUG_PRINT("info", ("event %s status is %d", top->name.str, top->status)); - top->execution_count++; (*event_name)->dropped= top->dropped; /* Save new values of last_executed timestamp and event status on stack From 3c1f324a5560d106f4918eda2d42eb626ab9ed57 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 3 Nov 2023 14:43:45 +0100 Subject: [PATCH 189/477] MDEV-32672: Don't hold LOCK_thd_data over commit_ordered Partial revert of this commit: commit 6b685ea7b0776430d45b095cb4be3ef0739a3c04 Author: Sergei Golubchik Date: Wed Sep 28 18:55:15 2022 +0200 Don't hold LOCK_thd_data over run_commit_ordered(). Holding the mutex is unnecessary and will deadlock if any code in a commit_ordered handlerton call tries to take the mutex to change THD local data. Instead, set the current_thd for the duration of the call to keep asserts happy around LOCK_thd_data. Signed-off-by: Kristian Nielsen --- sql/log.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index 12e2aee94cc..277d8de6701 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -8556,13 +8556,10 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader) DEBUG_SYNC(leader->thd, "commit_loop_entry_commit_ordered"); ++num_commits; + set_current_thd(current->thd); if (current->cache_mngr->using_xa && likely(!current->error) && DBUG_EVALUATE_IF("skip_commit_ordered", 0, 1)) - { - mysql_mutex_lock(¤t->thd->LOCK_thd_data); run_commit_ordered(current->thd, current->all); - mysql_mutex_unlock(¤t->thd->LOCK_thd_data); - } current->thd->wakeup_subsequent_commits(current->error); /* @@ -8579,6 +8576,7 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader) } current= next; } + set_current_thd(leader->thd); DEBUG_SYNC(leader->thd, "commit_after_group_run_commit_ordered"); mysql_mutex_unlock(&LOCK_commit_ordered); DEBUG_SYNC(leader->thd, "commit_after_group_release_commit_ordered"); From 23f9e3425699d22049cc2acc74fe9a16e70286ee Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Wed, 11 Oct 2023 12:37:24 +0400 Subject: [PATCH 190/477] MDEV-32444 Data from orphaned XA transaction is lost after online alter XA support for online alter was totally missing. Tying on binlog_hton made this hardly visible: simply having binlog_commit called from xa_commit made an impression that it will automagically work for online alter, which turns out wrong: all binlog does is writes "XA END" into trx cache and flushes it to a real binlog. In comparison, online alter can't do the same, since online replication happens in a single transaction. Solution: make a dedicated XA support. * Extend struct xid_t with a pointer to Online_alter_cache_list * On prepare: move online alter cache from THD::ha_data to XID passed * On XA commit/rollback: use the online alter cache stored in this XID. This makes us pass xid_cache_element->xid to xa_commit/xa_rollback instead of lex->xid * Use manual memory management for online alter cache list, instead of mem_root allocation, since we don't have mem_root connected to the XA transaction. --- .../main/alter_table_online_debug.result | 110 +++++++++++++++ mysql-test/main/alter_table_online_debug.test | 129 ++++++++++++++++++ sql/handler.cc | 4 +- sql/handler.h | 7 + sql/online_alter.cc | 94 ++++++++++--- sql/sql_class.cc | 2 + sql/xa.cc | 12 +- sql/xa.h | 1 + 8 files changed, 337 insertions(+), 22 deletions(-) diff --git a/mysql-test/main/alter_table_online_debug.result b/mysql-test/main/alter_table_online_debug.result index 1ebb19965eb..bf255b7828b 100644 --- a/mysql-test/main/alter_table_online_debug.result +++ b/mysql-test/main/alter_table_online_debug.result @@ -1563,6 +1563,116 @@ connection default; drop table t1, t2; set @@binlog_format=default; set debug_sync= reset; +# MDEV-32444 Data from orphaned XA transaction is lost after online alter +create table t (a int primary key) engine=innodb; +insert into t values (1); +# XA commit +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +alter table t force, algorithm=copy, lock=none; +connection con1; +set debug_sync= 'now wait_for downgraded'; +xa begin 'x1'; +update t set a = 2 where a = 1; +xa end 'x1'; +xa prepare 'x1'; +set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +disconnect con1; +connection con2; +set debug_sync= 'now wait_for xa_detach'; +xa commit 'x1'; +set debug_sync= 'now signal go'; +connection default; +select * from t; +a +2 +# XA rollback +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +alter table t force, algorithm=copy, lock=none; +connect con1, localhost, root,,; +set debug_sync= 'now wait_for downgraded'; +xa begin 'x2'; +insert into t values (53); +xa end 'x2'; +xa prepare 'x2'; +set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +disconnect con1; +connection con2; +set debug_sync= 'now wait_for xa_detach'; +xa rollback 'x2'; +set debug_sync= 'now signal go'; +connection default; +select * from t; +a +2 +# XA transaction is left uncommitted +# end then is rollbacked after alter fails +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +set statement innodb_lock_wait_timeout=0, lock_wait_timeout= 0 +for alter table t force, algorithm=copy, lock=none; +connect con1, localhost, root,,; +set debug_sync= 'now wait_for downgraded'; +xa begin 'xuncommitted'; +insert into t values (3); +xa end 'xuncommitted'; +xa prepare 'xuncommitted'; +set debug_sync= 'now signal go'; +set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +disconnect con1; +connection default; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +set debug_sync= 'now wait_for xa_detach'; +xa rollback 'xuncommitted'; +select * from t; +a +2 +# Same, but commit +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +set statement innodb_lock_wait_timeout=0, lock_wait_timeout= 0 +for alter table t force, algorithm=copy, lock=none; +connect con1, localhost, root,,; +set debug_sync= 'now wait_for downgraded'; +xa begin 'committed_later'; +insert into t values (3); +xa end 'committed_later'; +xa prepare 'committed_later'; +set debug_sync= 'now signal go'; +set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +disconnect con1; +connection default; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +set debug_sync= 'now wait_for xa_detach'; +xa commit 'committed_later'; +select * from t; +a +2 +3 +# Commit, but error in statement, and there is some stmt data to rollback +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +alter table t force, algorithm=copy, lock=none; +connect con1, localhost, root,,; +set debug_sync= 'now wait_for downgraded'; +xa begin 'x1'; +insert into t values (4), (3); +ERROR 23000: Duplicate entry '3' for key 'PRIMARY' +insert into t values (5); +xa end 'x1'; +xa prepare 'x1'; +set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +disconnect con1; +connection con2; +set debug_sync= 'now wait_for xa_detach'; +xa commit 'x1'; +set debug_sync= 'now signal go'; +connection default; +select * from t; +a +2 +3 +5 +connect con1, localhost, root,,; +connection default; +drop table t; +set debug_sync= reset; disconnect con1; disconnect con2; # diff --git a/mysql-test/main/alter_table_online_debug.test b/mysql-test/main/alter_table_online_debug.test index 0a0a9ab72fc..0299cd3b46e 100644 --- a/mysql-test/main/alter_table_online_debug.test +++ b/mysql-test/main/alter_table_online_debug.test @@ -1791,6 +1791,135 @@ set @@binlog_format=default; set debug_sync= reset; +--echo # MDEV-32444 Data from orphaned XA transaction is lost after online alter + +create table t (a int primary key) engine=innodb; +insert into t values (1); + +--echo # XA commit + +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +send alter table t force, algorithm=copy, lock=none; + +--connection con1 +set debug_sync= 'now wait_for downgraded'; +xa begin 'x1'; +update t set a = 2 where a = 1; +xa end 'x1'; +xa prepare 'x1'; +set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +--disconnect con1 + +--connection con2 +set debug_sync= 'now wait_for xa_detach'; +xa commit 'x1'; +set debug_sync= 'now signal go'; +--connection default +--reap # alter table + +select * from t; + +--echo # XA rollback + +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +send alter table t force, algorithm=copy, lock=none; +--connect(con1, localhost, root,,) +set debug_sync= 'now wait_for downgraded'; +xa begin 'x2'; +insert into t values (53); +xa end 'x2'; +xa prepare 'x2'; +set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +--disconnect con1 + +--connection con2 +set debug_sync= 'now wait_for xa_detach'; +xa rollback 'x2'; +set debug_sync= 'now signal go'; +--connection default +--reap # alter table + +select * from t; + +--echo # XA transaction is left uncommitted +--echo # end then is rollbacked after alter fails + +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +send set statement innodb_lock_wait_timeout=0, lock_wait_timeout= 0 + for alter table t force, algorithm=copy, lock=none; + +--connect(con1, localhost, root,,) +set debug_sync= 'now wait_for downgraded'; +xa begin 'xuncommitted'; +insert into t values (3); +xa end 'xuncommitted'; +xa prepare 'xuncommitted'; +set debug_sync= 'now signal go'; +set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +--disconnect con1 + +--connection default +--error ER_LOCK_WAIT_TIMEOUT +--reap # alter table +set debug_sync= 'now wait_for xa_detach'; +xa rollback 'xuncommitted'; + +select * from t; + +--echo # Same, but commit + +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +send set statement innodb_lock_wait_timeout=0, lock_wait_timeout= 0 + for alter table t force, algorithm=copy, lock=none; + +--connect(con1, localhost, root,,) +set debug_sync= 'now wait_for downgraded'; +xa begin 'committed_later'; +insert into t values (3); +xa end 'committed_later'; +xa prepare 'committed_later'; +set debug_sync= 'now signal go'; +set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +--disconnect con1 + +--connection default +--error ER_LOCK_WAIT_TIMEOUT +--reap # alter table +set debug_sync= 'now wait_for xa_detach'; +xa commit 'committed_later'; + + +select * from t; + +--echo # Commit, but error in statement, and there is some stmt data to rollback + +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +send alter table t force, algorithm=copy, lock=none; +--connect(con1, localhost, root,,) +set debug_sync= 'now wait_for downgraded'; +xa begin 'x1'; +--error ER_DUP_ENTRY +insert into t values (4), (3); +insert into t values (5); +xa end 'x1'; +xa prepare 'x1'; +set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +--disconnect con1 + +--connection con2 +set debug_sync= 'now wait_for xa_detach'; +xa commit 'x1'; +set debug_sync= 'now signal go'; +--connection default +--reap # alter table + +select * from t; + +--connect(con1, localhost, root,,) +--connection default +drop table t; +set debug_sync= reset; + --disconnect con1 --disconnect con2 --echo # diff --git a/sql/handler.cc b/sql/handler.cc index a48c16c278c..5a969b6d634 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2596,7 +2596,7 @@ static bool xarecover_decide_to_commit(xid_recovery_member* member, static void xarecover_do_commit_or_rollback(handlerton *hton, xarecover_complete_arg *arg) { - xid_t x; + XA_data x; my_bool rc; xid_recovery_member *member= arg->member; Binlog_offset *ptr_commit_max= arg->binlog_coord; @@ -2605,7 +2605,7 @@ static void xarecover_do_commit_or_rollback(handlerton *hton, // Populate xid using the server_id from original transaction x.set(member->xid, member->server_id); else - x= *member->full_xid; + (XID)x= *member->full_xid; rc= xarecover_decide_to_commit(member, ptr_commit_max) ? hton->commit_by_xid(hton, &x) : hton->rollback_by_xid(hton, &x); diff --git a/sql/handler.h b/sql/handler.h index 07b392c010a..01ab2103703 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -890,6 +890,7 @@ typedef ulonglong my_xid; // this line is the same as in log_event.h #define COMPATIBLE_DATA_YES 0 #define COMPATIBLE_DATA_NO 1 + /** struct xid_t is binary compatible with the XID structure as in the X/Open CAE Specification, Distributed Transaction Processing: @@ -973,6 +974,12 @@ struct xid_t { }; typedef struct xid_t XID; +struct Online_alter_cache_list; +struct XA_data: XID +{ + Online_alter_cache_list *online_alter_cache= NULL; +}; + /* Enumerates a sequence in the order of their creation that is in the top-down order of the index file. diff --git a/sql/online_alter.cc b/sql/online_alter.cc index 8b8c81319d1..bdf813f62dd 100644 --- a/sql/online_alter.cc +++ b/sql/online_alter.cc @@ -38,7 +38,7 @@ struct table_savepoint: ilist_node<> table_savepoint(sv_id_t id, my_off_t pos): id(id), log_prev_pos(pos){} }; -class online_alter_cache_data: public Sql_alloc, public ilist_node<>, +class online_alter_cache_data: public ilist_node<>, public binlog_cache_data { public: @@ -83,7 +83,7 @@ online_alter_cache_data *setup_cache_data(MEM_ROOT *root, TABLE_SHARE *share) { static ulong online_alter_cache_use= 0, online_alter_cache_disk_use= 0; - auto cache= new (root) online_alter_cache_data(); + auto cache= new online_alter_cache_data(); if (!cache || open_cached_file(&cache->cache_log, mysql_tmpdir, LOG_PREFIX, (size_t)binlog_cache_size, MYF(MY_WME))) { @@ -202,16 +202,15 @@ cleanup_cache_list(ilist &list, bool ending_trans) static -int online_alter_end_trans(handlerton *hton, THD *thd, bool all, bool commit) +int online_alter_end_trans(Online_alter_cache_list &cache_list, THD *thd, + bool is_ending_transaction, bool commit) { DBUG_ENTER("online_alter_end_trans"); int error= 0; - auto &cache_list= get_cache_list(hton, thd); + if (cache_list.empty()) DBUG_RETURN(0); - bool is_ending_transaction= ending_trans(thd, all); - for (auto &cache: cache_list) { auto *binlog= cache.sink_log; @@ -263,12 +262,16 @@ int online_alter_end_trans(handlerton *hton, THD *thd, bool all, bool commit) cleanup_cache_list(cache_list, is_ending_transaction); - for (TABLE *table= thd->open_tables; table; table= table->next) - table->online_alter_cache= NULL; DBUG_RETURN(error); } +void cleanup_tables(THD *thd) +{ + for (TABLE *table= thd->open_tables; table; table= table->next) + table->online_alter_cache= NULL; +} +static int online_alter_savepoint_set(handlerton *hton, THD *thd, sv_id_t sv_id) { DBUG_ENTER("binlog_online_alter_savepoint"); @@ -289,7 +292,7 @@ int online_alter_savepoint_set(handlerton *hton, THD *thd, sv_id_t sv_id) DBUG_RETURN(0); } - +static int online_alter_savepoint_rollback(handlerton *hton, THD *thd, sv_id_t sv_id) { DBUG_ENTER("online_alter_savepoint_rollback"); @@ -310,6 +313,63 @@ int online_alter_savepoint_rollback(handlerton *hton, THD *thd, sv_id_t sv_id) DBUG_RETURN(0); } +static int online_alter_commit(handlerton *hton, THD *thd, bool all) +{ + int res= online_alter_end_trans(get_cache_list(hton, thd), thd, + ending_trans(thd, all), true); + cleanup_tables(thd); + return res; +}; + +static int online_alter_rollback(handlerton *hton, THD *thd, bool all) +{ + int res= online_alter_end_trans(get_cache_list(hton, thd), thd, + ending_trans(thd, all), false); + cleanup_tables(thd); + return res; +}; + +static int online_alter_prepare(handlerton *hton, THD *thd, bool all) +{ + auto &cache_list= get_cache_list(hton, thd); + int res= 0; + if (ending_trans(thd, all)) + { + thd->transaction->xid_state.set_online_alter_cache(&cache_list); + thd_set_ha_data(thd, hton, NULL); + } + else + { + res= online_alter_end_trans(cache_list, thd, false, true); + } + + cleanup_tables(thd); + return res; +}; + +static int online_alter_commit_by_xid(handlerton *hton, XID *x) +{ + auto *xid= static_cast(x); + if (likely(xid->online_alter_cache == NULL)) + return 1; + int res= online_alter_end_trans(*xid->online_alter_cache, current_thd, + true, true); + delete xid->online_alter_cache; + xid->online_alter_cache= NULL; + return res; +}; + +static int online_alter_rollback_by_xid(handlerton *hton, XID *x) +{ + auto *xid= static_cast(x); + if (likely(xid->online_alter_cache == NULL)) + return 1; + int res= online_alter_end_trans(*xid->online_alter_cache, current_thd, + true, false); + delete xid->online_alter_cache; + xid->online_alter_cache= NULL; + return res; +}; static int online_alter_close_connection(handlerton *hton, THD *thd) { @@ -334,14 +394,14 @@ static int online_alter_log_init(void *p) online_alter_hton->savepoint_rollback_can_release_mdl= [](handlerton *hton, THD *thd){ return true; }; - online_alter_hton->commit= [](handlerton *hton, THD *thd, bool all) - { return online_alter_end_trans(hton, thd, all, true); }; - online_alter_hton->rollback= [](handlerton *hton, THD *thd, bool all) - { return online_alter_end_trans(hton, thd, all, false); }; - online_alter_hton->commit_by_xid= [](handlerton *hton, XID *xid) - { return online_alter_end_trans(hton, current_thd, true, true); }; - online_alter_hton->rollback_by_xid= [](handlerton *hton, XID *xid) - { return online_alter_end_trans(hton, current_thd, true, false); }; + online_alter_hton->commit= online_alter_commit; + online_alter_hton->rollback= online_alter_rollback; + + + online_alter_hton->recover= [](handlerton*, XID*, uint){ return 0; }; + online_alter_hton->prepare= online_alter_prepare; + online_alter_hton->commit_by_xid= online_alter_commit_by_xid; + online_alter_hton->rollback_by_xid= online_alter_rollback_by_xid; online_alter_hton->drop_table= [](handlerton *, const char*) { return -1; }; online_alter_hton->flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN diff --git a/sql/sql_class.cc b/sql/sql_class.cc index e8e17bef272..7248bf3c0a7 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1539,6 +1539,8 @@ void THD::cleanup(void) else trans_rollback(this); + DEBUG_SYNC(this, "THD_cleanup_after_trans_cleanup"); + DBUG_ASSERT(open_tables == NULL); DBUG_ASSERT(m_transaction_psi == NULL); diff --git a/sql/xa.cc b/sql/xa.cc index 49be7fb5347..51375cae537 100644 --- a/sql/xa.cc +++ b/sql/xa.cc @@ -78,7 +78,7 @@ public: /* Error reported by the Resource Manager (RM) to the Transaction Manager. */ uint rm_error; enum xa_states xa_state; - XID xid; + XA_data xid; bool is_set(int32_t flag) { return m_state.load(std::memory_order_relaxed) & flag; } void set(int32_t flag) @@ -140,6 +140,7 @@ public: { XID_cache_element *element= (XID_cache_element*) (ptr + LF_HASH_OVERHEAD); element->m_state= 0; + new(&element->xid) XA_data(); } static void lf_alloc_destructor(uchar *ptr) { @@ -179,6 +180,11 @@ void XID_STATE::set_error(uint error) xid_cache_element->rm_error= error; } +void XID_STATE::set_online_alter_cache(Online_alter_cache_list *cache) +{ + if (is_explicit_XA()) + xid_cache_element->xid.online_alter_cache= cache; +} void XID_STATE::er_xaer_rmfail() const { @@ -646,7 +652,7 @@ bool trans_xa_commit(THD *thd) DBUG_ASSERT(!xid_state.xid_cache_element); xid_state.xid_cache_element= xs; - ha_commit_or_rollback_by_xid(thd->lex->xid, !res); + ha_commit_or_rollback_by_xid(&xs->xid, !res); if (!res && thd->is_error()) { // hton completion error retains xs/xid in the cache, @@ -826,7 +832,7 @@ bool trans_xa_rollback(THD *thd) DBUG_ASSERT(!xid_state.xid_cache_element); xid_state.xid_cache_element= xs; - ha_commit_or_rollback_by_xid(thd->lex->xid, 0); + ha_commit_or_rollback_by_xid(&xs->xid, 0); if (!res && thd->is_error()) { goto _end_external_xid; diff --git a/sql/xa.h b/sql/xa.h index a9b06e427c6..7c23b8c735e 100644 --- a/sql/xa.h +++ b/sql/xa.h @@ -34,6 +34,7 @@ struct XID_STATE { bool check_has_uncommitted_xa() const; bool is_explicit_XA() const { return xid_cache_element != 0; } void set_error(uint error); + void set_online_alter_cache(Online_alter_cache_list *); void er_xaer_rmfail() const; XID *get_xid() const; enum xa_states get_state_code() const; From f7646d890b98e1ff5480f60c9d4795a4c9efa6ba Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Fri, 20 Oct 2023 17:06:22 +0400 Subject: [PATCH 191/477] main.alter_table_online_debug: remove explicit innodb --- .../main/alter_table_online_debug.result | 39 ++++++++++--------- mysql-test/main/alter_table_online_debug.test | 36 +++++++++-------- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/mysql-test/main/alter_table_online_debug.result b/mysql-test/main/alter_table_online_debug.result index bf255b7828b..06f23732365 100644 --- a/mysql-test/main/alter_table_online_debug.result +++ b/mysql-test/main/alter_table_online_debug.result @@ -1,3 +1,4 @@ +set global default_storage_engine= innodb; set default_storage_engine= innodb; connect con2, localhost, root,,; connection default; @@ -289,7 +290,7 @@ set debug_sync= 'alter_table_copy_end SIGNAL ended WAIT_FOR end'; alter table t1 add b int NULL, algorithm= copy, lock= none; connection con2; insert into t1 values (1),(2),(3),(4),(5),(6); -ERROR 23000: Duplicate entry '5' for key 'PRIMARY' +Got one of the listed errors select * from t1; a 1 @@ -496,6 +497,7 @@ a b UNIX_TIMESTAMP(row_start) UNIX_TIMESTAMP(row_end) 6 77 1.000000 2147483647.999999 alter table t1 drop system versioning, algorithm= copy, lock= none; ERROR 0A000: LOCK=NONE is not supported. Reason: DROP SYSTEM VERSIONING. Try LOCK=SHARED +drop table t1; # # Test ROLLBACK TO SAVEPOINT # @@ -582,7 +584,7 @@ set debug_sync= 'reset'; drop table t1; drop table t2; drop table t3; -create table t1 (a char(6), b int) engine=innodb; +create table t1 (a char(6), b int); insert t1 values ('abcde1',1),('abcde2',2); set debug_sync= 'now wait_for downgraded'; connection con2; @@ -838,7 +840,7 @@ a b drop table t1; set debug_sync= 'reset'; ## CHECK, UPDATE -create table t1 (a int) engine=innodb; +create table t1 (a int); insert t1 values (1),(2),(3),(4); set debug_sync= 'now wait_for downgraded'; connection con2; @@ -863,7 +865,7 @@ a 14 drop table t1; ## DEFAULT, UPDATE -create table t1 (a int) engine=innodb; +create table t1 (a int); insert t1 values (1),(2),(3),(4); set debug_sync= 'now wait_for downgraded'; connection con2; @@ -892,7 +894,7 @@ a b drop table t1; set debug_sync= 'reset'; ## VCOL + CHECK -create table t1 (a int) engine=innodb; +create table t1 (a int); insert t1 values (1),(2),(3),(4); set debug_sync= 'now wait_for downgraded'; connection con2; @@ -939,8 +941,8 @@ connection default; drop table t1; set debug_sync= reset; ### -create table t1 (a text, unique(a)) engine=innodb; -create table t2 (b text, unique(b)) engine=innodb; +create table t1 (a text, unique(a)); +create table t2 (b text, unique(b)); insert into t2 values (null),(null); set debug_sync= 'now wait_for downgraded'; connection con2; @@ -958,7 +960,7 @@ set debug_sync= reset; # # MDEV-29038 XA assertions failing in binlog_rollback and binlog_commit # -create table t (a int) engine=innodb; +create table t (a int); insert into t values (1); xa begin 'xid'; set debug_sync= 'now wait_for downgraded'; @@ -1303,7 +1305,7 @@ drop table t; # Test that correct fields are marked as explicit: # Drop a, reorder b, add new column with default. # -create table t (a int primary key, b int) engine=innodb; +create table t (a int primary key, b int); insert into t values (1, 1), (2, 2), (3, 3); set debug_sync= "alter_table_copy_end signal copy wait_for goon"; alter table t drop primary key, drop a, @@ -1334,7 +1336,7 @@ c x 3 123456 drop table t; # Test that all the fields are unpacked. -create table t (a int, b int) engine=innodb; +create table t (a int, b int); insert into t values (NULL, 123), (NULL, 456); set debug_sync= "alter_table_copy_end signal copy wait_for goon"; alter table t drop a, add primary key(b), algorithm=copy; @@ -1464,7 +1466,7 @@ INSERT iso_levels VALUES (0, "READ UNCOMMITTED"), (1, "READ COMMITTED"), (2, "REPEATABLE READ"), (3, "SERIALIZABLE"); -create table t1 (a int, b int, key(b)) engine=innodb; +create table t1 (a int, b int, key(b)); connection con2; insert into t1 values (1,1),(null,null),(3,3),(4,null),(null,5); connection default; @@ -1477,7 +1479,7 @@ delete from t1 where b is null; set debug_sync= "now signal goalters"; connection default; drop table t1; -create table t1 (a int, b int, key(b)) engine=innodb; +create table t1 (a int, b int, key(b)); connection con2; insert into t1 values (1,1),(null,null),(3,3),(4,null),(null,5); connection default; @@ -1490,7 +1492,7 @@ delete from t1 where b is null; set debug_sync= "now signal goalters"; connection default; drop table t1; -create table t1 (a int, b int, key(b)) engine=innodb; +create table t1 (a int, b int, key(b)); connection con2; insert into t1 values (1,1),(null,null),(3,3),(4,null),(null,5); connection default; @@ -1503,7 +1505,7 @@ delete from t1 where b is null; set debug_sync= "now signal goalters"; connection default; drop table t1; -create table t1 (a int, b int, key(b)) engine=innodb; +create table t1 (a int, b int, key(b)); connection con2; insert into t1 values (1,1),(null,null),(3,3),(4,null),(null,5); connection default; @@ -1520,8 +1522,8 @@ set debug_sync= reset; drop table iso_levels; # MDEV-32126 Assertion fails upon online ALTER and binary log enabled create temporary table tmp (id int, primary key(id)) engine=innodb; -create table t1 (a int, b text) engine=innodb; -create table t2 (a int, b int, c char(8), d text, unique(a)) engine=innodb; +create table t1 (a int, b text); +create table t2 (a int, b int, c char(8), d text, unique(a)); insert into t2 values (1,1,'f','e'),(1000,1000,'c','b'); connection default; set debug_sync= 'alter_table_online_before_lock signal go_trx wait_for go_alter'; @@ -1540,7 +1542,7 @@ truncate t2; set @@binlog_format=mixed; connection con2; start transaction; -create temporary table tmp (id int, primary key(id)) engine=innodb; +create temporary table tmp (id int, primary key(id)); insert into t1 values (1, repeat('x',8000)),(2, repeat('x',8000)); update t2 set b = null order by b limit 2; insert into t1 values (3, repeat('x',8000)); @@ -1564,7 +1566,7 @@ drop table t1, t2; set @@binlog_format=default; set debug_sync= reset; # MDEV-32444 Data from orphaned XA transaction is lost after online alter -create table t (a int primary key) engine=innodb; +create table t (a int primary key); insert into t values (1); # XA commit set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; @@ -1673,6 +1675,7 @@ connect con1, localhost, root,,; connection default; drop table t; set debug_sync= reset; +set global default_storage_engine= MyISAM; disconnect con1; disconnect con2; # diff --git a/mysql-test/main/alter_table_online_debug.test b/mysql-test/main/alter_table_online_debug.test index 0299cd3b46e..c8386c6d8ab 100644 --- a/mysql-test/main/alter_table_online_debug.test +++ b/mysql-test/main/alter_table_online_debug.test @@ -4,8 +4,10 @@ --source include/have_innodb.inc --source include/have_sequence.inc --source include/have_partition.inc -set default_storage_engine= innodb; +let $default_storage_engine= `select @@global.default_storage_engine`; +set global default_storage_engine= innodb; +set default_storage_engine= innodb; --connect (con2, localhost, root,,) --connection default @@ -368,7 +370,7 @@ alter table t1 add b int NULL, algorithm= copy, lock= none; --connection con2 --reap ---error ER_DUP_ENTRY +--error ER_DUP_ENTRY,ER_DUP_KEY insert into t1 values (1),(2),(3),(4),(5),(6); select * from t1; set debug_sync= 'now SIGNAL end'; @@ -629,6 +631,7 @@ alter table t1 drop system versioning, algorithm= copy, lock= none; #--reap #show create table t1; #select * from t1; +drop table t1; --echo # --echo # Test ROLLBACK TO SAVEPOINT @@ -730,7 +733,7 @@ drop table t3; # # Lossy alter, Update_row_log_event cannot find 'abcde2' in the new table # -create table t1 (a char(6), b int) engine=innodb; +create table t1 (a char(6), b int); insert t1 values ('abcde1',1),('abcde2',2); --send set debug_sync= 'now wait_for downgraded' --connection con2 @@ -1007,7 +1010,7 @@ drop table t1; set debug_sync= 'reset'; --echo ## CHECK, UPDATE -create table t1 (a int) engine=innodb; +create table t1 (a int); insert t1 values (1),(2),(3),(4); --send set debug_sync= 'now wait_for downgraded' --connection con2 @@ -1026,7 +1029,7 @@ select * from t1; drop table t1; --echo ## DEFAULT, UPDATE -create table t1 (a int) engine=innodb; +create table t1 (a int); insert t1 values (1),(2),(3),(4); --send set debug_sync= 'now wait_for downgraded' --connection con2 @@ -1048,7 +1051,7 @@ drop table t1; set debug_sync= 'reset'; --echo ## VCOL + CHECK -create table t1 (a int) engine=innodb; +create table t1 (a int); insert t1 values (1),(2),(3),(4); --send set debug_sync= 'now wait_for downgraded' --connection con2 @@ -1097,8 +1100,8 @@ set debug_sync= reset; --echo ### -create table t1 (a text, unique(a)) engine=innodb; -create table t2 (b text, unique(b)) engine=innodb; +create table t1 (a text, unique(a)); +create table t2 (b text, unique(b)); insert into t2 values (null),(null); --send set debug_sync= 'now wait_for downgraded'; @@ -1126,7 +1129,7 @@ set debug_sync= reset; --echo # --echo # MDEV-29038 XA assertions failing in binlog_rollback and binlog_commit --echo # -create table t (a int) engine=innodb; +create table t (a int); insert into t values (1); xa begin 'xid'; --send @@ -1513,7 +1516,7 @@ drop table t; --echo # Test that correct fields are marked as explicit: --echo # Drop a, reorder b, add new column with default. --echo # -create table t (a int primary key, b int) engine=innodb; +create table t (a int primary key, b int); insert into t values (1, 1), (2, 2), (3, 3); set debug_sync= "alter_table_copy_end signal copy wait_for goon"; @@ -1539,7 +1542,7 @@ select * from t; drop table t; --echo # Test that all the fields are unpacked. -create table t (a int, b int) engine=innodb; +create table t (a int, b int); insert into t values (NULL, 123), (NULL, 456); set debug_sync= "alter_table_copy_end signal copy wait_for goon"; @@ -1711,7 +1714,7 @@ while($tx_iso_id) { dec $tx_iso_id; let tx_iso= `select level from iso_levels where id = $tx_iso_id`; -create table t1 (a int, b int, key(b)) engine=innodb; +create table t1 (a int, b int, key(b)); --connection con2 insert into t1 values (1,1),(null,null),(3,3),(4,null),(null,5); @@ -1738,8 +1741,8 @@ drop table iso_levels; --echo # MDEV-32126 Assertion fails upon online ALTER and binary log enabled create temporary table tmp (id int, primary key(id)) engine=innodb; -create table t1 (a int, b text) engine=innodb; -create table t2 (a int, b int, c char(8), d text, unique(a)) engine=innodb; +create table t1 (a int, b text); +create table t2 (a int, b int, c char(8), d text, unique(a)); insert into t2 values (1,1,'f','e'),(1000,1000,'c','b'); --connection default set debug_sync= 'alter_table_online_before_lock signal go_trx wait_for go_alter'; @@ -1760,7 +1763,7 @@ truncate t2; set @@binlog_format=mixed; --connection con2 start transaction; -create temporary table tmp (id int, primary key(id)) engine=innodb; +create temporary table tmp (id int, primary key(id)); insert into t1 values (1, repeat('x',8000)),(2, repeat('x',8000)); update t2 set b = null order by b limit 2; insert into t1 values (3, repeat('x',8000)); @@ -1793,7 +1796,7 @@ set debug_sync= reset; --echo # MDEV-32444 Data from orphaned XA transaction is lost after online alter -create table t (a int primary key) engine=innodb; +create table t (a int primary key); insert into t values (1); --echo # XA commit @@ -1919,6 +1922,7 @@ select * from t; --connection default drop table t; set debug_sync= reset; +eval set global default_storage_engine= $default_storage_engine; --disconnect con1 --disconnect con2 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 192/477] 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 f0fe23566b74f06641dc3c324b4969da783f6c7f Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 4 Nov 2023 16:12:41 +0200 Subject: [PATCH 193/477] Fixed some valgrind warnings from unixODBC used by CONNECT --- mysql-test/valgrind.supp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index e58d0a10124..1cdd7d5f64a 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -1170,6 +1170,16 @@ fun:_ZN7ODBConn10GetDriversEP7_qryres } +{ + ConnectSE: unixODBC SQLAllocEnv leaves some "still reachable" pointers + Memcheck:Leak + fun:malloc + fun:strdup + ... + obj:*/libodbc.so* + fun:_ZN7ODBConn12AllocConnectEj +} + { ConnectSE: unixODBC SQLAllocEnv leaves some "still reachable" pointers Memcheck:Leak @@ -1179,6 +1189,15 @@ fun:_ZN7ODBConn10GetDriversEP7_qryres } +{ + ConnectSE: unixODBC SQLAllocEnv leaves some "still reachable" pointers + Memcheck:Leak + fun:calloc + ... + obj:*/libodbc.so* + fun:_ZN7ODBConn12AllocConnectEj +} + { ConnectSE: unixODBC SQLAllocEnv leavs some "still reachable" pointers Memcheck:Leak From c68620df48cd1b0e7f5f1cb5ff8b905a5d9c80a5 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Sat, 4 Nov 2023 20:40:31 +0100 Subject: [PATCH 194/477] Fix random test failures in testcase perfschema.mdl_func The test case can get extra rows in its output from table performance_schema.table_handles, left there by an earlier test case (for example main.long_unique_delayed). So force a server restart at the beginning of the test. Signed-off-by: Kristian Nielsen --- mysql-test/suite/perfschema/r/mdl_func.result | 1 + mysql-test/suite/perfschema/t/mdl_func.test | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/mysql-test/suite/perfschema/r/mdl_func.result b/mysql-test/suite/perfschema/r/mdl_func.result index 4887b15efa5..f3fc0d10a96 100644 --- a/mysql-test/suite/perfschema/r/mdl_func.result +++ b/mysql-test/suite/perfschema/r/mdl_func.result @@ -1,3 +1,4 @@ +# restart UPDATE performance_schema.setup_instruments SET enabled = 'NO', timed = 'YES'; UPDATE performance_schema.setup_instruments SET enabled = 'YES' WHERE name in ('wait/io/table/sql/handler', diff --git a/mysql-test/suite/perfschema/t/mdl_func.test b/mysql-test/suite/perfschema/t/mdl_func.test index c7f5585a5c2..209c2f112af 100644 --- a/mysql-test/suite/perfschema/t/mdl_func.test +++ b/mysql-test/suite/perfschema/t/mdl_func.test @@ -1,5 +1,11 @@ --source include/not_embedded.inc --source include/have_perfschema.inc +# This test needs a fresh restart. The table performance_schema.table_handles +# can otherwise contain extra rows left from previous testcases. +# For example the test case main.long_unique_delayed, which uses +# INSERT DELAYED, will leave extra rows in this table if run just before this +# test, causing .result diff failure. +--source include/restart_mysqld.inc UPDATE performance_schema.setup_instruments SET enabled = 'NO', timed = 'YES'; From 1fa196a559e117f70fc3670cf768afb272ac99a6 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sun, 24 Jul 2022 00:40:06 +0400 Subject: [PATCH 195/477] MDEV-27595 Backport SQL service, introduced by MDEV-19275. The SQL SERVICE backported into the 10.4. --- include/mysql.h | 4 +- include/mysql/plugin_audit.h.pp | 18 + include/mysql/plugin_auth.h.pp | 18 + include/mysql/plugin_encryption.h.pp | 18 + include/mysql/plugin_ftparser.h.pp | 18 + include/mysql/plugin_password_validation.h.pp | 18 + include/mysql/service_sql.h | 104 ++ include/mysql/services.h | 1 + include/service_versions.h | 1 + include/sql_common.h | 2 +- libmysqld/lib_sql.cc | 23 +- libmysqld/libmysql.c | 5 - libservices/CMakeLists.txt | 1 + libservices/sql_service.c | 19 + .../suite/plugins/r/test_sql_service.result | 70 + .../suite/plugins/t/test_sql_service.test | 60 + plugin/server_audit/server_audit.c | 1 - plugin/test_sql_service/CMakeLists.txt | 18 + plugin/test_sql_service/COPYING | 339 +++++ plugin/test_sql_service/test_sql_service.c | 270 ++++ sql-common/client.c | 23 +- sql/mysqld.cc | 25 +- sql/protocol.cc | 13 +- sql/protocol.h | 14 +- sql/sql_class.h | 16 +- sql/sql_connect.cc | 2 +- sql/sql_plugin_services.inl | 19 +- sql/sql_prepare.cc | 1127 ++++++++++++----- sql/sql_prepare.h | 7 +- storage/example/ha_example.cc | 2 +- 30 files changed, 1843 insertions(+), 413 deletions(-) create mode 100644 include/mysql/service_sql.h create mode 100644 libservices/sql_service.c create mode 100644 mysql-test/suite/plugins/r/test_sql_service.result create mode 100644 mysql-test/suite/plugins/t/test_sql_service.test create mode 100644 plugin/test_sql_service/CMakeLists.txt create mode 100644 plugin/test_sql_service/COPYING create mode 100644 plugin/test_sql_service/test_sql_service.c diff --git a/include/mysql.h b/include/mysql.h index 3bc07d9c480..89807c07fce 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -331,7 +331,7 @@ typedef struct st_mysql_res { } MYSQL_RES; -#if !defined(MYSQL_SERVER) && !defined(MYSQL_CLIENT) +#if !defined(MYSQL_SERVICE_SQL) && !defined(MYSQL_CLIENT) #define MYSQL_CLIENT #endif @@ -363,7 +363,7 @@ typedef struct st_mysql_parameters */ #define MYSQL_WAIT_TIMEOUT 8 -#if !defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY) +#if !defined(MYSQL_SERVICE_SQL) #define max_allowed_packet (*mysql_get_parameters()->p_max_allowed_packet) #define net_buffer_length (*mysql_get_parameters()->p_net_buffer_length) #endif diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index aa3a98435b6..9039ce7336b 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -419,6 +419,24 @@ int json_escape_string(const char *str,const char *str_end, char *json, char *json_end); int json_unescape_json(const char *json_str, const char *json_end, char *res, char *res_end); +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index 1ed18350e9e..f5707c71f7c 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -419,6 +419,24 @@ int json_escape_string(const char *str,const char *str_end, char *json, char *json_end); int json_unescape_json(const char *json_str, const char *json_end, char *res, char *res_end); +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp index 4101686d725..3ae71b70703 100644 --- a/include/mysql/plugin_encryption.h.pp +++ b/include/mysql/plugin_encryption.h.pp @@ -419,6 +419,24 @@ int json_escape_string(const char *str,const char *str_end, char *json, char *json_end); int json_unescape_json(const char *json_str, const char *json_end, char *res, char *res_end); +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index aa8809edabc..d87046cef03 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -419,6 +419,24 @@ int json_escape_string(const char *str,const char *str_end, char *json, char *json_end); int json_unescape_json(const char *json_str, const char *json_end, char *res, char *res_end); +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp index d0b624fa0c5..f87e3502167 100644 --- a/include/mysql/plugin_password_validation.h.pp +++ b/include/mysql/plugin_password_validation.h.pp @@ -419,6 +419,24 @@ int json_escape_string(const char *str,const char *str_end, char *json, char *json_end); int json_unescape_json(const char *json_str, const char *json_end, char *res, char *res_end); +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); +} *sql_service; +MYSQL *mysql_real_connect_local(MYSQL *mysql); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/service_sql.h b/include/mysql/service_sql.h new file mode 100644 index 00000000000..ef6de8b34ef --- /dev/null +++ b/include/mysql/service_sql.h @@ -0,0 +1,104 @@ +/* Copyright (C) 2021 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 02111-1301 USA */ + +#ifndef MYSQL_SERVICE_SQL +#define MYSQL_SERVICE_SQL + +#ifndef MYSQL_ABI_CHECK +#include +#endif + +/** + @file + SQL service + + Interface for plugins to execute SQL queries on the local server. + + Functions of the service are the 'server-limited' client library: + mysql_init + mysql_real_connect_local + mysql_real_connect + mysql_errno + mysql_error + mysql_real_query + mysql_affected_rows + mysql_num_rows + mysql_store_result + mysql_free_result + mysql_fetch_row + mysql_close +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct sql_service_st { + MYSQL *(STDCALL *mysql_init_func)(MYSQL *mysql); + MYSQL *(*mysql_real_connect_local_func)(MYSQL *mysql); + MYSQL *(STDCALL *mysql_real_connect_func)(MYSQL *mysql, const char *host, + const char *user, const char *passwd, const char *db, unsigned int port, + const char *unix_socket, unsigned long clientflag); + unsigned int(STDCALL *mysql_errno_func)(MYSQL *mysql); + const char *(STDCALL *mysql_error_func)(MYSQL *mysql); + int (STDCALL *mysql_real_query_func)(MYSQL *mysql, const char *q, + unsigned long length); + my_ulonglong (STDCALL *mysql_affected_rows_func)(MYSQL *mysql); + my_ulonglong (STDCALL *mysql_num_rows_func)(MYSQL_RES *res); + MYSQL_RES *(STDCALL *mysql_store_result_func)(MYSQL *mysql); + void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); + MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); + void (STDCALL *mysql_close_func)(MYSQL *mysql); +} *sql_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define mysql_init(M) sql_service->mysql_init_func(M) +#define mysql_real_connect_local(M) sql_service->mysql_real_connect_local_func(M) +#define mysql_real_connect(M,H,U,PW,D,P,S,F) sql_service->mysql_real_connect_func(M,H,U,PW,D,P,S,F) +#define mysql_errno(M) sql_service->mysql_errno_func(M) +#define mysql_error(M) sql_service->mysql_error_func(M) +#define mysql_real_query sql_service->mysql_real_query_func +#define mysql_affected_rows(M) sql_service->mysql_affected_rows_func(M) +#define mysql_num_rows(R) sql_service->mysql_num_rows_func(R) +#define mysql_store_result(M) sql_service->mysql_store_result_func(M) +#define mysql_free_result(R) sql_service->mysql_free_result_func(R) +#define mysql_fetch_row(R) sql_service->mysql_fetch_row_func(R) +#define mysql_close(M) sql_service->mysql_close_func(M) + +#else + +/* + Establishes the connection to the 'local' server that started the plugin. + Like the mysql_real_connect() does for the remote server. + The established connection has no user/host associated to it, + neither it has the current db, so the queries should have + database/table name specified. +*/ +MYSQL *mysql_real_connect_local(MYSQL *mysql); + +/* The rest of the function declarations mest be taken from the mysql.h */ + +#endif /*MYSQL_DYNAMIC_PLUGIN*/ + + +#ifdef __cplusplus +} +#endif + +#endif /*MYSQL_SERVICE_SQL */ + + diff --git a/include/mysql/services.h b/include/mysql/services.h index 2c3a0ae421b..94f7bb3b2da 100644 --- a/include/mysql/services.h +++ b/include/mysql/services.h @@ -41,6 +41,7 @@ extern "C" { #include #include /*#include */ +#include #ifdef __cplusplus } diff --git a/include/service_versions.h b/include/service_versions.h index fb7e715f858..fc31583b14a 100644 --- a/include/service_versions.h +++ b/include/service_versions.h @@ -43,3 +43,4 @@ #define VERSION_thd_wait 0x0100 #define VERSION_wsrep 0x0400 #define VERSION_json 0x0100 +#define VERSION_sql_service 0x0100 diff --git a/include/sql_common.h b/include/sql_common.h index a61572e380c..0825e729e26 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -65,13 +65,13 @@ typedef struct st_mysql_methods MYSQL_ROW column, unsigned int field_count); void (*flush_use_result)(MYSQL *mysql, my_bool flush_all_results); int (*read_change_user_result)(MYSQL *mysql); + void (*on_close_free)(MYSQL *mysql); #if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) MYSQL_FIELD * (*list_fields)(MYSQL *mysql); my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt); int (*stmt_execute)(MYSQL_STMT *stmt); int (*read_binary_rows)(MYSQL_STMT *stmt); int (*unbuffered_fetch)(MYSQL *mysql, char **row); - void (*free_embedded_thd)(MYSQL *mysql); const char *(*read_statistics)(MYSQL *mysql); my_bool (*next_result)(MYSQL *mysql); int (*read_rows_from_cursor)(MYSQL_STMT *stmt); diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 565a722e13b..2dbfea1f6c0 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -43,7 +43,7 @@ C_MODE_START extern unsigned int mysql_server_last_errno; extern char mysql_server_last_error[MYSQL_ERRMSG_SIZE]; static my_bool emb_read_query_result(MYSQL *mysql); -static void emb_free_embedded_thd(MYSQL *mysql); +static void free_embedded_thd(MYSQL *mysql); static bool embedded_print_errors= 0; extern "C" void unireg_clear(int exit_code) @@ -121,7 +121,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, thd->killed= NOT_KILLED; else { - emb_free_embedded_thd(mysql); + free_embedded_thd(mysql); thd= 0; } } @@ -431,7 +431,7 @@ int emb_unbuffered_fetch(MYSQL *mysql, char **row) return 0; } -static void emb_free_embedded_thd(MYSQL *mysql) +static void free_embedded_thd(MYSQL *mysql) { THD *thd= (THD*)mysql->thd; server_threads.erase(thd); @@ -454,12 +454,25 @@ static MYSQL_RES * emb_store_result(MYSQL *mysql) return mysql_store_result(mysql); } -int emb_read_change_user_result(MYSQL *mysql) +static int emb_read_change_user_result(MYSQL *mysql) { mysql->net.read_pos= (uchar*)""; // fake an OK packet return mysql_errno(mysql) ? (int)packet_error : 1 /* length of the OK packet */; } + +static void emb_on_close_free(MYSQL *mysql) +{ + my_free(mysql->info_buffer); + mysql->info_buffer= 0; + if (mysql->thd) + { + free_embedded_thd(mysql); + mysql->thd= 0; + } +} + + MYSQL_METHODS embedded_methods= { emb_read_query_result, @@ -469,12 +482,12 @@ MYSQL_METHODS embedded_methods= emb_fetch_lengths, emb_flush_use_result, emb_read_change_user_result, + emb_on_close_free, emb_list_fields, emb_read_prepare_result, emb_stmt_execute, emb_read_binary_rows, emb_unbuffered_fetch, - emb_free_embedded_thd, emb_read_statistics, emb_read_query_result, emb_read_rows_from_cursor diff --git a/libmysqld/libmysql.c b/libmysqld/libmysql.c index b9293d84771..0551788ea28 100644 --- a/libmysqld/libmysql.c +++ b/libmysqld/libmysql.c @@ -1064,11 +1064,6 @@ unsigned int STDCALL mysql_field_count(MYSQL *mysql) return mysql->field_count; } -my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql) -{ - return mysql->affected_rows; -} - my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql) { return mysql->insert_id; diff --git a/libservices/CMakeLists.txt b/libservices/CMakeLists.txt index 274c8ce6dac..6b47bb53fdb 100644 --- a/libservices/CMakeLists.txt +++ b/libservices/CMakeLists.txt @@ -38,6 +38,7 @@ SET(MYSQLSERVICES_SOURCES thd_wait_service.c wsrep_service.c json_service.c + sql_service.c ) ADD_CONVENIENCE_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES}) diff --git a/libservices/sql_service.c b/libservices/sql_service.c new file mode 100644 index 00000000000..5c0102bfadf --- /dev/null +++ b/libservices/sql_service.c @@ -0,0 +1,19 @@ + +/* Copyright (c) 2018, Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +SERVICE_VERSION sql_service= (void*)VERSION_sql_service; diff --git a/mysql-test/suite/plugins/r/test_sql_service.result b/mysql-test/suite/plugins/r/test_sql_service.result new file mode 100644 index 00000000000..00f0411b665 --- /dev/null +++ b/mysql-test/suite/plugins/r/test_sql_service.result @@ -0,0 +1,70 @@ +install plugin test_sql_service soname 'test_sql_service'; +show status like 'test_sql_service_passed'; +Variable_name Value +Test_sql_service_passed 1 +set global test_sql_service_run_test= 1; +show status like 'test_sql_service_passed'; +Variable_name Value +Test_sql_service_passed 1 +set global test_sql_service_execute_sql_local= 'create table test.t1(id int)'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Query affected 0 rows. +set global test_sql_service_execute_sql_local= 'insert into test.t1 values (1), (2)'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Query affected 2 rows. +set global test_sql_service_execute_sql_local= 'select * from test.t1'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Query returned 2 rows. +set global test_sql_service_execute_sql_local= 'drop table test.t1'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Query affected 0 rows. +set global test_sql_service_execute_sql_local= 'drop table test.t1'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Error 1051 returned. Unknown table 'test.t1' +set global test_sql_service_execute_sql_global= 'create table test.t1(id int)'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Query affected 0 rows. +set global test_sql_service_execute_sql_global= 'insert into test.t1 values (1), (2)'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Query affected 2 rows. +set global test_sql_service_execute_sql_global= 'select * from test.t1'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Query returned 2 rows. +set global test_sql_service_execute_sql_global= 'drop table test.t1'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Query affected 0 rows. +set global test_sql_service_execute_sql_global= 'drop table test.t1'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Error 1051 returned. Unknown table 'test.t1' +create table t1 (id int, time timestamp); +insert into t1 values (1, NULL), (2, NULL), (3, NULL), (4, NULL), (5, NULL); +set global test_sql_service_execute_sql_global= 'select * FROM test.t1 WHERE time < DATE_SUB(NOW(), interval 5 minute)'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Query returned 0 rows. +set global test_sql_service_execute_sql_global= 'select * FROM test.t1 WHERE time <= NOW()'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Query returned 5 rows. +set global test_sql_service_execute_sql_local= 'select * FROM test.t1 WHERE time < DATE_SUB(NOW(), interval 5 minute)'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Query returned 0 rows. +set global test_sql_service_execute_sql_local= 'select * FROM test.t1 WHERE time <= NOW()'; +show status like 'test_sql_query_result'; +Variable_name Value +Test_sql_query_result Query returned 5 rows. +drop table t1; +uninstall plugin test_sql_service; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown diff --git a/mysql-test/suite/plugins/t/test_sql_service.test b/mysql-test/suite/plugins/t/test_sql_service.test new file mode 100644 index 00000000000..b80d78fe6e5 --- /dev/null +++ b/mysql-test/suite/plugins/t/test_sql_service.test @@ -0,0 +1,60 @@ +--source include/not_embedded.inc + +if (!$TEST_SQL_SERVICE_SO) { + skip No TEST_SQL_SERVICE plugin; +} + +# An unfortunate wait for check-testcase.test to complete disconnect. +let count_sessions= 1; +source include/wait_until_count_sessions.inc; + +install plugin test_sql_service soname 'test_sql_service'; +show status like 'test_sql_service_passed'; + +set global test_sql_service_run_test= 1; +show status like 'test_sql_service_passed'; + +set global test_sql_service_execute_sql_local= 'create table test.t1(id int)'; +show status like 'test_sql_query_result'; + +set global test_sql_service_execute_sql_local= 'insert into test.t1 values (1), (2)'; +show status like 'test_sql_query_result'; + +set global test_sql_service_execute_sql_local= 'select * from test.t1'; +show status like 'test_sql_query_result'; + +set global test_sql_service_execute_sql_local= 'drop table test.t1'; +show status like 'test_sql_query_result'; + +set global test_sql_service_execute_sql_local= 'drop table test.t1'; +show status like 'test_sql_query_result'; + +set global test_sql_service_execute_sql_global= 'create table test.t1(id int)'; +show status like 'test_sql_query_result'; + +set global test_sql_service_execute_sql_global= 'insert into test.t1 values (1), (2)'; +show status like 'test_sql_query_result'; + +set global test_sql_service_execute_sql_global= 'select * from test.t1'; +show status like 'test_sql_query_result'; + +set global test_sql_service_execute_sql_global= 'drop table test.t1'; +show status like 'test_sql_query_result'; + +set global test_sql_service_execute_sql_global= 'drop table test.t1'; +show status like 'test_sql_query_result'; + +create table t1 (id int, time timestamp); +insert into t1 values (1, NULL), (2, NULL), (3, NULL), (4, NULL), (5, NULL); +set global test_sql_service_execute_sql_global= 'select * FROM test.t1 WHERE time < DATE_SUB(NOW(), interval 5 minute)'; +show status like 'test_sql_query_result'; +set global test_sql_service_execute_sql_global= 'select * FROM test.t1 WHERE time <= NOW()'; +show status like 'test_sql_query_result'; +set global test_sql_service_execute_sql_local= 'select * FROM test.t1 WHERE time < DATE_SUB(NOW(), interval 5 minute)'; +show status like 'test_sql_query_result'; +set global test_sql_service_execute_sql_local= 'select * FROM test.t1 WHERE time <= NOW()'; +show status like 'test_sql_query_result'; +drop table t1; + +uninstall plugin test_sql_service; + diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 86f38edf724..8770ee1be0e 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -1145,7 +1145,6 @@ static void setup_connection_simple(struct connection_info *ci) #define MAX_HOSTNAME 61 -#define USERNAME_LENGTH 384 static void setup_connection_connect(struct connection_info *cn, const struct mysql_event_connection *event) diff --git a/plugin/test_sql_service/CMakeLists.txt b/plugin/test_sql_service/CMakeLists.txt new file mode 100644 index 00000000000..615508bdc4e --- /dev/null +++ b/plugin/test_sql_service/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright (C) 2013 Alexey Botchkov and SkySQL Ab +# +# 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 + +SET(SOURCES test_sql_service.c) + +MYSQL_ADD_PLUGIN(test_sql_service ${SOURCES} MODULE_ONLY) diff --git a/plugin/test_sql_service/COPYING b/plugin/test_sql_service/COPYING new file mode 100644 index 00000000000..6e475df5526 --- /dev/null +++ b/plugin/test_sql_service/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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; either version 2 of the License, or + (at your option) any later version. + + 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. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugin/test_sql_service/test_sql_service.c b/plugin/test_sql_service/test_sql_service.c new file mode 100644 index 00000000000..4ea6533af84 --- /dev/null +++ b/plugin/test_sql_service/test_sql_service.c @@ -0,0 +1,270 @@ +/* Copyright (C) 2019, Alexey Botchkov and 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 */ + + +#define PLUGIN_VERSION 0x200 + +#include +#define STRING_WITH_LEN(X) (X), ((size_t) (sizeof(X) - 1)) + +/* Status variables for SHOW STATUS */ +static long test_passed= 0; +static char *sql_text_local, *sql_text_global; +static char qwe_res[1024]= ""; + +static struct st_mysql_show_var test_sql_status[]= +{ + {"test_sql_service_passed", (char *)&test_passed, SHOW_LONG}, + {"test_sql_query_result", qwe_res, SHOW_CHAR}, + {0,0,0} +}; + +static my_bool do_test= 1; +static int run_test(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save, + struct st_mysql_value *value); +static int run_sql_local(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save, + struct st_mysql_value *value); +static int run_sql_global(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save, + struct st_mysql_value *value); + +static void noop_update(MYSQL_THD thd, struct st_mysql_sys_var *var, + void *var_ptr, const void *save); + +static MYSQL_SYSVAR_BOOL(run_test, do_test, + PLUGIN_VAR_OPCMDARG, + "Perform the test now.", + run_test, NULL, 0); + +static MYSQL_SYSVAR_STR(execute_sql_local, sql_text_local, + PLUGIN_VAR_OPCMDARG, + "Create the new local connection, execute SQL statement with it.", + run_sql_local, noop_update, 0); + +static MYSQL_SYSVAR_STR(execute_sql_global, sql_text_global, + PLUGIN_VAR_OPCMDARG, + "Execute SQL statement using the global connection.", + run_sql_global, noop_update, 0); + +static struct st_mysql_sys_var* test_sql_vars[]= +{ + MYSQL_SYSVAR(run_test), + MYSQL_SYSVAR(execute_sql_local), + MYSQL_SYSVAR(execute_sql_global), + NULL +}; + +static MYSQL *global_mysql; + + +static int run_queries(MYSQL *mysql) +{ + MYSQL_RES *res; + + if (mysql_real_query(mysql, + STRING_WITH_LEN("CREATE TABLE test.ts_table" + " ( hash varbinary(512)," + " time timestamp default current_time," + " primary key (hash), index tm (time) )"))) + return 1; + + if (mysql_real_query(mysql, + STRING_WITH_LEN("INSERT INTO test.ts_table VALUES('1234567890', NULL)"))) + return 1; + + if (mysql_real_query(mysql, STRING_WITH_LEN("select * from test.ts_table"))) + return 1; + + if (!(res= mysql_store_result(mysql))) + return 1; + + mysql_free_result(res); + + if (mysql_real_query(mysql, STRING_WITH_LEN("DROP TABLE test.ts_table"))) + return 1; + + return 0; +} + + +static int do_tests() +{ + MYSQL *mysql; + int result= 1; + + mysql= mysql_init(NULL); + if (mysql_real_connect_local(mysql) == NULL) + return 1; + + if (run_queries(mysql)) + goto exit; + + if (run_queries(global_mysql)) + goto exit; + + result= 0; +exit: + mysql_close(mysql); + + return result; +} + + +void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev) +{ +} + + +static int run_test(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save, + struct st_mysql_value *value) +{ + return (test_passed= (do_tests() == 0)) == 0; +} + + +static int run_sql(MYSQL *mysql, void *save, struct st_mysql_value *value) +{ + const char *str; + int len= 0; + MYSQL_RES *res; + + str= value->val_str(value, NULL, &len); + + if (mysql_real_query(mysql, str, len)) + { + if (mysql_error(mysql)[0]) + { + my_snprintf(qwe_res, sizeof(qwe_res), "Error %d returned. %s", + mysql_errno(mysql), mysql_error(mysql)); + return 0; + } + + return 1; + } + + if ((res= mysql_store_result(mysql))) + { + my_snprintf(qwe_res, sizeof(qwe_res), "Query returned %lld rows.", + mysql_num_rows(res)); + mysql_free_result(res); + } + else + { + if (mysql_error(mysql)[0]) + { + my_snprintf(qwe_res, sizeof(qwe_res), "Error %d returned. %s", + mysql_errno(mysql), mysql_error(mysql)); + } + else + my_snprintf(qwe_res, sizeof(qwe_res), "Query affected %lld rows.", + mysql_affected_rows(mysql)); + } + + return 0; +} + + +static void noop_update(MYSQL_THD thd, struct st_mysql_sys_var *var, + void *var_ptr, const void *save) +{ + sql_text_local= sql_text_global= qwe_res; +} + +static int run_sql_local(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save, + struct st_mysql_value *value) +{ + MYSQL *mysql; + int result= 1; + + mysql= mysql_init(NULL); + if (mysql_real_connect_local(mysql) == NULL) + return 1; + + if (run_sql(mysql, save, value)) + goto exit; + + result= 0; + +exit: + mysql_close(mysql); + + return result; +} + + +static int run_sql_global(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save, + struct st_mysql_value *value) +{ + return run_sql(global_mysql, save, value); +} + + +static int init_done= 0; + +static int test_sql_service_plugin_init(void *p) +{ + (void) p; + global_mysql= mysql_init(NULL); + + if (!global_mysql || + mysql_real_connect_local(global_mysql) == NULL) + return 1; + + init_done= 1; + + test_passed= (do_tests() == 0); + + return 0; +} + + +static int test_sql_service_plugin_deinit(void *p) +{ + (void) p; + if (!init_done) + return 0; + + mysql_close(global_mysql); + + return 0; +} + + +static struct st_mysql_audit maria_descriptor = +{ + MYSQL_AUDIT_INTERFACE_VERSION, + NULL, + auditing, + { MYSQL_AUDIT_GENERAL_CLASSMASK | + MYSQL_AUDIT_TABLE_CLASSMASK | + MYSQL_AUDIT_CONNECTION_CLASSMASK } +}; +maria_declare_plugin(test_sql_service) +{ + MYSQL_AUDIT_PLUGIN, + &maria_descriptor, + "TEST_SQL_SERVICE", + "Alexey Botchkov (MariaDB Corporation)", + "Test SQL service", + PLUGIN_LICENSE_GPL, + test_sql_service_plugin_init, + test_sql_service_plugin_deinit, + PLUGIN_VERSION, + test_sql_status, + test_sql_vars, + NULL, + MariaDB_PLUGIN_MATURITY_STABLE +} +maria_declare_plugin_end; + diff --git a/sql-common/client.c b/sql-common/client.c index 6f4ea70a733..830c3600df2 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1670,14 +1670,14 @@ static MYSQL_METHODS client_methods= cli_use_result, /* use_result */ cli_fetch_lengths, /* fetch_lengths */ cli_flush_use_result, /* flush_use_result */ - cli_read_change_user_result /* read_change_user_result */ + cli_read_change_user_result, /* read_change_user_result */ + NULL /* on_close_free */ #ifndef MYSQL_SERVER ,cli_list_fields, /* list_fields */ cli_read_prepare_result, /* read_prepare_result */ cli_stmt_execute, /* stmt_execute */ cli_read_binary_rows, /* read_binary_rows */ cli_unbuffered_fetch, /* unbuffered_fetch */ - NULL, /* free_embedded_thd */ cli_read_statistics, /* read_statistics */ cli_read_query_result, /* next_result */ cli_read_binary_rows /* read_rows_from_cursor */ @@ -3351,10 +3351,8 @@ static void mysql_close_free(MYSQL *mysql) my_free(mysql->user); my_free(mysql->passwd); my_free(mysql->db); -#if defined(EMBEDDED_LIBRARY) || MYSQL_VERSION_ID >= 50100 - my_free(mysql->info_buffer); - mysql->info_buffer= 0; -#endif + if (mysql->methods && mysql->methods->on_close_free) + (*mysql->methods->on_close_free)(mysql); /* Clear pointers for better safety */ mysql->host_info= mysql->user= mysql->passwd= mysql->db= 0; } @@ -3473,13 +3471,6 @@ void STDCALL mysql_close(MYSQL *mysql) mysql_close_free_options(mysql); mysql_close_free(mysql); mysql_detach_stmt_list(&mysql->stmts, "mysql_close"); -#ifndef MYSQL_SERVER - if (mysql->thd) - { - (*mysql->methods->free_embedded_thd)(mysql); - mysql->thd= 0; - } -#endif if (mysql->free_me) my_free(mysql); } @@ -4301,3 +4292,9 @@ int STDCALL mysql_cancel(MYSQL *mysql) return vio_shutdown(mysql->net.vio, SHUT_RDWR); return -1; } + +my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql) +{ + return mysql->affected_rows; +} + diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 93e9ac54550..de2e1c7622e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1508,6 +1508,16 @@ static void end_ssl(); #ifndef EMBEDDED_LIBRARY +extern Atomic_counter local_connection_thread_count; + +uint THD_count::connection_thd_count() +{ + return value() - + binlog_dump_thread_count - + local_connection_thread_count; +} + + /**************************************************************************** ** Code to end mysqld ****************************************************************************/ @@ -1780,10 +1790,8 @@ static void close_connections(void) */ DBUG_PRINT("info", ("THD_count: %u", THD_count::value())); - for (int i= 0; (THD_count::value() - binlog_dump_thread_count - - n_threads_awaiting_ack) && - i < 1000; - i++) + for (int i= 0; THD_count::connection_thd_count() - n_threads_awaiting_ack + && i < 1000; i++) my_sleep(20000); if (global_system_variables.log_warnings) @@ -1801,13 +1809,12 @@ static void close_connections(void) THD_count::value() - binlog_dump_thread_count - n_threads_awaiting_ack)); - while (THD_count::value() - binlog_dump_thread_count - - n_threads_awaiting_ack) + while (THD_count::connection_thd_count() - n_threads_awaiting_ack) my_sleep(1000); /* Kill phase 2 */ server_threads.iterate(kill_thread_phase_2); - for (uint64 i= 0; THD_count::value(); i++) + for (uint64 i= 0; THD_count::connection_thd_count(); i++) { /* This time the warnings are emitted within the loop to provide a @@ -2570,7 +2577,7 @@ void close_connection(THD *thd, uint sql_errno) if (sql_errno) { - net_send_error(thd, sql_errno, ER_DEFAULT(sql_errno), NULL); + thd->protocol->net_send_error(thd, sql_errno, ER_DEFAULT(sql_errno), NULL); thd->print_aborted_warning(lvl, ER_DEFAULT(sql_errno)); } else if (!thd->main_security_ctx.user) @@ -5225,6 +5232,7 @@ static int init_server_components() init_global_table_stats(); init_global_index_stats(); + init_update_queries(); /* Allow storage engine to give real error messages */ if (unlikely(ha_init_errors())) @@ -5470,7 +5478,6 @@ static int init_server_components() ft_init_stopwords(); init_max_user_conn(); - init_update_queries(); init_global_user_stats(); init_global_client_stats(); if (!opt_bootstrap) diff --git a/sql/protocol.cc b/sql/protocol.cc index 5ec887e13d7..5f89c396139 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -33,11 +33,6 @@ static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024; /* Declared non-static only because of the embedded library. */ -bool net_send_error_packet(THD *, uint, const char *, const char *); -/* Declared non-static only because of the embedded library. */ -bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *, - bool, bool); -/* Declared non-static only because of the embedded library. */ bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count); #ifndef EMBEDDED_LIBRARY static bool write_eof_packet(THD *, NET *, uint, uint); @@ -147,7 +142,7 @@ bool Protocol_binary::net_store_data_cs(const uchar *from, size_t length, @retval TRUE An error occurred and the message wasn't sent properly */ -bool net_send_error(THD *thd, uint sql_errno, const char *err, +bool Protocol::net_send_error(THD *thd, uint sql_errno, const char *err, const char* sqlstate) { bool error; @@ -209,7 +204,7 @@ bool net_send_error(THD *thd, uint sql_errno, const char *err, #ifndef EMBEDDED_LIBRARY bool -net_send_ok(THD *thd, +Protocol::net_send_ok(THD *thd, uint server_status, uint statement_warn_count, ulonglong affected_rows, ulonglong id, const char *message, bool is_eof, @@ -321,7 +316,7 @@ static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */ */ bool -net_send_eof(THD *thd, uint server_status, uint statement_warn_count) +Protocol::net_send_eof(THD *thd, uint server_status, uint statement_warn_count) { NET *net= &thd->net; bool error= FALSE; @@ -412,7 +407,7 @@ static bool write_eof_packet(THD *thd, NET *net, @retval TRUE An error occurred and the messages wasn't sent properly */ -bool net_send_error_packet(THD *thd, uint sql_errno, const char *err, +bool Protocol::net_send_error_packet(THD *thd, uint sql_errno, const char *err, const char* sqlstate) { diff --git a/sql/protocol.h b/sql/protocol.h index 464af7bbaa0..8632f155847 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -49,14 +49,13 @@ protected: } #endif uint field_count; -#ifndef EMBEDDED_LIBRARY - bool net_store_data(const uchar *from, size_t length); - bool net_store_data_cs(const uchar *from, size_t length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs); -#else virtual bool net_store_data(const uchar *from, size_t length); virtual bool net_store_data_cs(const uchar *from, size_t length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs); + virtual bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *, + bool, bool); + virtual bool net_send_error_packet(THD *, uint, const char *, const char *); +#ifdef EMBEDDED_LIBRARY char **next_field; MYSQL_FIELD *next_mysql_field; MEM_ROOT *alloc; @@ -156,6 +155,9 @@ public: }; virtual enum enum_protocol_type type()= 0; + virtual bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count); + bool net_send_error(THD *thd, uint sql_errno, const char *err, + const char* sqlstate); void end_statement(); friend int send_answer_1(Protocol *protocol, String *s1, String *s2, @@ -289,8 +291,6 @@ public: void send_warning(THD *thd, uint sql_errno, const char *err=0); -bool net_send_error(THD *thd, uint sql_errno, const char *err, - const char* sqlstate); void net_send_progress_packet(THD *thd); uchar *net_store_data(uchar *to,const uchar *from, size_t length); uchar *net_store_data(uchar *to,int32 from); diff --git a/sql/sql_class.h b/sql/sql_class.h index c7f36ce3d8c..9427cc4faa5 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1035,6 +1035,7 @@ struct THD_count { static Atomic_counter count; static uint value() { return static_cast(count); } + static uint connection_thd_count(); THD_count() { count++; } ~THD_count() { count--; } }; @@ -3622,6 +3623,11 @@ public: user_time= t; set_time(); } + inline void force_set_time(my_time_t t, ulong sec_part) + { + start_time= system_time.sec= t; + start_time_sec_part= system_time.sec_part= sec_part; + } /* this is only used by replication and BINLOG command. usecs > TIME_MAX_SECOND_PART means "was not in binlog" @@ -3633,15 +3639,9 @@ public: else { if (sec_part <= TIME_MAX_SECOND_PART) - { - start_time= system_time.sec= t; - start_time_sec_part= system_time.sec_part= sec_part; - } + force_set_time(t, sec_part); else if (t != system_time.sec) - { - start_time= system_time.sec= t; - start_time_sec_part= system_time.sec_part= 0; - } + force_set_time(t, 0); else { start_time= t; diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 1c267e02839..263c9eab832 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1477,7 +1477,7 @@ void CONNECT::close_with_error(uint sql_errno, if (thd) { if (sql_errno) - net_send_error(thd, sql_errno, message, NULL); + thd->protocol->net_send_error(thd, sql_errno, message, NULL); close_connection(thd, close_error); delete thd; set_current_thd(0); diff --git a/sql/sql_plugin_services.inl b/sql/sql_plugin_services.inl index 519a21ee9c6..2cab05529df 100644 --- a/sql/sql_plugin_services.inl +++ b/sql/sql_plugin_services.inl @@ -222,6 +222,22 @@ struct json_service_st json_handler= json_unescape_json }; +struct sql_service_st sql_service_handler= +{ + mysql_init, + mysql_real_connect_local, + mysql_real_connect, + mysql_errno, + mysql_error, + mysql_real_query, + mysql_affected_rows, + mysql_num_rows, + mysql_store_result, + mysql_free_result, + mysql_fetch_row, + mysql_close, +}; + static struct st_service_ref list_of_services[]= { { "base64_service", VERSION_base64, &base64_handler }, @@ -245,5 +261,6 @@ static struct st_service_ref list_of_services[]= { "thd_timezone_service", VERSION_thd_timezone, &thd_timezone_handler }, { "thd_wait_service", VERSION_thd_wait, &thd_wait_handler }, { "wsrep_service", VERSION_wsrep, &wsrep_handler }, - { "json_service", VERSION_json, &json_handler } + { "json_service", VERSION_json, &json_handler }, + { "sql_service", VERSION_sql_service, &sql_service_handler }, }; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 63ce4d4c26d..68087d333b0 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -129,6 +129,7 @@ static const uint PARAMETER_FLAG_UNSIGNED= 128U << 8; #include "wsrep_mysqld.h" #include "wsrep_trans_observer.h" #endif /* WITH_WSREP */ +#include "sql_audit.h" // mysql_audit_release /** A result class used to send cursor rows using the binary protocol. @@ -258,63 +259,6 @@ private: class Ed_connection; -/** - Protocol_local: a helper class to intercept the result - of the data written to the network. -*/ - -class Protocol_local :public Protocol -{ -public: - Protocol_local(THD *thd, Ed_connection *ed_connection); - ~Protocol_local() { free_root(&m_rset_root, MYF(0)); } -protected: - virtual void prepare_for_resend(); - virtual bool write(); - virtual bool store_null(); - virtual bool store_tiny(longlong from); - virtual bool store_short(longlong from); - virtual bool store_long(longlong from); - virtual bool store_longlong(longlong from, bool unsigned_flag); - virtual bool store_decimal(const my_decimal *); - virtual bool store(const char *from, size_t length, CHARSET_INFO *cs); - virtual bool store(const char *from, size_t length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs); - virtual bool store(MYSQL_TIME *time, int decimals); - virtual bool store_date(MYSQL_TIME *time); - virtual bool store_time(MYSQL_TIME *time, int decimals); - virtual bool store(float value, uint32 decimals, String *buffer); - virtual bool store(double value, uint32 decimals, String *buffer); - virtual bool store(Field *field); - - virtual bool send_result_set_metadata(List *list, uint flags); - virtual bool send_out_parameters(List *sp_params); -#ifdef EMBEDDED_LIBRARY - void remove_last_row(); -#endif - virtual enum enum_protocol_type type() { return PROTOCOL_LOCAL; }; - - virtual bool send_ok(uint server_status, uint statement_warn_count, - ulonglong affected_rows, ulonglong last_insert_id, - const char *message, bool skip_flush); - - virtual bool send_eof(uint server_status, uint statement_warn_count); - virtual bool send_error(uint sql_errno, const char *err_msg, const char* sqlstate); -private: - bool store_string(const char *str, size_t length, - CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs); - - bool store_column(const void *data, size_t length); - void opt_add_row_to_rset(); -private: - Ed_connection *m_connection; - MEM_ROOT m_rset_root; - List *m_rset; - size_t m_column_count; - Ed_column *m_current_row; - Ed_column *m_current_column; -}; - /****************************************************************************** Implementation ******************************************************************************/ @@ -3951,19 +3895,22 @@ Execute_sql_statement(LEX_STRING sql_text) executions without having to cleanup/reset THD in between. */ -bool -Execute_sql_statement::execute_server_code(THD *thd) +static bool execute_server_code(THD *thd, + const char *sql_text, size_t sql_len) { PSI_statement_locker *parent_locker; bool error; + query_id_t save_query_id= thd->query_id; + query_id_t next_id= next_query_id(); - if (alloc_query(thd, m_sql_text.str, m_sql_text.length)) + if (alloc_query(thd, sql_text, sql_len)) return TRUE; Parser_state parser_state; if (parser_state.init(thd, thd->query(), thd->query_length())) return TRUE; + thd->query_id= next_id; parser_state.m_lip.multi_statements= FALSE; lex_start(thd); @@ -3981,16 +3928,26 @@ Execute_sql_statement::execute_server_code(THD *thd) /* report error issued during command execution */ if (likely(error == 0) && thd->spcont == NULL) - general_log_write(thd, COM_STMT_EXECUTE, + general_log_write(thd, COM_QUERY, thd->query(), thd->query_length()); end: thd->lex->restore_set_statement_var(); + thd->query_id= save_query_id; + delete_explain_query(thd->lex); + lex_end(thd->lex); return error; } + +bool Execute_sql_statement::execute_server_code(THD *thd) +{ + return ::execute_server_code(thd, m_sql_text.str, m_sql_text.length); +} + + /*************************************************************************** Prepared_statement ****************************************************************************/ @@ -5309,12 +5266,12 @@ Ed_connection::free_old_result() */ bool -Ed_connection::execute_direct(LEX_STRING sql_text) +Ed_connection::execute_direct(Protocol *p, LEX_STRING sql_text) { Execute_sql_statement execute_sql_statement(sql_text); DBUG_PRINT("ed_query", ("%s", sql_text.str)); - return execute_direct(&execute_sql_statement); + return execute_direct(p, &execute_sql_statement); } @@ -5331,10 +5288,9 @@ Ed_connection::execute_direct(LEX_STRING sql_text) @param server_runnable A code fragment to execute. */ -bool Ed_connection::execute_direct(Server_runnable *server_runnable) +bool Ed_connection::execute_direct(Protocol *p, Server_runnable *server_runnable) { bool rc= FALSE; - Protocol_local protocol_local(m_thd, this); Prepared_statement stmt(m_thd); Protocol *save_protocol= m_thd->protocol; Diagnostics_area *save_diagnostics_area= m_thd->get_stmt_da(); @@ -5343,7 +5299,7 @@ bool Ed_connection::execute_direct(Server_runnable *server_runnable) free_old_result(); /* Delete all data from previous execution, if any */ - m_thd->protocol= &protocol_local; + m_thd->protocol= p; m_thd->set_stmt_da(&m_diagnostics_area); rc= stmt.execute_server_runnable(server_runnable); @@ -5430,354 +5386,831 @@ Ed_connection::store_result_set() return ed_result_set; } -/************************************************************************* -* Protocol_local -**************************************************************************/ +#include +#include "../libmysqld/embedded_priv.h" -Protocol_local::Protocol_local(THD *thd, Ed_connection *ed_connection) - :Protocol(thd), - m_connection(ed_connection), - m_rset(NULL), - m_column_count(0), - m_current_row(NULL), - m_current_column(NULL) +class Protocol_local : public Protocol_text { - clear_alloc_root(&m_rset_root); +public: + struct st_mysql_data *cur_data; + struct st_mysql_data *first_data; + struct st_mysql_data **data_tail; + void clear_data_list(); + struct st_mysql_data *alloc_new_dataset(); + char **next_field; + MYSQL_FIELD *next_mysql_field; + MEM_ROOT *alloc; + THD *new_thd; + Security_context empty_ctx; + + Protocol_local(THD *thd_arg, THD *new_thd_arg, ulong prealloc) : + Protocol_text(thd_arg, prealloc), + cur_data(0), first_data(0), data_tail(&first_data), alloc(0), + new_thd(new_thd_arg) + {} + +protected: + bool net_store_data(const uchar *from, size_t length); + bool net_store_data_cs(const uchar *from, size_t length, + CHARSET_INFO *fromcs, CHARSET_INFO *tocs); + bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count); + bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *, + bool, bool); + bool net_send_error_packet(THD *, uint, const char *, const char *); + bool begin_dataset(); + bool begin_dataset(THD *thd, uint numfields); + + bool write(); + bool flush(); + + bool store_field_metadata(const THD *thd, const Send_field &field, + CHARSET_INFO *charset_for_protocol, + uint pos); + bool send_result_set_metadata(List *list, uint flags); + void remove_last_row(); + bool store_null(); + void prepare_for_resend(); + bool send_list_fields(List *list, const TABLE_LIST *table_list); + + enum enum_protocol_type type() { return PROTOCOL_LOCAL; }; +}; + +static +bool +write_eof_packet_local(THD *thd, + Protocol_local *p, uint server_status, uint statement_warn_count) +{ +// if (!thd->mysql) // bootstrap file handling +// return FALSE; + /* + The following test should never be true, but it's better to do it + because if 'is_fatal_error' is set the server is not going to execute + other queries (see the if test in dispatch_command / COM_QUERY) + */ + if (thd->is_fatal_error) + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; + p->cur_data->embedded_info->server_status= server_status; + /* + Don't send warn count during SP execution, as the warn_list + is cleared between substatements, and mysqltest gets confused + */ + p->cur_data->embedded_info->warning_count= + (thd->spcont ? 0 : MY_MIN(statement_warn_count, 65535)); + return FALSE; } -/** - Called between two result set rows. - Prepare structures to fill result set rows. - Unfortunately, we can't return an error here. If memory allocation - fails, we'll have to return an error later. And so is done - in methods such as @sa store_column(). -*/ - -void Protocol_local::prepare_for_resend() +MYSQL_DATA *Protocol_local::alloc_new_dataset() { - DBUG_ASSERT(alloc_root_inited(&m_rset_root)); + MYSQL_DATA *data; + struct embedded_query_result *emb_data; + if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), + &data, sizeof(*data), + &emb_data, sizeof(*emb_data), + NULL)) + return NULL; - opt_add_row_to_rset(); - /* Start a new row. */ - m_current_row= (Ed_column *) alloc_root(&m_rset_root, - sizeof(Ed_column) * m_column_count); - m_current_column= m_current_row; + emb_data->prev_ptr= &data->data; + cur_data= data; + *data_tail= data; + data_tail= &emb_data->next; + data->embedded_info= emb_data; + return data; +} + + +void Protocol_local::clear_data_list() +{ + while (first_data) + { + MYSQL_DATA *data= first_data; + first_data= data->embedded_info->next; + free_rows(data); + } + data_tail= &first_data; + free_rows(cur_data); + cur_data= 0; +} + + +static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length, + CHARSET_INFO *fromcs, CHARSET_INFO *tocs) +{ + uint32 dummy32; + uint dummy_err; + char *result; + + /* 'tocs' is set 0 when client issues SET character_set_results=NULL */ + if (tocs && String::needs_conversion(0, fromcs, tocs, &dummy32)) + { + uint new_len= (tocs->mbmaxlen * length) / fromcs->mbminlen + 1; + result= (char *)alloc_root(root, new_len); + length= copy_and_convert(result, new_len, + tocs, from, length, fromcs, &dummy_err); + } + else + { + result= (char *)alloc_root(root, length + 1); + memcpy(result, from, length); + } + + result[length]= 0; + return result; +} + + +static char *dup_str_aux(MEM_ROOT *root, const LEX_CSTRING &from, + CHARSET_INFO *fromcs, CHARSET_INFO *tocs) +{ + return dup_str_aux(root, from.str, (uint) from.length, fromcs, tocs); +} + + +static char *dup_str_aux(MEM_ROOT *root, const char *from, + CHARSET_INFO *fromcs, CHARSET_INFO *tocs) +{ + return dup_str_aux(root, from, from ? strlen(from) : 0 , fromcs, tocs); +} + + +bool Protocol_local::net_store_data(const uchar *from, size_t length) +{ + char *field_buf; +// if (!thd->mysql) // bootstrap file handling +// return FALSE; + + if (!(field_buf= (char*) alloc_root(alloc, length + sizeof(uint) + 1))) + return TRUE; + *(uint *)field_buf= (uint) length; + *next_field= field_buf + sizeof(uint); + memcpy((uchar*) *next_field, from, length); + (*next_field)[length]= 0; + if (next_mysql_field->max_length < length) + next_mysql_field->max_length= (unsigned long) length; + ++next_field; + ++next_mysql_field; + return FALSE; +} + + +bool Protocol_local::net_store_data_cs(const uchar *from, size_t length, + CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) +{ + uint conv_length= (uint) (to_cs->mbmaxlen * length / from_cs->mbminlen); + uint dummy_error; + char *field_buf; +// if (!thd->mysql) // bootstrap file handling +// return false; + + if (!(field_buf= (char*) alloc_root(alloc, conv_length + sizeof(uint) + 1))) + return true; + *next_field= field_buf + sizeof(uint); + length= copy_and_convert(*next_field, conv_length, to_cs, + (const char*) from, length, from_cs, &dummy_error); + *(uint *) field_buf= (uint) length; + (*next_field)[length]= 0; + if (next_mysql_field->max_length < length) + next_mysql_field->max_length= (unsigned long) length; + ++next_field; + ++next_mysql_field; + return false; } /** - In "real" protocols this is called to finish a result set row. - Unused in the local implementation. + Embedded library implementation of OK response. + + This function is used by the server to write 'OK' packet to + the "network" when the server is compiled as an embedded library. + Since there is no network in the embedded configuration, + a different implementation is necessary. + Instead of marshalling response parameters to a network representation + and then writing it to the socket, here we simply copy the data to the + corresponding client-side connection structures. + + @sa Server implementation of net_send_ok in protocol.cc for + description of the arguments. + + @return + @retval TRUE An error occurred + @retval FALSE Success */ +bool +Protocol_local::net_send_ok(THD *thd, + uint server_status, uint statement_warn_count, + ulonglong affected_rows, ulonglong id, const char *message, bool, bool) +{ + DBUG_ENTER("emb_net_send_ok"); + MYSQL_DATA *data; +// MYSQL *mysql= thd->mysql; + +// if (!mysql) // bootstrap file handling +// DBUG_RETURN(FALSE); + if (!(data= alloc_new_dataset())) + DBUG_RETURN(TRUE); + data->embedded_info->affected_rows= affected_rows; + data->embedded_info->insert_id= id; + if (message) + strmake_buf(data->embedded_info->info, message); + + bool error= write_eof_packet_local(thd, this, + server_status, statement_warn_count); + cur_data= 0; + DBUG_RETURN(error); +} + + +/** + Embedded library implementation of EOF response. + + @sa net_send_ok + + @return + @retval TRUE An error occurred + @retval FALSE Success +*/ + +bool +Protocol_local::net_send_eof(THD *thd, uint server_status, + uint statement_warn_count) +{ + bool error= write_eof_packet_local(thd, this, server_status, + statement_warn_count); + cur_data= 0; + return error; +} + + +bool Protocol_local::net_send_error_packet(THD *thd, uint sql_errno, + const char *err, const char *sqlstate) +{ + uint error; + char converted_err[MYSQL_ERRMSG_SIZE]; + MYSQL_DATA *data= cur_data; + struct embedded_query_result *ei; + +// if (!thd->mysql) // bootstrap file handling +// { +// fprintf(stderr, "ERROR: %d %s\n", sql_errno, err); +// return TRUE; +// } + if (!data) + data= alloc_new_dataset(); + + ei= data->embedded_info; + ei->last_errno= sql_errno; + convert_error_message(converted_err, sizeof(converted_err), + thd->variables.character_set_results, + err, strlen(err), + system_charset_info, &error); + /* Converted error message is always null-terminated. */ + strmake_buf(ei->info, converted_err); + strmov(ei->sqlstate, sqlstate); + ei->server_status= thd->server_status; + cur_data= 0; + return FALSE; +} + + +bool Protocol_local::begin_dataset() +{ + MYSQL_DATA *data= alloc_new_dataset(); + if (!data) + return 1; + alloc= &data->alloc; + /* Assume rowlength < 8192 */ + init_alloc_root(alloc, "dataset", 8192, 0, MYF(0)); + alloc->min_malloc= sizeof(MYSQL_ROWS); + return 0; +} + + +bool Protocol_local::begin_dataset(THD *thd, uint numfields) +{ + if (begin_dataset()) + return true; + MYSQL_DATA *data= cur_data; + data->fields= field_count= numfields; + if (!(data->embedded_info->fields_list= + (MYSQL_FIELD*)alloc_root(&data->alloc, sizeof(MYSQL_FIELD)*field_count))) + return true; + return false; +} + + bool Protocol_local::write() { - return FALSE; +// if (!thd->mysql) // bootstrap file handling +// return false; + + *next_field= 0; + return false; } -/** - A helper function to add the current row to the current result - set. Called in @sa prepare_for_resend(), when a new row is started, - and in send_eof(), when the result set is finished. -*/ -void Protocol_local::opt_add_row_to_rset() +bool Protocol_local::flush() { - if (m_current_row) + return 0; +} + + +bool Protocol_local::store_field_metadata(const THD * thd, + const Send_field &server_field, + CHARSET_INFO *charset_for_protocol, + uint pos) +{ + CHARSET_INFO *cs= system_charset_info; + CHARSET_INFO *thd_cs= thd->variables.character_set_results; + MYSQL_DATA *data= cur_data; + MEM_ROOT *field_alloc= &data->alloc; + MYSQL_FIELD *client_field= &cur_data->embedded_info->fields_list[pos]; + DBUG_ASSERT(server_field.is_sane()); + + client_field->db= dup_str_aux(field_alloc, server_field.db_name, + cs, thd_cs); + client_field->table= dup_str_aux(field_alloc, server_field.table_name, + cs, thd_cs); + client_field->name= dup_str_aux(field_alloc, server_field.col_name, + cs, thd_cs); + client_field->org_table= dup_str_aux(field_alloc, server_field.org_table_name, + cs, thd_cs); + client_field->org_name= dup_str_aux(field_alloc, server_field.org_col_name, + cs, thd_cs); + if (charset_for_protocol == &my_charset_bin || thd_cs == NULL) { - /* Add the old row to the result set */ - Ed_row *ed_row= new (&m_rset_root) Ed_row(m_current_row, m_column_count); - if (ed_row) - m_rset->push_back(ed_row, &m_rset_root); + /* No conversion */ + client_field->charsetnr= charset_for_protocol->number; + client_field->length= server_field.length; + } + else + { + /* With conversion */ + client_field->charsetnr= thd_cs->number; + client_field->length= server_field.max_octet_length(charset_for_protocol, + thd_cs); + } + client_field->type= server_field.type_handler()->type_code_for_protocol(); + client_field->flags= (uint16) server_field.flags; + client_field->decimals= server_field.decimals; + + client_field->db_length= (unsigned int) strlen(client_field->db); + client_field->table_length= (unsigned int) strlen(client_field->table); + client_field->name_length= (unsigned int) strlen(client_field->name); + client_field->org_name_length= (unsigned int) strlen(client_field->org_name); + client_field->org_table_length= (unsigned int) strlen(client_field->org_table); + + client_field->catalog= dup_str_aux(field_alloc, "def", 3, cs, thd_cs); + client_field->catalog_length= 3; + + if (IS_NUM(client_field->type)) + client_field->flags|= NUM_FLAG; + + client_field->max_length= 0; + client_field->def= 0; + return false; +} + + +void Protocol_local::remove_last_row() +{ + MYSQL_DATA *data= cur_data; + MYSQL_ROWS **last_row_hook= &data->data; + my_ulonglong count= data->rows; + DBUG_ENTER("Protocol_text::remove_last_row"); + while (--count) + last_row_hook= &(*last_row_hook)->next; + + *last_row_hook= 0; + data->embedded_info->prev_ptr= last_row_hook; + data->rows--; + + DBUG_VOID_RETURN; +} + + +bool Protocol_local::send_result_set_metadata(List *list, uint flags) +{ + List_iterator_fast it(*list); + Item *item; + DBUG_ENTER("send_result_set_metadata"); + +// if (!thd->mysql) // bootstrap file handling +// DBUG_RETURN(0); + + if (begin_dataset(thd, list->elements)) + goto err; + + for (uint pos= 0 ; (item= it++); pos++) + { + Send_field sf(thd, item); + if (store_field_metadata(thd, sf, item->charset_for_protocol(), pos)) + goto err; + } + + if (flags & SEND_EOF) + write_eof_packet_local(thd, this, thd->server_status, + thd->get_stmt_da()->current_statement_warn_count()); + + DBUG_RETURN(prepare_for_send(list->elements)); + err: + my_error(ER_OUT_OF_RESOURCES, MYF(0)); /* purecov: inspected */ + DBUG_RETURN(1); /* purecov: inspected */ +} + + +static void +list_fields_send_default(THD *thd, Protocol_local *p, Field *fld, uint pos) +{ + char buff[80]; + String tmp(buff, sizeof(buff), default_charset_info), *res; + MYSQL_FIELD *client_field= &p->cur_data->embedded_info->fields_list[pos]; + + if (fld->is_null() || !(res= fld->val_str(&tmp))) + { + client_field->def_length= 0; + client_field->def= strmake_root(&p->cur_data->alloc, "", 0); + } + else + { + client_field->def_length= res->length(); + client_field->def= strmake_root(&p->cur_data->alloc, res->ptr(), + client_field->def_length); } } -/** - Add a NULL column to the current row. -*/ +bool Protocol_local::send_list_fields(List *list, const TABLE_LIST *table_list) +{ + DBUG_ENTER("send_result_set_metadata"); + Protocol_text prot(thd); + List_iterator_fast it(*list); + Field *fld; + +// if (!thd->mysql) // bootstrap file handling +// DBUG_RETURN(0); + + if (begin_dataset(thd, list->elements)) + goto err; + + for (uint pos= 0 ; (fld= it++); pos++) + { + if (prot.store_field_metadata_for_list_fields(thd, fld, table_list, pos)) + goto err; + list_fields_send_default(thd, this, fld, pos); + } + + DBUG_RETURN(prepare_for_send(list->elements)); +err: + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + DBUG_RETURN(1); +} + + +void Protocol_local::prepare_for_resend() +{ + MYSQL_ROWS *cur; + MYSQL_DATA *data= cur_data; + DBUG_ENTER("send_data"); + +// if (!thd->mysql) // bootstrap file handling +// DBUG_VOID_RETURN; + + data->rows++; + if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+(field_count + 1) * sizeof(char *)))) + { + my_error(ER_OUT_OF_RESOURCES,MYF(0)); + DBUG_VOID_RETURN; + } + cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS)); + + *data->embedded_info->prev_ptr= cur; + data->embedded_info->prev_ptr= &cur->next; + next_field=cur->data; + next_mysql_field= data->embedded_info->fields_list; +#ifndef DBUG_OFF + field_pos= 0; +#endif + + DBUG_VOID_RETURN; +} bool Protocol_local::store_null() { - if (m_current_column == NULL) - return TRUE; /* prepare_for_resend() failed to allocate memory. */ - - bzero(m_current_column, sizeof(*m_current_column)); - ++m_current_column; - return FALSE; + *(next_field++)= NULL; + ++next_mysql_field; + return false; } -/** - A helper method to add any column to the current row - in its binary form. +#include +#include - Allocates memory for the data in the result set memory root. -*/ - -bool Protocol_local::store_column(const void *data, size_t length) +static void embedded_get_error(MYSQL *mysql, MYSQL_DATA *data) { - if (m_current_column == NULL) - return TRUE; /* prepare_for_resend() failed to allocate memory. */ - /* - alloc_root() automatically aligns memory, so we don't need to - do any extra alignment if we're pointing to, say, an integer. - */ - m_current_column->str= (char*) memdup_root(&m_rset_root, - data, - length + 1 /* Safety */); - if (! m_current_column->str) - return TRUE; - m_current_column->str[length]= '\0'; /* Safety */ - m_current_column->length= length; - ++m_current_column; - return FALSE; + NET *net= &mysql->net; + struct embedded_query_result *ei= data->embedded_info; + net->last_errno= ei->last_errno; + strmake_buf(net->last_error, ei->info); + memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate)); + mysql->server_status= ei->server_status; + my_free(data); } -/** - Store a string value in a result set column, optionally - having converted it to character_set_results. -*/ - -bool -Protocol_local::store_string(const char *str, size_t length, - CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs) +static my_bool loc_read_query_result(MYSQL *mysql) { - /* Store with conversion */ - uint error_unused; + Protocol_local *p= (Protocol_local *) mysql->thd; - if (dst_cs && !my_charset_same(src_cs, dst_cs) && - src_cs != &my_charset_bin && - dst_cs != &my_charset_bin) + MYSQL_DATA *res= p->first_data; + DBUG_ASSERT(!p->cur_data); + p->first_data= res->embedded_info->next; + if (res->embedded_info->last_errno && + !res->embedded_info->fields_list) { - if (unlikely(convert->copy(str, length, src_cs, dst_cs, &error_unused))) - return TRUE; - str= convert->ptr(); - length= convert->length(); + embedded_get_error(mysql, res); + return 1; } - return store_column(str, length); + + mysql->warning_count= res->embedded_info->warning_count; + mysql->server_status= res->embedded_info->server_status; + mysql->field_count= res->fields; + if (!(mysql->fields= res->embedded_info->fields_list)) + { + mysql->affected_rows= res->embedded_info->affected_rows; + mysql->insert_id= res->embedded_info->insert_id; + } + net_clear_error(&mysql->net); + mysql->info= 0; + + if (res->embedded_info->info[0]) + { + strmake(mysql->info_buffer, res->embedded_info->info, MYSQL_ERRMSG_SIZE-1); + mysql->info= mysql->info_buffer; + } + + if (res->embedded_info->fields_list) + { + mysql->status=MYSQL_STATUS_GET_RESULT; + p->cur_data= res; + } + else + my_free(res); + + return 0; } -/** Store a tiny int as is (1 byte) in a result set column. */ - -bool Protocol_local::store_tiny(longlong value) +static my_bool +loc_advanced_command(MYSQL *mysql, enum enum_server_command command, + const uchar *header, ulong header_length, + const uchar *arg, ulong arg_length, my_bool skip_check, + MYSQL_STMT *stmt) { - char v= (char) value; - return store_column(&v, 1); + my_bool result= 1; + Protocol_local *p= (Protocol_local *) mysql->thd; + NET *net= &mysql->net; + + if (p->thd && p->thd->killed != NOT_KILLED) + { + if (p->thd->killed < KILL_CONNECTION) + p->thd->killed= NOT_KILLED; + else + return 1; + } + + p->clear_data_list(); + /* Check that we are calling the client functions in right order */ + if (mysql->status != MYSQL_STATUS_READY) + { + set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); + goto end; + } + + /* Clear result variables */ + p->thd->clear_error(1); + mysql->affected_rows= ~(my_ulonglong) 0; + mysql->field_count= 0; + net_clear_error(net); + + /* + We have to call free_old_query before we start to fill mysql->fields + for new query. In the case of embedded server we collect field data + during query execution (not during data retrieval as it is in remote + client). So we have to call free_old_query here + */ + free_old_query(mysql); + + if (header) + { + arg= header; + arg_length= header_length; + } + + if (p->new_thd) + { + THD *thd_orig= current_thd; + set_current_thd(p->thd); + p->thd->thread_stack= (char*) &result; + p->thd->set_time(); + result= execute_server_code(p->thd, (const char *)arg, arg_length); + p->thd->cleanup_after_query(); + mysql_audit_release(p->thd); + p->end_statement(); + set_current_thd(thd_orig); + } + else + { + Ed_connection con(p->thd); + Security_context *ctx_orig= p->thd->security_ctx; + MYSQL_LEX_STRING sql_text; + DBUG_ASSERT(current_thd == p->thd); + sql_text.str= (char *) arg; + sql_text.length= arg_length; + p->thd->security_ctx= &p->empty_ctx; + result= con.execute_direct(p, sql_text); + p->thd->security_ctx= ctx_orig; + } + if (skip_check) + result= 0; + p->cur_data= 0; + +end: + return result; } -/** Store a short as is (2 bytes, host order) in a result set column. */ +/* + reads dataset from the next query result -bool Protocol_local::store_short(longlong value) -{ - int16 v= (int16) value; - return store_column(&v, 2); -} + SYNOPSIS + loc_read_rows() + mysql connection handle + other parameters are not used + NOTES + It just gets next MYSQL_DATA from the result's queue -/** Store a "long" as is (4 bytes, host order) in a result set column. */ - -bool Protocol_local::store_long(longlong value) -{ - int32 v= (int32) value; - return store_column(&v, 4); -} - - -/** Store a "longlong" as is (8 bytes, host order) in a result set column. */ - -bool Protocol_local::store_longlong(longlong value, bool unsigned_flag) -{ - int64 v= (int64) value; - return store_column(&v, 8); -} - - -/** Store a decimal in string format in a result set column */ - -bool Protocol_local::store_decimal(const my_decimal *value) -{ - DBUG_ASSERT(0); // This method is not used yet - StringBuffer str; - return value->to_string(&str) ? store_column(str.ptr(), str.length()) : true; -} - - -/** Convert to cs_results and store a string. */ - -bool Protocol_local::store(const char *str, size_t length, - CHARSET_INFO *src_cs) -{ - CHARSET_INFO *dst_cs; - - dst_cs= m_connection->m_thd->variables.character_set_results; - return store_string(str, length, src_cs, dst_cs); -} - - -/** Store a string. */ - -bool Protocol_local::store(const char *str, size_t length, - CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs) -{ - return store_string(str, length, src_cs, dst_cs); -} - - -/* Store MYSQL_TIME (in binary format) */ - -bool Protocol_local::store(MYSQL_TIME *time, int decimals) -{ - if (decimals != AUTO_SEC_PART_DIGITS) - my_datetime_trunc(time, decimals); - return store_column(time, sizeof(MYSQL_TIME)); -} - - -/** Store MYSQL_TIME (in binary format) */ - -bool Protocol_local::store_date(MYSQL_TIME *time) -{ - return store_column(time, sizeof(MYSQL_TIME)); -} - - -/** Store MYSQL_TIME (in binary format) */ - -bool Protocol_local::store_time(MYSQL_TIME *time, int decimals) -{ - if (decimals != AUTO_SEC_PART_DIGITS) - my_time_trunc(time, decimals); - return store_column(time, sizeof(MYSQL_TIME)); -} - - -/* Store a floating point number, as is. */ - -bool Protocol_local::store(float value, uint32 decimals, String *buffer) -{ - return store_column(&value, sizeof(float)); -} - - -/* Store a double precision number, as is. */ - -bool Protocol_local::store(double value, uint32 decimals, String *buffer) -{ - return store_column(&value, sizeof (double)); -} - - -/* Store a Field. */ - -bool Protocol_local::store(Field *field) -{ - if (field->is_null()) - return store_null(); - return field->send_binary(this); -} - - -/** Called to start a new result set. */ - -bool Protocol_local::send_result_set_metadata(List *columns, uint) -{ - DBUG_ASSERT(m_rset == 0 && !alloc_root_inited(&m_rset_root)); - - init_sql_alloc(&m_rset_root, "send_result_set_metadata", - MEM_ROOT_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); - - if (! (m_rset= new (&m_rset_root) List)) - return TRUE; - - m_column_count= columns->elements; - - return FALSE; -} - - -/** - Normally this is a separate result set with OUT parameters - of stored procedures. Currently unsupported for the local - version. + RETURN + pointer to MYSQL_DATA with the coming recordset */ -bool Protocol_local::send_out_parameters(List *sp_params) +static MYSQL_DATA * +loc_read_rows(MYSQL *mysql, MYSQL_FIELD *mysql_fields __attribute__((unused)), + unsigned int fields __attribute__((unused))) { - return FALSE; + MYSQL_DATA *result= ((Protocol_local *)mysql->thd)->cur_data; + ((Protocol_local *)mysql->thd)->cur_data= 0; + if (result->embedded_info->last_errno) + { + embedded_get_error(mysql, result); + return NULL; + } + *result->embedded_info->prev_ptr= NULL; + return result; } -/** Called for statements that don't have a result set, at statement end. */ +/************************************************************************** + Get column lengths of the current row + If one uses mysql_use_result, res->lengths contains the length information, + else the lengths are calculated from the offset between pointers. +**************************************************************************/ -bool -Protocol_local::send_ok(uint server_status, uint statement_warn_count, - ulonglong affected_rows, ulonglong last_insert_id, - const char *message, bool skip_flush) +static void loc_fetch_lengths(ulong *to, MYSQL_ROW column, + unsigned int field_count) { - /* - Just make sure nothing is sent to the client, we have grabbed - the status information in the connection diagnostics area. - */ - return FALSE; + MYSQL_ROW end; + + for (end=column + field_count; column != end ; column++,to++) + *to= *column ? *(uint *)((*column) - sizeof(uint)) : 0; } -/** - Called at the end of a result set. Append a complete - result set to the list in Ed_connection. - - Don't send anything to the client, but instead finish - building of the result set at hand. -*/ - -bool Protocol_local::send_eof(uint server_status, uint statement_warn_count) +static void loc_flush_use_result(MYSQL *mysql, my_bool) { - Ed_result_set *ed_result_set; - - DBUG_ASSERT(m_rset); - - opt_add_row_to_rset(); - m_current_row= 0; - - ed_result_set= new (&m_rset_root) Ed_result_set(m_rset, m_column_count, - &m_rset_root); - - m_rset= NULL; - - if (! ed_result_set) - return TRUE; - - /* In case of successful allocation memory ownership was transferred. */ - DBUG_ASSERT(!alloc_root_inited(&m_rset_root)); - - /* - Link the created Ed_result_set instance into the list of connection - result sets. Never fails. - */ - m_connection->add_result_set(ed_result_set); - return FALSE; + Protocol_local *p= (Protocol_local *) mysql->thd; + if (p->cur_data) + { + free_rows(p->cur_data); + p->cur_data= 0; + } + else if (p->first_data) + { + MYSQL_DATA *data= p->first_data; + p->first_data= data->embedded_info->next; + free_rows(data); + } } -/** Called to send an error to the client at the end of a statement. */ - -bool -Protocol_local::send_error(uint sql_errno, const char *err_msg, const char*) +static void loc_on_close_free(MYSQL *mysql) { - /* - Just make sure that nothing is sent to the client (default - implementation). - */ - return FALSE; + Protocol_local *p= (Protocol_local *) mysql->thd; + THD *thd= p->new_thd; + delete p; + if (thd) + { + delete thd; + local_connection_thread_count--; + } + my_free(mysql->info_buffer); + mysql->info_buffer= 0; } +static MYSQL_RES *loc_use_result(MYSQL *mysql) +{ + return mysql_store_result(mysql); +} +static MYSQL_METHODS local_methods= +{ + loc_read_query_result, /* read_query_result */ + loc_advanced_command, /* advanced_command */ + loc_read_rows, /* read_rows */ + loc_use_result, /* use_result */ + loc_fetch_lengths, /* fetch_lengths */ + loc_flush_use_result, /* flush_use_result */ + NULL, /* read_change_user_result */ + loc_on_close_free /* on_close_free */ #ifdef EMBEDDED_LIBRARY -void Protocol_local::remove_last_row() -{ } + ,NULL, /* list_fields */ + NULL, /* read_prepare_result */ + NULL, /* stmt_execute */ + NULL, /* read_binary_rows */ + NULL, /* unbuffered_fetch */ + NULL, /* read_statistics */ + NULL, /* next_result */ + NULL /* read_rows_from_cursor */ #endif +}; + + +Atomic_counter local_connection_thread_count; + +extern "C" MYSQL *mysql_real_connect_local(MYSQL *mysql) +{ + THD *thd_orig= current_thd; + THD *new_thd; + Protocol_local *p; + DBUG_ENTER("mysql_real_connect_local"); + + /* Test whether we're already connected */ + if (mysql->server_version) + { + set_mysql_error(mysql, CR_ALREADY_CONNECTED, unknown_sqlstate); + DBUG_RETURN(0); + } + + mysql->methods= &local_methods; + mysql->user= NULL; + + mysql->info_buffer= (char *) my_malloc(MYSQL_ERRMSG_SIZE, MYF(0)); + if (!thd_orig || thd_orig->lock) + { + /* + When we start with the empty current_thd (that happens when plugins + are loaded during the server start) or when some tables are locked + with the current_thd already (that happens when INSTALL PLUGIN + calls the plugin_init or with queries), we create the new THD for + the local connection. So queries with this MYSQL will be run with + it rather than the current THD. + */ + + new_thd= new THD(0); + local_connection_thread_count++; + new_thd->thread_stack= (char*) &thd_orig; + new_thd->store_globals(); + new_thd->security_ctx->skip_grants(); + new_thd->query_cache_is_applicable= 0; + new_thd->variables.wsrep_on= 0; + /* + TOSO: decide if we should turn the auditing off + for such threads. + We can do it like this: + new_thd->audit_class_mask[0]= ~0; + */ + bzero((char*) &new_thd->net, sizeof(new_thd->net)); + set_current_thd(thd_orig); + thd_orig= new_thd; + } + else + new_thd= NULL; + + p= new Protocol_local(thd_orig, new_thd, 0); + if (new_thd) + new_thd->protocol= p; + else + { + p->empty_ctx.init(); + p->empty_ctx.skip_grants(); + } + + mysql->thd= p; + mysql->server_status= SERVER_STATUS_AUTOCOMMIT; + + + DBUG_PRINT("exit",("Mysql handler: %p", mysql)); + DBUG_RETURN(mysql); +} + diff --git a/sql/sql_prepare.h b/sql/sql_prepare.h index 48910a197d9..ff6e986ec87 100644 --- a/sql/sql_prepare.h +++ b/sql/sql_prepare.h @@ -202,7 +202,7 @@ public: @retval TRUE error, use get_last_error() to see the error number. */ - bool execute_direct(LEX_STRING sql_text); + bool execute_direct(Protocol *p, LEX_STRING sql_text); /** Same as the previous, but takes an instance of Server_runnable @@ -215,7 +215,7 @@ public: return a result set @retval TRUE failure */ - bool execute_direct(Server_runnable *server_runnable); + bool execute_direct(Protocol *p, Server_runnable *server_runnable); /** Get the number of affected (deleted, updated) @@ -311,7 +311,6 @@ private: THD *m_thd; Ed_result_set *m_rsets; Ed_result_set *m_current_rset; - friend class Protocol_local; private: void free_old_result(); void add_result_set(Ed_result_set *ed_result_set); @@ -354,4 +353,6 @@ private: size_t m_column_count; /* TODO: change to point to metadata */ }; +extern Atomic_counter local_connection_thread_count; + #endif // SQL_PREPARE_H diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc index fd7df7ee06f..bee50c8332e 100644 --- a/storage/example/ha_example.cc +++ b/storage/example/ha_example.cc @@ -98,7 +98,7 @@ #pragma implementation // gcc: Class implementation #endif -#include +#include #include #include "ha_example.h" #include "sql_class.h" From f71f471ed2e1b9702faaa4507dccbe2121de10ca Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 18 Jan 2022 12:14:25 +0400 Subject: [PATCH 196/477] MDEV-27595 Backport SQL service, introduced by MDEV-19275. Fixes to make SQL SERVICE working. Conflicts: storage/spider/spd_table.cc --- sql/sql_prepare.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 68087d333b0..c4def110eb8 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -5402,6 +5402,7 @@ public: MEM_ROOT *alloc; THD *new_thd; Security_context empty_ctx; + ulonglong client_capabilities; Protocol_local(THD *thd_arg, THD *new_thd_arg, ulong prealloc) : Protocol_text(thd_arg, prealloc), @@ -6023,12 +6024,15 @@ loc_advanced_command(MYSQL *mysql, enum enum_server_command command, { Ed_connection con(p->thd); Security_context *ctx_orig= p->thd->security_ctx; + ulonglong cap_orig= p->thd->client_capabilities; MYSQL_LEX_STRING sql_text; DBUG_ASSERT(current_thd == p->thd); sql_text.str= (char *) arg; sql_text.length= arg_length; p->thd->security_ctx= &p->empty_ctx; + p->thd->client_capabilities= p->client_capabilities; result= con.execute_direct(p, sql_text); + p->thd->client_capabilities= cap_orig; p->thd->security_ctx= ctx_orig; } if (skip_check) @@ -6153,6 +6157,7 @@ extern "C" MYSQL *mysql_real_connect_local(MYSQL *mysql) THD *thd_orig= current_thd; THD *new_thd; Protocol_local *p; + ulonglong client_flag; DBUG_ENTER("mysql_real_connect_local"); /* Test whether we're already connected */ @@ -6164,6 +6169,9 @@ extern "C" MYSQL *mysql_real_connect_local(MYSQL *mysql) mysql->methods= &local_methods; mysql->user= NULL; + client_flag= mysql->options.client_flag; + client_flag|= CLIENT_MULTI_RESULTS;; + client_flag&= ~(CLIENT_COMPRESS | CLIENT_PLUGIN_AUTH); mysql->info_buffer= (char *) my_malloc(MYSQL_ERRMSG_SIZE, MYF(0)); if (!thd_orig || thd_orig->lock) @@ -6184,6 +6192,7 @@ extern "C" MYSQL *mysql_real_connect_local(MYSQL *mysql) new_thd->security_ctx->skip_grants(); new_thd->query_cache_is_applicable= 0; new_thd->variables.wsrep_on= 0; + new_thd->client_capabilities= client_flag; /* TOSO: decide if we should turn the auditing off for such threads. @@ -6204,6 +6213,7 @@ extern "C" MYSQL *mysql_real_connect_local(MYSQL *mysql) { p->empty_ctx.init(); p->empty_ctx.skip_grants(); + p->client_capabilities= client_flag; } mysql->thd= p; From 801b45bf4fb5ba4bf26fe4f733270b2a6a4234cd Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Mon, 24 Jan 2022 19:51:27 +0400 Subject: [PATCH 197/477] MDEV-26890 : Crash on shutdown, with active binlog dump threads Backported from 10.7. The reason for the crash was a bug in MDEV-19275, after which shutdown does not wait for binlog threads anymore. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index de2e1c7622e..a1a8a862a8e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1814,7 +1814,7 @@ static void close_connections(void) /* Kill phase 2 */ server_threads.iterate(kill_thread_phase_2); - for (uint64 i= 0; THD_count::connection_thd_count(); i++) + for (uint64 i= 0; THD_count::value() > local_connection_thread_count; i++) { /* This time the warnings are emitted within the loop to provide a From 3a8eb405e74ee9b1f8eb26b575818a8652cb6c5e Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 15 Feb 2022 13:37:59 +0400 Subject: [PATCH 198/477] MDEV-27832 disable binary logging for SQL SERVICE. Binary logging is now disabled for the queries run by SQL SERVICE. The binlogging can be turned on with the 'SET SQL_LOG_BIN=On' query. Conflicts: sql/sql_prepare.cc Conflicts: sql/sql_prepare.cc --- .../suite/plugins/r/test_sql_service.result | 29 +++++++++++++++++++ .../suite/plugins/t/test_sql_service.test | 21 ++++++++++++++ sql/sql_class.cc | 5 +--- sql/sql_class.h | 7 +++++ sql/sql_prepare.cc | 22 +++++++++++++- sql/sys_vars.cc | 5 +--- 6 files changed, 80 insertions(+), 9 deletions(-) diff --git a/mysql-test/suite/plugins/r/test_sql_service.result b/mysql-test/suite/plugins/r/test_sql_service.result index 00f0411b665..ca7326de51c 100644 --- a/mysql-test/suite/plugins/r/test_sql_service.result +++ b/mysql-test/suite/plugins/r/test_sql_service.result @@ -2,6 +2,26 @@ install plugin test_sql_service soname 'test_sql_service'; show status like 'test_sql_service_passed'; Variable_name Value Test_sql_service_passed 1 +set global test_sql_service_execute_sql_global= 'create table test.t1 select 1 as a, @@SQL_LOG_BIN'; +set global test_sql_service_execute_sql_local= 'insert into test.t1 select 2 as a, @@SQL_LOG_BIN'; +set global test_sql_service_execute_sql_global= 'SET SQL_LOG_BIN=1'; +set global test_sql_service_execute_sql_global= 'insert into test.t1 select 3 as a, @@SQL_LOG_BIN'; +set global test_sql_service_execute_sql_global= 'SET SQL_LOG_BIN=0'; +set global test_sql_service_execute_sql_global= 'insert into test.t1 select 4 as a, @@SQL_LOG_BIN'; +set global test_sql_service_execute_sql_global= 'SET sql_auto_is_null=1'; +set global test_sql_service_execute_sql_global= 'insert into test.t1 select 5 as a, @@sql_auto_is_null'; +set global test_sql_service_execute_sql_global= 'SET sql_auto_is_null=0'; +set global test_sql_service_execute_sql_global= 'insert into test.t1 select 6 as a, @@sql_auto_is_null'; +select * from t1 order by a; +a @@SQL_LOG_BIN +1 0 +2 0 +3 1 +4 0 +5 1 +6 0 +drop table t1; +SET SQL_LOG_BIN=0; set global test_sql_service_run_test= 1; show status like 'test_sql_service_passed'; Variable_name Value @@ -68,3 +88,12 @@ drop table t1; uninstall plugin test_sql_service; Warnings: Warning 1620 Plugin is busy and will be uninstalled on shutdown +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Annotate_rows # # insert into test.t1 select 3 as a, @@SQL_LOG_BIN +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ diff --git a/mysql-test/suite/plugins/t/test_sql_service.test b/mysql-test/suite/plugins/t/test_sql_service.test index b80d78fe6e5..3f2aaa81c4c 100644 --- a/mysql-test/suite/plugins/t/test_sql_service.test +++ b/mysql-test/suite/plugins/t/test_sql_service.test @@ -1,4 +1,5 @@ --source include/not_embedded.inc +--source include/have_log_bin.inc if (!$TEST_SQL_SERVICE_SO) { skip No TEST_SQL_SERVICE plugin; @@ -11,6 +12,20 @@ source include/wait_until_count_sessions.inc; install plugin test_sql_service soname 'test_sql_service'; show status like 'test_sql_service_passed'; +set global test_sql_service_execute_sql_global= 'create table test.t1 select 1 as a, @@SQL_LOG_BIN'; +set global test_sql_service_execute_sql_local= 'insert into test.t1 select 2 as a, @@SQL_LOG_BIN'; +set global test_sql_service_execute_sql_global= 'SET SQL_LOG_BIN=1'; +set global test_sql_service_execute_sql_global= 'insert into test.t1 select 3 as a, @@SQL_LOG_BIN'; +set global test_sql_service_execute_sql_global= 'SET SQL_LOG_BIN=0'; +set global test_sql_service_execute_sql_global= 'insert into test.t1 select 4 as a, @@SQL_LOG_BIN'; +set global test_sql_service_execute_sql_global= 'SET sql_auto_is_null=1'; +set global test_sql_service_execute_sql_global= 'insert into test.t1 select 5 as a, @@sql_auto_is_null'; +set global test_sql_service_execute_sql_global= 'SET sql_auto_is_null=0'; +set global test_sql_service_execute_sql_global= 'insert into test.t1 select 6 as a, @@sql_auto_is_null'; +select * from t1 order by a; +drop table t1; +SET SQL_LOG_BIN=0; + set global test_sql_service_run_test= 1; show status like 'test_sql_service_passed'; @@ -58,3 +73,9 @@ drop table t1; uninstall plugin test_sql_service; +# Check that statements were executed/binlogged in correct order. +source include/show_binlog_events.inc; +# --replace_column 2 # 5 # +# --replace_regex /xid=[0-9]+/xid=XX/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ +# SHOW BINLOG EVENTS LIMIT 3,100; + diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 93f42a462e5..55db1ff4f52 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1287,10 +1287,7 @@ void THD::init() wsrep_desynced_backup_stage= false; #endif /* WITH_WSREP */ - if (variables.sql_log_bin) - variables.option_bits|= OPTION_BIN_LOG; - else - variables.option_bits&= ~OPTION_BIN_LOG; + set_binlog_bit(); variables.sql_log_bin_off= 0; diff --git a/sql/sql_class.h b/sql/sql_class.h index 9427cc4faa5..e0f87383189 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2934,6 +2934,13 @@ public: auto_inc_intervals_forced.empty(); // in case of multiple SET INSERT_ID auto_inc_intervals_forced.append(next_id, ULONGLONG_MAX, 0); } + inline void set_binlog_bit() + { + if (variables.sql_log_bin) + variables.option_bits |= OPTION_BIN_LOG; + else + variables.option_bits &= ~OPTION_BIN_LOG; + } ulonglong limit_found_rows; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index c4def110eb8..e005060f642 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -5404,12 +5404,26 @@ public: Security_context empty_ctx; ulonglong client_capabilities; + my_bool do_log_bin; + Protocol_local(THD *thd_arg, THD *new_thd_arg, ulong prealloc) : Protocol_text(thd_arg, prealloc), cur_data(0), first_data(0), data_tail(&first_data), alloc(0), - new_thd(new_thd_arg) + new_thd(new_thd_arg), do_log_bin(FALSE) {} + void set_binlog_vars(my_bool *sav_log_bin) + { + *sav_log_bin= thd->variables.sql_log_bin; + thd->variables.sql_log_bin= do_log_bin; + thd->set_binlog_bit(); + } + void restore_binlog_vars(my_bool sav_log_bin) + { + do_log_bin= thd->variables.sql_log_bin; + thd->variables.sql_log_bin= sav_log_bin; + thd->set_binlog_bit(); + } protected: bool net_store_data(const uchar *from, size_t length); bool net_store_data_cs(const uchar *from, size_t length, @@ -6026,6 +6040,9 @@ loc_advanced_command(MYSQL *mysql, enum enum_server_command command, Security_context *ctx_orig= p->thd->security_ctx; ulonglong cap_orig= p->thd->client_capabilities; MYSQL_LEX_STRING sql_text; + my_bool log_bin_orig; + p->set_binlog_vars(&log_bin_orig); + DBUG_ASSERT(current_thd == p->thd); sql_text.str= (char *) arg; sql_text.length= arg_length; @@ -6034,6 +6051,7 @@ loc_advanced_command(MYSQL *mysql, enum enum_server_command command, result= con.execute_direct(p, sql_text); p->thd->client_capabilities= cap_orig; p->thd->security_ctx= ctx_orig; + p->restore_binlog_vars(log_bin_orig); } if (skip_check) result= 0; @@ -6193,6 +6211,8 @@ extern "C" MYSQL *mysql_real_connect_local(MYSQL *mysql) new_thd->query_cache_is_applicable= 0; new_thd->variables.wsrep_on= 0; new_thd->client_capabilities= client_flag; + new_thd->variables.sql_log_bin= 0; + new_thd->set_binlog_bit(); /* TOSO: decide if we should turn the auditing off for such threads. diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 7540858da32..921a5572991 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4225,10 +4225,7 @@ static bool fix_sql_log_bin_after_update(sys_var *self, THD *thd, { DBUG_ASSERT(type == OPT_SESSION); - if (thd->variables.sql_log_bin) - thd->variables.option_bits |= OPTION_BIN_LOG; - else - thd->variables.option_bits &= ~OPTION_BIN_LOG; + thd->set_binlog_bit(); return FALSE; } From f81432510531b44db401fac6b2ed34519edc4aaa Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sun, 3 Jul 2022 16:37:15 +0400 Subject: [PATCH 199/477] MDEV-27595 Backport SQL service, introduced by MDEV-19275. Embedded-server related fixes. --- libmysqld/emb_qcache.cc | 2 +- libmysqld/lib_sql.cc | 11 +++++------ sql/protocol.cc | 4 ++-- sql/protocol.h | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libmysqld/emb_qcache.cc b/libmysqld/emb_qcache.cc index 603542e820e..95e09cd8635 100644 --- a/libmysqld/emb_qcache.cc +++ b/libmysqld/emb_qcache.cc @@ -490,7 +490,7 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src) *prev_row= NULL; data->embedded_info->prev_ptr= prev_row; return_ok: - net_send_eof(thd, thd->server_status, + thd->protocol->net_send_eof(thd, thd->server_status, thd->get_stmt_da()->current_statement_warn_count()); DBUG_RETURN(0); err: diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 2dbfea1f6c0..01a70e724cf 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -1125,7 +1125,7 @@ bool Protocol::send_result_set_metadata(List *list, uint flags) for (uint pos= 0 ; (item= it++); pos++) { - if (prot.store_field_metadata(thd, item, pos)) + if (prot.store_item_metadata(thd, item, pos)) goto err; } @@ -1240,8 +1240,7 @@ bool Protocol_binary::write() @retval FALSE Success */ -bool -net_send_ok(THD *thd, +bool Protocol::net_send_ok(THD *thd, uint server_status, uint statement_warn_count, ulonglong affected_rows, ulonglong id, const char *message, bool, bool) @@ -1276,7 +1275,7 @@ net_send_ok(THD *thd, */ bool -net_send_eof(THD *thd, uint server_status, uint statement_warn_count) +Protocol::net_send_eof(THD *thd, uint server_status, uint statement_warn_count) { bool error= write_eof_packet(thd, server_status, statement_warn_count); thd->cur_data= 0; @@ -1284,8 +1283,8 @@ net_send_eof(THD *thd, uint server_status, uint statement_warn_count) } -bool net_send_error_packet(THD *thd, uint sql_errno, const char *err, - const char *sqlstate) +bool Protocol::net_send_error_packet(THD *thd, uint sql_errno, const char *err, + const char *sqlstate) { uint error; char converted_err[MYSQL_ERRMSG_SIZE]; diff --git a/sql/protocol.cc b/sql/protocol.cc index 5f89c396139..7f9fda9e40d 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -906,7 +906,7 @@ bool Protocol::send_result_set_metadata(List *list, uint flags) for (uint pos= 0; (item=it++); pos++) { prot.prepare_for_resend(); - if (prot.store_field_metadata(thd, item, pos)) + if (prot.store_item_metadata(thd, item, pos)) goto err; if (prot.write()) DBUG_RETURN(1); @@ -986,7 +986,7 @@ bool Protocol::write() #endif /* EMBEDDED_LIBRARY */ -bool Protocol_text::store_field_metadata(THD *thd, Item *item, uint pos) +bool Protocol_text::store_item_metadata(THD *thd, Item *item, uint pos) { Send_field field(thd, item); return store_field_metadata(thd, field, item->charset_for_protocol(), pos); diff --git a/sql/protocol.h b/sql/protocol.h index 8632f155847..259b6585b4e 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -201,7 +201,7 @@ public: bool store_field_metadata(const THD *thd, const Send_field &field, CHARSET_INFO *charset_for_protocol, uint pos); - bool store_field_metadata(THD *thd, Item *item, uint pos); + bool store_item_metadata(THD *thd, Item *item, uint pos); bool store_field_metadata_for_list_fields(const THD *thd, Field *field, const TABLE_LIST *table_list, uint pos); From 624ad863d09833448b9f23f14ff42473f4d3e75b Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 7 Jul 2022 16:12:05 +0400 Subject: [PATCH 200/477] MDEV-27595 Backport SQL service, introduced by MDEV-19275. test_sql_service.test fixed. --- mysql-test/suite/plugins/r/test_sql_service.result | 1 + mysql-test/suite/plugins/t/test_sql_service.test | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/plugins/r/test_sql_service.result b/mysql-test/suite/plugins/r/test_sql_service.result index ca7326de51c..c8467a42f15 100644 --- a/mysql-test/suite/plugins/r/test_sql_service.result +++ b/mysql-test/suite/plugins/r/test_sql_service.result @@ -2,6 +2,7 @@ install plugin test_sql_service soname 'test_sql_service'; show status like 'test_sql_service_passed'; Variable_name Value Test_sql_service_passed 1 +reset master; set global test_sql_service_execute_sql_global= 'create table test.t1 select 1 as a, @@SQL_LOG_BIN'; set global test_sql_service_execute_sql_local= 'insert into test.t1 select 2 as a, @@SQL_LOG_BIN'; set global test_sql_service_execute_sql_global= 'SET SQL_LOG_BIN=1'; diff --git a/mysql-test/suite/plugins/t/test_sql_service.test b/mysql-test/suite/plugins/t/test_sql_service.test index 3f2aaa81c4c..393fb431e23 100644 --- a/mysql-test/suite/plugins/t/test_sql_service.test +++ b/mysql-test/suite/plugins/t/test_sql_service.test @@ -11,6 +11,7 @@ source include/wait_until_count_sessions.inc; install plugin test_sql_service soname 'test_sql_service'; show status like 'test_sql_service_passed'; +reset master; set global test_sql_service_execute_sql_global= 'create table test.t1 select 1 as a, @@SQL_LOG_BIN'; set global test_sql_service_execute_sql_local= 'insert into test.t1 select 2 as a, @@SQL_LOG_BIN'; @@ -74,8 +75,8 @@ drop table t1; uninstall plugin test_sql_service; # Check that statements were executed/binlogged in correct order. -source include/show_binlog_events.inc; +--source include/show_binlog_events.inc # --replace_column 2 # 5 # # --replace_regex /xid=[0-9]+/xid=XX/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ -# SHOW BINLOG EVENTS LIMIT 3,100; +# SHOW BINLOG EVENTS LIMIT 3,5; From e2c90e36b41a03474451799f952ca396b6c2b2f9 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Fri, 8 Jul 2022 13:54:10 +0400 Subject: [PATCH 201/477] Fix to quiet the compiler on Windows. --- sql/sql_prepare.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index e005060f642..5a2c39b160d 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -5544,7 +5544,8 @@ static char *dup_str_aux(MEM_ROOT *root, const LEX_CSTRING &from, static char *dup_str_aux(MEM_ROOT *root, const char *from, CHARSET_INFO *fromcs, CHARSET_INFO *tocs) { - return dup_str_aux(root, from, from ? strlen(from) : 0 , fromcs, tocs); + return dup_str_aux(root, from, (uint) (from ? strlen(from) : 0), + fromcs, tocs); } From b080cff3aa916871c4fcfe1060c656368016e1c4 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 5 Sep 2023 15:37:33 +0400 Subject: [PATCH 202/477] MDEV-27295 Backport SQL service, introduced by MDEV-19275. ifdef fixed. --- include/mariadb_capi_rename.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mariadb_capi_rename.h b/include/mariadb_capi_rename.h index 616a9142fe6..58e16fdc0c0 100644 --- a/include/mariadb_capi_rename.h +++ b/include/mariadb_capi_rename.h @@ -22,7 +22,7 @@ #ifndef MARIADB_CAPI_RENAME_INCLUDED #define MARIADB_CAPI_RENAME_INCLUDED -#if !defined(EMBEDDED_LIBRARY) +#if !defined(EMBEDDED_LIBRARY) && !defined(MYSQL_DYNAMIC_PLUGIN) #define MARIADB_ADD_PREFIX(_SYMBOL) server_##_SYMBOL #define mysql_real_connect MARIADB_ADD_PREFIX(mysql_real_connect) From 910a0ddd2d67bb8d16137b1584611b23ce3ee408 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sun, 10 Sep 2023 16:09:44 +0400 Subject: [PATCH 203/477] MDEV-27295 Backport SQL service, introduced by MDEV-19275. necessary functions added to the SQL SERVICE. --- include/mysql/plugin_audit.h.pp | 9 +++++++++ include/mysql/plugin_auth.h.pp | 9 +++++++++ include/mysql/plugin_encryption.h.pp | 9 +++++++++ include/mysql/plugin_ftparser.h.pp | 9 +++++++++ include/mysql/plugin_password_validation.h.pp | 9 +++++++++ include/mysql/service_sql.h | 17 ++++++++++++++++- sql/sql_plugin_services.inl | 6 ++++++ 7 files changed, 67 insertions(+), 1 deletion(-) diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index 9039ce7336b..a298eadfb4d 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -435,6 +435,15 @@ extern struct sql_service_st { void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, + const char *cert, const char *ca, + const char *capath, const char *cipher); } *sql_service; MYSQL *mysql_real_connect_local(MYSQL *mysql); struct st_mysql_xid { diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index f5707c71f7c..d418eb787e5 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -435,6 +435,15 @@ extern struct sql_service_st { void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, + const char *cert, const char *ca, + const char *capath, const char *cipher); } *sql_service; MYSQL *mysql_real_connect_local(MYSQL *mysql); struct st_mysql_xid { diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp index 3ae71b70703..df82bbe0190 100644 --- a/include/mysql/plugin_encryption.h.pp +++ b/include/mysql/plugin_encryption.h.pp @@ -435,6 +435,15 @@ extern struct sql_service_st { void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, + const char *cert, const char *ca, + const char *capath, const char *cipher); } *sql_service; MYSQL *mysql_real_connect_local(MYSQL *mysql); struct st_mysql_xid { diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index d87046cef03..5574aaf7143 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -435,6 +435,15 @@ extern struct sql_service_st { void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, + const char *cert, const char *ca, + const char *capath, const char *cipher); } *sql_service; MYSQL *mysql_real_connect_local(MYSQL *mysql); struct st_mysql_xid { diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp index f87e3502167..3addf80565d 100644 --- a/include/mysql/plugin_password_validation.h.pp +++ b/include/mysql/plugin_password_validation.h.pp @@ -435,6 +435,15 @@ extern struct sql_service_st { void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, + const char *cert, const char *ca, + const char *capath, const char *cipher); } *sql_service; MYSQL *mysql_real_connect_local(MYSQL *mysql); struct st_mysql_xid { diff --git a/include/mysql/service_sql.h b/include/mysql/service_sql.h index ef6de8b34ef..0a3a2294fa1 100644 --- a/include/mysql/service_sql.h +++ b/include/mysql/service_sql.h @@ -62,6 +62,15 @@ extern struct sql_service_st { void (STDCALL *mysql_free_result_func)(MYSQL_RES *result); MYSQL_ROW (STDCALL *mysql_fetch_row_func)(MYSQL_RES *result); void (STDCALL *mysql_close_func)(MYSQL *mysql); + int (STDCALL *mysql_options_func)(MYSQL *mysql, enum mysql_option option, + const void *arg); + unsigned long *(STDCALL *mysql_fetch_lengths_func)(MYSQL_RES *res); + int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); + unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); + int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, + const char *cert, const char *ca, + const char *capath, const char *cipher); } *sql_service; #ifdef MYSQL_DYNAMIC_PLUGIN @@ -78,6 +87,12 @@ extern struct sql_service_st { #define mysql_free_result(R) sql_service->mysql_free_result_func(R) #define mysql_fetch_row(R) sql_service->mysql_fetch_row_func(R) #define mysql_close(M) sql_service->mysql_close_func(M) +#define mysql_options(M,O,V) sql_service->mysql_options_func(M,O,V) +#define mysql_fetch_lengths(R) sql_service->mysql_fetch_lengths_func(R) +#define mysql_set_character_set(M,C) sql_service->mysql_set_character_set_func(M,C) +#define mysql_num_fields(R) sql_service->mysql_num_fields_func(R) +#define mysql_select_db(M,D) sql_service->mysql_select_db_func(M,D) +#define mysql_ssl_set(M,K,C,A,P,H) sql_service->mysql_ssl_set_func(M,K,C,A,P,H) #else @@ -90,7 +105,7 @@ extern struct sql_service_st { */ MYSQL *mysql_real_connect_local(MYSQL *mysql); -/* The rest of the function declarations mest be taken from the mysql.h */ +/* The rest of the function declarations must be taken from the mysql.h */ #endif /*MYSQL_DYNAMIC_PLUGIN*/ diff --git a/sql/sql_plugin_services.inl b/sql/sql_plugin_services.inl index 2cab05529df..f73c52f677a 100644 --- a/sql/sql_plugin_services.inl +++ b/sql/sql_plugin_services.inl @@ -236,6 +236,12 @@ struct sql_service_st sql_service_handler= mysql_free_result, mysql_fetch_row, mysql_close, + mysql_options, + mysql_fetch_lengths, + mysql_set_character_set, + mysql_num_fields, + mysql_select_db, + mysql_ssl_set }; static struct st_service_ref list_of_services[]= From fa81afdaa66350085188bf965147f5ae9c56c63e Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sun, 5 Nov 2023 17:11:39 +0400 Subject: [PATCH 204/477] MDEV-27595 Backport SQL service, introduced by MDEV-19275. Post-review fixes. --- plugin/test_sql_service/CMakeLists.txt | 2 +- plugin/test_sql_service/COPYING | 339 ------------------------- 2 files changed, 1 insertion(+), 340 deletions(-) delete mode 100644 plugin/test_sql_service/COPYING diff --git a/plugin/test_sql_service/CMakeLists.txt b/plugin/test_sql_service/CMakeLists.txt index 615508bdc4e..b40e2575db5 100644 --- a/plugin/test_sql_service/CMakeLists.txt +++ b/plugin/test_sql_service/CMakeLists.txt @@ -15,4 +15,4 @@ SET(SOURCES test_sql_service.c) -MYSQL_ADD_PLUGIN(test_sql_service ${SOURCES} MODULE_ONLY) +MYSQL_ADD_PLUGIN(test_sql_service ${SOURCES} MODULE_ONLY COMPONENT Test) diff --git a/plugin/test_sql_service/COPYING b/plugin/test_sql_service/COPYING deleted file mode 100644 index 6e475df5526..00000000000 --- a/plugin/test_sql_service/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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; either version 2 of the License, or - (at your option) any later version. - - 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. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. From f77a3868a7a5694bae679fcadd78a365669ffc0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 6 Nov 2023 10:20:51 +0200 Subject: [PATCH 205/477] MDEV-11816 fixup: Remove an orphan test file --- .../innodb_zip/include/innodb_dml_ops.inc | 82 ------------------- 1 file changed, 82 deletions(-) delete mode 100644 mysql-test/suite/innodb_zip/include/innodb_dml_ops.inc diff --git a/mysql-test/suite/innodb_zip/include/innodb_dml_ops.inc b/mysql-test/suite/innodb_zip/include/innodb_dml_ops.inc deleted file mode 100644 index 4908dfb6bee..00000000000 --- a/mysql-test/suite/innodb_zip/include/innodb_dml_ops.inc +++ /dev/null @@ -1,82 +0,0 @@ -delimiter |; -create procedure populate_t1() -begin - declare i int default 1; - while (i <= 200) do - insert into t1 values (i, 'a', 'b'); - set i = i + 1; - end while; -end| -create procedure populate_t1_small() -begin - declare i int default 1; - while (i <= 20) do - insert into t1 values (i, 'c', 'd'); - set i = i + 1; - end while; -end| -create procedure populate_t1_small2() -begin - declare i int default 30; - while (i <= 50) do - insert into t1 values (i, 'e', 'f'); - set i = i + 1; - end while; -end| -delimiter ;| -# -begin; -select count(*) from t1; -call populate_t1(); -select count(*) from t1; -select * from t1 limit 10; -rollback; -select count(*) from t1; -# -begin; -call populate_t1(); -select count(*) from t1; -commit; -select count(*) from t1; -# -truncate table t1; -select count(*) from t1; -# -call populate_t1_small(); -select count(*) from t1; -rollback; -select count(*) from t1; -truncate table t1; -# -call populate_t1(); -select count(*) from t1; -delete from t1 where keyc <= 60; -select count(*) from t1; -call populate_t1_small(); -select count(*) from t1; -select * from t1 limit 10; -begin; -call populate_t1_small2(); -select count(*) from t1; -select * from t1 where keyc > 30 limit 10; -rollback; -select count(*) from t1; -select * from t1 where keyc > 30 limit 10; -# -update t1 set keyc = keyc + 2000; -select * from t1 limit 10; -rollback; -begin; -update t1 set keyc = keyc + 2000; -select * from t1 limit 10; -rollback; -select * from t1 limit 10; -commit; -select * from t1 limit 10; -# -insert into t2 select * from t1 where keyc < 2101; -select count(*) from t2; -# -drop procedure populate_t1; -drop procedure populate_t1_small; -drop procedure populate_t1_small2; From 01623ac9ea7a721855c1683ca216758f53b227b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 6 Nov 2023 10:32:39 +0200 Subject: [PATCH 206/477] Fix clang -Wtypedef-redefinition --- plugin/auth_pam/auth_pam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/auth_pam/auth_pam.c b/plugin/auth_pam/auth_pam.c index d232b3b5c65..cce5042443c 100644 --- a/plugin/auth_pam/auth_pam.c +++ b/plugin/auth_pam/auth_pam.c @@ -21,9 +21,9 @@ #include #include #include +#include #include #include "auth_pam_tool.h" -#include #ifndef DBUG_OFF static char pam_debug = 0; From b52b7b41296fa8857bcd2abc42f9ab6721b86f8b Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 6 Nov 2023 19:16:16 +0530 Subject: [PATCH 207/477] 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 2447172afb5afed1687779e46eed217c38f89ebc Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 6 Nov 2023 17:37:11 +0200 Subject: [PATCH 208/477] Ensure that process "State" is properly cleaned after query execution In some cases "SHOW PROCESSLIST" could show "Reset for next command" as State, even if the previous query had finished properly. Fixed by clearing State after end of command and also setting the State for the "Connect" command. Other things: - Changed usage of 'thd->set_command(COM_SLEEP)' to 'thd->mark_connection_idle()'. - Changed thread_state_info() to return "" instead of NULL. This is just a safety measurement and in line with the logic of the rest of the function. --- libmysqld/lib_sql.cc | 3 +-- plugin/feedback/sender_thread.cc | 2 +- sql/sql_class.cc | 1 + sql/sql_class.h | 13 ++++++++++++- sql/sql_connect.cc | 3 +-- sql/sql_parse.cc | 3 ++- sql/sql_show.cc | 2 +- sql/wsrep_client_service.cc | 2 +- sql/wsrep_mysqld.cc | 3 +-- sql/wsrep_server_service.cc | 2 +- 10 files changed, 22 insertions(+), 12 deletions(-) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 01a70e724cf..9a011b2180f 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -708,8 +708,7 @@ void *create_embedded_thd(int client_flag) if (thd->variables.max_join_size == HA_POS_ERROR) thd->variables.option_bits |= OPTION_BIG_SELECTS; - thd->proc_info=0; // Remove 'login' - thd->set_command(COM_SLEEP); + thd->mark_connection_idle(); thd->set_time(); thd->init_for_queries(); thd->client_capabilities= client_flag; diff --git a/plugin/feedback/sender_thread.cc b/plugin/feedback/sender_thread.cc index 3976c950541..dcd9d783dfb 100644 --- a/plugin/feedback/sender_thread.cc +++ b/plugin/feedback/sender_thread.cc @@ -97,8 +97,8 @@ static int prepare_for_fill(TABLE_LIST *tables) thd->mysys_var->current_cond= &sleep_condition; thd->mysys_var->current_mutex= &sleep_mutex; + thd->mark_connection_idle(); thd->proc_info="feedback"; - thd->set_command(COM_SLEEP); thd->system_thread= SYSTEM_THREAD_EVENT_WORKER; // whatever thd->set_time(); thd->init_for_queries(); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 55db1ff4f52..0f83b3d4c08 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1630,6 +1630,7 @@ void THD::reset_for_reuse() abort_on_warning= 0; free_connection_done= 0; m_command= COM_CONNECT; + proc_info= "login"; // Same as in THD::THD() transaction.on= 1; #if defined(ENABLED_PROFILING) profiling.reset(); diff --git a/sql/sql_class.h b/sql/sql_class.h index e0f87383189..a903b70fa84 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4630,13 +4630,24 @@ public: public: /** Overloaded to guard query/query_length fields */ virtual void set_statement(Statement *stmt); - void set_command(enum enum_server_command command) + inline void set_command(enum enum_server_command command) { + DBUG_ASSERT(command != COM_SLEEP); m_command= command; #ifdef HAVE_PSI_THREAD_INTERFACE PSI_STATEMENT_CALL(set_thread_command)(m_command); #endif } + /* As sleep needs a bit of special handling, we have a special case for it */ + inline void mark_connection_idle() + { + proc_info= 0; + m_command= COM_SLEEP; +#ifdef HAVE_PSI_THREAD_INTERFACE + PSI_STATEMENT_CALL(set_thread_command)(m_command); +#endif + } + inline enum enum_server_command get_command() const { return m_command; } diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 263c9eab832..eae30ce76aa 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1249,8 +1249,7 @@ void prepare_new_connection_state(THD* thd) embedded server library. TODO: refactor this to avoid code duplication there */ - thd->proc_info= 0; - thd->set_command(COM_SLEEP); + thd->mark_connection_idle(); thd->init_for_queries(); if (opt_init_connect.length && !(sctx->master_access & SUPER_ACL)) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ffba37b84a7..1c487ba9d14 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2465,7 +2465,7 @@ dispatch_end: /* Performance Schema Interface instrumentation, end */ MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); thd->set_examined_row_count(0); // For processlist - thd->set_command(COM_SLEEP); + thd->mark_connection_idle(); thd->m_statement_psi= NULL; thd->m_digest= NULL; @@ -7903,6 +7903,7 @@ static bool wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, thd->wsrep_retry_query = NULL; thd->wsrep_retry_query_len = 0; thd->wsrep_retry_command = COM_CONNECT; + thd->proc_info= 0; } return false; } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 7d549c653f2..2b3e8d41757 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2818,7 +2818,7 @@ static const char *thread_state_info(THD *tmp) if (cond) return "Waiting on cond"; } - return NULL; + return ""; } diff --git a/sql/wsrep_client_service.cc b/sql/wsrep_client_service.cc index 0399cf4f442..0d0443ad5f2 100644 --- a/sql/wsrep_client_service.cc +++ b/sql/wsrep_client_service.cc @@ -287,7 +287,7 @@ enum wsrep::provider::status Wsrep_client_service::replay() replayer_thd->real_id= pthread_self(); replayer_thd->prior_thr_create_utime= replayer_thd->start_utime= microsecond_interval_timer(); - replayer_thd->set_command(COM_SLEEP); + replayer_thd->mark_connection_idle(); replayer_thd->reset_for_next_command(true); enum wsrep::provider::status ret; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 06991c7f44d..6008bc0b72c 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -3015,8 +3015,7 @@ void* start_wsrep_THD(void *arg) thd->security_ctx->skip_grants(); /* handle_one_connection() again... */ - thd->proc_info= 0; - thd->set_command(COM_SLEEP); + thd->mark_connection_idle(); thd->init_for_queries(); mysql_mutex_lock(&LOCK_wsrep_slave_threads); diff --git a/sql/wsrep_server_service.cc b/sql/wsrep_server_service.cc index 7bf9851c25b..70723aefb38 100644 --- a/sql/wsrep_server_service.cc +++ b/sql/wsrep_server_service.cc @@ -39,7 +39,7 @@ static void init_service_thd(THD* thd, char* thread_stack) thd->thread_stack= thread_stack; thd->real_id= pthread_self(); thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer(); - thd->set_command(COM_SLEEP); + thd->mark_connection_idle(); thd->reset_for_next_command(true); } From 21822625aa675b36a5c2548f78e8d3d8cde8b7cd Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 7 Nov 2023 11:00:49 +0100 Subject: [PATCH 209/477] 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 228b7e4db59441656abfb194da0e239fd091cfd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 8 Nov 2023 12:17:14 +0200 Subject: [PATCH 210/477] MDEV-13626 Merge InnoDB test cases from MySQL 5.7 This imports and adapts a number of MySQL 5.7 test cases that are applicable to MariaDB. Some tests for old bug fixes are not that relevant because the code has been refactored since then (especially starting with MariaDB Server 10.6), and the tests would not reproduce the original bug if the fix was reverted. In the test innodb_fts.opt, there are many duplicate MATCH ranks, which would make the results nondeterministic. The test was stabilized by changing some LIMIT clauses or by adding sorted_result in those cases where the purpose of a test was to show that no sorting took place in the server. In the test innodb_fts.phrase, MySQL 5.7 would generate FTS_DOC_ID that are 1 larger than in MariaDB. In innodb_fts.index_table the difference is 2. This is because in MariaDB, fts_get_next_doc_id() post-increments cache->next_doc_id, while MySQL 5.7 pre-increments it. Reviewed by: Thirunarayanan Balathandayuthapani --- .../gcol/r/innodb_prefix_index_check.result | 29 + .../gcol/t/innodb_prefix_index_check.test | 43 + .../suite/innodb/r/add_foreign_key.result | 31 + .../suite/innodb/r/cascade_lock_wait.result | 76 + .../suite/innodb/r/import_update_stats.result | 72 + mysql-test/suite/innodb/r/index_length.result | 23 + mysql-test/suite/innodb/r/innodb-32k.result | 20 + mysql-test/suite/innodb/r/innodb-64k.result | 20 + .../r/innodb-ac-non-locking-select.result | 62 + mysql-test/suite/innodb/r/innodb-alter.result | 56 + .../innodb/r/innodb-index-online-fk.result | 36 + .../innodb-lock-inherit-read_commited.result | 124 ++ .../suite/innodb/r/innodb-read-view.result | 41 +- .../innodb/r/innodb_i_s_innodb_locks.result | Bin 0 -> 5451 bytes .../innodb/r/innodb_i_s_innodb_trx.result | 90 + .../r/innodb_information_schema_tables.result | 1 + .../innodb/r/innodb_stats_auto_recalc.result | 44 + .../r/innodb_stats_auto_recalc_ddl.result | 34 + .../r/innodb_stats_auto_recalc_lots.result | 202 ++ ...db_stats_auto_recalc_on_nonexistent.result | 57 + .../r/innodb_stats_external_pages.result | 10 + .../r/innodb_stats_flag_global,off.rdiff | 34 + .../innodb/r/innodb_stats_flag_global.result | 207 ++ .../innodb/r/innodb_stats_persistent.result | 26 +- .../innodb/r/innodb_stats_sample_pages.result | 29 + ...innodb_stats_table_flag_auto_recalc.result | 82 + ...nnodb_stats_table_flag_sample_pages.result | 95 + .../innodb/r/innodb_ut_format_name.result | 5 + .../suite/innodb/r/records_in_range,4k.rdiff | 8 + .../suite/innodb/r/records_in_range,8k.rdiff | 8 + .../suite/innodb/r/records_in_range.result | 1275 +++++++++++ .../r/tablespace_per_table_not_windows.result | 134 ++ .../r/tablespace_per_table_windows.result | 51 + .../suite/innodb/t/add_foreign_key.test | 38 + .../suite/innodb/t/cascade_lock_wait.test | 45 + .../suite/innodb/t/import_update_stats.test | 81 + mysql-test/suite/innodb/t/index_length.test | 23 + mysql-test/suite/innodb/t/innodb-32k.test | 13 + mysql-test/suite/innodb/t/innodb-64k.test | 13 + .../t/innodb-ac-non-locking-select.test | 117 + mysql-test/suite/innodb/t/innodb-alter.test | 26 + .../innodb/t/innodb-index-online-fk.test | 29 + .../t/innodb-lock-inherit-read_commited.test | 115 + .../suite/innodb/t/innodb-read-view.test | 48 +- .../innodb/t/innodb_i_s_innodb_locks.test | 169 ++ .../suite/innodb/t/innodb_i_s_innodb_trx.test | 95 + .../t/innodb_information_schema_tables.opt | 1 + .../t/innodb_information_schema_tables.test | 4 + .../innodb/t/innodb_stats_auto_recalc.opt | 1 + .../innodb/t/innodb_stats_auto_recalc.test | 48 + .../innodb/t/innodb_stats_auto_recalc_ddl.opt | 1 + .../t/innodb_stats_auto_recalc_ddl.test | 49 + .../t/innodb_stats_auto_recalc_lots.opt | 1 + .../t/innodb_stats_auto_recalc_lots.test | 45 + ...nnodb_stats_auto_recalc_on_nonexistent.opt | 1 + ...nodb_stats_auto_recalc_on_nonexistent.test | 85 + .../innodb/t/innodb_stats_external_pages.test | 79 + .../t/innodb_stats_flag_global.combinations | 4 + .../innodb/t/innodb_stats_flag_global.test | 91 + .../t/innodb_stats_flag_global_analyze.inc | 13 + .../innodb/t/innodb_stats_persistent.test | 39 + .../innodb/t/innodb_stats_sample_pages.opt | 1 + .../innodb/t/innodb_stats_sample_pages.test | 53 + .../innodb_stats_table_flag_auto_recalc.test | 83 + .../innodb_stats_table_flag_sample_pages.test | 103 + .../suite/innodb/t/innodb_ut_format_name.test | 17 + .../suite/innodb/t/records_in_range.test | 432 ++++ .../t/tablespace_per_table_not_windows.opt | 2 + .../t/tablespace_per_table_not_windows.test | 164 ++ .../innodb/t/tablespace_per_table_windows.opt | 2 + .../t/tablespace_per_table_windows.test | 79 + .../innodb_fts/r/foreign_key_check.result | 27 + .../innodb_fts/r/foreign_key_update.result | 34 + .../suite/innodb_fts/r/index_table.result | 265 +++ .../innodb_fts/r/innodb_fts_proximity.result | 5 +- .../suite/innodb_fts/r/limit_union.result | 157 ++ mysql-test/suite/innodb_fts/r/misc.result | 1878 +++++++++++++++++ mysql-test/suite/innodb_fts/r/misc_1.result | 922 ++++++++ mysql-test/suite/innodb_fts/r/opt.result | 1650 +++++++++++++++ mysql-test/suite/innodb_fts/r/phrase.result | 84 + .../innodb_fts/r/result_cache_limit.result | 31 + .../suite/innodb_fts/r/savepoint.result | 318 +++ mysql-test/suite/innodb_fts/r/subexpr.result | 105 + .../suite/innodb_fts/t/foreign_key_check.test | 41 + .../innodb_fts/t/foreign_key_update.test | 34 + mysql-test/suite/innodb_fts/t/index_table.opt | 2 + .../suite/innodb_fts/t/index_table.test | 121 ++ .../innodb_fts/t/innodb_fts_proximity.test | 2 + .../suite/innodb_fts/t/limit_union.test | 143 ++ mysql-test/suite/innodb_fts/t/misc.test | 1511 +++++++++++++ mysql-test/suite/innodb_fts/t/misc_1.test | 894 ++++++++ mysql-test/suite/innodb_fts/t/opt.opt | 1 + mysql-test/suite/innodb_fts/t/opt.test | 1086 ++++++++++ mysql-test/suite/innodb_fts/t/phrase.opt | 2 + mysql-test/suite/innodb_fts/t/phrase.test | 39 + .../innodb_fts/t/result_cache_limit.test | 52 + mysql-test/suite/innodb_fts/t/savepoint.test | 475 +++++ mysql-test/suite/innodb_fts/t/subexpr.test | 58 + .../innodb_gis/r/rtree_create_inplace.result | 36 +- .../innodb_gis/t/rtree_create_inplace.opt | 1 + .../innodb_gis/t/rtree_create_inplace.test | 36 +- 101 files changed, 15119 insertions(+), 126 deletions(-) create mode 100644 mysql-test/suite/innodb/r/add_foreign_key.result create mode 100644 mysql-test/suite/innodb/r/cascade_lock_wait.result create mode 100644 mysql-test/suite/innodb/r/import_update_stats.result create mode 100644 mysql-test/suite/innodb/r/index_length.result create mode 100644 mysql-test/suite/innodb/r/innodb-ac-non-locking-select.result create mode 100644 mysql-test/suite/innodb/r/innodb-lock-inherit-read_commited.result create mode 100644 mysql-test/suite/innodb/r/innodb_i_s_innodb_locks.result create mode 100644 mysql-test/suite/innodb/r/innodb_i_s_innodb_trx.result create mode 100644 mysql-test/suite/innodb/r/innodb_stats_auto_recalc.result create mode 100644 mysql-test/suite/innodb/r/innodb_stats_auto_recalc_ddl.result create mode 100644 mysql-test/suite/innodb/r/innodb_stats_auto_recalc_lots.result create mode 100644 mysql-test/suite/innodb/r/innodb_stats_auto_recalc_on_nonexistent.result create mode 100644 mysql-test/suite/innodb/r/innodb_stats_external_pages.result create mode 100644 mysql-test/suite/innodb/r/innodb_stats_flag_global,off.rdiff create mode 100644 mysql-test/suite/innodb/r/innodb_stats_flag_global.result create mode 100644 mysql-test/suite/innodb/r/innodb_stats_sample_pages.result create mode 100644 mysql-test/suite/innodb/r/innodb_stats_table_flag_auto_recalc.result create mode 100644 mysql-test/suite/innodb/r/innodb_stats_table_flag_sample_pages.result create mode 100644 mysql-test/suite/innodb/r/innodb_ut_format_name.result create mode 100644 mysql-test/suite/innodb/r/records_in_range,4k.rdiff create mode 100644 mysql-test/suite/innodb/r/records_in_range,8k.rdiff create mode 100644 mysql-test/suite/innodb/r/records_in_range.result create mode 100644 mysql-test/suite/innodb/r/tablespace_per_table_not_windows.result create mode 100644 mysql-test/suite/innodb/r/tablespace_per_table_windows.result create mode 100644 mysql-test/suite/innodb/t/add_foreign_key.test create mode 100644 mysql-test/suite/innodb/t/cascade_lock_wait.test create mode 100644 mysql-test/suite/innodb/t/import_update_stats.test create mode 100644 mysql-test/suite/innodb/t/index_length.test create mode 100644 mysql-test/suite/innodb/t/innodb-ac-non-locking-select.test create mode 100644 mysql-test/suite/innodb/t/innodb-lock-inherit-read_commited.test create mode 100644 mysql-test/suite/innodb/t/innodb_i_s_innodb_locks.test create mode 100644 mysql-test/suite/innodb/t/innodb_i_s_innodb_trx.test create mode 100644 mysql-test/suite/innodb/t/innodb_stats_auto_recalc.opt create mode 100644 mysql-test/suite/innodb/t/innodb_stats_auto_recalc.test create mode 100644 mysql-test/suite/innodb/t/innodb_stats_auto_recalc_ddl.opt create mode 100644 mysql-test/suite/innodb/t/innodb_stats_auto_recalc_ddl.test create mode 100644 mysql-test/suite/innodb/t/innodb_stats_auto_recalc_lots.opt create mode 100644 mysql-test/suite/innodb/t/innodb_stats_auto_recalc_lots.test create mode 100644 mysql-test/suite/innodb/t/innodb_stats_auto_recalc_on_nonexistent.opt create mode 100644 mysql-test/suite/innodb/t/innodb_stats_auto_recalc_on_nonexistent.test create mode 100644 mysql-test/suite/innodb/t/innodb_stats_external_pages.test create mode 100644 mysql-test/suite/innodb/t/innodb_stats_flag_global.combinations create mode 100644 mysql-test/suite/innodb/t/innodb_stats_flag_global.test create mode 100644 mysql-test/suite/innodb/t/innodb_stats_flag_global_analyze.inc create mode 100644 mysql-test/suite/innodb/t/innodb_stats_sample_pages.opt create mode 100644 mysql-test/suite/innodb/t/innodb_stats_sample_pages.test create mode 100644 mysql-test/suite/innodb/t/innodb_stats_table_flag_auto_recalc.test create mode 100644 mysql-test/suite/innodb/t/innodb_stats_table_flag_sample_pages.test create mode 100644 mysql-test/suite/innodb/t/innodb_ut_format_name.test create mode 100644 mysql-test/suite/innodb/t/records_in_range.test create mode 100644 mysql-test/suite/innodb/t/tablespace_per_table_not_windows.opt create mode 100644 mysql-test/suite/innodb/t/tablespace_per_table_not_windows.test create mode 100644 mysql-test/suite/innodb/t/tablespace_per_table_windows.opt create mode 100644 mysql-test/suite/innodb/t/tablespace_per_table_windows.test create mode 100644 mysql-test/suite/innodb_fts/r/foreign_key_check.result create mode 100644 mysql-test/suite/innodb_fts/r/foreign_key_update.result create mode 100644 mysql-test/suite/innodb_fts/r/index_table.result create mode 100644 mysql-test/suite/innodb_fts/r/limit_union.result create mode 100644 mysql-test/suite/innodb_fts/r/misc.result create mode 100644 mysql-test/suite/innodb_fts/r/misc_1.result create mode 100644 mysql-test/suite/innodb_fts/r/opt.result create mode 100644 mysql-test/suite/innodb_fts/r/phrase.result create mode 100644 mysql-test/suite/innodb_fts/r/result_cache_limit.result create mode 100644 mysql-test/suite/innodb_fts/r/savepoint.result create mode 100644 mysql-test/suite/innodb_fts/r/subexpr.result create mode 100644 mysql-test/suite/innodb_fts/t/foreign_key_check.test create mode 100644 mysql-test/suite/innodb_fts/t/foreign_key_update.test create mode 100644 mysql-test/suite/innodb_fts/t/index_table.opt create mode 100644 mysql-test/suite/innodb_fts/t/index_table.test create mode 100644 mysql-test/suite/innodb_fts/t/limit_union.test create mode 100644 mysql-test/suite/innodb_fts/t/misc.test create mode 100644 mysql-test/suite/innodb_fts/t/misc_1.test create mode 100644 mysql-test/suite/innodb_fts/t/opt.opt create mode 100644 mysql-test/suite/innodb_fts/t/opt.test create mode 100644 mysql-test/suite/innodb_fts/t/phrase.opt create mode 100644 mysql-test/suite/innodb_fts/t/phrase.test create mode 100644 mysql-test/suite/innodb_fts/t/result_cache_limit.test create mode 100644 mysql-test/suite/innodb_fts/t/savepoint.test create mode 100644 mysql-test/suite/innodb_fts/t/subexpr.test create mode 100644 mysql-test/suite/innodb_gis/t/rtree_create_inplace.opt diff --git a/mysql-test/suite/gcol/r/innodb_prefix_index_check.result b/mysql-test/suite/gcol/r/innodb_prefix_index_check.result index 01dbe4a6592..ea84cd154ad 100644 --- a/mysql-test/suite/gcol/r/innodb_prefix_index_check.result +++ b/mysql-test/suite/gcol/r/innodb_prefix_index_check.result @@ -13,3 +13,32 @@ key(f1,f2(1)) )ENGINE=INNODB; REPLACE INTO t1(f3) VALUES (1),(1); DROP TABLE t1; +#Create and alter table examples for full column index followed by prefix index. +CREATE TABLE t1( +f1 VARCHAR(100), +f2 char(2), +KEY(f1,f2), +KEY(f1(5)))ENGINE=INNODB; +REPLACE INTO t1(f2) VALUES (1),(1); +ALTER TABLE t1 ADD INDEX(f2,f1); +DROP TABLE t1; +#Create and alter table examples for small prefix index followed by large +#prefix index. +CREATE TABLE t1( +f1 VARCHAR(100), +f2 char(2), +KEY(f1(5),f2), +KEY(f1(10)))ENGINE=INNODB; +REPLACE INTO t1(f2) VALUES (1),(1); +ALTER TABLE t1 ADD INDEX(f2,f1); +DROP TABLE t1; +#Create and alter table examples for prefix index followed by full column +#index. +CREATE TABLE t1( +f1 VARCHAR(100), +f2 char(2), +KEY(f1(5),f2), +KEY(f1))ENGINE=INNODB; +REPLACE INTO t1(f2) VALUES (1),(1); +ALTER TABLE t1 ADD INDEX(f2,f1); +DROP TABLE t1; diff --git a/mysql-test/suite/gcol/t/innodb_prefix_index_check.test b/mysql-test/suite/gcol/t/innodb_prefix_index_check.test index 4923ead91ac..5cc46e16dde 100644 --- a/mysql-test/suite/gcol/t/innodb_prefix_index_check.test +++ b/mysql-test/suite/gcol/t/innodb_prefix_index_check.test @@ -20,3 +20,46 @@ REPLACE INTO t1(f3) VALUES (1),(1); DROP TABLE t1; +--echo #Create and alter table examples for full column index followed by prefix index. + +CREATE TABLE t1( +f1 VARCHAR(100), +f2 char(2), +KEY(f1,f2), +KEY(f1(5)))ENGINE=INNODB; + +REPLACE INTO t1(f2) VALUES (1),(1); + +ALTER TABLE t1 ADD INDEX(f2,f1); + +DROP TABLE t1; + +--echo #Create and alter table examples for small prefix index followed by large +--echo #prefix index. + +CREATE TABLE t1( +f1 VARCHAR(100), +f2 char(2), +KEY(f1(5),f2), +KEY(f1(10)))ENGINE=INNODB; + +REPLACE INTO t1(f2) VALUES (1),(1); + +ALTER TABLE t1 ADD INDEX(f2,f1); + +DROP TABLE t1; + +--echo #Create and alter table examples for prefix index followed by full column +--echo #index. + +CREATE TABLE t1( +f1 VARCHAR(100), +f2 char(2), +KEY(f1(5),f2), +KEY(f1))ENGINE=INNODB; + +REPLACE INTO t1(f2) VALUES (1),(1); + +ALTER TABLE t1 ADD INDEX(f2,f1); + +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/add_foreign_key.result b/mysql-test/suite/innodb/r/add_foreign_key.result new file mode 100644 index 00000000000..75177478e60 --- /dev/null +++ b/mysql-test/suite/innodb/r/add_foreign_key.result @@ -0,0 +1,31 @@ +# +# Bug #19471516 SERVER CRASHES WHEN EXECUTING ALTER TABLE ADD +# FOREIGN KEY +# +CREATE TABLE `parent` (`parent_id` INT, PRIMARY KEY (`parent_id`)); +CREATE TABLE `child1` (`id` INT ,`child1_fk1` INT, `child1_fk2` INT, +PRIMARY KEY (`id`)); +CREATE TABLE `child2` (`id` INT, `child2_fk1` INT, `child2_fk2` INT, +PRIMARY KEY (`id`)); +CREATE TABLE `child3` (`id` INT , `child3_fk1` INT, PRIMARY KEY (`id`)); +ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk1`) REFERENCES `parent` +(`parent_id`); +ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk1`) REFERENCES +`parent` (`parent_id`); +ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk2`) REFERENCES `parent` +(`parent_id`); +ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk1`) REFERENCES `parent` +(`parent_id`); +ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk2`) REFERENCES `parent` +(`parent_id`); +ALTER TABLE `child3` ADD FOREIGN KEY (`child3_fk1`) REFERENCES `parent` +(`parent_id`); +ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk2`) REFERENCES +`parent` (`parent_id`); +ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk1`) REFERENCES +`parent` (`parent_id`); +ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk2`) REFERENCES +`parent` (`parent_id`); +ALTER TABLE `child3` ADD FOREIGN KEY (`child3_fk1`) REFERENCES +`parent` (`parent_id`); +drop table child3, child2, child1, parent; diff --git a/mysql-test/suite/innodb/r/cascade_lock_wait.result b/mysql-test/suite/innodb/r/cascade_lock_wait.result new file mode 100644 index 00000000000..9cc05df739e --- /dev/null +++ b/mysql-test/suite/innodb/r/cascade_lock_wait.result @@ -0,0 +1,76 @@ +create table t1 (f1 int primary key) engine=innodb; +create table t2 (f1 int primary key, +constraint c1 foreign key (f1) references t1(f1) +on update cascade +on delete cascade) engine=innodb; +create table t3 (f1 int primary key, +constraint c2 foreign key (f1) references t1(f1) +on update cascade +on delete cascade) engine=innodb; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`), + CONSTRAINT `c1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +show create table t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`), + CONSTRAINT `c2` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +insert into t1 values (1); +insert into t1 values (2); +insert into t1 values (3); +insert into t2 values (1); +insert into t2 values (2); +insert into t2 values (3); +insert into t3 values (1); +insert into t3 values (2); +insert into t3 values (3); +select f1 from t1; +f1 +1 +2 +3 +select f1 from t2; +f1 +1 +2 +3 +select f1 from t3; +f1 +1 +2 +3 +set @save_dbug = @@debug_dbug; +set debug_dbug = '+d,dml_cascade_only_once'; +set debug_dbug = '+d,row_upd_cascade_lock_wait_err'; +update t1 set f1 = 100 where f1 = 2; +select f1 from t1; +f1 +1 +3 +100 +select f1 from t2; +f1 +1 +3 +100 +select f1 from t3; +f1 +1 +3 +100 +set debug_dbug = @save_dbug; +drop table t2; +drop table t3; +drop table t1; diff --git a/mysql-test/suite/innodb/r/import_update_stats.result b/mysql-test/suite/innodb/r/import_update_stats.result new file mode 100644 index 00000000000..57b3abf42af --- /dev/null +++ b/mysql-test/suite/innodb/r/import_update_stats.result @@ -0,0 +1,72 @@ +SET @old_innodb_file_per_table = @@innodb_file_per_table; +SET GLOBAL innodb_file_per_table = 1; +SELECT @@innodb_file_per_table; +@@innodb_file_per_table +1 +CREATE TABLE t1 ( +col_1 CHAR (255), +col_2 VARCHAR (255) +) ENGINE = InnoDB; +CREATE INDEX idx1 ON t1(col_1); +CREATE INDEX idx2 ON t1(col_2); +SHOW INDEXES FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t1 1 idx1 1 col_1 A 0 NULL NULL YES BTREE +t1 1 idx2 1 col_2 A 0 NULL NULL YES BTREE +INSERT INTO t1 VALUES ("col1_00001", "col2_00001"), ("col1_00002", "col2_00002"); +SHOW INDEXES FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t1 1 idx1 1 col_1 A 2 NULL NULL YES BTREE +t1 1 idx2 1 col_2 A 2 NULL NULL YES BTREE +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SHOW INDEXES FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t1 1 idx1 1 col_1 A 2 NULL NULL YES BTREE +t1 1 idx2 1 col_2 A 2 NULL NULL YES BTREE +FLUSH TABLES t1 FOR EXPORT; +backup: t1 +UNLOCK TABLES; +DROP TABLE t1; +CREATE TABLE t1 ( +col_1 CHAR (255), +col_2 VARCHAR (255) +) ENGINE = InnoDB STATS_PERSISTENT=1; +CREATE INDEX idx1 ON t1(col_1); +CREATE INDEX idx2 ON t1(col_2); +SHOW INDEXES FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t1 1 idx1 1 col_1 A 0 NULL NULL YES BTREE +t1 1 idx2 1 col_2 A 0 NULL NULL YES BTREE +INSERT INTO t1 VALUES ("col1_00001", "col2_00001"); +SHOW INDEXES FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t1 1 idx1 1 col_1 A 1 NULL NULL YES BTREE +t1 1 idx2 1 col_2 A 1 NULL NULL YES BTREE +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +SHOW INDEXES FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t1 1 idx1 1 col_1 A 1 NULL NULL YES BTREE +t1 1 idx2 1 col_2 A 1 NULL NULL YES BTREE +ALTER TABLE t1 DISCARD TABLESPACE; +restore: t1 .ibd and .cfg files +ALTER TABLE t1 IMPORT TABLESPACE; +SHOW INDEXES FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t1 1 idx1 1 col_1 A 2 NULL NULL YES BTREE +t1 1 idx2 1 col_2 A 2 NULL NULL YES BTREE +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +SHOW INDEXES FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t1 1 idx1 1 col_1 A 2 NULL NULL YES BTREE +t1 1 idx2 1 col_2 A 2 NULL NULL YES BTREE +DROP TABLE t1; +SET GLOBAL innodb_file_per_table = @old_innodb_file_per_table; diff --git a/mysql-test/suite/innodb/r/index_length.result b/mysql-test/suite/innodb/r/index_length.result new file mode 100644 index 00000000000..cc92780ac32 --- /dev/null +++ b/mysql-test/suite/innodb/r/index_length.result @@ -0,0 +1,23 @@ +connect stop_purge,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +CREATE TABLE t1(a INT PRIMARY KEY, b VARCHAR(1024)) +ENGINE=InnoDB STATS_PERSISTENT=1; +INSERT INTO t1 VALUES (1,REPEAT('b',1024)); +SELECT index_length FROM information_schema.tables +WHERE table_schema = 'test' AND table_name = 't1'; +index_length +0 +ALTER TABLE t1 ADD INDEX b (b(800)); +SELECT FLOOR(index_length/@@innodb_page_size) FROM information_schema.tables +WHERE table_schema = 'test' AND table_name = 't1'; +FLOOR(index_length/@@innodb_page_size) +1 +ALTER TABLE t1 ADD INDEX ba (b(800),a); +SELECT FLOOR(index_length/@@innodb_page_size) FROM information_schema.tables +WHERE table_schema = 'test' AND table_name = 't1'; +FLOOR(index_length/@@innodb_page_size) +2 +disconnect stop_purge; +DROP TABLE t1; +# End of 10.4 tests diff --git a/mysql-test/suite/innodb/r/innodb-32k.result b/mysql-test/suite/innodb/r/innodb-32k.result index e39939b5d13..e4a980a83be 100644 --- a/mysql-test/suite/innodb/r/innodb-32k.result +++ b/mysql-test/suite/innodb/r/innodb-32k.result @@ -1,4 +1,24 @@ call mtr.add_suppression("Innodb: Cannot add field.*row size is"); +SET SESSION innodb_strict_mode=ON; +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB KEY_BLOCK_SIZE=4; +ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") +SET SESSION innodb_strict_mode=OFF; +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +Warnings: +Warning 1478 InnoDB: Cannot create a COMPRESSED table when innodb_page_size > 16k. Assuming ROW_FORMAT=DYNAMIC. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: Cannot create a COMPRESSED table when innodb_page_size > 16k. Assuming ROW_FORMAT=DYNAMIC. +DROP TABLE t1; +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB KEY_BLOCK_SIZE=4; +Warnings: +Warning 1478 InnoDB: Cannot create a COMPRESSED table when innodb_page_size > 16k. Assuming ROW_FORMAT=DYNAMIC. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: Cannot create a COMPRESSED table when innodb_page_size > 16k. Assuming ROW_FORMAT=DYNAMIC. +DROP TABLE t1; # Test 1) Show the page size from Information Schema SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size'; diff --git a/mysql-test/suite/innodb/r/innodb-64k.result b/mysql-test/suite/innodb/r/innodb-64k.result index 758179568b9..c172483905e 100644 --- a/mysql-test/suite/innodb/r/innodb-64k.result +++ b/mysql-test/suite/innodb/r/innodb-64k.result @@ -1,4 +1,24 @@ call mtr.add_suppression('InnoDB: Cannot add field.*because after adding it, the row size is'); +SET SESSION innodb_strict_mode=ON; +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB KEY_BLOCK_SIZE=4; +ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") +SET SESSION innodb_strict_mode=OFF; +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +Warnings: +Warning 1478 InnoDB: Cannot create a COMPRESSED table when innodb_page_size > 16k. Assuming ROW_FORMAT=DYNAMIC. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: Cannot create a COMPRESSED table when innodb_page_size > 16k. Assuming ROW_FORMAT=DYNAMIC. +DROP TABLE t1; +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB KEY_BLOCK_SIZE=4; +Warnings: +Warning 1478 InnoDB: Cannot create a COMPRESSED table when innodb_page_size > 16k. Assuming ROW_FORMAT=DYNAMIC. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: Cannot create a COMPRESSED table when innodb_page_size > 16k. Assuming ROW_FORMAT=DYNAMIC. +DROP TABLE t1; # Test 1) Show the page size from Information Schema SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size'; diff --git a/mysql-test/suite/innodb/r/innodb-ac-non-locking-select.result b/mysql-test/suite/innodb/r/innodb-ac-non-locking-select.result new file mode 100644 index 00000000000..5d12c1076e7 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-ac-non-locking-select.result @@ -0,0 +1,62 @@ +CREATE TABLE t1 (c1 INT , c2 CHAR(10), PRIMARY KEY (c1)) ENGINE = InnoDB; +INSERT INTO t1 VALUES(0, "0"); +INSERT INTO t1 VALUES(1, "1"); +INSERT INTO t1 VALUES(2, "2"); +INSERT INTO t1 VALUES(3, "3"); +connect con1,localhost,root,,; +connect con2,localhost,root,,; +connect con3,localhost,root,,; +connect con4,localhost,root,,; +connect con5,localhost,root,,; +connect con6,localhost,root,,; +connection default; +SET AUTOCOMMIT=0; +BEGIN; +SELECT * FROM t1 FOR UPDATE; +c1 c2 +0 0 +1 1 +2 2 +3 3 +SELECT * FROM t1 WHERE c1 <= 3; +c1 c2 +0 0 +1 1 +2 2 +3 3 +connection default; +SET DEBUG_SYNC='now WAIT_FOR waiting4'; +SET DEBUG_SYNC= 'RESET'; +SELECT trx_state, trx_query, trx_autocommit_non_locking +FROM INFORMATION_SCHEMA.INNODB_TRX +WHERE trx_state = 'LOCK WAIT' +ORDER BY trx_query; +trx_state trx_query trx_autocommit_non_locking +LOCK WAIT SELECT COUNT(*) FROM t1 LOCK IN SHARE MODE 0 +LOCK WAIT SELECT COUNT(*) FROM t1 WHERE c1 >= 0 0 +INSERT INTO t1 VALUES(4, '4'); +COMMIT; +connection con6; +SELECT * FROM t1 WHERE c1 <= 4; +c1 c2 +0 0 +1 1 +2 2 +3 3 +XA END '1'; +XA PREPARE '1'; +XA ROLLBACK '1'; +disconnect con6; +disconnect con2; +disconnect con3; +disconnect con5; +connection con1; +COUNT(*) +5 +disconnect con1; +connection con4; +COUNT(*) +5 +disconnect con4; +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb-alter.result b/mysql-test/suite/innodb/r/innodb-alter.result index 2b3120016aa..126821de203 100644 --- a/mysql-test/suite/innodb/r/innodb-alter.result +++ b/mysql-test/suite/innodb/r/innodb-alter.result @@ -1090,3 +1090,59 @@ ALTER TABLE t1 ADD COLUMN b DATETIME NOT NULL, LOCK=NONE; # Cleanup SET @@SQL_MODE= @OLD_SQL_MODE; DROP TABLE t1; +# +# Bug#20977779 CANNOT IMPORT TABLES CONTAINING PREFIX INDEXES +# +CREATE TABLE t1 (c1 VARCHAR(32), c2 VARCHAR(32), c3 VARCHAR(32), +PRIMARY KEY (c1, c2, c3)) +ENGINE=InnoDB; +ALTER TABLE t1 ADD INDEX ind1(c1(5), c2, c3); +ALTER TABLE t1 ADD INDEX ind2(c3, c1(10), c2); +ALTER TABLE t1 ADD INDEX ind3(c2, c3, c1(20)); +INSERT INTO t1 VALUES ('Test Data -1', 'Test Data -2', 'Test Data -3'); +# Test with 2ndary index having prefix +FLUSH TABLES test.t1 FOR EXPORT; +UNLOCK TABLES; +ALTER TABLE test.t1 DISCARD TABLESPACE; +ALTER TABLE test.t1 IMPORT TABLESPACE; +CHECK TABLE test.t1; +Table Op Msg_type Msg_text +test.t1 check status OK +SHOW CREATE TABLE test.t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` varchar(32) NOT NULL, + `c2` varchar(32) NOT NULL, + `c3` varchar(32) NOT NULL, + PRIMARY KEY (`c1`,`c2`,`c3`), + KEY `ind1` (`c1`(5),`c2`,`c3`), + KEY `ind2` (`c3`,`c1`(10),`c2`), + KEY `ind3` (`c2`,`c3`,`c1`(20)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT * FROM test.t1; +c1 c2 c3 +Test Data -1 Test Data -2 Test Data -3 +# Test with PK & 2ndary index with prefix +ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c1(5), c2(10), c3(20)); +FLUSH TABLES test.t1 FOR EXPORT; +UNLOCK TABLES; +ALTER TABLE test.t1 DISCARD TABLESPACE; +ALTER TABLE test.t1 IMPORT TABLESPACE; +CHECK TABLE test.t1; +Table Op Msg_type Msg_text +test.t1 check status OK +SHOW CREATE TABLE test.t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` varchar(32) NOT NULL, + `c2` varchar(32) NOT NULL, + `c3` varchar(32) NOT NULL, + PRIMARY KEY (`c1`(5),`c2`(10),`c3`(20)), + KEY `ind1` (`c1`(5),`c2`,`c3`), + KEY `ind2` (`c3`,`c1`(10),`c2`), + KEY `ind3` (`c2`,`c3`,`c1`(20)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT * FROM test.t1; +c1 c2 c3 +Test Data -1 Test Data -2 Test Data -3 +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb-index-online-fk.result b/mysql-test/suite/innodb/r/innodb-index-online-fk.result index b610d7a00b5..afe55543e55 100644 --- a/mysql-test/suite/innodb/r/innodb-index-online-fk.result +++ b/mysql-test/suite/innodb/r/innodb-index-online-fk.result @@ -618,3 +618,39 @@ test/e d a 0 test/fw c a 0 DROP TABLE t2; DROP TABLE t3; +# Bug #17449901 TABLE DISAPPEARS WHEN ALTERING +# WITH FOREIGN KEY CHECKS OFF +create table t1(f1 int,primary key(f1))engine=innodb; +create table t2(f2 int,f3 int,key t(f2,f3),foreign key(f2) references t1(f1))engine=innodb; +SET foreign_key_checks=0; +drop index t on t2; +drop table t2; +drop table t1; +create table t1(f1 int ,primary key(f1))engine=innodb; +create table t2(f2 int,f3 int, key t(f2),foreign key(f2) references t1(f1))engine=innodb; +SET foreign_key_checks = 0; +alter table t2 drop key t,algorithm=inplace; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f2` int(11) DEFAULT NULL, + `f3` int(11) DEFAULT NULL, + CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +drop table t2; +drop table t1; +create table t1(f1 int ,primary key(f1))engine=innodb; +create table t2(f2 int,f3 int, key t(f2),key t1(f2,f3), +foreign key(f2) references t1(f1))engine=innodb; +SET foreign_key_checks = 0; +alter table t2 drop key t,algorithm=inplace; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f2` int(11) DEFAULT NULL, + `f3` int(11) DEFAULT NULL, + KEY `t1` (`f2`,`f3`), + CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +drop table t2; +drop table t1; diff --git a/mysql-test/suite/innodb/r/innodb-lock-inherit-read_commited.result b/mysql-test/suite/innodb/r/innodb-lock-inherit-read_commited.result new file mode 100644 index 00000000000..1fe569d28ef --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-lock-inherit-read_commited.result @@ -0,0 +1,124 @@ +# +# Bug #21025880 DUPLICATE UK VALUES IN READ-COMMITTED(AGAIN) +# +SET @save_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency=1; +CREATE TABLE t1 ( +a INT NOT NULL, +b INT NOT NULL, +PRIMARY KEY(b), +UNIQUE KEY(a)) +ENGINE=INNODB; +SET @old_innodb_stats_auto_recalc = @@innodb_stats_auto_recalc; +SET GLOBAL innodb_stats_auto_recalc = OFF; +connect purge_control,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +SET @old_tx_isolation = @@tx_isolation; +SET GLOBAL tx_isolation = 'READ-COMMITTED'; +SET @old_innodb_lock_wait_timeout = @@innodb_lock_wait_timeout; +SET GLOBAL innodb_lock_wait_timeout = 1; +connect con1,localhost,root,,; +INSERT INTO t1 VALUES (1,1),(2,2); +DELETE FROM t1; +SET debug_sync = 'row_ins_sec_index_entry_dup_locks_created SIGNAL +con1_locks_done WAIT_FOR con1_go'; +SET debug_sync = 'ha_commit_trans_after_acquire_commit_lock SIGNAL +con1_insert_done WAIT_FOR con1_finish'; +REPLACE INTO t1 VALUES (1,2); +connect con2,localhost,root,,; +SET debug_sync = 'now WAIT_FOR con1_locks_done'; +SET debug_sync = 'lock_wait_suspend_thread_enter SIGNAL con2_blocked +WAIT_FOR con2_go'; +SET debug_sync = 'ha_commit_trans_after_acquire_commit_lock +WAIT_FOR con2_finish'; +SET debug_sync = 'ib_after_row_insert SIGNAL con2_insert_done'; +REPLACE INTO t1 VALUES (1,3); +connection default; +SET debug_sync = 'now WAIT_FOR con2_blocked'; +connection purge_control; +COMMIT; +disconnect purge_control; +connection default; +InnoDB 0 transactions not purged +SET debug_sync = 'now SIGNAL con2_go WAIT_FOR con2_insert_done'; +SET debug_sync = 'now SIGNAL con1_go WAIT_FOR con1_insert_done'; +SET debug_sync = 'now SIGNAL con1_finish'; +connection con1; +disconnect con1; +connection default; +SET debug_sync = 'now SIGNAL con2_finish'; +connection con2; +disconnect con2; +connection default; +SET DEBUG_SYNC= 'RESET'; +SELECT * FROM t1; +a b +1 2 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +SET GLOBAL innodb_stats_auto_recalc = @old_innodb_stats_auto_recalc; +SET GLOBAL tx_isolation = @old_tx_isolation; +SET GLOBAL innodb_lock_wait_timeout = @old_innodb_lock_wait_timeout; +CREATE TABLE t1 ( +a INT NOT NULL, +b INT NOT NULL, +PRIMARY KEY(b), +UNIQUE KEY(a)) +ENGINE=INNODB; +SET @old_innodb_stats_auto_recalc = @@innodb_stats_auto_recalc; +SET GLOBAL innodb_stats_auto_recalc = OFF; +connect purge_control,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +SET @old_tx_isolation = @@tx_isolation; +SET GLOBAL tx_isolation = 'READ-COMMITTED'; +SET @old_innodb_lock_wait_timeout = @@innodb_lock_wait_timeout; +SET GLOBAL innodb_lock_wait_timeout = 1; +connect con1,localhost,root,,; +INSERT INTO t1 VALUES (1,1),(2,2); +DELETE FROM t1; +SET debug_sync = 'row_ins_sec_index_entry_dup_locks_created SIGNAL +con1_locks_done WAIT_FOR con1_go'; +SET debug_sync = 'ha_commit_trans_after_acquire_commit_lock SIGNAL +con1_insert_done WAIT_FOR con1_finish'; +INSERT INTO t1 values (1,2) ON DUPLICATE KEY UPDATE a=2; +connect con2,localhost,root,,; +SET debug_sync = 'now WAIT_FOR con1_locks_done'; +SET debug_sync = 'lock_wait_suspend_thread_enter SIGNAL con2_blocked +WAIT_FOR con2_go'; +SET debug_sync = 'ha_commit_trans_after_acquire_commit_lock +WAIT_FOR con2_finish'; +SET debug_sync = 'ib_after_row_insert SIGNAL con2_insert_done'; +REPLACE INTO t1 VALUES (1,3); +connection default; +SET debug_sync = 'now WAIT_FOR con2_blocked'; +connection purge_control; +COMMIT; +disconnect purge_control; +connection default; +InnoDB 0 transactions not purged +SET debug_sync = 'now SIGNAL con2_go WAIT_FOR con2_insert_done'; +SET debug_sync = 'now SIGNAL con1_go WAIT_FOR con1_insert_done'; +SET debug_sync = 'now SIGNAL con1_finish'; +connection con1; +disconnect con1; +connection default; +SET debug_sync = 'now SIGNAL con2_finish'; +connection con2; +disconnect con2; +connection default; +SET DEBUG_SYNC= 'RESET'; +SELECT * FROM t1; +a b +1 2 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +SET GLOBAL innodb_stats_auto_recalc = @old_innodb_stats_auto_recalc; +SET GLOBAL tx_isolation = @old_tx_isolation; +SET GLOBAL innodb_lock_wait_timeout = @old_innodb_lock_wait_timeout; +SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; diff --git a/mysql-test/suite/innodb/r/innodb-read-view.result b/mysql-test/suite/innodb/r/innodb-read-view.result index e01d8a110e6..f3084fbdc52 100644 --- a/mysql-test/suite/innodb/r/innodb-read-view.result +++ b/mysql-test/suite/innodb/r/innodb-read-view.result @@ -9,9 +9,6 @@ INSERT INTO t2 VALUES(1, "b"); INSERT INTO t2 VALUES(2, "c"); INSERT INTO t2 VALUES(3, "d"); connect con1,localhost,root,,; -connect con2,localhost,root,,; -connection con1; -'T1' SET AUTOCOMMIT=0; BEGIN; SELECT * FROM t2; @@ -21,7 +18,6 @@ c1 c2 2 c 3 d connection default; -'T2' SET AUTOCOMMIT=0; BEGIN; SELECT * FROM t1; @@ -30,8 +26,7 @@ c1 c2 1 1 2 2 3 3 -connection con2; -'T3' +connect con2,localhost,root,,; SET AUTOCOMMIT=0; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN; @@ -48,7 +43,6 @@ c1 c2 2 c 3 d connection con1; -'T1' UPDATE t2 SET c1 = c1 + 100; SELECT * FROM t2; c1 c2 @@ -58,7 +52,6 @@ c1 c2 103 d COMMIT; connection default; -'T2' UPDATE t1 SET c1 = c1 + 100; SELECT * FROM t1; c1 c2 @@ -68,42 +61,29 @@ c1 c2 103 3 COMMIT; connection con2; -'T3' SET DEBUG_SYNC='row_search_for_mysql_before_return WAIT_FOR waiting1'; SELECT * FROM t1;; connection default; -'T2' SET DEBUG_SYNC='now SIGNAL waiting1'; -'Signalled T3' connection con2; -'T3' c1 c2 0 0 1 1 2 2 3 3 connection con2; -'T3' SET DEBUG_SYNC='row_search_for_mysql_before_return WAIT_FOR waiting1'; SELECT * FROM t2;; connection default; -'T2' SET DEBUG_SYNC='now SIGNAL waiting1'; -'Signalled T3' connection con2; -'T3' c1 c2 0 a 1 b 2 c 3 d connection default; -disconnect con1; -disconnect con2; -connect con1,localhost,root,,; -connect con2,localhost,root,,; connection con1; -'T1' SET AUTOCOMMIT=0; BEGIN; SELECT * FROM t1; @@ -113,7 +93,6 @@ c1 c2 102 2 103 3 connection default; -'T2' SET AUTOCOMMIT=0; BEGIN; SELECT * FROM t2; @@ -131,7 +110,6 @@ c1 c2 203 d COMMIT; connection con2; -'T3' SET AUTOCOMMIT=0; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN; @@ -148,7 +126,6 @@ c1 c2 202 c 203 d connection con1; -'T1' UPDATE t1 SET c1 = c1 + 100; SELECT * FROM t1; c1 c2 @@ -158,44 +135,34 @@ c1 c2 203 3 COMMIT; connection con2; -'T3' SET DEBUG_SYNC='row_select_wait WAIT_FOR waiting1'; SELECT * FROM t1;; connection con1; -'T2' SET DEBUG_SYNC='now SIGNAL waiting1'; -'Signalled T3' connection con2; -'T3' c1 c2 100 0 101 1 102 2 103 3 -connection con2; -'T3' SET DEBUG_SYNC='row_select_wait WAIT_FOR waiting1'; SELECT * FROM t2;; connection default; -'T2' SET DEBUG_SYNC='now SIGNAL waiting1'; -'Signalled T3' connection con2; -'T3' c1 c2 200 a 201 b 202 c 203 d -connection default; -disconnect con1; disconnect con2; +connection default; DROP TABLE t1; DROP TABLE t2; # # Bug 21433768: NON-REPEATABLE READ WITH REPEATABLE READ ISOLATION # -connect con1,localhost,root,,; +connection con1; CREATE TABLE t1(col1 INT PRIMARY KEY, col2 INT) ENGINE = InnoDB; INSERT INTO t1 values (1, 0), (2, 0); SELECT * FROM t1 ORDER BY col1; @@ -218,5 +185,5 @@ SET DEBUG_SYNC = 'now SIGNAL s2'; connection con1; disconnect con1; connection default; -DROP TABLE t1; SET DEBUG_SYNC= 'RESET'; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb_i_s_innodb_locks.result b/mysql-test/suite/innodb/r/innodb_i_s_innodb_locks.result new file mode 100644 index 0000000000000000000000000000000000000000..a410362ab525f846535b8d12f6b86fd9527d6b05 GIT binary patch literal 5451 zcmeGgYj4^}FkjcdV&yMRDiZl^5JCz8H$erQ8o0YimW&Io4qd=GFl}SX-JQoy>?yt61z$oxUaiAuA9pStik$q~LeI6kQ=3k^S3{e|{(7~cr@}&3=yWi?8;qw7K-3hWv+-nb zJ+}Ku)#zl@9S##7J;Mr21|8Y`!EBUpnFqAMX3>P9i9n&NMXv_eyjPJEILC174n|$~ zj()K3PC@Mk1$D8}u+gzGuraZ*uxVn`f<}?ggfnW7LAc!+jK@y@s@)a_S{}GnU>lDdUY3Y zSX0+cOV?#fv*eaxD5heRH)cMc$C4-dyLdat{ZT+Gw|CQZPc`)nZh%_CwGytEaHE8q zCEP0Fg_Dg38_zW!YdqC>sPRl&)iYc;!i6=YMwJw)L8ai+0{^5GKwM%SlEk|L1~3}u zf_@3Cl)od#Cs1<}h{;6oCo-~_NQZw$Kn78)Cs@k~_Pm2+&tn~)m&itd(-@Zrzj_ns zhY93ISvD0@HNoieBZp*}!_bq_Ib7^P{|c5`M4L^xh$#htIqL>^?BM>-XcsrOQ4}{C zB_8mPO!h)?80sA@AePdaJ^r@CLM>c=(3HzDsN#{-@>fDg;{@% z`AfK6eSU(KX0dVi{E$_&$##WD&0rr#i)g)G#T^+bL%TPn@92Bi86~0Mz2nl^Z65+A zY@4hQh&AwO@agaw@R{&g@HOFU5r{DYh7BSU9yAb0LI#4F%VHc=M+M}n9^f6nMGx?# z1RN=0ev~jbN)j(hQYT6>g)DM#p`@yqMUFYplCA~UP*52x2ZjT?f!V-nU^Gim2;63Z z&IkdC1mJ{NBQc^R2`b}2Z-IbF0&pO#5eau8g2p(|Eg;~L0K5QeJc2~e6LiLLl5m`m z-~>6K;o!+hdS%n&k-LyJ&IG^i+1SGkJu?!kG$=sC0T^z_{sPg7rs z48pbR%x<&D5Tl4BG%%Q?(uCB}!zn{st9im|lPBaC0O{^7jFUI3-QV{<#yUtBE-zCA zL*bN8J`Vkn)3-ZP7ao-Sk27a#Po!d)WC}HCs?iT#pNN4>yb#&?L|9*ru-fDa>t<8 literal 0 HcmV?d00001 diff --git a/mysql-test/suite/innodb/r/innodb_i_s_innodb_trx.result b/mysql-test/suite/innodb/r/innodb_i_s_innodb_trx.result new file mode 100644 index 00000000000..e4bb83a3b24 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_i_s_innodb_trx.result @@ -0,0 +1,90 @@ +SET @save_timeout=@@GLOBAL.innodb_lock_wait_timeout; +SET GLOBAL innodb_lock_wait_timeout=100000000; +DESCRIBE INFORMATION_SCHEMA.INNODB_TRX; +Field Type Null Key Default Extra +trx_id varchar(18) NO NULL +trx_state varchar(13) NO NULL +trx_started datetime NO NULL +trx_requested_lock_id varchar(81) YES NULL +trx_wait_started datetime YES NULL +trx_weight bigint(21) unsigned NO NULL +trx_mysql_thread_id bigint(21) unsigned NO NULL +trx_query varchar(1024) YES NULL +trx_operation_state varchar(64) YES NULL +trx_tables_in_use bigint(21) unsigned NO NULL +trx_tables_locked bigint(21) unsigned NO NULL +trx_lock_structs bigint(21) unsigned NO NULL +trx_lock_memory_bytes bigint(21) unsigned NO NULL +trx_rows_locked bigint(21) unsigned NO NULL +trx_rows_modified bigint(21) unsigned NO NULL +trx_concurrency_tickets bigint(21) unsigned NO NULL +trx_isolation_level varchar(16) NO NULL +trx_unique_checks int(1) NO NULL +trx_foreign_key_checks int(1) NO NULL +trx_last_foreign_key_error varchar(256) YES NULL +trx_is_read_only int(1) NO NULL +trx_autocommit_non_locking int(1) NO NULL +CREATE TABLE t1 ( +c01 INT, +c02 INT, +PRIMARY KEY (c01) +) ENGINE=INNODB STATS_AUTO_RECALC=0; +INSERT INTO t1 VALUES +(1,2),(2,4),(3,6),(4,8); +CREATE TABLE t2 ( +c01 INT, +c02 INT, +PRIMARY KEY (c01), +FOREIGN KEY fk1 (c02) REFERENCES t1 (c01) +) ENGINE=INNODB STATS_AUTO_RECALC=0; +INSERT INTO t2 VALUES +(1,1),(2,2),(3,3); +connect con_trx,localhost,root,,; +connect con_verify_innodb_trx,localhost,root,,; +connection con_trx; +SET autocommit=0; +INSERT INTO t1 VALUES (5,10); +SELECT * FROM t1 FOR UPDATE; +c01 c02 +1 2 +2 4 +3 6 +4 8 +5 10 +connection con_verify_innodb_trx; +SELECT trx_state, trx_weight, trx_tables_in_use, trx_tables_locked, +trx_rows_locked, trx_rows_modified, trx_concurrency_tickets, +trx_isolation_level, trx_unique_checks, trx_foreign_key_checks +FROM INFORMATION_SCHEMA.INNODB_TRX; +trx_state trx_weight trx_tables_in_use trx_tables_locked trx_rows_locked trx_rows_modified trx_concurrency_tickets trx_isolation_level trx_unique_checks trx_foreign_key_checks +RUNNING 3 0 1 6 1 0 REPEATABLE READ 1 1 +connection con_trx; +ROLLBACK; +SET FOREIGN_KEY_CHECKS = 0; +SET UNIQUE_CHECKS = 0; +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +BEGIN; +INSERT INTO t1 VALUES (6,12); +connection con_verify_innodb_trx; +SELECT trx_isolation_level, trx_unique_checks, trx_foreign_key_checks +FROM INFORMATION_SCHEMA.INNODB_TRX; +trx_isolation_level trx_unique_checks trx_foreign_key_checks +SERIALIZABLE 0 0 +connection con_trx; +ROLLBACK; +SET FOREIGN_KEY_CHECKS = 1; +SET UNIQUE_CHECKS = 1; +BEGIN; +INSERT INTO t2 VALUES (4,10); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk1` FOREIGN KEY (`c02`) REFERENCES `t1` (`c01`)) +disconnect con_trx; +connection con_verify_innodb_trx; +SELECT trx_state, trx_isolation_level, trx_last_foreign_key_error +FROM INFORMATION_SCHEMA.INNODB_TRX; +trx_state trx_isolation_level trx_last_foreign_key_error +RUNNING REPEATABLE READ `test`.`t2`, CONSTRAINT `fk1` FOREIGN KEY (`c02`) REFERENCES `t1` (`c01`) +disconnect con_verify_innodb_trx; +connection default; +DROP TABLE t2; +DROP TABLE t1; +SET GLOBAL innodb_lock_wait_timeout=@save_timeout; diff --git a/mysql-test/suite/innodb/r/innodb_information_schema_tables.result b/mysql-test/suite/innodb/r/innodb_information_schema_tables.result index ea713ea6f6a..87ff94a9ab1 100644 --- a/mysql-test/suite/innodb/r/innodb_information_schema_tables.result +++ b/mysql-test/suite/innodb/r/innodb_information_schema_tables.result @@ -1,2 +1,3 @@ +FOUND 1 /\[Warning\] InnoDB: innodb_open_files 1000000 should not be greater than the open_files_limit [0-9]+/ in mysqld.1.err CREATE TABLE t1 ENGINE=InnoDB AS SELECT * FROM mysql.help_topic; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb_stats_auto_recalc.result b/mysql-test/suite/innodb/r/innodb_stats_auto_recalc.result new file mode 100644 index 00000000000..40eae0a9385 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_stats_auto_recalc.result @@ -0,0 +1,44 @@ +CREATE TABLE autorecalc (a INT, PRIMARY KEY (a)) ENGINE=INNODB; +SELECT n_rows, clustered_index_size FROM mysql.innodb_table_stats WHERE table_name = 'autorecalc'; +n_rows 0 +clustered_index_size 1 +SELECT index_name, stat_name, stat_value FROM mysql.innodb_index_stats WHERE table_name = 'autorecalc'; +index_name PRIMARY +stat_name n_diff_pfx01 +stat_value 0 +index_name PRIMARY +stat_name n_leaf_pages +stat_value 1 +index_name PRIMARY +stat_name size +stat_value 1 +INSERT INTO autorecalc VALUES (1); +INSERT INTO autorecalc VALUES (2); +SELECT n_rows, clustered_index_size FROM mysql.innodb_table_stats WHERE table_name = 'autorecalc'; +n_rows 2 +clustered_index_size 1 +SELECT index_name, stat_name, stat_value FROM mysql.innodb_index_stats WHERE table_name = 'autorecalc'; +index_name PRIMARY +stat_name n_diff_pfx01 +stat_value 2 +index_name PRIMARY +stat_name n_leaf_pages +stat_value 1 +index_name PRIMARY +stat_name size +stat_value 1 +DELETE FROM autorecalc; +SELECT n_rows, clustered_index_size FROM mysql.innodb_table_stats WHERE table_name = 'autorecalc'; +n_rows 0 +clustered_index_size 1 +SELECT index_name, stat_name, stat_value FROM mysql.innodb_index_stats WHERE table_name = 'autorecalc'; +index_name PRIMARY +stat_name n_diff_pfx01 +stat_value 0 +index_name PRIMARY +stat_name n_leaf_pages +stat_value 1 +index_name PRIMARY +stat_name size +stat_value 1 +DROP TABLE autorecalc; diff --git a/mysql-test/suite/innodb/r/innodb_stats_auto_recalc_ddl.result b/mysql-test/suite/innodb/r/innodb_stats_auto_recalc_ddl.result new file mode 100644 index 00000000000..8c68fe74504 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_stats_auto_recalc_ddl.result @@ -0,0 +1,34 @@ +CREATE TABLE arddl (a INT, b INT, PRIMARY KEY (a)) ENGINE=INNODB; +INSERT INTO arddl VALUES (1, 10); +INSERT INTO arddl VALUES (2, 10); +ALTER TABLE arddl ADD INDEX (b); +SELECT n_rows FROM mysql.innodb_table_stats WHERE table_name = 'arddl' ORDER BY 1; +n_rows 2 +SELECT index_name, stat_name, stat_value FROM mysql.innodb_index_stats WHERE table_name = 'arddl' AND index_name = 'PRIMARY' ORDER BY 1, 2, 3; +index_name PRIMARY +stat_name n_diff_pfx01 +stat_value 2 +index_name PRIMARY +stat_name n_leaf_pages +stat_value 1 +index_name PRIMARY +stat_name size +stat_value 1 +DROP TABLE arddl; +CREATE TABLE arddl (a INT, b INT, PRIMARY KEY (a), KEY (b)) ENGINE=INNODB; +INSERT INTO arddl VALUES (3, 10); +INSERT INTO arddl VALUES (4, 10); +ALTER TABLE arddl DROP INDEX b; +SELECT n_rows FROM mysql.innodb_table_stats WHERE table_name = 'arddl' ORDER BY 1; +n_rows 2 +SELECT index_name, stat_name, stat_value FROM mysql.innodb_index_stats WHERE table_name = 'arddl' AND index_name = 'PRIMARY' ORDER BY 1, 2, 3; +index_name PRIMARY +stat_name n_diff_pfx01 +stat_value 2 +index_name PRIMARY +stat_name n_leaf_pages +stat_value 1 +index_name PRIMARY +stat_name size +stat_value 1 +DROP TABLE arddl; diff --git a/mysql-test/suite/innodb/r/innodb_stats_auto_recalc_lots.result b/mysql-test/suite/innodb/r/innodb_stats_auto_recalc_lots.result new file mode 100644 index 00000000000..746bce5687e --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_stats_auto_recalc_lots.result @@ -0,0 +1,202 @@ +SELECT table_name, n_rows FROM mysql.innodb_table_stats WHERE table_name LIKE 'ar_%' ORDER BY table_name; +table_name n_rows +ar_1001 0 +ar_1002 0 +ar_1003 0 +ar_1004 0 +ar_1005 0 +ar_1006 0 +ar_1007 0 +ar_1008 0 +ar_1009 0 +ar_1010 0 +ar_1011 0 +ar_1012 0 +ar_1013 0 +ar_1014 0 +ar_1015 0 +ar_1016 0 +ar_1017 0 +ar_1018 0 +ar_1019 0 +ar_1020 0 +ar_1021 0 +ar_1022 0 +ar_1023 0 +ar_1024 0 +ar_1025 0 +ar_1026 0 +ar_1027 0 +ar_1028 0 +ar_1029 0 +ar_1030 0 +ar_1031 0 +ar_1032 0 +ar_1033 0 +ar_1034 0 +ar_1035 0 +ar_1036 0 +ar_1037 0 +ar_1038 0 +ar_1039 0 +ar_1040 0 +ar_1041 0 +ar_1042 0 +ar_1043 0 +ar_1044 0 +ar_1045 0 +ar_1046 0 +ar_1047 0 +ar_1048 0 +ar_1049 0 +ar_1050 0 +ar_1051 0 +ar_1052 0 +ar_1053 0 +ar_1054 0 +ar_1055 0 +ar_1056 0 +ar_1057 0 +ar_1058 0 +ar_1059 0 +ar_1060 0 +ar_1061 0 +ar_1062 0 +ar_1063 0 +ar_1064 0 +ar_1065 0 +ar_1066 0 +ar_1067 0 +ar_1068 0 +ar_1069 0 +ar_1070 0 +ar_1071 0 +ar_1072 0 +ar_1073 0 +ar_1074 0 +ar_1075 0 +ar_1076 0 +ar_1077 0 +ar_1078 0 +ar_1079 0 +ar_1080 0 +ar_1081 0 +ar_1082 0 +ar_1083 0 +ar_1084 0 +ar_1085 0 +ar_1086 0 +ar_1087 0 +ar_1088 0 +ar_1089 0 +ar_1090 0 +ar_1091 0 +ar_1092 0 +ar_1093 0 +ar_1094 0 +ar_1095 0 +ar_1096 0 +ar_1097 0 +ar_1098 0 +ar_1099 0 +ar_1100 0 +ar_1101 0 +ar_1102 0 +ar_1103 0 +ar_1104 0 +ar_1105 0 +ar_1106 0 +ar_1107 0 +ar_1108 0 +ar_1109 0 +ar_1110 0 +ar_1111 0 +ar_1112 0 +ar_1113 0 +ar_1114 0 +ar_1115 0 +ar_1116 0 +ar_1117 0 +ar_1118 0 +ar_1119 0 +ar_1120 0 +ar_1121 0 +ar_1122 0 +ar_1123 0 +ar_1124 0 +ar_1125 0 +ar_1126 0 +ar_1127 0 +ar_1128 0 +ar_1129 0 +ar_1130 0 +ar_1131 0 +ar_1132 0 +ar_1133 0 +ar_1134 0 +ar_1135 0 +ar_1136 0 +ar_1137 0 +ar_1138 0 +ar_1139 0 +ar_1140 0 +ar_1141 0 +ar_1142 0 +ar_1143 0 +ar_1144 0 +ar_1145 0 +ar_1146 0 +ar_1147 0 +ar_1148 0 +ar_1149 0 +ar_1150 0 +ar_1151 0 +ar_1152 0 +ar_1153 0 +ar_1154 0 +ar_1155 0 +ar_1156 0 +ar_1157 0 +ar_1158 0 +ar_1159 0 +ar_1160 0 +ar_1161 0 +ar_1162 0 +ar_1163 0 +ar_1164 0 +ar_1165 0 +ar_1166 0 +ar_1167 0 +ar_1168 0 +ar_1169 0 +ar_1170 0 +ar_1171 0 +ar_1172 0 +ar_1173 0 +ar_1174 0 +ar_1175 0 +ar_1176 0 +ar_1177 0 +ar_1178 0 +ar_1179 0 +ar_1180 0 +ar_1181 0 +ar_1182 0 +ar_1183 0 +ar_1184 0 +ar_1185 0 +ar_1186 0 +ar_1187 0 +ar_1188 0 +ar_1189 0 +ar_1190 0 +ar_1191 0 +ar_1192 0 +ar_1193 0 +ar_1194 0 +ar_1195 0 +ar_1196 0 +ar_1197 0 +ar_1198 0 +ar_1199 0 +ar_1200 0 diff --git a/mysql-test/suite/innodb/r/innodb_stats_auto_recalc_on_nonexistent.result b/mysql-test/suite/innodb/r/innodb_stats_auto_recalc_on_nonexistent.result new file mode 100644 index 00000000000..25a97935223 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_stats_auto_recalc_on_nonexistent.result @@ -0,0 +1,57 @@ +Test with default setting +CREATE TABLE t (a INT, PRIMARY KEY (a)) ENGINE=INNODB; +SELECT COUNT(*) FROM mysql.innodb_table_stats WHERE table_name = 't'; +COUNT(*) 1 +SELECT COUNT(*) FROM mysql.innodb_index_stats WHERE table_name = 't'; +COUNT(*) 3 +FLUSH TABLE t; +DELETE FROM mysql.innodb_index_stats WHERE table_name = 't'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 't'; +SELECT COUNT(*) FROM mysql.innodb_table_stats WHERE table_name = 't'; +COUNT(*) 0 +SELECT COUNT(*) FROM mysql.innodb_index_stats WHERE table_name = 't'; +COUNT(*) 0 +SELECT * FROM t; +SELECT COUNT(*) FROM mysql.innodb_table_stats WHERE table_name = 't'; +COUNT(*) 1 +SELECT COUNT(*) FROM mysql.innodb_index_stats WHERE table_name = 't'; +COUNT(*) 3 +DROP TABLE t; +Test with explicit enable +CREATE TABLE t (a INT, PRIMARY KEY (a)) ENGINE=INNODB STATS_AUTO_RECALC=1; +SELECT COUNT(*) FROM mysql.innodb_table_stats WHERE table_name = 't'; +COUNT(*) 1 +SELECT COUNT(*) FROM mysql.innodb_index_stats WHERE table_name = 't'; +COUNT(*) 3 +FLUSH TABLE t; +DELETE FROM mysql.innodb_index_stats WHERE table_name = 't'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 't'; +SELECT COUNT(*) FROM mysql.innodb_table_stats WHERE table_name = 't'; +COUNT(*) 0 +SELECT COUNT(*) FROM mysql.innodb_index_stats WHERE table_name = 't'; +COUNT(*) 0 +SELECT * FROM t; +SELECT COUNT(*) FROM mysql.innodb_table_stats WHERE table_name = 't'; +COUNT(*) 1 +SELECT COUNT(*) FROM mysql.innodb_index_stats WHERE table_name = 't'; +COUNT(*) 3 +DROP TABLE t; +Test with explicit disable +CREATE TABLE t (a INT, PRIMARY KEY (a)) ENGINE=INNODB STATS_AUTO_RECALC=0; +SELECT COUNT(*) FROM mysql.innodb_table_stats WHERE table_name = 't'; +COUNT(*) 1 +SELECT COUNT(*) FROM mysql.innodb_index_stats WHERE table_name = 't'; +COUNT(*) 3 +FLUSH TABLE t; +DELETE FROM mysql.innodb_index_stats WHERE table_name = 't'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 't'; +SELECT COUNT(*) FROM mysql.innodb_table_stats WHERE table_name = 't'; +COUNT(*) 0 +SELECT COUNT(*) FROM mysql.innodb_index_stats WHERE table_name = 't'; +COUNT(*) 0 +SELECT * FROM t; +SELECT COUNT(*) FROM mysql.innodb_table_stats WHERE table_name = 't'; +COUNT(*) 0 +SELECT COUNT(*) FROM mysql.innodb_index_stats WHERE table_name = 't'; +COUNT(*) 0 +DROP TABLE t; diff --git a/mysql-test/suite/innodb/r/innodb_stats_external_pages.result b/mysql-test/suite/innodb/r/innodb_stats_external_pages.result new file mode 100644 index 00000000000..52e1e153059 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_stats_external_pages.result @@ -0,0 +1,10 @@ +CREATE TABLE bug18384390 ( +id INT AUTO_INCREMENT PRIMARY KEY, +txt VARCHAR(10000) +) ENGINE=INNODB STATS_PERSISTENT=1 STATS_AUTO_RECALC=0; +INSERT INTO bug18384390 (txt) SELECT REPEAT('0', 10000) FROM seq_1_to_1024; +set use_stat_tables=never; +ANALYZE TABLE bug18384390; +Table Op Msg_type Msg_text +test.bug18384390 analyze status OK +DROP TABLE bug18384390; diff --git a/mysql-test/suite/innodb/r/innodb_stats_flag_global,off.rdiff b/mysql-test/suite/innodb/r/innodb_stats_flag_global,off.rdiff new file mode 100644 index 00000000000..f5b235438aa --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_stats_flag_global,off.rdiff @@ -0,0 +1,34 @@ +@@ -18,7 +18,7 @@ + test.test_ps_flag analyze status OK + SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; + cnt_after +-1 ++0 + DROP TABLE test_ps_flag; + CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB STATS_PERSISTENT=default; + SHOW CREATE TABLE test_ps_flag; +@@ -37,7 +37,7 @@ + test.test_ps_flag analyze status OK + SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; + cnt_after +-1 ++0 + DROP TABLE test_ps_flag; + ===== + === Test ANALYZE behavior after creation with explicit PS=OFF +@@ -142,7 +142,7 @@ + test.test_ps_flag analyze status OK + SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; + cnt_after +-1 ++0 + DROP TABLE test_ps_flag; + ===== + === Test ANALYZE behavior after creation with explicit PS=ON, +@@ -203,5 +203,5 @@ + test.test_ps_flag analyze status OK + SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; + cnt_after +-1 ++0 + DROP TABLE test_ps_flag; diff --git a/mysql-test/suite/innodb/r/innodb_stats_flag_global.result b/mysql-test/suite/innodb/r/innodb_stats_flag_global.result new file mode 100644 index 00000000000..8bafb725d89 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_stats_flag_global.result @@ -0,0 +1,207 @@ +===== +=== Test ANALYZE behavior after default creation +===== +CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB; +SHOW CREATE TABLE test_ps_flag; +Table Create Table +test_ps_flag CREATE TABLE `test_ps_flag` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DELETE FROM mysql.innodb_index_stats WHERE table_name = 'test_ps_flag'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +SELECT COUNT(*) AS cnt_before FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_before +0 +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE test_ps_flag; +Table Op Msg_type Msg_text +test.test_ps_flag analyze status OK +SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_after +1 +DROP TABLE test_ps_flag; +CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB STATS_PERSISTENT=default; +SHOW CREATE TABLE test_ps_flag; +Table Create Table +test_ps_flag CREATE TABLE `test_ps_flag` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DELETE FROM mysql.innodb_index_stats WHERE table_name = 'test_ps_flag'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +SELECT COUNT(*) AS cnt_before FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_before +0 +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE test_ps_flag; +Table Op Msg_type Msg_text +test.test_ps_flag analyze status OK +SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_after +1 +DROP TABLE test_ps_flag; +===== +=== Test ANALYZE behavior after creation with explicit PS=OFF +===== +CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB STATS_PERSISTENT=0; +SHOW CREATE TABLE test_ps_flag; +Table Create Table +test_ps_flag CREATE TABLE `test_ps_flag` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_PERSISTENT=0 +DELETE FROM mysql.innodb_index_stats WHERE table_name = 'test_ps_flag'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +SELECT COUNT(*) AS cnt_before FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_before +0 +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE test_ps_flag; +Table Op Msg_type Msg_text +test.test_ps_flag analyze status OK +SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_after +0 +DROP TABLE test_ps_flag; +===== +=== Test ANALYZE behavior after creation with explicit PS=ON +===== +CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB STATS_PERSISTENT=1; +SHOW CREATE TABLE test_ps_flag; +Table Create Table +test_ps_flag CREATE TABLE `test_ps_flag` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_PERSISTENT=1 +DELETE FROM mysql.innodb_index_stats WHERE table_name = 'test_ps_flag'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +SELECT COUNT(*) AS cnt_before FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_before +0 +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE test_ps_flag; +Table Op Msg_type Msg_text +test.test_ps_flag analyze status OK +SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_after +1 +DROP TABLE test_ps_flag; +===== +=== Test ANALYZE behavior after creation with explicit PS=OFF, +=== then ALTER to ON, then ALTER to OFF, then ALTER to default +===== +CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB STATS_PERSISTENT=0; +ALTER TABLE test_ps_flag STATS_PERSISTENT=1; +# restart +SHOW CREATE TABLE test_ps_flag; +Table Create Table +test_ps_flag CREATE TABLE `test_ps_flag` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_PERSISTENT=1 +DELETE FROM mysql.innodb_index_stats WHERE table_name = 'test_ps_flag'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +SELECT COUNT(*) AS cnt_before FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_before +0 +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE test_ps_flag; +Table Op Msg_type Msg_text +test.test_ps_flag analyze status OK +SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_after +1 +ALTER TABLE test_ps_flag STATS_PERSISTENT=0; +SHOW CREATE TABLE test_ps_flag; +Table Create Table +test_ps_flag CREATE TABLE `test_ps_flag` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_PERSISTENT=0 +DELETE FROM mysql.innodb_index_stats WHERE table_name = 'test_ps_flag'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +SELECT COUNT(*) AS cnt_before FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_before +0 +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE test_ps_flag; +Table Op Msg_type Msg_text +test.test_ps_flag analyze status OK +SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_after +0 +ALTER TABLE test_ps_flag STATS_PERSISTENT=default; +SHOW CREATE TABLE test_ps_flag; +Table Create Table +test_ps_flag CREATE TABLE `test_ps_flag` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DELETE FROM mysql.innodb_index_stats WHERE table_name = 'test_ps_flag'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +SELECT COUNT(*) AS cnt_before FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_before +0 +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE test_ps_flag; +Table Op Msg_type Msg_text +test.test_ps_flag analyze status OK +SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_after +1 +DROP TABLE test_ps_flag; +===== +=== Test ANALYZE behavior after creation with explicit PS=ON, +=== then ALTER to OFF, then ALTER to ON, then ALTER to default +===== +CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB STATS_PERSISTENT=1; +ALTER TABLE test_ps_flag STATS_PERSISTENT=0; +# restart +SHOW CREATE TABLE test_ps_flag; +Table Create Table +test_ps_flag CREATE TABLE `test_ps_flag` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_PERSISTENT=0 +DELETE FROM mysql.innodb_index_stats WHERE table_name = 'test_ps_flag'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +SELECT COUNT(*) AS cnt_before FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_before +0 +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE test_ps_flag; +Table Op Msg_type Msg_text +test.test_ps_flag analyze status OK +SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_after +0 +ALTER TABLE test_ps_flag STATS_PERSISTENT=1; +SHOW CREATE TABLE test_ps_flag; +Table Create Table +test_ps_flag CREATE TABLE `test_ps_flag` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_PERSISTENT=1 +DELETE FROM mysql.innodb_index_stats WHERE table_name = 'test_ps_flag'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +SELECT COUNT(*) AS cnt_before FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_before +0 +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE test_ps_flag; +Table Op Msg_type Msg_text +test.test_ps_flag analyze status OK +SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_after +1 +ALTER TABLE test_ps_flag STATS_PERSISTENT=default; +SHOW CREATE TABLE test_ps_flag; +Table Create Table +test_ps_flag CREATE TABLE `test_ps_flag` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DELETE FROM mysql.innodb_index_stats WHERE table_name = 'test_ps_flag'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +SELECT COUNT(*) AS cnt_before FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_before +0 +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE test_ps_flag; +Table Op Msg_type Msg_text +test.test_ps_flag analyze status OK +SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; +cnt_after +1 +DROP TABLE test_ps_flag; diff --git a/mysql-test/suite/innodb/r/innodb_stats_persistent.result b/mysql-test/suite/innodb/r/innodb_stats_persistent.result index e25ab2a8a24..7778f8da84d 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_persistent.result +++ b/mysql-test/suite/innodb/r/innodb_stats_persistent.result @@ -10,9 +10,9 @@ CREATE TABLE t1 (id SERIAL, val INT UNSIGNED NOT NULL, KEY(val)) ENGINE=INNODB STATS_PERSISTENT=1,STATS_AUTO_RECALC=1; CREATE TABLE t2 LIKE t1; INSERT INTO t1 (val) SELECT 4 FROM seq_1_to_16; +SET STATEMENT use_stat_tables=never FOR ANALYZE TABLE t1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK connect con1, localhost, root,,; START TRANSACTION; @@ -91,7 +91,7 @@ COUNT(*) # ha_innobase::records_in_range() would count the delete-marked records. EXPLAIN SELECT * FROM t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL val 4 NULL 16 Using index +1 SIMPLE t1 index NULL val 4 NULL 1 Using index ROLLBACK; EXPLAIN SELECT * FROM t1; id select_type table type possible_keys key key_len ref rows Extra @@ -106,3 +106,25 @@ 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; +CREATE TABLE bug12429573 (i INTEGER PRIMARY KEY, j INTEGER, KEY(j)) +ENGINE=INNODB STATS_PERSISTENT=1; +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE bug12429573; +Table Op Msg_type Msg_text +test.bug12429573 analyze status OK +SELECT last_update INTO @last FROM mysql.innodb_table_stats +WHERE table_name = 'bug12429573'; +SELECT * FROM mysql.innodb_index_stats +WHERE table_name = 'bug12429573' AND last_update!=@last; +database_name table_name index_name last_update stat_name stat_value sample_size stat_description +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE bug12429573; +Table Op Msg_type Msg_text +test.bug12429573 analyze status OK +SELECT * FROM mysql.innodb_table_stats +WHERE table_name = 'bug12429573' AND last_update=@last; +database_name table_name last_update n_rows clustered_index_size sum_of_other_index_sizes +SELECT * FROM mysql.innodb_index_stats +WHERE table_name = 'bug12429573' AND last_update=@last; +database_name table_name index_name last_update stat_name stat_value sample_size stat_description +DROP TABLE bug12429573; diff --git a/mysql-test/suite/innodb/r/innodb_stats_sample_pages.result b/mysql-test/suite/innodb/r/innodb_stats_sample_pages.result new file mode 100644 index 00000000000..a24d9aa8b62 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_stats_sample_pages.result @@ -0,0 +1,29 @@ +SET GLOBAL innodb_stats_persistent_sample_pages=17; +CREATE TABLE test_ps_sample_pages_used ( +a VARCHAR(512), PRIMARY KEY (a) +) ENGINE=INNODB STATS_SAMPLE_PAGES=default; +BEGIN; +COMMIT; +ANALYZE TABLE test_ps_sample_pages_used; +Table Op Msg_type Msg_text +test.test_ps_sample_pages_used analyze status Engine-independent statistics collected +test.test_ps_sample_pages_used analyze status OK +SELECT stat_name, stat_value FROM mysql.innodb_index_stats +WHERE table_name='test_ps_sample_pages_used' AND stat_name='n_leaf_pages'; +stat_name stat_value +n_leaf_pages 37 +SELECT sample_size FROM mysql.innodb_index_stats +WHERE table_name='test_ps_sample_pages_used' AND stat_name='n_diff_pfx01'; +sample_size +17 +ALTER TABLE test_ps_sample_pages_used STATS_SAMPLE_PAGES=14; +ANALYZE TABLE test_ps_sample_pages_used; +Table Op Msg_type Msg_text +test.test_ps_sample_pages_used analyze status Engine-independent statistics collected +test.test_ps_sample_pages_used analyze status OK +SELECT sample_size FROM mysql.innodb_index_stats +WHERE table_name='test_ps_sample_pages_used' AND stat_name='n_diff_pfx01'; +sample_size +14 +DROP TABLE test_ps_sample_pages_used; +SET GLOBAL innodb_stats_persistent_sample_pages=default; diff --git a/mysql-test/suite/innodb/r/innodb_stats_table_flag_auto_recalc.result b/mysql-test/suite/innodb/r/innodb_stats_table_flag_auto_recalc.result new file mode 100644 index 00000000000..5585d3f654e --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_stats_table_flag_auto_recalc.result @@ -0,0 +1,82 @@ +CREATE TABLE test_ps_auto_recalc (a INT, PRIMARY KEY (a)) ENGINE=INNODB; +SHOW CREATE TABLE test_ps_auto_recalc; +Table test_ps_auto_recalc +Create Table CREATE TABLE `test_ps_auto_recalc` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; +create_options +ALTER TABLE test_ps_auto_recalc STATS_AUTO_RECALC=1; +# restart +SHOW CREATE TABLE test_ps_auto_recalc; +Table test_ps_auto_recalc +Create Table CREATE TABLE `test_ps_auto_recalc` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_AUTO_RECALC=1 +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; +create_options stats_auto_recalc=1 +DROP TABLE test_ps_auto_recalc; +CREATE TABLE test_ps_auto_recalc (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_AUTO_RECALC=default; +SHOW CREATE TABLE test_ps_auto_recalc; +Table test_ps_auto_recalc +Create Table CREATE TABLE `test_ps_auto_recalc` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; +create_options +DROP TABLE test_ps_auto_recalc; +CREATE TABLE test_ps_auto_recalc (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_AUTO_RECALC=0; +# restart +SHOW CREATE TABLE test_ps_auto_recalc; +Table test_ps_auto_recalc +Create Table CREATE TABLE `test_ps_auto_recalc` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_AUTO_RECALC=0 +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; +create_options stats_auto_recalc=0 +ALTER TABLE test_ps_auto_recalc STATS_AUTO_RECALC=1; +# restart +SHOW CREATE TABLE test_ps_auto_recalc; +Table test_ps_auto_recalc +Create Table CREATE TABLE `test_ps_auto_recalc` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_AUTO_RECALC=1 +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; +create_options stats_auto_recalc=1 +DROP TABLE test_ps_auto_recalc; +CREATE TABLE test_ps_auto_recalc (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_AUTO_RECALC=1; +# restart +SHOW CREATE TABLE test_ps_auto_recalc; +Table test_ps_auto_recalc +Create Table CREATE TABLE `test_ps_auto_recalc` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_AUTO_RECALC=1 +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; +create_options stats_auto_recalc=1 +ALTER TABLE test_ps_auto_recalc STATS_AUTO_RECALC=0; +# restart +SHOW CREATE TABLE test_ps_auto_recalc; +Table test_ps_auto_recalc +Create Table CREATE TABLE `test_ps_auto_recalc` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_AUTO_RECALC=0 +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; +create_options stats_auto_recalc=0 +DROP TABLE test_ps_auto_recalc; diff --git a/mysql-test/suite/innodb/r/innodb_stats_table_flag_sample_pages.result b/mysql-test/suite/innodb/r/innodb_stats_table_flag_sample_pages.result new file mode 100644 index 00000000000..b26b0150c8d --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_stats_table_flag_sample_pages.result @@ -0,0 +1,95 @@ +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB; +SHOW CREATE TABLE test_ps_sample_pages; +Table test_ps_sample_pages +Create Table CREATE TABLE `test_ps_sample_pages` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_sample_pages'; +create_options +ALTER TABLE test_ps_sample_pages STATS_SAMPLE_PAGES=12345; +# restart +SHOW CREATE TABLE test_ps_sample_pages; +Table test_ps_sample_pages +Create Table CREATE TABLE `test_ps_sample_pages` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_SAMPLE_PAGES=12345 +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_sample_pages'; +create_options stats_sample_pages=12345 +DROP TABLE test_ps_sample_pages; +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=default; +SHOW CREATE TABLE test_ps_sample_pages; +Table test_ps_sample_pages +Create Table CREATE TABLE `test_ps_sample_pages` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_sample_pages'; +create_options +DROP TABLE test_ps_sample_pages; +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=-5; +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 '-5' at line 2 +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=0; +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 '0' at line 2 +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=67000; +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 '67000' at line 2 +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=670000; +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 '670000' at line 2 +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=65536; +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 '65536' at line 2 +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=65535; +SHOW CREATE TABLE test_ps_sample_pages; +Table test_ps_sample_pages +Create Table CREATE TABLE `test_ps_sample_pages` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_SAMPLE_PAGES=65535 +DROP TABLE test_ps_sample_pages; +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=1; +# restart +SHOW CREATE TABLE test_ps_sample_pages; +Table test_ps_sample_pages +Create Table CREATE TABLE `test_ps_sample_pages` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_SAMPLE_PAGES=1 +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_sample_pages'; +create_options stats_sample_pages=1 +DROP TABLE test_ps_sample_pages; +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=5678; +# restart +SHOW CREATE TABLE test_ps_sample_pages; +Table test_ps_sample_pages +Create Table CREATE TABLE `test_ps_sample_pages` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_SAMPLE_PAGES=5678 +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_sample_pages'; +create_options stats_sample_pages=5678 +ALTER TABLE test_ps_sample_pages STATS_SAMPLE_PAGES=default; +# restart +SHOW CREATE TABLE test_ps_sample_pages; +Table test_ps_sample_pages +Create Table CREATE TABLE `test_ps_sample_pages` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_sample_pages'; +create_options +DROP TABLE test_ps_sample_pages; diff --git a/mysql-test/suite/innodb/r/innodb_ut_format_name.result b/mysql-test/suite/innodb/r/innodb_ut_format_name.result new file mode 100644 index 00000000000..41a5b0f7149 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_ut_format_name.result @@ -0,0 +1,5 @@ +CREATE TABLE t (c INT) ENGINE=INNODB; +SET @save_dbug = @@debug_dbug; +SET debug_dbug = '+d,test_ut_format_name'; +DROP TABLE t; +SET debug_dbug = @save_dbug; diff --git a/mysql-test/suite/innodb/r/records_in_range,4k.rdiff b/mysql-test/suite/innodb/r/records_in_range,4k.rdiff new file mode 100644 index 00000000000..12b857ece22 --- /dev/null +++ b/mysql-test/suite/innodb/r/records_in_range,4k.rdiff @@ -0,0 +1,8 @@ +@@ -39,7 +39,7 @@ + WHERE + table_name='records_in_range_test' AND stat_name = 'size'; + index_name stat_name stat_value +-PRIMARY size 1 ++PRIMARY size 5 + SET @save_dbug = @@debug_dbug; + SET DEBUG_DBUG='+d,print_btr_estimate_n_rows_in_range_return_value'; diff --git a/mysql-test/suite/innodb/r/records_in_range,8k.rdiff b/mysql-test/suite/innodb/r/records_in_range,8k.rdiff new file mode 100644 index 00000000000..bd24af160ba --- /dev/null +++ b/mysql-test/suite/innodb/r/records_in_range,8k.rdiff @@ -0,0 +1,8 @@ +@@ -39,7 +39,7 @@ + WHERE + table_name='records_in_range_test' AND stat_name = 'size'; + index_name stat_name stat_value +-PRIMARY size 1 ++PRIMARY size 3 + SET @save_dbug = @@debug_dbug; + SET DEBUG_DBUG='+d,print_btr_estimate_n_rows_in_range_return_value'; diff --git a/mysql-test/suite/innodb/r/records_in_range.result b/mysql-test/suite/innodb/r/records_in_range.result new file mode 100644 index 00000000000..e5a698f59cc --- /dev/null +++ b/mysql-test/suite/innodb/r/records_in_range.result @@ -0,0 +1,1275 @@ +CREATE TABLE records_in_range_test ( +c1 VARCHAR(16), +c2 VARCHAR(512), +PRIMARY KEY (c1) +) ENGINE=INNODB STATS_PERSISTENT=1; +INSERT INTO records_in_range_test VALUES +('ccc', REPEAT('v', 512)), +('kkk01', REPEAT('v', 512)), +('kkk02', REPEAT('v', 512)), +('kkk03', REPEAT('v', 512)), +('kkk04', REPEAT('v', 512)), +('kkk05', REPEAT('v', 512)), +('kkk06', REPEAT('v', 512)), +('kkk07', REPEAT('v', 512)), +('kkk08', REPEAT('v', 512)), +('mmm', REPEAT('v', 512)), +('nnn', REPEAT('v', 512)), +('uuu01', REPEAT('v', 512)), +('uuu02', REPEAT('v', 512)), +('uuu03', REPEAT('v', 512)), +('uuu04', REPEAT('v', 512)), +('uuu05', REPEAT('v', 512)), +('uuu06', REPEAT('v', 512)), +('uuu07', REPEAT('v', 512)), +('uuu08', REPEAT('v', 512)), +('xxx', REPEAT('v', 512)); +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE records_in_range_test; +Table Op Msg_type Msg_text +test.records_in_range_test analyze status OK +SELECT index_name, stat_name, stat_value +FROM mysql.innodb_index_stats +WHERE +table_name='records_in_range_test' AND stat_name = 'n_leaf_pages'; +index_name stat_name stat_value +PRIMARY n_leaf_pages 1 +SELECT index_name, stat_name, stat_value +FROM mysql.innodb_index_stats +WHERE +table_name='records_in_range_test' AND stat_name = 'size'; +index_name stat_name stat_value +PRIMARY size 1 +SET @save_dbug = @@debug_dbug; +SET DEBUG_DBUG='+d,print_btr_estimate_n_rows_in_range_return_value'; + +In all SELECTs below the number of the records in the range returned +by COUNT(*) must be the same as the number returned by +btr_estimate_n_rows_in_range() which can be seen inside the artificial +warning + +Test left-unbounded, right-open intervals + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'aaa'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'ccc'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'eee'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'mmm'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'nnn'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'qqq'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'xxx'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'zzz'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 + +Test left-unbounded, right-closed intervals + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'aaa'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'ccc'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'eee'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'mmm'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'nnn'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'qqq'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'xxx'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'zzz'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 + +Test left-open, right-unbounded intervals + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 + +Test left-closed, right-unbounded intervals + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 + +Test left-open, right-open intervals +In some cases here the optimizer is smart enough not to call +ha_innobase::records_in_range() at all, so we get no warning containing +the value returned from btr_estimate_n_rows_in_range() + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'bbb'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'ccc'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'eee'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'mmm'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'nnn'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'qqq'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'xxx'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'zzz'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'eee'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'mmm'; +COUNT(*) +8 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 8 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'nnn'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'qqq'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'xxx'; +COUNT(*) +18 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 18 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'zzz'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'mmm'; +COUNT(*) +8 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 8 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'nnn'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'qqq'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'xxx'; +COUNT(*) +18 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 18 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'zzz'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'nnn'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'qqq'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'xxx'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'zzz'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'qqq'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'xxx'; +COUNT(*) +8 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 8 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'zzz'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'qqq'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'xxx'; +COUNT(*) +8 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 8 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'zzz'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'qqq'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'xxx'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'zzz'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'qqq'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'xxx'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'zzz'; +COUNT(*) +0 + +Test left-closed, right-open intervals +In some cases here the optimizer is smart enough not to call +ha_innobase::records_in_range() at all, so we get no warning containing +the value returned from btr_estimate_n_rows_in_range() + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'bbb'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'ccc'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'eee'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'mmm'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'nnn'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'qqq'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'xxx'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'zzz'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'eee'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'mmm'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'nnn'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'qqq'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'xxx'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'zzz'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'mmm'; +COUNT(*) +8 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 8 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'nnn'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'qqq'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'xxx'; +COUNT(*) +18 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 18 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'zzz'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'nnn'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'qqq'; +COUNT(*) +2 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 2 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'xxx'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'zzz'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'qqq'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'xxx'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'zzz'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'qqq'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'xxx'; +COUNT(*) +8 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 8 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'zzz'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'qqq'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'xxx'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'zzz'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'qqq'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'xxx'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'zzz'; +COUNT(*) +0 + +Test left-open, right-closed intervals +In some cases here the optimizer is smart enough not to call +ha_innobase::records_in_range() at all, so we get no warning containing +the value returned from btr_estimate_n_rows_in_range() + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'bbb'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'ccc'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'eee'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'mmm'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'nnn'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'qqq'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'xxx'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'zzz'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'eee'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'mmm'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'nnn'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'qqq'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'xxx'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'zzz'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'mmm'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'nnn'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'qqq'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'xxx'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'zzz'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'nnn'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'qqq'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'xxx'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'zzz'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'qqq'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'xxx'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'zzz'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'qqq'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'xxx'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'zzz'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'qqq'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'xxx'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'zzz'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'qqq'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'xxx'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'zzz'; +COUNT(*) +0 + +Test left-closed, right-closed intervals +In some cases here the optimizer is smart enough not to call +ha_innobase::records_in_range() at all, so we get no warning containing +the value returned from btr_estimate_n_rows_in_range() + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'bbb'; +COUNT(*) +0 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'ccc'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'eee'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'mmm'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'nnn'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'qqq'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'xxx'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'zzz'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'ccc'; +COUNT(*) +1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'eee'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'mmm'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'nnn'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'qqq'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'xxx'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'zzz'; +COUNT(*) +20 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 20 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'mmm'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'nnn'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'qqq'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'xxx'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'zzz'; +COUNT(*) +19 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 19 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'mmm'; +COUNT(*) +1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'nnn'; +COUNT(*) +2 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 2 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'qqq'; +COUNT(*) +2 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 2 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'xxx'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'zzz'; +COUNT(*) +11 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 11 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'nnn'; +COUNT(*) +1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'qqq'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'xxx'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'zzz'; +COUNT(*) +10 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 10 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'qqq'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'xxx'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'zzz'; +COUNT(*) +9 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 9 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'qqq'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'xxx'; +COUNT(*) +1 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'zzz'; +COUNT(*) +1 +Warnings: +Warning 1230 btr_estimate_n_rows_in_range(): 1 + +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'bbb'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'ccc'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'eee'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'mmm'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'nnn'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'qqq'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'xxx'; +COUNT(*) +0 +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'zzz'; +COUNT(*) +0 +SET DEBUG_DBUG = @save_dbug; +DROP TABLE records_in_range_test; diff --git a/mysql-test/suite/innodb/r/tablespace_per_table_not_windows.result b/mysql-test/suite/innodb/r/tablespace_per_table_not_windows.result new file mode 100644 index 00000000000..580269182ec --- /dev/null +++ b/mysql-test/suite/innodb/r/tablespace_per_table_not_windows.result @@ -0,0 +1,134 @@ +# +# Test the limits of a file-per-table tablespace name. MySQL combines +# the database name with the table name to make a unique table name. +# +SET default_storage_engine=InnoDB; +# +# MySQL limits each database and tablename identifier to 64 characters +# of up to 3 bytes per character, corresponding to 192 bytes. +# +CREATE DATABASE `this_sixty_five_byte_name_is_too_long____________________________`; +ERROR 42000: Incorrect database name 'this_sixty_five_byte_name_is_too_long____________________________' +CREATE DATABASE `this_sixty_four_byte_name_is_not_too_long_______________________`; +USE `this_sixty_four_byte_name_is_not_too_long_______________________`; +# +# A 64 character tablename can be created in a 64 character database name +# +CREATE TABLE `this_sixty_four_byte_name_is_not_too_long_______________________`.`this_sixty_four_byte_name_is_not_too_long_______________________` (a SERIAL); +# +# A 65 character tablename is too long. +# +CREATE TABLE `test`.`this_sixty_five_byte_name_is_too_long____________________________` (a SERIAL); +ERROR 42000: Incorrect table name 'this_sixty_five_byte_name_is_too_long____________________________' +CREATE TABLE `this_sixty_four_byte_name_is_not_too_long_______________________`.`this_sixty_five_byte_name_is_too_long____________________________` (a SERIAL); +ERROR 42000: Incorrect table name 'this_sixty_five_byte_name_is_too_long____________________________' +# +# Non-non-filename-safe characters like '#' are expanded to '@0023'. +# On many file systems, such as Linux extfs, you can create a database name +# that expands to up to 255 bytes long. +# `##################################################_long` is expanded to +# (50 * 5) + 5 = 255. +# +CREATE DATABASE `##################################################_long`;; +USE `##################################################_long`; +# +# This 256-byte name is only one byte longer but fails with an error code +# from the stat operation. +# `##################################################_long_` is expanded to +# (50 * 5) + 6 = 256. +# +CREATE DATABASE `##################################################_long_`; +ERROR HY000: Can't get stat of './##################################################_long_' (Errcode: ## "File name too long") +# +# This 300-byte name which is the longest name that gets an error code +# from the stat operation. +# `###########################################################_long` is expanded to +# (59 * 5) + 5 = 300. +# +CREATE DATABASE `###########################################################_long`; +ERROR HY000: Can't get stat of './###########################################################_long' (Errcode: ## "File name too long") +# +# This 301-byte name which is only one byte longer but fails with ER_TOO_LONG_IDENT. +# `###########################################################_long_` is expanded to +# (59 * 5) + 6 = 301. +# +CREATE DATABASE `###########################################################_long_`; +ERROR 42000: Incorrect database name '###########################################################_long_' +USE test; +# +# An expanded table name is limited to 251 bytes +# +CREATE TABLE `test`.`#################################################_long_` (a SERIAL); +# +# A 252-byte tablename is too long +# +CREATE TABLE `test`.`#################################################_long___` (a SERIAL); +ERROR HY000: Can't create table `test`.`#################################################_long___` (errno: ## "File name too long") +CREATE DATABASE twenty_byte_db_name_; +USE `twenty_byte_db_name_`; +# +# A 251 byte expanded table name will fit with a longer database name +# +CREATE TABLE `twenty_byte_db_name_`.`#################################################_long_` (a SERIAL); +# +# A 252 byte expanded table name is also too long in a longer database name +# +CREATE TABLE `twenty_byte_db_name_`.`#################################################_long___` (a SERIAL); +ERROR HY000: Can't create table `twenty_byte_db_name_`.`#################################################_long___` (errno: ## "File name too long") +# +# Another limitation is a 512 byte length to an expanded path that includes +# the datadir which is './' in this test, the expanded database name, +# the directory separator '/', the expanded table name, and the file extension. +# './long_db_name.long_250_byte_table_name.frm' +# 2+ 255 +1+ 250 +1+3 = 512 +# +CREATE TABLE `##################################################_long`.`#################################################_long` (a SERIAL); +CREATE TABLE `##################################################_long`.`#################################################_long_` (a SERIAL); +ERROR HY000: Long database name and identifier for object resulted in path length exceeding 512 characters. Path: './@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023_long/@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@ +SHOW WARNINGS; +Level Code Message +Error 1860 Long database name and identifier for object resulted in path length exceeding 512 characters. Path: './@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023_long/@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@ +# +# Show the successfully created databases and tables +# +---- list_files MYSQLD_DATADIR/test +#################################################_long_.frm +#################################################_long_.ibd +db.opt +---- list_files MYSQLD_DATADIR/this_sixty_four_byte_name_is_not_too_long_______________________ +db.opt +this_sixty_four_byte_name_is_not_too_long_______________________.frm +this_sixty_four_byte_name_is_not_too_long_______________________.ibd +---- list_files MYSQLD_DATADIR/##################################################_long +#################################################_long.frm +#################################################_long.ibd +db.opt +SELECT name FROM information_schema.innodb_sys_tables WHERE name LIKE '%long%'; +name +##################################################_long/#################################################_long +test/#################################################_long_ +this_sixty_four_byte_name_is_not_too_long_______________________/this_sixty_four_byte_name_is_not_too_long_______________________ +twenty_byte_db_name_/#################################################_long_ +SELECT name FROM information_schema.innodb_sys_tablespaces WHERE name LIKE '%long%'; +name +this_sixty_four_byte_name_is_not_too_long_______________________/this_sixty_four_byte_name_is_not_too_long_______________________ +test/#################################################_long_ +twenty_byte_db_name_/#################################################_long_ +##################################################_long/#################################################_long +SELECT path FROM information_schema.innodb_sys_datafiles WHERE path LIKE '%long%'; +path +./this_sixty_four_byte_name_is_not_too_long_______________________/this_sixty_four_byte_name_is_not_too_long_______________________.ibd +./test/#################################################_long_.ibd +./twenty_byte_db_name_/#################################################_long_.ibd +./##################################################_long/#################################################_long.ibd +SELECT file_name, tablespace_name FROM information_schema.files WHERE file_name LIKE '%long%'; +# +# Cleanup +# +DROP TABLE `this_sixty_four_byte_name_is_not_too_long_______________________`.`this_sixty_four_byte_name_is_not_too_long_______________________`; +DROP TABLE `test`.`#################################################_long_`; +DROP TABLE `twenty_byte_db_name_`.`#################################################_long_`; +DROP TABLE `##################################################_long`.`#################################################_long`; +DROP DATABASE `this_sixty_four_byte_name_is_not_too_long_______________________`; +DROP DATABASE `##################################################_long`; +DROP DATABASE `twenty_byte_db_name_`; diff --git a/mysql-test/suite/innodb/r/tablespace_per_table_windows.result b/mysql-test/suite/innodb/r/tablespace_per_table_windows.result new file mode 100644 index 00000000000..9d46557056b --- /dev/null +++ b/mysql-test/suite/innodb/r/tablespace_per_table_windows.result @@ -0,0 +1,51 @@ +# +# Test the limits of a file-per-table tablespace name. MySQL combines +# the database name with the table name to make a unique table name. +# +SET default_storage_engine=InnoDB; +# +# MySQL limits each database and tablename identifier to 64 characters +# of up to 3 bytes per character, corresponding to 192 bytes. +# +CREATE DATABASE `this_sixty_five_byte_name_is_too_long____________________________`; +ERROR 42000: Incorrect database name 'this_sixty_five_byte_name_is_too_long____________________________' +CREATE DATABASE `this_sixty_four_byte_name_is_not_too_long_______________________`; +USE `this_sixty_four_byte_name_is_not_too_long_______________________`; +# +# A 64 character tablename can be created in a 64 character database name +# +CREATE TABLE `this_sixty_four_byte_name_is_not_too_long_______________________`.`this_sixty_four_byte_name_is_not_too_long_______________________` (a SERIAL); +# +# A 65 character tablename is too long. +# +CREATE TABLE `test`.`this_sixty_five_byte_name_is_too_long____________________________` (a SERIAL); +ERROR 42000: Incorrect table name 'this_sixty_five_byte_name_is_too_long____________________________' +CREATE TABLE `this_sixty_four_byte_name_is_not_too_long_______________________`.`this_sixty_five_byte_name_is_too_long____________________________` (a SERIAL); +ERROR 42000: Incorrect table name 'this_sixty_five_byte_name_is_too_long____________________________' +# +# Show the successfully created database and table +# +SHOW CREATE TABLE `this_sixty_four_byte_name_is_not_too_long_______________________`.`this_sixty_four_byte_name_is_not_too_long_______________________`; +Table Create Table +this_sixty_four_byte_name_is_not_too_long_______________________ CREATE TABLE `this_sixty_four_byte_name_is_not_too_long_______________________` ( + `a` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + UNIQUE KEY `a` (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +---- list_files MYSQLD_DATADIR/this_sixty_four_byte_name_is_not_too_long_______________________ +db.opt +this_sixty_four_byte_name_is_not_too_long_______________________.frm +this_sixty_four_byte_name_is_not_too_long_______________________.ibd +SELECT name FROM information_schema.innodb_sys_tables WHERE name LIKE '%long%'; +name +this_sixty_four_byte_name_is_not_too_long_______________________/this_sixty_four_byte_name_is_not_too_long_______________________ +SELECT name FROM information_schema.innodb_sys_tablespaces WHERE name LIKE '%long%'; +name +this_sixty_four_byte_name_is_not_too_long_______________________/this_sixty_four_byte_name_is_not_too_long_______________________ +SELECT path FROM information_schema.innodb_sys_datafiles WHERE path LIKE '%long%'; +path +.\this_sixty_four_byte_name_is_not_too_long_______________________\this_sixty_four_byte_name_is_not_too_long_______________________.ibd +SELECT file_name, tablespace_name FROM information_schema.files WHERE file_name LIKE '%long%'; +# +# Cleanup +# +DROP DATABASE `this_sixty_four_byte_name_is_not_too_long_______________________`; diff --git a/mysql-test/suite/innodb/t/add_foreign_key.test b/mysql-test/suite/innodb/t/add_foreign_key.test new file mode 100644 index 00000000000..d0febfd62f0 --- /dev/null +++ b/mysql-test/suite/innodb/t/add_foreign_key.test @@ -0,0 +1,38 @@ +--source include/have_innodb.inc + +--echo # +--echo # Bug #19471516 SERVER CRASHES WHEN EXECUTING ALTER TABLE ADD +--echo # FOREIGN KEY +--echo # + +CREATE TABLE `parent` (`parent_id` INT, PRIMARY KEY (`parent_id`)); +CREATE TABLE `child1` (`id` INT ,`child1_fk1` INT, `child1_fk2` INT, +PRIMARY KEY (`id`)); +CREATE TABLE `child2` (`id` INT, `child2_fk1` INT, `child2_fk2` INT, +PRIMARY KEY (`id`)); +CREATE TABLE `child3` (`id` INT , `child3_fk1` INT, PRIMARY KEY (`id`)); +ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk1`) REFERENCES `parent` +(`parent_id`); +ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk1`) REFERENCES +`parent` (`parent_id`); +ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk2`) REFERENCES `parent` +(`parent_id`); + +ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk1`) REFERENCES `parent` +(`parent_id`); + +ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk2`) REFERENCES `parent` +(`parent_id`); + +ALTER TABLE `child3` ADD FOREIGN KEY (`child3_fk1`) REFERENCES `parent` +(`parent_id`); +ALTER TABLE `child1` ADD FOREIGN KEY (`child1_fk2`) REFERENCES +`parent` (`parent_id`); +ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk1`) REFERENCES +`parent` (`parent_id`); +ALTER TABLE `child2` ADD FOREIGN KEY (`child2_fk2`) REFERENCES +`parent` (`parent_id`); +ALTER TABLE `child3` ADD FOREIGN KEY (`child3_fk1`) REFERENCES +`parent` (`parent_id`); + +drop table child3, child2, child1, parent; diff --git a/mysql-test/suite/innodb/t/cascade_lock_wait.test b/mysql-test/suite/innodb/t/cascade_lock_wait.test new file mode 100644 index 00000000000..4489c9aefac --- /dev/null +++ b/mysql-test/suite/innodb/t/cascade_lock_wait.test @@ -0,0 +1,45 @@ +--source include/have_innodb.inc +--source include/have_debug.inc + +create table t1 (f1 int primary key) engine=innodb; +create table t2 (f1 int primary key, + constraint c1 foreign key (f1) references t1(f1) + on update cascade + on delete cascade) engine=innodb; +create table t3 (f1 int primary key, + constraint c2 foreign key (f1) references t1(f1) + on update cascade + on delete cascade) engine=innodb; +show create table t1; +show create table t2; +show create table t3; + +insert into t1 values (1); +insert into t1 values (2); +insert into t1 values (3); + +insert into t2 values (1); +insert into t2 values (2); +insert into t2 values (3); + +insert into t3 values (1); +insert into t3 values (2); +insert into t3 values (3); + +select f1 from t1; +select f1 from t2; +select f1 from t3; + +set @save_dbug = @@debug_dbug; +set debug_dbug = '+d,dml_cascade_only_once'; +set debug_dbug = '+d,row_upd_cascade_lock_wait_err'; +update t1 set f1 = 100 where f1 = 2; + +select f1 from t1; +select f1 from t2; +select f1 from t3; + +set debug_dbug = @save_dbug; +drop table t2; +drop table t3; +drop table t1; diff --git a/mysql-test/suite/innodb/t/import_update_stats.test b/mysql-test/suite/innodb/t/import_update_stats.test new file mode 100644 index 00000000000..128213c77b2 --- /dev/null +++ b/mysql-test/suite/innodb/t/import_update_stats.test @@ -0,0 +1,81 @@ +# +# BUG#20125349 - PERSISTANT STATS IS NOT UPDATED WHEN TTS IS IMPORTED. +# + +--source include/not_embedded.inc +--source include/have_innodb.inc +--source include/not_valgrind.inc # MDEV-32725 FIXME + +let MYSQLD_DATADIR =`SELECT @@datadir`; +SET @old_innodb_file_per_table = @@innodb_file_per_table; + +SET GLOBAL innodb_file_per_table = 1; +SELECT @@innodb_file_per_table; + +CREATE TABLE t1 ( + col_1 CHAR (255), + col_2 VARCHAR (255) +) ENGINE = InnoDB; + +CREATE INDEX idx1 ON t1(col_1); +CREATE INDEX idx2 ON t1(col_2); + +SHOW INDEXES FROM t1; + +INSERT INTO t1 VALUES ("col1_00001", "col2_00001"), ("col1_00002", "col2_00002"); + +SHOW INDEXES FROM t1; + +ANALYZE TABLE t1; +SHOW INDEXES FROM t1; + +FLUSH TABLES t1 FOR EXPORT; +perl; +do "$ENV{MTR_SUITE_DIR}/../innodb/include/innodb-util.pl"; +ib_backup_tablespaces("test", "t1"); +EOF + +UNLOCK TABLES; + +DROP TABLE t1; + +CREATE TABLE t1 ( + col_1 CHAR (255), + col_2 VARCHAR (255) +) ENGINE = InnoDB STATS_PERSISTENT=1; + +CREATE INDEX idx1 ON t1(col_1); +CREATE INDEX idx2 ON t1(col_2); + +SHOW INDEXES FROM t1; + +INSERT INTO t1 VALUES ("col1_00001", "col2_00001"); + +SHOW INDEXES FROM t1; + +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE t1; +SHOW INDEXES FROM t1; + +ALTER TABLE t1 DISCARD TABLESPACE; + +perl; +do "$ENV{MTR_SUITE_DIR}/../innodb/include/innodb-util.pl"; +ib_discard_tablespaces("test", "t1"); +ib_restore_tablespaces("test", "t1"); +EOF + +ALTER TABLE t1 IMPORT TABLESPACE; + +SHOW INDEXES FROM t1; + +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE t1; +SHOW INDEXES FROM t1; + +DROP TABLE t1; + +SET GLOBAL innodb_file_per_table = @old_innodb_file_per_table; + +--remove_files_wildcard $MYSQLTEST_VARDIR/tmp t1*.ibd +--remove_files_wildcard $MYSQLTEST_VARDIR/tmp t1*.cfg diff --git a/mysql-test/suite/innodb/t/index_length.test b/mysql-test/suite/innodb/t/index_length.test new file mode 100644 index 00000000000..bf4940d4b39 --- /dev/null +++ b/mysql-test/suite/innodb/t/index_length.test @@ -0,0 +1,23 @@ +--source include/have_innodb.inc + +--connect (stop_purge,localhost,root) +# Prevent the purge of history from acquiring a table handle. +START TRANSACTION WITH CONSISTENT SNAPSHOT; +--connection default + +CREATE TABLE t1(a INT PRIMARY KEY, b VARCHAR(1024)) +ENGINE=InnoDB STATS_PERSISTENT=1; +INSERT INTO t1 VALUES (1,REPEAT('b',1024)); + +SELECT index_length FROM information_schema.tables +WHERE table_schema = 'test' AND table_name = 't1'; +ALTER TABLE t1 ADD INDEX b (b(800)); +SELECT FLOOR(index_length/@@innodb_page_size) FROM information_schema.tables +WHERE table_schema = 'test' AND table_name = 't1'; +ALTER TABLE t1 ADD INDEX ba (b(800),a); +SELECT FLOOR(index_length/@@innodb_page_size) FROM information_schema.tables +WHERE table_schema = 'test' AND table_name = 't1'; +disconnect stop_purge; +DROP TABLE t1; + +--echo # End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/innodb-32k.test b/mysql-test/suite/innodb/t/innodb-32k.test index a9645d65998..7cf28ed79c6 100644 --- a/mysql-test/suite/innodb/t/innodb-32k.test +++ b/mysql-test/suite/innodb/t/innodb-32k.test @@ -7,6 +7,19 @@ call mtr.add_suppression("Innodb: Cannot add field.*row size is"); let $MYSQLD_DATADIR= `select @@datadir`; +SET SESSION innodb_strict_mode=ON; +--error ER_CANT_CREATE_TABLE +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +--error ER_CANT_CREATE_TABLE +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB KEY_BLOCK_SIZE=4; +SET SESSION innodb_strict_mode=OFF; +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +SHOW WARNINGS; +DROP TABLE t1; +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB KEY_BLOCK_SIZE=4; +SHOW WARNINGS; +DROP TABLE t1; + --echo # Test 1) Show the page size from Information Schema SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size'; diff --git a/mysql-test/suite/innodb/t/innodb-64k.test b/mysql-test/suite/innodb/t/innodb-64k.test index 972ba6bb8b8..d89370ff538 100644 --- a/mysql-test/suite/innodb/t/innodb-64k.test +++ b/mysql-test/suite/innodb/t/innodb-64k.test @@ -8,6 +8,19 @@ call mtr.add_suppression('InnoDB: Cannot add field.*because after adding it, the let $MYSQLD_DATADIR= `select @@datadir`; +SET SESSION innodb_strict_mode=ON; +--error ER_CANT_CREATE_TABLE +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +--error ER_CANT_CREATE_TABLE +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB KEY_BLOCK_SIZE=4; +SET SESSION innodb_strict_mode=OFF; +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +SHOW WARNINGS; +DROP TABLE t1; +CREATE TABLE t1(a int PRIMARY KEY) ENGINE=InnoDB KEY_BLOCK_SIZE=4; +SHOW WARNINGS; +DROP TABLE t1; + --echo # Test 1) Show the page size from Information Schema SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size'; diff --git a/mysql-test/suite/innodb/t/innodb-ac-non-locking-select.test b/mysql-test/suite/innodb/t/innodb-ac-non-locking-select.test new file mode 100644 index 00000000000..9ecddacba52 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-ac-non-locking-select.test @@ -0,0 +1,117 @@ +# DEBUG_SYNC must be compiled in. +--source include/have_debug_sync.inc +--source include/have_debug.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (c1 INT , c2 CHAR(10), PRIMARY KEY (c1)) ENGINE = InnoDB; +INSERT INTO t1 VALUES(0, "0"); +INSERT INTO t1 VALUES(1, "1"); +INSERT INTO t1 VALUES(2, "2"); +INSERT INTO t1 VALUES(3, "3"); + +--connect (con1,localhost,root,,) +--connect (con2,localhost,root,,) +--connect (con3,localhost,root,,) +--connect (con4,localhost,root,,) +--connect (con5,localhost,root,,) +--connect (con6,localhost,root,,) + +connection default; +# Disable query log to avoid non-deterministic output conflicts +SET AUTOCOMMIT=0; +BEGIN; +# Lock all the records +SELECT * FROM t1 FOR UPDATE; +--disable_query_log + +connection con1; +SET AUTOCOMMIT=1; +# Test if locking autocommit selects end up in the trx_sys_t::trx_list. +# We check this via the INFORMATION_SCHEMA.INNODB_TRX. +# This should block and show up in the I_S. +SET DEBUG_SYNC='lock_wait_suspend_thread_enter SIGNAL waiting1'; +--send +SELECT COUNT(*) FROM t1 LOCK IN SHARE MODE; + +connection con2; +SET AUTOCOMMIT=1; +# Test if non-locking autocommit selects end up in the trx_sys_t::trx_list. +# We check this via the INFORMATION_SCHEMA.INNODB_TRX. +# This should not block and should not show up in the I_S. +--send +SELECT COUNT(*) FROM t1; + +connection con3; +SET AUTOCOMMIT=1; +# Note: autocommit non-locking selects are not converted to locking selects +# Therefore this should not block; +SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; +--send +SELECT COUNT(*) FROM t1; + +connection con4; +SET AUTOCOMMIT=0; +# Note: Non-locking selects are converted to locking selects +# therefore this should block; +SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; +SET DEBUG_SYNC='now WAIT_FOR waiting1'; +SET DEBUG_SYNC='lock_wait_suspend_thread_enter SIGNAL waiting4'; +--send +SELECT COUNT(*) FROM t1 WHERE c1 >= 0; + +connection con5; +SET AUTOCOMMIT=1; +# This should not block +BEGIN; +--send +SELECT COUNT(*) FROM t1; + +connection con6; +SET AUTOCOMMIT=1; +# This will ignore the auto-commit setting but wont block because it is +# a non-locking select. +XA START '1'; +--enable_query_log +SELECT * FROM t1 WHERE c1 <= 3; + +connection default; +# Wait for SELECTs to get into the lock wait queue +SET DEBUG_SYNC='now WAIT_FOR waiting4'; +SET DEBUG_SYNC= 'RESET'; + +# Check the number of non-locking transactions +let $wait_condition = + SELECT COUNT(*) = 5 + FROM INFORMATION_SCHEMA.INNODB_TRX + WHERE trx_autocommit_non_locking = 0; +--source include/wait_condition.inc + +# Check the waiting transactions +SELECT trx_state, trx_query, trx_autocommit_non_locking +FROM INFORMATION_SCHEMA.INNODB_TRX +WHERE trx_state = 'LOCK WAIT' +ORDER BY trx_query; + +INSERT INTO t1 VALUES(4, '4'); +COMMIT; + +connection con6; +SELECT * FROM t1 WHERE c1 <= 4; +XA END '1'; +XA PREPARE '1'; +XA ROLLBACK '1'; +disconnect con6; +disconnect con2; +disconnect con3; +disconnect con5; + +connection con1; +reap; +disconnect con1; + +connection con4; +reap; +disconnect con4; + +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb-alter.test b/mysql-test/suite/innodb/t/innodb-alter.test index 0bedbdc7bbb..60ce7d4f707 100644 --- a/mysql-test/suite/innodb/t/innodb-alter.test +++ b/mysql-test/suite/innodb/t/innodb-alter.test @@ -690,6 +690,32 @@ ALTER TABLE t1 ADD COLUMN b DATETIME NOT NULL, LOCK=NONE; SET @@SQL_MODE= @OLD_SQL_MODE; DROP TABLE t1; +--echo # +--echo # Bug#20977779 CANNOT IMPORT TABLES CONTAINING PREFIX INDEXES +--echo # + +CREATE TABLE t1 (c1 VARCHAR(32), c2 VARCHAR(32), c3 VARCHAR(32), +PRIMARY KEY (c1, c2, c3)) +ENGINE=InnoDB; + +ALTER TABLE t1 ADD INDEX ind1(c1(5), c2, c3); +ALTER TABLE t1 ADD INDEX ind2(c3, c1(10), c2); +ALTER TABLE t1 ADD INDEX ind3(c2, c3, c1(20)); + +INSERT INTO t1 VALUES ('Test Data -1', 'Test Data -2', 'Test Data -3'); + +let $source_db = test; +let $dest_db = test; + +--echo # Test with 2ndary index having prefix +--source suite/innodb/include/import.inc + +--echo # Test with PK & 2ndary index with prefix +ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c1(5), c2(10), c3(20)); +--source suite/innodb/include/import.inc + +DROP TABLE t1; + # # End of 10.2 tests # diff --git a/mysql-test/suite/innodb/t/innodb-index-online-fk.test b/mysql-test/suite/innodb/t/innodb-index-online-fk.test index 5c8954064ce..12a6eea49c2 100644 --- a/mysql-test/suite/innodb/t/innodb-index-online-fk.test +++ b/mysql-test/suite/innodb/t/innodb-index-online-fk.test @@ -482,3 +482,32 @@ SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS; DROP TABLE t2; DROP TABLE t3; + +--echo # Bug #17449901 TABLE DISAPPEARS WHEN ALTERING +--echo # WITH FOREIGN KEY CHECKS OFF + +# Drop index via inplace algorithm +create table t1(f1 int,primary key(f1))engine=innodb; +create table t2(f2 int,f3 int,key t(f2,f3),foreign key(f2) references t1(f1))engine=innodb; +SET foreign_key_checks=0; +drop index t on t2; +drop table t2; +drop table t1; + +# Drop index using alter statement via inplace +create table t1(f1 int ,primary key(f1))engine=innodb; +create table t2(f2 int,f3 int, key t(f2),foreign key(f2) references t1(f1))engine=innodb; +SET foreign_key_checks = 0; +alter table t2 drop key t,algorithm=inplace; +show create table t2; +drop table t2; +drop table t1; + +create table t1(f1 int ,primary key(f1))engine=innodb; +create table t2(f2 int,f3 int, key t(f2),key t1(f2,f3), +foreign key(f2) references t1(f1))engine=innodb; +SET foreign_key_checks = 0; +alter table t2 drop key t,algorithm=inplace; +show create table t2; +drop table t2; +drop table t1; diff --git a/mysql-test/suite/innodb/t/innodb-lock-inherit-read_commited.test b/mysql-test/suite/innodb/t/innodb-lock-inherit-read_commited.test new file mode 100644 index 00000000000..d9c933fa9b5 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-lock-inherit-read_commited.test @@ -0,0 +1,115 @@ +--echo # +--echo # Bug #21025880 DUPLICATE UK VALUES IN READ-COMMITTED(AGAIN) +--echo # + +--source include/have_innodb.inc +--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; + +let $i=0; + +while ($i <=1 ) +{ + +CREATE TABLE t1 ( + a INT NOT NULL, + b INT NOT NULL, + PRIMARY KEY(b), + UNIQUE KEY(a)) +ENGINE=INNODB; + +SET @old_innodb_stats_auto_recalc = @@innodb_stats_auto_recalc; +SET GLOBAL innodb_stats_auto_recalc = OFF; + +# Block purge +connect purge_control,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; + +SET @old_tx_isolation = @@tx_isolation; +SET GLOBAL tx_isolation = 'READ-COMMITTED'; + +SET @old_innodb_lock_wait_timeout = @@innodb_lock_wait_timeout; +SET GLOBAL innodb_lock_wait_timeout = 1; + +--connect(con1,localhost,root,,) + +# Create and delete-mark an index record + +INSERT INTO t1 VALUES (1,1),(2,2); +DELETE FROM t1; + +SET debug_sync = 'row_ins_sec_index_entry_dup_locks_created SIGNAL +con1_locks_done WAIT_FOR con1_go'; +SET debug_sync = 'ha_commit_trans_after_acquire_commit_lock SIGNAL +con1_insert_done WAIT_FOR con1_finish'; +--send + +if ($i == 0) +{ +REPLACE INTO t1 VALUES (1,2); +} + +if ( $i == 1) +{ +INSERT INTO t1 values (1,2) ON DUPLICATE KEY UPDATE a=2; +} +--connect(con2,localhost,root,,) + +SET debug_sync = 'now WAIT_FOR con1_locks_done'; + +SET debug_sync = 'lock_wait_suspend_thread_enter SIGNAL con2_blocked +WAIT_FOR con2_go'; +SET debug_sync = 'ha_commit_trans_after_acquire_commit_lock +WAIT_FOR con2_finish'; +SET debug_sync = 'ib_after_row_insert SIGNAL con2_insert_done'; + +--send +REPLACE INTO t1 VALUES (1,3); + +--connection default +SET debug_sync = 'now WAIT_FOR con2_blocked'; + +connection purge_control; +COMMIT; +disconnect purge_control; +connection default; + +# Wait for purge to delete the delete-marked record +--source ../../innodb/include/wait_all_purged.inc + +SET debug_sync = 'now SIGNAL con2_go WAIT_FOR con2_insert_done'; +SET debug_sync = 'now SIGNAL con1_go WAIT_FOR con1_insert_done'; + +SET debug_sync = 'now SIGNAL con1_finish'; + +--connection con1 +--reap +--disconnect con1 +--connection default +SET debug_sync = 'now SIGNAL con2_finish'; + +--connection con2 +--error 0,ER_LOCK_WAIT_TIMEOUT +--reap +--disconnect con2 + +--connection default +SET DEBUG_SYNC= 'RESET'; + +SELECT * FROM t1; +CHECK TABLE t1; + +DROP TABLE t1; + +SET GLOBAL innodb_stats_auto_recalc = @old_innodb_stats_auto_recalc; +SET GLOBAL tx_isolation = @old_tx_isolation; +SET GLOBAL innodb_lock_wait_timeout = @old_innodb_lock_wait_timeout; + +--inc $i +} + +SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; diff --git a/mysql-test/suite/innodb/t/innodb-read-view.test b/mysql-test/suite/innodb/t/innodb-read-view.test index 425cbeb08c8..21c79cf6566 100644 --- a/mysql-test/suite/innodb/t/innodb-read-view.test +++ b/mysql-test/suite/innodb/t/innodb-read-view.test @@ -1,7 +1,6 @@ # DEBUG_SYNC must be compiled in. --source include/have_debug_sync.inc --source include/have_debug.inc - # We need to test the use case: # a. Create a transaction T1 that will be promoted to RW. # b. Create a transaction T2 that will be promoted to RW. @@ -27,22 +26,16 @@ INSERT INTO t2 VALUES(2, "c"); INSERT INTO t2 VALUES(3, "d"); --connect (con1,localhost,root,,) ---connect (con2,localhost,root,,) - -connection con1; ---echo 'T1' SET AUTOCOMMIT=0; BEGIN; SELECT * FROM t2; connection default; ---echo 'T2' SET AUTOCOMMIT=0; BEGIN; SELECT * FROM t1; -connection con2; ---echo 'T3' +--connect (con2,localhost,root,,) SET AUTOCOMMIT=0; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN; @@ -50,48 +43,36 @@ SELECT * FROM t1; SELECT * FROM t2; connection con1; ---echo 'T1' UPDATE t2 SET c1 = c1 + 100; SELECT * FROM t2; COMMIT; connection default; ---echo 'T2' UPDATE t1 SET c1 = c1 + 100; SELECT * FROM t1; COMMIT; connection con2; ---echo 'T3' SET DEBUG_SYNC='row_search_for_mysql_before_return WAIT_FOR waiting1'; --send SELECT * FROM t1; connection default; ---echo 'T2' SET DEBUG_SYNC='now SIGNAL waiting1'; ---echo 'Signalled T3' connection con2; ---echo 'T3' reap; connection con2; ---echo 'T3' SET DEBUG_SYNC='row_search_for_mysql_before_return WAIT_FOR waiting1'; --send SELECT * FROM t2; connection default; ---echo 'T2' SET DEBUG_SYNC='now SIGNAL waiting1'; ---echo 'Signalled T3' connection con2; ---echo 'T3' reap; connection default; -disconnect con1; -disconnect con2; # We need to test the use case: # a. Create a transaction T1 that will be promoted to RW. @@ -105,17 +86,12 @@ disconnect con2; # i. T3 Does a select - it should not see the changes made by T1 but should # see the changes by T2 ---connect (con1,localhost,root,,) ---connect (con2,localhost,root,,) - connection con1; ---echo 'T1' SET AUTOCOMMIT=0; BEGIN; SELECT * FROM t1; connection default; ---echo 'T2' SET AUTOCOMMIT=0; BEGIN; SELECT * FROM t2; @@ -124,7 +100,6 @@ SELECT * FROM t2; COMMIT; connection con2; ---echo 'T3' SET AUTOCOMMIT=0; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN; @@ -132,42 +107,30 @@ SELECT * FROM t1; SELECT * FROM t2; connection con1; ---echo 'T1' UPDATE t1 SET c1 = c1 + 100; SELECT * FROM t1; COMMIT; connection con2; ---echo 'T3' SET DEBUG_SYNC='row_select_wait WAIT_FOR waiting1'; --send SELECT * FROM t1; connection con1; ---echo 'T2' SET DEBUG_SYNC='now SIGNAL waiting1'; ---echo 'Signalled T3' connection con2; ---echo 'T3' reap; - -connection con2; ---echo 'T3' SET DEBUG_SYNC='row_select_wait WAIT_FOR waiting1'; --send SELECT * FROM t2; connection default; ---echo 'T2' SET DEBUG_SYNC='now SIGNAL waiting1'; ---echo 'Signalled T3' connection con2; ---echo 'T3' reap; +disconnect con2; connection default; -disconnect con1; -disconnect con2; DROP TABLE t1; DROP TABLE t2; @@ -176,8 +139,7 @@ DROP TABLE t2; --echo # Bug 21433768: NON-REPEATABLE READ WITH REPEATABLE READ ISOLATION --echo # ---connect (con1,localhost,root,,) - +connection con1; CREATE TABLE t1(col1 INT PRIMARY KEY, col2 INT) ENGINE = InnoDB; INSERT INTO t1 values (1, 0), (2, 0); SELECT * FROM t1 ORDER BY col1; @@ -200,9 +162,7 @@ reap; disconnect con1; connection default; - +SET DEBUG_SYNC= 'RESET'; DROP TABLE t1; -# Clean up resources used in this test case. -SET DEBUG_SYNC= 'RESET'; --source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/innodb_i_s_innodb_locks.test b/mysql-test/suite/innodb/t/innodb_i_s_innodb_locks.test new file mode 100644 index 00000000000..e6e46dbf556 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_i_s_innodb_locks.test @@ -0,0 +1,169 @@ +# +# Test that user data is correctly "visualized" in +# INFORMATION_SCHEMA.innodb_locks.lock_data +# + +-- source include/have_innodb.inc + +SET @save_timeout=@@GLOBAL.innodb_lock_wait_timeout; +SET GLOBAL innodb_lock_wait_timeout=100000000; + +let $table_def = +( + c01 TINYINT, + c02 TINYINT UNSIGNED, + c03 SMALLINT, + c04 SMALLINT UNSIGNED, + c05 MEDIUMINT, + c06 MEDIUMINT UNSIGNED, + c07 INT, + c08 INT UNSIGNED, + c09 BIGINT, + c10 BIGINT UNSIGNED, + PRIMARY KEY(c01, c02, c03, c04, c05, c06, c07, c08, c09, c10) +) ENGINE=INNODB; + +-- eval CREATE TABLE t_min $table_def; +INSERT INTO t_min VALUES +(-128, 0, + -32768, 0, + -8388608, 0, + -2147483648, 0, + -9223372036854775808, 0); + +-- eval CREATE TABLE t_max $table_def; +INSERT INTO t_max VALUES +(127, 255, + 32767, 65535, + 8388607, 16777215, + 2147483647, 4294967295, + 9223372036854775807, 18446744073709551615); + +CREATE TABLE ```t'\"_str` ( + c1 VARCHAR(32), + c2 VARCHAR(32), + c3 VARCHAR(32), + c4 VARCHAR(32), + c5 VARCHAR(32), + c6 VARCHAR(32), + c7 VARCHAR(32), + PRIMARY KEY(c1, c2, c3, c4, c5, c6, c7) +) ENGINE=INNODB; +INSERT INTO ```t'\"_str` VALUES +('1', 'abc', '''abc', 'abc''', 'a''bc', 'a''bc''', '''abc'''''); +INSERT INTO ```t'\"_str` VALUES +('2', 'abc', '"abc', 'abc"', 'a"bc', 'a"bc"', '"abc""'); +INSERT INTO ```t'\"_str` VALUES +('3', 'abc', '\\abc', 'abc\\', 'a\\bc', 'a\\bc\\', '\\abc\\\\'); +INSERT INTO ```t'\"_str` VALUES +('4', 'abc', 0x00616263, 0x61626300, 0x61006263, 0x6100626300, 0x610062630000); + +-- source include/count_sessions.inc + +-- connect (con_lock,localhost,root,,) +-- connect (con_min_trylock,localhost,root,,) +-- connect (con_max_trylock,localhost,root,,) +-- connect (con_str_insert_supremum,localhost,root,,) +-- connect (con_str_lock_row1,localhost,root,,) +-- connect (con_str_lock_row2,localhost,root,,) +-- connect (con_str_lock_row3,localhost,root,,) +-- connect (con_str_lock_row4,localhost,root,,) +-- connect (con_verify_innodb_locks,localhost,root,,) + +-- connection con_lock +SET autocommit=0; +SELECT * FROM t_min FOR UPDATE; +SELECT * FROM t_max FOR UPDATE; +SELECT * FROM ```t'\"_str` FOR UPDATE; + +-- connection con_min_trylock +-- send +SELECT * FROM t_min FOR UPDATE; + +-- connection con_max_trylock +-- send +SELECT * FROM t_max FOR UPDATE; + +-- connection con_str_insert_supremum +-- send +INSERT INTO ```t'\"_str` VALUES +('z', 'z', 'z', 'z', 'z', 'z', 'z'); + +-- connection con_str_lock_row1 +-- send +SELECT * FROM ```t'\"_str` WHERE c1 = '1' FOR UPDATE; + +-- connection con_str_lock_row2 +-- send +SELECT * FROM ```t'\"_str` WHERE c1 = '2' FOR UPDATE; + +-- connection con_str_lock_row3 +-- send +SELECT * FROM ```t'\"_str` WHERE c1 = '3' FOR UPDATE; + +-- connection con_str_lock_row4 +-- send +SELECT * FROM ```t'\"_str` WHERE c1 = '4' FOR UPDATE; + +-- connection con_verify_innodb_locks +# Wait for the above queries to execute before continuing. +# Without this, it sometimes happens that the SELECT from innodb_locks +# executes before some of them, resulting in less than expected number +# of rows being selected from innodb_locks. If there is a bug and there +# are no 14 rows in innodb_locks then this test will fail with timeout. +# Notice that if we query INNODB_LOCKS more often than once per 0.1 sec +# then its contents will never change because the cache from which it is +# filled is updated only if it has not been read for 0.1 seconds. See +# CACHE_MIN_IDLE_TIME_US in trx/trx0i_s.c. +let $cnt=10; +while ($cnt) +{ + let $success=`SELECT COUNT(*) = 14 FROM INFORMATION_SCHEMA.INNODB_LOCKS`; + if ($success) + { + let $cnt=0; + } + if (!$success) + { + real_sleep 0.2; + dec $cnt; + } +} +if (!$success) +{ + -- echo Timeout waiting for rows in INNODB_LOCKS to appear +} + +SELECT lock_mode, lock_type, lock_table, lock_index, lock_rec, lock_data +FROM INFORMATION_SCHEMA.INNODB_LOCKS ORDER BY lock_data; + +SELECT lock_table, COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCKS +GROUP BY lock_table; + +set @save_sql_mode = @@sql_mode; +SET SQL_MODE='ANSI_QUOTES'; +SELECT lock_table, COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCKS +GROUP BY lock_table; +SET @@sql_mode=@save_sql_mode; + +# Release all the locks; +-- connection con_lock +COMMIT; + +-- connection default + +-- disconnect con_lock +-- disconnect con_min_trylock +-- disconnect con_max_trylock +-- disconnect con_str_insert_supremum +-- disconnect con_str_lock_row1 +-- disconnect con_str_lock_row2 +-- disconnect con_str_lock_row3 +-- disconnect con_str_lock_row4 +-- disconnect con_verify_innodb_locks + +DROP TABLE t_min, t_max, ```t'\"_str`; + +-- source include/wait_until_count_sessions.inc + +SET GLOBAL innodb_lock_wait_timeout=@save_timeout; diff --git a/mysql-test/suite/innodb/t/innodb_i_s_innodb_trx.test b/mysql-test/suite/innodb/t/innodb_i_s_innodb_trx.test new file mode 100644 index 00000000000..745e1d94a12 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_i_s_innodb_trx.test @@ -0,0 +1,95 @@ +--source include/have_innodb.inc + +# +# Test that transaction data is correctly "visualized" in +# INFORMATION_SCHEMA.INNODB_TRX +# + +SET @save_timeout=@@GLOBAL.innodb_lock_wait_timeout; +SET GLOBAL innodb_lock_wait_timeout=100000000; + +DESCRIBE INFORMATION_SCHEMA.INNODB_TRX; + +CREATE TABLE t1 ( + c01 INT, + c02 INT, + PRIMARY KEY (c01) +) ENGINE=INNODB STATS_AUTO_RECALC=0; + +INSERT INTO t1 VALUES +(1,2),(2,4),(3,6),(4,8); + +CREATE TABLE t2 ( + c01 INT, + c02 INT, + PRIMARY KEY (c01), + FOREIGN KEY fk1 (c02) REFERENCES t1 (c01) +) ENGINE=INNODB STATS_AUTO_RECALC=0; + +INSERT INTO t2 VALUES +(1,1),(2,2),(3,3); + +-- source include/count_sessions.inc + +-- connect (con_trx,localhost,root,,) +-- connect (con_verify_innodb_trx,localhost,root,,) + +-- connection con_trx +SET autocommit=0; +INSERT INTO t1 VALUES (5,10); +SELECT * FROM t1 FOR UPDATE; + +let $wait_timeout= 300; +let $wait_condition= + SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_TRX; +-- source include/wait_condition.inc + +-- connection con_verify_innodb_trx +SELECT trx_state, trx_weight, trx_tables_in_use, trx_tables_locked, +trx_rows_locked, trx_rows_modified, trx_concurrency_tickets, +trx_isolation_level, trx_unique_checks, trx_foreign_key_checks +FROM INFORMATION_SCHEMA.INNODB_TRX; + +-- connection con_trx +ROLLBACK; +SET FOREIGN_KEY_CHECKS = 0; +SET UNIQUE_CHECKS = 0; +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +BEGIN; +INSERT INTO t1 VALUES (6,12); + +let $wait_timeout= 300; +let $wait_condition= + SELECT trx_unique_checks = 0 FROM INFORMATION_SCHEMA.INNODB_TRX; +-- source include/wait_condition.inc + +-- connection con_verify_innodb_trx +SELECT trx_isolation_level, trx_unique_checks, trx_foreign_key_checks +FROM INFORMATION_SCHEMA.INNODB_TRX; + +-- connection con_trx +ROLLBACK; +SET FOREIGN_KEY_CHECKS = 1; +SET UNIQUE_CHECKS = 1; +BEGIN; +--error ER_NO_REFERENCED_ROW_2 +INSERT INTO t2 VALUES (4,10); + +let $wait_timeout= 300; +let $wait_condition= + SELECT trx_unique_checks = 1 FROM INFORMATION_SCHEMA.INNODB_TRX; +-- source include/wait_condition.inc +-- disconnect con_trx + +-- connection con_verify_innodb_trx +SELECT trx_state, trx_isolation_level, trx_last_foreign_key_error +FROM INFORMATION_SCHEMA.INNODB_TRX; +-- disconnect con_verify_innodb_trx + +-- connection default +DROP TABLE t2; +DROP TABLE t1; + +-- source include/wait_until_count_sessions.inc + +SET GLOBAL innodb_lock_wait_timeout=@save_timeout; diff --git a/mysql-test/suite/innodb/t/innodb_information_schema_tables.opt b/mysql-test/suite/innodb/t/innodb_information_schema_tables.opt index 9f30d81ef9c..1e45e63659f 100644 --- a/mysql-test/suite/innodb/t/innodb_information_schema_tables.opt +++ b/mysql-test/suite/innodb/t/innodb_information_schema_tables.opt @@ -27,3 +27,4 @@ --loose-innodb_buffer_pool_pages --loose-innodb_buffer_pool_pages_index --loose-innodb_buffer_pool_pages_blob +--innodb-open-files=1000000 diff --git a/mysql-test/suite/innodb/t/innodb_information_schema_tables.test b/mysql-test/suite/innodb/t/innodb_information_schema_tables.test index 15b3bf4f561..c62705da84b 100644 --- a/mysql-test/suite/innodb/t/innodb_information_schema_tables.test +++ b/mysql-test/suite/innodb/t/innodb_information_schema_tables.test @@ -1,6 +1,10 @@ -- source include/have_innodb.inc -- source include/not_embedded.inc +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; +let SEARCH_PATTERN= \[Warning\] InnoDB: innodb_open_files 1000000 should not be greater than the open_files_limit [0-9]+; +--source include/search_pattern_in_file.inc + # # MDEV-7762 InnoDB: Failing assertion: block->page.buf_fix_count > 0 in buf0buf.ic line 730 # diff --git a/mysql-test/suite/innodb/t/innodb_stats_auto_recalc.opt b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc.opt new file mode 100644 index 00000000000..aa53ff2e659 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc.opt @@ -0,0 +1 @@ +--innodb-stats-persistent diff --git a/mysql-test/suite/innodb/t/innodb_stats_auto_recalc.test b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc.test new file mode 100644 index 00000000000..e441a795540 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc.test @@ -0,0 +1,48 @@ +# +# Test the persistent stats auto recalc +# + +-- source include/have_innodb.inc +# Page numbers printed by this test depend on the page size +-- source include/have_innodb_16k.inc + +-- vertical_results + +-- let $check_stats1 = SELECT n_rows, clustered_index_size FROM mysql.innodb_table_stats WHERE table_name = 'autorecalc' +-- let $check_stats2 = SELECT index_name, stat_name, stat_value FROM mysql.innodb_index_stats WHERE table_name = 'autorecalc' + +CREATE TABLE autorecalc (a INT, PRIMARY KEY (a)) ENGINE=INNODB; + +# the CREATE should have inserted zeroed stats +-- eval $check_stats1 +-- eval $check_stats2 + +INSERT INTO autorecalc VALUES (1); +INSERT INTO autorecalc VALUES (2); + +# wait for the bg stats thread to update the stats, notice we wait on +# innodb_index_stats because innodb_table_stats gets updated first and +# it is possible that (if we wait on innodb_table_stats) the wait cond +# gets satisfied before innodb_index_stats is updated +let $wait_condition = SELECT stat_value = 2 FROM mysql.innodb_index_stats WHERE table_name = 'autorecalc' AND index_name = 'PRIMARY' AND stat_name = 'n_diff_pfx01'; +-- source include/wait_condition.inc + +# the second INSERT from above should have triggered an auto-recalc +-- eval $check_stats1 +-- eval $check_stats2 + +# now DELETE the rows and trigger a second auto-recalc, InnoDB may wait a +# few seconds before triggering an auto-recalc again (it tries not to be too +# aggressive) + +DELETE FROM autorecalc; + +let $wait_timeout = 25; +let $wait_condition = SELECT stat_value = 0 FROM mysql.innodb_index_stats WHERE table_name = 'autorecalc' AND index_name = 'PRIMARY' AND stat_name = 'n_diff_pfx01'; +-- source include/wait_condition.inc + +# the DELETE from above should have triggered an auto-recalc +-- eval $check_stats1 +-- eval $check_stats2 + +DROP TABLE autorecalc; diff --git a/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_ddl.opt b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_ddl.opt new file mode 100644 index 00000000000..aa53ff2e659 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_ddl.opt @@ -0,0 +1 @@ +--innodb-stats-persistent diff --git a/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_ddl.test b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_ddl.test new file mode 100644 index 00000000000..aeb5b5c291e --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_ddl.test @@ -0,0 +1,49 @@ +# +# Test the persistent stats auto recalc during DDL +# + +-- source include/have_innodb.inc + +-- vertical_results + +-- let $check_stats1 = SELECT n_rows FROM mysql.innodb_table_stats WHERE table_name = 'arddl' ORDER BY 1 +-- let $check_stats2 = SELECT index_name, stat_name, stat_value FROM mysql.innodb_index_stats WHERE table_name = 'arddl' AND index_name = 'PRIMARY' ORDER BY 1, 2, 3 + +# Test ADD INDEX during background stats gathering + +CREATE TABLE arddl (a INT, b INT, PRIMARY KEY (a)) ENGINE=INNODB; + +INSERT INTO arddl VALUES (1, 10); +INSERT INTO arddl VALUES (2, 10); + +ALTER TABLE arddl ADD INDEX (b); + +# wait for the bg stats thread to update the stats, notice we wait on +# innodb_index_stats because innodb_table_stats gets updated first and +# it is possible that (if we wait on innodb_table_stats) the wait cond +# gets satisfied before innodb_index_stats is updated +let $wait_condition = SELECT stat_value = 2 FROM mysql.innodb_index_stats WHERE table_name = 'arddl' AND index_name = 'PRIMARY' AND stat_name = 'n_diff_pfx01'; +-- source include/wait_condition.inc + +# the second INSERT from above should have triggered an auto-recalc +-- eval $check_stats1 +-- eval $check_stats2 + +DROP TABLE arddl; + +# Test DROP INDEX during background stats gathering + +CREATE TABLE arddl (a INT, b INT, PRIMARY KEY (a), KEY (b)) ENGINE=INNODB; + +INSERT INTO arddl VALUES (3, 10); +INSERT INTO arddl VALUES (4, 10); + +ALTER TABLE arddl DROP INDEX b; + +let $wait_condition = SELECT stat_value = 2 FROM mysql.innodb_index_stats WHERE table_name = 'arddl' AND index_name = 'PRIMARY' AND stat_name = 'n_diff_pfx01'; +-- source include/wait_condition.inc + +-- eval $check_stats1 +-- eval $check_stats2 + +DROP TABLE arddl; diff --git a/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_lots.opt b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_lots.opt new file mode 100644 index 00000000000..aa53ff2e659 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_lots.opt @@ -0,0 +1 @@ +--innodb-stats-persistent diff --git a/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_lots.test b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_lots.test new file mode 100644 index 00000000000..88ca8910cd2 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_lots.test @@ -0,0 +1,45 @@ +# +# Test the persistent stats auto recalc on lots of tables +# + +--source include/no_valgrind_without_big.inc +-- source include/have_innodb.inc + +let $check_stats = SELECT table_name, n_rows FROM mysql.innodb_table_stats WHERE table_name LIKE 'ar_%' ORDER BY table_name; + +-- disable_query_log +let $i = 1200; +while ($i > 1000) { + eval CREATE TABLE ar_$i (a INT, PRIMARY KEY (a)) ENGINE=INNODB; + dec $i; +} +-- enable_query_log + +# the CREATEs above should have inserted zeroed stats +-- eval $check_stats + +-- disable_query_log +let $i = 1200; +while ($i > 1000) { + eval INSERT INTO ar_$i VALUES (1), (2); + dec $i; +} +-- enable_query_log + +-- disable_query_log +let $i = 1200; +while ($i > 1000) { + eval INSERT INTO ar_$i VALUES (3), (4); + dec $i; +} +-- enable_query_log + +# would be too long to wait for stats to become up to date here + +-- disable_query_log +let $i = 1200; +while ($i > 1000) { + eval DROP TABLE ar_$i; + dec $i; +} +-- enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_on_nonexistent.opt b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_on_nonexistent.opt new file mode 100644 index 00000000000..aa53ff2e659 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_on_nonexistent.opt @@ -0,0 +1 @@ +--innodb-stats-persistent diff --git a/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_on_nonexistent.test b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_on_nonexistent.test new file mode 100644 index 00000000000..d8e7332958d --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_auto_recalc_on_nonexistent.test @@ -0,0 +1,85 @@ +# +# Test the persistent stats auto recalc when persistent stats do not exist +# + +-- source include/have_innodb.inc + +-- vertical_results + +-- let $check_stats1 = SELECT COUNT(*) FROM mysql.innodb_table_stats WHERE table_name = 't' +-- let $check_stats2 = SELECT COUNT(*) FROM mysql.innodb_index_stats WHERE table_name = 't' + +-- echo Test with default setting + +CREATE TABLE t (a INT, PRIMARY KEY (a)) ENGINE=INNODB; + +# the CREATE should have inserted zeroed stats +-- eval $check_stats1 +-- eval $check_stats2 + +# close the table +FLUSH TABLE t; + +DELETE FROM mysql.innodb_index_stats WHERE table_name = 't'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 't'; + +-- eval $check_stats1 +-- eval $check_stats2 + +# open the table, causing stats recalc/save +SELECT * FROM t; + +-- eval $check_stats1 +-- eval $check_stats2 + +DROP TABLE t; + +-- echo Test with explicit enable + +CREATE TABLE t (a INT, PRIMARY KEY (a)) ENGINE=INNODB STATS_AUTO_RECALC=1; + +# the CREATE should have inserted zeroed stats +-- eval $check_stats1 +-- eval $check_stats2 + +# close the table +FLUSH TABLE t; + +DELETE FROM mysql.innodb_index_stats WHERE table_name = 't'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 't'; + +-- eval $check_stats1 +-- eval $check_stats2 + +# open the table, causing stats recalc/save +SELECT * FROM t; + +-- eval $check_stats1 +-- eval $check_stats2 + +DROP TABLE t; + +-- echo Test with explicit disable + +CREATE TABLE t (a INT, PRIMARY KEY (a)) ENGINE=INNODB STATS_AUTO_RECALC=0; + +# the CREATE should have inserted zeroed stats +-- eval $check_stats1 +-- eval $check_stats2 + +# close the table +FLUSH TABLE t; + +DELETE FROM mysql.innodb_index_stats WHERE table_name = 't'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 't'; + +-- eval $check_stats1 +-- eval $check_stats2 + +# open the table, stats should not be present, since autorecalc is disabled +SELECT * FROM t; + +-- eval $check_stats1 +-- eval $check_stats2 + +DROP TABLE t; diff --git a/mysql-test/suite/innodb/t/innodb_stats_external_pages.test b/mysql-test/suite/innodb/t/innodb_stats_external_pages.test new file mode 100644 index 00000000000..da0dce9a454 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_external_pages.test @@ -0,0 +1,79 @@ +# +# Bug#18384390 WRONG STATISTICS WITH BIG ROW LENGTH AND PERSISTENT STATS +# + +--source include/have_innodb.inc +--source include/have_innodb_max_16k.inc +--source include/have_sequence.inc + +CREATE TABLE bug18384390 ( + id INT AUTO_INCREMENT PRIMARY KEY, + txt VARCHAR(10000) +) ENGINE=INNODB STATS_PERSISTENT=1 STATS_AUTO_RECALC=0; + +let $count=1024; +eval +INSERT INTO bug18384390 (txt) SELECT REPEAT('0', 10000) FROM seq_1_to_$count; + +set use_stat_tables=never; +ANALYZE TABLE bug18384390; + +-- let $n_rows = `SELECT n_rows FROM mysql.innodb_table_stats WHERE table_name = 'bug18384390'` + +-- let $table_rows = `SELECT table_rows FROM information_schema.tables WHERE table_name = 'bug18384390'` + +-- let $n_diff = `SELECT stat_value FROM mysql.innodb_index_stats WHERE table_name = 'bug18384390' AND stat_name = 'n_diff_pfx01'` + +-- let $cardinality = `SELECT cardinality FROM information_schema.statistics WHERE table_name = 'bug18384390'` + +-- let $margin_of_err_pct = 30 +-- let $margin_of_err_rows = `SELECT ROUND($count * $margin_of_err_pct / 100)` + +-- let $min_allowed = `SELECT $count - $margin_of_err_rows` +-- let $max_allowed = `SELECT $count + $margin_of_err_rows` + +-- let $dump_sql = SELECT COUNT(*) FROM bug18384390; SELECT * FROM mysql.innodb_table_stats; SELECT * FROM mysql.innodb_index_stats; SELECT * FROM information_schema.tables WHERE table_name = 'bug18384390'; SELECT * FROM information_schema.statistics WHERE table_name = 'bug18384390'; + +-- vertical_results + +if ($n_rows < $min_allowed) { + -- echo mysql.innodb_table_stats.n_rows is too small ($n_rows < $min_allowed) + -- eval $dump_sql +} + +if ($n_rows > $max_allowed) { + -- echo mysql.innodb_table_stats.n_rows is too big ($n_rows > $max_allowed) + -- eval $dump_sql +} + +if ($table_rows < $min_allowed) { + -- echo information_schema.tables.table_rows is too small ($table_rows < $min_allowed) + -- eval $dump_sql +} + +if ($table_rows > $max_allowed) { + -- echo information_schema.tables.table_rows is too big ($table_rows > $max_allowed) + -- eval $dump_sql +} + +if ($n_diff < $min_allowed) { + -- echo mysql.innodb_index_stats.stat_value is too small ($n_diff < $min_allowed) + -- eval $dump_sql +} + +if ($n_diff > $max_allowed) { + -- echo mysql.innodb_index_stats.stat_value is too big ($n_diff > $max_allowed) + -- eval $dump_sql +} + +if ($cardinality < $min_allowed) { + -- echo information_schema.statistics.cardinality is too small ($cardinality < $min_allowed) + -- eval $dump_sql +} + +if ($cardinality > $max_allowed) { + -- echo information_schema.statistics.cardinality is too big ($cardinality > $max_allowed) + -- eval $dump_sql +} + +DROP TABLE bug18384390; diff --git a/mysql-test/suite/innodb/t/innodb_stats_flag_global.combinations b/mysql-test/suite/innodb/t/innodb_stats_flag_global.combinations new file mode 100644 index 00000000000..561eb72d9a9 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_flag_global.combinations @@ -0,0 +1,4 @@ +[on] +--innodb-stats-persistent=1 +[off] +--innodb-stats-persistent=0 diff --git a/mysql-test/suite/innodb/t/innodb_stats_flag_global.test b/mysql-test/suite/innodb/t/innodb_stats_flag_global.test new file mode 100644 index 00000000000..88f0ed7c16d --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_flag_global.test @@ -0,0 +1,91 @@ +-- source include/have_innodb.inc +-- source include/not_embedded.inc + +# +-- echo ===== +-- echo === Test ANALYZE behavior after default creation +-- echo ===== + +CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB; + +-- source innodb_stats_flag_global_analyze.inc + +DROP TABLE test_ps_flag; + +CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB STATS_PERSISTENT=default; + +-- source innodb_stats_flag_global_analyze.inc + +DROP TABLE test_ps_flag; + +# +-- echo ===== +-- echo === Test ANALYZE behavior after creation with explicit PS=OFF +-- echo ===== + +CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB STATS_PERSISTENT=0; + +-- source innodb_stats_flag_global_analyze.inc + +DROP TABLE test_ps_flag; + +# +-- echo ===== +-- echo === Test ANALYZE behavior after creation with explicit PS=ON +-- echo ===== + +CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB STATS_PERSISTENT=1; + +-- source innodb_stats_flag_global_analyze.inc + +DROP TABLE test_ps_flag; + +# +-- echo ===== +-- echo === Test ANALYZE behavior after creation with explicit PS=OFF, +-- echo === then ALTER to ON, then ALTER to OFF, then ALTER to default +-- echo ===== + +CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB STATS_PERSISTENT=0; + +ALTER TABLE test_ps_flag STATS_PERSISTENT=1; + +# also check that the change from the ALTER TABLE survives server restart +-- source include/restart_mysqld.inc + +-- source innodb_stats_flag_global_analyze.inc + +ALTER TABLE test_ps_flag STATS_PERSISTENT=0; + +-- source innodb_stats_flag_global_analyze.inc + +ALTER TABLE test_ps_flag STATS_PERSISTENT=default; + +-- source innodb_stats_flag_global_analyze.inc + +DROP TABLE test_ps_flag; + +# +-- echo ===== +-- echo === Test ANALYZE behavior after creation with explicit PS=ON, +-- echo === then ALTER to OFF, then ALTER to ON, then ALTER to default +-- echo ===== + +CREATE TABLE test_ps_flag (a INT) ENGINE=INNODB STATS_PERSISTENT=1; + +ALTER TABLE test_ps_flag STATS_PERSISTENT=0; + +# also check that the change from the ALTER TABLE survives server restart +-- source include/restart_mysqld.inc + +-- source innodb_stats_flag_global_analyze.inc + +ALTER TABLE test_ps_flag STATS_PERSISTENT=1; + +-- source innodb_stats_flag_global_analyze.inc + +ALTER TABLE test_ps_flag STATS_PERSISTENT=default; + +-- source innodb_stats_flag_global_analyze.inc + +DROP TABLE test_ps_flag; diff --git a/mysql-test/suite/innodb/t/innodb_stats_flag_global_analyze.inc b/mysql-test/suite/innodb/t/innodb_stats_flag_global_analyze.inc new file mode 100644 index 00000000000..8a68677e8ee --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_flag_global_analyze.inc @@ -0,0 +1,13 @@ +SHOW CREATE TABLE test_ps_flag; + +DELETE FROM mysql.innodb_index_stats WHERE table_name = 'test_ps_flag'; +DELETE FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; + +# must be 0, we have just deleted the rows +SELECT COUNT(*) AS cnt_before FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; + +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE test_ps_flag; + +# if the table is PS enabled, then this should be 1 and 0 otherwise +SELECT COUNT(*) AS cnt_after FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_flag'; diff --git a/mysql-test/suite/innodb/t/innodb_stats_persistent.test b/mysql-test/suite/innodb/t/innodb_stats_persistent.test index f79ae37e8de..cfcd7c2128d 100644 --- a/mysql-test/suite/innodb/t/innodb_stats_persistent.test +++ b/mysql-test/suite/innodb/t/innodb_stats_persistent.test @@ -15,6 +15,7 @@ ENGINE=INNODB STATS_PERSISTENT=1,STATS_AUTO_RECALC=1; CREATE TABLE t2 LIKE t1; INSERT INTO t1 (val) SELECT 4 FROM seq_1_to_16; +SET STATEMENT use_stat_tables=never FOR ANALYZE TABLE t1; connect(con1, localhost, root,,); @@ -85,3 +86,41 @@ 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; + +# +# Bug#12429573 TIMESTAMP COLUMN OF INNODB.INDEX_STATS ARE NOT UPDATED +# WHEN RE-RUNNING ANALYZE +# +CREATE TABLE bug12429573 (i INTEGER PRIMARY KEY, j INTEGER, KEY(j)) +ENGINE=INNODB STATS_PERSISTENT=1; + +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE bug12429573; + +# Cannot check the exact timestamp here because it is always different +# but at least check that both timestamps in innodb_table_stats and in +# innodb_index_stats have been updated to the same value. If the bug is +# present this check will fail. + +SELECT last_update INTO @last FROM mysql.innodb_table_stats +WHERE table_name = 'bug12429573'; +SELECT * FROM mysql.innodb_index_stats +WHERE table_name = 'bug12429573' AND last_update!=@last; + +# The first ANALYZE would insert timestamp e.g. 17:23:39 in both +# innodb_table_stats and innodb_index_stats. The bug is that the second +# ANALYZE only updates the timestamp in innodb_table_stats. In order to +# check if the timestamp in innodb_index_stats has really been updated we +# need it to be different from the previous one (17:23:39) with at least +# one second. +-- sleep 1 + +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE bug12429573; + +SELECT * FROM mysql.innodb_table_stats +WHERE table_name = 'bug12429573' AND last_update=@last; +SELECT * FROM mysql.innodb_index_stats +WHERE table_name = 'bug12429573' AND last_update=@last; + +DROP TABLE bug12429573; diff --git a/mysql-test/suite/innodb/t/innodb_stats_sample_pages.opt b/mysql-test/suite/innodb/t/innodb_stats_sample_pages.opt new file mode 100644 index 00000000000..aa53ff2e659 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_sample_pages.opt @@ -0,0 +1 @@ +--innodb-stats-persistent diff --git a/mysql-test/suite/innodb/t/innodb_stats_sample_pages.test b/mysql-test/suite/innodb/t/innodb_stats_sample_pages.test new file mode 100644 index 00000000000..1aac71a0450 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_sample_pages.test @@ -0,0 +1,53 @@ +# +# Test that the table option STATS_SAMPLE_PAGES=N|default is indeed +# used by InnoDB +# + +-- source include/have_innodb.inc +# Page numbers printed by this test depend on the page size +-- source include/have_innodb_16k.inc + +SET GLOBAL innodb_stats_persistent_sample_pages=17; + +CREATE TABLE test_ps_sample_pages_used ( + a VARCHAR(512), PRIMARY KEY (a) +) ENGINE=INNODB STATS_SAMPLE_PAGES=default; + +# Insert enough records into the table so that it has more than 2*17+1 pages +# If we ask to scan more than the half of the leaf pages, then the sampling +# will do full scan and we cannot check whether the sample_pages variable was +# honored. +BEGIN; +-- disable_query_log +let $i=999; +while ($i) { + eval INSERT INTO test_ps_sample_pages_used VALUES (REPEAT(1000+$i, 128)); + dec $i; +} +-- enable_query_log +COMMIT; + +ANALYZE TABLE test_ps_sample_pages_used; + +# confirm the big number of leaf pages in the index +SELECT stat_name, stat_value FROM mysql.innodb_index_stats +WHERE table_name='test_ps_sample_pages_used' AND stat_name='n_leaf_pages'; + +# confirm that 17 pages were sampled, that is - the global +# innodb_stats_persistent_sample_pages is used when the table option +# STATS_SAMPLE_PAGES is set to 'default'. +SELECT sample_size FROM mysql.innodb_index_stats +WHERE table_name='test_ps_sample_pages_used' AND stat_name='n_diff_pfx01'; + +ALTER TABLE test_ps_sample_pages_used STATS_SAMPLE_PAGES=14; + +ANALYZE TABLE test_ps_sample_pages_used; + +# confirm that 14 pages were sampled, that is - the table option +# STATS_SAMPLE_PAGES is used when it is set. +SELECT sample_size FROM mysql.innodb_index_stats +WHERE table_name='test_ps_sample_pages_used' AND stat_name='n_diff_pfx01'; + +DROP TABLE test_ps_sample_pages_used; + +SET GLOBAL innodb_stats_persistent_sample_pages=default; diff --git a/mysql-test/suite/innodb/t/innodb_stats_table_flag_auto_recalc.test b/mysql-test/suite/innodb/t/innodb_stats_table_flag_auto_recalc.test new file mode 100644 index 00000000000..01fe4331926 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_table_flag_auto_recalc.test @@ -0,0 +1,83 @@ +# +# Test CREATE TABLE ... STATS_AUTO_RECALC=0|1|default +# + +-- source include/no_valgrind_without_big.inc +-- source include/have_innodb.inc +-- source include/not_embedded.inc + +-- vertical_results + +CREATE TABLE test_ps_auto_recalc (a INT, PRIMARY KEY (a)) ENGINE=INNODB; + +SHOW CREATE TABLE test_ps_auto_recalc; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; + +ALTER TABLE test_ps_auto_recalc STATS_AUTO_RECALC=1; + +# confirm that the flag survives server restart +-- source include/restart_mysqld.inc + +SHOW CREATE TABLE test_ps_auto_recalc; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; + +DROP TABLE test_ps_auto_recalc; + +## + +CREATE TABLE test_ps_auto_recalc (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_AUTO_RECALC=default; + +SHOW CREATE TABLE test_ps_auto_recalc; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; + +DROP TABLE test_ps_auto_recalc; + +## + +CREATE TABLE test_ps_auto_recalc (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_AUTO_RECALC=0; + +# confirm that the flag survives server restart +-- source include/restart_mysqld.inc + +SHOW CREATE TABLE test_ps_auto_recalc; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; + +ALTER TABLE test_ps_auto_recalc STATS_AUTO_RECALC=1; + +# confirm that the flag survives server restart +-- source include/restart_mysqld.inc + +SHOW CREATE TABLE test_ps_auto_recalc; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; + +DROP TABLE test_ps_auto_recalc; + +## + +CREATE TABLE test_ps_auto_recalc (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_AUTO_RECALC=1; + +# confirm that the flag survives server restart +-- source include/restart_mysqld.inc + +SHOW CREATE TABLE test_ps_auto_recalc; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; + +ALTER TABLE test_ps_auto_recalc STATS_AUTO_RECALC=0; + +# confirm that the flag survives server restart +-- source include/restart_mysqld.inc + +SHOW CREATE TABLE test_ps_auto_recalc; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_auto_recalc'; + +DROP TABLE test_ps_auto_recalc; diff --git a/mysql-test/suite/innodb/t/innodb_stats_table_flag_sample_pages.test b/mysql-test/suite/innodb/t/innodb_stats_table_flag_sample_pages.test new file mode 100644 index 00000000000..a5c3c8624b1 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_table_flag_sample_pages.test @@ -0,0 +1,103 @@ +# +# Test CREATE TABLE ... STATS_SAMPLE_PAGES=N|default +# + +-- source include/have_innodb.inc +# include/restart_mysqld.inc does not work in embedded mode +-- source include/not_embedded.inc + +-- vertical_results + +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB; + +SHOW CREATE TABLE test_ps_sample_pages; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_sample_pages'; + +ALTER TABLE test_ps_sample_pages STATS_SAMPLE_PAGES=12345; + +# confirm that the flag survives server restart +-- source include/restart_mysqld.inc + +SHOW CREATE TABLE test_ps_sample_pages; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_sample_pages'; + +DROP TABLE test_ps_sample_pages; + +## + +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=default; + +SHOW CREATE TABLE test_ps_sample_pages; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_sample_pages'; + +DROP TABLE test_ps_sample_pages; + +## + +-- error ER_PARSE_ERROR +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=-5; + +-- error ER_PARSE_ERROR +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=0; + +-- error ER_PARSE_ERROR +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=67000; + +-- error ER_PARSE_ERROR +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=670000; + +-- error ER_PARSE_ERROR +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=65536; + +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=65535; + +SHOW CREATE TABLE test_ps_sample_pages; + +DROP TABLE test_ps_sample_pages; + +## + +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=1; + +# confirm that the flag survives server restart +-- source include/restart_mysqld.inc + +SHOW CREATE TABLE test_ps_sample_pages; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_sample_pages'; + +DROP TABLE test_ps_sample_pages; + +## + +CREATE TABLE test_ps_sample_pages (a INT, PRIMARY KEY (a)) ENGINE=INNODB +STATS_SAMPLE_PAGES=5678; + +# confirm that the flag survives server restart +-- source include/restart_mysqld.inc + +SHOW CREATE TABLE test_ps_sample_pages; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_sample_pages'; + +ALTER TABLE test_ps_sample_pages STATS_SAMPLE_PAGES=default; + +# confirm that the flag survives server restart +-- source include/restart_mysqld.inc + +SHOW CREATE TABLE test_ps_sample_pages; +SELECT create_options FROM information_schema.tables +WHERE table_name='test_ps_sample_pages'; + +DROP TABLE test_ps_sample_pages; diff --git a/mysql-test/suite/innodb/t/innodb_ut_format_name.test b/mysql-test/suite/innodb/t/innodb_ut_format_name.test new file mode 100644 index 00000000000..6e4023c7088 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_ut_format_name.test @@ -0,0 +1,17 @@ +# +# Test ut_format_name() +# + +-- source include/have_debug.inc +-- source include/have_innodb.inc + +CREATE TABLE t (c INT) ENGINE=INNODB; + +# This will invoke test_ut_format_name() in debug builds + +SET @save_dbug = @@debug_dbug; +SET debug_dbug = '+d,test_ut_format_name'; + +DROP TABLE t; + +SET debug_dbug = @save_dbug; diff --git a/mysql-test/suite/innodb/t/records_in_range.test b/mysql-test/suite/innodb/t/records_in_range.test new file mode 100644 index 00000000000..697dbc1e8dd --- /dev/null +++ b/mysql-test/suite/innodb/t/records_in_range.test @@ -0,0 +1,432 @@ +# +# Test btr_estimate_n_rows_in_range() which is used by +# ha_innobase::records_in_range() +# + +-- source include/have_debug.inc +-- source include/have_innodb.inc +-- source include/innodb_page_size_small.inc + +CREATE TABLE records_in_range_test ( + c1 VARCHAR(16), + c2 VARCHAR(512), + PRIMARY KEY (c1) +) ENGINE=INNODB STATS_PERSISTENT=1; + +# Insert some records so that they cannot fit in one page for some page sizes +# in order to exercise records_in_range() where 1, 2 or more pages are sampled +INSERT INTO records_in_range_test VALUES +('ccc', REPEAT('v', 512)), +('kkk01', REPEAT('v', 512)), +('kkk02', REPEAT('v', 512)), +('kkk03', REPEAT('v', 512)), +('kkk04', REPEAT('v', 512)), +('kkk05', REPEAT('v', 512)), +('kkk06', REPEAT('v', 512)), +('kkk07', REPEAT('v', 512)), +('kkk08', REPEAT('v', 512)), +('mmm', REPEAT('v', 512)), +('nnn', REPEAT('v', 512)), +('uuu01', REPEAT('v', 512)), +('uuu02', REPEAT('v', 512)), +('uuu03', REPEAT('v', 512)), +('uuu04', REPEAT('v', 512)), +('uuu05', REPEAT('v', 512)), +('uuu06', REPEAT('v', 512)), +('uuu07', REPEAT('v', 512)), +('uuu08', REPEAT('v', 512)), +('xxx', REPEAT('v', 512)); + +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE records_in_range_test; + +# 16k or bigger page size: 1 leaf page +# 8k page size: 2 leaf pages +# 4k page size: 4 leaf pages +SELECT index_name, stat_name, stat_value +FROM mysql.innodb_index_stats +WHERE +table_name='records_in_range_test' AND stat_name = 'n_leaf_pages'; + +# 16k or bigger page size: 1 page in total (leaf + nonleaf) +# 8k page size: 3 pages in total (leaf + nonleaf) +# 4k page size: 5 pages in total (leaf + nonleaf) +SELECT index_name, stat_name, stat_value +FROM mysql.innodb_index_stats +WHERE +table_name='records_in_range_test' AND stat_name = 'size'; + +# We exploit the warning mechanism here to display the return value from +# btr_estimate_n_rows_in_range() +SET @save_dbug = @@debug_dbug; +SET DEBUG_DBUG='+d,print_btr_estimate_n_rows_in_range_return_value'; + +-- echo +-- echo In all SELECTs below the number of the records in the range returned +-- echo by COUNT(*) must be the same as the number returned by +-- echo btr_estimate_n_rows_in_range() which can be seen inside the artificial +-- echo warning + +-- echo +-- echo Test left-unbounded, right-open intervals +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'aaa'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 < 'zzz'; + +-- echo +-- echo Test left-unbounded, right-closed intervals +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'aaa'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 <= 'zzz'; + +-- echo +-- echo Test left-open, right-unbounded intervals +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz'; + +-- echo +-- echo Test left-closed, right-unbounded intervals +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz'; + +-- echo +-- echo Test left-open, right-open intervals +-- echo In some cases here the optimizer is smart enough not to call +-- echo ha_innobase::records_in_range() at all, so we get no warning containing +-- echo the value returned from btr_estimate_n_rows_in_range() +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 < 'zzz'; + +-- echo +-- echo Test left-closed, right-open intervals +-- echo In some cases here the optimizer is smart enough not to call +-- echo ha_innobase::records_in_range() at all, so we get no warning containing +-- echo the value returned from btr_estimate_n_rows_in_range() +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 < 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 < 'zzz'; + +-- echo +-- echo Test left-open, right-closed intervals +-- echo In some cases here the optimizer is smart enough not to call +-- echo ha_innobase::records_in_range() at all, so we get no warning containing +-- echo the value returned from btr_estimate_n_rows_in_range() +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'aaa' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'ccc' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'eee' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'mmm' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'nnn' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'qqq' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'xxx' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 > 'zzz' AND c1 <= 'zzz'; + +-- echo +-- echo Test left-closed, right-closed intervals +-- echo In some cases here the optimizer is smart enough not to call +-- echo ha_innobase::records_in_range() at all, so we get no warning containing +-- echo the value returned from btr_estimate_n_rows_in_range() +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'aaa' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'ccc' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'eee' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'mmm' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'nnn' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'qqq' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'xxx' AND c1 <= 'zzz'; +-- echo +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'bbb'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'ccc'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'eee'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'mmm'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'nnn'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'qqq'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'xxx'; +SELECT COUNT(*) FROM records_in_range_test WHERE c1 >= 'zzz' AND c1 <= 'zzz'; + +SET DEBUG_DBUG = @save_dbug; + +DROP TABLE records_in_range_test; diff --git a/mysql-test/suite/innodb/t/tablespace_per_table_not_windows.opt b/mysql-test/suite/innodb/t/tablespace_per_table_not_windows.opt new file mode 100644 index 00000000000..bd6d9db453b --- /dev/null +++ b/mysql-test/suite/innodb/t/tablespace_per_table_not_windows.opt @@ -0,0 +1,2 @@ +--innodb-sys-tablespaces +--innodb-sys-datafiles diff --git a/mysql-test/suite/innodb/t/tablespace_per_table_not_windows.test b/mysql-test/suite/innodb/t/tablespace_per_table_not_windows.test new file mode 100644 index 00000000000..2cc2460e517 --- /dev/null +++ b/mysql-test/suite/innodb/t/tablespace_per_table_not_windows.test @@ -0,0 +1,164 @@ +--echo # +--echo # Test the limits of a file-per-table tablespace name. MySQL combines +--echo # the database name with the table name to make a unique table name. +--echo # + +--source include/have_innodb.inc +--source include/not_windows.inc +# This will test the limit of a filename in MySQL at 512 bytes. +# We control that by making it a relative path starting with "./". +# The embedded server uses an absolute path as the datadir +# which has a non-deterministic length. +--source include/not_embedded.inc + +SET default_storage_engine=InnoDB; +LET $MYSQLD_DATADIR = `select @@datadir`; + +--echo # +--echo # MySQL limits each database and tablename identifier to 64 characters +--echo # of up to 3 bytes per character, corresponding to 192 bytes. +--echo # +LET $too_long_name = this_sixty_five_byte_name_is_too_long____________________________; +--error ER_WRONG_DB_NAME +--eval CREATE DATABASE `$too_long_name` + +LET $long_name = this_sixty_four_byte_name_is_not_too_long_______________________; +--eval CREATE DATABASE `$long_name` +--eval USE `$long_name` + +--echo # +--echo # A 64 character tablename can be created in a 64 character database name +--echo # +--eval CREATE TABLE `$long_name`.`$long_name` (a SERIAL) + +--echo # +--echo # A 65 character tablename is too long. +--echo # +--error ER_WRONG_TABLE_NAME +--eval CREATE TABLE `test`.`$too_long_name` (a SERIAL) +--error ER_WRONG_TABLE_NAME +--eval CREATE TABLE `$long_name`.`$too_long_name` (a SERIAL) + +--echo # +--echo # Non-non-filename-safe characters like '#' are expanded to '@0023'. +--echo # On many file systems, such as Linux extfs, you can create a database name +--echo # that expands to up to 255 bytes long. +--echo # `##################################################_long` is expanded to +--echo # (50 * 5) + 5 = 255. +--echo # +LET $long_db_name = ##################################################_long; +--eval CREATE DATABASE `$long_db_name`; +--eval USE `$long_db_name` + +--echo # +--echo # This 256-byte name is only one byte longer but fails with an error code +--echo # from the stat operation. +--echo # `##################################################_long_` is expanded to +--echo # (50 * 5) + 6 = 256. +--echo # +--replace_regex /Errcode: [0-9]+/Errcode: ##/ /@0023/#/ +--error 13 +CREATE DATABASE `##################################################_long_`; + +--echo # +--echo # This 300-byte name which is the longest name that gets an error code +--echo # from the stat operation. +--echo # `###########################################################_long` is expanded to +--echo # (59 * 5) + 5 = 300. +--echo # +--replace_regex /Errcode: [0-9]+/Errcode: ##/ /@0023/#/ +--error 13 +CREATE DATABASE `###########################################################_long`; + +--echo # +--echo # This 301-byte name which is only one byte longer but fails with ER_TOO_LONG_IDENT. +--echo # `###########################################################_long_` is expanded to +--echo # (59 * 5) + 6 = 301. +--echo # +--replace_result @0023 # +--error ER_WRONG_DB_NAME +CREATE DATABASE `###########################################################_long_`; + +USE test; + +LET $long_249_byte_table_name = #################################################long; +LET $long_250_byte_table_name = #################################################_long; +LET $long_251_byte_table_name = #################################################_long_; +LET $long_252_byte_table_name = #################################################_long___; + +--echo # +--echo # An expanded table name is limited to 251 bytes +--echo # +--eval CREATE TABLE `test`.`$long_251_byte_table_name` (a SERIAL) + +--echo # +--echo # A 252-byte tablename is too long +--echo # +--replace_regex /errno: [0-9]+/errno: ##/ /@0023/#/ +--error ER_CANT_CREATE_TABLE +--eval CREATE TABLE `test`.`$long_252_byte_table_name` (a SERIAL) + +CREATE DATABASE twenty_byte_db_name_; +USE `twenty_byte_db_name_`; + +--echo # +--echo # A 251 byte expanded table name will fit with a longer database name +--echo # +--eval CREATE TABLE `twenty_byte_db_name_`.`$long_251_byte_table_name` (a SERIAL) + +--echo # +--echo # A 252 byte expanded table name is also too long in a longer database name +--echo # +--replace_regex /errno: [0-9]+/errno: ##/ /@0023/#/ +--error ER_CANT_CREATE_TABLE +--eval CREATE TABLE `twenty_byte_db_name_`.`$long_252_byte_table_name` (a SERIAL) + +--echo # +--echo # Another limitation is a 512 byte length to an expanded path that includes +--echo # the datadir which is './' in this test, the expanded database name, +--echo # the directory separator '/', the expanded table name, and the file extension. +--echo # './long_db_name.long_250_byte_table_name.frm' +--echo # 2+ 255 +1+ 250 +1+3 = 512 +--echo # +--eval CREATE TABLE `$long_db_name`.`$long_250_byte_table_name` (a SERIAL) + +--error ER_IDENT_CAUSES_TOO_LONG_PATH +--eval CREATE TABLE `$long_db_name`.`$long_251_byte_table_name` (a SERIAL) +SHOW WARNINGS; + +--echo # +--echo # Show the successfully created databases and tables +--echo # +--echo ---- list_files MYSQLD_DATADIR/test +--replace_result @0023 # +--list_files $MYSQLD_DATADIR/test +--echo ---- list_files MYSQLD_DATADIR/$long_name +--replace_result @0023 # +--list_files $MYSQLD_DATADIR/$long_name +--echo ---- list_files MYSQLD_DATADIR/$long_db_name +--replace_result @0023 # +--list_files $MYSQLD_DATADIR/@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023_long + +--replace_result @0023 # +SELECT name FROM information_schema.innodb_sys_tables WHERE name LIKE '%long%'; +--replace_result @0023 # +SELECT name FROM information_schema.innodb_sys_tablespaces WHERE name LIKE '%long%'; +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR @0023 # +SELECT path FROM information_schema.innodb_sys_datafiles WHERE path LIKE '%long%'; +--vertical_results +--replace_regex /innodb_file_per_table_[0-9]*/innodb_file_per_table_##/ +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR @0023 # +SELECT file_name, tablespace_name FROM information_schema.files WHERE file_name LIKE '%long%'; +--horizontal_results + +--echo # +--echo # Cleanup +--echo # + +--eval DROP TABLE `$long_name`.`$long_name` +--eval DROP TABLE `test`.`$long_251_byte_table_name` +--eval DROP TABLE `twenty_byte_db_name_`.`$long_251_byte_table_name` +--eval DROP TABLE `$long_db_name`.`$long_250_byte_table_name` +--eval DROP DATABASE `$long_name` +--eval DROP DATABASE `$long_db_name` +DROP DATABASE `twenty_byte_db_name_`; diff --git a/mysql-test/suite/innodb/t/tablespace_per_table_windows.opt b/mysql-test/suite/innodb/t/tablespace_per_table_windows.opt new file mode 100644 index 00000000000..bd6d9db453b --- /dev/null +++ b/mysql-test/suite/innodb/t/tablespace_per_table_windows.opt @@ -0,0 +1,2 @@ +--innodb-sys-tablespaces +--innodb-sys-datafiles diff --git a/mysql-test/suite/innodb/t/tablespace_per_table_windows.test b/mysql-test/suite/innodb/t/tablespace_per_table_windows.test new file mode 100644 index 00000000000..c556a3ed23c --- /dev/null +++ b/mysql-test/suite/innodb/t/tablespace_per_table_windows.test @@ -0,0 +1,79 @@ +--echo # +--echo # Test the limits of a file-per-table tablespace name. MySQL combines +--echo # the database name with the table name to make a unique table name. +--echo # + +# There is no use in testing the maximum expanded filename using "#" or +# some other character that is expanded by MySQL to "@0023" because +# Windows imposes a maximum absolute path length of 260 bytes. So the +# results will depend upon what local directory this test is run in. +# See https://msdn.microsoft.com/en-us/library/aa365247.aspx +# "Maximum Path Length Limitation +# In the Windows API, the maximum length for a path is MAX_PATH, which is +# defined as 260 characters. A local path is structured in the following +# order: drive letter, colon, backslash, name components separated by +# backslashes, and a terminating null character. For example, the maximum +# path on drive D is "D:\some 256-character path string" where +# "" represents the invisible terminating null character for the +# current system codepage. (The characters < > are used here for visual +# clarity and cannot be part of a valid path string.)" + +--source include/have_innodb.inc +--source include/windows.inc +# This will test the limit of a filename in MySQL at 512 bytes. +# We control that by making it a relative path starting with "./". +# The embedded server uses an absolute path as the datadir +# which has a non-deterministic length. +--source include/not_embedded.inc + +SET default_storage_engine=InnoDB; +LET $MYSQLD_DATADIR = `select @@datadir`; + +--echo # +--echo # MySQL limits each database and tablename identifier to 64 characters +--echo # of up to 3 bytes per character, corresponding to 192 bytes. +--echo # +LET $too_long_name = this_sixty_five_byte_name_is_too_long____________________________; +--error ER_WRONG_DB_NAME +--eval CREATE DATABASE `$too_long_name` + +LET $long_name = this_sixty_four_byte_name_is_not_too_long_______________________; +--eval CREATE DATABASE `$long_name` +--eval USE `$long_name` + +--echo # +--echo # A 64 character tablename can be created in a 64 character database name +--echo # +--eval CREATE TABLE `$long_name`.`$long_name` (a SERIAL) + +--echo # +--echo # A 65 character tablename is too long. +--echo # +--error ER_WRONG_TABLE_NAME +--eval CREATE TABLE `test`.`$too_long_name` (a SERIAL) +--error ER_WRONG_TABLE_NAME +--eval CREATE TABLE `$long_name`.`$too_long_name` (a SERIAL) + +--echo # +--echo # Show the successfully created database and table +--echo # +--eval SHOW CREATE TABLE `$long_name`.`$long_name` + +--echo ---- list_files MYSQLD_DATADIR/$long_name +--list_files $MYSQLD_DATADIR/$long_name + +SELECT name FROM information_schema.innodb_sys_tables WHERE name LIKE '%long%'; +SELECT name FROM information_schema.innodb_sys_tablespaces WHERE name LIKE '%long%'; +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +SELECT path FROM information_schema.innodb_sys_datafiles WHERE path LIKE '%long%'; +--vertical_results +--replace_regex /innodb_file_per_table_[0-9]*/innodb_file_per_table_##/ +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +SELECT file_name, tablespace_name FROM information_schema.files WHERE file_name LIKE '%long%'; +--horizontal_results + +--echo # +--echo # Cleanup +--echo # + +--eval DROP DATABASE `$long_name` diff --git a/mysql-test/suite/innodb_fts/r/foreign_key_check.result b/mysql-test/suite/innodb_fts/r/foreign_key_check.result new file mode 100644 index 00000000000..38f46d5ff3c --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/foreign_key_check.result @@ -0,0 +1,27 @@ +CREATE TABLE t1 ( +id INT NOT NULL, +title TEXT, +PRIMARY KEY (id), +FULLTEXT KEY (title), +FOREIGN KEY (id) REFERENCES t2 (id) +) ENGINE=InnoDB; +ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") +CREATE TABLE t1 ( +id INT NOT NULL, +title TEXT, +PRIMARY KEY (id) +) ENGINE=InnoDB; +ALTER TABLE t1 ADD FULLTEXT KEY (title), ADD FOREIGN KEY (id) REFERENCES t2 (id); +ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") +SET FOREIGN_KEY_CHECKS = 0; +ALTER TABLE t1 ADD FULLTEXT KEY (title), ADD FOREIGN KEY (id) REFERENCES t2 (id); +DROP TABLE t1; +CREATE TABLE t1 ( +id INT NOT NULL, +title TEXT, +PRIMARY KEY (id), +FULLTEXT KEY (title), +FOREIGN KEY (id) REFERENCES t2 (id) +) ENGINE=InnoDB; +DROP TABLE t1; +SET FOREIGN_KEY_CHECKS = 1; diff --git a/mysql-test/suite/innodb_fts/r/foreign_key_update.result b/mysql-test/suite/innodb_fts/r/foreign_key_update.result new file mode 100644 index 00000000000..f2d47da78c5 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/foreign_key_update.result @@ -0,0 +1,34 @@ +CREATE TABLE t1 ( +a varchar(40), +KEY a(a) +) ENGINE=InnoDB; +CREATE TABLE t1_fk ( +a varchar(40), +KEY a(a), +FULLTEXT KEY (a), +CONSTRAINT fk FOREIGN KEY (a) REFERENCES t1 (a) ON UPDATE CASCADE +) ENGINE=InnoDB; +INSERT INTO t1 VALUES('mysql'); +INSERT INTO t1_fk VALUES('mysql'); +INSERT INTO t1_fk VALUES('mysql'); +SELECT * FROM t1_fk; +a +mysql +mysql +SELECT * FROM t1_fk WHERE MATCH(a) AGAINST('mysql'); +a +mysql +mysql +UPDATE t1 SET a = 'database' WHERE a = 'mysql'; +SELECT * FROM t1_fk; +a +database +database +SELECT * FROM t1_fk WHERE MATCH(a) AGAINST('mysql'); +a +SELECT * FROM t1_fk WHERE MATCH(a) AGAINST('database'); +a +database +database +DROP TABLE t1_fk; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/r/index_table.result b/mysql-test/suite/innodb_fts/r/index_table.result new file mode 100644 index 00000000000..570e367a7d4 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/index_table.result @@ -0,0 +1,265 @@ +SET @optimize=@@GLOBAL.INNODB_OPTIMIZE_FULLTEXT_ONLY; +SET GLOBAL INNODB_OPTIMIZE_FULLTEXT_ONLY=1; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +content TEXT +) ENGINE= InnoDB; +CREATE FULLTEXT INDEX idx ON articles (title, content); +INSERT INTO articles (title, content) VALUES +('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','How to use full-text search engine'), +('Go MySQL Tricks','How to use full text search engine'); +SET @aux=@@GLOBAL.innodb_ft_aux_table; +SET GLOBAL innodb_ft_aux_table='test/articles'; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +1001 4 4 1 4 0 +after 2 2 1 2 22 +database 1 1 1 1 37 +dbms 1 1 1 1 15 +engine 4 5 2 4 46 +engine 4 5 2 5 44 +full 4 5 2 4 29 +full 4 5 2 5 27 +mysql 1 5 5 1 0 +mysql 1 5 5 1 31 +mysql 1 5 5 2 11 +mysql 1 5 5 3 11 +mysql 1 5 5 4 5 +mysql 1 5 5 5 3 +optimizing 3 3 1 3 0 +search 4 5 2 4 39 +search 4 5 2 5 37 +show 3 3 1 3 42 +stands 1 1 1 1 20 +text 4 5 2 4 34 +text 4 5 2 5 32 +through 2 2 1 2 37 +tricks 4 5 2 4 11 +tricks 4 5 2 5 9 +tutorial 1 3 2 1 6 +tutorial 1 3 2 3 25 +use 2 5 3 2 7 +use 2 5 3 4 25 +use 2 5 3 5 23 +well 2 2 1 2 17 +went 2 2 1 2 32 +you 2 2 1 2 28 +OPTIMIZE TABLE articles; +Table Op Msg_type Msg_text +test.articles optimize status OK +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +1001 4 4 1 4 0 +after 2 2 1 2 22 +database 1 1 1 1 37 +dbms 1 1 1 1 15 +engine 4 5 2 4 46 +engine 4 5 2 5 44 +full 4 5 2 4 29 +full 4 5 2 5 27 +mysql 1 5 5 1 0 +mysql 1 5 5 1 31 +mysql 1 5 5 2 11 +mysql 1 5 5 3 11 +mysql 1 5 5 4 5 +mysql 1 5 5 5 3 +optimizing 3 3 1 3 0 +search 4 5 2 4 39 +search 4 5 2 5 37 +show 3 3 1 3 42 +stands 1 1 1 1 20 +text 4 5 2 4 34 +text 4 5 2 5 32 +through 2 2 1 2 37 +tricks 4 5 2 4 11 +tricks 4 5 2 5 9 +tutorial 1 3 2 1 6 +tutorial 1 3 2 3 25 +use 2 5 3 2 7 +use 2 5 3 4 25 +use 2 5 3 5 23 +well 2 2 1 2 17 +went 2 2 1 2 32 +you 2 2 1 2 28 +SET @save_dbug=@@debug_dbug; +SET debug_dbug='+d,fts_instrument_result_cache_limit'; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +1001 4 4 1 4 0 +after 2 2 1 2 22 +database 1 1 1 1 37 +dbms 1 1 1 1 15 +engine 4 5 2 4 46 +engine 4 5 2 5 44 +full 4 5 2 4 29 +full 4 5 2 5 27 +mysql 1 5 5 1 0 +mysql 1 5 5 1 31 +mysql 1 5 5 2 11 +mysql 1 5 5 3 11 +mysql 1 5 5 4 5 +mysql 1 5 5 5 3 +optimizing 3 3 1 3 0 +search 4 5 2 4 39 +search 4 5 2 5 37 +show 3 3 1 3 42 +stands 1 1 1 1 20 +text 4 5 2 4 34 +text 4 5 2 5 32 +through 2 2 1 2 37 +tricks 4 5 2 4 11 +tricks 4 5 2 5 9 +tutorial 1 3 2 1 6 +tutorial 1 3 2 3 25 +use 2 5 3 2 7 +use 2 5 3 4 25 +use 2 5 3 5 23 +well 2 2 1 2 17 +went 2 2 1 2 32 +you 2 2 1 2 28 +SET debug_dbug=@save_dbug; +DROP TABLE articles; +SET GLOBAL innodb_ft_result_cache_limit=default; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +content TEXT +) ENGINE= InnoDB; +CREATE FULLTEXT INDEX idx_t ON articles (title); +CREATE FULLTEXT INDEX idx_c ON articles (content); +INSERT INTO articles (title, content) VALUES +('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','How to use full-text search engine'), +('Go MySQL Tricks','How to use full text search engine'); +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +SET GLOBAL innodb_ft_aux_table='test/articles'; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +1001 4 4 1 4 0 +mysql 1 5 5 1 0 +mysql 1 5 5 2 11 +mysql 1 5 5 3 11 +mysql 1 5 5 4 5 +mysql 1 5 5 5 3 +optimizing 3 3 1 3 0 +tricks 4 5 2 4 11 +tricks 4 5 2 5 9 +tutorial 1 1 1 1 6 +use 2 2 1 2 7 +well 2 2 1 2 17 +after 2 2 1 2 0 +database 1 1 1 1 22 +dbms 1 1 1 1 0 +engine 4 5 2 4 28 +engine 4 5 2 5 28 +full 4 5 2 4 11 +full 4 5 2 5 11 +mysql 1 1 1 1 16 +search 4 5 2 4 21 +search 4 5 2 5 21 +show 3 3 1 3 25 +stands 1 1 1 1 5 +text 4 5 2 4 16 +text 4 5 2 5 16 +through 2 2 1 2 15 +tutorial 3 3 1 3 8 +use 4 5 2 4 7 +use 4 5 2 5 7 +went 2 2 1 2 10 +you 2 2 1 2 6 +OPTIMIZE TABLE articles; +Table Op Msg_type Msg_text +test.articles optimize status OK +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +1001 4 4 1 4 0 +mysql 1 5 5 1 0 +mysql 1 5 5 2 11 +mysql 1 5 5 3 11 +mysql 1 5 5 4 5 +mysql 1 5 5 5 3 +optimizing 3 3 1 3 0 +tricks 4 5 2 4 11 +tricks 4 5 2 5 9 +tutorial 1 1 1 1 6 +use 2 2 1 2 7 +well 2 2 1 2 17 +after 2 2 1 2 0 +database 1 1 1 1 22 +dbms 1 1 1 1 0 +engine 4 5 2 4 28 +engine 4 5 2 5 28 +full 4 5 2 4 11 +full 4 5 2 5 11 +mysql 1 1 1 1 16 +search 4 5 2 4 21 +search 4 5 2 5 21 +show 3 3 1 3 25 +stands 1 1 1 1 5 +text 4 5 2 4 16 +text 4 5 2 5 16 +through 2 2 1 2 15 +tutorial 3 3 1 3 8 +use 4 5 2 4 7 +use 4 5 2 5 7 +went 2 2 1 2 10 +you 2 2 1 2 6 +DROP TABLE articles; +SET NAMES utf8; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200) +) ENGINE=InnoDB DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; +CREATE FULLTEXT INDEX idx ON articles (title); +INSERT INTO articles (title) VALUES +('相亲相爱'),('怜香惜爱'),('充满å¯çˆ±'),('爱æ¨äº¤ç»‡'); +SET GLOBAL innodb_ft_aux_table="test/articles"; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +充满å¯çˆ± 3 3 1 3 0 +怜香惜爱 2 2 1 2 0 +爱æ¨äº¤ç»‡ 4 4 1 4 0 +相亲相爱 1 1 1 1 0 +OPTIMIZE TABLE articles; +Table Op Msg_type Msg_text +test.articles optimize status OK +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +充满å¯çˆ± 3 3 1 3 0 +怜香惜爱 2 2 1 2 0 +爱æ¨äº¤ç»‡ 4 4 1 4 0 +相亲相爱 1 1 1 1 0 +DROP TABLE articles; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200) +) ENGINE=InnoDB DEFAULT CHARACTER SET gb2312 COLLATE gb2312_chinese_ci; +CREATE FULLTEXT INDEX idx ON articles (title); +INSERT INTO articles (title) VALUES +('相亲相爱'),('怜香惜爱'),('充满å¯çˆ±'),('爱æ¨äº¤ç»‡'); +SET GLOBAL innodb_ft_aux_table="test/articles"; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +爱æ¨äº¤ç»‡ 4 4 1 4 0 +充满å¯çˆ± 3 3 1 3 0 +怜香惜爱 2 2 1 2 0 +相亲相爱 1 1 1 1 0 +OPTIMIZE TABLE articles; +Table Op Msg_type Msg_text +test.articles optimize status OK +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +怜香惜爱 2 2 1 2 0 +充满å¯çˆ± 3 3 1 3 0 +相亲相爱 1 1 1 1 0 +爱æ¨äº¤ç»‡ 4 4 1 4 0 +DROP TABLE articles; +SET GLOBAL innodb_ft_aux_table=@aux; +SET GLOBAL INNODB_OPTIMIZE_FULLTEXT_ONLY=@optimize; diff --git a/mysql-test/suite/innodb_fts/r/innodb_fts_proximity.result b/mysql-test/suite/innodb_fts/r/innodb_fts_proximity.result index d67981e0851..a53fca51c6c 100644 --- a/mysql-test/suite/innodb_fts/r/innodb_fts_proximity.result +++ b/mysql-test/suite/innodb_fts/r/innodb_fts_proximity.result @@ -134,6 +134,7 @@ count(*) 2 DROP TABLE t1; set global innodb_file_per_table=1; +set names utf8; CREATE TABLE t1 ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, a TEXT, @@ -160,7 +161,7 @@ SELECT count(*) FROM t1 WHERE MATCH (a,b,c) AGAINST ('"very blob"@4' IN BOOLEAN MODE); count(*) -4 +5 SELECT count(*) FROM t1 WHERE MATCH (a,b,c) AGAINST ('"interesting blob"@9' IN BOOLEAN MODE); @@ -175,7 +176,7 @@ SELECT COUNT(*) FROM t1 WHERE MATCH (a,b,c) AGAINST ('"very blob"@4 - "interesting blob"@9' IN BOOLEAN MODE); COUNT(*) -3 +4 DROP TABLE t1; CREATE TABLE t1 ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, diff --git a/mysql-test/suite/innodb_fts/r/limit_union.result b/mysql-test/suite/innodb_fts/r/limit_union.result new file mode 100644 index 00000000000..843d55d23e4 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/limit_union.result @@ -0,0 +1,157 @@ +# Bug #22709692 FTS QUERY EXCEEDS RESULT CACHE LIMIT +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body), +FULLTEXT (body))ENGINE=InnoDB; +INSERT INTO articles (title,body) VALUES +('MySQL Tutorial','DBMS stands for DataBase ...'), +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SET @default_cache_size = @@GLOBAL.query_cache_size; +SET GLOBAL query_cache_size=0; +# Query involves Ranking +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('MySQL' IN NATURAL LANGUAGE MODE) LIMIT 1; +id title body +6 MySQL Security When configured properly, MySQL ... +# Without optimization +SET @save_dbug = @@debug_dbug; +SET debug_dbug = '+d,fts_union_limit_off'; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('MySQL' IN NATURAL LANGUAGE MODE) LIMIT 1; +id title body +6 MySQL Security When configured properly, MySQL ... +SET debug_dbug = @save_dbug; +# Query involves No Ranking and fts_union operations +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('MySQL' IN BOOLEAN MODE) limit 1; +id title body +6 MySQL Security When configured properly, MySQL ... +# Without optimization +SET debug_dbug = '+d,fts_union_limit_off'; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('MySQL' IN BOOLEAN MODE) limit 1; +id title body +6 MySQL Security When configured properly, MySQL ... +SET debug_dbug = @save_dbug; +# Query involves No ranking and fts_union, fts_ignore +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('MySQL -YourSQL' IN BOOLEAN MODE) limit 1; +id title body +6 MySQL Security When configured properly, MySQL ... +# Without optimization +SET debug_dbug = '+d,fts_union_limit_off'; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('MySQL -YourSQL' IN BOOLEAN MODE) limit 1; +id title body +6 MySQL Security When configured properly, MySQL ... +SET debug_dbug = @save_dbug; +# Query with fts_intersect +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('MySQL +YourSQL' IN BOOLEAN MODE) limit 1; +id title body +5 MySQL vs. YourSQL In the following database comparison ... +# Without optimization +SET debug_dbug = '+d,fts_union_limit_off'; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('MySQL +YourSQL' IN BOOLEAN MODE) limit 1; +id title body +5 MySQL vs. YourSQL In the following database comparison ... +SET debug_dbug = @save_dbug; +INSERT INTO articles (title,body) VALUES +('MySQL Tutorial','request doc@oraclehelp.com ...'), +('MySQL Tutorial','request support@oraclehelp.com ...'), +('Trial version','query performace @1255 minute on 2.1Hz + Memory 2GB...'), +('when To Use MySQL Well','for free faq mail@xyz.com ...'); +# Query with @distance +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('"MySQL request"@3' IN BOOLEAN MODE) limit 1; +id title body +7 MySQL Tutorial request doc@oraclehelp.com ... +# Without optimization +SET debug_dbug = '+d,fts_union_limit_off'; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('"MySQL request"@3' IN BOOLEAN MODE) limit 1; +id title body +7 MySQL Tutorial request doc@oraclehelp.com ... +SET debug_dbug = @save_dbug; +# Query with subexpression +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('+MySQL +(-support +doc)' IN BOOLEAN MODE) limit 1; +id title body +7 MySQL Tutorial request doc@oraclehelp.com ... +# Without optimization +SET debug_dbug = '+d,fts_union_limit_off'; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('+MySQL +(-support +doc)' IN BOOLEAN MODE) limit 1; +id title body +7 MySQL Tutorial request doc@oraclehelp.com ... +SET debug_dbug = @save_dbug; +# limit num1 OFFSET num2 +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('MySQL' in boolean mode) limit 4 offset 2; +id title body +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +5 MySQL vs. YourSQL In the following database comparison ... +# Without optimization +SET debug_dbug = '+d,fts_union_limit_off'; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('MySQL' in boolean mode) limit 4 offset 2; +id title body +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +5 MySQL vs. YourSQL In the following database comparison ... +SET debug_dbug = @save_dbug; +# wild card search +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('ru*' IN BOOLEAN MODE) limit 1; +id title body +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +# Without optimization +SET debug_dbug = '+d,fts_union_limit_off'; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('ru*' IN BOOLEAN MODE) limit 1; +id title body +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +SET debug_dbug = @save_dbug; +# phrase search +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('"request support"' IN BOOLEAN MODE) limit 1; +id title body +8 MySQL Tutorial request support@oraclehelp.com ... +# Without optimization +SET debug_dbug = '+d,fts_union_limit_off'; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('"request support"' IN BOOLEAN MODE) limit 1; +id title body +8 MySQL Tutorial request support@oraclehelp.com ... +SET debug_dbug = @save_dbug; +DROP TABLE articles; +SET GLOBAL query_cache_size = @default_cache_size; diff --git a/mysql-test/suite/innodb_fts/r/misc.result b/mysql-test/suite/innodb_fts/r/misc.result new file mode 100644 index 00000000000..684996fb748 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/misc.result @@ -0,0 +1,1878 @@ +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +b TEXT +) ENGINE = InnoDB; +INSERT INTO t1 (a,b) VALUES +('MySQL Tutorial','DBMS stands for DataBase ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'); +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `a` varchar(200) DEFAULT NULL, + `b` text DEFAULT NULL, + PRIMARY KEY (`id`), + FULLTEXT KEY `idx` (`a`,`b`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 (a,b) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +id +1 +3 +select id from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE); +id +select id, MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE) as x from t1; +id x +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +select id, MATCH(a,b) AGAINST("collections support" IN BOOLEAN MODE) as x from t1; +id x +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +select id from t1 where MATCH a,b AGAINST ("+call* +coll*" IN BOOLEAN MODE); +id +select id from t1 where MATCH a,b AGAINST ('"support now"' IN BOOLEAN MODE); +id +select id from t1 where MATCH a,b AGAINST ('"Now sUPPort"' IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST ("collections" WITH QUERY EXPANSION); +id +select id from t1 where MATCH(a,b) AGAINST ("indexes" WITH QUERY EXPANSION); +id +select id from t1 where MATCH(a,b) AGAINST ("indexes collections" WITH QUERY EXPANSION); +id +ALTER TABLE t1 DROP INDEX idx; +CREATE FULLTEXT INDEX idx on t1 (a,b); +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +id +1 +3 +select id from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE); +id +select id, MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE) as x from t1; +id x +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +select id, MATCH(a,b) AGAINST("collections support" IN BOOLEAN MODE) as x from t1; +id x +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +select id from t1 where MATCH a,b AGAINST ("+call* +coll*" IN BOOLEAN MODE); +id +select id from t1 where MATCH a,b AGAINST ('"support now"' IN BOOLEAN MODE); +id +select id from t1 where MATCH a,b AGAINST ('"Now sUPPort"' IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST ("collections" WITH QUERY EXPANSION); +id +select id from t1 where MATCH(a,b) AGAINST ("indexes" WITH QUERY EXPANSION); +id +select id from t1 where MATCH(a,b) AGAINST ("indexes collections" WITH QUERY EXPANSION); +id +INSERT INTO t1 (a,b) VALUES ('test query expansion','for database ...'); +INSERT INTO t1 (a,b) VALUES +('test proximity search, test, proximity and phrase', +'search, with proximity innodb'); +INSERT INTO t1 (a,b) VALUES +('test proximity fts search, test, proximity and phrase', +'search, with proximity innodb'); +INSERT INTO t1 (a,b) VALUES +('test more proximity fts search, test, more proximity and phrase', +'search, with proximity innodb'); +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST ('"proximity search"@2' IN BOOLEAN MODE); +id +8 +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST ('"proximity search"@1' IN BOOLEAN MODE); +id +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST ('"proximity search"@3' IN BOOLEAN MODE); +id +8 +9 +10 +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST ('"test proximity"@3' IN BOOLEAN MODE); +id +8 +9 +10 +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST ('"more test proximity"@3' IN BOOLEAN MODE); +id +10 +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST ('"more test proximity"@2' IN BOOLEAN MODE); +id +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST ('"more fts proximity"@02' IN BOOLEAN MODE); +id +DROP TABLE t1; +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +b TEXT +) ENGINE = InnoDB; +CREATE FULLTEXT INDEX idx on t1 (a,b); +INSERT INTO t1 (a,b) VALUES +('MySQL Tutorial','DBMS stands for DataBase ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'); +INSERT INTO t1 (a,b) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +id +1 +3 +SELECT id FROM t1 WHERE id = (SELECT MAX(id) FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE)); +id +3 +SELECT id FROM t1 WHERE id = (SELECT MIN(id) FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE)); +id +1 +SELECT id FROM t1 WHERE id = (SELECT MIN(id) FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE)) OR id = 3 ; +id +1 +3 +SELECT id FROM t1 WHERE CONCAT(t1.a,t1.b) IN ( +SELECT CONCAT(a,b) FROM t1 AS t2 WHERE +MATCH (t2.a,t2.b) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) +) OR t1.id = 3 ; +id +1 +3 +SELECT id FROM t1 WHERE CONCAT(t1.a,t1.b) IN ( +SELECT CONCAT(a,b) FROM t1 AS t2 +WHERE MATCH (t2.a,t2.b) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) +AND t2.id != 3) ; +id +1 +SELECT id FROM t1 WHERE id IN (SELECT MIN(id) FROM t1 WHERE +MATCH (a,b) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE)) OR id = 3 ; +id +1 +3 +SELECT id FROM t1 WHERE id NOT IN (SELECT MIN(id) FROM t1 +WHERE MATCH (a,b) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE)) ; +id +2 +3 +4 +5 +6 +SELECT id FROM t1 WHERE EXISTS (SELECT t2.id FROM t1 AS t2 WHERE +MATCH (t2.a,t2.b) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) +AND t1.id = t2.id) ; +id +1 +3 +SELECT id FROM t1 WHERE NOT EXISTS (SELECT t2.id FROM t1 AS t2 WHERE +MATCH (t2.a,t2.b) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) +AND t1.id = t2.id) ; +id +2 +4 +5 +6 +DROP TABLE t1; +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +b TEXT , +FULLTEXT (a,b) +) ENGINE = InnoDB; +INSERT INTO t1(a,b) VALUES('MySQL has now support', 'for full-text search'), +('Full-text indexes', 'are called collections'), +('Only MyISAM tables','support collections'), +('Function MATCH ... AGAINST()','is used to do a search'), +('Full-text search in MySQL', 'implements vector space model'); +SELECT id FROM t1 WHERE t1.id = (SELECT MAX(t2.id) FROM t1 AS t2 WHERE +MATCH(t2.a,t2.b) AGAINST("+support +collections" IN BOOLEAN MODE)); +id +3 +SELECT id FROM t1 WHERE t1.id != (SELECT MIN(t2.id) FROM t1 AS t2 WHERE +MATCH(t2.a,t2.b) AGAINST("+search" IN BOOLEAN MODE)); +id +2 +3 +4 +5 +SELECT id FROM t1 WHERE t1.id IN (SELECT t2.id FROM t1 AS t2 WHERE +MATCH (t2.a,t2.b) AGAINST ("+call* +coll*" IN BOOLEAN MODE)); +id +2 +SELECT id FROM t1 WHERE EXISTS (SELECT id FROM t1 AS t2 WHERE +MATCH t2.a,t2.b AGAINST ('"Now sUPPort"' IN BOOLEAN MODE) AND t2.id=t1.id); +id +1 +INSERT INTO t1 (a,b) VALUES ('test query expansion','for database ...'); +INSERT INTO t1 (a,b) VALUES +('test proximity search, test, proximity and phrase', +'search, with proximity innodb'); +INSERT INTO t1 (a,b) VALUES +('test proximity fts search, test, proximity and phrase', +'search, with proximity innodb'); +INSERT INTO t1 (a,b) VALUES +('test more proximity fts search, test, more proximity and phrase', +'search, with proximity innodb'); +SELECT id FROM t1 WHERE t1.id = (SELECT MAX(t2.id) FROM t1 AS t2 WHERE +MATCH(t2.a,t2.b) AGAINST ('"proximity search"@2' IN BOOLEAN MODE)); +id +7 +SELECT id FROM t1 WHERE t1.id > (SELECT MIN(t2.id) FROM t1 AS t2 WHERE +MATCH(t2.a,t2.b) AGAINST ('"proximity search"@2' IN BOOLEAN MODE)); +id +8 +9 +SELECT id FROM t1 WHERE t1.id IN (SELECT t2.id FROM t1 AS t2 WHERE +MATCH (t2.a,t2.b) AGAINST ('"proximity search"@2' IN BOOLEAN MODE)); +id +7 +SELECT id FROM t1 WHERE EXISTS (SELECT id FROM t1 AS t2 WHERE +MATCH t2.a,t2.b AGAINST ('"proximity search"@2' IN BOOLEAN MODE) +AND t2.id=t1.id); +id +7 +SELECT id FROM t1 WHERE EXISTS (SELECT id FROM t1 AS t2 WHERE +MATCH t2.a,t2.b AGAINST ('"more test proximity"@3' IN BOOLEAN MODE) +AND t2.id=t1.id); +id +9 +SELECT id FROM t1 WHERE EXISTS (SELECT id FROM t1 AS t2 WHERE +MATCH t2.a,t2.b AGAINST ('"more test proximity"@2' IN BOOLEAN MODE) +AND t2.id=t1.id); +id +CREATE TABLE t2 ENGINE = InnoDB AS SELECT id FROM t1 WHERE +MATCH a,b AGAINST ('support') ; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `id` int(10) unsigned NOT NULL DEFAULT 0 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT id FROM t2; +id +1 +3 +DROP TABLE t2; +CREATE TABLE t2 ENGINE = InnoDB AS SELECT id FROM t1 WHERE +MATCH a,b AGAINST("+support +collections" IN BOOLEAN MODE); +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `id` int(10) unsigned NOT NULL DEFAULT 0 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT id FROM t2; +id +3 +DROP TABLE t2; +CREATE TABLE t2 ENGINE = InnoDB AS SELECT id FROM t1 WHERE +MATCH a,b AGAINST ('"proximity search"@10' IN BOOLEAN MODE); +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `id` int(10) unsigned NOT NULL DEFAULT 0 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT id FROM t2; +id +7 +8 +9 +DROP TABLE t2; +DROP TABLE t1; +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +b TEXT +) ENGINE = InnoDB; +CREATE FULLTEXT INDEX idx on t1 (a,b); +INSERT INTO t1 (a,b) VALUES +('MySQL from Tutorial','DBMS stands for DataBase ...'); +INSERT INTO t1 (a,b) VALUES +('when To Use MySQL Well','After that you went through a ...'); +INSERT INTO t1 (a,b) VALUES +('where will Optimizing MySQL','what In this tutorial we will show ...'); +INSERT INTO t1 (a,b) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL null...'); +SELECT COUNT(*) FROM t1; +COUNT(*) +106 +SELECT COUNT(*) FROM t1 WHERE a IS NULL; +COUNT(*) +100 +SELECT COUNT(*) FROM t1 WHERE b IS NOT NULL; +COUNT(*) +6 +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +id +1 +103 +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST (NULL IN NATURAL LANGUAGE MODE); +id +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST (NULL WITH QUERY EXPANSION); +id +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST ('null' IN NATURAL LANGUAGE MODE); +id +106 +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE); +id +106 +1 +52 +103 +104 +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE) AND (a IS NOT NULL OR b IS NOT NULL); +id +106 +1 +52 +103 +104 +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE) AND (a IS NULL AND b IS NOT NULL); +id +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('DBMS Security' IN BOOLEAN MODE); +id +1 +106 +SELECT COUNT(*) FROM t1 +WHERE MATCH (a,b) +AGAINST ('database' WITH QUERY EXPANSION); +COUNT(*) +6 +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST ('"following database"@10' IN BOOLEAN MODE); +id +105 +DROP TABLE t1; +drop table if exists t50; +set names utf8; +"----------Test1---------" +create table t50 (s1 varchar(60) character set utf8 collate utf8_bin) engine = innodb; +create fulltext index i on t50 (s1); +insert into t50 values ('ABCDE'),('FGHIJ'),('KLMNO'),('VÃÆ·Wİ'); +select * from t50 where match(s1) against ('VÃÆ·Wİ'); +s1 +VÃÆ·Wİ +drop table t50; +"----------Test2---------" +create table t50 (s1 int unsigned primary key auto_increment, s2 +varchar(60) character set utf8) engine = innodb; +create fulltext index i on t50 (s2); +insert into t50 (s2) values ('FGHIJ'),('KLMNO'),('VÃÆ·Wİ'),('ABCDE'); +select * from t50 order by s2; +s1 s2 +4 ABCDE +1 FGHIJ +2 KLMNO +3 VÃÆ·Wİ +drop table t50; +"----------Test3---------" +create table t50 (id int unsigned primary key auto_increment, s2 +varchar(60) character set utf8) engine = innodb; +create fulltext index i on t50 (s2); +insert into t50 (s2) values ('FGHIJ'),('KLMNO'),('VÃÆ·Wİ'),('ABCDE'); +set @@autocommit=0; +update t50 set s2 = lower(s2); +update t50 set s2 = upper(s2); +commit; +select * from t50 where match(s2) against ('VÃÆ·Wİ FGHIJ KLMNO ABCDE' in boolean mode); +id s2 +1 FGHIJ +2 KLMNO +3 VÃÆ·WI +4 ABCDE +select * from t50; +id s2 +1 FGHIJ +2 KLMNO +3 VÃÆ·WI +4 ABCDE +drop table t50; +set @@autocommit=1; +"----------Test4---------" +create table t50 (id int unsigned primary key auto_increment, s2 +varchar(60) character set utf8) engine = innodb; +create fulltext index i on t50 (s2); +insert into t50 (s2) values ('FGHIJ'),('KLMNO'),('VÃÆ·Wİ'),('ABCD*'); +select * from t50 where match(s2) against ('abcd*' in natural language +mode); +id s2 +4 ABCD* +select * from t50 where match(s2) against ('abcd*' in boolean mode); +id s2 +4 ABCD* +drop table t50; +"----------Test5---------" +create table t50 (s1 int, s2 varchar(200), fulltext key(s2)) engine = innodb; +set @@autocommit=0; +insert into t50 values (1,'Sunshine'),(2,'Lollipops'); +select * from t50 where match(s2) against('Rainbows'); +s1 s2 +rollback; +select * from t50; +s1 s2 +drop table t50; +set @@autocommit=1; +"----------Test6---------" +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +b TEXT +) ENGINE = InnoDB; +INSERT INTO t1 (a,b) VALUES +('aab` MySQL Tutorial','DBMS stands for DataBase ...') , +('aas How To Use MySQL Well','After you went through a ...'), +('aac Optimizing MySQL','In this tutorial we will show ...'); +INSERT INTO t1 (a,b) VALUES +('aac 1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('aab MySQL vs. YourSQL','In the following database comparison ...'), +('aaa MySQL Security','When configured properly, MySQL ...'); +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); +SELECT * FROM t1 ORDER BY MATCH(a,b) AGAINST ('aac') DESC; +id a b +3 aac Optimizing MySQL In this tutorial we will show ... +4 aac 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +1 aab` MySQL Tutorial DBMS stands for DataBase ... +2 aas How To Use MySQL Well After you went through a ... +5 aab MySQL vs. YourSQL In the following database comparison ... +6 aaa MySQL Security When configured properly, MySQL ... +SELECT * FROM t1 ORDER BY MATCH(a,b) AGAINST ('aab') DESC; +id a b +1 aab` MySQL Tutorial DBMS stands for DataBase ... +5 aab MySQL vs. YourSQL In the following database comparison ... +2 aas How To Use MySQL Well After you went through a ... +3 aac Optimizing MySQL In this tutorial we will show ... +4 aac 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +6 aaa MySQL Security When configured properly, MySQL ... +"----------Test7---------" +select * from t1 where match(a,b) against ('aaa') +union select * from t1 where match(a,b) against ('aab') +union select * from t1 where match(a,b) against ('aac'); +id a b +6 aaa MySQL Security When configured properly, MySQL ... +1 aab` MySQL Tutorial DBMS stands for DataBase ... +5 aab MySQL vs. YourSQL In the following database comparison ... +3 aac Optimizing MySQL In this tutorial we will show ... +4 aac 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +select * from t1 where match(a,b) against ('aaa') +or match(a,b) against ('aab') +or match(a,b) against ('aac'); +id a b +1 aab` MySQL Tutorial DBMS stands for DataBase ... +3 aac Optimizing MySQL In this tutorial we will show ... +4 aac 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +5 aab MySQL vs. YourSQL In the following database comparison ... +6 aaa MySQL Security When configured properly, MySQL ... +DROP TABLE t1; +"----------Test8---------" +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +b TEXT +) ENGINE = InnoDB; +INSERT INTO t1 (a,b) VALUES +('MySQL Tutorial','DBMS stands for DataBase ... abcd') , +('How To Use MySQL Well','After you went through a q ...abdd'), +('Optimizing MySQL','In this tutorial we will show ...abed'); +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `a` varchar(200) DEFAULT NULL, + `b` text DEFAULT NULL, + PRIMARY KEY (`id`), + FULLTEXT KEY `idx` (`a`,`b`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 (a,b) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. q ...'), +('MySQL vs. YourSQL use','In the following database comparison ...'), +('MySQL Security','When run configured properly, MySQL ...'); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('run'); +id a b +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. q ... +6 MySQL Security When run configured properly, MySQL ... +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('use'); +id a b +2 How To Use MySQL Well After you went through a q ...abdd +5 MySQL vs. YourSQL use In the following database comparison ... +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('went'); +id a b +2 How To Use MySQL Well After you went through a q ...abdd +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('run') AND NOT MATCH(a,b) AGAINST ('q'); +id a b +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. q ... +6 MySQL Security When run configured properly, MySQL ... +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('use') AND NOT MATCH(a,b) AGAINST ('q'); +id a b +2 How To Use MySQL Well After you went through a q ...abdd +5 MySQL vs. YourSQL use In the following database comparison ... +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('went') AND NOT MATCH(a,b) AGAINST ('q'); +id a b +2 How To Use MySQL Well After you went through a q ...abdd +"----------Test9---------" +CREATE TABLE t2 AS SELECT * FROM t1; +ALTER TABLE t2 ENGINE=MYISAM; +CREATE FULLTEXT INDEX i ON t2 (a,b); +SET @x = (SELECT COUNT(*) FROM t1 WHERE MATCH(a,b) AGAINST ('run')); +SET @x = @x + (SELECT COUNT(*) FROM t1 WHERE MATCH(a,b) AGAINST ('use')); +SET @x = @x + (SELECT COUNT(*) FROM t1 WHERE MATCH(a,b) AGAINST ('went')); +SET @x = @x + (SELECT COUNT(*) FROM t1 WHERE MATCH(a,b) AGAINST ('run')); +SET @x2 = (SELECT COUNT(*) FROM t2 WHERE MATCH(a,b) AGAINST ('run')); +SET @x2 = @x2 + (SELECT COUNT(*) FROM t2 WHERE MATCH(a,b) AGAINST ('use')); +SET @x2 = @x2 + (SELECT COUNT(*) FROM t2 WHERE MATCH(a,b) AGAINST ('went')); +SET @x2 = @x2 + (SELECT COUNT(*) FROM t2 WHERE MATCH(a,b) AGAINST ('run')); +SELECT @x, @x2; +@x @x2 +7 0 +DROP TABLE t2; +"----------Test10---------" +CREATE TABLE t2 AS SELECT * FROM t1; +ALTER TABLE t2 ENGINE=MYISAM; +CREATE FULLTEXT INDEX i ON t2 (a,b); +SELECT COUNT(*) FROM t2 WHERE MATCH(a,b) AGAINST ('abc*' IN BOOLEAN MODE); +COUNT(*) +1 +SELECT COUNT(*) FROM t1 WHERE MATCH(a,b) AGAINST ('abc*' IN BOOLEAN MODE); +COUNT(*) +1 +DROP TABLE t2; +"----------Test11---------" +CREATE TABLE t2 AS SELECT * FROM t1; +ALTER TABLE t2 ENGINE = MYISAM; +CREATE FULLTEXT INDEX i ON t2 (a,b); +ALTER TABLE t2 ENGINE=InnoDB; +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('run'); +id a b +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. q ... +6 MySQL Security When run configured properly, MySQL ... +SELECT COUNT(*) FROM t2 WHERE MATCH(a,b) AGAINST ('abc*' IN BOOLEAN MODE); +COUNT(*) +1 +DROP TABLE t2,t1; +"----------Test13---------" +set names utf8; +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200) CHARACTER SET UTF8 COLLATE UTF8_SPANISH_CI) ENGINE = InnoDB; +CREATE FULLTEXT INDEX i ON t1 (s2); +INSERT INTO t1 VALUES (1,'aaCen'),(2,'aaCha'),(3,'aaCio'),(4,'aaçen'),(5,'aaçha'),(6,'aaçio'); +SELECT * FROM t1 WHERE MATCH(s2) AGAINST ('aach*' IN BOOLEAN MODE); +s1 s2 +2 aaCha +5 aaçha +SELECT * FROM t1 WHERE MATCH(s2) AGAINST ('aaC*' IN BOOLEAN MODE); +s1 s2 +1 aaCen +2 aaCha +3 aaCio +4 aaçen +5 aaçha +6 aaçio +DROP TABLE t1; +"----------Test14---------" +CREATE TABLE t1(s1 INT , s2 VARCHAR(100) CHARACTER SET sjis) ENGINE = InnoDB; +CREATE FULLTEXT INDEX i ON t1 (s2); +INSERT INTO t1 VALUES (1,'ペペペ'),(2,'テテテ'),(3,'ルルル'),(4,'ã‚°ã‚°ã‚°'); +DROP TABLE t1; +"----------Test15---------" +CREATE TABLE t1 (s1 VARCHAR (60) CHARACTER SET UTF8 COLLATE UTF8_UNICODE_520_CI) ENGINE = MyISAM; +CREATE FULLTEXT INDEX i ON t1 (s1); +INSERT INTO t1 VALUES +('a'),('b'),('c'),('d'),('ÅÅÅÅ'),('LLLL'),(NULL),('ÅÅÅÅ ÅÅÅÅ'),('LLLLLLLL'); +SELECT * FROM t1 WHERE MATCH(s1) AGAINST ('LLLL' COLLATE UTF8_UNICODE_520_CI); +s1 +ÅÅÅÅ +LLLL +ÅÅÅÅ ÅÅÅÅ +DROP TABLE if EXISTS t2; +Warnings: +Note 1051 Unknown table 'test.t2' +CREATE TABLE t2 (s1 VARCHAR(60) CHARACTER SET UTF8 COLLATE UTF8_POLISH_CI) ENGINE = InnoDB; +CREATE FULLTEXT INDEX i ON t2 ( s1); +INSERT INTO t2 VALUES +('a'),('b'),('c'),('d'),('ÅÅÅÅ'),('LLLL'),(NULL),('ÅÅÅÅ ÅÅÅÅ'),('LLLLLLLL'); +SELECT * FROM t2 WHERE MATCH(s1) AGAINST ('LLLL' COLLATE UTF8_UNICODE_520_CI); +s1 +LLLL +DROP TABLE t1,t2; +"----------Test16---------" +CREATE TABLE t1 (s1 INT, s2 VARCHAR(50) CHARACTER SET UTF8) ENGINE = InnoDB; +CREATE FULLTEXT INDEX i ON t1(s2); +INSERT INTO t1 VALUES (2, 'ÄŸÄ— DaÅ›i p '); +SELECT * FROM t1 WHERE MATCH(s2) AGAINST ('+p +"ÄŸÄ— DaÅ›i*"' IN BOOLEAN MODE); +s1 s2 +DROP TABLE t1; +"----------Test19---------" +CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF8) ENGINE = InnoDB; +INSERT INTO t1 VALUES (1,'İóëɠ'); +CREATE FULLTEXT INDEX i ON t1 (char_column); +SELECT * FROM t1 WHERE MATCH(char_column) AGAINST ('"İóëɠ"' IN BOOLEAN MODE); +id char_column +1 İóëɠ +DROP TABLE t1; +"----------Test20---------" +CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF32, char_column2 VARCHAR(60) character set utf8) ENGINE = InnoDB; +INSERT INTO t1 (char_column) VALUES ('abcde'),('fghij'),('klmno'),('qrstu'); +UPDATE t1 SET char_column2 = char_column; +CREATE FULLTEXT INDEX i ON t1 (char_column2); +SELECT * FROM t1 WHERE MATCH(char_column) AGAINST ('abc*' IN BOOLEAN MODE); +ERROR HY000: Can't find FULLTEXT index matching the column list +DROP TABLE t1; +"----------Test22---------" +CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF8) ENGINE = InnoDB; +INSERT INTO t1 VALUES (1,'aaa'),(2,'bbb'),(3,'ccc'); +CREATE FULLTEXT INDEX i ON t1 (char_column); +HANDLER t1 OPEN; +HANDLER t1 READ i = ('aaa'); +ERROR HY000: FULLTEXT index `i` does not support this operation +DROP TABLE t1; +"----------Test25---------" +CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF8 COLLATE UTF8_CROATIAN_CI) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,'LJin'),(2,'ljin'),(3,'lmin'),(4,'LJLJLJLJLJ'); +CREATE FULLTEXT INDEX i ON t1 (char_column); +SELECT count(*) FROM t1 WHERE MATCH (char_column) AGAINST ('lj*' IN BOOLEAN MODE); +count(*) +3 +DROP TABLE t1; +"----------Test27---------" +CREATE TABLE t1 (id INT,char_column VARCHAR(60)) ENGINE=InnoDB; +SET @@autocommit=0; +CREATE FULLTEXT INDEX i ON t1 (char_column); +INSERT INTO t1 values (1,'aaa'); +"restart server..." +# Restart the server +--source include/restart_mysqld.inc +DELETE FROM t1 WHERE MATCH(char_column) AGAINST ('bbb') +SET @@autocommit=1; +DROP TABLE t1; +"----------Test28---------" +drop table if exists `fts_test`; +Warnings: +Note 1051 Unknown table 'test.fts_test' +create table `fts_test`(`a` text,fulltext key(`a`))engine=innodb; +set session autocommit=0; +insert into `fts_test` values (''); +savepoint `b`; +savepoint `b`; +set session autocommit=1; +DROP TABLE fts_test; +"----------Test29---------" +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles (title,body) VALUES +('MySQL Tutorial','DBMS stands for DataBase ...'); +start transaction; +INSERT INTO articles (title,body) VALUES +('How To Use MySQL Well','After you went through a ...'); +savepoint `a1`; +INSERT INTO articles (title,body) VALUES +('Optimizing MySQL','In this tutorial we will show ...'); +savepoint `a2`; +INSERT INTO articles (title,body) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'); +savepoint `a3`; +INSERT INTO articles (title,body) VALUES +('MySQL vs. YourSQL','In the following database comparison ...'); +savepoint `a4`; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('Database' IN NATURAL LANGUAGE MODE); +id title body +1 MySQL Tutorial DBMS stands for DataBase ... +rollback to savepoint a3; +select title, body from articles; +title body +MySQL Tutorial DBMS stands for DataBase ... +How To Use MySQL Well After you went through a ... +Optimizing MySQL In this tutorial we will show ... +1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +INSERT INTO articles (title,body) VALUES +('MySQL Security','When configured properly, MySQL ...'); +savepoint `a5`; +select title, body from articles; +title body +MySQL Tutorial DBMS stands for DataBase ... +How To Use MySQL Well After you went through a ... +Optimizing MySQL In this tutorial we will show ... +1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +MySQL Security When configured properly, MySQL ... +rollback to savepoint a2; +select title, body from articles; +title body +MySQL Tutorial DBMS stands for DataBase ... +How To Use MySQL Well After you went through a ... +Optimizing MySQL In this tutorial we will show ... +commit; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('Database' IN NATURAL LANGUAGE MODE); +id title body +1 MySQL Tutorial DBMS stands for DataBase ... +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +id title body +1 MySQL Tutorial DBMS stands for DataBase ... +3 Optimizing MySQL In this tutorial we will show ... +DROP TABLE articles; +"----------Test30---------" +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles (title,body) VALUES +('MySQL Tutorial','DBMS stands for DataBase ...'); +start transaction; +INSERT INTO articles (title,body) VALUES +('How To Use MySQL Well','After you went through a ...'); +savepoint `a1`; +INSERT INTO articles (title,body) VALUES +('Optimizing MySQL','In this tutorial we will show ...'); +savepoint `a2`; +INSERT INTO articles (title,body) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'); +savepoint `a3`; +INSERT INTO articles (title,body) VALUES +('MySQL vs. YourSQL','In the following database comparison ...'); +savepoint `a4`; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('Database' IN NATURAL LANGUAGE MODE); +id title body +1 MySQL Tutorial DBMS stands for DataBase ... +rollback to savepoint a3; +select title, body from articles; +title body +MySQL Tutorial DBMS stands for DataBase ... +How To Use MySQL Well After you went through a ... +Optimizing MySQL In this tutorial we will show ... +1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +INSERT INTO articles (title,body) VALUES +('MySQL Security','When configured properly, MySQL ...'); +savepoint `a5`; +select title, body from articles; +title body +MySQL Tutorial DBMS stands for DataBase ... +How To Use MySQL Well After you went through a ... +Optimizing MySQL In this tutorial we will show ... +1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +MySQL Security When configured properly, MySQL ... +rollback to savepoint a2; +select title, body from articles; +title body +MySQL Tutorial DBMS stands for DataBase ... +How To Use MySQL Well After you went through a ... +Optimizing MySQL In this tutorial we will show ... +rollback; +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('Database' IN NATURAL LANGUAGE MODE); +id title body +1 MySQL Tutorial DBMS stands for DataBase ... +SELECT * FROM articles +WHERE MATCH (title,body) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +id title body +1 MySQL Tutorial DBMS stands for DataBase ... +DROP TABLE articles; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles (title,body) VALUES +('MySQL Tutorial','DBMS stands for DataBase ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +ANALYZE TABLE articles; +SELECT *, MATCH(title, body) AGAINST ('-database +MySQL' IN BOOLEAN MODE) AS score from articles; +id title body score +1 MySQL Tutorial DBMS stands for DataBase ... 0 +2 How To Use MySQL Well After you went through a ... 0.000000001885928302414186 +3 Optimizing MySQL In this tutorial we will show ... 0.000000001885928302414186 +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... 0.000000001885928302414186 +5 MySQL vs. YourSQL In the following database comparison ... 0 +6 MySQL Security When configured properly, MySQL ... 0.000000003771856604828372 +SELECT *, MATCH(title, body) AGAINST ('+MySQL -database' IN BOOLEAN MODE) AS score FROM articles; +id title body score +1 MySQL Tutorial DBMS stands for DataBase ... 0 +2 How To Use MySQL Well After you went through a ... 0.000000001885928302414186 +3 Optimizing MySQL In this tutorial we will show ... 0.000000001885928302414186 +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... 0.000000001885928302414186 +5 MySQL vs. YourSQL In the following database comparison ... 0 +6 MySQL Security When configured properly, MySQL ... 0.000000003771856604828372 +SELECT * FROM articles where MATCH(title, body) AGAINST ('MySQL - (database - tutorial)' IN BOOLEAN MODE); +id title body +6 MySQL Security When configured properly, MySQL ... +1 MySQL Tutorial DBMS stands for DataBase ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +SELECT * FROM articles where MATCH(title, body) AGAINST ('MySQL - (- tutorial database)' IN BOOLEAN MODE); +id title body +6 MySQL Security When configured properly, MySQL ... +1 MySQL Tutorial DBMS stands for DataBase ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +SELECT * FROM articles where MATCH(title, body) AGAINST ('MySQL - (- tutorial database) -Tricks' IN BOOLEAN MODE); +id title body +6 MySQL Security When configured properly, MySQL ... +1 MySQL Tutorial DBMS stands for DataBase ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM articles where MATCH(title, body) AGAINST ('-Tricks MySQL - (- tutorial database)' IN BOOLEAN MODE); +id title body +6 MySQL Security When configured properly, MySQL ... +1 MySQL Tutorial DBMS stands for DataBase ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +DROP TABLE articles; +drop table if exists t1; +Warnings: +Note 1051 Unknown table 'test.t1' +create table t1 (FTS_DOC_ID bigint unsigned auto_increment not null primary key, +title varchar(200),body text,fulltext(title,body)) engine=innodb; +insert into t1 set body='test'; +select * from t1 where match(title,body) against('%test'); +FTS_DOC_ID title body +1 NULL test +select * from t1 where match(title,body) against('%'); +FTS_DOC_ID title body +select * from t1 where match(title,body) against('%%%%'); +FTS_DOC_ID title body +drop table t1; +CREATE DATABASE `benu database`; +USE `benu database`; +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +b TEXT +) ENGINE = InnoDB; +INSERT INTO t1 (a,b) VALUES +('MySQL Tutorial','DBMS stands for DataBase ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'); +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `a` varchar(200) DEFAULT NULL, + `b` text DEFAULT NULL, + PRIMARY KEY (`id`), + FULLTEXT KEY `idx` (`a`,`b`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 (a,b) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +id +1 +3 +select id from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE); +id +select id, MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE) as x from t1; +id x +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +select id, MATCH(a,b) AGAINST("collections support" IN BOOLEAN MODE) as x from t1; +id x +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +select id from t1 where MATCH a,b AGAINST ("+call* +coll*" IN BOOLEAN MODE); +id +select id from t1 where MATCH a,b AGAINST ('"support now"' IN BOOLEAN MODE); +id +select id from t1 where MATCH a,b AGAINST ('"Now sUPPort"' IN BOOLEAN MODE); +id +DROP DATABASE `benu database`; +USE test; +CREATE TABLE `t21` (`a` text, `b` int not null, +fulltext key (`a`), fulltext key (`a`) +) ENGINE=INNODB DEFAULT CHARSET=LATIN1; +Warnings: +Note 1831 Duplicate index `a_2`. This is deprecated and will be disallowed in a future release +ALTER TABLE `t21` ADD UNIQUE INDEX (`b`), ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try ALGORITHM=COPY +ALTER TABLE `t21` ADD UNIQUE INDEX (`b`); +DROP TABLE t21; +CREATE TABLE `t21` (`a` text, `b` int not null, +fulltext key (`a`)) ENGINE=INNODB DEFAULT CHARSET=LATIN1; +ALTER TABLE `t21` ADD UNIQUE INDEX (`b`); +DROP TABLE t21; +CREATE TABLE t1 ( +id INT NOT NULL, +a VARCHAR(200), +b TEXT +) ENGINE = InnoDB; +INSERT INTO t1 VALUES +(1, 'MySQL Tutorial','DBMS stands for DataBase ...') , +(2, 'How To Use MySQL Well','After you went through a ...'), +(3, 'Optimizing MySQL','In this tutorial we will show ...'); +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); +ALTER TABLE t1 ADD UNIQUE INDEX (`id`); +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +id +1 +3 +select id from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE); +id +select id, MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE) as x from t1; +id x +1 0 +2 0 +3 0 +DROP TABLE t1; +CREATE TABLE t1 ( +id INT NOT NULL, +a VARCHAR(200), +b TEXT +) ENGINE = InnoDB; +INSERT INTO t1 VALUES +(1, 'MySQL Tutorial','DBMS stands for DataBase ...') , +(2, 'How To Use MySQL Well','After you went through a ...'), +(3, 'Optimizing MySQL','In this tutorial we will show ...'); +ALTER TABLE t1 ADD UNIQUE INDEX (`id`), ADD FULLTEXT INDEX idx (a,b); +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +id +1 +3 +select id from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE); +id +select id from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE); +id +DROP TABLE t1; +CREATE TABLE t1 ( +FTS_DOC_ID BIGINT UNSIGNED NOT NULL, +a VARCHAR(200), +b TEXT +) ENGINE = InnoDB; +INSERT INTO t1 VALUES +(1, 'MySQL Tutorial','DBMS stands for DataBase ...') , +(2, 'How To Use MySQL Well','After you went through a ...'), +(3, 'Optimizing MySQL','In this tutorial we will show ...'); +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); +ALTER TABLE t1 ADD UNIQUE INDEX (`FTS_DOC_ID`); +SELECT FTS_DOC_ID FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +FTS_DOC_ID +1 +3 +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE); +FTS_DOC_ID +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE); +FTS_DOC_ID +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE); +FTS_DOC_ID +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE); +FTS_DOC_ID +select FTS_DOC_ID, MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE) as x from t1; +FTS_DOC_ID x +1 0 +2 0 +3 0 +DROP TABLE t1; +CREATE TABLE t1 ( +FTS_DOC_ID BIGINT UNSIGNED NOT NULL, +a VARCHAR(200), +b TEXT +) ENGINE = InnoDB; +INSERT INTO t1 VALUES +(1, 'MySQL Tutorial','DBMS stands for DataBase ...') , +(2, 'How To Use MySQL Well','After you went through a ...'), +(3, 'Optimizing MySQL','In this tutorial we will show ...'); +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b), ADD UNIQUE INDEX FTS_DOC_ID_INDEX (FTS_DOC_ID); +SELECT FTS_DOC_ID FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +FTS_DOC_ID +1 +3 +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE); +FTS_DOC_ID +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE); +FTS_DOC_ID +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE); +FTS_DOC_ID +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE); +FTS_DOC_ID +select FTS_DOC_ID, MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE) as x from t1; +FTS_DOC_ID x +1 0 +2 0 +3 0 +DROP TABLE t1; +CREATE TABLE t2 (`b` char(2),fulltext(`b`)) ENGINE=INNODB +DEFAULT CHARSET=LATIN1; +CREATE TABLE t3 LIKE t2; +INSERT INTO `t2` VALUES(); +COMMIT WORK AND CHAIN; +INSERT INTO `t3` VALUES (); +UPDATE `t2` SET `b` = 'a'; +SAVEPOINT BATCH1; +DROP TABLE t2; +DROP TABLE t3; +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +b TEXT +) ENGINE = InnoDB; +INSERT INTO t1 (a,b) VALUES +('MySQL Tutorial','DBMS stands for DataBase ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'); +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); +COMMIT WORK AND CHAIN; +INSERT INTO t1 (a,b) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SAVEPOINT BATCH1; +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('MySQL' IN NATURAL LANGUAGE MODE); +id +1 +2 +3 +INSERT INTO t1 (a,b) VALUES +('1002 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +ROLLBACK TO SAVEPOINT BATCH1; +COMMIT; +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('MySQL' IN NATURAL LANGUAGE MODE); +id +6 +1 +2 +3 +4 +5 +DROP TABLE t1; +CREATE TABLE `t` (`a` char(20) character set utf8 default null, +fulltext key (`a`)) ENGINE=INNODB; +INSERT INTO `t` VALUES ('a'); +INSERT INTO `t` VALUES ('aaa'); +SELECT MATCH(`a`) AGAINST (0x22dd22) FROM `t`; +MATCH(`a`) AGAINST (0x22dd22) +0 +0 +SELECT MATCH(`a`) AGAINST (0x2222) FROM `t`; +MATCH(`a`) AGAINST (0x2222) +0 +0 +SELECT MATCH(`a`) AGAINST (0x22) FROM `t`; +MATCH(`a`) AGAINST (0x22) +0 +0 +SELECT MATCH(`a`) AGAINST (0x2261616122) FROM `t`; +MATCH(`a`) AGAINST (0x2261616122) +0 +0.0906190574169159 +SELECT MATCH(`a`) AGAINST (0x2261dd6122) FROM `t`; +MATCH(`a`) AGAINST (0x2261dd6122) +0 +0 +SELECT MATCH(`a`) AGAINST (0x2261dd612222226122) FROM `t`; +MATCH(`a`) AGAINST (0x2261dd612222226122) +0 +0 +DROP TABLE t; +CREATE TABLE t(a CHAR(1),FULLTEXT KEY(a)) ENGINE=INNODB; +HANDLER t OPEN; +HANDLER t READ a NEXT; +a +HANDLER t READ a PREV; +a +DROP TABLE t; +CREATE TABLE `%`(a TEXT, FULLTEXT INDEX(a)) ENGINE=INNODB; +CREATE TABLE `A B`(a TEXT, FULLTEXT INDEX(a)) ENGINE=INNODB; +DROP TABLE `%`; +DROP TABLE `A B`; +CREATE TABLE `t-26`(a VARCHAR(10),FULLTEXT KEY(a)) ENGINE=INNODB; +INSERT INTO `t-26` VALUES('117'); +DROP TABLE `t-26`; +CREATE TABLE `t1` ( +`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, +`content` TEXT NOT NULL, +PRIMARY KEY (`id`), +FULLTEXT INDEX `IDX_CONTEXT_FULLTEXT`(`content`) +) +ENGINE = InnoDB; +insert into t1 (content) +values +('This is a story which has has a complicated phrase structure here in the +middle'), +('This is a story which doesn''t have that text'), +('This is a story that has complicated the phrase structure'); +select * from t1 +where match(content) against('"complicated phrase structure"' in boolean +mode); +id content +1 This is a story which has has a complicated phrase structure here in the +middle +select * from t1 +where match(content) against('+"complicated phrase structure"' in boolean +mode); +id content +1 This is a story which has has a complicated phrase structure here in the +middle +select * from t1 +where match(content) against('"complicated the phrase structure"' in boolean +mode); +id content +3 This is a story that has complicated the phrase structure +select * from t1 where match(content) against('+"this is a story which" +"complicated the phrase structure"' in boolean mode); +id content +select * from t1 where match(content) against('"the complicated the phrase structure"' in boolean mode); +id content +3 This is a story that has complicated the phrase structure +select * from t1 where match(content) against('"complicated a phrase structure"' in boolean mode); +id content +DROP TABLE t1; +CREATE TABLE my (id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, +c VARCHAR(32), FULLTEXT(c)) ENGINE = INNODB; +INSERT INTO my (c) VALUES ('green-iguana'); +SELECT * FROM my WHERE MATCH(c) AGAINST ('green-iguana'); +id c +1 green-iguana +DROP TABLE my; +CREATE TABLE ift ( +`a` int(11) NOT NULL, +`b` text, +PRIMARY KEY (`a`), +FULLTEXT KEY `b` (`b`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO ift values (1, "skip"); +INSERT INTO ift values (2, "skip and networking"); +INSERT INTO ift values (3, "--skip-networking"); +INSERT INTO ift values (4, "-donot--skip-networking"); +SELECT * FROM ift WHERE MATCH (b) AGAINST ('--skip-networking'); +a b +2 skip and networking +3 --skip-networking +4 -donot--skip-networking +1 skip +SELECT * FROM ift WHERE MATCH (b) AGAINST ('skip-networking'); +a b +2 skip and networking +3 --skip-networking +4 -donot--skip-networking +1 skip +SELECT * FROM ift WHERE MATCH (b) AGAINST ('----'); +a b +SELECT * FROM ift WHERE MATCH (b) AGAINST ('-donot--skip-networking'); +a b +4 -donot--skip-networking +2 skip and networking +3 --skip-networking +1 skip +DROP TABLE ift; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles (title,body) VALUES +('MySQL Tutorial','DBMS stands for DataBase ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('( that''s me )','When configured properly, MySQL ...'); +SELECT * FROM articles WHERE MATCH (title,body) +AGAINST ('( yours''s* )' IN BOOLEAN MODE); +id title body +5 MySQL vs. YourSQL In the following database comparison ... +SELECT * FROM articles WHERE MATCH (title,body) +AGAINST ('s*' IN BOOLEAN MODE); +id title body +1 MySQL Tutorial DBMS stands for DataBase ... +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) +AGAINST ('stands\'] | * | show[@database' IN NATURAL LANGUAGE MODE); +id title body +1 MySQL Tutorial DBMS stands for DataBase ... +3 Optimizing MySQL In this tutorial we will show ... +5 MySQL vs. YourSQL In the following database comparison ... +DROP TABLE articles; +CREATE TABLE t1(a TEXT CHARACTER SET LATIN1, FULLTEXT INDEX(a)) ENGINE=INNODB; +SELECT * FROM t1 WHERE MATCH(a) AGAINST("*"); +ERROR 42000: syntax error, unexpected $end, expecting FTS_TERM or FTS_NUMB or '*' +DROP TABLE t1; +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +FULLTEXT (a) +) ENGINE= InnoDB; +INSERT INTO t1 (a) VALUES +('Do you know MySQL is a good database'), +('How to build a good database'), +('Do you know'), +('Do you know MySQL'), +('How to use MySQL'), +('Do you feel good'), +('MySQL is good'), +('MySQL is good to know'), +('What is database'); +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+"know mysql"' IN BOOLEAN MODE); +id a +1 Do you know MySQL is a good database +4 Do you know MySQL +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+("know mysql")' IN BOOLEAN MODE); +id a +1 Do you know MySQL is a good database +4 Do you know MySQL +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('("know mysql" good)' IN BOOLEAN MODE); +id a +1 Do you know MySQL is a good database +4 Do you know MySQL +2 How to build a good database +6 Do you feel good +7 MySQL is good +8 MySQL is good to know +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+("know mysql" good)' IN BOOLEAN MODE); +id a +1 Do you know MySQL is a good database +4 Do you know MySQL +2 How to build a good database +6 Do you feel good +7 MySQL is good +8 MySQL is good to know +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('(good "know mysql")' IN BOOLEAN MODE); +id a +1 Do you know MySQL is a good database +4 Do you know MySQL +2 How to build a good database +6 Do you feel good +7 MySQL is good +8 MySQL is good to know +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+(good "know mysql")' IN BOOLEAN MODE); +id a +1 Do you know MySQL is a good database +4 Do you know MySQL +2 How to build a good database +6 Do you feel good +7 MySQL is good +8 MySQL is good to know +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+("know mysql" "good database")' IN BOOLEAN MODE); +id a +1 Do you know MySQL is a good database +2 How to build a good database +4 Do you know MySQL +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+"know mysql" +"good database"' IN BOOLEAN MODE); +id a +1 Do you know MySQL is a good database +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+"know database"@4' IN BOOLEAN MODE); +id a +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+"know database"@8' IN BOOLEAN MODE); +id a +1 Do you know MySQL is a good database +DROP TABLE t1; +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +FULLTEXT (a) +) ENGINE= InnoDB; +INSERT INTO t1 (a) VALUES +('know mysql good database'); +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+"good database"' IN BOOLEAN MODE); +id a +1 know mysql good database +DROP TABLE t1; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles (title,body) VALUES ('Test Article','blah blah +blah'),("Matt's Noise",'this is noisy'),('February Weather','It was terrible +this year.'),('Peter Pan','Tis a kids story.'),('Test1','nada'),('Database +database database','foo database database database'),('Database article +title','body with lots of words.'),('myfulltext database', 'my test fulltext +database'); +SELECT id, title, body FROM articles ORDER BY MATCH (title,body) AGAINST ('database' IN BOOLEAN MODE) DESC; +id title body +6 Database +database database foo database database database +8 myfulltext database my test fulltext +database +7 Database article +title body with lots of words. +1 Test Article blah blah +blah +2 Matt's Noise this is noisy +3 February Weather It was terrible +this year. +4 Peter Pan Tis a kids story. +5 Test1 nada +DELETE from articles WHERE title like "myfulltext database"; +INSERT INTO articles (title,body) VALUES ('myfulltext database', 'my test fulltext database'); +SELECT id, title, body FROM articles ORDER BY MATCH (title,body) AGAINST ('database' IN BOOLEAN MODE) DESC; +id title body +6 Database +database database foo database database database +9 myfulltext database my test fulltext database +7 Database article +title body with lots of words. +1 Test Article blah blah +blah +2 Matt's Noise this is noisy +3 February Weather It was terrible +this year. +4 Peter Pan Tis a kids story. +5 Test1 nada +DELETE from articles WHERE title like "myfulltext database"; +INSERT INTO articles (title,body) VALUES ('myfulltext database', 'my test fulltext database'); +SELECT id, title, body FROM articles ORDER BY MATCH (title,body) AGAINST ('database' IN BOOLEAN MODE) DESC; +id title body +6 Database +database database foo database database database +10 myfulltext database my test fulltext database +7 Database article +title body with lots of words. +1 Test Article blah blah +blah +2 Matt's Noise this is noisy +3 February Weather It was terrible +this year. +4 Peter Pan Tis a kids story. +5 Test1 nada +DROP TABLE articles; +CREATE TABLE t1( +a TEXT CHARSET ujis COLLATE ujis_japanese_ci, +b TEXT CHARSET utf8mb4 COLLATE utf8mb4_turkish_ci, +c TEXT CHARSET eucjpms COLLATE eucjpms_bin, +d TEXT CHARSET utf8mb4, +FULLTEXT INDEX(a), +FULLTEXT INDEX(b), +FULLTEXT INDEX(c), +FULLTEXT INDEX(d) +) ENGINE = InnoDB; +INSERT INTO t1 VALUES +('myisam', 'myisam', 'myisam', 'myisam'), +('innodb', 'innodb', 'innodb', 'innodb'), +('innodb myisam', 'innodb myisam', 'innodb myisam', 'innodb myisam'), +('memory', 'memory', 'memory', 'memory'), +('archive', 'archive', 'archive', 'archive'), +('federated', 'federated', 'federated', 'federated'), +('storage engine innodb', 'storage engine innodb', 'storage engine innodb', 'storage engine innodb'), +('storage engine myisam', 'storage engine myisam', 'storage engine myisam', 'storage engine myisam'), +('innobase', 'innobase', 'innobase', 'innobase'), +('myisam innodb', 'myisam innodb', 'myisam innodb', 'myisam innodb'), +('innodb myisam engines', 'innodb myisam engines', 'innodb myisam engines', 'innodb myisam engines'); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00)); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', '"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', ' ', '"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, '"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 0x00, '"', 0x00)); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', '&', 0x00, '"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, '&', '"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', '%', '"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +a +innodb +innodb myisam +storage engine innodb +myisam innodb +innodb myisam engines +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +a +innodb +innodb myisam +storage engine innodb +myisam innodb +innodb myisam engines +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, 0x00, 0x00, '"')); +a +innodb +innodb myisam +storage engine innodb +myisam innodb +innodb myisam engines +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +a +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +a +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"')); +a +innodb myisam +innodb myisam engines +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', '(', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', ')')); +a +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', 'm', 'y', 'i', 's', 'a', 'm')); +a +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', 'm', 'y', 'i', 's', 'a', 'm', '"')); +a +innodb myisam +innodb myisam engines +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"','@', '2') IN BOOLEAN MODE); +a +innodb myisam +myisam innodb +innodb myisam engines +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 'm', 'y', 'i', 's', 'a', 'm', '"','@', '4') IN BOOLEAN MODE); +a +innodb myisam +myisam innodb +innodb myisam engines +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 's', 't', 'o', 'r', 'a', 'g', 'e', '"','@', '4', 0x00) IN BOOLEAN MODE); +ERROR 42000: syntax error, unexpected FTS_TERM, expecting FTS_NUMB +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"')); +b +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT(0x00)); +b +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', '"')); +b +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', ' ', '"')); +b +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', 0x00, '"')); +b +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT(0x00, '"', 0x00, '"', 0x00)); +b +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', '&', 0x00, '"')); +b +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', 0x00, '&', '"')); +b +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', '%', '"')); +b +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +b +innodb +innodb myisam +storage engine innodb +myisam innodb +innodb myisam engines +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +b +innodb +innodb myisam +storage engine innodb +myisam innodb +innodb myisam engines +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, 0x00, 0x00, '"')); +b +innodb +innodb myisam +storage engine innodb +myisam innodb +innodb myisam engines +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +b +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"','@', '2') IN BOOLEAN MODE); +b +innodb myisam +myisam innodb +innodb myisam engines +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 'm', 'y', 'i', 's', 'a', 'm', '"','@', '4') IN BOOLEAN MODE); +b +innodb myisam +myisam innodb +innodb myisam engines +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT(0x00, '"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 's', 't', 'o', 'r', 'a', 'g', 'e', '"','@', '4', 0x00) IN BOOLEAN MODE); +ERROR 42000: syntax error, unexpected FTS_TERM, expecting FTS_NUMB +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"')); +c +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT(0x00)); +c +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', '"')); +c +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', ' ', '"')); +c +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 0x00, '"')); +c +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT(0x00, '"', 0x00, '"', 0x00)); +c +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', '&', 0x00, '"')); +c +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 0x00, '&', '"')); +c +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', '%', '"')); +c +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +c +innodb +innodb myisam +storage engine innodb +myisam innodb +innodb myisam engines +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +c +innodb +innodb myisam +storage engine innodb +myisam innodb +innodb myisam engines +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, 0x00, 0x00, '"')); +c +innodb +innodb myisam +storage engine innodb +myisam innodb +innodb myisam engines +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +c +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +c +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"')); +c +innodb myisam +innodb myisam engines +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', '(', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', ')')); +c +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', 'm', 'y', 'i', 's', 'a', 'm')); +c +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', 'm', 'y', 'i', 's', 'a', 'm', '"')); +c +innodb myisam +innodb myisam engines +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"','@', '2') IN BOOLEAN MODE); +c +innodb myisam +myisam innodb +innodb myisam engines +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 'm', 'y', 'i', 's', 'a', 'm', '"','@', '4') IN BOOLEAN MODE); +c +innodb myisam +myisam innodb +innodb myisam engines +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT(0x00, '"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 's', 't', 'o', 'r', 'a', 'g', 'e', '"','@', '4', 0x00) IN BOOLEAN MODE); +ERROR 42000: syntax error, unexpected FTS_TERM, expecting FTS_NUMB +ALTER TABLE t1 ENGINE = MyISAM; +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00)); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', '"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', ' ', '"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, '"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 0x00, '"', 0x00)); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', '&', 0x00, '"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, '&', '"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', '%', '"')); +a +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +a +innodb +innodb myisam +myisam innodb +storage engine innodb +innodb myisam engines +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +a +innodb +innodb myisam +myisam innodb +storage engine innodb +innodb myisam engines +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, 0x00, 0x00, '"')); +a +innodb +innodb myisam +myisam innodb +storage engine innodb +innodb myisam engines +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +a +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +a +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"')); +a +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', '(', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', ')')); +a +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', 'm', 'y', 'i', 's', 'a', 'm')); +a +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', 'm', 'y', 'i', 's', 'a', 'm', '"')); +a +innodb myisam +myisam innodb +innodb myisam engines +myisam +innodb +storage engine innodb +storage engine myisam +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"','@', '2') IN BOOLEAN MODE); +a +innodb myisam +innodb myisam engines +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 'm', 'y', 'i', 's', 'a', 'm', '"','@', '4') IN BOOLEAN MODE); +a +innodb myisam +innodb myisam engines +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 's', 't', 'o', 'r', 'a', 'g', 'e', '"','@', '4', 0x00) IN BOOLEAN MODE); +a +DROP TABLE t1; +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +FULLTEXT (a) +) ENGINE= InnoDB; +INSERT INTO t1 (a) VALUES +('know database'),('good database'), ('gmail email'), ('ghome windows'); +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g *' IN NATURAL LANGUAGE MODE); +id a +2 good database +3 gmail email +4 ghome windows +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g *' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); +id a +3 gmail email +4 ghome windows +2 good database +1 know database +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g * k *' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); +id a +1 know database +3 gmail email +4 ghome windows +2 good database +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g * k * d *' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); +id a +1 know database +3 gmail email +4 ghome windows +2 good database +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g * go *' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); +id a +2 good database +3 gmail email +4 ghome windows +1 know database +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g * good' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); +id a +2 good database +3 gmail email +4 ghome windows +1 know database +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('gm * go *' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); +id a +3 gmail email +2 good database +1 know database +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('good *' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); +id a +2 good database +1 know database +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g* database' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); +id a +1 know database +2 good database +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/r/misc_1.result b/mysql-test/suite/innodb_fts/r/misc_1.result new file mode 100644 index 00000000000..2b26a87c3d7 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/misc_1.result @@ -0,0 +1,922 @@ +set names utf8; +call mtr.add_suppression("\\[Warning\\] InnoDB: A new Doc ID must be supplied while updating FTS indexed columns."); +call mtr.add_suppression("\\[Warning\\] InnoDB: FTS Doc ID must be larger than [0-9]+ for table `test`.`t1`"); +CREATE TABLE t1 ( +id1 INT , +a1 VARCHAR(200) , +b1 TEXT , +FULLTEXT KEY (a1,b1), PRIMARY KEY (a1, id1) +) CHARACTER SET = utf8 , ENGINE = InnoDB; +CREATE TABLE t2 ( +id2 INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a2 VARCHAR(200), +b2 TEXT , +FOREIGN KEY (a2) REFERENCES t1(a1) ON UPDATE CASCADE, +FULLTEXT KEY (b2,a2) +) CHARACTER SET = utf8 ,ENGINE = InnoDB; +INSERT INTO t1 (id1,a1,b1) VALUES +(1,'MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , +(2,'How To Use MySQL Well','After you went through a ...'), +(3,'Optimizing MySQL','In this tutorial we will show ...'); +INSERT INTO t1 (id1,a1,b1) VALUES +(4,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +(5,'MySQL vs. YourSQL','In the following database comparison ...'), +(6,'MySQL Security','When configured properly, MySQL ...'); +INSERT INTO t2 (a2,b2) VALUES +('MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'); +INSERT INTO t2 (a2,b2) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +INSERT INTO t2 (a2,b2) VALUES +('MySQL Tricks','1. Never run mysqld as root. 2. ...'); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE) +DELETE FROM t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE) +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b1' +test.t1 analyze status OK +ANALYZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze Warning Engine-independent statistics are not collected for column 'b2' +test.t2 analyze status OK +SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial') ORDER BY id1; +id1 +1 +3 +SELECT id2 FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial') ORDER BY id2; +id2 +1 +3 +SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ORDER BY id1; +id1 +1 +2 +3 +4 +5 +6 +SELECT id2 FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ORDER BY id2; +id2 +1 +2 +3 +4 +5 +6 +SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial' WITH QUERY EXPANSION) ORDER BY id1; +id1 +1 +2 +3 +4 +5 +6 +SELECT id2 FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial' WITH QUERY EXPANSION) ORDER BY id2; +id2 +1 +2 +3 +4 +5 +6 +SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('"dbms database"@4' IN BOOLEAN MODE) ; +id1 +1 +SELECT id2 FROM t2 WHERE MATCH (a2,b2) AGAINST ('"dbms database"@4' IN BOOLEAN MODE) ; +id2 +1 +set global innodb_optimize_fulltext_only=1; +optimize table t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +set global innodb_optimize_fulltext_only=0; +UPDATE t1 SET a1 = "changing column - on update cascade" , b1 = "to check foreign constraint" WHERE +MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +id1 +SELECT id2 FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +id2 +3 +6 +SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('+update +cascade' IN BOOLEAN MODE) ORDER BY id1; +id1 +1 +2 +3 +4 +5 +6 +SELECT id2 FROM t2 WHERE MATCH (a2,b2) AGAINST ('+update +cascade' IN BOOLEAN MODE) ORDER BY id2; +id2 +1 +2 +3 +4 +5 +6 +SELECT id2 FROM t2 WHERE a2 LIKE '%UPDATE CASCADE%' ORDER BY id2; +id2 +1 +2 +3 +4 +5 +6 +DROP TABLE t2 , t1; +create table t1 (s1 int, s2 varchar(200), primary key (s1,s2)) ENGINE = InnoDB; +create table t2 (s1 int, s2 varchar(200), +fulltext key(s2), +foreign key (s1,s2) references t1 (s1,s2) on update cascade) ENGINE = InnoDB; +insert into t1 values (1,'Sunshine'),(2,'Lollipops'); +insert into t2 values (1,'Sunshine'),(2,'Lollipops'); +update t1 set s2 = 'Rainbows' where s2 <> 'Sunshine'; +commit; +select * from t2 where match(s2) against ('Lollipops'); +s1 s2 +DROP TABLE t2 , t1; +create table t1 (s1 int, s2 varchar(200), primary key (s1,s2)) ENGINE = InnoDB; +create table t2 (s1 int, s2 varchar(200), +fulltext key(s2), +foreign key (s1,s2) references t1 (s1,s2) on delete cascade) ENGINE = InnoDB; +insert into t1 values (1,'Sunshine'),(2,'Lollipops'); +insert into t2 values (1,'Sunshine'),(2,'Lollipops'); +delete from t1 where s2 <> 'Sunshine'; +select * from t2 where match(s2) against ('Lollipops'); +s1 s2 +DROP TABLE t2 , t1; +create table t1 (s1 int, s2 varchar(200), primary key (s1,s2)) ENGINE = InnoDB; +create table t2 (s1 int, s2 varchar(200), +fulltext key(s2), +foreign key (s1,s2) references t1 (s1,s2) on delete set null) ENGINE = InnoDB; +insert into t1 values (1,'Sunshine'),(2,'Lollipops'); +insert into t2 values (1,'Sunshine'),(2,'Lollipops'); +delete from t1 where s2 <> 'Sunshine'; +select * from t2 where match(s2) against ('Lollipops'); +s1 s2 +DROP TABLE t2 , t1; +create table t1 (s1 int, s2 varchar(200), primary key (s1,s2)) ENGINE = InnoDB; +create table t2 (s1 int, s2 varchar(200), +fulltext key(s2), +foreign key (s1,s2) references t1 (s1,s2) on update set null) ENGINE = InnoDB; +insert into t1 values (1,'Sunshine'),(2,'Lollipops'); +insert into t2 values (1,'Sunshine'),(2,'Lollipops'); +update t1 set s2 = 'Rainbows' where s2 <> 'Sunshine'; +commit; +select * from t2 where match(s2) against ('Lollipops'); +s1 s2 +DROP TABLE t2 , t1; +create table t1 (s1 bigint unsigned not null, s2 varchar(200), +primary key (s1,s2)) ENGINE = InnoDB; +create table t2 (FTS_DOC_ID BIGINT UNSIGNED NOT NULL, s2 varchar(200), +foreign key (FTS_DOC_ID) references t1 (s1) +on update cascade) ENGINE = InnoDB; +create fulltext index idx on t2(s2); +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `FTS_DOC_ID` bigint(20) unsigned NOT NULL, + `s2` varchar(200) DEFAULT NULL, + KEY `FTS_DOC_ID` (`FTS_DOC_ID`), + FULLTEXT KEY `idx` (`s2`), + CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`FTS_DOC_ID`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +insert into t1 values (1,'Sunshine'),(2,'Lollipops'); +insert into t2 values (1,'Sunshine'),(2,'Lollipops'); +update t1 set s1 = 3 where s1=1; +select * from t2 where match(s2) against ('sunshine'); +FTS_DOC_ID s2 +3 Sunshine +update t1 set s1 = 1 where s1=3; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`FTS_DOC_ID`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +DROP TABLE t2 , t1; +CREATE TABLE t1 ( +id1 INT , +a1 VARCHAR(200) PRIMARY KEY, +b1 TEXT character set utf8 , +FULLTEXT KEY (a1,b1) +) CHARACTER SET = utf8 ,ENGINE = InnoDB; +CREATE TABLE t2 ( +id2 INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a2 VARCHAR(200), +b2 TEXT character set utf8 , +FOREIGN KEY (a2) REFERENCES t1(a1) ON DELETE CASCADE, +FULLTEXT KEY (b2,a2) +) CHARACTER SET = utf8 ,ENGINE = InnoDB; +INSERT INTO t1 (id1,a1,b1) VALUES +(1,'MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , +(2,'How To Use MySQL Well','After you went through a ...'), +(3,'Optimizing MySQL','In this tutorial we will show ...'), +(4,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +(5,'MySQL vs. YourSQL','In the following database comparison ...'), +(6,'MySQL Security','When configured properly, MySQL ...'); +INSERT INTO t2 (a2,b2) VALUES +('MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +DELETE FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +id1 a1 b1 +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +id2 a2 b2 +SELECT * FROM t1 WHERE a1 LIKE '%tutorial%'; +id1 a1 b1 +SELECT * FROM t2 WHERE a2 LIKE '%tutorial%'; +id2 a2 b2 +DROP TABLE t2 , t1; +call mtr.add_suppression("\\[ERROR\\] InnoDB: FTS Doc ID must be larger than 3 for table `test`.`t2`"); +CREATE TABLE t1 ( +id1 INT , +a1 VARCHAR(200) , +b1 TEXT , +FULLTEXT KEY (a1,b1), PRIMARY KEY(a1, id1) +) CHARACTER SET = utf8 , ENGINE = InnoDB; +CREATE TABLE t2 ( +id2 INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a2 VARCHAR(200), +b2 TEXT , +FOREIGN KEY (a2) REFERENCES t1(a1) ON UPDATE CASCADE, +FULLTEXT KEY (b2,a2) +) CHARACTER SET = utf8 ,ENGINE = InnoDB; +INSERT INTO t1 (id1,a1,b1) VALUES +(1,'MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , +(2,'How To Use MySQL Well','After you went through a ...'), +(3,'Optimizing MySQL','In this tutorial we will show ...'); +INSERT INTO t2 (a2,b2) VALUES +('MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'); +START TRANSACTION; +INSERT INTO t1 (id1,a1,b1) VALUES +(4,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +(5,'MySQL vs. YourSQL','In the following database comparison ...'), +(6,'MySQL Security','When configured properly, MySQL ...'); +INSERT INTO t2 (a2,b2) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +INSERT INTO t2 (a2,b2) VALUES +('MySQL Tricks','1. Never run mysqld as root. 2. ...'); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE) +DELETE FROM t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE) +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial') ORDER BY id1; +id1 a1 b1 +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial') ORDER BY id2; +id2 a2 b2 +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ORDER BY id1; +id1 a1 b1 +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ORDER BY id2; +id2 a2 b2 +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial' WITH QUERY EXPANSION) ORDER BY id1; +id1 a1 b1 +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial' WITH QUERY EXPANSION) ORDER BY id2; +id2 a2 b2 +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('"dbms database"@4' IN BOOLEAN MODE) ; +id1 a1 b1 +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('"dbms database"@4' IN BOOLEAN MODE) ; +id2 a2 b2 +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('root') ; +id1 a1 b1 +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('root') ; +id2 a2 b2 +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('mysqld (+root)' IN BOOLEAN MODE) ; +id1 a1 b1 +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('mysqld (-root)' IN BOOLEAN MODE) ; +id2 a2 b2 +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('root' WITH QUERY EXPANSION) ; +id1 a1 b1 +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('root' WITH QUERY EXPANSION) ; +id2 a2 b2 +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('"database comparison"@02' IN BOOLEAN MODE) ; +id1 a1 b1 +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('"database comparison"@02' IN BOOLEAN MODE) ; +id2 a2 b2 +SELECT * FROM t1 ORDER BY id1; +id1 a1 b1 +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +5 MySQL vs. YourSQL In the following database comparison ... +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM t2 ORDER BY id2; +id2 a2 b2 +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +5 MySQL vs. YourSQL In the following database comparison ... +6 MySQL Security When configured properly, MySQL ... +COMMIT; +START TRANSACTION; +UPDATE t1 SET a1 = "changing column - on UPDATE cascade" , b1 = "to check foreign constraint" WHERE +MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +COMMIT; +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +id1 a1 b1 +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +id2 a2 b2 +3 changing column - on UPDATE cascade In this tutorial we will show ... +6 changing column - on UPDATE cascade When configured properly, MySQL ... +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('+UPDATE +cascade' IN BOOLEAN MODE) ORDER BY id1; +id1 a1 b1 +1 changing column - on UPDATE cascade to check foreign constraint +2 changing column - on UPDATE cascade to check foreign constraint +3 changing column - on UPDATE cascade to check foreign constraint +4 changing column - on UPDATE cascade to check foreign constraint +5 changing column - on UPDATE cascade to check foreign constraint +6 changing column - on UPDATE cascade to check foreign constraint +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('+UPDATE +cascade' IN BOOLEAN MODE) ORDER BY id2; +id2 a2 b2 +1 changing column - on UPDATE cascade DBMS stands for DataBase VÃÆ·Wİ... +2 changing column - on UPDATE cascade After you went through a ... +3 changing column - on UPDATE cascade In this tutorial we will show ... +4 changing column - on UPDATE cascade 1. Never run mysqld as root. 2. ... +5 changing column - on UPDATE cascade In the following database comparison ... +6 changing column - on UPDATE cascade When configured properly, MySQL ... +SELECT * FROM t2 WHERE a2 LIKE '%UPDATE CASCADE%' ORDER BY id2; +id2 a2 b2 +1 changing column - on UPDATE cascade DBMS stands for DataBase VÃÆ·Wİ... +2 changing column - on UPDATE cascade After you went through a ... +3 changing column - on UPDATE cascade In this tutorial we will show ... +4 changing column - on UPDATE cascade 1. Never run mysqld as root. 2. ... +5 changing column - on UPDATE cascade In the following database comparison ... +6 changing column - on UPDATE cascade When configured properly, MySQL ... +DROP TABLE t2 , t1; +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), +FULLTEXT KEY(s2), +FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on UPDATE cascade) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +UPDATE t1 set s2 = 'Rainbows' WHERE s2 <> 'Sunshine'; +COMMIT; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +s1 s2 +DROP TABLE t2 , t1; +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), +FULLTEXT KEY(s2), +FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on DELETE cascade) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +DELETE FROM t1 WHERE s2 <> 'Sunshine'; +COMMIT; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +s1 s2 +DROP TABLE t2 , t1; +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), +FULLTEXT KEY(s2), +FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on DELETE SET NULL) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +DELETE FROM t1 WHERE s2 <> 'Sunshine'; +COMMIT; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +s1 s2 +DROP TABLE t2 , t1; +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), +FULLTEXT KEY(s2), +FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on UPDATE SET NULL) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +UPDATE t1 set s2 = 'Rainbows' WHERE s2 <> 'Sunshine'; +COMMIT; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +s1 s2 +DROP TABLE t2 , t1; +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), +FULLTEXT KEY(s2), +FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on UPDATE cascade) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +UPDATE t1 set s2 = 'Rainbows' WHERE s2 <> 'Sunshine'; +ROLLBACK; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +s1 s2 +DROP TABLE t2 , t1; +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), +FULLTEXT KEY(s2), +FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on DELETE cascade) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +DELETE FROM t1 WHERE s2 <> 'Sunshine'; +ROLLBACK; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +s1 s2 +DROP TABLE t2 , t1; +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), +FULLTEXT KEY(s2), +FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on DELETE SET NULL) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +DELETE FROM t1 WHERE s2 <> 'Sunshine'; +ROLLBACK; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +s1 s2 +DROP TABLE t2 , t1; +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), +FULLTEXT KEY(s2), +FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on UPDATE SET NULL) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +UPDATE t1 set s2 = 'Rainbows' WHERE s2 <> 'Sunshine'; +ROLLBACK; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +s1 s2 +DROP TABLE t2 , t1; +set global innodb_file_per_table=1; +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +b TEXT +) CHARACTER SET = utf8, ROW_FORMAT=COMPRESSED, ENGINE = InnoDB; +INSERT INTO t1 (a,b) VALUES +('MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'); +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `a` varchar(200) DEFAULT NULL, + `b` text DEFAULT NULL, + PRIMARY KEY (`id`), + FULLTEXT KEY `idx` (`a`,`b`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=COMPRESSED +SELECT count(*) FROM information_schema.innodb_sys_tables WHERE name LIKE "%FTS_%" AND space !=0; +count(*) +11 +INSERT INTO t1 (a,b) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +ANALYZE TABLE t1; +SELECT * FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) ORDER BY id; +id a b +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +3 Optimizing MySQL In this tutorial we will show ... +select * from t1 where MATCH(a,b) AGAINST("+tutorial +VÃÆ·Wİ" IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +select * from t1 where MATCH(a,b) AGAINST("+-VÃÆ·Wİ" IN BOOLEAN MODE); +ERROR 42000: syntax error, unexpected '-' +select * from t1 where MATCH(a,b) AGAINST("+Mysql +(tricks never)" IN BOOLEAN MODE); +id a b +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +select * from t1 where MATCH(a,b) AGAINST("+mysql -(tricks never)" IN BOOLEAN MODE) ORDER BY id; +id a b +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +5 MySQL vs. YourSQL In the following database comparison ... +6 MySQL Security When configured properly, MySQL ... +select *, MATCH(a,b) AGAINST("mysql stands" IN BOOLEAN MODE) as x from t1 ORDER BY id; +id a b x +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... 0.6055193543434143 +2 How To Use MySQL Well After you went through a ... 0.000000001885928302414186 +3 Optimizing MySQL In this tutorial we will show ... 0.000000001885928302414186 +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... 0.000000001885928302414186 +5 MySQL vs. YourSQL In the following database comparison ... 0.000000001885928302414186 +6 MySQL Security When configured properly, MySQL ... 0.000000003771856604828372 +select * from t1 where MATCH a,b AGAINST ("+database* +VÃÆ·W*" IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +select * from t1 where MATCH a,b AGAINST ('"security mysql"' IN BOOLEAN MODE); +id a b +select * from t1 where MATCH(a,b) AGAINST ("VÃÆ·Wİ" WITH QUERY EXPANSION) ORDER BY id; +id a b +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +5 MySQL vs. YourSQL In the following database comparison ... +6 MySQL Security When configured properly, MySQL ... +ALTER TABLE t1 DROP INDEX idx; +CREATE FULLTEXT INDEX idx on t1 (a,b); +SELECT * FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) ORDER BY id; +id a b +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +3 Optimizing MySQL In this tutorial we will show ... +select * from t1 where MATCH(a,b) AGAINST("+tutorial +VÃÆ·Wİ" IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +select * from t1 where MATCH(a,b) AGAINST("+dbms" IN BOOLEAN MODE); +id a b +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +select * from t1 where MATCH(a,b) AGAINST("+Mysql +(tricks never)" IN BOOLEAN MODE); +id a b +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +select * from t1 where MATCH(a,b) AGAINST("+mysql -(tricks never)" IN BOOLEAN MODE) ORDER BY id; +id a b +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +5 MySQL vs. YourSQL In the following database comparison ... +6 MySQL Security When configured properly, MySQL ... +select *, MATCH(a,b) AGAINST("mysql VÃÆ·Wİ" IN BOOLEAN MODE) as x from t1 ORDER BY id; +id a b x +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... 0.6055193543434143 +2 How To Use MySQL Well After you went through a ... 0.000000001885928302414186 +3 Optimizing MySQL In this tutorial we will show ... 0.000000001885928302414186 +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... 0.000000001885928302414186 +5 MySQL vs. YourSQL In the following database comparison ... 0.000000001885928302414186 +6 MySQL Security When configured properly, MySQL ... 0.000000003771856604828372 +select * from t1 where MATCH a,b AGAINST ('"security mysql"' IN BOOLEAN MODE); +id a b +select * from t1 where MATCH(a,b) AGAINST ("VÃÆ·Wİ" WITH QUERY EXPANSION) ORDER BY id; +id a b +1 MySQL Tutorial DBMS stands for DataBase VÃÆ·Wİ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +5 MySQL vs. YourSQL In the following database comparison ... +6 MySQL Security When configured properly, MySQL ... +INSERT INTO t1 (a,b) VALUES ('test query expansion','for database ...'); +INSERT INTO t1 (a,b) VALUES +('test proximity search, test, proximity and phrase', +'search, with proximity innodb'); +INSERT INTO t1 (a,b) VALUES +('test proximity fts search, test, proximity and phrase', +'search, with proximity innodb'); +INSERT INTO t1 (a,b) VALUES +('test more proximity fts search, test, more proximity and phrase', +'search, with proximity innodb'); +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"proximity search"@2' IN BOOLEAN MODE); +id a b +8 test proximity search, test, proximity and phrase search, with proximity innodb +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"proximity search"@1' IN BOOLEAN MODE); +id a b +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"proximity search"@3' IN BOOLEAN MODE) ORDER BY id; +id a b +8 test proximity search, test, proximity and phrase search, with proximity innodb +9 test proximity fts search, test, proximity and phrase search, with proximity innodb +10 test more proximity fts search, test, more proximity and phrase search, with proximity innodb +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"test proximity"@5' IN BOOLEAN MODE) ORDER BY id; +id a b +8 test proximity search, test, proximity and phrase search, with proximity innodb +9 test proximity fts search, test, proximity and phrase search, with proximity innodb +10 test more proximity fts search, test, more proximity and phrase search, with proximity innodb +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"more test proximity"@2' IN BOOLEAN MODE); +id a b +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"more test proximity"@3' IN BOOLEAN MODE); +id a b +10 test more proximity fts search, test, more proximity and phrase search, with proximity innodb +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"more fts proximity"@03' IN BOOLEAN MODE); +id a b +10 test more proximity fts search, test, more proximity and phrase search, with proximity innodb +UPDATE t1 SET a = UPPER(a) , b = UPPER(b) ; +UPDATE t1 SET a = UPPER(a) , b = LOWER(b) ; +select * from t1 where MATCH(a,b) AGAINST("+tutorial +dbms" IN BOOLEAN MODE); +id a b +1 MYSQL TUTORIAL dbms stands for database vðʒwi... +select * from t1 where MATCH(a,b) AGAINST("+VÃÆ·Wİ" IN BOOLEAN MODE); +id a b +1 MYSQL TUTORIAL dbms stands for database vðʒwi... +SELECT * FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) ORDER BY id; +id a b +1 MYSQL TUTORIAL dbms stands for database vðʒwi... +3 OPTIMIZING MYSQL in this tutorial we will show ... +DELETE FROM t1 WHERE MATCH (a,b) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +DELETE FROM t1 WHERE MATCH (a,b) AGAINST ('"proximity search"@14' IN BOOLEAN MODE); +SELECT * FROM t1 WHERE MATCH (a,b) +AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +id a b +SELECT * FROM t1 ORDER BY id; +id a b +2 HOW TO USE MYSQL WELL after you went through a ... +4 1001 MYSQL TRICKS 1. never run mysqld as root. 2. ... +5 MYSQL VS. YOURSQL in the following database comparison ... +6 MYSQL SECURITY when configured properly, mysql ... +7 TEST QUERY EXPANSION for database ... +DROP TABLE t1; +SET GLOBAL innodb_file_per_table=1; +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +b TEXT +) CHARACTER SET = utf8, ENGINE=InnoDB; +INSERT INTO t1 (a,b) VALUES +('Я могу еÑть Ñтекло', 'оно мне не вредит'), +('Мога да Ñм Ñтъкло', 'то не ми вреди'), +('ΜποÏá¿¶ νὰ φάω σπασμένα' ,'γυαλιὰ χωÏá½¶Ï‚ νὰ πάθω τίποτα'), +('PříliÅ¡ žluÅ¥ouÄký kůň', 'úpÄ›l Äábelské kódy'), +('Sævör grét', 'áðan því úlpan var ónýt'), +('ã†ã‚ã®ãŠãã‚„ã¾','ã‘ãµã“ãˆã¦'), +('ã„ã‚ã¯ã«ã»ã¸ã©ã€€ã¡ã‚Šã¬ã‚‹','ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš'); +INSERT INTO t1 (a,b) VALUES +('MySQL Tutorial','request docteam@oraclehelp.com ...') , +('Trial version','query performace @1255 minute on 2.1Hz Memory 2GB...') , +('when To Use MySQL Well','for free faq mail@xyz.com ...'); +CREATE FULLTEXT INDEX idx on t1 (a,b); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("вредит χωÏá½¶Ï‚") ORDER BY id; +id a b +1 Я могу еÑть Ñтекло оно мне не вредит +3 ΜποÏá¿¶ νὰ φάω σπασμένα γυαλιὰ χωÏá½¶Ï‚ νὰ πάθω τίποτα +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("оно" WITH QUERY EXPANSION); +id a b +1 Я могу еÑть Ñтекло оно мне не вредит +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("вред*" IN BOOLEAN MODE) ORDER BY id; +id a b +1 Я могу еÑть Ñтекло оно мне не вредит +2 Мога да Ñм Ñтъкло то не ми вреди +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("+γυαλιὰ +tutorial" IN BOOLEAN MODE); +id a b +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("+tutorial +(Мога τίποτα)" IN BOOLEAN MODE); +id a b +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš"); +id a b +7 ã„ã‚ã¯ã«ã»ã¸ã©ã€€ã¡ã‚Šã¬ã‚‹ ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("ã¡ã‚Šã¬ã‚‹" WITH QUERY EXPANSION); +id a b +7 ã„ã‚ã¯ã«ã»ã¸ã©ã€€ã¡ã‚Šã¬ã‚‹ ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("+ã‚ã•ãゆã‚ã¿ã˜ã€€+ã‚‘ã²ã‚‚ã›ãš" IN BOOLEAN MODE); +id a b +7 ã„ã‚ã¯ã«ã»ã¸ã©ã€€ã¡ã‚Šã¬ã‚‹ ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("ã†ã‚ã®ãŠã*" IN BOOLEAN MODE); +id a b +6 ã†ã‚ã®ãŠãã‚„ã¾ ã‘ãµã“ãˆã¦ +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("+Sævör +úlpan" IN BOOLEAN MODE); +id a b +5 Sævör grét áðan því úlpan var ónýt +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"γυαλιὰ χωÏá½¶Ï‚"@2' IN BOOLEAN MODE); +id a b +3 ΜποÏá¿¶ νὰ φάω σπασμένα γυαλιὰ χωÏá½¶Ï‚ νὰ πάθω τίποτα +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"query performace"@02' IN BOOLEAN MODE); +id a b +9 Trial version query performace @1255 minute on 2.1Hz Memory 2GB... +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"πάθω τίποτα"@2' IN BOOLEAN MODE); +id a b +3 ΜποÏá¿¶ νὰ φάω σπασμένα γυαλιὰ χωÏá½¶Ï‚ νὰ πάθω τίποτα +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"ã‚ã•ãゆã‚ã¿ã˜ ã‚‘ã²ã‚‚ã›ãš"@1' IN BOOLEAN MODE); +id a b +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"ã‚ã•ãゆã‚ã¿ã˜ ã‚‘ã²ã‚‚ã›ãš"@2' IN BOOLEAN MODE); +id a b +7 ã„ã‚ã¯ã«ã»ã¸ã©ã€€ã¡ã‚Šã¬ã‚‹ ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš +ALTER TABLE t1 DROP INDEX idx; +CREATE FULLTEXT INDEX idx on t1 (a,b); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("ã‚ã•ãゆã‚ã¿ã˜ ã‚‘ã²ã‚‚ã›ãš"); +id a b +7 ã„ã‚ã¯ã«ã»ã¸ã©ã€€ã¡ã‚Šã¬ã‚‹ ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš +UPDATE t1 SET a = "Pchnąć w tÄ™ łódź jeża" , b = "lub osiem skrzyÅ„ fig" WHERE MATCH(a,b) AGAINST ("ã‚ã•ãゆã‚ã¿ã˜ ã‚‘ã²ã‚‚ã›ãš"); +UPDATE t1 SET a = "Ð’ чащах юга жил-был цитруÑ? Да", b = "но фальшивый ÑкземплÑÑ€! ёъ" WHERE MATCH(a,b) AGAINST ("вред*" IN BOOLEAN MODE); +DELETE FROM t1 WHERE MATCH(a,b) AGAINST("+Sævör +úlpan" IN BOOLEAN MODE); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš"); +id a b +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("łódź osiem"); +id a b +7 Pchnąć w tÄ™ łódź jeża lub osiem skrzyÅ„ fig +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("вред*" IN BOOLEAN MODE); +id a b +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("фальшив*" IN BOOLEAN MODE) ORDER BY id; +id a b +1 Ð’ чащах юга жил-был цитруÑ? Да но фальшивый ÑкземплÑÑ€! ёъ +2 Ð’ чащах юга жил-был цитруÑ? Да но фальшивый ÑкземплÑÑ€! ёъ +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("+Sævör +úlpan" IN BOOLEAN MODE); +id a b +SELECT * FROM t1 +WHERE MATCH (a,b) +AGAINST ('"łódź jeża"@2' IN BOOLEAN MODE); +id a b +7 Pchnąć w tÄ™ łódź jeża lub osiem skrzyÅ„ fig +SELECT * FROM t1 ORDER BY id; +id a b +1 Ð’ чащах юга жил-был цитруÑ? Да но фальшивый ÑкземплÑÑ€! ёъ +2 Ð’ чащах юга жил-был цитруÑ? Да но фальшивый ÑкземплÑÑ€! ёъ +3 ΜποÏá¿¶ νὰ φάω σπασμένα γυαλιὰ χωÏá½¶Ï‚ νὰ πάθω τίποτα +4 PříliÅ¡ žluÅ¥ouÄký kůň úpÄ›l Äábelské kódy +6 ã†ã‚ã®ãŠãã‚„ã¾ ã‘ãµã“ãˆã¦ +7 Pchnąć w tÄ™ łódź jeża lub osiem skrzyÅ„ fig +8 MySQL Tutorial request docteam@oraclehelp.com ... +9 Trial version query performace @1255 minute on 2.1Hz Memory 2GB... +10 when To Use MySQL Well for free faq mail@xyz.com ... +DROP TABLE t1; +CREATE TABLE t1(ID INT PRIMARY KEY, +no_fts_field VARCHAR(10), +fts_field VARCHAR(10), +FULLTEXT INDEX f(fts_field)) ENGINE=INNODB; +INSERT INTO t1 VALUES (1, 'AAA', 'BBB'); +SELECT * FROM t1 WHERE MATCH(fts_field) against("BBB"); +ID no_fts_field fts_field +1 AAA BBB +UPDATE t1 SET fts_field='anychange' where id = 1; +SELECT * FROM t1 WHERE MATCH(fts_field) against("anychange"); +ID no_fts_field fts_field +1 AAA anychange +UPDATE t1 SET no_fts_field='anychange' where id = 1; +SELECT * FROM t1 WHERE MATCH(fts_field) against("anychange"); +ID no_fts_field fts_field +1 anychange anychange +UPDATE t1 SET no_fts_field='anychange', fts_field='other' where id = 1; +SELECT * FROM t1 WHERE MATCH(fts_field) against("other"); +ID no_fts_field fts_field +1 anychange other +SELECT * FROM t1 WHERE MATCH(fts_field) against("BBB"); +ID no_fts_field fts_field +DROP INDEX f on t1; +UPDATE t1 SET fts_field='anychange' where id = 1; +UPDATE t1 SET no_fts_field='anychange' where id = 1; +UPDATE t1 SET no_fts_field='anychange', fts_field='other' where id = 1; +CREATE FULLTEXT INDEX f ON t1(FTS_FIELD); +SELECT * FROM t1 WHERE MATCH(fts_field) against("other"); +ID no_fts_field fts_field +1 anychange other +DROP TABLE t1; +CREATE TABLE t1(`FTS_DOC_ID` serial, +no_fts_field VARCHAR(10), +fts_field VARCHAR(10), +FULLTEXT INDEX f(fts_field)) ENGINE=INNODB; +INSERT INTO t1 VALUES (1, 'AAA', 'BBB'); +UPDATE t1 SET fts_field='anychange' where FTS_DOC_ID = 1; +ERROR HY000: Invalid InnoDB FTS Doc ID +UPDATE t1 SET fts_field='anychange', FTS_DOC_ID = 2 where FTS_DOC_ID = 1; +SELECT * FROM t1 WHERE MATCH(fts_field) against("anychange"); +FTS_DOC_ID no_fts_field fts_field +2 AAA anychange +SELECT * FROM t1 WHERE MATCH(fts_field) against("BBB"); +FTS_DOC_ID no_fts_field fts_field +UPDATE t1 SET no_fts_field='anychange' where FTS_DOC_ID = 2; +SELECT * FROM t1 WHERE MATCH(fts_field) against("anychange"); +FTS_DOC_ID no_fts_field fts_field +2 anychange anychange +UPDATE t1 SET no_fts_field='anychange', fts_field='other' where FTS_DOC_ID = 2; +ERROR HY000: Invalid InnoDB FTS Doc ID +SELECT * FROM t1 WHERE MATCH(fts_field) against("other"); +FTS_DOC_ID no_fts_field fts_field +UPDATE t1 SET FTS_DOC_ID = 1 where FTS_DOC_ID = 2; +ERROR HY000: Invalid InnoDB FTS Doc ID +DROP INDEX f ON t1; +UPDATE t1 SET fts_field='newchange' where FTS_DOC_ID = 2; +UPDATE t1 SET no_fts_field='anychange' where FTS_DOC_ID = 2; +SELECT * FROM t1; +FTS_DOC_ID no_fts_field fts_field +2 anychange newchange +DROP TABLE t1; +CREATE TABLE t1(ID INT PRIMARY KEY, +no_fts_field VARCHAR(10), +fts_field VARCHAR(10), +FULLTEXT INDEX f(fts_field), index k(fts_field)) ENGINE=INNODB; +CREATE TABLE t2(ID INT PRIMARY KEY, +no_fts_field VARCHAR(10), +fts_field VARCHAR(10), +FULLTEXT INDEX f(fts_field), +INDEX k2(fts_field), +FOREIGN KEY(fts_field) REFERENCES +t1(fts_field) ON UPDATE CASCADE) ENGINE=INNODB; +INSERT INTO t1 VALUES (1, 'AAA', 'BBB'); +INSERT INTO t2 VALUES (1, 'AAA', 'BBB'); +update t1 set fts_field='newchange' where id =1; +SELECT * FROM t1 WHERE MATCH(fts_field) against("BBB"); +ID no_fts_field fts_field +SELECT * FROM t2 WHERE MATCH(fts_field) against("BBB"); +ID no_fts_field fts_field +SELECT * FROM t1 WHERE MATCH(fts_field) against("newchange"); +ID no_fts_field fts_field +1 AAA newchange +SELECT * FROM t2 WHERE MATCH(fts_field) against("newchange"); +ID no_fts_field fts_field +1 AAA newchange +DROP TABLE t2; +DROP TABLE t1; +CREATE TABLE t1(id INT PRIMARY KEY, +fts_field VARCHAR(10), +FULLTEXT INDEX f(fts_field)) ENGINE=INNODB; +CREATE TABLE t2(id INT PRIMARY KEY, +fts_field VARCHAR(10), +FULLTEXT INDEX f(fts_field)) ENGINE=INNODB; +INSERT INTO t1 values (1,'100'),(2,'200'),(3,'300'),(4,'400'),(5,'500'),(6,'600'), (7,'700'),(8,'800'),(9,'900'),(10,'1000'),(11,'1100'),(12,'1200'); +INSERT INTO t2 values (1,'100'),(2,'200'),(3,'300'),(4,'400'),(5,'500'),(6,'600'), (7,'700'),(8,'800'); +UPDATE t1, t2 set t1.fts_field = CONCAT(t1.fts_field, 'foo'); +UPDATE t1, t2 set t1.fts_field = CONCAT(t1.fts_field, 'foo') WHERE t1.fts_field = "100foo"; +UPDATE t1, t2 set t1.fts_field = CONCAT(t1.fts_field, 'xoo'), t2.fts_field = CONCAT(t1.fts_field, 'xoo') where t1.fts_field=CONCAT(t2.fts_field, 'foo'); +SELECT * FROM t1 WHERE MATCH(fts_field) against("100foofoo"); +id fts_field +1 100foofoo +SELECT * FROM t1 WHERE MATCH(fts_field) against("100foo"); +id fts_field +SELECT * FROM t1 WHERE MATCH(fts_field) against("100"); +id fts_field +SELECT * FROM t2 WHERE MATCH(fts_field) against("400fooxoo"); +id fts_field +4 400fooxoo +SELECT * FROM t2 WHERE MATCH(fts_field) against("100"); +id fts_field +1 100 +SELECT * FROM t2 WHERE MATCH(fts_field) against("200"); +id fts_field +SELECT * FROM t2 WHERE MATCH(fts_field) against("400"); +id fts_field +DROP TABLE t1; +DROP TABLE t2; + +BUG#13701973/64274: MYSQL THREAD WAS SUSPENDED WHEN EXECUTE UPDATE QUERY + +SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; +CREATE TABLE t1 ( +t1_id INT(10) UNSIGNED NOT NULL, +t2_id INT(10) UNSIGNED DEFAULT NULL, +PRIMARY KEY (t1_id), +FOREIGN KEY (t2_id) REFERENCES t2 (t2_id) +ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; +CREATE TABLE t2 ( +t1_id INT(10) UNSIGNED NOT NULL, +t2_id INT(10) UNSIGNED NOT NULL, +t3_id INT(10) UNSIGNED NOT NULL, +t4_id INT(10) UNSIGNED NOT NULL, +PRIMARY KEY (t2_id), +FOREIGN KEY (t1_id) REFERENCES t1 (t1_id), +FOREIGN KEY (t3_id) REFERENCES t3 (t3_id) +ON DELETE CASCADE ON UPDATE CASCADE, +FOREIGN KEY (t4_id) REFERENCES t4 (t4_id) +) ENGINE=InnoDB; +CREATE TABLE t3 ( +t3_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, +payload char(3), +PRIMARY KEY (t3_id) +) ENGINE=InnoDB; +INSERT INTO t3 VALUES (1, '100'); +CREATE TABLE t4 ( +t2_id INT(10) UNSIGNED DEFAULT NULL, +t4_id INT(10) UNSIGNED NOT NULL, +PRIMARY KEY (t4_id), +FOREIGN KEY (t2_id) REFERENCES t2 (t2_id) +ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; +SET FOREIGN_KEY_CHECKS=1; +UPDATE t3 SET payload='101' WHERE t3_id=1; +SET FOREIGN_KEY_CHECKS=0; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; +SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; diff --git a/mysql-test/suite/innodb_fts/r/opt.result b/mysql-test/suite/innodb_fts/r/opt.result new file mode 100644 index 00000000000..6385ea2a778 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/opt.result @@ -0,0 +1,1650 @@ +CREATE TABLE wp( +FTS_DOC_ID BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, +title VARCHAR(255) NOT NULL DEFAULT '', +text MEDIUMTEXT NOT NULL, +dummy INTEGER, +PRIMARY KEY (FTS_DOC_ID), +UNIQUE KEY FTS_DOC_ID_INDEX (FTS_DOC_ID), +FULLTEXT KEY idx (title,text) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO wp (title, text) VALUES +('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database to database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +CREATE TABLE t1 (i INTEGER); +INSERT INTO t1 SELECT FTS_DOC_ID FROM wp; +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE wp; +Table Op Msg_type Msg_text +test.wp analyze status OK +SELECT FTS_DOC_ID, title, MATCH(title, text) AGAINST ('database') AS score1, +MATCH(title, text) AGAINST ('mysql') AS score2 +FROM wp; +FTS_DOC_ID title score1 score2 +1 MySQL Tutorial 0.22764469683170319 0.000000003771856604828372 +2 How To Use MySQL Well 0 0.000000001885928302414186 +3 Optimizing MySQL 0 0.000000001885928302414186 +4 1001 MySQL Tricks 0 0.000000001885928302414186 +5 MySQL vs. YourSQL 0.45528939366340637 0.000000001885928302414186 +6 MySQL Security 0 0.000000003771856604828372 +No sorting for this query +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score DESC; +title score +MySQL vs. YourSQL 0.45528939366340637 +MySQL Tutorial 0.22764469683170319 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 0 +Sort_range 0 +Sort_rows 2 +Sort_scan 1 +No sorting for this query even if MATCH is part of an expression +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') > 0.1 +ORDER BY score DESC; +title score +MySQL vs. YourSQL 0.45528939366340637 +MySQL Tutorial 0.22764469683170319 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 0 +Sort_range 0 +Sort_rows 2 +Sort_scan 1 +No sorting even if there are several MATCH expressions as long as the +right one is used in ORDER BY +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score1, +MATCH(title, text) AGAINST ('mysql') AS score2 +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score1 DESC; +title score1 score2 +MySQL vs. YourSQL 0.45528939366340637 0.000000001885928302414186 +MySQL Tutorial 0.22764469683170319 0.000000003771856604828372 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 0 +Sort_range 0 +Sort_rows 2 +Sort_scan 1 +No Sorting since FT table is first table in query +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp, t1 +WHERE MATCH(title, text) AGAINST ('database') AND FTS_DOC_ID = t1.i +ORDER BY score DESC; +title score +MySQL vs. YourSQL 0.45528939366340637 +MySQL Tutorial 0.22764469683170319 +SHOW SESSION STATUS LIKE 'Sort_rows%'; +Variable_name Value +Sort_rows 2 +Sorting since there is no WHERE clause +FLUSH STATUS; +SELECT MATCH(title, text) AGAINST ('database'), title AS score +FROM wp +ORDER BY score DESC; +MATCH(title, text) AGAINST ('database') score +0 1001 MySQL Tricks +0 How To Use MySQL Well +0 MySQL Security +0 Optimizing MySQL +0.22764469683170319 MySQL Tutorial +0.45528939366340637 MySQL vs. YourSQL +SHOW SESSION STATUS LIKE 'Sort_rows%'; +Variable_name Value +Sort_rows 6 +Sorting since ordering on multiple columns +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score DESC, FTS_DOC_ID; +title score +MySQL vs. YourSQL 0.45528939366340637 +MySQL Tutorial 0.22764469683170319 +SHOW SESSION STATUS LIKE 'Sort_rows%'; +Variable_name Value +Sort_rows 2 +Sorting since ordering is not descending +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score ASC; +title score +MySQL Tutorial 0.22764469683170319 +MySQL vs. YourSQL 0.45528939366340637 +SHOW SESSION STATUS LIKE 'Sort_rows%'; +Variable_name Value +Sort_rows 2 +Sorting because one is ordering on a different MATCH expression +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('mysql') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score DESC; +title score +MySQL Tutorial 0.000000003771856604828372 +MySQL vs. YourSQL 0.000000001885928302414186 +SHOW SESSION STATUS LIKE 'Sort_rows%'; +Variable_name Value +Sort_rows 2 +No sorting for this query +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +ORDER BY score DESC LIMIT 2; +title score +MySQL vs. YourSQL 0.45528939366340637 +MySQL Tutorial 0.22764469683170319 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 1 +Sort_range 0 +Sort_rows 2 +Sort_scan 1 +Revert to table scan and sorting for this query since not +enough matching rows to satisfy LIMIT clause +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +ORDER BY score DESC LIMIT 2; +title score +MySQL vs. YourSQL 0.45528939366340637 +MySQL Tutorial 0.22764469683170319 +SHOW SESSION STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 2 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 14 +SHOW SESSION STATUS LIKE 'Sort_rows%'; +Variable_name Value +Sort_rows 2 +Sorting since no LIMIT clause +FLUSH STATUS; +SELECT MATCH(title, text) AGAINST ('database') AS score, title +FROM wp +ORDER BY score DESC; +score title +0 1001 MySQL Tricks +0 How To Use MySQL Well +0 MySQL Security +0 Optimizing MySQL +0.22764469683170319 MySQL Tutorial +0.45528939366340637 MySQL vs. YourSQL +SHOW SESSION STATUS LIKE 'Sort_rows%'; +Variable_name Value +Sort_rows 6 +Sorting since there is a WHERE clause +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE dummy IS NULL +ORDER BY score DESC LIMIT 2; +title score +MySQL vs. YourSQL 0.45528939366340637 +MySQL Tutorial 0.22764469683170319 +SHOW SESSION STATUS LIKE 'Sort_rows%'; +Variable_name Value +Sort_rows 2 +Sorting since ordering is not on a simple MATCH expressions +FLUSH STATUS; +SELECT title, (MATCH(title, text) AGAINST ('database')) * 100 AS score +FROM wp +ORDER BY score DESC LIMIT 2; +title score +MySQL vs. YourSQL 45.52893936634064 +MySQL Tutorial 22.76446968317032 +SHOW SESSION STATUS LIKE 'Sort_rows%'; +Variable_name Value +Sort_rows 2 +No ordinary handler accesses when only accessing FTS_DOC_ID and MATCH +FLUSH STATUS; +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database'); +docid score +5 0.45528939366340637 +1 0.22764469683170319 +SHOW SESSION STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +Still no handler accesses when adding FTS_DOC_ID to WHERE clause +FLUSH STATUS; +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') AND FTS_DOC_ID > 2; +docid score +5 0.45528939366340637 +SHOW SESSION STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +Still no handler accesses when ordering by MATCH expression +FLUSH STATUS; +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score; +docid score +1 0.22764469683170319 +5 0.45528939366340637 +SHOW SESSION STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 2 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 3 +Optimization is disabled when ordering on FTS_DOC_ID +FLUSH STATUS; +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY 1 DESC; +docid score +5 0.45528939366340637 +1 0.22764469683170319 +SHOW SESSION STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 2 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +Optimization also work with several MATCH expressions +FLUSH STATUS; +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score1, +MATCH(title, text) AGAINST ('mysql') AS score2 +FROM wp +WHERE MATCH(title, text) AGAINST ('database'); +docid score1 score2 +5 0.45528939366340637 0.000000001885928302414186 +1 0.22764469683170319 0.000000003771856604828372 +SHOW SESSION STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +Optimization does not apply if sorting on a different MATCH expressions +from the one used to access the +FLUSH STATUS; +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score1, +MATCH(title, text) AGAINST ('mysql') AS score2 +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score2 DESC; +docid score1 score2 +1 0.22764469683170319 0.000000003771856604828372 +5 0.45528939366340637 0.000000001885928302414186 +SHOW SESSION STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 2 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 3 +FLUSH STATUS; +Optimization does not apply for GROUP BY +SET @save_mode = @@sql_mode; +SET sql_mode = (select replace(@@sql_mode,'ONLY_FULL_GROUP_BY','')); +SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +GROUP BY score; +FTS_DOC_ID score +1 0.22764469683170319 +5 0.45528939366340637 +SHOW SESSION STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 2 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 3 +SET sql_mode = @save_mode; +No sorting and no table access with LIMIT clause and only information +from FTS result +FLUSH STATUS; +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +ORDER BY score DESC LIMIT 2; +docid score +5 0.45528939366340637 +1 0.22764469683170319 +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 2 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 14 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 1 +Sort_range 0 +Sort_rows 2 +Sort_scan 1 +If count optimization applies, EXPLAIN shows +"Select tables optimized away." +EXPLAIN SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE wp fulltext idx idx 0 1 Using where +FLUSH STATUS; +SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE); +COUNT(*) +2 +Verify that there was no table access +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +Optimization applies also to COUNT(expr) as long as expr is not nullable +EXPLAIN SELECT COUNT(title) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE wp fulltext idx idx 0 1 Using where +SELECT COUNT(title) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE); +COUNT(title) +2 +Optimization does not apply if not a single table query. +EXPLAIN SELECT count(*) +FROM wp, t1 +WHERE MATCH(title, text) AGAINST ('database'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE wp fulltext idx idx 0 1 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 6 +SELECT count(*) +FROM wp, t1 +WHERE MATCH(title, text) AGAINST ('database'); +count(*) +12 +Optimization does not apply if MATCH is part of an expression +EXPLAIN SELECT COUNT(title) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE) > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE wp fulltext idx idx 0 1 Using where +SELECT COUNT(title) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE) > 0; +COUNT(title) +2 +Optimization does not apply if MATCH is part of an expression +EXPLAIN SELECT COUNT(title) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE) > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE wp fulltext idx idx 0 1 Using where +SELECT COUNT(title) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE) > 0; +COUNT(title) +2 +Optimization does not apply if COUNT expression is nullable +EXPLAIN SELECT COUNT(dummy) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE wp fulltext idx idx 0 1 Using where +SELECT COUNT(dummy) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE); +COUNT(dummy) +0 +FLUSH STATUS; +SELECT MATCH(title, text) AGAINST ('database' WITH QUERY EXPANSION) AS score, +title +FROM wp +WHERE MATCH(title, text) AGAINST ('database' WITH QUERY EXPANSION) +ORDER BY score DESC; +score title +0.000000001885928302414186 1001 MySQL Tricks +0.000000001885928302414186 How To Use MySQL Well +0.000000003771856604828372 MySQL Security +0.22764469683170319 Optimizing MySQL +1.6663280725479126 MySQL Tutorial +2.2718474864959717 MySQL vs. YourSQL +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 0 +Sort_range 0 +Sort_rows 6 +Sort_scan 1 +FLUSH STATUS; +SELECT title, +MATCH(title, text) AGAINST ('database' WITH QUERY EXPANSION) AS score +FROM wp +ORDER BY score DESC LIMIT 2; +title score +MySQL vs. YourSQL 2.2718474864959717 +MySQL Tutorial 1.6663280725479126 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 1 +Sort_range 0 +Sort_rows 2 +Sort_scan 1 +FLUSH STATUS; +SELECT FTS_DOC_ID docid, +MATCH(title, text) AGAINST ('database' WITH QUERY EXPANSION) AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database'); +docid score +5 2.2718474864959717 +1 1.6663280725479126 +SHOW SESSION STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +SELECT FTS_DOC_ID docid, +MATCH(title, text) AGAINST ('database' WITH QUERY EXPANSION) AS score +FROM wp +ORDER BY score DESC LIMIT 2; +docid score +5 2.2718474864959717 +1 1.6663280725479126 +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 2 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 14 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 1 +Sort_range 0 +Sort_rows 2 +Sort_scan 1 +EXPLAIN SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' WITH QUERY EXPANSION); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE wp fulltext idx idx 0 1 Using where +FLUSH STATUS; +SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' WITH QUERY EXPANSION); +COUNT(*) +6 +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +SELECT MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) score, +title +FROM wp +WHERE MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) +ORDER BY score DESC; +score title +0.000000001885928302414186 1001 MySQL Tricks +0.000000001885928302414186 How To Use MySQL Well +0.000000001885928302414186 Optimizing MySQL +0.000000003771856604828372 MySQL Security +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 0 +Sort_range 0 +Sort_rows 4 +Sort_scan 1 +FLUSH STATUS; +SELECT MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) score, +title +FROM wp +ORDER BY score DESC; +score title +0 MySQL Tutorial +0 MySQL vs. YourSQL +0.000000001885928302414186 1001 MySQL Tricks +0.000000001885928302414186 How To Use MySQL Well +0.000000001885928302414186 Optimizing MySQL +0.000000003771856604828372 MySQL Security +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 0 +Sort_range 0 +Sort_rows 6 +Sort_scan 1 +FLUSH STATUS; +SELECT FTS_DOC_ID docid, +MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('+MySQL -database'); +docid score +5 0 +1 0 +6 0.000000003771856604828372 +2 0.000000001885928302414186 +3 0.000000001885928302414186 +4 0.000000001885928302414186 +SHOW SESSION STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +SELECT FTS_DOC_ID docid, +MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) AS score +FROM wp +ORDER BY score DESC LIMIT 1; +docid score +6 0.000000003771856604828372 +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 1 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 14 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 1 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +EXPLAIN SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('+MySQL -database' IN BOOLEAN MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE wp fulltext idx idx 0 1 Using where +FLUSH STATUS; +SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('+MySQL -database' IN BOOLEAN MODE); +COUNT(*) +4 +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +SELECT title, +MATCH(title, text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE) AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE) +ORDER BY score DESC; +title score +MySQL Tutorial 0.22764469683170319 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 0 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +FLUSH STATUS; +SELECT title, +MATCH(title, text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE) AS score +FROM wp +ORDER BY score DESC LIMIT 1; +title score +MySQL Tutorial 0.22764469683170319 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 1 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +FLUSH STATUS; +SELECT FTS_DOC_ID docid, +MATCH(title, text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE) AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('"MySQL database"@5'); +docid score +1 0.22764469683170319 +SHOW SESSION STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +SELECT FTS_DOC_ID docid, +MATCH(title, text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE) AS score +FROM wp +ORDER BY score DESC LIMIT 1; +docid score +1 0.22764469683170319 +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 1 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 14 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 1 +Sort_range 0 +Sort_rows 1 +Sort_scan 1 +EXPLAIN SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE wp fulltext idx idx 0 1 Using where +FLUSH STATUS; +SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE); +COUNT(*) +1 +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +SELECT title, +MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database' WITH QUERY EXPANSION) +ORDER BY score DESC, title ASC; +title score +MySQL vs. YourSQL 0.45528939366340637 +MySQL Tutorial 0.22764469683170319 +1001 MySQL Tricks 0 +How To Use MySQL Well 0 +MySQL Security 0 +Optimizing MySQL 0 +SELECT title, +MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('MySQL database' WITH QUERY EXPANSION) +ORDER BY score DESC, title ASC; +title score +MySQL Security 0.000000003771856604828372 +1001 MySQL Tricks 0.000000001885928302414186 +How To Use MySQL Well 0.000000001885928302414186 +Optimizing MySQL 0.000000001885928302414186 +MySQL Tutorial 0 +MySQL vs. YourSQL 0 +SELECT title, +MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE) +ORDER BY score DESC, title ASC; +title score +MySQL Tutorial 0 +ALTER TABLE wp ENGINE=myisam; +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score DESC; +title score +MySQL vs. YourSQL 0.9562782645225525 +MySQL Tutorial 0.5756555199623108 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 0 +Sort_range 0 +Sort_rows 2 +Sort_scan 1 +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +ORDER BY score DESC LIMIT 2; +title score +MySQL vs. YourSQL 0.9562782645225525 +MySQL Tutorial 0.5756555199623108 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 1 +Sort_range 0 +Sort_rows 2 +Sort_scan 1 +FLUSH STATUS; +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database'); +docid score +5 0.9562782645225525 +1 0.5756555199623108 +SHOW SESSION STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 3 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +FLUSH STATUS; +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +ORDER BY score DESC LIMIT 2; +docid score +5 0.9562782645225525 +1 0.5756555199623108 +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 2 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 14 +SHOW SESSION STATUS LIKE 'Sort%'; +Variable_name Value +Sort_merge_passes 0 +Sort_priority_queue_sorts 1 +Sort_range 0 +Sort_rows 2 +Sort_scan 1 +EXPLAIN SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE wp fulltext idx idx 0 1 Using where +FLUSH STATUS; +SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE); +COUNT(*) +2 +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_last 0 +Handler_read_next 3 +Handler_read_prev 0 +Handler_read_retry 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +DROP TABLE wp, t1; +CREATE TABLE t1 +( +FTS_DOC_ID BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, +title VARCHAR(255) DEFAULT '', +text MEDIUMTEXT , +PRIMARY KEY (FTS_DOC_ID), +UNIQUE KEY FTS_DOC_ID_INDEX (FTS_DOC_ID), +FULLTEXT KEY ft_idx (title,text) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t1 (title, text) VALUES +('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL database','In the following database to database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'), +('InnoDB', 'InnoDB is a transaction-safe (ACID compliant) storage engine'), +('MySQL is a database management system', 'A database is a structured collection of data...'), +('MySQL databases are relational', 'A relational database stores data in separate tables rather than putting all the data in one big storeroom...'), +('MySQL software is Open Source', 'Open Source means that it is possible for anyone to use and modify the software...'), +('The MySQL Database Server is very fast, reliable, scalable, and easy to use', 'MySQL Server can run comfortably on a desktop or laptop...'), +('MySQL Server works in client/server or embedded systems', 'The MySQL Database Software is a client/server system...'), +('MyISAM', 'MyISAM is based on the older (and no longer available) ISAM storage engine but has many useful extensions'), +('A large amount of contributed MySQL software is available', 'MySQL Server has a practical set of features developed in close cooperation with our users'), +(NULL,NULL); +ANALYZE TABLE t1; +# No ranking +EXPLAIN +SELECT count(*) FROM t1 WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where +SELECT count(*) FROM t1 WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE); +count(*) +6 +EXPLAIN +SELECT count(*) FROM t1 WHERE MATCH (title, text) AGAINST ('data*' IN BOOLEAN MODE) ORDER BY title LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where +SELECT count(*) FROM t1 WHERE MATCH (title, text) AGAINST ('data*' IN BOOLEAN MODE) ORDER BY title LIMIT 3; +count(*) +6 +EXPLAIN +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE); +FTS_DOC_ID title +11 The MySQL Database Server is very fast, reliable, scalable, and easy to use +EXPLAIN +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION); +FTS_DOC_ID title +11 The MySQL Database Server is very fast, reliable, scalable, and easy to use +12 MySQL Server works in client/server or embedded systems +10 MySQL software is Open Source +4 1001 MySQL Tricks +14 A large amount of contributed MySQL software is available +2 How To Use MySQL Well +13 MyISAM +5 MySQL vs. YourSQL database +8 MySQL is a database management system +1 MySQL Tutorial +9 MySQL databases are relational +6 MySQL Security +3 Optimizing MySQL +EXPLAIN +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('"very fast"@3' IN BOOLEAN MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('"very fast"@3' IN BOOLEAN MODE); +FTS_DOC_ID title +11 The MySQL Database Server is very fast, reliable, scalable, and easy to use +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+for' IN BOOLEAN MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+for' IN BOOLEAN MODE); +FTS_DOC_ID +# No sorting by rank +EXPLAIN SELECT FTS_DOC_ID, TITLE FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY title; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using filesort +SELECT FTS_DOC_ID, TITLE FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY title; +FTS_DOC_ID TITLE +9 MySQL databases are relational +8 MySQL is a database management system +12 MySQL Server works in client/server or embedded systems +1 MySQL Tutorial +5 MySQL vs. YourSQL database +11 The MySQL Database Server is very fast, reliable, scalable, and easy to use +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE); +FTS_DOC_ID +11 +EXPLAIN +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) ORDER BY title; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using filesort +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) ORDER BY title; +FTS_DOC_ID title +4 1001 MySQL Tricks +14 A large amount of contributed MySQL software is available +2 How To Use MySQL Well +13 MyISAM +9 MySQL databases are relational +8 MySQL is a database management system +6 MySQL Security +12 MySQL Server works in client/server or embedded systems +10 MySQL software is Open Source +1 MySQL Tutorial +5 MySQL vs. YourSQL database +3 Optimizing MySQL +11 The MySQL Database Server is very fast, reliable, scalable, and easy to use +EXPLAIN +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('"very fast"@3' IN BOOLEAN MODE) ORDER BY title; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using filesort +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('"very fast"@3' IN BOOLEAN MODE) ORDER BY title; +FTS_DOC_ID title +11 The MySQL Database Server is very fast, reliable, scalable, and easy to use +# LIMIT optimization +EXPLAIN SELECT FTS_DOC_ID, TITLE FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where +SELECT FTS_DOC_ID, TITLE FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +LIMIT 3; +FTS_DOC_ID TITLE +11 The MySQL Database Server is very fast, reliable, scalable, and easy to use +5 MySQL vs. YourSQL database +8 MySQL is a database management system +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE) +LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE) +LIMIT 3; +FTS_DOC_ID +11 +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE) +ORDER BY title +LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using filesort +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE) +ORDER BY title +LIMIT 3; +FTS_DOC_ID +11 +EXPLAIN +SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) ORDER BY title LIMIT 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using filesort +SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) ORDER BY title LIMIT 1; +FTS_DOC_ID +4 +EXPLAIN +SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ('"very fast"@3' IN BOOLEAN MODE) ORDER BY title LIMIT 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using filesort +SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ('"very fast"@3' IN BOOLEAN MODE) ORDER BY title LIMIT 1; +FTS_DOC_ID +11 +EXPLAIN +SELECT FTS_DOC_ID, MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) as rank +FROM t1 WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY rank, FTS_DOC_ID +LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using temporary; Using filesort +SELECT FTS_DOC_ID, MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) as rank +FROM t1 WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY rank, FTS_DOC_ID +LIMIT 3; +FTS_DOC_ID rank +1 0.15835624933242798 +9 0.15835624933242798 +12 0.15835624933242798 +EXPLAIN +SELECT FTS_DOC_ID, MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) as rank +FROM t1 WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY rank DESC, FTS_DOC_ID ASC +LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using temporary; Using filesort +SELECT FTS_DOC_ID, MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) as rank +FROM t1 WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY rank DESC, FTS_DOC_ID ASC +LIMIT 3; +FTS_DOC_ID rank +11 1.5415468215942383 +5 0.47506874799728394 +8 0.31671249866485596 +EXPLAIN SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 +ORDER BY rank DESC +LIMIT 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 15 Using temporary; Using filesort +SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 +ORDER BY rank DESC +LIMIT 2; +FTS_DOC_ID rank +5 0.47506874799728394 +8 0.31671249866485596 +EXPLAIN SELECT FTS_DOC_ID, MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) as rank +FROM t1 +ORDER BY rank DESC +LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 15 Using temporary; Using filesort +SELECT FTS_DOC_ID, MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) as rank +FROM t1 +ORDER BY rank DESC +LIMIT 3; +FTS_DOC_ID rank +11 1.5415468215942383 +5 0.47506874799728394 +8 0.31671249866485596 +EXPLAIN SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) +ORDER BY MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) DESC, +FTS_DOC_ID ASC; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using temporary; Using filesort +SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) +ORDER BY MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) DESC, +FTS_DOC_ID ASC; +FTS_DOC_ID rank +5 0.47506874799728394 +8 0.31671249866485596 +1 0.15835624933242798 +9 0.15835624933242798 +11 0.15835624933242798 +12 0.15835624933242798 +EXPLAIN SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) and FTS_DOC_ID > 1 +ORDER BY MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) DESC +LIMIT 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext PRIMARY,FTS_DOC_ID_INDEX,ft_idx ft_idx 0 1 Using where; Using temporary; Using filesort +SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) and FTS_DOC_ID > 1 +ORDER BY MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) DESC +LIMIT 2; +FTS_DOC_ID rank +5 0.47506874799728394 +8 0.31671249866485596 +EXPLAIN +SELECT FTS_DOC_ID,MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +ORDER BY rank +LIMIT 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using temporary; Using filesort +SELECT FTS_DOC_ID,MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +ORDER BY rank +LIMIT 1; +FTS_DOC_ID rank +3 0.009391550906002522 +EXPLAIN +SELECT FTS_DOC_ID,MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +ORDER BY rank DESC +LIMIT 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using temporary; Using filesort +SELECT FTS_DOC_ID,MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +ORDER BY rank DESC +LIMIT 1; +FTS_DOC_ID rank +11 15.345823287963867 +EXPLAIN +SELECT FTS_DOC_ID,MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +ORDER BY MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +LIMIT 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using temporary; Using filesort +SELECT FTS_DOC_ID,MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +ORDER BY MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) DESC +LIMIT 1; +FTS_DOC_ID rank +11 15.345823287963867 +# WHERE optimization on MATCH > 'some_rank' +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) > 0.1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) > 0.1; +FTS_DOC_ID +11 +5 +8 +1 +9 +12 +# additional test for correct behaviour +EXPLAIN SELECT * FROM t1 ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC LIMIT 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 15 Using temporary; Using filesort +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) AND +MATCH (title, text) AGAINST ('mysql' IN NATURAL LANGUAGE MODE) +LIMIT 6; +FTS_DOC_ID +11 +5 +8 +1 +9 +12 +# test OR condition +SELECT FTS_DOC_ID +FROM t1 +WHERE MATCH(title, text) AGAINST ('database') +OR MATCH(title, text) AGAINST ('mysql') +ORDER BY MATCH(title, text) AGAINST ('database') DESC, FTS_DOC_ID ASC; +FTS_DOC_ID +5 +8 +1 +9 +11 +12 +2 +3 +4 +6 +10 +14 +EXPLAIN SELECT FTS_DOC_ID +FROM t1 +WHERE MATCH(title, text) AGAINST ('database') +OR MATCH(title, text) AGAINST ('mysql') +ORDER BY MATCH(title, text) AGAINST ('database') DESC, FTS_DOC_ID ASC; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 15 Using where; Using temporary; Using filesort +# MATCH and GROUP BY, DISTINCT +SET sql_mode = (select replace(@@sql_mode,'ONLY_FULL_GROUP_BY','')); +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +GROUP BY FTS_DOC_ID +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using temporary; Using filesort +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +GROUP BY FTS_DOC_ID +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +FTS_DOC_ID +11 +5 +8 +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +GROUP BY title +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using temporary; Using filesort +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +GROUP BY title +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +FTS_DOC_ID +11 +5 +8 +EXPLAIN SELECT MAX(FTS_DOC_ID) FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where +SELECT MAX(FTS_DOC_ID) FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +MAX(FTS_DOC_ID) +12 +EXPLAIN SELECT DISTINCT(title) FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using temporary; Using filesort +SELECT DISTINCT(title) FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +title +The MySQL Database Server is very fast, reliable, scalable, and easy to use +MySQL vs. YourSQL database +MySQL is a database management system +EXPLAIN SELECT DISTINCT(FTS_DOC_ID) FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext ft_idx ft_idx 0 1 Using where; Using temporary; Using filesort +SELECT DISTINCT(FTS_DOC_ID) FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +FTS_DOC_ID +11 +5 +8 +SET sql_mode = @save_mode; +# FTS index access +SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 +ORDER BY rank DESC +LIMIT 2; +FTS_DOC_ID rank +5 0.47506874799728394 +8 0.31671249866485596 +EXPLAIN SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 +ORDER BY rank DESC +LIMIT 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 15 Using temporary; Using filesort +SELECT a.FTS_DOC_ID, b.FTS_DOC_ID +FROM t1 a, t1 b +WHERE MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE) and +MATCH(b.title, b.text) AGAINST ('+mysql' IN BOOLEAN MODE) and +a.FTS_DOC_ID = b.FTS_DOC_ID; +FTS_DOC_ID FTS_DOC_ID +5 5 +8 8 +1 1 +9 9 +11 11 +12 12 +EXPLAIN SELECT a.FTS_DOC_ID, b.FTS_DOC_ID +FROM t1 a, t1 b +WHERE MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE) and +MATCH(b.title, b.text) AGAINST ('+mysql' IN BOOLEAN MODE) and +a.FTS_DOC_ID = b.FTS_DOC_ID; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE a fulltext PRIMARY,FTS_DOC_ID_INDEX,ft_idx ft_idx 0 1 Using where +1 SIMPLE b eq_ref PRIMARY,FTS_DOC_ID_INDEX,ft_idx PRIMARY 8 test.a.FTS_DOC_ID 1 Using where +SELECT a.FTS_DOC_ID, MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE), +b.FTS_DOC_ID, MATCH(b.title, b.text) AGAINST ('+database' IN BOOLEAN MODE) +FROM t1 a, t1 b +WHERE MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE) and +MATCH(b.title, b.text) AGAINST ('+database' IN BOOLEAN MODE); +FTS_DOC_ID MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE) FTS_DOC_ID MATCH(b.title, b.text) AGAINST ('+database' IN BOOLEAN MODE) +5 0.47506874799728394 5 0.47506874799728394 +5 0.47506874799728394 8 0.31671249866485596 +5 0.47506874799728394 1 0.15835624933242798 +5 0.47506874799728394 9 0.15835624933242798 +5 0.47506874799728394 11 0.15835624933242798 +5 0.47506874799728394 12 0.15835624933242798 +8 0.31671249866485596 5 0.47506874799728394 +8 0.31671249866485596 8 0.31671249866485596 +8 0.31671249866485596 1 0.15835624933242798 +8 0.31671249866485596 9 0.15835624933242798 +8 0.31671249866485596 11 0.15835624933242798 +8 0.31671249866485596 12 0.15835624933242798 +1 0.15835624933242798 5 0.47506874799728394 +1 0.15835624933242798 8 0.31671249866485596 +1 0.15835624933242798 1 0.15835624933242798 +1 0.15835624933242798 9 0.15835624933242798 +1 0.15835624933242798 11 0.15835624933242798 +1 0.15835624933242798 12 0.15835624933242798 +9 0.15835624933242798 5 0.47506874799728394 +9 0.15835624933242798 8 0.31671249866485596 +9 0.15835624933242798 1 0.15835624933242798 +9 0.15835624933242798 9 0.15835624933242798 +9 0.15835624933242798 11 0.15835624933242798 +9 0.15835624933242798 12 0.15835624933242798 +11 0.15835624933242798 5 0.47506874799728394 +11 0.15835624933242798 8 0.31671249866485596 +11 0.15835624933242798 1 0.15835624933242798 +11 0.15835624933242798 9 0.15835624933242798 +11 0.15835624933242798 11 0.15835624933242798 +11 0.15835624933242798 12 0.15835624933242798 +12 0.15835624933242798 5 0.47506874799728394 +12 0.15835624933242798 8 0.31671249866485596 +12 0.15835624933242798 1 0.15835624933242798 +12 0.15835624933242798 9 0.15835624933242798 +12 0.15835624933242798 11 0.15835624933242798 +12 0.15835624933242798 12 0.15835624933242798 +EXPLAIN SELECT a.FTS_DOC_ID, MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE), +b.FTS_DOC_ID, MATCH(b.title, b.text) AGAINST ('+database' IN BOOLEAN MODE) +FROM t1 a, t1 b +WHERE MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE) and +MATCH(b.title, b.text) AGAINST ('+database' IN BOOLEAN MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE a fulltext ft_idx ft_idx 0 1 Using where +1 SIMPLE b fulltext ft_idx ft_idx 0 1 Using where +EXPLAIN SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ("data*" IN BOOLEAN MODE) * 100; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 15 Using where +SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ("data*" IN BOOLEAN MODE) * 100 +FROM t1 WHERE MATCH(title, text) AGAINST ("data*" IN BOOLEAN MODE) * 100; +FTS_DOC_ID MATCH(title, text) AGAINST ("data*" IN BOOLEAN MODE) * 100 +1 4.92168664932251 +5 14.76505994796753 +8 9.84337329864502 +9 4.92168664932251 +11 4.92168664932251 +12 4.92168664932251 +SELECT * FROM t1 WHERE title IS NULL AND text IS NULL; +FTS_DOC_ID title text +15 NULL NULL +CREATE TABLE t2 SELECT FTS_DOC_ID as doc_id, title, text FROM t1; +ALTER TABLE t2 ADD PRIMARY KEY (doc_id); +ALTER TABLE t2 ADD FULLTEXT KEY ft_idx (title,text); +ANALYZE TABLE t2; +EXPLAIN SELECT DOC_ID FROM t2 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) * 100; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 15 Using where +SELECT DOC_ID FROM t2 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) * 100; +DOC_ID +1 +5 +8 +9 +11 +12 +EXPLAIN SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) * 100; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 15 Using where +SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) * 100; +FTS_DOC_ID +1 +5 +8 +9 +11 +12 +DROP TABLE t1, t2; +"Check hints with uft8 charset for 2 cases" +set names utf8; +CREATE TABLE t1 ( +FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +text TEXT +) CHARACTER SET = utf8, ENGINE=InnoDB; +INSERT INTO t1 (title, text) VALUES +('Я могу еÑть Ñтекло', 'оно мне не вредит'), +('Мога да Ñм Ñтъкло', 'то не ми вреди'), +('ΜποÏá¿¶ νὰ φάω σπασμένα' ,'γυαλιὰ χωÏá½¶Ï‚ νὰ πάθω τίποτα'), +('PříliÅ¡ žluÅ¥ouÄký kůň', 'úpÄ›l Äábelské kódy'), +('Sævör grét', 'áðan því úlpan var ónýt'), +('ã†ã‚ã®ãŠãã‚„ã¾','ã‘ãµã“ãˆã¦'), +('ã„ã‚ã¯ã«ã»ã¸ã©ã€€ã¡ã‚Šã¬ã‚‹','ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš'); +CREATE FULLTEXT INDEX idx on t1 (title, text); +# No ranking +EXPLAIN +SELECT count(*) FROM t1 WHERE MATCH (title, text) AGAINST ('вредит' IN NATURAL LANGUAGE MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext idx idx 0 1 Using where +SELECT count(*) FROM t1 WHERE MATCH (title, text) AGAINST ('вредит' IN NATURAL LANGUAGE MODE); +count(*) +1 +EXPLAIN +SELECT * FROM t1 WHERE MATCH(title, text) AGAINST ("оно" WITH QUERY EXPANSION); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext idx idx 0 1 Using where +SELECT * FROM t1 WHERE MATCH(title, text) AGAINST ("оно" WITH QUERY EXPANSION); +FTS_DOC_ID title text +1 Я могу еÑть Ñтекло оно мне не вредит +# No sorting by rank +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+(Мога τίποτα)' IN BOOLEAN MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext idx idx 0 1 Using where +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+(Мога τίποτα)' IN BOOLEAN MODE); +FTS_DOC_ID +2 +3 +DROP TABLE t1; +# +# Bug #18924341 CRASH IN TEST_IF_SKIP_SORT_ORDER, GROUP BY MATCH AGAINST DESC +# +CREATE TABLE t1 (f1 CHAR(1), FULLTEXT KEY (f1)); +SELECT 1 FROM t1 NATURAL JOIN t1 a GROUP BY MATCH(t1.f1) AGAINST ("1") DESC; +1 +DROP TABLE t1; +# +# Bug#20261601 ASSERTION FAILED: !FIRST_QEP_TAB->TABLE()->NO_KEYREAD +# +CREATE TABLE t1(a INT PRIMARY KEY); +INSERT INTO t1 VALUES(1),(2); +SELECT (SELECT MATCH(`a`)AGAINST('1') FROM t1) FROM t1; +ERROR HY000: Can't find FULLTEXT index matching the column list +SELECT 1, a IN (SELECT a FROM t1) FROM t1; +1 a IN (SELECT a FROM t1) +1 1 +1 1 +DROP TABLE t1; +# +# Bug#20442572 ASSERTION `!FIRST_QEP_TAB->TABLE()->NO_KEYREAD' FAILED. +# Bug#75688 Assertion `!first_qep_tab->table()->no_keyread' failed. +# +CREATE TABLE t1(a INT,b POINT NOT NULL,KEY(a)); +HANDLER t1 OPEN; +select * from t1 where MATCH a,b AGAINST('"Now sUPPort"' IN BOOLEAN MODE); +a b +prepare stmt1 from "truncate t1"; +SELECT a IN(SELECT a FROM t1)FROM t1; +a IN(SELECT a FROM t1) +deallocate prepare stmt1; +DROP TABLE t1; +# +# Bug #20685427 INVALID WRITE OF FREED MEMORY IN ITEM_FUNC_MATCH::CLEANUP +# +CREATE TABLE t1(a TEXT CHARSET LATIN1, FULLTEXT KEY(a)) ENGINE=INNODB; +SELECT MATCH(a) AGAINST ('') FROM (SELECT a FROM t1 LIMIT 1) q; +ERROR HY000: Can't find FULLTEXT index matching the column list +DROP TABLE t1; +# +# Bug#21140067 EXPLAIN .. MATCH AGAINST: ASSERTION FAILED: TO <= END +# +CREATE TABLE t1(f1 CHAR(1) CHARSET latin1, FULLTEXT(f1)) ENGINE=INNODB; +EXPLAIN SELECT 1 FROM t1 WHERE 1.238585e+308 <= MATCH(f1) AGAINST ('1' IN BOOLEAN MODE); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext f1 f1 0 1 Using where +EXPLAIN FORMAT = JSON SELECT 1 FROM t1 WHERE 1.238585e+308 <= MATCH(f1) AGAINST ('1' IN BOOLEAN MODE); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "fulltext", + "possible_keys": ["f1"], + "key": "f1", + "key_length": "0", + "used_key_parts": ["f1"], + "rows": 1, + "filtered": 100, + "attached_condition": "1.238585e+308 <= (match t1.f1 against ('1' in boolean mode))" + } + } +} +DROP TABLE t1; +# +# Bug#21140088 MATCH AGAINST: ASSERTION FAILED: !TABLE || (!TABLE->READ_SET || BITMAP_IS_SET +# +SET sql_mode=''; +CREATE TABLE t1(a INT) ENGINE=INNODB; +CREATE TABLE t2(b TEXT CHARSET LATIN1, FULLTEXT(b), PRIMARY KEY(b(10))) ENGINE=INNODB; +INSERT INTO t2 VALUES ('a'),('b'); +SELECT NOT EXISTS (SELECT MATCH(b) AGAINST ('1') FROM t1) FROM t2 GROUP BY "a"; +ERROR HY000: Incorrect arguments to MATCH +DROP TABLE t1, t2; +CREATE TABLE t1(a INT) ENGINE=MyISAM; +CREATE TABLE t2(b TEXT CHARSET LATIN1, FULLTEXT(b), PRIMARY KEY(b(10))) ENGINE=MyISAM; +INSERT INTO t2 VALUES ('a'),('b'); +SELECT NOT EXISTS (SELECT MATCH(b) AGAINST ('1' in BOOLEAN MODE) FROM t1) FROM t2 GROUP BY "a"; +NOT EXISTS (SELECT MATCH(b) AGAINST ('1' in BOOLEAN MODE) FROM t1) +1 +DROP TABLE t1, t2; +SET sql_mode=default; +# +# Bug#21140039 ASSERTION FAILED: !FIRST_QEP_TAB->TABLE()->NO_KEYREAD MATCH AGAINST..... +# +CREATE TABLE t1 +( +a INT, +b INT, +c CHAR(1) CHARSET latin1, +PRIMARY KEY (b,a), +FULLTEXT KEY (c) +) ENGINE=INNODB; +SELECT "a" NOT IN(SELECT b FROM t1 WHERE MATCH(c) AGAINST ('a' IN BOOLEAN MODE)); +"a" NOT IN(SELECT b FROM t1 WHERE MATCH(c) AGAINST ('a' IN BOOLEAN MODE)) +1 +DROP TABLE t1; +# +# Bug#21300774 ASSERT `!INIT_FTFUNCS(THD, SELECT_LEX)` IN JOIN::RESET AT SQL/SQL_SELECT.CC:874 +# +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +CREATE TABLE t2 (ft TEXT, FULLTEXT KEY ft(ft)); +INSERT INTO t2 VALUES ('abc'); +INSERT INTO t2 VALUES ('def'); +UPDATE t1 SET f1 = +(SELECT t1.f1 FROM t2 WHERE NOT TRUE AND +MATCH (ft) AGAINST ((SELECT 'xyz' FROM t2))); +ERROR 21000: Subquery returns more than 1 row +DROP TABLE t1, t2; +# +# Bug#22679209: FULL-TEXT QUERIES WITH ADDITIONAL SECONDARY INDEX +# GIVES NULL OR ZERO ROWS +# +CREATE TABLE t1 ( +f1 INTEGER, +title varchar(255), +body mediumtext, +KEY f1 (f1), +FULLTEXT KEY title (title), +FULLTEXT KEY body (body) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(1, 'Insert into table', 'insert into table select from'), +(1, 'Delete from table', 'insert into table select from'), +(1, 'Update', 'perform update'), +(2, 'Insert into table', 'insert into table select from'), +( 2, 'Delete from table', 'some body text here'), +( 2, 'Update', 'perform update'), +( 3, 'Insert into table', 'insert into table select from'), +( 3, 'Delete from table', 'some body text here'); +SELECT f1 FROM t1 WHERE f1=1 AND +(MATCH (title) AGAINST ('table' IN BOOLEAN MODE) OR +MATCH (body) AGAINST ('table' IN BOOLEAN MODE)); +f1 +1 +1 +DROP TABLE t1; +# End of test for Bug#22679209 diff --git a/mysql-test/suite/innodb_fts/r/phrase.result b/mysql-test/suite/innodb_fts/r/phrase.result new file mode 100644 index 00000000000..efcbaeac66c --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/phrase.result @@ -0,0 +1,84 @@ +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles (title,body) VALUES +(NULL, 'mysql good database'), +(NULL, ' mysql good database'), +('', 'mysql good database'), +('', ' mysql good database'), +(' ', 'mysql good database'), +('mysql', 'good database'), +('mysql ', 'good database'), +('mysql', ' good database'), +('mysql good database', ''), +('mysql good database', NULL); +SET GLOBAL innodb_ft_aux_table="test/articles"; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +database 1 10 10 1 11 +database 1 10 10 2 12 +database 1 10 10 3 11 +database 1 10 10 4 12 +database 1 10 10 5 13 +database 1 10 10 6 11 +database 1 10 10 7 12 +database 1 10 10 8 12 +database 1 10 10 9 11 +database 1 10 10 10 11 +good 1 10 10 1 6 +good 1 10 10 2 7 +good 1 10 10 3 6 +good 1 10 10 4 7 +good 1 10 10 5 8 +good 1 10 10 6 6 +good 1 10 10 7 7 +good 1 10 10 8 7 +good 1 10 10 9 6 +good 1 10 10 10 6 +mysql 1 10 10 1 0 +mysql 1 10 10 2 1 +mysql 1 10 10 3 0 +mysql 1 10 10 4 1 +mysql 1 10 10 5 2 +mysql 1 10 10 6 0 +mysql 1 10 10 7 0 +mysql 1 10 10 8 0 +mysql 1 10 10 9 0 +mysql 1 10 10 10 0 +SET GLOBAL innodb_ft_aux_table=default; +SELECT * FROM articles; +id title body +1 NULL mysql good database +2 NULL mysql good database +3 mysql good database +4 mysql good database +5 mysql good database +6 mysql good database +7 mysql good database +8 mysql good database +9 mysql good database +10 mysql good database NULL +SELECT * FROM articles WHERE MATCH(title, body) +AGAINST('"mysql good database"' IN BOOLEAN MODE); +id title body +1 NULL mysql good database +2 NULL mysql good database +3 mysql good database +4 mysql good database +5 mysql good database +9 mysql good database +10 mysql good database NULL +SELECT * FROM articles WHERE MATCH(title, body) +AGAINST('("mysql good database")' IN BOOLEAN MODE); +id title body +1 NULL mysql good database +2 NULL mysql good database +3 mysql good database +4 mysql good database +5 mysql good database +9 mysql good database +10 mysql good database NULL +DROP TABLE articles; diff --git a/mysql-test/suite/innodb_fts/r/result_cache_limit.result b/mysql-test/suite/innodb_fts/r/result_cache_limit.result new file mode 100644 index 00000000000..4f13f4e702e --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/result_cache_limit.result @@ -0,0 +1,31 @@ +CREATE TABLE t1 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +a VARCHAR(200), +b TEXT +) ENGINE= InnoDB; +CREATE FULLTEXT INDEX idx on t1 (a,b); +INSERT INTO t1 (a,b) VALUES +('MySQL from Tutorial','DBMS stands for DataBase ...') , +('when To Use MySQL Well','After that you went through a ...'), +('where will Optimizing MySQL','what In this tutorial we will show ...'), +('MySQL from Tutorial','DBMS stands for DataBase ...') , +('when To Use MySQL Well','After that you went through a ...'), +('where will Optimizing MySQL','what In this tutorial we will show ...'), +('MySQL from Tutorial','DBMS stands for DataBase ...') , +('when To Use MySQL Well','After that you went through a ...'), +('where will Optimizing MySQL','what In this tutorial we will show ...'); +SET @save_limit=@@GLOBAL.innodb_ft_result_cache_limit; +SET @save_dbug=@@debug_dbug; +SET debug_dbug="+d,fts_instrument_result_cache_limit"; +SELECT COUNT(*) FROM t1 WHERE MATCH (a,b) AGAINST ('mysql' IN BOOLEAN MODE); +COUNT(*) +9 +SELECT COUNT(*) FROM t1 WHERE MATCH (a,b) AGAINST ('mysql' WITH QUERY EXPANSION); +ERROR HY000: Table handler out of memory +SELECT COUNT(*) FROM t1 WHERE MATCH (a,b) AGAINST ('"mysql database"' IN BOOLEAN MODE); +ERROR HY000: Table handler out of memory +SELECT COUNT(*) FROM t1 WHERE MATCH (a,b) AGAINST ('"mysql database" @ 5' IN BOOLEAN MODE); +ERROR HY000: Table handler out of memory +SET debug_dbug=@save_dbug; +DROP TABLE t1; +SET GLOBAL innodb_ft_result_cache_limit=@save_limit; diff --git a/mysql-test/suite/innodb_fts/r/savepoint.result b/mysql-test/suite/innodb_fts/r/savepoint.result new file mode 100644 index 00000000000..1abfc961d0a --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/savepoint.result @@ -0,0 +1,318 @@ +CREATE TABLE articles ( +id INT UNSIGNED NOT NULL PRIMARY KEY, +title VARCHAR(200), +FULLTEXT (title) +) ENGINE= InnoDB; +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +ROLLBACK TO SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +COMMIT; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +2 mysql +4 mysql +5 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +ROLLBACK TO SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +ROLLBACK TO SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(6, 'mysql'); +COMMIT; +INSERT INTO articles(id, title) VALUES(7, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +2 mysql +4 mysql +6 mysql +7 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +ROLLBACK TO SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +COMMIT; +INSERT INTO articles(id, title) VALUES(6, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +2 mysql +5 mysql +6 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +ROLLBACK TO SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +ROLLBACK TO SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(6, 'mysql'); +COMMIT; +INSERT INTO articles(id, title) VALUES(7, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +2 mysql +6 mysql +7 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +RELEASE SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +COMMIT; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +2 mysql +3 mysql +4 mysql +5 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +RELEASE SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +RELEASE SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(6, 'mysql'); +COMMIT; +INSERT INTO articles(id, title) VALUES(7, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +2 mysql +3 mysql +4 mysql +5 mysql +6 mysql +7 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +RELEASE SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +COMMIT; +INSERT INTO articles(id, title) VALUES(6, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +2 mysql +3 mysql +4 mysql +5 mysql +6 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +RELEASE SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +RELEASE SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(6, 'mysql'); +COMMIT; +INSERT INTO articles(id, title) VALUES(7, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +2 mysql +3 mysql +4 mysql +5 mysql +6 mysql +7 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +ROLLBACK TO SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +RELEASE SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(6, 'mysql'); +COMMIT; +INSERT INTO articles(id, title) VALUES(7, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +2 mysql +4 mysql +5 mysql +6 mysql +7 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +RELEASE SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +ROLLBACK TO SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(6, 'mysql'); +COMMIT; +INSERT INTO articles(id, title) VALUES(7, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +2 mysql +3 mysql +4 mysql +6 mysql +7 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +RELEASE SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +ROLLBACK TO SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(6, 'mysql'); +COMMIT; +INSERT INTO articles(id, title) VALUES(7, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +2 mysql +6 mysql +7 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +ROLLBACK TO SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +RELEASE SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(6, 'mysql'); +COMMIT; +INSERT INTO articles(id, title) VALUES(7, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +2 mysql +3 mysql +5 mysql +6 mysql +7 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +ROLLBACK; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +3 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +ROLLBACK; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +4 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +RELEASE SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +ROLLBACK; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +5 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +ROLLBACK TO SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +ROLLBACK; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +5 mysql +TRUNCATE TABLE articles; +INSERT INTO articles(id, title) VALUES(1, 'mysql'); +BEGIN; +INSERT INTO articles(id, title) VALUES(2, 'mysql'); +SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(3, 'mysql'); +SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(4, 'mysql'); +ROLLBACK TO SAVEPOINT sp2; +INSERT INTO articles(id, title) VALUES(5, 'mysql'); +RELEASE SAVEPOINT sp1; +INSERT INTO articles(id, title) VALUES(6, 'mysql'); +ROLLBACK; +INSERT INTO articles(id, title) VALUES(7, 'mysql'); +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); +id title +1 mysql +7 mysql +DROP TABLE articles; diff --git a/mysql-test/suite/innodb_fts/r/subexpr.result b/mysql-test/suite/innodb_fts/r/subexpr.result new file mode 100644 index 00000000000..cf476abb893 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/subexpr.result @@ -0,0 +1,105 @@ +# +# Bug #20028323 INNODB FULLTEXT BOOLEAN SEARCH INCORRECTLY HANDLES +# PARENTHESES +# +CREATE TABLE t1 ( +f1 INT NOT NULL AUTO_INCREMENT, +f2 TEXT NOT NULL, +PRIMARY KEY (f1), +FULLTEXT (f2) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT INTO t1 (f2) VALUES +('Pumpkin soup with cheese bread'), +('Yellow chicken curry'), +('Fresh green vegetables with garlic'); +SELECT * FROM t1 WHERE MATCH(f2) AGAINST('+pumpkin' IN BOOLEAN MODE); +f1 f2 +1 Pumpkin soup with cheese bread +SELECT * FROM t1 WHERE MATCH(f2) AGAINST('+cheese' IN BOOLEAN MODE); +f1 f2 +1 Pumpkin soup with cheese bread +SELECT * FROM t1 WHERE MATCH(f2) AGAINST('+(pumpkin cheese)' IN BOOLEAN MODE); +f1 f2 +1 Pumpkin soup with cheese bread +SELECT * FROM t1 WHERE MATCH(f2) +AGAINST('+pumpkin +(souffle)' IN BOOLEAN MODE); +f1 f2 +SELECT * FROM t1 WHERE MATCH(f2) +AGAINST('+pumpkin +(souffle tart)' IN BOOLEAN MODE); +f1 f2 +SELECT * FROM t1 WHERE MATCH(f2) +AGAINST('+pumpkin +(>souffle souffle = 1 +#AND t1.id <=3 ; + +# proximity search +# insert for proximity search +INSERT INTO t1 (a,b) VALUES ('test query expansion','for database ...'); +# Insert into table with similar word of different distances +INSERT INTO t1 (a,b) VALUES + ('test proximity search, test, proximity and phrase', + 'search, with proximity innodb'); + +INSERT INTO t1 (a,b) VALUES + ('test proximity fts search, test, proximity and phrase', + 'search, with proximity innodb'); + +INSERT INTO t1 (a,b) VALUES + ('test more proximity fts search, test, more proximity and phrase', + 'search, with proximity innodb'); + + +SELECT id FROM t1 WHERE t1.id = (SELECT MAX(t2.id) FROM t1 AS t2 WHERE +MATCH(t2.a,t2.b) AGAINST ('"proximity search"@2' IN BOOLEAN MODE)); +SELECT id FROM t1 WHERE t1.id > (SELECT MIN(t2.id) FROM t1 AS t2 WHERE +MATCH(t2.a,t2.b) AGAINST ('"proximity search"@2' IN BOOLEAN MODE)); + +SELECT id FROM t1 WHERE t1.id IN (SELECT t2.id FROM t1 AS t2 WHERE +MATCH (t2.a,t2.b) AGAINST ('"proximity search"@2' IN BOOLEAN MODE)); + +SELECT id FROM t1 WHERE EXISTS (SELECT id FROM t1 AS t2 WHERE +MATCH t2.a,t2.b AGAINST ('"proximity search"@2' IN BOOLEAN MODE) +AND t2.id=t1.id); + +SELECT id FROM t1 WHERE EXISTS (SELECT id FROM t1 AS t2 WHERE +MATCH t2.a,t2.b AGAINST ('"more test proximity"@3' IN BOOLEAN MODE) +AND t2.id=t1.id); + +SELECT id FROM t1 WHERE EXISTS (SELECT id FROM t1 AS t2 WHERE +MATCH t2.a,t2.b AGAINST ('"more test proximity"@2' IN BOOLEAN MODE) +AND t2.id=t1.id); + + +#------------------------------------------------------------------------------ +# create table AS SELECT from fts indexed table +#------------------------------------------------------------------------------ +CREATE TABLE t2 ENGINE = InnoDB AS SELECT id FROM t1 WHERE +MATCH a,b AGAINST ('support') ; +SHOW CREATE TABLE t2; +SELECT id FROM t2; +DROP TABLE t2; + +CREATE TABLE t2 ENGINE = InnoDB AS SELECT id FROM t1 WHERE +MATCH a,b AGAINST("+support +collections" IN BOOLEAN MODE); +SHOW CREATE TABLE t2; +SELECT id FROM t2; +DROP TABLE t2; + +CREATE TABLE t2 ENGINE = InnoDB AS SELECT id FROM t1 WHERE +MATCH a,b AGAINST ('"proximity search"@10' IN BOOLEAN MODE); +SHOW CREATE TABLE t2; +SELECT id FROM t2; +DROP TABLE t2; + +DROP TABLE t1; + + +#------------------------------------------------------------------------------ +# Verift FTS with NULL records +#------------------------------------------------------------------------------ +# Create FTS table +EVAL CREATE TABLE t1 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a VARCHAR(200), + b TEXT + ) ENGINE = InnoDB; + +# Create the FTS index again +CREATE FULLTEXT INDEX idx on t1 (a,b); + + +# Insert rows +INSERT INTO t1 (a,b) VALUES +('MySQL from Tutorial','DBMS stands for DataBase ...'); + +let $counter = 50; +--disable_query_log +WHILE ($counter > 0) { + INSERT INTO t1 (a,b) VALUES (NULL,NULL); + dec $counter; +} +--enable_query_log +INSERT INTO t1 (a,b) VALUES +('when To Use MySQL Well','After that you went through a ...'); + +let $counter = 50; +--disable_query_log +WHILE ($counter > 0) { + INSERT INTO t1 (a,b) VALUES (NULL,NULL); + dec $counter; +} +--enable_query_log +INSERT INTO t1 (a,b) VALUES +('where will Optimizing MySQL','what In this tutorial we will show ...'); + +INSERT INTO t1 (a,b) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL null...'); + +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM t1 WHERE a IS NULL; +SELECT COUNT(*) FROM t1 WHERE b IS NOT NULL; + +SELECT id FROM t1 + WHERE MATCH (a,b) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + +SELECT id FROM t1 + WHERE MATCH (a,b) + AGAINST (NULL IN NATURAL LANGUAGE MODE); +SELECT id FROM t1 + WHERE MATCH (a,b) + AGAINST (NULL WITH QUERY EXPANSION); +SELECT id FROM t1 + WHERE MATCH (a,b) + AGAINST ('null' IN NATURAL LANGUAGE MODE); +# Boolean search +# Select rows contain "MySQL" but not "YourSQL" +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE); +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE) AND (a IS NOT NULL OR b IS NOT NULL); +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE) AND (a IS NULL AND b IS NOT NULL); + +# Select rows contain at least one of the two words +SELECT id FROM t1 WHERE MATCH (a,b) +AGAINST ('DBMS Security' IN BOOLEAN MODE); + +# Test query expansion +SELECT COUNT(*) FROM t1 +WHERE MATCH (a,b) +AGAINST ('database' WITH QUERY EXPANSION); + +# proximity +SELECT id FROM t1 +WHERE MATCH (a,b) +AGAINST ('"following database"@10' IN BOOLEAN MODE); + + +DROP TABLE t1; + + + +#------------------------------------------------------------------------------ +# More FTS test from peter's testing +#------------------------------------------------------------------------------ +--disable_warnings +drop table if exists t50; +--enable_warnings + +set names utf8; + + +--echo "----------Test1---------" +# Create FTS table +create table t50 (s1 varchar(60) character set utf8 collate utf8_bin) engine = innodb; +create fulltext index i on t50 (s1); +# INNODB_FTS: Assert - fixed +# Assert : InnoDB: Failing assertion: rbt_validate(result_doc->tokens) +insert into t50 values ('ABCDE'),('FGHIJ'),('KLMNO'),('VÃÆ·Wİ'); +# it was giving empty result set instead of one record +select * from t50 where match(s1) against ('VÃÆ·Wİ'); +drop table t50; + + +--echo "----------Test2---------" +create table t50 (s1 int unsigned primary key auto_increment, s2 +varchar(60) character set utf8) engine = innodb; +create fulltext index i on t50 (s2); +insert into t50 (s2) values ('FGHIJ'),('KLMNO'),('VÃÆ·Wİ'),('ABCDE'); +# INNODB_FTS: RESULT DIFF +# Order by does not sort result. +# Optimizer's Evgeny is investigate a similar issue. InnoDB FTS is used only +# for FT search, and should not be used as regular index for such order by query. +# Correct the result file when fixed. +select * from t50 order by s2; +drop table t50; + + +--echo "----------Test3---------" +create table t50 (id int unsigned primary key auto_increment, s2 +varchar(60) character set utf8) engine = innodb; +create fulltext index i on t50 (s2); +insert into t50 (s2) values ('FGHIJ'),('KLMNO'),('VÃÆ·Wİ'),('ABCDE'); +set @@autocommit=0; +update t50 set s2 = lower(s2); +update t50 set s2 = upper(s2); +commit; +select * from t50 where match(s2) against ('VÃÆ·Wİ FGHIJ KLMNO ABCDE' in boolean mode); +select * from t50; +drop table t50; +set @@autocommit=1; + +--echo "----------Test4---------" +create table t50 (id int unsigned primary key auto_increment, s2 +varchar(60) character set utf8) engine = innodb; +create fulltext index i on t50 (s2); +insert into t50 (s2) values ('FGHIJ'),('KLMNO'),('VÃÆ·Wİ'),('ABCD*'); +select * from t50 where match(s2) against ('abcd*' in natural language +mode); +# INNODB_FTS: RESULT DIFF(Expected). InnoDB do not index "*", so +# word "ABCD" indexed, instead of "ABCD*" +select * from t50 where match(s2) against ('abcd*' in boolean mode); +drop table t50; + + +--echo "----------Test5---------" +create table t50 (s1 int, s2 varchar(200), fulltext key(s2)) engine = innodb; +set @@autocommit=0; +insert into t50 values (1,'Sunshine'),(2,'Lollipops'); +select * from t50 where match(s2) against('Rainbows'); +rollback; +select * from t50; +drop table t50; +set @@autocommit=1; + +--echo "----------Test6---------" +CREATE TABLE t1 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a VARCHAR(200), + b TEXT + ) ENGINE = InnoDB; + +# Insert rows +INSERT INTO t1 (a,b) VALUES + ('aab` MySQL Tutorial','DBMS stands for DataBase ...') , + ('aas How To Use MySQL Well','After you went through a ...'), + ('aac Optimizing MySQL','In this tutorial we will show ...'); +# Insert rows +INSERT INTO t1 (a,b) VALUES + ('aac 1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('aab MySQL vs. YourSQL','In the following database comparison ...'), + ('aaa MySQL Security','When configured properly, MySQL ...'); +# Create the FTS index Using Alter Table +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); + +-- disable_query_log +-- disable_result_log +ANALYZE TABLE t1; +-- enable_result_log +-- enable_query_log + +SELECT * FROM t1 ORDER BY MATCH(a,b) AGAINST ('aac') DESC; +SELECT * FROM t1 ORDER BY MATCH(a,b) AGAINST ('aab') DESC; + +--echo "----------Test7---------" +select * from t1 where match(a,b) against ('aaa') +union select * from t1 where match(a,b) against ('aab') +union select * from t1 where match(a,b) against ('aac'); + +select * from t1 where match(a,b) against ('aaa') + or match(a,b) against ('aab') + or match(a,b) against ('aac'); + +DROP TABLE t1; + +--echo "----------Test8---------" +# Create FTS table +CREATE TABLE t1 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a VARCHAR(200), + b TEXT + ) ENGINE = InnoDB; + +# Insert rows +INSERT INTO t1 (a,b) VALUES + ('MySQL Tutorial','DBMS stands for DataBase ... abcd') , + ('How To Use MySQL Well','After you went through a q ...abdd'), + ('Optimizing MySQL','In this tutorial we will show ...abed'); + +# Create the FTS index Using Alter Table +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); +EVAL SHOW CREATE TABLE t1; + +# Insert rows +INSERT INTO t1 (a,b) VALUES + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. q ...'), + ('MySQL vs. YourSQL use','In the following database comparison ...'), + ('MySQL Security','When run configured properly, MySQL ...'); + +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('run'); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('use'); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('went'); +# rows should be matched as 'q' is single char its not indexed +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('run') AND NOT MATCH(a,b) AGAINST ('q'); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('use') AND NOT MATCH(a,b) AGAINST ('q'); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('went') AND NOT MATCH(a,b) AGAINST ('q'); + +--echo "----------Test9---------" +CREATE TABLE t2 AS SELECT * FROM t1; +ALTER TABLE t2 ENGINE=MYISAM; +CREATE FULLTEXT INDEX i ON t2 (a,b); +SET @x = (SELECT COUNT(*) FROM t1 WHERE MATCH(a,b) AGAINST ('run')); +SET @x = @x + (SELECT COUNT(*) FROM t1 WHERE MATCH(a,b) AGAINST ('use')); +SET @x = @x + (SELECT COUNT(*) FROM t1 WHERE MATCH(a,b) AGAINST ('went')); +SET @x = @x + (SELECT COUNT(*) FROM t1 WHERE MATCH(a,b) AGAINST ('run')); +SET @x2 = (SELECT COUNT(*) FROM t2 WHERE MATCH(a,b) AGAINST ('run')); +SET @x2 = @x2 + (SELECT COUNT(*) FROM t2 WHERE MATCH(a,b) AGAINST ('use')); +SET @x2 = @x2 + (SELECT COUNT(*) FROM t2 WHERE MATCH(a,b) AGAINST ('went')); +SET @x2 = @x2 + (SELECT COUNT(*) FROM t2 WHERE MATCH(a,b) AGAINST ('run')); +# Innodb returns value for x which is correct +SELECT @x, @x2; + + +DROP TABLE t2; + +--echo "----------Test10---------" +CREATE TABLE t2 AS SELECT * FROM t1; +ALTER TABLE t2 ENGINE=MYISAM; +CREATE FULLTEXT INDEX i ON t2 (a,b); +SELECT COUNT(*) FROM t2 WHERE MATCH(a,b) AGAINST ('abc*' IN BOOLEAN MODE); +SELECT COUNT(*) FROM t1 WHERE MATCH(a,b) AGAINST ('abc*' IN BOOLEAN MODE); + +DROP TABLE t2; + + +--echo "----------Test11---------" +CREATE TABLE t2 AS SELECT * FROM t1; +ALTER TABLE t2 ENGINE = MYISAM; +CREATE FULLTEXT INDEX i ON t2 (a,b); +ALTER TABLE t2 ENGINE=InnoDB; +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ('run'); +SELECT COUNT(*) FROM t2 WHERE MATCH(a,b) AGAINST ('abc*' IN BOOLEAN MODE); +DROP TABLE t2,t1; + + +--echo "----------Test13---------" +set names utf8; + +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200) CHARACTER SET UTF8 COLLATE UTF8_SPANISH_CI) ENGINE = InnoDB; +CREATE FULLTEXT INDEX i ON t1 (s2); +INSERT INTO t1 VALUES (1,'aaCen'),(2,'aaCha'),(3,'aaCio'),(4,'aaçen'),(5,'aaçha'),(6,'aaçio'); +SELECT * FROM t1 WHERE MATCH(s2) AGAINST ('aach*' IN BOOLEAN MODE); +SELECT * FROM t1 WHERE MATCH(s2) AGAINST ('aaC*' IN BOOLEAN MODE); +DROP TABLE t1; + +--echo "----------Test14---------" +CREATE TABLE t1(s1 INT , s2 VARCHAR(100) CHARACTER SET sjis) ENGINE = InnoDB; +CREATE FULLTEXT INDEX i ON t1 (s2); +INSERT INTO t1 VALUES (1,'ペペペ'),(2,'テテテ'),(3,'ルルル'),(4,'ã‚°ã‚°ã‚°'); +# Innodb Asset : file ha_innodb.cc line 4557 +#SELECT * FROM t1 WHERE MATCH(s2) AGAINST ('テテ*' IN BOOLEAN MODE); +DROP TABLE t1; + + +--echo "----------Test15---------" +CREATE TABLE t1 (s1 VARCHAR (60) CHARACTER SET UTF8 COLLATE UTF8_UNICODE_520_CI) ENGINE = MyISAM; +CREATE FULLTEXT INDEX i ON t1 (s1); +INSERT INTO t1 VALUES +('a'),('b'),('c'),('d'),('ÅÅÅÅ'),('LLLL'),(NULL),('ÅÅÅÅ ÅÅÅÅ'),('LLLLLLLL'); +SELECT * FROM t1 WHERE MATCH(s1) AGAINST ('LLLL' COLLATE UTF8_UNICODE_520_CI); +DROP TABLE if EXISTS t2; +CREATE TABLE t2 (s1 VARCHAR(60) CHARACTER SET UTF8 COLLATE UTF8_POLISH_CI) ENGINE = InnoDB; +CREATE FULLTEXT INDEX i ON t2 ( s1); +INSERT INTO t2 VALUES +('a'),('b'),('c'),('d'),('ÅÅÅÅ'),('LLLL'),(NULL),('ÅÅÅÅ ÅÅÅÅ'),('LLLLLLLL'); +SELECT * FROM t2 WHERE MATCH(s1) AGAINST ('LLLL' COLLATE UTF8_UNICODE_520_CI); +--disable_warnings +DROP TABLE t1,t2; +--enable_warnings + +--echo "----------Test16---------" +CREATE TABLE t1 (s1 INT, s2 VARCHAR(50) CHARACTER SET UTF8) ENGINE = InnoDB; +CREATE FULLTEXT INDEX i ON t1(s2); +INSERT INTO t1 VALUES (2, 'ÄŸÄ— DaÅ›i p '); +SELECT * FROM t1 WHERE MATCH(s2) AGAINST ('+p +"ÄŸÄ— DaÅ›i*"' IN BOOLEAN MODE); +DROP TABLE t1; + + +--echo "----------Test19---------" +#19 Failure with Boolean quoted search +CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF8) ENGINE = InnoDB; +INSERT INTO t1 VALUES (1,'İóëɠ'); +CREATE FULLTEXT INDEX i ON t1 (char_column); +SELECT * FROM t1 WHERE MATCH(char_column) AGAINST ('"İóëɠ"' IN BOOLEAN MODE); +DROP TABLE t1; + +--echo "----------Test20---------" +#20 Crash with utf32 and boolean mode. +CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF32, char_column2 VARCHAR(60) character set utf8) ENGINE = InnoDB; +INSERT INTO t1 (char_column) VALUES ('abcde'),('fghij'),('klmno'),('qrstu'); +UPDATE t1 SET char_column2 = char_column; +CREATE FULLTEXT INDEX i ON t1 (char_column2); +--error ER_FT_MATCHING_KEY_NOT_FOUND +SELECT * FROM t1 WHERE MATCH(char_column) AGAINST ('abc*' IN BOOLEAN MODE); +DROP TABLE t1; + +--echo "----------Test22---------" +# case 22 +CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF8) ENGINE = InnoDB; +INSERT INTO t1 VALUES (1,'aaa'),(2,'bbb'),(3,'ccc'); +CREATE FULLTEXT INDEX i ON t1 (char_column); +HANDLER t1 OPEN; +--error ER_KEY_DOESNT_SUPPORT +HANDLER t1 READ i = ('aaa'); +DROP TABLE t1; +#23. Duplicate key error when there are no unique indexes (procedure test) +#24 Failure after cascading update - already have tests + +--echo "----------Test25---------" +#25 Failure with Croatian boolean truncated search. +CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF8 COLLATE UTF8_CROATIAN_CI) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,'LJin'),(2,'ljin'),(3,'lmin'),(4,'LJLJLJLJLJ'); +CREATE FULLTEXT INDEX i ON t1 (char_column); +#inndob:error incorrect result correct it after fix +SELECT count(*) FROM t1 WHERE MATCH (char_column) AGAINST ('lj*' IN BOOLEAN MODE); +DROP TABLE t1; + +#26. Index error when run procedure call from multiple clients + +--echo "----------Test27---------" +#27 Crash after server restart +CREATE TABLE t1 (id INT,char_column VARCHAR(60)) ENGINE=InnoDB; +SET @@autocommit=0; +CREATE FULLTEXT INDEX i ON t1 (char_column); +INSERT INTO t1 values (1,'aaa'); +echo "restart server..." +# Restart the server +--source include/restart_mysqld.inc +DELETE FROM t1 WHERE MATCH(char_column) AGAINST ('bbb'); +SET @@autocommit=1; +DROP TABLE t1; + +--echo "----------Test28---------" +drop table if exists `fts_test`; +create table `fts_test`(`a` text,fulltext key(`a`))engine=innodb; +set session autocommit=0; +insert into `fts_test` values (''); +savepoint `b`; +savepoint `b`; +set session autocommit=1; +DROP TABLE fts_test; + +# Continue test savepoint related operations. With a commit after +# multiple rollback to savepoints +--echo "----------Test29---------" +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +INSERT INTO articles (title,body) VALUES + ('MySQL Tutorial','DBMS stands for DataBase ...'); + + +start transaction; + +INSERT INTO articles (title,body) VALUES +('How To Use MySQL Well','After you went through a ...'); + +savepoint `a1`; + +INSERT INTO articles (title,body) VALUES +('Optimizing MySQL','In this tutorial we will show ...'); + +savepoint `a2`; + +INSERT INTO articles (title,body) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'); + +savepoint `a3`; + +INSERT INTO articles (title,body) VALUES +('MySQL vs. YourSQL','In the following database comparison ...'); + +savepoint `a4`; + +# FTS do not parse those uncommitted rows, only one row should show up +SELECT * FROM articles + WHERE MATCH (title,body) + AGAINST ('Database' IN NATURAL LANGUAGE MODE); + +rollback to savepoint a3; + +# The last inserted row should not be there +select title, body from articles; + +INSERT INTO articles (title,body) VALUES +('MySQL Security','When configured properly, MySQL ...'); + +savepoint `a5`; + +select title, body from articles; + +rollback to savepoint a2; + +select title, body from articles; + +commit; + +SELECT * FROM articles + WHERE MATCH (title,body) + AGAINST ('Database' IN NATURAL LANGUAGE MODE); + +SELECT * FROM articles + WHERE MATCH (title,body) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + +DROP TABLE articles; + +# Continue test savepoint related operations. With a rollback after +# multiple rollback to savepoints +--echo "----------Test30---------" +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +INSERT INTO articles (title,body) VALUES + ('MySQL Tutorial','DBMS stands for DataBase ...'); + +start transaction; + +INSERT INTO articles (title,body) VALUES +('How To Use MySQL Well','After you went through a ...'); + +savepoint `a1`; + +INSERT INTO articles (title,body) VALUES +('Optimizing MySQL','In this tutorial we will show ...'); + +savepoint `a2`; + +INSERT INTO articles (title,body) VALUES +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'); + +savepoint `a3`; + +INSERT INTO articles (title,body) VALUES +('MySQL vs. YourSQL','In the following database comparison ...'); + +savepoint `a4`; + +# FTS do not parse those uncommitted rows, only one row should show up +SELECT * FROM articles + WHERE MATCH (title,body) + AGAINST ('Database' IN NATURAL LANGUAGE MODE); + +rollback to savepoint a3; + +# The last inserted row should not be there +select title, body from articles; + +INSERT INTO articles (title,body) VALUES +('MySQL Security','When configured properly, MySQL ...'); + +savepoint `a5`; + +select title, body from articles; + +rollback to savepoint a2; + +select title, body from articles; + +rollback; + +SELECT * FROM articles + WHERE MATCH (title,body) + AGAINST ('Database' IN NATURAL LANGUAGE MODE); + +SELECT * FROM articles + WHERE MATCH (title,body) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + +DROP TABLE articles; + +# Test for Bug #13907075 - DIFFERENT RESULTS FOR DIFFERENT TERM ORDER +# WITH INNODB BOOLEAN FULLTEXT SEARCH. The FTS_IGNORE ("-") operation +# is orderless +# Create FTS table +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +# Insert six rows +INSERT INTO articles (title,body) VALUES + ('MySQL Tutorial','DBMS stands for DataBase ...') , + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +-- disable_result_log +ANALYZE TABLE articles; +-- enable_result_log + +SELECT *, MATCH(title, body) AGAINST ('-database +MySQL' IN BOOLEAN MODE) AS score from articles; + +SELECT *, MATCH(title, body) AGAINST ('+MySQL -database' IN BOOLEAN MODE) AS score FROM articles; + +# With subquery +SELECT * FROM articles where MATCH(title, body) AGAINST ('MySQL - (database - tutorial)' IN BOOLEAN MODE); + +SELECT * FROM articles where MATCH(title, body) AGAINST ('MySQL - (- tutorial database)' IN BOOLEAN MODE); + +# More complex query +SELECT * FROM articles where MATCH(title, body) AGAINST ('MySQL - (- tutorial database) -Tricks' IN BOOLEAN MODE); + +SELECT * FROM articles where MATCH(title, body) AGAINST ('-Tricks MySQL - (- tutorial database)' IN BOOLEAN MODE); + +DROP TABLE articles; + +# Test for Bug 13940669 - 64901: INNODB: ASSERTION FAILURE IN +# THREAD 34387022112 IN FILE REM0CMP.CC LINE 5 + +drop table if exists t1; + +create table t1 (FTS_DOC_ID bigint unsigned auto_increment not null primary key, +title varchar(200),body text,fulltext(title,body)) engine=innodb; + +insert into t1 set body='test'; + +select * from t1 where match(title,body) against('%test'); + +select * from t1 where match(title,body) against('%'); + +select * from t1 where match(title,body) against('%%%%'); + +drop table t1; + +# Test for Bug 13881758 - 64745: CREATE FULLTEXT INDEX CAUSES CRASH +# Create a database with empty space in its name +CREATE DATABASE `benu database`; + +USE `benu database`; + +# Create FTS table +CREATE TABLE t1 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a VARCHAR(200), + b TEXT + ) ENGINE = InnoDB; + +# Insert rows +INSERT INTO t1 (a,b) VALUES + ('MySQL Tutorial','DBMS stands for DataBase ...') , + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'); + +# Create the FTS index Using Alter Table +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); +EVAL SHOW CREATE TABLE t1; + +# Insert rows +INSERT INTO t1 (a,b) VALUES + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# Select word "tutorial" in the table +SELECT id FROM t1 WHERE MATCH (a,b) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + +# boolean mode +select id from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE); +select id from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE); +select id from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE); +select id from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE); +select id, MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE) as x from t1; +select id, MATCH(a,b) AGAINST("collections support" IN BOOLEAN MODE) as x from t1; +select id from t1 where MATCH a,b AGAINST ("+call* +coll*" IN BOOLEAN MODE); +select id from t1 where MATCH a,b AGAINST ('"support now"' IN BOOLEAN MODE); +select id from t1 where MATCH a,b AGAINST ('"Now sUPPort"' IN BOOLEAN MODE); + +DROP DATABASE `benu database`; + +USE test; + +# Test for Bug #14101706 - CRASH WITH DDL IN ROW_MERGE_BUILD_INDEXES +# WHEN FULLTEXT INDEXES EXIST + +CREATE TABLE `t21` (`a` text, `b` int not null, +fulltext key (`a`), fulltext key (`a`) +) ENGINE=INNODB DEFAULT CHARSET=LATIN1; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE `t21` ADD UNIQUE INDEX (`b`), ALGORITHM=INPLACE; +ALTER TABLE `t21` ADD UNIQUE INDEX (`b`); + +DROP TABLE t21; + +CREATE TABLE `t21` (`a` text, `b` int not null, +fulltext key (`a`)) ENGINE=INNODB DEFAULT CHARSET=LATIN1; + +ALTER TABLE `t21` ADD UNIQUE INDEX (`b`); + +DROP TABLE t21; + +# Test primary index rebuild +CREATE TABLE t1 ( + id INT NOT NULL, + a VARCHAR(200), + b TEXT + ) ENGINE = InnoDB; + +# Insert rows +INSERT INTO t1 VALUES + (1, 'MySQL Tutorial','DBMS stands for DataBase ...') , + (2, 'How To Use MySQL Well','After you went through a ...'), + (3, 'Optimizing MySQL','In this tutorial we will show ...'); + +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); + +ALTER TABLE t1 ADD UNIQUE INDEX (`id`); + +# Select word "tutorial" in the table +SELECT id FROM t1 WHERE MATCH (a,b) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + +# boolean mode +select id from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE); +select id from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE); +select id from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE); +select id from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE); +select id, MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE) as x from t1; + +DROP TABLE t1; + +# Test create the FTS and primary index in the same clause +CREATE TABLE t1 ( + id INT NOT NULL, + a VARCHAR(200), + b TEXT + ) ENGINE = InnoDB; + +# Insert rows +INSERT INTO t1 VALUES + (1, 'MySQL Tutorial','DBMS stands for DataBase ...') , + (2, 'How To Use MySQL Well','After you went through a ...'), + (3, 'Optimizing MySQL','In this tutorial we will show ...'); + +ALTER TABLE t1 ADD UNIQUE INDEX (`id`), ADD FULLTEXT INDEX idx (a,b); + +# Select word "tutorial" in the table +SELECT id FROM t1 WHERE MATCH (a,b) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + +# boolean mode +select id from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE); +select id from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE); +select id from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE); +select id from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE); + +DROP TABLE t1; + +# Create FTS table with FTS_DOC_ID already existed +CREATE TABLE t1 ( + FTS_DOC_ID BIGINT UNSIGNED NOT NULL, + a VARCHAR(200), + b TEXT + ) ENGINE = InnoDB; + +# Insert rows +INSERT INTO t1 VALUES + (1, 'MySQL Tutorial','DBMS stands for DataBase ...') , + (2, 'How To Use MySQL Well','After you went through a ...'), + (3, 'Optimizing MySQL','In this tutorial we will show ...'); + +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); + +ALTER TABLE t1 ADD UNIQUE INDEX (`FTS_DOC_ID`); + +# Select word "tutorial" in the table +SELECT FTS_DOC_ID FROM t1 WHERE MATCH (a,b) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + +# boolean mode +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE); +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE); +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE); +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE); +select FTS_DOC_ID, MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE) as x from t1; + +DROP TABLE t1; + +# Create FTS table with FTS_DOC_ID and FTS_DOC_ID_INDEX +CREATE TABLE t1 ( + FTS_DOC_ID BIGINT UNSIGNED NOT NULL, + a VARCHAR(200), + b TEXT + ) ENGINE = InnoDB; + +# Insert rows +INSERT INTO t1 VALUES + (1, 'MySQL Tutorial','DBMS stands for DataBase ...') , + (2, 'How To Use MySQL Well','After you went through a ...'), + (3, 'Optimizing MySQL','In this tutorial we will show ...'); + +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b), ADD UNIQUE INDEX FTS_DOC_ID_INDEX (FTS_DOC_ID); + +# Select word "tutorial" in the table +SELECT FTS_DOC_ID FROM t1 WHERE MATCH (a,b) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + +# boolean mode +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+support +collections" IN BOOLEAN MODE); +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+search" IN BOOLEAN MODE); +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+search +(support vector)" IN BOOLEAN MODE); +select FTS_DOC_ID from t1 where MATCH(a,b) AGAINST("+search -(support vector)" IN BOOLEAN MODE); +select FTS_DOC_ID, MATCH(a,b) AGAINST("support collections" IN BOOLEAN MODE) as x from t1; + +DROP TABLE t1; + +# Test for bug #14079609 - FTS: CRASH IN FTS_TRX_TABLE_CMP WITH SAVEPOINTS, XA + +CREATE TABLE t2 (`b` char(2),fulltext(`b`)) ENGINE=INNODB +DEFAULT CHARSET=LATIN1; + +CREATE TABLE t3 LIKE t2; + +INSERT INTO `t2` VALUES(); + +COMMIT WORK AND CHAIN; + +INSERT INTO `t3` VALUES (); +UPDATE `t2` SET `b` = 'a'; + +SAVEPOINT BATCH1; + +DROP TABLE t2; +DROP TABLE t3; + +# Create FTS table +CREATE TABLE t1 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a VARCHAR(200), + b TEXT + ) ENGINE = InnoDB; + +# Insert rows +INSERT INTO t1 (a,b) VALUES + ('MySQL Tutorial','DBMS stands for DataBase ...') , + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'); + +# Create the FTS index Using Alter Table +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); + +COMMIT WORK AND CHAIN; + +INSERT INTO t1 (a,b) VALUES + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +SAVEPOINT BATCH1; + +SELECT id FROM t1 WHERE MATCH (a,b) + AGAINST ('MySQL' IN NATURAL LANGUAGE MODE); + +INSERT INTO t1 (a,b) VALUES + ('1002 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + + +ROLLBACK TO SAVEPOINT BATCH1; + +COMMIT; + +SELECT id FROM t1 WHERE MATCH (a,b) + AGAINST ('MySQL' IN NATURAL LANGUAGE MODE); + +DROP TABLE t1; + +# Test for Bug 14588091 - FTS: BUFFER OVERFLOW IN FTS_AST_CREATE_NODE_TEXT +CREATE TABLE `t` (`a` char(20) character set utf8 default null, +fulltext key (`a`)) ENGINE=INNODB; +INSERT INTO `t` VALUES ('a'); +INSERT INTO `t` VALUES ('aaa'); + +# 0x22 is the '"', 0xdd is not encoded in utf8 +SELECT MATCH(`a`) AGAINST (0x22dd22) FROM `t`; +SELECT MATCH(`a`) AGAINST (0x2222) FROM `t`; +SELECT MATCH(`a`) AGAINST (0x22) FROM `t`; + +# this should show one match +SELECT MATCH(`a`) AGAINST (0x2261616122) FROM `t`; + +# again 0xdd should be ignored +SELECT MATCH(`a`) AGAINST (0x2261dd6122) FROM `t`; + +SELECT MATCH(`a`) AGAINST (0x2261dd612222226122) FROM `t`; + +DROP TABLE t; + +# InnoDB FTS does not support index scan from handler +CREATE TABLE t(a CHAR(1),FULLTEXT KEY(a)) ENGINE=INNODB; +HANDLER t OPEN; +HANDLER t READ a NEXT; +HANDLER t READ a PREV; +DROP TABLE t; + +CREATE TABLE `%`(a TEXT, FULLTEXT INDEX(a)) ENGINE=INNODB; +CREATE TABLE `A B`(a TEXT, FULLTEXT INDEX(a)) ENGINE=INNODB; +DROP TABLE `%`; +DROP TABLE `A B`; + +CREATE TABLE `t-26`(a VARCHAR(10),FULLTEXT KEY(a)) ENGINE=INNODB; +INSERT INTO `t-26` VALUES('117'); +DROP TABLE `t-26`; + +# Test on phrase search with stopwords contained in the search string +CREATE TABLE `t1` ( + `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + `content` TEXT NOT NULL, + PRIMARY KEY (`id`), + FULLTEXT INDEX `IDX_CONTEXT_FULLTEXT`(`content`) +) +ENGINE = InnoDB; + +insert into t1 (content) +values +('This is a story which has has a complicated phrase structure here in the +middle'), +('This is a story which doesn''t have that text'), +('This is a story that has complicated the phrase structure'); + +select * from t1 +where match(content) against('"complicated phrase structure"' in boolean +mode); + +# Test single phrase search with "+" symbol, one row should be returned +select * from t1 +where match(content) against('+"complicated phrase structure"' in boolean +mode); + +# Test phrase search with stopwords in between, one row should be returned +select * from t1 +where match(content) against('"complicated the phrase structure"' in boolean +mode); + +# Test phrase search with multiple "+" symbols +select * from t1 where match(content) against('+"this is a story which" +"complicated the phrase structure"' in boolean mode); + +# Test phrase search with leading word is a stopword, such stopword would be +# ignored +select * from t1 where match(content) against('"the complicated the phrase structure"' in boolean mode); + +# Test phrase search with non-matching stopword in between, no row should be +# returned +select * from t1 where match(content) against('"complicated a phrase structure"' in boolean mode); + +DROP TABLE t1; + +CREATE TABLE my (id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, +c VARCHAR(32), FULLTEXT(c)) ENGINE = INNODB; + +INSERT INTO my (c) VALUES ('green-iguana'); + +SELECT * FROM my WHERE MATCH(c) AGAINST ('green-iguana'); + +DROP TABLE my; + +CREATE TABLE ift ( + `a` int(11) NOT NULL, + `b` text, + PRIMARY KEY (`a`), + FULLTEXT KEY `b` (`b`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO ift values (1, "skip"); +INSERT INTO ift values (2, "skip and networking"); +INSERT INTO ift values (3, "--skip-networking"); +INSERT INTO ift values (4, "-donot--skip-networking"); + +SELECT * FROM ift WHERE MATCH (b) AGAINST ('--skip-networking'); +SELECT * FROM ift WHERE MATCH (b) AGAINST ('skip-networking'); +SELECT * FROM ift WHERE MATCH (b) AGAINST ('----'); +SELECT * FROM ift WHERE MATCH (b) AGAINST ('-donot--skip-networking'); + +DROP TABLE ift; + +# Test special cases of wildword. +# Create FTS table +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +# Insert six rows +INSERT INTO articles (title,body) VALUES + ('MySQL Tutorial','DBMS stands for DataBase ...') , + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('( that''s me )','When configured properly, MySQL ...'); + +SELECT * FROM articles WHERE MATCH (title,body) + AGAINST ('( yours''s* )' IN BOOLEAN MODE); + +SELECT * FROM articles WHERE MATCH (title,body) + AGAINST ('s*' IN BOOLEAN MODE); + +SELECT * FROM articles WHERE MATCH (title,body) + AGAINST ('stands\'] | * | show[@database' IN NATURAL LANGUAGE MODE); + +DROP TABLE articles; + +# Test for BUG#16429688 - FTS: SYNTAX ERROR, UNEXPECTED '*', EXPECTING $END +CREATE TABLE t1(a TEXT CHARACTER SET LATIN1, FULLTEXT INDEX(a)) ENGINE=INNODB; + +--error ER_PARSE_ERROR +SELECT * FROM t1 WHERE MATCH(a) AGAINST("*"); + +DROP TABLE t1; + +# Test for BUG#16516193 - LITERAL PHRASES CANNOT BE COMBINED WITH + OR - OPERATOR +# Create FTS table +CREATE TABLE t1 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a VARCHAR(200), + FULLTEXT (a) + ) ENGINE= InnoDB; + +# Insert rows +INSERT INTO t1 (a) VALUES + ('Do you know MySQL is a good database'), + ('How to build a good database'), + ('Do you know'), + ('Do you know MySQL'), + ('How to use MySQL'), + ('Do you feel good'), + ('MySQL is good'), + ('MySQL is good to know'), + ('What is database'); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+"know mysql"' IN BOOLEAN MODE); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+("know mysql")' IN BOOLEAN MODE); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('("know mysql" good)' IN BOOLEAN MODE); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+("know mysql" good)' IN BOOLEAN MODE); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('(good "know mysql")' IN BOOLEAN MODE); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+(good "know mysql")' IN BOOLEAN MODE); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+("know mysql" "good database")' IN BOOLEAN MODE); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+"know mysql" +"good database"' IN BOOLEAN MODE); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+"know database"@4' IN BOOLEAN MODE); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+"know database"@8' IN BOOLEAN MODE); + +# Drop table +DROP TABLE t1; + +# Test for BUG#16885178 - INNODB FULLTEXT PHRASE SEARCH VALGRIND ERROR +CREATE TABLE t1 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a VARCHAR(200), + FULLTEXT (a) + ) ENGINE= InnoDB; + +# Insert a special row +INSERT INTO t1 (a) VALUES + ('know mysql good database'); + +# This phrase search fails in valgrind test before the fix. +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+"good database"' IN BOOLEAN MODE); + +DROP TABLE t1; + +# Test single term ranking +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +# Repeatedly insert/delete records, the ranking should be the same for +# each of them +INSERT INTO articles (title,body) VALUES ('Test Article','blah blah +blah'),("Matt's Noise",'this is noisy'),('February Weather','It was terrible +this year.'),('Peter Pan','Tis a kids story.'),('Test1','nada'),('Database +database database','foo database database database'),('Database article +title','body with lots of words.'),('myfulltext database', 'my test fulltext +database'); + +SELECT id, title, body FROM articles ORDER BY MATCH (title,body) AGAINST ('database' IN BOOLEAN MODE) DESC; +DELETE from articles WHERE title like "myfulltext database"; + +INSERT INTO articles (title,body) VALUES ('myfulltext database', 'my test fulltext database'); + +SELECT id, title, body FROM articles ORDER BY MATCH (title,body) AGAINST ('database' IN BOOLEAN MODE) DESC; +DELETE from articles WHERE title like "myfulltext database"; + +INSERT INTO articles (title,body) VALUES ('myfulltext database', 'my test fulltext database'); + +SELECT id, title, body FROM articles ORDER BY MATCH (title,body) AGAINST ('database' IN BOOLEAN MODE) DESC; + +DROP TABLE articles; + +# Test for BUG 18277305 - FTS: FAILING ASSERTION: PTR[1] == '\"' +# IN FTS_AST_CREATE_NODE_TEXT +CREATE TABLE t1( + a TEXT CHARSET ujis COLLATE ujis_japanese_ci, + b TEXT CHARSET utf8mb4 COLLATE utf8mb4_turkish_ci, + c TEXT CHARSET eucjpms COLLATE eucjpms_bin, + d TEXT CHARSET utf8mb4, + FULLTEXT INDEX(a), + FULLTEXT INDEX(b), + FULLTEXT INDEX(c), + FULLTEXT INDEX(d) +) ENGINE = InnoDB; + +INSERT INTO t1 VALUES + ('myisam', 'myisam', 'myisam', 'myisam'), + ('innodb', 'innodb', 'innodb', 'innodb'), + ('innodb myisam', 'innodb myisam', 'innodb myisam', 'innodb myisam'), + ('memory', 'memory', 'memory', 'memory'), + ('archive', 'archive', 'archive', 'archive'), + ('federated', 'federated', 'federated', 'federated'), + ('storage engine innodb', 'storage engine innodb', 'storage engine innodb', 'storage engine innodb'), + ('storage engine myisam', 'storage engine myisam', 'storage engine myisam', 'storage engine myisam'), + ('innobase', 'innobase', 'innobase', 'innobase'), + ('myisam innodb', 'myisam innodb', 'myisam innodb', 'myisam innodb'), + ('innodb myisam engines', 'innodb myisam engines', 'innodb myisam engines', 'innodb myisam engines'); + +# Test the ujis_japanese_ci +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00)); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', ' ', '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 0x00, '"', 0x00)); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', '&', 0x00, '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, '&', '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', '%', '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, 0x00, 0x00, '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', '(', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', ')')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', 'm', 'y', 'i', 's', 'a', 'm')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', 'm', 'y', 'i', 's', 'a', 'm', '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"','@', '2') IN BOOLEAN MODE); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 'm', 'y', 'i', 's', 'a', 'm', '"','@', '4') IN BOOLEAN MODE); +--error ER_PARSE_ERROR +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 's', 't', 'o', 'r', 'a', 'g', 'e', '"','@', '4', 0x00) IN BOOLEAN MODE); + + +# Test the utf8mb4_turkish_ci +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"')); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT(0x00)); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', '"')); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', ' ', '"')); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', 0x00, '"')); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT(0x00, '"', 0x00, '"', 0x00)); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', '&', 0x00, '"')); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', 0x00, '&', '"')); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', '%', '"')); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, 0x00, 0x00, '"')); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"','@', '2') IN BOOLEAN MODE); +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 'm', 'y', 'i', 's', 'a', 'm', '"','@', '4') IN BOOLEAN MODE); +--error ER_PARSE_ERROR +SELECT b FROM t1 WHERE MATCH (b) AGAINST (CONCAT(0x00, '"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 's', 't', 'o', 'r', 'a', 'g', 'e', '"','@', '4', 0x00) IN BOOLEAN MODE); + +# Test the eucjpms_bin +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT(0x00)); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', '"')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', ' ', '"')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 0x00, '"')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT(0x00, '"', 0x00, '"', 0x00)); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', '&', 0x00, '"')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 0x00, '&', '"')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', '%', '"')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, 0x00, 0x00, '"')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', '(', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', ')')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', 'm', 'y', 'i', 's', 'a', 'm')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', 'm', 'y', 'i', 's', 'a', 'm', '"')); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"','@', '2') IN BOOLEAN MODE); +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 'm', 'y', 'i', 's', 'a', 'm', '"','@', '4') IN BOOLEAN MODE); +--error ER_PARSE_ERROR +SELECT c FROM t1 WHERE MATCH (c) AGAINST (CONCAT(0x00, '"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 's', 't', 'o', 'r', 'a', 'g', 'e', '"','@', '4', 0x00) IN BOOLEAN MODE); + +ALTER TABLE t1 ENGINE = MyISAM; + +# Test the query against myisam to verify +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00)); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', ' ', '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 0x00, '"', 0x00)); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', '&', 0x00, '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, '&', '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', '%', '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, 0x00, 0x00, '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', 0x00, '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00)); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', '(', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', ')')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', 'm', 'y', 'i', 's', 'a', 'm')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', 'm', 'y', 'i', 's', 'a', 'm', '"')); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 0x00, 'i', 'n', 'n', 'o', 'd', 'b', '@', '$', 'm', 'y', 'i', 's', 'a', 'm', '%', 0x00, 0x00, '"','@', '2') IN BOOLEAN MODE); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT('"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 'm', 'y', 'i', 's', 'a', 'm', '"','@', '4') IN BOOLEAN MODE); +SELECT a FROM t1 WHERE MATCH (a) AGAINST (CONCAT(0x00, '"', 'i', 'n', 'n', 'o', 'd', 'b', ' ', '$', 's', 't', 'o', 'r', 'a', 'g', 'e', '"','@', '4', 0x00) IN BOOLEAN MODE); + +DROP TABLE t1; + +# Test for BUG#18229097 - FTS: DID NOT FIND WORD 0 IN DOC 39161 FOR QUERY EXPANSION SEARCH. +CREATE TABLE t1 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a VARCHAR(200), + FULLTEXT (a) +) ENGINE= InnoDB; + +INSERT INTO t1 (a) VALUES + ('know database'),('good database'), ('gmail email'), ('ghome windows'); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g *' IN NATURAL LANGUAGE MODE); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g *' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g * k *' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g * k * d *' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g * go *' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g * good' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('gm * go *' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('good *' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); + +SELECT * FROM t1 WHERE MATCH (a) AGAINST ('g* database' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION); + +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/t/misc_1.test b/mysql-test/suite/innodb_fts/t/misc_1.test new file mode 100644 index 00000000000..45eaf447978 --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/misc_1.test @@ -0,0 +1,894 @@ +--source include/have_innodb.inc +--source include/innodb_page_size_small.inc +--source include/no_valgrind_without_big.inc + +#------------------------------------------------------------------------------ +# FTS with FK and update cascade +#------------------------------------------------------------------------------- +set names utf8; + +call mtr.add_suppression("\\[Warning\\] InnoDB: A new Doc ID must be supplied while updating FTS indexed columns."); +call mtr.add_suppression("\\[Warning\\] InnoDB: FTS Doc ID must be larger than [0-9]+ for table `test`.`t1`"); + +# Create FTS table +CREATE TABLE t1 ( + id1 INT , + a1 VARCHAR(200) , + b1 TEXT , + FULLTEXT KEY (a1,b1), PRIMARY KEY (a1, id1) + ) CHARACTER SET = utf8 , ENGINE = InnoDB; + +CREATE TABLE t2 ( + id2 INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a2 VARCHAR(200), + b2 TEXT , + FOREIGN KEY (a2) REFERENCES t1(a1) ON UPDATE CASCADE, + FULLTEXT KEY (b2,a2) + ) CHARACTER SET = utf8 ,ENGINE = InnoDB; + +# Insert rows +INSERT INTO t1 (id1,a1,b1) VALUES + (1,'MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , + (2,'How To Use MySQL Well','After you went through a ...'), + (3,'Optimizing MySQL','In this tutorial we will show ...'); + +# Insert rows +INSERT INTO t1 (id1,a1,b1) VALUES + (4,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + (5,'MySQL vs. YourSQL','In the following database comparison ...'), + (6,'MySQL Security','When configured properly, MySQL ...'); + +# Insert rows in t2 fk table +INSERT INTO t2 (a2,b2) VALUES + ('MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'); + +# Insert rows t2 fk table +INSERT INTO t2 (a2,b2) VALUES + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# error on violating fk constraint +--error 1452 +INSERT INTO t2 (a2,b2) VALUES + ('MySQL Tricks','1. Never run mysqld as root. 2. ...'); + +# error on delete from parent table +--error 1451 +DELETE FROM t1; + +ANALYZE TABLE t1; +ANALYZE TABLE t2; + +SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial') ORDER BY id1; +SELECT id2 FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial') ORDER BY id2; + +SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ORDER BY id1; +SELECT id2 FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ORDER BY id2; + +SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial' WITH QUERY EXPANSION) ORDER BY id1; +SELECT id2 FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial' WITH QUERY EXPANSION) ORDER BY id2; + + +SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('"dbms database"@4' IN BOOLEAN MODE) ; +SELECT id2 FROM t2 WHERE MATCH (a2,b2) AGAINST ('"dbms database"@4' IN BOOLEAN MODE) ; + +set global innodb_optimize_fulltext_only=1; +optimize table t1; +set global innodb_optimize_fulltext_only=0; +# Updating parent table hence child table should get updated due to 'update cascade' clause +UPDATE t1 SET a1 = "changing column - on update cascade" , b1 = "to check foreign constraint" WHERE +MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; + +# no records expected +SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +# InnoDB:Error child table shows records which is incorrect - UPADTE on Fix +SELECT id2 FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; + +# it shows updated record +SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('+update +cascade' IN BOOLEAN MODE) ORDER BY id1; +# InnoDB:Error child table does not show the expected record +SELECT id2 FROM t2 WHERE MATCH (a2,b2) AGAINST ('+update +cascade' IN BOOLEAN MODE) ORDER BY id2; +SELECT id2 FROM t2 WHERE a2 LIKE '%UPDATE CASCADE%' ORDER BY id2; + +DROP TABLE t2 , t1; + +# on update cascade +create table t1 (s1 int, s2 varchar(200), primary key (s1,s2)) ENGINE = InnoDB; +create table t2 (s1 int, s2 varchar(200), + fulltext key(s2), + foreign key (s1,s2) references t1 (s1,s2) on update cascade) ENGINE = InnoDB; +insert into t1 values (1,'Sunshine'),(2,'Lollipops'); +insert into t2 values (1,'Sunshine'),(2,'Lollipops'); +update t1 set s2 = 'Rainbows' where s2 <> 'Sunshine'; +commit; +select * from t2 where match(s2) against ('Lollipops'); +DROP TABLE t2 , t1; + +# on delete cascade +create table t1 (s1 int, s2 varchar(200), primary key (s1,s2)) ENGINE = InnoDB; +create table t2 (s1 int, s2 varchar(200), + fulltext key(s2), + foreign key (s1,s2) references t1 (s1,s2) on delete cascade) ENGINE = InnoDB; +insert into t1 values (1,'Sunshine'),(2,'Lollipops'); +insert into t2 values (1,'Sunshine'),(2,'Lollipops'); +delete from t1 where s2 <> 'Sunshine'; +select * from t2 where match(s2) against ('Lollipops'); +DROP TABLE t2 , t1; + +# on delete set NULL +create table t1 (s1 int, s2 varchar(200), primary key (s1,s2)) ENGINE = InnoDB; +create table t2 (s1 int, s2 varchar(200), + fulltext key(s2), + foreign key (s1,s2) references t1 (s1,s2) on delete set null) ENGINE = InnoDB; +insert into t1 values (1,'Sunshine'),(2,'Lollipops'); +insert into t2 values (1,'Sunshine'),(2,'Lollipops'); +delete from t1 where s2 <> 'Sunshine'; +select * from t2 where match(s2) against ('Lollipops'); +DROP TABLE t2 , t1; + + +# on update set NULL +create table t1 (s1 int, s2 varchar(200), primary key (s1,s2)) ENGINE = InnoDB; +create table t2 (s1 int, s2 varchar(200), + fulltext key(s2), + foreign key (s1,s2) references t1 (s1,s2) on update set null) ENGINE = InnoDB; +insert into t1 values (1,'Sunshine'),(2,'Lollipops'); +insert into t2 values (1,'Sunshine'),(2,'Lollipops'); +update t1 set s2 = 'Rainbows' where s2 <> 'Sunshine'; +commit; +select * from t2 where match(s2) against ('Lollipops'); +DROP TABLE t2 , t1; + +# When Doc ID is involved +create table t1 (s1 bigint unsigned not null, s2 varchar(200), + primary key (s1,s2)) ENGINE = InnoDB; +create table t2 (FTS_DOC_ID BIGINT UNSIGNED NOT NULL, s2 varchar(200), + foreign key (FTS_DOC_ID) references t1 (s1) + on update cascade) ENGINE = InnoDB; + +create fulltext index idx on t2(s2); + +show create table t2; + +insert into t1 values (1,'Sunshine'),(2,'Lollipops'); +insert into t2 values (1,'Sunshine'),(2,'Lollipops'); + +update t1 set s1 = 3 where s1=1; + +select * from t2 where match(s2) against ('sunshine'); + +# FTS Doc ID cannot be reused +--error 1451 +update t1 set s1 = 1 where s1=3; + +DROP TABLE t2 , t1; + +#------------------------------------------------------------------------------ +# FTS with FK and delete casecade +#------------------------------------------------------------------------------ + +# Create FTS table +CREATE TABLE t1 ( + id1 INT , + a1 VARCHAR(200) PRIMARY KEY, + b1 TEXT character set utf8 , + FULLTEXT KEY (a1,b1) + ) CHARACTER SET = utf8 ,ENGINE = InnoDB; + +CREATE TABLE t2 ( + id2 INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a2 VARCHAR(200), + b2 TEXT character set utf8 , + FOREIGN KEY (a2) REFERENCES t1(a1) ON DELETE CASCADE, + FULLTEXT KEY (b2,a2) + ) CHARACTER SET = utf8 ,ENGINE = InnoDB; + +# Insert rows +INSERT INTO t1 (id1,a1,b1) VALUES + (1,'MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , + (2,'How To Use MySQL Well','After you went through a ...'), + (3,'Optimizing MySQL','In this tutorial we will show ...'), + (4,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + (5,'MySQL vs. YourSQL','In the following database comparison ...'), + (6,'MySQL Security','When configured properly, MySQL ...'); + +# Insert rows in t2 +INSERT INTO t2 (a2,b2) VALUES + ('MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# delete records from parent +DELETE FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; + +# no records expected +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; + +SELECT * FROM t1 WHERE a1 LIKE '%tutorial%'; +SELECT * FROM t2 WHERE a2 LIKE '%tutorial%'; + +DROP TABLE t2 , t1; + +#------------------------------------------------------------------------------ +# FTS with FK+transactions and UPDATE casecade with transaction +#------------------------------------------------------------------------------- + +call mtr.add_suppression("\\[ERROR\\] InnoDB: FTS Doc ID must be larger than 3 for table `test`.`t2`"); + +# Create FTS table +CREATE TABLE t1 ( + id1 INT , + a1 VARCHAR(200) , + b1 TEXT , + FULLTEXT KEY (a1,b1), PRIMARY KEY(a1, id1) + ) CHARACTER SET = utf8 , ENGINE = InnoDB; + +CREATE TABLE t2 ( + id2 INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a2 VARCHAR(200), + b2 TEXT , + FOREIGN KEY (a2) REFERENCES t1(a1) ON UPDATE CASCADE, + FULLTEXT KEY (b2,a2) + ) CHARACTER SET = utf8 ,ENGINE = InnoDB; + +# Insert rows +INSERT INTO t1 (id1,a1,b1) VALUES + (1,'MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , + (2,'How To Use MySQL Well','After you went through a ...'), + (3,'Optimizing MySQL','In this tutorial we will show ...'); + +# Insert rows in t2 fk table +INSERT INTO t2 (a2,b2) VALUES + ('MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'); + +START TRANSACTION; +# Insert rows +INSERT INTO t1 (id1,a1,b1) VALUES + (4,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + (5,'MySQL vs. YourSQL','In the following database comparison ...'), + (6,'MySQL Security','When configured properly, MySQL ...'); + +# Insert rows t2 fk table +INSERT INTO t2 (a2,b2) VALUES + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# error on violating fk constraint +--error 1452 +INSERT INTO t2 (a2,b2) VALUES + ('MySQL Tricks','1. Never run mysqld as root. 2. ...'); + +# error on DELETE FROM parent table +--error 1451 +DELETE FROM t1; + +# records expected +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial') ORDER BY id1; +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial') ORDER BY id2; +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ORDER BY id1; +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ORDER BY id2; +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial' WITH QUERY EXPANSION) ORDER BY id1; +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial' WITH QUERY EXPANSION) ORDER BY id2; +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('"dbms database"@4' IN BOOLEAN MODE) ; +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('"dbms database"@4' IN BOOLEAN MODE) ; + +# no records as data not COMMITted. +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('root') ; +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('root') ; +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('mysqld (+root)' IN BOOLEAN MODE) ; +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('mysqld (-root)' IN BOOLEAN MODE) ; +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('root' WITH QUERY EXPANSION) ; +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('root' WITH QUERY EXPANSION) ; +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('"database comparison"@02' IN BOOLEAN MODE) ; +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('"database comparison"@02' IN BOOLEAN MODE) ; + +SELECT * FROM t1 ORDER BY id1; +SELECT * FROM t2 ORDER BY id2; + +COMMIT; + +START TRANSACTION; +# Updating parent table hence child table should get updated due to 'UPDATE cascade' clause +UPDATE t1 SET a1 = "changing column - on UPDATE cascade" , b1 = "to check foreign constraint" WHERE +MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +COMMIT; + +# no records expected +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('tutorial (+mysql -VÃÆ·Wİ)' IN BOOLEAN MODE) ; + +# it shows updated record +SELECT * FROM t1 WHERE MATCH (a1,b1) AGAINST ('+UPDATE +cascade' IN BOOLEAN MODE) ORDER BY id1; +SELECT * FROM t2 WHERE MATCH (a2,b2) AGAINST ('+UPDATE +cascade' IN BOOLEAN MODE) ORDER BY id2; +SELECT * FROM t2 WHERE a2 LIKE '%UPDATE CASCADE%' ORDER BY id2; + +DROP TABLE t2 , t1; + + +# FTS with FK+transactions - UPDATE cascade +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), + FULLTEXT KEY(s2), + FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on UPDATE cascade) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +UPDATE t1 set s2 = 'Rainbows' WHERE s2 <> 'Sunshine'; +COMMIT; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +DROP TABLE t2 , t1; + +# FTS with FK+transactions - on DELETE cascade +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), + FULLTEXT KEY(s2), + FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on DELETE cascade) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +DELETE FROM t1 WHERE s2 <> 'Sunshine'; +COMMIT; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +DROP TABLE t2 , t1; + +# FTS with FK+transactions - DELETE SET NULL +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), + FULLTEXT KEY(s2), + FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on DELETE SET NULL) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +DELETE FROM t1 WHERE s2 <> 'Sunshine'; +COMMIT; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +DROP TABLE t2 , t1; + + +# FTS with FK+transactions - UPDATE SET NULL +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), + FULLTEXT KEY(s2), + FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on UPDATE SET NULL) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +UPDATE t1 set s2 = 'Rainbows' WHERE s2 <> 'Sunshine'; +COMMIT; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +DROP TABLE t2 , t1; + + +#----------------------------------------------------------------------------- + +# FTS with FK+transactions - UPDATE cascade +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), + FULLTEXT KEY(s2), + FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on UPDATE cascade) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +UPDATE t1 set s2 = 'Rainbows' WHERE s2 <> 'Sunshine'; +ROLLBACK; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +DROP TABLE t2 , t1; + +# FTS with FK+transactions - DELETE cascade +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), + FULLTEXT KEY(s2), + FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on DELETE cascade) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +DELETE FROM t1 WHERE s2 <> 'Sunshine'; +ROLLBACK; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +DROP TABLE t2 , t1; + +# FTS with FK+transactions - DELETE SET NULL +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), + FULLTEXT KEY(s2), + FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on DELETE SET NULL) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +DELETE FROM t1 WHERE s2 <> 'Sunshine'; +ROLLBACK; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +DROP TABLE t2 , t1; + + +# FTS with FK+transactions - UPDATE SET NULL +CREATE TABLE t1 (s1 INT, s2 VARCHAR(200), PRIMARY KEY (s1,s2)) ENGINE = InnoDB; +CREATE TABLE t2 (s1 INT, s2 VARCHAR(200), + FULLTEXT KEY(s2), + FOREIGN KEY (s1,s2) REFERENCES t1 (s1,s2) on UPDATE SET NULL) ENGINE = InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'Sunshine'),(2,'Lollipops'); +INSERT INTO t2 VALUES (1,'Sunshine'),(2,'Lollipops'); +UPDATE t1 set s2 = 'Rainbows' WHERE s2 <> 'Sunshine'; +ROLLBACK; +SELECT * FROM t2 WHERE MATCH(s2) AGAINST ('Lollipops'); +DROP TABLE t2 , t1; + + +#------------------------------------------------------------------------------ +# FTS index with compressed row format +#------------------------------------------------------------------------------ + +# Save innodb variables +let $innodb_file_per_table_orig=`select @@innodb_file_per_table`; + +set global innodb_file_per_table=1; + +# Create FTS table +CREATE TABLE t1 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a VARCHAR(200), + b TEXT + ) CHARACTER SET = utf8, ROW_FORMAT=COMPRESSED, ENGINE = InnoDB; + +# Insert rows +INSERT INTO t1 (a,b) VALUES + ('MySQL Tutorial','DBMS stands for DataBase VÃÆ·Wİ...') , + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'); + +# Create the FTS index Using Alter Table +ALTER TABLE t1 ADD FULLTEXT INDEX idx (a,b); +EVAL SHOW CREATE TABLE t1; + +# Check whether individual space id created for AUX tables +SELECT count(*) FROM information_schema.innodb_sys_tables WHERE name LIKE "%FTS_%" AND space !=0; + +# Insert rows +INSERT INTO t1 (a,b) VALUES + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +-- disable_result_log +ANALYZE TABLE t1; +-- enable_result_log + +# Select word "tutorial" in the table +SELECT * FROM t1 WHERE MATCH (a,b) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) ORDER BY id; + +# boolean mode +select * from t1 where MATCH(a,b) AGAINST("+tutorial +VÃÆ·Wİ" IN BOOLEAN MODE); +--error ER_PARSE_ERROR +select * from t1 where MATCH(a,b) AGAINST("+-VÃÆ·Wİ" IN BOOLEAN MODE); +select * from t1 where MATCH(a,b) AGAINST("+Mysql +(tricks never)" IN BOOLEAN MODE); +select * from t1 where MATCH(a,b) AGAINST("+mysql -(tricks never)" IN BOOLEAN MODE) ORDER BY id; +select *, MATCH(a,b) AGAINST("mysql stands" IN BOOLEAN MODE) as x from t1 ORDER BY id; +select * from t1 where MATCH a,b AGAINST ("+database* +VÃÆ·W*" IN BOOLEAN MODE); +select * from t1 where MATCH a,b AGAINST ('"security mysql"' IN BOOLEAN MODE); + +# query expansion +select * from t1 where MATCH(a,b) AGAINST ("VÃÆ·Wİ" WITH QUERY EXPANSION) ORDER BY id; + +# Drop index +ALTER TABLE t1 DROP INDEX idx; + +# Create the FTS index again +CREATE FULLTEXT INDEX idx on t1 (a,b); + +-- disable_query_log +-- disable_result_log +ANALYZE TABLE t1; +-- enable_result_log +-- enable_query_log + +# Select word "tutorial" in the table +SELECT * FROM t1 WHERE MATCH (a,b) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) ORDER BY id; + +# boolean mode +select * from t1 where MATCH(a,b) AGAINST("+tutorial +VÃÆ·Wİ" IN BOOLEAN MODE); +select * from t1 where MATCH(a,b) AGAINST("+dbms" IN BOOLEAN MODE); +select * from t1 where MATCH(a,b) AGAINST("+Mysql +(tricks never)" IN BOOLEAN MODE); +select * from t1 where MATCH(a,b) AGAINST("+mysql -(tricks never)" IN BOOLEAN MODE) ORDER BY id; +select *, MATCH(a,b) AGAINST("mysql VÃÆ·Wİ" IN BOOLEAN MODE) as x from t1 ORDER BY id; +# Innodb:Assert eval0eval.c line 148 +#select * from t1 where MATCH a,b AGAINST ("+database* +VÃÆ·Wİ*" IN BOOLEAN MODE); +select * from t1 where MATCH a,b AGAINST ('"security mysql"' IN BOOLEAN MODE); + +# query expansion +select * from t1 where MATCH(a,b) AGAINST ("VÃÆ·Wİ" WITH QUERY EXPANSION) ORDER BY id; + + +# insert for proximity search +INSERT INTO t1 (a,b) VALUES ('test query expansion','for database ...'); +# Insert into table with similar word of different distances +INSERT INTO t1 (a,b) VALUES + ('test proximity search, test, proximity and phrase', + 'search, with proximity innodb'); + +INSERT INTO t1 (a,b) VALUES + ('test proximity fts search, test, proximity and phrase', + 'search, with proximity innodb'); + +INSERT INTO t1 (a,b) VALUES + ('test more proximity fts search, test, more proximity and phrase', + 'search, with proximity innodb'); + +# This should only return the first document +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"proximity search"@2' IN BOOLEAN MODE); + +# This would return no document +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"proximity search"@1' IN BOOLEAN MODE); + +# This give you all three documents +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"proximity search"@3' IN BOOLEAN MODE) ORDER BY id; + +# Similar boundary testing for the words +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"test proximity"@5' IN BOOLEAN MODE) ORDER BY id; + +# Test with more word The last document will return, please notice there +# is no ordering requirement for proximity search. +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"more test proximity"@2' IN BOOLEAN MODE); + +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"more test proximity"@3' IN BOOLEAN MODE); + +# The phrase search will not require exact word ordering +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"more fts proximity"@03' IN BOOLEAN MODE); + + +UPDATE t1 SET a = UPPER(a) , b = UPPER(b) ; +UPDATE t1 SET a = UPPER(a) , b = LOWER(b) ; + +select * from t1 where MATCH(a,b) AGAINST("+tutorial +dbms" IN BOOLEAN MODE); +select * from t1 where MATCH(a,b) AGAINST("+VÃÆ·Wİ" IN BOOLEAN MODE); + +SELECT * FROM t1 WHERE MATCH (a,b) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) ORDER BY id; + +DELETE FROM t1 WHERE MATCH (a,b) AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); +DELETE FROM t1 WHERE MATCH (a,b) AGAINST ('"proximity search"@14' IN BOOLEAN MODE); + + +SELECT * FROM t1 WHERE MATCH (a,b) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + +SELECT * FROM t1 ORDER BY id; + +DROP TABLE t1; +eval SET GLOBAL innodb_file_per_table=$innodb_file_per_table_orig; + +#------------------------------------------------------------------------------ +# FTS index with utf8 character testcase +#------------------------------------------------------------------------------ + +# Create FTS table +EVAL CREATE TABLE t1 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a VARCHAR(200), + b TEXT + ) CHARACTER SET = utf8, ENGINE=InnoDB; + + +# Insert rows from different languages +INSERT INTO t1 (a,b) VALUES +('Я могу еÑть Ñтекло', 'оно мне не вредит'), +('Мога да Ñм Ñтъкло', 'то не ми вреди'), +('ΜποÏá¿¶ νὰ φάω σπασμένα' ,'γυαλιὰ χωÏá½¶Ï‚ νὰ πάθω τίποτα'), +('PříliÅ¡ žluÅ¥ouÄký kůň', 'úpÄ›l Äábelské kódy'), +('Sævör grét', 'áðan því úlpan var ónýt'), +('ã†ã‚ã®ãŠãã‚„ã¾','ã‘ãµã“ãˆã¦'), +('ã„ã‚ã¯ã«ã»ã¸ã©ã€€ã¡ã‚Šã¬ã‚‹','ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš'); + +# insert english text +INSERT INTO t1 (a,b) VALUES + ('MySQL Tutorial','request docteam@oraclehelp.com ...') , + ('Trial version','query performace @1255 minute on 2.1Hz Memory 2GB...') , + ('when To Use MySQL Well','for free faq mail@xyz.com ...'); + +# Create the FTS index again +CREATE FULLTEXT INDEX idx on t1 (a,b); + +# FTS Queries +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("вредит χωÏá½¶Ï‚") ORDER BY id; +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("оно" WITH QUERY EXPANSION); + +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("вред*" IN BOOLEAN MODE) ORDER BY id; +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("+γυαλιὰ +tutorial" IN BOOLEAN MODE); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("+tutorial +(Мога τίποτα)" IN BOOLEAN MODE); + +# Innodb:error - no result returned (update result of query once fixed) (innodb limit , does not understand character boundry for japanses like charcter set) +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš"); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("ã¡ã‚Šã¬ã‚‹" WITH QUERY EXPANSION); + +# Innodb:error - no result returned (update result of query once fixed) (innodb limit , does not understand character boundry for japanses like charcter set) +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("+ã‚ã•ãゆã‚ã¿ã˜ã€€+ã‚‘ã²ã‚‚ã›ãš" IN BOOLEAN MODE); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("ã†ã‚ã®ãŠã*" IN BOOLEAN MODE); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("+Sævör +úlpan" IN BOOLEAN MODE); + +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"γυαλιὰ χωÏá½¶Ï‚"@2' IN BOOLEAN MODE); + +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"query performace"@02' IN BOOLEAN MODE); + +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"πάθω τίποτα"@2' IN BOOLEAN MODE); + +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"ã‚ã•ãゆã‚ã¿ã˜ ã‚‘ã²ã‚‚ã›ãš"@1' IN BOOLEAN MODE); + +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"ã‚ã•ãゆã‚ã¿ã˜ ã‚‘ã²ã‚‚ã›ãš"@2' IN BOOLEAN MODE); + +ALTER TABLE t1 DROP INDEX idx; +# Create the FTS index again +CREATE FULLTEXT INDEX idx on t1 (a,b); + +# Innodb:error - no result returned (update result of query once fixed) (innodb limit , does not understand character boundry for japanses like charcter set) +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("ã‚ã•ãゆã‚ã¿ã˜ ã‚‘ã²ã‚‚ã›ãš"); +# Update fails because where condition do not succeed which is incorrect (update result of query once fixed) +UPDATE t1 SET a = "Pchnąć w tÄ™ łódź jeża" , b = "lub osiem skrzyÅ„ fig" WHERE MATCH(a,b) AGAINST ("ã‚ã•ãゆã‚ã¿ã˜ ã‚‘ã²ã‚‚ã›ãš"); +UPDATE t1 SET a = "Ð’ чащах юга жил-был цитруÑ? Да", b = "но фальшивый ÑкземплÑÑ€! ёъ" WHERE MATCH(a,b) AGAINST ("вред*" IN BOOLEAN MODE); +DELETE FROM t1 WHERE MATCH(a,b) AGAINST("+Sævör +úlpan" IN BOOLEAN MODE); + +# Innodb error - no result returned +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš"); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST ("łódź osiem"); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("вред*" IN BOOLEAN MODE); +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("фальшив*" IN BOOLEAN MODE) ORDER BY id; +SELECT * FROM t1 WHERE MATCH(a,b) AGAINST("+Sævör +úlpan" IN BOOLEAN MODE); + +SELECT * FROM t1 + WHERE MATCH (a,b) + AGAINST ('"łódź jeża"@2' IN BOOLEAN MODE); + +SELECT * FROM t1 ORDER BY id; +DROP TABLE t1; + +# This is to test the update operation on FTS indexed and non-indexed +# column +CREATE TABLE t1(ID INT PRIMARY KEY, + no_fts_field VARCHAR(10), + fts_field VARCHAR(10), + FULLTEXT INDEX f(fts_field)) ENGINE=INNODB; + +INSERT INTO t1 VALUES (1, 'AAA', 'BBB'); + +SELECT * FROM t1 WHERE MATCH(fts_field) against("BBB"); + +# Update FULLTEXT indexed column, Doc ID will be updated +UPDATE t1 SET fts_field='anychange' where id = 1; + +SELECT * FROM t1 WHERE MATCH(fts_field) against("anychange"); + +# Update non-FULLTEXT indexed column, Doc ID stay to be the same +UPDATE t1 SET no_fts_field='anychange' where id = 1; + +SELECT * FROM t1 WHERE MATCH(fts_field) against("anychange"); + +# Update both FULLTEXT indexed and non-indexed column, Doc ID will be updated +UPDATE t1 SET no_fts_field='anychange', fts_field='other' where id = 1; + +SELECT * FROM t1 WHERE MATCH(fts_field) against("other"); + +SELECT * FROM t1 WHERE MATCH(fts_field) against("BBB"); + +# FTS index dropped, the DOC_ID column is kept, however, the ID will not +# change +DROP INDEX f on t1; + +UPDATE t1 SET fts_field='anychange' where id = 1; + +UPDATE t1 SET no_fts_field='anychange' where id = 1; + +UPDATE t1 SET no_fts_field='anychange', fts_field='other' where id = 1; + +CREATE FULLTEXT INDEX f ON t1(FTS_FIELD); + +SELECT * FROM t1 WHERE MATCH(fts_field) against("other"); + +DROP TABLE t1; + +# Test on user supplied 'FTS_DOC_ID' +CREATE TABLE t1(`FTS_DOC_ID` serial, + no_fts_field VARCHAR(10), + fts_field VARCHAR(10), + FULLTEXT INDEX f(fts_field)) ENGINE=INNODB; + +INSERT INTO t1 VALUES (1, 'AAA', 'BBB'); + +# Doc ID must be updated as well (HA_FTS_INVALID_DOCID). +--error 182 +UPDATE t1 SET fts_field='anychange' where FTS_DOC_ID = 1; + +UPDATE t1 SET fts_field='anychange', FTS_DOC_ID = 2 where FTS_DOC_ID = 1; + +SELECT * FROM t1 WHERE MATCH(fts_field) against("anychange"); + +# "BBB" should be marked as deleted. +SELECT * FROM t1 WHERE MATCH(fts_field) against("BBB"); + +UPDATE t1 SET no_fts_field='anychange' where FTS_DOC_ID = 2; + +SELECT * FROM t1 WHERE MATCH(fts_field) against("anychange"); + +# "HA_FTS_INVALID_DOCID" +--error 182 +UPDATE t1 SET no_fts_field='anychange', fts_field='other' where FTS_DOC_ID = 2; + +SELECT * FROM t1 WHERE MATCH(fts_field) against("other"); + +# Doc ID must be monotonically increase (HA_FTS_INVALID_DOCID) +--error 182 +UPDATE t1 SET FTS_DOC_ID = 1 where FTS_DOC_ID = 2; + +DROP INDEX f ON t1; + +# After FULLTEXT index dropped, we can update the fields freely +UPDATE t1 SET fts_field='newchange' where FTS_DOC_ID = 2; + +UPDATE t1 SET no_fts_field='anychange' where FTS_DOC_ID = 2; + +SELECT * FROM t1; + +DROP TABLE t1; + +CREATE TABLE t1(ID INT PRIMARY KEY, + no_fts_field VARCHAR(10), + fts_field VARCHAR(10), + FULLTEXT INDEX f(fts_field), index k(fts_field)) ENGINE=INNODB; + +CREATE TABLE t2(ID INT PRIMARY KEY, + no_fts_field VARCHAR(10), + fts_field VARCHAR(10), + FULLTEXT INDEX f(fts_field), + INDEX k2(fts_field), + FOREIGN KEY(fts_field) REFERENCES + t1(fts_field) ON UPDATE CASCADE) ENGINE=INNODB; + +INSERT INTO t1 VALUES (1, 'AAA', 'BBB'); + +INSERT INTO t2 VALUES (1, 'AAA', 'BBB'); + +update t1 set fts_field='newchange' where id =1; + +SELECT * FROM t1 WHERE MATCH(fts_field) against("BBB"); +SELECT * FROM t2 WHERE MATCH(fts_field) against("BBB"); +SELECT * FROM t1 WHERE MATCH(fts_field) against("newchange"); +SELECT * FROM t2 WHERE MATCH(fts_field) against("newchange"); + +DROP TABLE t2; + +DROP TABLE t1; + +# Testcases adopted from innodb_multi_update.test + +CREATE TABLE t1(id INT PRIMARY KEY, + fts_field VARCHAR(10), + FULLTEXT INDEX f(fts_field)) ENGINE=INNODB; + + +CREATE TABLE t2(id INT PRIMARY KEY, + fts_field VARCHAR(10), + FULLTEXT INDEX f(fts_field)) ENGINE=INNODB; + +INSERT INTO t1 values (1,'100'),(2,'200'),(3,'300'),(4,'400'),(5,'500'),(6,'600'), (7,'700'),(8,'800'),(9,'900'),(10,'1000'),(11,'1100'),(12,'1200'); +INSERT INTO t2 values (1,'100'),(2,'200'),(3,'300'),(4,'400'),(5,'500'),(6,'600'), (7,'700'),(8,'800'); + +UPDATE t1, t2 set t1.fts_field = CONCAT(t1.fts_field, 'foo'); + +UPDATE t1, t2 set t1.fts_field = CONCAT(t1.fts_field, 'foo') WHERE t1.fts_field = "100foo"; + +# Update two tables in the same statement +UPDATE t1, t2 set t1.fts_field = CONCAT(t1.fts_field, 'xoo'), t2.fts_field = CONCAT(t1.fts_field, 'xoo') where t1.fts_field=CONCAT(t2.fts_field, 'foo'); + +# Following selects shows whether the correct Doc ID are updated + +# This row should present in table t1 +SELECT * FROM t1 WHERE MATCH(fts_field) against("100foofoo"); + +# Following rows should be dropped +SELECT * FROM t1 WHERE MATCH(fts_field) against("100foo"); +SELECT * FROM t1 WHERE MATCH(fts_field) against("100"); + +# This row should present in table t2 +SELECT * FROM t2 WHERE MATCH(fts_field) against("400fooxoo"); +SELECT * FROM t2 WHERE MATCH(fts_field) against("100"); + +# Follow rows should be marked as dropped +SELECT * FROM t2 WHERE MATCH(fts_field) against("200"); +SELECT * FROM t2 WHERE MATCH(fts_field) against("400"); + + +DROP TABLE t1; + +DROP TABLE t2; + + +--echo +--echo BUG#13701973/64274: MYSQL THREAD WAS SUSPENDED WHEN EXECUTE UPDATE QUERY +--echo +# FTS setup did not track which tables it had already looked at to see whether +# they need initialization. Hilarity ensued when hitting circular dependencies. + +SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; + +CREATE TABLE t1 ( + t1_id INT(10) UNSIGNED NOT NULL, + t2_id INT(10) UNSIGNED DEFAULT NULL, + PRIMARY KEY (t1_id), + FOREIGN KEY (t2_id) REFERENCES t2 (t2_id) + ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; + +CREATE TABLE t2 ( + t1_id INT(10) UNSIGNED NOT NULL, + t2_id INT(10) UNSIGNED NOT NULL, + t3_id INT(10) UNSIGNED NOT NULL, + t4_id INT(10) UNSIGNED NOT NULL, + PRIMARY KEY (t2_id), + FOREIGN KEY (t1_id) REFERENCES t1 (t1_id), + FOREIGN KEY (t3_id) REFERENCES t3 (t3_id) + ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY (t4_id) REFERENCES t4 (t4_id) +) ENGINE=InnoDB; + +CREATE TABLE t3 ( + t3_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + payload char(3), + PRIMARY KEY (t3_id) +) ENGINE=InnoDB; + +INSERT INTO t3 VALUES (1, '100'); + +CREATE TABLE t4 ( + t2_id INT(10) UNSIGNED DEFAULT NULL, + t4_id INT(10) UNSIGNED NOT NULL, + PRIMARY KEY (t4_id), + FOREIGN KEY (t2_id) REFERENCES t2 (t2_id) + ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; + +SET FOREIGN_KEY_CHECKS=1; + +UPDATE t3 SET payload='101' WHERE t3_id=1; + +SET FOREIGN_KEY_CHECKS=0; + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; + +SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; diff --git a/mysql-test/suite/innodb_fts/t/opt.opt b/mysql-test/suite/innodb_fts/t/opt.opt new file mode 100644 index 00000000000..d7d47164883 --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/opt.opt @@ -0,0 +1 @@ +--query_cache_type=0 diff --git a/mysql-test/suite/innodb_fts/t/opt.test b/mysql-test/suite/innodb_fts/t/opt.test new file mode 100644 index 00000000000..19dfdcad8fd --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/opt.test @@ -0,0 +1,1086 @@ +--source include/have_innodb.inc + +# +# Tests for optimizations for InnoDB fulltext search (WL#6043) +# + +CREATE TABLE wp( + FTS_DOC_ID BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + title VARCHAR(255) NOT NULL DEFAULT '', + text MEDIUMTEXT NOT NULL, + dummy INTEGER, + PRIMARY KEY (FTS_DOC_ID), + UNIQUE KEY FTS_DOC_ID_INDEX (FTS_DOC_ID), + FULLTEXT KEY idx (title,text) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO wp (title, text) VALUES + ('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database to database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +CREATE TABLE t1 (i INTEGER); +INSERT INTO t1 SELECT FTS_DOC_ID FROM wp; + +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE t1; +SET STATEMENT use_stat_tables=never FOR +ANALYZE TABLE wp; + +--disable_ps2_protocol + +# +# Show results of MATCH expressions for reference +# +SELECT FTS_DOC_ID, title, MATCH(title, text) AGAINST ('database') AS score1, + MATCH(title, text) AGAINST ('mysql') AS score2 +FROM wp; + +# +# Test that filesort is not used if ordering on same match expression +# as where clause +# +--echo No sorting for this query +FLUSH STATUS; + +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score DESC; + +SHOW SESSION STATUS LIKE 'Sort%'; + +--echo No sorting for this query even if MATCH is part of an expression +FLUSH STATUS; + +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') > 0.1 +ORDER BY score DESC; + +SHOW SESSION STATUS LIKE 'Sort%'; + +--echo No sorting even if there are several MATCH expressions as long as the +--echo right one is used in ORDER BY +FLUSH STATUS; + +SELECT title, MATCH(title, text) AGAINST ('database') AS score1, + MATCH(title, text) AGAINST ('mysql') AS score2 +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score1 DESC; + +SHOW SESSION STATUS LIKE 'Sort%'; + +--echo No Sorting since FT table is first table in query +FLUSH STATUS; + +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp, t1 +WHERE MATCH(title, text) AGAINST ('database') AND FTS_DOC_ID = t1.i +ORDER BY score DESC; + +SHOW SESSION STATUS LIKE 'Sort_rows%'; + +--echo Sorting since there is no WHERE clause +FLUSH STATUS; + +--sorted_result +SELECT MATCH(title, text) AGAINST ('database'), title AS score +FROM wp +ORDER BY score DESC; + +SHOW SESSION STATUS LIKE 'Sort_rows%'; + +--echo Sorting since ordering on multiple columns +FLUSH STATUS; + +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score DESC, FTS_DOC_ID; + +SHOW SESSION STATUS LIKE 'Sort_rows%'; + +--echo Sorting since ordering is not descending +FLUSH STATUS; + +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score ASC; + +SHOW SESSION STATUS LIKE 'Sort_rows%'; + +--echo Sorting because one is ordering on a different MATCH expression +FLUSH STATUS; + +SELECT title, MATCH(title, text) AGAINST ('mysql') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score DESC; + +SHOW SESSION STATUS LIKE 'Sort_rows%'; + +# +# Tests for ORDER BY/LIMIT optimzation +# +--echo No sorting for this query +FLUSH STATUS; + +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +ORDER BY score DESC LIMIT 2; + +SHOW SESSION STATUS LIKE 'Sort%'; + +--echo Revert to table scan and sorting for this query since not +--echo enough matching rows to satisfy LIMIT clause +FLUSH STATUS; + +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +ORDER BY score DESC LIMIT 2; + +SHOW SESSION STATUS LIKE 'Handler_read%'; +SHOW SESSION STATUS LIKE 'Sort_rows%'; + +--echo Sorting since no LIMIT clause +FLUSH STATUS; + +--sorted_result +SELECT MATCH(title, text) AGAINST ('database') AS score, title +FROM wp +ORDER BY score DESC; + +SHOW SESSION STATUS LIKE 'Sort_rows%'; + +--echo Sorting since there is a WHERE clause +FLUSH STATUS; + +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE dummy IS NULL +ORDER BY score DESC LIMIT 2; + +SHOW SESSION STATUS LIKE 'Sort_rows%'; + +--echo Sorting since ordering is not on a simple MATCH expressions +FLUSH STATUS; + +SELECT title, (MATCH(title, text) AGAINST ('database')) * 100 AS score +FROM wp +ORDER BY score DESC LIMIT 2; + +SHOW SESSION STATUS LIKE 'Sort_rows%'; + +# +# Test that there is no row accesses if all necessary information is +# available in FTS result +# +--echo No ordinary handler accesses when only accessing FTS_DOC_ID and MATCH +FLUSH STATUS; + +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database'); + +SHOW SESSION STATUS LIKE 'Handler_read%'; + +--echo Still no handler accesses when adding FTS_DOC_ID to WHERE clause +FLUSH STATUS; + +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') AND FTS_DOC_ID > 2; + +SHOW SESSION STATUS LIKE 'Handler_read%'; + +--echo Still no handler accesses when ordering by MATCH expression +FLUSH STATUS; + +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score; + +SHOW SESSION STATUS LIKE 'Handler_read%'; + +--echo Optimization is disabled when ordering on FTS_DOC_ID +FLUSH STATUS; + +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY 1 DESC; + +SHOW SESSION STATUS LIKE 'Handler_read%'; + +--echo Optimization also work with several MATCH expressions +FLUSH STATUS; + +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score1, + MATCH(title, text) AGAINST ('mysql') AS score2 +FROM wp +WHERE MATCH(title, text) AGAINST ('database'); + +SHOW SESSION STATUS LIKE 'Handler_read%'; + +--echo Optimization does not apply if sorting on a different MATCH expressions +--echo from the one used to access the +FLUSH STATUS; + +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score1, + MATCH(title, text) AGAINST ('mysql') AS score2 +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score2 DESC; + +SHOW SESSION STATUS LIKE 'Handler_read%'; + +FLUSH STATUS; + +--echo Optimization does not apply for GROUP BY +SET @save_mode = @@sql_mode; +SET sql_mode = (select replace(@@sql_mode,'ONLY_FULL_GROUP_BY','')); +SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +GROUP BY score; + +SHOW SESSION STATUS LIKE 'Handler_read%'; +SET sql_mode = @save_mode; + +# +# Putting all three optimizations together +# +--echo No sorting and no table access with LIMIT clause and only information +--echo from FTS result +FLUSH STATUS; + +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +ORDER BY score DESC LIMIT 2; + +SHOW STATUS LIKE 'Handler_read%'; +SHOW SESSION STATUS LIKE 'Sort%'; + +# +# Count optimization +# +let $query = +SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE); + +--echo If count optimization applies, EXPLAIN shows +--echo "Select tables optimized away." +eval EXPLAIN $query; +FLUSH STATUS; +eval $query; +--echo Verify that there was no table access +SHOW STATUS LIKE 'Handler_read%'; + +let $query = +SELECT COUNT(title) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE); + +--echo Optimization applies also to COUNT(expr) as long as expr is not nullable +eval EXPLAIN $query; +eval $query; + +let $query = +SELECT count(*) +FROM wp, t1 +WHERE MATCH(title, text) AGAINST ('database'); + +--echo Optimization does not apply if not a single table query. +eval EXPLAIN $query; +eval $query; + +let $query = +SELECT COUNT(title) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE) > 0; + +--echo Optimization does not apply if MATCH is part of an expression +eval EXPLAIN $query; +eval $query; + +let $query = +SELECT COUNT(title) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE) > 0; + +--echo Optimization does not apply if MATCH is part of an expression +eval EXPLAIN $query; +eval $query; + +let $query = +SELECT COUNT(dummy) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE); + +--echo Optimization does not apply if COUNT expression is nullable +eval EXPLAIN $query; +eval $query; + +# +# Verify that the queries optimized for InnoDB works with QUERY EXPANSION +# + +# Query will also avoid sorting when query expansion is used +FLUSH STATUS; +--sorted_result +SELECT MATCH(title, text) AGAINST ('database' WITH QUERY EXPANSION) AS score, +title +FROM wp +WHERE MATCH(title, text) AGAINST ('database' WITH QUERY EXPANSION) +ORDER BY score DESC; +SHOW SESSION STATUS LIKE 'Sort%'; + +# Check ORDER BY/LIMIT query with no WHERE clause +FLUSH STATUS; +SELECT title, + MATCH(title, text) AGAINST ('database' WITH QUERY EXPANSION) AS score +FROM wp +ORDER BY score DESC LIMIT 2; +SHOW SESSION STATUS LIKE 'Sort%'; + +# Check query where FTS result is "covering" +FLUSH STATUS; +SELECT FTS_DOC_ID docid, + MATCH(title, text) AGAINST ('database' WITH QUERY EXPANSION) AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database'); +SHOW SESSION STATUS LIKE 'Handler_read%'; + +# Check the combination of all three +FLUSH STATUS; +SELECT FTS_DOC_ID docid, + MATCH(title, text) AGAINST ('database' WITH QUERY EXPANSION) AS score +FROM wp +ORDER BY score DESC LIMIT 2; +SHOW STATUS LIKE 'Handler_read%'; +SHOW SESSION STATUS LIKE 'Sort%'; + +# Check the count optimization +let $query = +SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' WITH QUERY EXPANSION); +eval EXPLAIN $query; +FLUSH STATUS; +eval $query; +SHOW STATUS LIKE 'Handler_read%'; + +# +# Verify that the queries optimized for InnoDB works with BOOLEAN MODE +# + +# Query will also avoid sorting when Boolean mode is used +FLUSH STATUS; +--sorted_result +SELECT MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) score, +title +FROM wp +WHERE MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) +ORDER BY score DESC; +SHOW SESSION STATUS LIKE 'Sort%'; + +# Check ORDER BY/LIMIT query with no WHERE clause +FLUSH STATUS; +--sorted_result +SELECT MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) score, +title +FROM wp +ORDER BY score DESC; +SHOW SESSION STATUS LIKE 'Sort%'; + +# Check query where FTS result is "covering" +FLUSH STATUS; +SELECT FTS_DOC_ID docid, + MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('+MySQL -database'); +SHOW SESSION STATUS LIKE 'Handler_read%'; + +# Check the combination of all three +FLUSH STATUS; +SELECT FTS_DOC_ID docid, + MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) AS score +FROM wp +ORDER BY score DESC LIMIT 1; +SHOW STATUS LIKE 'Handler_read%'; +SHOW SESSION STATUS LIKE 'Sort%'; + +# Check the count optimization +let $query = +SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('+MySQL -database' IN BOOLEAN MODE); +eval EXPLAIN $query; +FLUSH STATUS; +eval $query; +SHOW STATUS LIKE 'Handler_read%'; + + +# +# Verify that the queries optimized for InnoDB works with +# BOOLEAN proximity search +# + +# Query will also avoid sorting when Boolean mode is used +FLUSH STATUS; +SELECT title, + MATCH(title, text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE) AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE) +ORDER BY score DESC; +SHOW SESSION STATUS LIKE 'Sort%'; + +# Check ORDER BY/LIMIT query with no WHERE clause +FLUSH STATUS; +SELECT title, + MATCH(title, text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE) AS score +FROM wp +ORDER BY score DESC LIMIT 1; +SHOW SESSION STATUS LIKE 'Sort%'; + +# Check query where FTS result is "covering" +FLUSH STATUS; +SELECT FTS_DOC_ID docid, + MATCH(title, text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE) AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('"MySQL database"@5'); +SHOW SESSION STATUS LIKE 'Handler_read%'; + +# Check the combination of all three +FLUSH STATUS; +SELECT FTS_DOC_ID docid, + MATCH(title, text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE) AS score +FROM wp +ORDER BY score DESC LIMIT 1; +SHOW STATUS LIKE 'Handler_read%'; +SHOW SESSION STATUS LIKE 'Sort%'; + +# Check the count optimization +let $query = +SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE); +eval EXPLAIN $query; +FLUSH STATUS; +eval $query; +SHOW STATUS LIKE 'Handler_read%'; + +# +# Check that nothing goes wrong when combining different modes +# +SELECT title, + MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database' WITH QUERY EXPANSION) +ORDER BY score DESC, title ASC; + +SELECT title, + MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('MySQL database' WITH QUERY EXPANSION) +ORDER BY score DESC, title ASC; + +SELECT title, + MATCH(title, text) AGAINST ('+MySQL -database' IN BOOLEAN MODE) AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('"MySQL database"@5' IN BOOLEAN MODE) +ORDER BY score DESC, title ASC; + + +# +# Verify that the queries optimized for InnoDB still works with MyISAM +# +ALTER TABLE wp ENGINE=myisam; + +# Check avoid sorting query +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database') +ORDER BY score DESC; +SHOW SESSION STATUS LIKE 'Sort%'; + +# Check ORDER BY/LIMIT query with no WHERE clause +FLUSH STATUS; +SELECT title, MATCH(title, text) AGAINST ('database') AS score +FROM wp +ORDER BY score DESC LIMIT 2; +SHOW SESSION STATUS LIKE 'Sort%'; + +# Check query where FTS result is "covering" +FLUSH STATUS; +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +WHERE MATCH(title, text) AGAINST ('database'); +SHOW SESSION STATUS LIKE 'Handler_read%'; + +# Check the combination of all three +FLUSH STATUS; +SELECT FTS_DOC_ID docid, MATCH(title, text) AGAINST ('database') AS score +FROM wp +ORDER BY score DESC LIMIT 2; +SHOW STATUS LIKE 'Handler_read%'; +SHOW SESSION STATUS LIKE 'Sort%'; + +# Check the count optimization +let $query = +SELECT COUNT(*) +FROM wp +WHERE MATCH(title,text) AGAINST ('database' IN NATURAL LANGUAGE MODE); +eval EXPLAIN $query; +FLUSH STATUS; +eval $query; +SHOW STATUS LIKE 'Handler_read%'; + + +DROP TABLE wp, t1; + +--enable_ps2_protocol + +# Tests for FT hints. + +CREATE TABLE t1 +( + FTS_DOC_ID BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + title VARCHAR(255) DEFAULT '', + text MEDIUMTEXT , + PRIMARY KEY (FTS_DOC_ID), + UNIQUE KEY FTS_DOC_ID_INDEX (FTS_DOC_ID), + FULLTEXT KEY ft_idx (title,text) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + + +INSERT INTO t1 (title, text) VALUES + ('MySQL Tutorial','DBMS stands for MySQL DataBase ...'), + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL database','In the following database to database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'), + ('InnoDB', 'InnoDB is a transaction-safe (ACID compliant) storage engine'), + ('MySQL is a database management system', 'A database is a structured collection of data...'), + ('MySQL databases are relational', 'A relational database stores data in separate tables rather than putting all the data in one big storeroom...'), + ('MySQL software is Open Source', 'Open Source means that it is possible for anyone to use and modify the software...'), + ('The MySQL Database Server is very fast, reliable, scalable, and easy to use', 'MySQL Server can run comfortably on a desktop or laptop...'), + ('MySQL Server works in client/server or embedded systems', 'The MySQL Database Software is a client/server system...'), + ('MyISAM', 'MyISAM is based on the older (and no longer available) ISAM storage engine but has many useful extensions'), + ('A large amount of contributed MySQL software is available', 'MySQL Server has a practical set of features developed in close cooperation with our users'), + (NULL,NULL); + +-- disable_result_log +ANALYZE TABLE t1; +-- enable_result_log + +--echo # No ranking + +EXPLAIN +SELECT count(*) FROM t1 WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE); +SELECT count(*) FROM t1 WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE); + +# Atm opt_sum_query does not support COUNT optimization if +# ORDER BY is present. TODO: fix it. +EXPLAIN +SELECT count(*) FROM t1 WHERE MATCH (title, text) AGAINST ('data*' IN BOOLEAN MODE) ORDER BY title LIMIT 3; +SELECT count(*) FROM t1 WHERE MATCH (title, text) AGAINST ('data*' IN BOOLEAN MODE) ORDER BY title LIMIT 3; + +EXPLAIN +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE); +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE); + +EXPLAIN +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION); +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION); + +EXPLAIN +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('"very fast"@3' IN BOOLEAN MODE); +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('"very fast"@3' IN BOOLEAN MODE); + +# check case with 'for' stopword +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+for' IN BOOLEAN MODE); +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+for' IN BOOLEAN MODE); + + +--echo # No sorting by rank + +EXPLAIN SELECT FTS_DOC_ID, TITLE FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY title; +SELECT FTS_DOC_ID, TITLE FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY title; + +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE); +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE); + +EXPLAIN +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) ORDER BY title; +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) ORDER BY title; + +EXPLAIN +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('"very fast"@3' IN BOOLEAN MODE) ORDER BY title; +SELECT FTS_DOC_ID, title FROM t1 WHERE MATCH(title, text) AGAINST ('"very fast"@3' IN BOOLEAN MODE) ORDER BY title; + +--echo # LIMIT optimization + +EXPLAIN SELECT FTS_DOC_ID, TITLE FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +LIMIT 3; +SELECT FTS_DOC_ID, TITLE FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +LIMIT 3; + +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE) +LIMIT 3; +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE) +LIMIT 3; + +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE) +ORDER BY title +LIMIT 3; +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+fast +database' IN BOOLEAN MODE) +ORDER BY title +LIMIT 3; + + +EXPLAIN +SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) ORDER BY title LIMIT 1; +SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) ORDER BY title LIMIT 1; + +EXPLAIN +SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ('"very fast"@3' IN BOOLEAN MODE) ORDER BY title LIMIT 1; +SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ('"very fast"@3' IN BOOLEAN MODE) ORDER BY title LIMIT 1; + +EXPLAIN +SELECT FTS_DOC_ID, MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) as rank +FROM t1 WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY rank, FTS_DOC_ID +LIMIT 3; +SELECT FTS_DOC_ID, MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) as rank +FROM t1 WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY rank, FTS_DOC_ID +LIMIT 3; + +EXPLAIN +SELECT FTS_DOC_ID, MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) as rank +FROM t1 WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY rank DESC, FTS_DOC_ID ASC +LIMIT 3; +SELECT FTS_DOC_ID, MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) as rank +FROM t1 WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY rank DESC, FTS_DOC_ID ASC +LIMIT 3; + +EXPLAIN SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 +ORDER BY rank DESC +LIMIT 2; +SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 +ORDER BY rank DESC +LIMIT 2; + +EXPLAIN SELECT FTS_DOC_ID, MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) as rank +FROM t1 +ORDER BY rank DESC +LIMIT 3; +SELECT FTS_DOC_ID, MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) as rank +FROM t1 +ORDER BY rank DESC +LIMIT 3; + +EXPLAIN SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) +ORDER BY MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) DESC, +FTS_DOC_ID ASC; +SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) +ORDER BY MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) DESC, +FTS_DOC_ID ASC; + +EXPLAIN SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) and FTS_DOC_ID > 1 +ORDER BY MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) DESC +LIMIT 2; +SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) and FTS_DOC_ID > 1 +ORDER BY MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) DESC +LIMIT 2; + + +EXPLAIN +SELECT FTS_DOC_ID,MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +ORDER BY rank +LIMIT 1; +SELECT FTS_DOC_ID,MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +ORDER BY rank +LIMIT 1; + +EXPLAIN +SELECT FTS_DOC_ID,MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +ORDER BY rank DESC +LIMIT 1; +SELECT FTS_DOC_ID,MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +ORDER BY rank DESC +LIMIT 1; + + +EXPLAIN +SELECT FTS_DOC_ID,MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +ORDER BY MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +LIMIT 1; +SELECT FTS_DOC_ID,MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) as rank +FROM t1 WHERE MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) +ORDER BY MATCH(title, text) AGAINST ('+very +fast' WITH QUERY EXPANSION) DESC +LIMIT 1; + +--echo # WHERE optimization on MATCH > 'some_rank' + +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) > 0.1; + +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) > 0.1; + + +--echo # additional test for correct behaviour + +EXPLAIN SELECT * FROM t1 ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC LIMIT 10; + +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) AND +MATCH (title, text) AGAINST ('mysql' IN NATURAL LANGUAGE MODE) +LIMIT 6; + +--echo # test OR condition + +SELECT FTS_DOC_ID +FROM t1 +WHERE MATCH(title, text) AGAINST ('database') + OR MATCH(title, text) AGAINST ('mysql') +ORDER BY MATCH(title, text) AGAINST ('database') DESC, FTS_DOC_ID ASC; + +EXPLAIN SELECT FTS_DOC_ID +FROM t1 +WHERE MATCH(title, text) AGAINST ('database') + OR MATCH(title, text) AGAINST ('mysql') +ORDER BY MATCH(title, text) AGAINST ('database') DESC, FTS_DOC_ID ASC; + +--echo # MATCH and GROUP BY, DISTINCT + +SET sql_mode = (select replace(@@sql_mode,'ONLY_FULL_GROUP_BY','')); + +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +GROUP BY FTS_DOC_ID +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +GROUP BY FTS_DOC_ID +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; + +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +GROUP BY title +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; + +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +GROUP BY title +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; + +EXPLAIN SELECT MAX(FTS_DOC_ID) FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +SELECT MAX(FTS_DOC_ID) FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; + +EXPLAIN SELECT DISTINCT(title) FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +SELECT DISTINCT(title) FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; + +EXPLAIN SELECT DISTINCT(FTS_DOC_ID) FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; +SELECT DISTINCT(FTS_DOC_ID) FROM t1 +WHERE MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) +ORDER BY MATCH (title, text) AGAINST ('fast database' IN NATURAL LANGUAGE MODE) DESC +LIMIT 3; + +SET sql_mode = @save_mode; + +--echo # FTS index access + +SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 +ORDER BY rank DESC +LIMIT 2; +EXPLAIN SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) as rank +FROM t1 +ORDER BY rank DESC +LIMIT 2; + +SELECT a.FTS_DOC_ID, b.FTS_DOC_ID +FROM t1 a, t1 b +WHERE MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE) and + MATCH(b.title, b.text) AGAINST ('+mysql' IN BOOLEAN MODE) and + a.FTS_DOC_ID = b.FTS_DOC_ID; +EXPLAIN SELECT a.FTS_DOC_ID, b.FTS_DOC_ID +FROM t1 a, t1 b +WHERE MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE) and + MATCH(b.title, b.text) AGAINST ('+mysql' IN BOOLEAN MODE) and + a.FTS_DOC_ID = b.FTS_DOC_ID; + +SELECT a.FTS_DOC_ID, MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE), + b.FTS_DOC_ID, MATCH(b.title, b.text) AGAINST ('+database' IN BOOLEAN MODE) +FROM t1 a, t1 b +WHERE MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE) and + MATCH(b.title, b.text) AGAINST ('+database' IN BOOLEAN MODE); + +EXPLAIN SELECT a.FTS_DOC_ID, MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE), + b.FTS_DOC_ID, MATCH(b.title, b.text) AGAINST ('+database' IN BOOLEAN MODE) +FROM t1 a, t1 b +WHERE MATCH(a.title, a.text) AGAINST ('+database' IN BOOLEAN MODE) and + MATCH(b.title, b.text) AGAINST ('+database' IN BOOLEAN MODE); + +# Index only access by non-FTS index + +EXPLAIN SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ("data*" IN BOOLEAN MODE) * 100; +SELECT FTS_DOC_ID, MATCH(title, text) AGAINST ("data*" IN BOOLEAN MODE) * 100 +FROM t1 WHERE MATCH(title, text) AGAINST ("data*" IN BOOLEAN MODE) * 100; +# Run query returning null record +SELECT * FROM t1 WHERE title IS NULL AND text IS NULL; + +# More testing of index only access by non-FTS index + +CREATE TABLE t2 SELECT FTS_DOC_ID as doc_id, title, text FROM t1; +ALTER TABLE t2 ADD PRIMARY KEY (doc_id); +ALTER TABLE t2 ADD FULLTEXT KEY ft_idx (title,text); + +-- disable_result_log +ANALYZE TABLE t2; +-- enable_result_log + +# No index access +EXPLAIN SELECT DOC_ID FROM t2 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) * 100; +SELECT DOC_ID FROM t2 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) * 100; +# Index access +EXPLAIN SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) * 100; +SELECT FTS_DOC_ID FROM t1 WHERE MATCH(title, text) AGAINST ('+database' IN BOOLEAN MODE) * 100; + +DROP TABLE t1, t2; + +--echo "Check hints with uft8 charset for 2 cases" +set names utf8; +EVAL CREATE TABLE t1 ( + FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + text TEXT + ) CHARACTER SET = utf8, ENGINE=InnoDB; + +INSERT INTO t1 (title, text) VALUES +('Я могу еÑть Ñтекло', 'оно мне не вредит'), +('Мога да Ñм Ñтъкло', 'то не ми вреди'), +('ΜποÏá¿¶ νὰ φάω σπασμένα' ,'γυαλιὰ χωÏá½¶Ï‚ νὰ πάθω τίποτα'), +('PříliÅ¡ žluÅ¥ouÄký kůň', 'úpÄ›l Äábelské kódy'), +('Sævör grét', 'áðan því úlpan var ónýt'), +('ã†ã‚ã®ãŠãã‚„ã¾','ã‘ãµã“ãˆã¦'), +('ã„ã‚ã¯ã«ã»ã¸ã©ã€€ã¡ã‚Šã¬ã‚‹','ã‚ã•ãゆã‚ã¿ã˜ã€€ã‚‘ã²ã‚‚ã›ãš'); +CREATE FULLTEXT INDEX idx on t1 (title, text); + +--echo # No ranking + +EXPLAIN +SELECT count(*) FROM t1 WHERE MATCH (title, text) AGAINST ('вредит' IN NATURAL LANGUAGE MODE); +SELECT count(*) FROM t1 WHERE MATCH (title, text) AGAINST ('вредит' IN NATURAL LANGUAGE MODE); + +EXPLAIN +SELECT * FROM t1 WHERE MATCH(title, text) AGAINST ("оно" WITH QUERY EXPANSION); +SELECT * FROM t1 WHERE MATCH(title, text) AGAINST ("оно" WITH QUERY EXPANSION); +--echo # No sorting by rank +EXPLAIN SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+(Мога τίποτα)' IN BOOLEAN MODE); +SELECT FTS_DOC_ID FROM t1 +WHERE MATCH(title, text) AGAINST ('+(Мога τίποτα)' IN BOOLEAN MODE); +DROP TABLE t1; + + +--echo # +--echo # Bug #18924341 CRASH IN TEST_IF_SKIP_SORT_ORDER, GROUP BY MATCH AGAINST DESC +--echo # + +CREATE TABLE t1 (f1 CHAR(1), FULLTEXT KEY (f1)); +SELECT 1 FROM t1 NATURAL JOIN t1 a GROUP BY MATCH(t1.f1) AGAINST ("1") DESC; +DROP TABLE t1; + + +--echo # +--echo # Bug#20261601 ASSERTION FAILED: !FIRST_QEP_TAB->TABLE()->NO_KEYREAD +--echo # + +CREATE TABLE t1(a INT PRIMARY KEY); +INSERT INTO t1 VALUES(1),(2); +--error ER_FT_MATCHING_KEY_NOT_FOUND +SELECT (SELECT MATCH(`a`)AGAINST('1') FROM t1) FROM t1; +SELECT 1, a IN (SELECT a FROM t1) FROM t1; +DROP TABLE t1; + +--echo # +--echo # Bug#20442572 ASSERTION `!FIRST_QEP_TAB->TABLE()->NO_KEYREAD' FAILED. +--echo # Bug#75688 Assertion `!first_qep_tab->table()->no_keyread' failed. +--echo # + +CREATE TABLE t1(a INT,b POINT NOT NULL,KEY(a)); + +HANDLER t1 OPEN; +#--error ER_FT_MATCHING_KEY_NOT_FOUND +select * from t1 where MATCH a,b AGAINST('"Now sUPPort"' IN BOOLEAN MODE); +prepare stmt1 from "truncate t1"; +SELECT a IN(SELECT a FROM t1)FROM t1; + +deallocate prepare stmt1; +DROP TABLE t1; + +--echo # +--echo # Bug #20685427 INVALID WRITE OF FREED MEMORY IN ITEM_FUNC_MATCH::CLEANUP +--echo # + +CREATE TABLE t1(a TEXT CHARSET LATIN1, FULLTEXT KEY(a)) ENGINE=INNODB; +--error ER_FT_MATCHING_KEY_NOT_FOUND +SELECT MATCH(a) AGAINST ('') FROM (SELECT a FROM t1 LIMIT 1) q; +DROP TABLE t1; + +--echo # +--echo # Bug#21140067 EXPLAIN .. MATCH AGAINST: ASSERTION FAILED: TO <= END +--echo # + +CREATE TABLE t1(f1 CHAR(1) CHARSET latin1, FULLTEXT(f1)) ENGINE=INNODB; +EXPLAIN SELECT 1 FROM t1 WHERE 1.238585e+308 <= MATCH(f1) AGAINST ('1' IN BOOLEAN MODE); + +EXPLAIN FORMAT = JSON SELECT 1 FROM t1 WHERE 1.238585e+308 <= MATCH(f1) AGAINST ('1' IN BOOLEAN MODE); + +DROP TABLE t1; + +--echo # +--echo # Bug#21140088 MATCH AGAINST: ASSERTION FAILED: !TABLE || (!TABLE->READ_SET || BITMAP_IS_SET +--echo # + +SET sql_mode=''; +CREATE TABLE t1(a INT) ENGINE=INNODB; +CREATE TABLE t2(b TEXT CHARSET LATIN1, FULLTEXT(b), PRIMARY KEY(b(10))) ENGINE=INNODB; +INSERT INTO t2 VALUES ('a'),('b'); +--error ER_WRONG_ARGUMENTS +SELECT NOT EXISTS (SELECT MATCH(b) AGAINST ('1') FROM t1) FROM t2 GROUP BY "a"; +DROP TABLE t1, t2; + +CREATE TABLE t1(a INT) ENGINE=MyISAM; +CREATE TABLE t2(b TEXT CHARSET LATIN1, FULLTEXT(b), PRIMARY KEY(b(10))) ENGINE=MyISAM; +INSERT INTO t2 VALUES ('a'),('b'); +#--error ER_WRONG_ARGUMENTS +SELECT NOT EXISTS (SELECT MATCH(b) AGAINST ('1' in BOOLEAN MODE) FROM t1) FROM t2 GROUP BY "a"; +DROP TABLE t1, t2; + +SET sql_mode=default; + +--echo # +--echo # Bug#21140039 ASSERTION FAILED: !FIRST_QEP_TAB->TABLE()->NO_KEYREAD MATCH AGAINST..... +--echo # + +CREATE TABLE t1 +( + a INT, + b INT, + c CHAR(1) CHARSET latin1, + PRIMARY KEY (b,a), + FULLTEXT KEY (c) +) ENGINE=INNODB; +SELECT "a" NOT IN(SELECT b FROM t1 WHERE MATCH(c) AGAINST ('a' IN BOOLEAN MODE)); +DROP TABLE t1; + +--echo # +--echo # Bug#21300774 ASSERT `!INIT_FTFUNCS(THD, SELECT_LEX)` IN JOIN::RESET AT SQL/SQL_SELECT.CC:874 +--echo # + +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +CREATE TABLE t2 (ft TEXT, FULLTEXT KEY ft(ft)); +INSERT INTO t2 VALUES ('abc'); +INSERT INTO t2 VALUES ('def'); + +--error ER_SUBQUERY_NO_1_ROW +UPDATE t1 SET f1 = +(SELECT t1.f1 FROM t2 WHERE NOT TRUE AND + MATCH (ft) AGAINST ((SELECT 'xyz' FROM t2))); + +DROP TABLE t1, t2; + +--echo # +--echo # Bug#22679209: FULL-TEXT QUERIES WITH ADDITIONAL SECONDARY INDEX +--echo # GIVES NULL OR ZERO ROWS +--echo # + +CREATE TABLE t1 ( +f1 INTEGER, +title varchar(255), +body mediumtext, +KEY f1 (f1), +FULLTEXT KEY title (title), +FULLTEXT KEY body (body) +) ENGINE=InnoDB; + +INSERT INTO t1 VALUES +(1, 'Insert into table', 'insert into table select from'), +(1, 'Delete from table', 'insert into table select from'), +(1, 'Update', 'perform update'), +(2, 'Insert into table', 'insert into table select from'), +( 2, 'Delete from table', 'some body text here'), +( 2, 'Update', 'perform update'), +( 3, 'Insert into table', 'insert into table select from'), +( 3, 'Delete from table', 'some body text here'); + +SELECT f1 FROM t1 WHERE f1=1 AND +(MATCH (title) AGAINST ('table' IN BOOLEAN MODE) OR +MATCH (body) AGAINST ('table' IN BOOLEAN MODE)); + +DROP TABLE t1; + +--echo # End of test for Bug#22679209 diff --git a/mysql-test/suite/innodb_fts/t/phrase.opt b/mysql-test/suite/innodb_fts/t/phrase.opt new file mode 100644 index 00000000000..7724f97647f --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/phrase.opt @@ -0,0 +1,2 @@ +--innodb-ft-index-cache +--innodb-ft-index-table diff --git a/mysql-test/suite/innodb_fts/t/phrase.test b/mysql-test/suite/innodb_fts/t/phrase.test new file mode 100644 index 00000000000..fb0d29f369a --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/phrase.test @@ -0,0 +1,39 @@ +-- source include/have_innodb.inc + +# +# BUG#20465273 - FULLTEXT SEARCH BEHAVIOUR WITH MYISAM VS. INNODB (WRONG RESULT WITH INNODB) +# + +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) +) ENGINE=InnoDB; + +INSERT INTO articles (title,body) VALUES + (NULL, 'mysql good database'), + (NULL, ' mysql good database'), + ('', 'mysql good database'), + ('', ' mysql good database'), + (' ', 'mysql good database'), + ('mysql', 'good database'), + ('mysql ', 'good database'), + ('mysql', ' good database'), + ('mysql good database', ''), + ('mysql good database', NULL); + + +SET GLOBAL innodb_ft_aux_table="test/articles"; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +SET GLOBAL innodb_ft_aux_table=default; + +SELECT * FROM articles; + +SELECT * FROM articles WHERE MATCH(title, body) + AGAINST('"mysql good database"' IN BOOLEAN MODE); + +SELECT * FROM articles WHERE MATCH(title, body) + AGAINST('("mysql good database")' IN BOOLEAN MODE); + +DROP TABLE articles; diff --git a/mysql-test/suite/innodb_fts/t/result_cache_limit.test b/mysql-test/suite/innodb_fts/t/result_cache_limit.test new file mode 100644 index 00000000000..b19907a5052 --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/result_cache_limit.test @@ -0,0 +1,52 @@ +# This is a basic test for innodb fts result cache limit. + +-- source include/have_innodb.inc + +# Must have debug code to use SET SESSION debug +--source include/have_debug.inc + +# Create FTS table +CREATE TABLE t1 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + a VARCHAR(200), + b TEXT + ) ENGINE= InnoDB; + +# Create the FTS index again +CREATE FULLTEXT INDEX idx on t1 (a,b); + +# Insert rows +INSERT INTO t1 (a,b) VALUES + ('MySQL from Tutorial','DBMS stands for DataBase ...') , + ('when To Use MySQL Well','After that you went through a ...'), + ('where will Optimizing MySQL','what In this tutorial we will show ...'), + ('MySQL from Tutorial','DBMS stands for DataBase ...') , + ('when To Use MySQL Well','After that you went through a ...'), + ('where will Optimizing MySQL','what In this tutorial we will show ...'), + ('MySQL from Tutorial','DBMS stands for DataBase ...') , + ('when To Use MySQL Well','After that you went through a ...'), + ('where will Optimizing MySQL','what In this tutorial we will show ...'); + +SET @save_limit=@@GLOBAL.innodb_ft_result_cache_limit; +SET @save_dbug=@@debug_dbug; +SET debug_dbug="+d,fts_instrument_result_cache_limit"; + +# Simple term search +SELECT COUNT(*) FROM t1 WHERE MATCH (a,b) AGAINST ('mysql' IN BOOLEAN MODE); + +# Query expansion +--error 128 +SELECT COUNT(*) FROM t1 WHERE MATCH (a,b) AGAINST ('mysql' WITH QUERY EXPANSION); + +# Simple phrase search +--error 128 +SELECT COUNT(*) FROM t1 WHERE MATCH (a,b) AGAINST ('"mysql database"' IN BOOLEAN MODE); + +# Simple proximity search +--error 128 +SELECT COUNT(*) FROM t1 WHERE MATCH (a,b) AGAINST ('"mysql database" @ 5' IN BOOLEAN MODE); + +SET debug_dbug=@save_dbug; + +DROP TABLE t1; +SET GLOBAL innodb_ft_result_cache_limit=@save_limit; diff --git a/mysql-test/suite/innodb_fts/t/savepoint.test b/mysql-test/suite/innodb_fts/t/savepoint.test new file mode 100644 index 00000000000..09ccb383bb9 --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/savepoint.test @@ -0,0 +1,475 @@ +# This is the basic function tests for innodb FTS savepoint + +-- source include/have_innodb.inc + + +CREATE TABLE articles ( + id INT UNSIGNED NOT NULL PRIMARY KEY, + title VARCHAR(200), + FULLTEXT (title) + ) ENGINE= InnoDB; + +# Test Part 1: ROLLBACK TO SAVEPOINT +# Test rollback to savepoint 1(S1,RB1) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +ROLLBACK TO SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +COMMIT; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test rollback to savepoint 2(S1,RB1,S2,RB2) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +ROLLBACK TO SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +ROLLBACK TO SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(6, 'mysql'); + +COMMIT; + +INSERT INTO articles(id, title) VALUES(7, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test rollback to savepoint 3(S1,S2,RB1) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +ROLLBACK TO SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +COMMIT; + +INSERT INTO articles(id, title) VALUES(6, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test rollback to savepoint 4(S1,S2,RB2,RB1) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +ROLLBACK TO SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +ROLLBACK TO SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(6, 'mysql'); + +COMMIT; + +INSERT INTO articles(id, title) VALUES(7, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test Part 2: RELEASE SAVEPOINT +# Test release savepoint 1(S1,RL1) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +RELEASE SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +COMMIT; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test release savepoint 2(S1,RL1,S2,RL2) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +RELEASE SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +RELEASE SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(6, 'mysql'); + +COMMIT; + +INSERT INTO articles(id, title) VALUES(7, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test release savepoint 3(S1,S2,RL1) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +RELEASE SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +COMMIT; + +INSERT INTO articles(id, title) VALUES(6, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test release savepoint 4(S1,S2,RL2,RL1) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +RELEASE SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +RELEASE SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(6, 'mysql'); + +COMMIT; + +INSERT INTO articles(id, title) VALUES(7, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test Part 3: RELEASE & ROLLBACK TO SAVEPOINT +# Test release & rollback to savepoint 1(S1,RB1,S2,RL2) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +ROLLBACK TO SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +RELEASE SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(6, 'mysql'); + +COMMIT; + +INSERT INTO articles(id, title) VALUES(7, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test release & rollback to savepoint 2(S1,RL1,S2,RB2) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +RELEASE SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +ROLLBACK TO SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(6, 'mysql'); + +COMMIT; + +INSERT INTO articles(id, title) VALUES(7, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test release & rollback to savepoint 3(S1,S2,RL2,RB1) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +RELEASE SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +ROLLBACK TO SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(6, 'mysql'); + +COMMIT; + +INSERT INTO articles(id, title) VALUES(7, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test release & rollback to savepoint 4(S1,S2,RB2,RL1) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +ROLLBACK TO SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +RELEASE SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(6, 'mysql'); + +COMMIT; + +INSERT INTO articles(id, title) VALUES(7, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test Part 4: ROLLBACK & SAVEPOINT +# Test rollback 1 +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +ROLLBACK; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test rollback 2(S1) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +ROLLBACK; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test rollback 3(S1,RL1) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +RELEASE SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +ROLLBACK; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test rollback 4(S1,RB1) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +ROLLBACK TO SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +ROLLBACK; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +# Test rollback 5(S1,S2,RB2,RL1) +TRUNCATE TABLE articles; + +INSERT INTO articles(id, title) VALUES(1, 'mysql'); + +BEGIN; + +INSERT INTO articles(id, title) VALUES(2, 'mysql'); + +SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(3, 'mysql'); + +SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(4, 'mysql'); + +ROLLBACK TO SAVEPOINT sp2; + +INSERT INTO articles(id, title) VALUES(5, 'mysql'); + +RELEASE SAVEPOINT sp1; + +INSERT INTO articles(id, title) VALUES(6, 'mysql'); + +ROLLBACK; + +INSERT INTO articles(id, title) VALUES(7, 'mysql'); + +SELECT * FROM articles WHERE MATCH(title) AGAINST('mysql'); + +DROP TABLE articles; diff --git a/mysql-test/suite/innodb_fts/t/subexpr.test b/mysql-test/suite/innodb_fts/t/subexpr.test new file mode 100644 index 00000000000..632940661b5 --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/subexpr.test @@ -0,0 +1,58 @@ +--source include/have_innodb.inc + +--echo # +--echo # Bug #20028323 INNODB FULLTEXT BOOLEAN SEARCH INCORRECTLY HANDLES +--echo # PARENTHESES +--echo # + +CREATE TABLE t1 ( + f1 INT NOT NULL AUTO_INCREMENT, + f2 TEXT NOT NULL, + PRIMARY KEY (f1), + FULLTEXT (f2) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO t1 (f2) VALUES +('Pumpkin soup with cheese bread'), +('Yellow chicken curry'), +('Fresh green vegetables with garlic'); + +SELECT * FROM t1 WHERE MATCH(f2) AGAINST('+pumpkin' IN BOOLEAN MODE); +SELECT * FROM t1 WHERE MATCH(f2) AGAINST('+cheese' IN BOOLEAN MODE); +SELECT * FROM t1 WHERE MATCH(f2) AGAINST('+(pumpkin cheese)' IN BOOLEAN MODE); +SELECT * FROM t1 WHERE MATCH(f2) + AGAINST('+pumpkin +(souffle)' IN BOOLEAN MODE); +SELECT * FROM t1 WHERE MATCH(f2) + AGAINST('+pumpkin +(souffle tart)' IN BOOLEAN MODE); +SELECT * FROM t1 WHERE MATCH(f2) + AGAINST('+pumpkin +(>souffle souffle Date: Wed, 8 Nov 2023 12:00:29 +0100 Subject: [PATCH 211/477] MDEV-28836 fix crashing PFS unit tests on Windows. In stub_pfs_global, use aligned_free() for pfs_free(), to match aligned_malloc() in pfs_malloc() --- storage/perfschema/unittest/stub_pfs_global.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/perfschema/unittest/stub_pfs_global.h b/storage/perfschema/unittest/stub_pfs_global.h index 4b792f9bfef..e6876dccfe6 100644 --- a/storage/perfschema/unittest/stub_pfs_global.h +++ b/storage/perfschema/unittest/stub_pfs_global.h @@ -58,7 +58,7 @@ void *pfs_malloc(PFS_builtin_memory_class *klass, size_t size, myf) void pfs_free(PFS_builtin_memory_class *, size_t, void *ptr) { if (ptr != NULL) - free(ptr); + aligned_free(ptr); } void *pfs_malloc_array(PFS_builtin_memory_class *klass, size_t n, size_t size, myf flags) From 2b6d241ee4b46d0d444d9758e3a9134eb26a1ca2 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 4 Apr 2022 14:50:21 +0400 Subject: [PATCH 212/477] MDEV-27744 LPAD in vcol created in ORACLE mode makes table corrupted in non-ORACLE The crash happened with an indexed virtual column whose value is evaluated using a function that has a different meaning in sql_mode='' vs sql_mode=ORACLE: - DECODE() - LTRIM() - RTRIM() - LPAD() - RPAD() - REPLACE() - SUBSTR() For example: CREATE TABLE t1 ( b VARCHAR(1), g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL, KEY g(g) ); So far we had replacement XXX_ORACLE() functions for all mentioned function, e.g. SUBSTR_ORACLE() for SUBSTR(). So it was possible to correctly re-parse SUBSTR_ORACLE() even in sql_mode=''. But it was not possible to re-parse the MariaDB version of SUBSTR() after switching to sql_mode=ORACLE. It was erroneously mis-interpreted as SUBSTR_ORACLE(). As a result, this combination worked fine: SET sql_mode=ORACLE; CREATE TABLE t1 ... g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL, ...; INSERT ... FLUSH TABLES; SET sql_mode=''; INSERT ... But the other way around it crashed: SET sql_mode=''; CREATE TABLE t1 ... g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL, ...; INSERT ... FLUSH TABLES; SET sql_mode=ORACLE; INSERT ... At CREATE time, SUBSTR was instantiated as Item_func_substr and printed in the FRM file as substr(). At re-open time with sql_mode=ORACLE, "substr()" was erroneously instantiated as Item_func_substr_oracle. Fix: The fix proposes a symmetric solution. It provides a way to re-parse reliably all sql_mode dependent functions to their original CREATE TABLE time meaning, no matter what the open-time sql_mode is. We take advantage of the same idea we previously used to resolve sql_mode dependent data types. Now all sql_mode dependent functions are printed by SHOW using a schema qualifier when the current sql_mode differs from the function sql_mode: SET sql_mode=''; CREATE TABLE t1 ... SUBSTR(a,b,c) ..; SET sql_mode=ORACLE; SHOW CREATE TABLE t1; -> mariadb_schema.substr(a,b,c) SET sql_mode=ORACLE; CREATE TABLE t2 ... SUBSTR(a,b,c) ..; SET sql_mode=''; SHOW CREATE TABLE t1; -> oracle_schema.substr(a,b,c) Old replacement names like substr_oracle() are still understood for backward compatibility and used in FRM files (for downgrade compatibility), but they are not printed by SHOW any more. --- include/m_ctype.h | 3 +- mysql-test/main/keywords.result | 16 +- .../suite/compat/oracle/r/func_concat.result | 38 +- .../suite/compat/oracle/r/func_decode.result | 12 +- .../suite/compat/oracle/r/func_pad.result | 4 +- .../compat/oracle/r/func_qualified.result | 2468 +++++++++++++++++ .../suite/compat/oracle/r/func_replace.result | 4 +- .../suite/compat/oracle/r/func_substr.result | 4 +- .../suite/compat/oracle/r/func_trim.result | 6 +- .../r/mysqldump_restore_func_qualified.result | 112 + mysql-test/suite/compat/oracle/r/ps.result | 4 +- .../compat/oracle/r/sp-cursor-rowtype.result | 2 +- .../suite/compat/oracle/r/vcol_innodb.result | 54 + .../suite/compat/oracle/t/func_qualified.test | 247 ++ .../t/mysqldump_restore_func_qualified.test | 50 + .../suite/compat/oracle/t/vcol_innodb.test | 47 + sql/item.h | 12 +- sql/item_cmpfunc.cc | 8 +- sql/item_cmpfunc.h | 3 +- sql/item_create.cc | 48 +- sql/item_create.h | 7 + sql/item_func.cc | 17 +- sql/item_func.h | 40 +- sql/item_strfunc.cc | 24 +- sql/item_strfunc.h | 128 +- sql/mysqld.h | 4 + sql/sql_lex.cc | 277 +- sql/sql_lex.h | 48 +- sql/sql_schema.cc | 27 + sql/sql_schema.h | 22 + sql/sql_view.cc | 3 +- sql/sql_yacc.yy | 73 +- sql/sql_yacc_ora.yy | 61 +- sql/structs.h | 7 +- 34 files changed, 3754 insertions(+), 126 deletions(-) create mode 100644 mysql-test/suite/compat/oracle/r/func_qualified.result create mode 100644 mysql-test/suite/compat/oracle/r/mysqldump_restore_func_qualified.result create mode 100644 mysql-test/suite/compat/oracle/r/vcol_innodb.result create mode 100644 mysql-test/suite/compat/oracle/t/func_qualified.test create mode 100644 mysql-test/suite/compat/oracle/t/mysqldump_restore_func_qualified.test create mode 100644 mysql-test/suite/compat/oracle/t/vcol_innodb.test diff --git a/include/m_ctype.h b/include/m_ctype.h index 96eea74d5ba..7cd8bb75aab 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -324,7 +324,8 @@ enum my_lex_states MY_LEX_IDENT_OR_KEYWORD, MY_LEX_IDENT_OR_HEX, MY_LEX_IDENT_OR_BIN, MY_LEX_IDENT_OR_NCHAR, MY_LEX_STRING_OR_DELIMITER, MY_LEX_MINUS_OR_COMMENT, MY_LEX_PLACEHOLDER, - MY_LEX_COMMA + MY_LEX_COMMA, + MY_LEX_IDENT_OR_QUALIFIED_SPECIAL_FUNC }; struct charset_info_st; diff --git a/mysql-test/main/keywords.result b/mysql-test/main/keywords.result index 8db364ac156..c0b33670890 100644 --- a/mysql-test/main/keywords.result +++ b/mysql-test/main/keywords.result @@ -500,21 +500,21 @@ SELECT @@global.rpad(); -- Unknown system variable 'rpad' -------- SELECT @@global.adddate(); -- Unknown system variable 'adddate' -------- -SELECT @@global.substr(); -- Unknown system variable 'substr' +SELECT @@global.substr(); -- ..syntax.. near 'substr()' at line 1 -------- -SELECT @@global.substring(); -- Unknown system variable 'substring' +SELECT @@global.substring(); -- ..syntax.. near 'substring()' at line 1 -------- SELECT @@global.trim_oracle(); -- Unknown system variable 'trim_oracle' -------- SELECT @@global.ascii(); -- Unknown system variable 'ascii' -------- -SELECT @@global.replace(); -- Unknown system variable 'replace' +SELECT @@global.replace(); -- ..syntax.. near 'replace()' at line 1 -------- SELECT @@global.weight_string(); -- Unknown system variable 'weight_string' -------- SELECT @@global.char(); -- Unknown system variable 'char' -------- -SELECT @@global.trim(); -- Unknown system variable 'trim' +SELECT @@global.trim(); -- ..syntax.. near 'trim()' at line 1 -------- SELECT @@global.year(); -- Unknown system variable 'year' -------- @@ -732,21 +732,21 @@ CREATE FUNCTION test.rpad() RETURNS OOPS; -- ..syntax.. near 'OOPS' at line 1 -------- CREATE FUNCTION test.adddate() RETURNS OOPS; -- ..syntax.. near 'OOPS' at line 1 -------- -CREATE FUNCTION test.substr() RETURNS OOPS; -- ..syntax.. near 'OOPS' at line 1 +CREATE FUNCTION test.substr() RETURNS OOPS; -- ..syntax.. near 'substr() RETURNS OOPS' -------- -CREATE FUNCTION test.substring() RETURNS OOPS; -- ..syntax.. near 'OOPS' at line 1 +CREATE FUNCTION test.substring() RETURNS OOPS; -- ..syntax.. near 'substring() RETURNS OOP -------- CREATE FUNCTION test.trim_oracle() RETURNS OOPS; -- ..syntax.. near 'OOPS' at line 1 -------- CREATE FUNCTION test.ascii() RETURNS OOPS; -- ..syntax.. near 'OOPS' at line 1 -------- -CREATE FUNCTION test.replace() RETURNS OOPS; -- ..syntax.. near 'OOPS' at line 1 +CREATE FUNCTION test.replace() RETURNS OOPS; -- ..syntax.. near 'replace() RETURNS OOPS' -------- CREATE FUNCTION test.weight_string() RETURNS OOPS; -- ..syntax.. near 'OOPS' at line 1 -------- CREATE FUNCTION test.char() RETURNS OOPS; -- ..syntax.. near 'OOPS' at line 1 -------- -CREATE FUNCTION test.trim() RETURNS OOPS; -- ..syntax.. near 'OOPS' at line 1 +CREATE FUNCTION test.trim() RETURNS OOPS; -- ..syntax.. near 'trim() RETURNS OOPS' at -------- CREATE FUNCTION test.year() RETURNS OOPS; -- ..syntax.. near 'OOPS' at line 1 -------- diff --git a/mysql-test/suite/compat/oracle/r/func_concat.result b/mysql-test/suite/compat/oracle/r/func_concat.result index 392d579707a..17ca4be078a 100644 --- a/mysql-test/suite/compat/oracle/r/func_concat.result +++ b/mysql-test/suite/compat/oracle/r/func_concat.result @@ -3,12 +3,12 @@ EXPLAIN EXTENDED SELECT 'a'||'b'||'c'; 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 concat_operator_oracle(concat_operator_oracle('a','b'),'c') AS "'a'||'b'||'c'" +Note 1003 select concat(concat('a','b'),'c') AS "'a'||'b'||'c'" EXPLAIN EXTENDED SELECT CONCAT('a'||'b'||'c'); 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 concat_operator_oracle(concat_operator_oracle(concat_operator_oracle('a','b'),'c')) AS "CONCAT('a'||'b'||'c')" +Note 1003 select concat(concat(concat('a','b'),'c')) AS "CONCAT('a'||'b'||'c')" SELECT '' || ''; '' || '' @@ -211,14 +211,14 @@ SET sql_mode=ORACLE; CREATE VIEW v1 AS SELECT 'foo'||NULL||'bar' AS test; SHOW CREATE VIEW v1; View Create View character_set_client collation_connection -v1 CREATE VIEW "v1" AS select concat_operator_oracle(concat_operator_oracle('foo',NULL),'bar') AS "test" latin1 latin1_swedish_ci +v1 CREATE VIEW "v1" AS select concat(concat('foo',NULL),'bar') AS "test" latin1 latin1_swedish_ci SELECT * FROM v1; test foobar SET sql_mode=DEFAULT; SHOW CREATE VIEW v1; View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select concat_operator_oracle(concat_operator_oracle('foo',NULL),'bar') AS `test` latin1 latin1_swedish_ci +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select oracle_schema.concat(oracle_schema.concat('foo',NULL),'bar') AS `test` latin1 latin1_swedish_ci SELECT * FROM v1; test foobar @@ -234,7 +234,7 @@ NULL SET sql_mode=ORACLE; SHOW CREATE VIEW v1; View Create View character_set_client collation_connection -v1 CREATE VIEW "v1" AS select concat('foo',NULL,'bar') AS "test" latin1 latin1_swedish_ci +v1 CREATE VIEW "v1" AS select mariadb_schema.concat('foo',NULL,'bar') AS "test" latin1 latin1_swedish_ci SELECT * FROM v1; test NULL @@ -268,12 +268,12 @@ EXPLAIN EXTENDED SELECT -1<<1||1 AS a FROM DUAL; 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 -1 << concat_operator_oracle(1,1) AS "a" +Note 1003 select -1 << concat(1,1) AS "a" EXPLAIN EXTENDED SELECT -1||0<<1 AS a FROM DUAL; 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 concat_operator_oracle(-1,0) << 1 AS "a" +Note 1003 select concat(-1,0) << 1 AS "a" SELECT -1+1||1 AS a FROM DUAL; a 01 @@ -284,12 +284,12 @@ EXPLAIN EXTENDED SELECT -1+1||1 AS a FROM DUAL; 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 concat_operator_oracle(-1 + 1,1) AS "a" +Note 1003 select concat(-1 + 1,1) AS "a" EXPLAIN EXTENDED SELECT -1||0+1 AS a FROM DUAL; 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 concat_operator_oracle(-1,0) + 1 AS "a" +Note 1003 select concat(-1,0) + 1 AS "a" SELECT 1*1||-1 AS a FROM DUAL; a 1-1 @@ -300,12 +300,12 @@ EXPLAIN EXTENDED SELECT 1*1||-1 AS a FROM DUAL; 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 concat_operator_oracle(1 * 1,-1) AS "a" +Note 1003 select concat(1 * 1,-1) AS "a" EXPLAIN EXTENDED SELECT 1||1*-1 AS a FROM DUAL; 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 concat_operator_oracle(1,1 * -1) AS "a" +Note 1003 select concat(1,1 * -1) AS "a" SELECT -1^1||1 AS a FROM DUAL; a 184467440737095516141 @@ -316,12 +316,12 @@ EXPLAIN EXTENDED SELECT -1^1||1 AS a FROM DUAL; 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 concat_operator_oracle(-1 ^ 1,1) AS "a" +Note 1003 select concat(-1 ^ 1,1) AS "a" EXPLAIN EXTENDED SELECT -1||0^1 AS a FROM DUAL; 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 concat_operator_oracle(-1,0 ^ 1) AS "a" +Note 1003 select concat(-1,0 ^ 1) AS "a" # # MDEV-17359 Concatenation operator || in like expression failed in sql_mode=ORACLE # @@ -332,7 +332,7 @@ EXPLAIN EXTENDED SELECT 'abc' LIKE 'a'||'%'; 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 'abc' like concat_operator_oracle('a','%') AS "'abc' LIKE 'a'||'%'" +Note 1003 select 'abc' like concat('a','%') AS "'abc' LIKE 'a'||'%'" SELECT 'x' FROM DUAL WHERE 11 LIKE 1||1; x x @@ -353,7 +353,7 @@ EXPLAIN EXTENDED SELECT c1 FROM t1 WHERE c1 LIKE '%'||'b' ORDER BY ord; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort Warnings: -Note 1003 select "test"."t1"."c1" AS "c1" from "test"."t1" where "test"."t1"."c1" like (concat_operator_oracle('%','b')) order by "test"."t1"."ord" +Note 1003 select "test"."t1"."c1" AS "c1" from "test"."t1" where "test"."t1"."c1" like (concat('%','b')) order by "test"."t1"."ord" SELECT c1 FROM t1 WHERE c1 LIKE c2||'%'||'c' ORDER BY ord; c1 abc @@ -361,7 +361,7 @@ EXPLAIN EXTENDED SELECT c1 FROM t1 WHERE c1 LIKE c2||'%'||'c' ORDER BY ord; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort Warnings: -Note 1003 select "test"."t1"."c1" AS "c1" from "test"."t1" where "test"."t1"."c1" like concat_operator_oracle(concat_operator_oracle("test"."t1"."c2",'%'),'c') order by "test"."t1"."ord" +Note 1003 select "test"."t1"."c1" AS "c1" from "test"."t1" where "test"."t1"."c1" like concat(concat("test"."t1"."c2",'%'),'c') order by "test"."t1"."ord" SELECT 'x' FROM t1 WHERE c1||c2 LIKE 'aa%'; x x @@ -369,7 +369,7 @@ EXPLAIN EXTENDED SELECT 'x' FROM t1 WHERE c1||c2 LIKE 'aa%'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: -Note 1003 select 'x' AS "x" from "test"."t1" where concat_operator_oracle("test"."t1"."c1","test"."t1"."c2") like 'aa%' +Note 1003 select 'x' AS "x" from "test"."t1" where concat("test"."t1"."c1","test"."t1"."c2") like 'aa%' SELECT 'x' FROM t1 WHERE c1||c2 LIKE c2||c1; x x @@ -377,7 +377,7 @@ EXPLAIN EXTENDED SELECT 'x' FROM t1 WHERE c1||c2 LIKE c2||c1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: -Note 1003 select 'x' AS "x" from "test"."t1" where concat_operator_oracle("test"."t1"."c1","test"."t1"."c2") like concat_operator_oracle("test"."t1"."c2","test"."t1"."c1") +Note 1003 select 'x' AS "x" from "test"."t1" where concat("test"."t1"."c1","test"."t1"."c2") like concat("test"."t1"."c2","test"."t1"."c1") CREATE VIEW v1 AS SELECT c1, c2, c1 LIKE c2||'_' FROM t1 ORDER BY ord; SELECT * FROM v1; c1 c2 c1 LIKE c2||'_' @@ -388,6 +388,6 @@ EXPLAIN EXTENDED SELECT * FROM v1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using filesort Warnings: -Note 1003 select "test"."t1"."c1" AS "c1","test"."t1"."c2" AS "c2","test"."t1"."c1" like concat_operator_oracle("test"."t1"."c2",'_') AS "c1 LIKE c2||'_'" from "test"."t1" order by "test"."t1"."ord" +Note 1003 select "test"."t1"."c1" AS "c1","test"."t1"."c2" AS "c2","test"."t1"."c1" like concat("test"."t1"."c2",'_') AS "c1 LIKE c2||'_'" from "test"."t1" order by "test"."t1"."ord" DROP VIEW v1; DROP TABLE t1; diff --git a/mysql-test/suite/compat/oracle/r/func_decode.result b/mysql-test/suite/compat/oracle/r/func_decode.result index 2809e971be3..afbba204e1b 100644 --- a/mysql-test/suite/compat/oracle/r/func_decode.result +++ b/mysql-test/suite/compat/oracle/r/func_decode.result @@ -28,7 +28,7 @@ EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11','def'); 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 decode_oracle(12,10,'x10',11,'x11','def') AS "DECODE(12,10,'x10',11,'x11','def')" +Note 1003 select decode(12,10,'x10',11,'x11','def') AS "DECODE(12,10,'x10',11,'x11','def')" CREATE TABLE decode (decode int); DROP TABLE decode; # @@ -46,22 +46,22 @@ EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11'); 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 decode_oracle(12,10,'x10',11,'x11') AS "DECODE(12,10,'x10',11,'x11')" +Note 1003 select decode(12,10,'x10',11,'x11') AS "DECODE(12,10,'x10',11,'x11')" EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11','def'); 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 decode_oracle(12,10,'x10',11,'x11','def') AS "DECODE(12,10,'x10',11,'x11','def')" +Note 1003 select decode(12,10,'x10',11,'x11','def') AS "DECODE(12,10,'x10',11,'x11','def')" EXPLAIN EXTENDED SELECT DECODE_ORACLE(12,10,'x10',11,'x11'); 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 decode_oracle(12,10,'x10',11,'x11') AS "DECODE_ORACLE(12,10,'x10',11,'x11')" +Note 1003 select decode(12,10,'x10',11,'x11') AS "DECODE_ORACLE(12,10,'x10',11,'x11')" EXPLAIN EXTENDED SELECT DECODE_ORACLE(12,10,'x10',11,'x11','def'); 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 decode_oracle(12,10,'x10',11,'x11','def') AS "DECODE_ORACLE(12,10,'x10',11,'x11','def')" +Note 1003 select decode(12,10,'x10',11,'x11','def') AS "DECODE_ORACLE(12,10,'x10',11,'x11','def')" CREATE TABLE t1 (a INT); CREATE VIEW v1 AS SELECT @@ -72,7 +72,7 @@ DECODE_ORACLE(a,1,'x1',NULL,'xNULL','xELSE') AS d4 FROM t1; SHOW CREATE VIEW v1; View Create View character_set_client collation_connection -v1 CREATE VIEW "v1" AS select decode_oracle("t1"."a",1,'x1',NULL,'xNULL') AS "d1",decode_oracle("t1"."a",1,'x1',NULL,'xNULL','xELSE') AS "d2",decode_oracle("t1"."a",1,'x1',NULL,'xNULL') AS "d3",decode_oracle("t1"."a",1,'x1',NULL,'xNULL','xELSE') AS "d4" from "t1" latin1 latin1_swedish_ci +v1 CREATE VIEW "v1" AS select decode("t1"."a",1,'x1',NULL,'xNULL') AS "d1",decode("t1"."a",1,'x1',NULL,'xNULL','xELSE') AS "d2",decode("t1"."a",1,'x1',NULL,'xNULL') AS "d3",decode("t1"."a",1,'x1',NULL,'xNULL','xELSE') AS "d4" from "t1" latin1 latin1_swedish_ci DROP VIEW v1; DROP TABLE t1; SELECT DECODE(TIME'10:20:31','10:20:31','then1','10:20:32','then2','def'); diff --git a/mysql-test/suite/compat/oracle/r/func_pad.result b/mysql-test/suite/compat/oracle/r/func_pad.result index ca7d52cd542..63952959945 100644 --- a/mysql-test/suite/compat/oracle/r/func_pad.result +++ b/mysql-test/suite/compat/oracle/r/func_pad.result @@ -44,11 +44,11 @@ EXPLAIN EXTENDED SELECT RPAD('a',0,'.'), LPAD('a',0,'.'), LPAD(c1,c2,c3), LPAD(c id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 7 100.00 Using filesort Warnings: -Note 1003 select rpad_oracle('a',0,'.') AS "RPAD('a',0,'.')",lpad_oracle('a',0,'.') AS "LPAD('a',0,'.')",lpad_oracle("test"."t1"."c1","test"."t1"."c2","test"."t1"."c3") AS "LPAD(c1,c2,c3)",lpad_oracle("test"."t1"."c1","test"."t1"."c2") AS "LPAD(c1,c2)",rpad_oracle("test"."t1"."c1","test"."t1"."c2","test"."t1"."c3") AS "RPAD(c1,c2,c3)",rpad_oracle("test"."t1"."c1","test"."t1"."c2") AS "RPAD(c1,c2)" from "test"."t1" order by "test"."t1"."ord" +Note 1003 select rpad('a',0,'.') AS "RPAD('a',0,'.')",lpad('a',0,'.') AS "LPAD('a',0,'.')",lpad("test"."t1"."c1","test"."t1"."c2","test"."t1"."c3") AS "LPAD(c1,c2,c3)",lpad("test"."t1"."c1","test"."t1"."c2") AS "LPAD(c1,c2)",rpad("test"."t1"."c1","test"."t1"."c2","test"."t1"."c3") AS "RPAD(c1,c2,c3)",rpad("test"."t1"."c1","test"."t1"."c2") AS "RPAD(c1,c2)" from "test"."t1" order by "test"."t1"."ord" CREATE VIEW v1 AS SELECT RPAD('a',0,'.') AS "C1", LPAD('a',0,'.') AS "C2", LPAD(c1,c2,c3) AS "C3", LPAD(c1,c2) AS "C4", RPAD(c1,c2,c3) AS "C5", RPAD(c1,c2) AS "C6" FROM t1 ORDER BY ord; SHOW CREATE VIEW v1; View Create View character_set_client collation_connection -v1 CREATE VIEW "v1" AS select rpad_oracle('a',0,'.') AS "C1",lpad_oracle('a',0,'.') AS "C2",lpad_oracle("t1"."c1","t1"."c2","t1"."c3") AS "C3",lpad_oracle("t1"."c1","t1"."c2") AS "C4",rpad_oracle("t1"."c1","t1"."c2","t1"."c3") AS "C5",rpad_oracle("t1"."c1","t1"."c2") AS "C6" from "t1" order by "t1"."ord" latin1 latin1_swedish_ci +v1 CREATE VIEW "v1" AS select rpad('a',0,'.') AS "C1",lpad('a',0,'.') AS "C2",lpad("t1"."c1","t1"."c2","t1"."c3") AS "C3",lpad("t1"."c1","t1"."c2") AS "C4",rpad("t1"."c1","t1"."c2","t1"."c3") AS "C5",rpad("t1"."c1","t1"."c2") AS "C6" from "t1" order by "t1"."ord" latin1 latin1_swedish_ci SELECT * FROM v1; C1 C2 C3 C4 C5 C6 NULL NULL NULL a NULL a diff --git a/mysql-test/suite/compat/oracle/r/func_qualified.result b/mysql-test/suite/compat/oracle/r/func_qualified.result new file mode 100644 index 00000000000..f8224b7ce81 --- /dev/null +++ b/mysql-test/suite/compat/oracle/r/func_qualified.result @@ -0,0 +1,2468 @@ +# +# MDEV-27744 LPAD in vcol created in ORACLE mode makes table corrupted in non-ORACLE +# +SET sql_mode=DEFAULT; +SELECT decode_oracle(1); +ERROR 42000: Incorrect parameter count in the call to native function 'decode_oracle' +SELECT DECODE_ORACLE(1); +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE_ORACLE' +SET sql_mode=ORACLE; +SELECT decode_oracle(1); +ERROR 42000: Incorrect parameter count in the call to native function 'decode_oracle' +SELECT DECODE_ORACLE(1); +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE_ORACLE' +SET sql_mode=DEFAULT; +SELECT decode(1); +ERROR 42000: Incorrect parameter count in the call to native function 'decode' +SELECT DECODE(1); +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE' +SET sql_mode=ORACLE; +SELECT decode(1); +ERROR 42000: Incorrect parameter count in the call to native function 'decode' +SELECT DECODE(1); +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE' +SELECT mariadb_schema.decode(1); +ERROR 42000: Incorrect parameter count in the call to native function 'decode' +SELECT mariadb_schema.DECODE(1); +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE' +SELECT mariadb_schema.decode_oracle(1); +ERROR 42000: Incorrect parameter count in the call to native function 'decode_oracle' +SELECT mariadb_schema.DECODE_ORACLE(1); +ERROR 42000: Incorrect parameter count in the call to native function 'DECODE_ORACLE' +SET sql_mode=DEFAULT; +SELECT unknown.TRIM(1); +ERROR 42000: FUNCTION unknown.TRIM does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +SELECT unknown.trim(1); +ERROR 42000: FUNCTION unknown.trim does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +SELECT oracle_schema.TRIM(); +ERROR HY000: Function 'TRIM' is not defined +SELECT oracle_schema.TRIM('a','b'); +ERROR HY000: Function 'TRIM' is not defined +SELECT oracle_schema.TRIM('a','b','c','d'); +ERROR HY000: Function 'TRIM' is not defined +SELECT unknown.SUBSTR('a',1,2); +ERROR 42000: FUNCTION unknown.SUBSTR does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +SELECT unknown.substr('a',1,2); +ERROR 42000: FUNCTION unknown.substr does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +SELECT unknown.SUBSTRING('a',1,2); +ERROR 42000: FUNCTION unknown.SUBSTRING does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +SELECT unknown.substring('a',1,2); +ERROR 42000: FUNCTION unknown.substring does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +SELECT unknown.REPLACE('a','b','c'); +ERROR 42000: FUNCTION unknown.REPLACE does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +SELECT unknown.replace('a','b','c'); +ERROR 42000: FUNCTION unknown.replace does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +SELECT oracle_schema.REPLACE(); +ERROR HY000: Function 'REPLACE' is not defined +SELECT oracle_schema.REPLACE('a'); +ERROR HY000: Function 'REPLACE' is not defined +SELECT oracle_schema.REPLACE('a','b'); +ERROR HY000: Function 'REPLACE' is not defined +SELECT oracle_schema.REPLACE('a','b','c','d'); +ERROR HY000: Function 'REPLACE' is not defined +SET sql_mode=DEFAULT; +CREATE PROCEDURE p1(sqlmode TEXT, qualifier TEXT, expr TEXT) +BEGIN +DECLARE query TEXT DEFAULT 'SELECT $(QUALIFIER)$(EXPR)'; +DECLARE errmsg TEXT DEFAULT NULL; +DECLARE CONTINUE HANDLER FOR 1064, 1128, 1305, 1582, 1630 +BEGIN +GET DIAGNOSTICS CONDITION 1 errmsg = MESSAGE_TEXT; +END; +SET sql_mode=sqlmode; +SET query=REPLACE(query, '$(QUALIFIER)', qualifier); +SET query=REPLACE(query, '$(EXPR)', expr); +SET query= CONCAT('EXPLAIN EXTENDED ', query); +SELECT CONCAT('sql_mode=''',sqlmode,'''', ' ', +'qualifier=''',qualifier,'''') AS `----------`; +SELECT query; +EXECUTE IMMEDIATE query; +IF errmsg IS NOT NULL THEN +SELECT CONCAT('ERROR: ', errmsg) AS errmsg; +ELSE +SHOW WARNINGS; +END IF; +END; +$$ +CREATE PROCEDURE p2(sqlmode TEXT, expr TEXT) +BEGIN +CALL p1(sqlmode, '', expr); +CALL p1(sqlmode, 'unknown_schema.', expr); +CALL p1(sqlmode, 'mariadb_schema.', expr); +CALL p1(sqlmode, 'maxdb_schema.', expr); +CALL p1(sqlmode, 'oracle_schema.', expr); +END; +$$ +CREATE PROCEDURE p3(expr TEXT) +BEGIN +CALL p2('', expr); +CALL p2('ORACLE', expr); +END; +$$ +CALL p3('CONCAT(''a'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT CONCAT('a') +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 +Level Code Message +Note 1003 select concat('a') AS `CONCAT('a')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.CONCAT('a') +errmsg +ERROR: FUNCTION unknown_schema.CONCAT does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.CONCAT('a') +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 +Level Code Message +Note 1003 select concat('a') AS `mariadb_schema.CONCAT('a')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.CONCAT('a') +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 +Level Code Message +Note 1003 select concat('a') AS `maxdb_schema.CONCAT('a')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.CONCAT('a') +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 +Level Code Message +Note 1003 select oracle_schema.concat('a') AS `oracle_schema.CONCAT('a')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT CONCAT('a') +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 +Level Code Message +Note 1003 select concat('a') AS "CONCAT('a')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.CONCAT('a') +errmsg +ERROR: FUNCTION unknown_schema.CONCAT does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.CONCAT('a') +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 +Level Code Message +Note 1003 select mariadb_schema.concat('a') AS "mariadb_schema.CONCAT('a')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.CONCAT('a') +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 +Level Code Message +Note 1003 select mariadb_schema.concat('a') AS "maxdb_schema.CONCAT('a')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.CONCAT('a') +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 +Level Code Message +Note 1003 select concat('a') AS "oracle_schema.CONCAT('a')" +Warnings: +Note 1003 select concat('a') AS "oracle_schema.CONCAT('a')" +CALL p3('DECODE(''1'',''2'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT DECODE('1','2') +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 +Level Code Message +Note 1003 select decode('1','2') AS `DECODE('1','2')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.DECODE('1','2') +errmsg +ERROR: FUNCTION unknown_schema.DECODE does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.DECODE('1','2') +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 +Level Code Message +Note 1003 select decode('1','2') AS `mariadb_schema.DECODE('1','2')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.DECODE('1','2') +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 +Level Code Message +Note 1003 select decode('1','2') AS `maxdb_schema.DECODE('1','2')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.DECODE('1','2') +errmsg +ERROR: Incorrect parameter count in the call to native function 'DECODE' +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT DECODE('1','2') +errmsg +ERROR: Incorrect parameter count in the call to native function 'DECODE' +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.DECODE('1','2') +errmsg +ERROR: FUNCTION unknown_schema.DECODE does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.DECODE('1','2') +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 +Level Code Message +Note 1003 select mariadb_schema.decode('1','2') AS "mariadb_schema.DECODE('1','2')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.DECODE('1','2') +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 +Level Code Message +Note 1003 select mariadb_schema.decode('1','2') AS "maxdb_schema.DECODE('1','2')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.DECODE('1','2') +errmsg +ERROR: Incorrect parameter count in the call to native function 'DECODE' +CALL p3('DECODE(1,1,10)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT DECODE(1,1,10) +errmsg +ERROR: Incorrect parameter count in the call to native function 'DECODE' +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.DECODE(1,1,10) +errmsg +ERROR: FUNCTION unknown_schema.DECODE does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.DECODE(1,1,10) +errmsg +ERROR: Incorrect parameter count in the call to native function 'DECODE' +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.DECODE(1,1,10) +errmsg +ERROR: Incorrect parameter count in the call to native function 'DECODE' +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.DECODE(1,1,10) +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 +Level Code Message +Note 1003 select oracle_schema.decode(1,1,10) AS `oracle_schema.DECODE(1,1,10)` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT DECODE(1,1,10) +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 +Level Code Message +Note 1003 select decode(1,1,10) AS "DECODE(1,1,10)" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.DECODE(1,1,10) +errmsg +ERROR: FUNCTION unknown_schema.DECODE does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.DECODE(1,1,10) +errmsg +ERROR: Incorrect parameter count in the call to native function 'DECODE' +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.DECODE(1,1,10) +errmsg +ERROR: Incorrect parameter count in the call to native function 'DECODE' +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.DECODE(1,1,10) +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 +Level Code Message +Note 1003 select decode(1,1,10) AS "oracle_schema.DECODE(1,1,10)" +Warnings: +Note 1003 select decode(1,1,10) AS "oracle_schema.DECODE(1,1,10)" +CALL p3('LTRIM(''a'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT LTRIM('a') +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 +Level Code Message +Note 1003 select ltrim('a') AS `LTRIM('a')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.LTRIM('a') +errmsg +ERROR: FUNCTION unknown_schema.LTRIM does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.LTRIM('a') +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 +Level Code Message +Note 1003 select ltrim('a') AS `mariadb_schema.LTRIM('a')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.LTRIM('a') +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 +Level Code Message +Note 1003 select ltrim('a') AS `maxdb_schema.LTRIM('a')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.LTRIM('a') +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 +Level Code Message +Note 1003 select oracle_schema.ltrim('a') AS `oracle_schema.LTRIM('a')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT LTRIM('a') +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 +Level Code Message +Note 1003 select ltrim('a') AS "LTRIM('a')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.LTRIM('a') +errmsg +ERROR: FUNCTION unknown_schema.LTRIM does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.LTRIM('a') +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 +Level Code Message +Note 1003 select mariadb_schema.ltrim('a') AS "mariadb_schema.LTRIM('a')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.LTRIM('a') +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 +Level Code Message +Note 1003 select mariadb_schema.ltrim('a') AS "maxdb_schema.LTRIM('a')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.LTRIM('a') +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 +Level Code Message +Note 1003 select ltrim('a') AS "oracle_schema.LTRIM('a')" +Warnings: +Note 1003 select ltrim('a') AS "oracle_schema.LTRIM('a')" +CALL p3('RTRIM(''a'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT RTRIM('a') +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 +Level Code Message +Note 1003 select rtrim('a') AS `RTRIM('a')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.RTRIM('a') +errmsg +ERROR: FUNCTION unknown_schema.RTRIM does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.RTRIM('a') +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 +Level Code Message +Note 1003 select rtrim('a') AS `mariadb_schema.RTRIM('a')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.RTRIM('a') +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 +Level Code Message +Note 1003 select rtrim('a') AS `maxdb_schema.RTRIM('a')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.RTRIM('a') +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 +Level Code Message +Note 1003 select oracle_schema.rtrim('a') AS `oracle_schema.RTRIM('a')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT RTRIM('a') +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 +Level Code Message +Note 1003 select rtrim('a') AS "RTRIM('a')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.RTRIM('a') +errmsg +ERROR: FUNCTION unknown_schema.RTRIM does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.RTRIM('a') +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 +Level Code Message +Note 1003 select mariadb_schema.rtrim('a') AS "mariadb_schema.RTRIM('a')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.RTRIM('a') +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 +Level Code Message +Note 1003 select mariadb_schema.rtrim('a') AS "maxdb_schema.RTRIM('a')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.RTRIM('a') +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 +Level Code Message +Note 1003 select rtrim('a') AS "oracle_schema.RTRIM('a')" +Warnings: +Note 1003 select rtrim('a') AS "oracle_schema.RTRIM('a')" +CALL p3('LPAD(''a'',3)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT LPAD('a',3) +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 +Level Code Message +Note 1003 select lpad('a',3) AS `LPAD('a',3)` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.LPAD('a',3) +errmsg +ERROR: FUNCTION unknown_schema.LPAD does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.LPAD('a',3) +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 +Level Code Message +Note 1003 select lpad('a',3) AS `mariadb_schema.LPAD('a',3)` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.LPAD('a',3) +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 +Level Code Message +Note 1003 select lpad('a',3) AS `maxdb_schema.LPAD('a',3)` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.LPAD('a',3) +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 +Level Code Message +Note 1003 select oracle_schema.lpad('a',3) AS `oracle_schema.LPAD('a',3)` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT LPAD('a',3) +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 +Level Code Message +Note 1003 select lpad('a',3) AS "LPAD('a',3)" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.LPAD('a',3) +errmsg +ERROR: FUNCTION unknown_schema.LPAD does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.LPAD('a',3) +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 +Level Code Message +Note 1003 select mariadb_schema.lpad('a',3) AS "mariadb_schema.LPAD('a',3)" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.LPAD('a',3) +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 +Level Code Message +Note 1003 select mariadb_schema.lpad('a',3) AS "maxdb_schema.LPAD('a',3)" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.LPAD('a',3) +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 +Level Code Message +Note 1003 select lpad('a',3) AS "oracle_schema.LPAD('a',3)" +Warnings: +Note 1003 select lpad('a',3) AS "oracle_schema.LPAD('a',3)" +CALL p3('LPAD(''a'',3, '' '')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT LPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select lpad('a',3,' ') AS `LPAD('a',3, ' ')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.LPAD('a',3, ' ') +errmsg +ERROR: FUNCTION unknown_schema.LPAD does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.LPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select lpad('a',3,' ') AS `mariadb_schema.LPAD('a',3, ' ')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.LPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select lpad('a',3,' ') AS `maxdb_schema.LPAD('a',3, ' ')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.LPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select oracle_schema.lpad('a',3,' ') AS `oracle_schema.LPAD('a',3, ' ')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT LPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select lpad('a',3,' ') AS "LPAD('a',3, ' ')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.LPAD('a',3, ' ') +errmsg +ERROR: FUNCTION unknown_schema.LPAD does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.LPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select mariadb_schema.lpad('a',3,' ') AS "mariadb_schema.LPAD('a',3, ' ')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.LPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select mariadb_schema.lpad('a',3,' ') AS "maxdb_schema.LPAD('a',3, ' ')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.LPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select lpad('a',3,' ') AS "oracle_schema.LPAD('a',3, ' ')" +Warnings: +Note 1003 select lpad('a',3,' ') AS "oracle_schema.LPAD('a',3, ' ')" +CALL p3('RPAD(''a'',3)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT RPAD('a',3) +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 +Level Code Message +Note 1003 select rpad('a',3) AS `RPAD('a',3)` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.RPAD('a',3) +errmsg +ERROR: FUNCTION unknown_schema.RPAD does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.RPAD('a',3) +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 +Level Code Message +Note 1003 select rpad('a',3) AS `mariadb_schema.RPAD('a',3)` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.RPAD('a',3) +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 +Level Code Message +Note 1003 select rpad('a',3) AS `maxdb_schema.RPAD('a',3)` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.RPAD('a',3) +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 +Level Code Message +Note 1003 select oracle_schema.rpad('a',3) AS `oracle_schema.RPAD('a',3)` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT RPAD('a',3) +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 +Level Code Message +Note 1003 select rpad('a',3) AS "RPAD('a',3)" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.RPAD('a',3) +errmsg +ERROR: FUNCTION unknown_schema.RPAD does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.RPAD('a',3) +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 +Level Code Message +Note 1003 select mariadb_schema.rpad('a',3) AS "mariadb_schema.RPAD('a',3)" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.RPAD('a',3) +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 +Level Code Message +Note 1003 select mariadb_schema.rpad('a',3) AS "maxdb_schema.RPAD('a',3)" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.RPAD('a',3) +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 +Level Code Message +Note 1003 select rpad('a',3) AS "oracle_schema.RPAD('a',3)" +Warnings: +Note 1003 select rpad('a',3) AS "oracle_schema.RPAD('a',3)" +CALL p3('RPAD(''a'',3, '' '')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT RPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select rpad('a',3,' ') AS `RPAD('a',3, ' ')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.RPAD('a',3, ' ') +errmsg +ERROR: FUNCTION unknown_schema.RPAD does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.RPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select rpad('a',3,' ') AS `mariadb_schema.RPAD('a',3, ' ')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.RPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select rpad('a',3,' ') AS `maxdb_schema.RPAD('a',3, ' ')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.RPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select oracle_schema.rpad('a',3,' ') AS `oracle_schema.RPAD('a',3, ' ')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT RPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select rpad('a',3,' ') AS "RPAD('a',3, ' ')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.RPAD('a',3, ' ') +errmsg +ERROR: FUNCTION unknown_schema.RPAD does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.RPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select mariadb_schema.rpad('a',3,' ') AS "mariadb_schema.RPAD('a',3, ' ')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.RPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select mariadb_schema.rpad('a',3,' ') AS "maxdb_schema.RPAD('a',3, ' ')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.RPAD('a',3, ' ') +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 +Level Code Message +Note 1003 select rpad('a',3,' ') AS "oracle_schema.RPAD('a',3, ' ')" +Warnings: +Note 1003 select rpad('a',3,' ') AS "oracle_schema.RPAD('a',3, ' ')" +CALL p3('REPLACE()'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT REPLACE() +errmsg +ERROR: 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 +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REPLACE() +errmsg +ERROR: FUNCTION unknown_schema.REPLACE does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REPLACE() +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REPLACE() +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REPLACE() +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT REPLACE() +errmsg +ERROR: 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 +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REPLACE() +errmsg +ERROR: FUNCTION unknown_schema.REPLACE does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REPLACE() +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REPLACE() +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REPLACE() +errmsg +ERROR: Function 'REPLACE' is not defined +CALL p3('REPLACE(''a'',''b'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT REPLACE('a','b') +errmsg +ERROR: 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 +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REPLACE('a','b') +errmsg +ERROR: FUNCTION unknown_schema.REPLACE does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REPLACE('a','b') +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REPLACE('a','b') +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REPLACE('a','b') +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT REPLACE('a','b') +errmsg +ERROR: 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 +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REPLACE('a','b') +errmsg +ERROR: FUNCTION unknown_schema.REPLACE does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REPLACE('a','b') +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REPLACE('a','b') +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REPLACE('a','b') +errmsg +ERROR: Function 'REPLACE' is not defined +CALL p3('REPLACE(''a'',''b'',''c'',''d'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT REPLACE('a','b','c','d') +errmsg +ERROR: 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 ''d')' at line 1 +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REPLACE('a','b','c','d') +errmsg +ERROR: FUNCTION unknown_schema.REPLACE does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REPLACE('a','b','c','d') +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REPLACE('a','b','c','d') +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REPLACE('a','b','c','d') +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT REPLACE('a','b','c','d') +errmsg +ERROR: 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 ''d')' at line 1 +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REPLACE('a','b','c','d') +errmsg +ERROR: FUNCTION unknown_schema.REPLACE does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REPLACE('a','b','c','d') +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REPLACE('a','b','c','d') +errmsg +ERROR: Function 'REPLACE' is not defined +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REPLACE('a','b','c','d') +errmsg +ERROR: Function 'REPLACE' is not defined +CALL p3('REPLACE(''a'',''b'',''c'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT REPLACE('a','b','c') +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 +Level Code Message +Note 1003 select replace('a','b','c') AS `REPLACE('a','b','c')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REPLACE('a','b','c') +errmsg +ERROR: FUNCTION unknown_schema.REPLACE does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REPLACE('a','b','c') +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 +Level Code Message +Note 1003 select replace('a','b','c') AS `mariadb_schema.REPLACE('a','b','c')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REPLACE('a','b','c') +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 +Level Code Message +Note 1003 select replace('a','b','c') AS `maxdb_schema.REPLACE('a','b','c')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REPLACE('a','b','c') +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 +Level Code Message +Note 1003 select oracle_schema.replace('a','b','c') AS `oracle_schema.REPLACE('a','b','c')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT REPLACE('a','b','c') +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 +Level Code Message +Note 1003 select replace('a','b','c') AS "REPLACE('a','b','c')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REPLACE('a','b','c') +errmsg +ERROR: FUNCTION unknown_schema.REPLACE does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REPLACE('a','b','c') +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 +Level Code Message +Note 1003 select mariadb_schema.replace('a','b','c') AS "mariadb_schema.REPLACE('a','b','c')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REPLACE('a','b','c') +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 +Level Code Message +Note 1003 select mariadb_schema.replace('a','b','c') AS "maxdb_schema.REPLACE('a','b','c')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REPLACE('a','b','c') +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 +Level Code Message +Note 1003 select replace('a','b','c') AS "oracle_schema.REPLACE('a','b','c')" +Warnings: +Note 1003 select replace('a','b','c') AS "oracle_schema.REPLACE('a','b','c')" +CALL p3('SUBSTR()'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTR() +errmsg +ERROR: 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 +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTR() +errmsg +ERROR: FUNCTION unknown_schema.SUBSTR does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTR() +errmsg +ERROR: Function 'SUBSTR' is not defined +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTR() +errmsg +ERROR: Function 'SUBSTR' is not defined +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTR() +errmsg +ERROR: Function 'SUBSTR' is not defined +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTR() +errmsg +ERROR: 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 +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTR() +errmsg +ERROR: FUNCTION unknown_schema.SUBSTR does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTR() +errmsg +ERROR: Function 'SUBSTR' is not defined +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTR() +errmsg +ERROR: Function 'SUBSTR' is not defined +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTR() +errmsg +ERROR: Function 'SUBSTR' is not defined +CALL p3('SUBSTR(''a'',1,2,3)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTR('a',1,2,3) +errmsg +ERROR: 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 '3)' at line 1 +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTR('a',1,2,3) +errmsg +ERROR: FUNCTION unknown_schema.SUBSTR does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTR('a',1,2,3) +errmsg +ERROR: Function 'SUBSTR' is not defined +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTR('a',1,2,3) +errmsg +ERROR: Function 'SUBSTR' is not defined +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTR('a',1,2,3) +errmsg +ERROR: Function 'SUBSTR' is not defined +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTR('a',1,2,3) +errmsg +ERROR: 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 '3)' at line 1 +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTR('a',1,2,3) +errmsg +ERROR: FUNCTION unknown_schema.SUBSTR does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTR('a',1,2,3) +errmsg +ERROR: Function 'SUBSTR' is not defined +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTR('a',1,2,3) +errmsg +ERROR: Function 'SUBSTR' is not defined +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTR('a',1,2,3) +errmsg +ERROR: Function 'SUBSTR' is not defined +CALL p3('SUBSTR(''a'',1,2)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTR('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS `SUBSTR('a',1,2)` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTR('a',1,2) +errmsg +ERROR: FUNCTION unknown_schema.SUBSTR does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTR('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS `mariadb_schema.SUBSTR('a',1,2)` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTR('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS `maxdb_schema.SUBSTR('a',1,2)` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTR('a',1,2) +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 +Level Code Message +Note 1003 select oracle_schema.substr('a',1,2) AS `oracle_schema.SUBSTR('a',1,2)` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTR('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS "SUBSTR('a',1,2)" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTR('a',1,2) +errmsg +ERROR: FUNCTION unknown_schema.SUBSTR does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTR('a',1,2) +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 +Level Code Message +Note 1003 select mariadb_schema.substr('a',1,2) AS "mariadb_schema.SUBSTR('a',1,2)" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTR('a',1,2) +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 +Level Code Message +Note 1003 select mariadb_schema.substr('a',1,2) AS "maxdb_schema.SUBSTR('a',1,2)" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTR('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS "oracle_schema.SUBSTR('a',1,2)" +Warnings: +Note 1003 select substr('a',1,2) AS "oracle_schema.SUBSTR('a',1,2)" +CALL p3('SUBSTR(''a'' FROM 1)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTR('a' FROM 1) +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 +Level Code Message +Note 1003 select substr('a',1) AS `SUBSTR('a' FROM 1)` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTR('a' FROM 1) +errmsg +ERROR: Function 'unknown_schema.SUBSTR' is not defined +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTR('a' FROM 1) +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 +Level Code Message +Note 1003 select substr('a',1) AS `mariadb_schema.SUBSTR('a' FROM 1)` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTR('a' FROM 1) +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 +Level Code Message +Note 1003 select substr('a',1) AS `maxdb_schema.SUBSTR('a' FROM 1)` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTR('a' FROM 1) +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 +Level Code Message +Note 1003 select oracle_schema.substr('a',1) AS `oracle_schema.SUBSTR('a' FROM 1)` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTR('a' FROM 1) +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 +Level Code Message +Note 1003 select substr('a',1) AS "SUBSTR('a' FROM 1)" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTR('a' FROM 1) +errmsg +ERROR: Function 'unknown_schema.SUBSTR' is not defined +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTR('a' FROM 1) +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 +Level Code Message +Note 1003 select mariadb_schema.substr('a',1) AS "mariadb_schema.SUBSTR('a' FROM 1)" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTR('a' FROM 1) +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 +Level Code Message +Note 1003 select mariadb_schema.substr('a',1) AS "maxdb_schema.SUBSTR('a' FROM 1)" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTR('a' FROM 1) +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 +Level Code Message +Note 1003 select substr('a',1) AS "oracle_schema.SUBSTR('a' FROM 1)" +Warnings: +Note 1003 select substr('a',1) AS "oracle_schema.SUBSTR('a' FROM 1)" +CALL p3('SUBSTRING(''a'',1,2)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTRING('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS `SUBSTRING('a',1,2)` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTRING('a',1,2) +errmsg +ERROR: FUNCTION unknown_schema.SUBSTRING does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTRING('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS `mariadb_schema.SUBSTRING('a',1,2)` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTRING('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS `maxdb_schema.SUBSTRING('a',1,2)` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTRING('a',1,2) +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 +Level Code Message +Note 1003 select oracle_schema.substr('a',1,2) AS `oracle_schema.SUBSTRING('a',1,2)` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTRING('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS "SUBSTRING('a',1,2)" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTRING('a',1,2) +errmsg +ERROR: FUNCTION unknown_schema.SUBSTRING does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTRING('a',1,2) +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 +Level Code Message +Note 1003 select mariadb_schema.substr('a',1,2) AS "mariadb_schema.SUBSTRING('a',1,2)" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTRING('a',1,2) +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 +Level Code Message +Note 1003 select mariadb_schema.substr('a',1,2) AS "maxdb_schema.SUBSTRING('a',1,2)" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTRING('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS "oracle_schema.SUBSTRING('a',1,2)" +Warnings: +Note 1003 select substr('a',1,2) AS "oracle_schema.SUBSTRING('a',1,2)" +CALL p3('SUBSTRING(''a'' FROM 1)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTRING('a' FROM 1) +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 +Level Code Message +Note 1003 select substr('a',1) AS `SUBSTRING('a' FROM 1)` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTRING('a' FROM 1) +errmsg +ERROR: Function 'unknown_schema.SUBSTRING' is not defined +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTRING('a' FROM 1) +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 +Level Code Message +Note 1003 select substr('a',1) AS `mariadb_schema.SUBSTRING('a' FROM 1)` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTRING('a' FROM 1) +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 +Level Code Message +Note 1003 select substr('a',1) AS `maxdb_schema.SUBSTRING('a' FROM 1)` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTRING('a' FROM 1) +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 +Level Code Message +Note 1003 select oracle_schema.substr('a',1) AS `oracle_schema.SUBSTRING('a' FROM 1)` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTRING('a' FROM 1) +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 +Level Code Message +Note 1003 select substr('a',1) AS "SUBSTRING('a' FROM 1)" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTRING('a' FROM 1) +errmsg +ERROR: Function 'unknown_schema.SUBSTRING' is not defined +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTRING('a' FROM 1) +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 +Level Code Message +Note 1003 select mariadb_schema.substr('a',1) AS "mariadb_schema.SUBSTRING('a' FROM 1)" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTRING('a' FROM 1) +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 +Level Code Message +Note 1003 select mariadb_schema.substr('a',1) AS "maxdb_schema.SUBSTRING('a' FROM 1)" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTRING('a' FROM 1) +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 +Level Code Message +Note 1003 select substr('a',1) AS "oracle_schema.SUBSTRING('a' FROM 1)" +Warnings: +Note 1003 select substr('a',1) AS "oracle_schema.SUBSTRING('a' FROM 1)" +CALL p3('TRIM()'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT TRIM() +errmsg +ERROR: 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 +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.TRIM() +errmsg +ERROR: FUNCTION unknown_schema.TRIM does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.TRIM() +errmsg +ERROR: Function 'TRIM' is not defined +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.TRIM() +errmsg +ERROR: Function 'TRIM' is not defined +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.TRIM() +errmsg +ERROR: Function 'TRIM' is not defined +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT TRIM() +errmsg +ERROR: 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 +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.TRIM() +errmsg +ERROR: FUNCTION unknown_schema.TRIM does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.TRIM() +errmsg +ERROR: Function 'TRIM' is not defined +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.TRIM() +errmsg +ERROR: Function 'TRIM' is not defined +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.TRIM() +errmsg +ERROR: Function 'TRIM' is not defined +CALL p3('TRIM(1,2)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT TRIM(1,2) +errmsg +ERROR: 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 '2)' at line 1 +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.TRIM(1,2) +errmsg +ERROR: FUNCTION unknown_schema.TRIM does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.TRIM(1,2) +errmsg +ERROR: Function 'TRIM' is not defined +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.TRIM(1,2) +errmsg +ERROR: Function 'TRIM' is not defined +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.TRIM(1,2) +errmsg +ERROR: Function 'TRIM' is not defined +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT TRIM(1,2) +errmsg +ERROR: 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 '2)' at line 1 +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.TRIM(1,2) +errmsg +ERROR: FUNCTION unknown_schema.TRIM does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.TRIM(1,2) +errmsg +ERROR: Function 'TRIM' is not defined +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.TRIM(1,2) +errmsg +ERROR: Function 'TRIM' is not defined +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.TRIM(1,2) +errmsg +ERROR: Function 'TRIM' is not defined +CALL p3('TRIM(''a'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT TRIM('a') +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 +Level Code Message +Note 1003 select trim('a') AS `TRIM('a')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.TRIM('a') +errmsg +ERROR: FUNCTION unknown_schema.TRIM does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.TRIM('a') +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 +Level Code Message +Note 1003 select trim('a') AS `mariadb_schema.TRIM('a')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.TRIM('a') +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 +Level Code Message +Note 1003 select trim('a') AS `maxdb_schema.TRIM('a')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.TRIM('a') +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 +Level Code Message +Note 1003 select oracle_schema.trim('a') AS `oracle_schema.TRIM('a')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT TRIM('a') +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 +Level Code Message +Note 1003 select trim('a') AS "TRIM('a')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.TRIM('a') +errmsg +ERROR: FUNCTION unknown_schema.TRIM does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.TRIM('a') +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 +Level Code Message +Note 1003 select mariadb_schema.trim('a') AS "mariadb_schema.TRIM('a')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.TRIM('a') +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 +Level Code Message +Note 1003 select mariadb_schema.trim('a') AS "maxdb_schema.TRIM('a')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.TRIM('a') +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 +Level Code Message +Note 1003 select trim('a') AS "oracle_schema.TRIM('a')" +Warnings: +Note 1003 select trim('a') AS "oracle_schema.TRIM('a')" +CALL p3('TRIM(BOTH '' '' FROM ''a'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT TRIM(BOTH ' ' FROM 'a') +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 +Level Code Message +Note 1003 select trim(both ' ' from 'a') AS `TRIM(BOTH ' ' FROM 'a')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.TRIM(BOTH ' ' FROM 'a') +errmsg +ERROR: Function 'unknown_schema.TRIM' is not defined +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.TRIM(BOTH ' ' FROM 'a') +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 +Level Code Message +Note 1003 select trim(both ' ' from 'a') AS `mariadb_schema.TRIM(BOTH ' ' FROM 'a')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.TRIM(BOTH ' ' FROM 'a') +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 +Level Code Message +Note 1003 select trim(both ' ' from 'a') AS `maxdb_schema.TRIM(BOTH ' ' FROM 'a')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.TRIM(BOTH ' ' FROM 'a') +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 +Level Code Message +Note 1003 select oracle_schema.trim(both ' ' from 'a') AS `oracle_schema.TRIM(BOTH ' ' FROM 'a')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT TRIM(BOTH ' ' FROM 'a') +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 +Level Code Message +Note 1003 select trim(both ' ' from 'a') AS "TRIM(BOTH ' ' FROM 'a')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.TRIM(BOTH ' ' FROM 'a') +errmsg +ERROR: Function 'unknown_schema.TRIM' is not defined +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.TRIM(BOTH ' ' FROM 'a') +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 +Level Code Message +Note 1003 select mariadb_schema.trim(both ' ' from 'a') AS "mariadb_schema.TRIM(BOTH ' ' FROM 'a')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.TRIM(BOTH ' ' FROM 'a') +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 +Level Code Message +Note 1003 select mariadb_schema.trim(both ' ' from 'a') AS "maxdb_schema.TRIM(BOTH ' ' FROM 'a')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.TRIM(BOTH ' ' FROM 'a') +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 +Level Code Message +Note 1003 select trim(both ' ' from 'a') AS "oracle_schema.TRIM(BOTH ' ' FROM 'a')" +Warnings: +Note 1003 select trim(both ' ' from 'a') AS "oracle_schema.TRIM(BOTH ' ' FROM 'a')" +CALL p3('CONCAT_OPERATOR_ORACLE(''a'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT CONCAT_OPERATOR_ORACLE('a') +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 +Level Code Message +Note 1003 select oracle_schema.concat('a') AS `CONCAT_OPERATOR_ORACLE('a')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.CONCAT_OPERATOR_ORACLE('a') +errmsg +ERROR: FUNCTION unknown_schema.CONCAT_OPERATOR_ORACLE does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.CONCAT_OPERATOR_ORACLE('a') +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 +Level Code Message +Note 1003 select oracle_schema.concat('a') AS `mariadb_schema.CONCAT_OPERATOR_ORACLE('a')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.CONCAT_OPERATOR_ORACLE('a') +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 +Level Code Message +Note 1003 select oracle_schema.concat('a') AS `maxdb_schema.CONCAT_OPERATOR_ORACLE('a')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.CONCAT_OPERATOR_ORACLE('a') +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 +Level Code Message +Note 1003 select oracle_schema.concat('a') AS `oracle_schema.CONCAT_OPERATOR_ORACLE('a')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT CONCAT_OPERATOR_ORACLE('a') +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 +Level Code Message +Note 1003 select concat('a') AS "CONCAT_OPERATOR_ORACLE('a')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.CONCAT_OPERATOR_ORACLE('a') +errmsg +ERROR: FUNCTION unknown_schema.CONCAT_OPERATOR_ORACLE does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.CONCAT_OPERATOR_ORACLE('a') +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 +Level Code Message +Note 1003 select concat('a') AS "mariadb_schema.CONCAT_OPERATOR_ORACLE('a')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.CONCAT_OPERATOR_ORACLE('a') +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 +Level Code Message +Note 1003 select concat('a') AS "maxdb_schema.CONCAT_OPERATOR_ORACLE('a')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.CONCAT_OPERATOR_ORACLE('a') +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 +Level Code Message +Note 1003 select concat('a') AS "oracle_schema.CONCAT_OPERATOR_ORACLE('a')" +Warnings: +Note 1003 select concat('a') AS "oracle_schema.CONCAT_OPERATOR_ORACLE('a')" +CALL p3('DECODE_ORACLE(1,1,10)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT DECODE_ORACLE(1,1,10) +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 +Level Code Message +Note 1003 select oracle_schema.decode(1,1,10) AS `DECODE_ORACLE(1,1,10)` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.DECODE_ORACLE(1,1,10) +errmsg +ERROR: FUNCTION unknown_schema.DECODE_ORACLE does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.DECODE_ORACLE(1,1,10) +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 +Level Code Message +Note 1003 select oracle_schema.decode(1,1,10) AS `mariadb_schema.DECODE_ORACLE(1,1,10)` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.DECODE_ORACLE(1,1,10) +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 +Level Code Message +Note 1003 select oracle_schema.decode(1,1,10) AS `maxdb_schema.DECODE_ORACLE(1,1,10)` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.DECODE_ORACLE(1,1,10) +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 +Level Code Message +Note 1003 select oracle_schema.decode(1,1,10) AS `oracle_schema.DECODE_ORACLE(1,1,10)` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT DECODE_ORACLE(1,1,10) +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 +Level Code Message +Note 1003 select decode(1,1,10) AS "DECODE_ORACLE(1,1,10)" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.DECODE_ORACLE(1,1,10) +errmsg +ERROR: FUNCTION unknown_schema.DECODE_ORACLE does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.DECODE_ORACLE(1,1,10) +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 +Level Code Message +Note 1003 select decode(1,1,10) AS "mariadb_schema.DECODE_ORACLE(1,1,10)" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.DECODE_ORACLE(1,1,10) +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 +Level Code Message +Note 1003 select decode(1,1,10) AS "maxdb_schema.DECODE_ORACLE(1,1,10)" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.DECODE_ORACLE(1,1,10) +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 +Level Code Message +Note 1003 select decode(1,1,10) AS "oracle_schema.DECODE_ORACLE(1,1,10)" +Warnings: +Note 1003 select decode(1,1,10) AS "oracle_schema.DECODE_ORACLE(1,1,10)" +CALL p3('LTRIM_ORACLE(''a'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT LTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select oracle_schema.ltrim('a') AS `LTRIM_ORACLE('a')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.LTRIM_ORACLE('a') +errmsg +ERROR: FUNCTION unknown_schema.LTRIM_ORACLE does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.LTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select oracle_schema.ltrim('a') AS `mariadb_schema.LTRIM_ORACLE('a')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.LTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select oracle_schema.ltrim('a') AS `maxdb_schema.LTRIM_ORACLE('a')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.LTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select oracle_schema.ltrim('a') AS `oracle_schema.LTRIM_ORACLE('a')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT LTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select ltrim('a') AS "LTRIM_ORACLE('a')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.LTRIM_ORACLE('a') +errmsg +ERROR: FUNCTION unknown_schema.LTRIM_ORACLE does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.LTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select ltrim('a') AS "mariadb_schema.LTRIM_ORACLE('a')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.LTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select ltrim('a') AS "maxdb_schema.LTRIM_ORACLE('a')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.LTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select ltrim('a') AS "oracle_schema.LTRIM_ORACLE('a')" +Warnings: +Note 1003 select ltrim('a') AS "oracle_schema.LTRIM_ORACLE('a')" +CALL p3('RTRIM_ORACLE(''a'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT RTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select oracle_schema.rtrim('a') AS `RTRIM_ORACLE('a')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.RTRIM_ORACLE('a') +errmsg +ERROR: FUNCTION unknown_schema.RTRIM_ORACLE does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.RTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select oracle_schema.rtrim('a') AS `mariadb_schema.RTRIM_ORACLE('a')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.RTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select oracle_schema.rtrim('a') AS `maxdb_schema.RTRIM_ORACLE('a')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.RTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select oracle_schema.rtrim('a') AS `oracle_schema.RTRIM_ORACLE('a')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT RTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select rtrim('a') AS "RTRIM_ORACLE('a')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.RTRIM_ORACLE('a') +errmsg +ERROR: FUNCTION unknown_schema.RTRIM_ORACLE does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.RTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select rtrim('a') AS "mariadb_schema.RTRIM_ORACLE('a')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.RTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select rtrim('a') AS "maxdb_schema.RTRIM_ORACLE('a')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.RTRIM_ORACLE('a') +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 +Level Code Message +Note 1003 select rtrim('a') AS "oracle_schema.RTRIM_ORACLE('a')" +Warnings: +Note 1003 select rtrim('a') AS "oracle_schema.RTRIM_ORACLE('a')" +CALL p3('LPAD_ORACLE(''a'',3)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT LPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select oracle_schema.lpad('a',3) AS `LPAD_ORACLE('a',3)` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.LPAD_ORACLE('a',3) +errmsg +ERROR: FUNCTION unknown_schema.LPAD_ORACLE does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.LPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select oracle_schema.lpad('a',3) AS `mariadb_schema.LPAD_ORACLE('a',3)` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.LPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select oracle_schema.lpad('a',3) AS `maxdb_schema.LPAD_ORACLE('a',3)` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.LPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select oracle_schema.lpad('a',3) AS `oracle_schema.LPAD_ORACLE('a',3)` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT LPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select lpad('a',3) AS "LPAD_ORACLE('a',3)" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.LPAD_ORACLE('a',3) +errmsg +ERROR: FUNCTION unknown_schema.LPAD_ORACLE does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.LPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select lpad('a',3) AS "mariadb_schema.LPAD_ORACLE('a',3)" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.LPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select lpad('a',3) AS "maxdb_schema.LPAD_ORACLE('a',3)" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.LPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select lpad('a',3) AS "oracle_schema.LPAD_ORACLE('a',3)" +Warnings: +Note 1003 select lpad('a',3) AS "oracle_schema.LPAD_ORACLE('a',3)" +CALL p3('RPAD_ORACLE(''a'',3)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT RPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select oracle_schema.rpad('a',3) AS `RPAD_ORACLE('a',3)` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.RPAD_ORACLE('a',3) +errmsg +ERROR: FUNCTION unknown_schema.RPAD_ORACLE does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.RPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select oracle_schema.rpad('a',3) AS `mariadb_schema.RPAD_ORACLE('a',3)` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.RPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select oracle_schema.rpad('a',3) AS `maxdb_schema.RPAD_ORACLE('a',3)` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.RPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select oracle_schema.rpad('a',3) AS `oracle_schema.RPAD_ORACLE('a',3)` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT RPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select rpad('a',3) AS "RPAD_ORACLE('a',3)" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.RPAD_ORACLE('a',3) +errmsg +ERROR: FUNCTION unknown_schema.RPAD_ORACLE does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.RPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select rpad('a',3) AS "mariadb_schema.RPAD_ORACLE('a',3)" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.RPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select rpad('a',3) AS "maxdb_schema.RPAD_ORACLE('a',3)" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.RPAD_ORACLE('a',3) +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 +Level Code Message +Note 1003 select rpad('a',3) AS "oracle_schema.RPAD_ORACLE('a',3)" +Warnings: +Note 1003 select rpad('a',3) AS "oracle_schema.RPAD_ORACLE('a',3)" +CALL p3('REPLACE_ORACLE(''a'',''b'',''c'')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT REPLACE_ORACLE('a','b','c') +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 +Level Code Message +Note 1003 select oracle_schema.replace('a','b','c') AS `REPLACE_ORACLE('a','b','c')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REPLACE_ORACLE('a','b','c') +errmsg +ERROR: FUNCTION unknown_schema.REPLACE_ORACLE does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REPLACE_ORACLE('a','b','c') +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 +Level Code Message +Note 1003 select oracle_schema.replace('a','b','c') AS `mariadb_schema.REPLACE_ORACLE('a','b','c')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REPLACE_ORACLE('a','b','c') +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 +Level Code Message +Note 1003 select oracle_schema.replace('a','b','c') AS `maxdb_schema.REPLACE_ORACLE('a','b','c')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REPLACE_ORACLE('a','b','c') +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 +Level Code Message +Note 1003 select oracle_schema.replace('a','b','c') AS `oracle_schema.REPLACE_ORACLE('a','b','c')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT REPLACE_ORACLE('a','b','c') +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 +Level Code Message +Note 1003 select replace('a','b','c') AS "REPLACE_ORACLE('a','b','c')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REPLACE_ORACLE('a','b','c') +errmsg +ERROR: FUNCTION unknown_schema.REPLACE_ORACLE does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REPLACE_ORACLE('a','b','c') +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 +Level Code Message +Note 1003 select replace('a','b','c') AS "mariadb_schema.REPLACE_ORACLE('a','b','c')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REPLACE_ORACLE('a','b','c') +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 +Level Code Message +Note 1003 select replace('a','b','c') AS "maxdb_schema.REPLACE_ORACLE('a','b','c')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REPLACE_ORACLE('a','b','c') +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 +Level Code Message +Note 1003 select replace('a','b','c') AS "oracle_schema.REPLACE_ORACLE('a','b','c')" +Warnings: +Note 1003 select replace('a','b','c') AS "oracle_schema.REPLACE_ORACLE('a','b','c')" +CALL p3('SUBSTR_ORACLE(''a'',1,2)'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTR_ORACLE('a',1,2) +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 +Level Code Message +Note 1003 select oracle_schema.substr('a',1,2) AS `SUBSTR_ORACLE('a',1,2)` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTR_ORACLE('a',1,2) +errmsg +ERROR: FUNCTION unknown_schema.SUBSTR_ORACLE does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTR_ORACLE('a',1,2) +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 +Level Code Message +Note 1003 select oracle_schema.substr('a',1,2) AS `mariadb_schema.SUBSTR_ORACLE('a',1,2)` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTR_ORACLE('a',1,2) +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 +Level Code Message +Note 1003 select oracle_schema.substr('a',1,2) AS `maxdb_schema.SUBSTR_ORACLE('a',1,2)` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTR_ORACLE('a',1,2) +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 +Level Code Message +Note 1003 select oracle_schema.substr('a',1,2) AS `oracle_schema.SUBSTR_ORACLE('a',1,2)` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT SUBSTR_ORACLE('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS "SUBSTR_ORACLE('a',1,2)" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.SUBSTR_ORACLE('a',1,2) +errmsg +ERROR: FUNCTION unknown_schema.SUBSTR_ORACLE does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.SUBSTR_ORACLE('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS "mariadb_schema.SUBSTR_ORACLE('a',1,2)" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.SUBSTR_ORACLE('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS "maxdb_schema.SUBSTR_ORACLE('a',1,2)" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.SUBSTR_ORACLE('a',1,2) +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 +Level Code Message +Note 1003 select substr('a',1,2) AS "oracle_schema.SUBSTR_ORACLE('a',1,2)" +Warnings: +Note 1003 select substr('a',1,2) AS "oracle_schema.SUBSTR_ORACLE('a',1,2)" +SELECT oracle_schema.SUBSTR_ORACLE('a' FROM 1 FOR 2); +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 'FROM 1 FOR 2)' at line 1 +SELECT oracle_schema.SUBSTR('a' FROM 1 FOR 2); +oracle_schema.SUBSTR('a' FROM 1 FOR 2) +a +SELECT oracle_schema.TRIM_ORACLE(LEADING ' ' FROM 'a'); +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 'LEADING ' ' FROM 'a')' at line 1 +SELECT oracle_schema.TRIM(LEADING ' ' FROM 'a'); +oracle_schema.TRIM(LEADING ' ' FROM 'a') +a +SELECT oracle_schema.TRIM_ORACLE('a'); +ERROR HY000: Function 'TRIM_ORACLE' is not defined +SELECT oracle_schema.TRIM('a'); +oracle_schema.TRIM('a') +a +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP PROCEDURE p3; +SET sql_mode=''; +CREATE VIEW v1 AS SELECT +concat('a','b'), +decode('1','2'), +ltrim('1'), +rtrim('1'), +lpad('1','2', 3), +rpad('1','2', 3), +replace('1','2','3'), +substr('a',1,2), +trim(both 'a' FROM 'b'); +CREATE TABLE kv (v BLOB); +LOAD DATA INFILE 'MYSQLD_DATADIR/test/v1.frm' REPLACE INTO TABLE kv; +SELECT v FROM kv WHERE v RLIKE '^(query|view_body_utf8)=' ORDER BY v; +v +query=select concat('a','b') AS `concat('a','b')`,decode('1','2') AS `decode('1','2')`,ltrim('1') AS `ltrim('1')`,rtrim('1') AS `rtrim('1')`,lpad('1','2',3) AS `lpad('1','2', 3)`,rpad('1','2',3) AS `rpad('1','2', 3)`,replace('1','2','3') AS `replace('1','2','3')`,substr('a',1,2) AS `substr('a',1,2)`,trim(both 'a' from 'b') AS `trim(both 'a' FROM 'b')` +view_body_utf8=select concat('a','b') AS `concat('a','b')`,decode('1','2') AS `decode('1','2')`,ltrim('1') AS `ltrim('1')`,rtrim('1') AS `rtrim('1')`,lpad('1','2',3) AS `lpad('1','2', 3)`,rpad('1','2',3) AS `rpad('1','2', 3)`,replace('1','2','3') AS `replace('1','2','3')`,substr('a',1,2) AS `substr('a',1,2)`,trim(both 'a' from 'b') AS `trim(both 'a' FROM 'b')` +SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME='v1' AND TABLE_SCHEMA='test'; +VIEW_DEFINITION +select concat('a','b') AS `concat('a','b')`,decode('1','2') AS `decode('1','2')`,ltrim('1') AS `ltrim('1')`,rtrim('1') AS `rtrim('1')`,lpad('1','2',3) AS `lpad('1','2', 3)`,rpad('1','2',3) AS `rpad('1','2', 3)`,replace('1','2','3') AS `replace('1','2','3')`,substr('a',1,2) AS `substr('a',1,2)`,trim(both 'a' from 'b') AS `trim(both 'a' FROM 'b')` +DROP TABLE kv; +DROP VIEW v1; +SET sql_mode='ORACLE'; +CREATE VIEW v1 AS SELECT +concat('a','b'), +decode('1',2,3), +ltrim('1'), +rtrim('1'), +lpad('1','2', 3), +rpad('1','2', 3), +replace('1','2','3'), +substr('a',1,2), +trim(both 'a' FROM 'b'); +CREATE TABLE kv (v BLOB); +LOAD DATA INFILE 'MYSQLD_DATADIR/test/v1.frm' REPLACE INTO TABLE kv; +SELECT v FROM kv WHERE v RLIKE '^(query|view_body_utf8)=' ORDER BY v; +v +query=select concat_operator_oracle('a','b') AS `concat('a','b')`,decode_oracle('1',2,3) AS `decode('1',2,3)`,ltrim_oracle('1') AS `ltrim('1')`,rtrim_oracle('1') AS `rtrim('1')`,lpad_oracle('1','2',3) AS `lpad('1','2', 3)`,rpad_oracle('1','2',3) AS `rpad('1','2', 3)`,replace_oracle('1','2','3') AS `replace('1','2','3')`,substr_oracle('a',1,2) AS `substr('a',1,2)`,trim_oracle(both 'a' from 'b') AS `trim(both 'a' FROM 'b')` +view_body_utf8=select oracle_schema.concat('a','b') AS `concat('a','b')`,oracle_schema.decode('1',2,3) AS `decode('1',2,3)`,oracle_schema.ltrim('1') AS `ltrim('1')`,oracle_schema.rtrim('1') AS `rtrim('1')`,oracle_schema.lpad('1','2',3) AS `lpad('1','2', 3)`,oracle_schema.rpad('1','2',3) AS `rpad('1','2', 3)`,oracle_schema.replace('1','2','3') AS `replace('1','2','3')`,oracle_schema.substr('a',1,2) AS `substr('a',1,2)`,oracle_schema.trim(both 'a' from 'b') AS `trim(both 'a' FROM 'b')` +SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME='v1' AND TABLE_SCHEMA='test'; +VIEW_DEFINITION +select oracle_schema.concat('a','b') AS `concat('a','b')`,oracle_schema.decode('1',2,3) AS `decode('1',2,3)`,oracle_schema.ltrim('1') AS `ltrim('1')`,oracle_schema.rtrim('1') AS `rtrim('1')`,oracle_schema.lpad('1','2',3) AS `lpad('1','2', 3)`,oracle_schema.rpad('1','2',3) AS `rpad('1','2', 3)`,oracle_schema.replace('1','2','3') AS `replace('1','2','3')`,oracle_schema.substr('a',1,2) AS `substr('a',1,2)`,oracle_schema.trim(both 'a' from 'b') AS `trim(both 'a' FROM 'b')` +DROP TABLE kv; +DROP VIEW v1; diff --git a/mysql-test/suite/compat/oracle/r/func_replace.result b/mysql-test/suite/compat/oracle/r/func_replace.result index 02516096286..012db2a7500 100644 --- a/mysql-test/suite/compat/oracle/r/func_replace.result +++ b/mysql-test/suite/compat/oracle/r/func_replace.result @@ -21,11 +21,11 @@ EXPLAIN EXTENDED SELECT REPLACE('ab','a',null) ; 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 replace_oracle('ab','a',NULL) AS "REPLACE('ab','a',null)" +Note 1003 select replace('ab','a',NULL) AS "REPLACE('ab','a',null)" CREATE VIEW v1 AS SELECT REPLACE('ab','a',null) ; SHOW CREATE VIEW v1; View Create View character_set_client collation_connection -v1 CREATE VIEW "v1" AS select replace_oracle('ab','a',NULL) AS "REPLACE('ab','a',null)" latin1 latin1_swedish_ci +v1 CREATE VIEW "v1" AS select replace('ab','a',NULL) AS "REPLACE('ab','a',null)" latin1 latin1_swedish_ci SELECT * FROM v1; REPLACE('ab','a',null) b diff --git a/mysql-test/suite/compat/oracle/r/func_substr.result b/mysql-test/suite/compat/oracle/r/func_substr.result index 5d9fdd5f2b9..cbb0e74cc3a 100644 --- a/mysql-test/suite/compat/oracle/r/func_substr.result +++ b/mysql-test/suite/compat/oracle/r/func_substr.result @@ -76,11 +76,11 @@ EXPLAIN EXTENDED SELECT SUBSTR('abc',2,1) ; 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 substr_oracle('abc',2,1) AS "SUBSTR('abc',2,1)" +Note 1003 select substr('abc',2,1) AS "SUBSTR('abc',2,1)" CREATE VIEW v1 AS SELECT SUBSTR('abc',2,1) ; SHOW CREATE VIEW v1; View Create View character_set_client collation_connection -v1 CREATE VIEW "v1" AS select substr_oracle('abc',2,1) AS "SUBSTR('abc',2,1)" latin1 latin1_swedish_ci +v1 CREATE VIEW "v1" AS select substr('abc',2,1) AS "SUBSTR('abc',2,1)" latin1 latin1_swedish_ci SELECT * FROM v1; SUBSTR('abc',2,1) b diff --git a/mysql-test/suite/compat/oracle/r/func_trim.result b/mysql-test/suite/compat/oracle/r/func_trim.result index bed8dadf97f..965531db288 100644 --- a/mysql-test/suite/compat/oracle/r/func_trim.result +++ b/mysql-test/suite/compat/oracle/r/func_trim.result @@ -116,13 +116,13 @@ TRIM(TRAILING 'a' FROM 'abc') ; 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 trim_oracle('abc') AS "TRIM('abc')",trim_oracle(both 'a' from 'abc') AS "TRIM(BOTH 'a' FROM 'abc')",trim_oracle(leading 'a' from 'abc') AS "TRIM(LEADING 'a' FROM 'abc')",trim_oracle(trailing 'a' from 'abc') AS "TRIM(TRAILING 'a' FROM 'abc')" +Note 1003 select trim('abc') AS "TRIM('abc')",trim(both 'a' from 'abc') AS "TRIM(BOTH 'a' FROM 'abc')",trim(leading 'a' from 'abc') AS "TRIM(LEADING 'a' FROM 'abc')",trim(trailing 'a' from 'abc') AS "TRIM(TRAILING 'a' FROM 'abc')" EXPLAIN EXTENDED SELECT RTRIM('abc'), LTRIM('abc'); 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 rtrim_oracle('abc') AS "RTRIM('abc')",ltrim_oracle('abc') AS "LTRIM('abc')" +Note 1003 select rtrim('abc') AS "RTRIM('abc')",ltrim('abc') AS "LTRIM('abc')" CREATE VIEW v1 AS SELECT ord,TRIM('abc'),RTRIM('abc'),LTRIM('abc'), '['||c1||']', TRIM(LEADING 'a' FROM c1), @@ -133,7 +133,7 @@ RTRIM(c1) FROM t1 ORDER BY ord ; SHOW CREATE VIEW v1; View Create View character_set_client collation_connection -v1 CREATE VIEW "v1" AS select "t1"."ord" AS "ord",trim_oracle('abc') AS "TRIM('abc')",rtrim_oracle('abc') AS "RTRIM('abc')",ltrim_oracle('abc') AS "LTRIM('abc')",concat_operator_oracle(concat_operator_oracle('[',"t1"."c1"),']') AS "'['||c1||']'",trim_oracle(leading 'a' from "t1"."c1") AS "TRIM(LEADING 'a' FROM c1)",trim_oracle(trailing 'a' from "t1"."c1") AS "TRIM(TRAILING 'a' FROM c1)",trim_oracle(both 'a' from "t1"."c1") AS "TRIM(BOTH 'a' FROM c1)",ltrim_oracle("t1"."c1") AS "LTRIM(c1)",rtrim_oracle("t1"."c1") AS "RTRIM(c1)" from "t1" order by "t1"."ord" latin1 latin1_swedish_ci +v1 CREATE VIEW "v1" AS select "t1"."ord" AS "ord",trim('abc') AS "TRIM('abc')",rtrim('abc') AS "RTRIM('abc')",ltrim('abc') AS "LTRIM('abc')",concat(concat('[',"t1"."c1"),']') AS "'['||c1||']'",trim(leading 'a' from "t1"."c1") AS "TRIM(LEADING 'a' FROM c1)",trim(trailing 'a' from "t1"."c1") AS "TRIM(TRAILING 'a' FROM c1)",trim(both 'a' from "t1"."c1") AS "TRIM(BOTH 'a' FROM c1)",ltrim("t1"."c1") AS "LTRIM(c1)",rtrim("t1"."c1") AS "RTRIM(c1)" from "t1" order by "t1"."ord" latin1 latin1_swedish_ci SELECT * FROM v1; ord TRIM('abc') RTRIM('abc') LTRIM('abc') '['||c1||']' TRIM(LEADING 'a' FROM c1) TRIM(TRAILING 'a' FROM c1) TRIM(BOTH 'a' FROM c1) LTRIM(c1) RTRIM(c1) 1 abc abc abc [abc] bc abc bc abc abc diff --git a/mysql-test/suite/compat/oracle/r/mysqldump_restore_func_qualified.result b/mysql-test/suite/compat/oracle/r/mysqldump_restore_func_qualified.result new file mode 100644 index 00000000000..fd3dd787f1e --- /dev/null +++ b/mysql-test/suite/compat/oracle/r/mysqldump_restore_func_qualified.result @@ -0,0 +1,112 @@ +# +# Start of 10.4 tests +# +# +# MDEV-27744 LPAD in vcol created in ORACLE mode makes table corrupted in non-ORACLE +# +SET sql_mode=DEFAULT; +CREATE TABLE t1 ( +a0 VARCHAR(64) NOT NULL DEFAULT LTRIM(now()), +a1 VARCHAR(64) AS (LTRIM(a0)) PERSISTENT, +b0 VARCHAR(64) NOT NULL DEFAULT LPAD(now(),10), +b1 VARCHAR(64) AS (LPAD(b0,10)) PERSISTENT +); +CREATE VIEW v1 AS SELECT +LTRIM(now()) AS a0, +LPAD(now(),10) AS b0; +SET sql_mode=ORACLE; +CREATE TABLE t2 ( +a0 VARCHAR(64) NOT NULL DEFAULT LTRIM(now()), +a1 VARCHAR(64) AS (LTRIM(a0)) PERSISTENT, +b0 VARCHAR(64) NOT NULL DEFAULT LPAD(now(),10), +b1 VARCHAR(64) AS (LPAD(b0,10)) PERSISTENT +); +CREATE VIEW v2 AS SELECT +LTRIM(now()) AS a0, +LPAD(now(),10) AS b0; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `t1` ( + `a0` varchar(64) NOT NULL DEFAULT ltrim(current_timestamp()), + `a1` varchar(64) GENERATED ALWAYS AS (ltrim(`a0`)) STORED, + `b0` varchar(64) NOT NULL DEFAULT lpad(current_timestamp(),10), + `b1` varchar(64) GENERATED ALWAYS AS (lpad(`b0`,10)) STORED +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `t2` ( + `a0` varchar(64) NOT NULL DEFAULT ltrim_oracle(current_timestamp()), + `a1` varchar(64) GENERATED ALWAYS AS (ltrim_oracle(`a0`)) STORED, + `b0` varchar(64) NOT NULL DEFAULT lpad_oracle(current_timestamp(),10), + `b1` varchar(64) GENERATED ALWAYS AS (lpad_oracle(`b0`,10)) STORED +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; +/*!40101 SET character_set_client = @saved_cs_client */; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; +/*!50001 CREATE VIEW `v1` AS SELECT + 1 AS `a0`, + 1 AS `b0` */; +SET character_set_client = @saved_cs_client; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; +/*!50001 CREATE VIEW `v2` AS SELECT + 1 AS `a0`, + 1 AS `b0` */; +SET character_set_client = @saved_cs_client; +/*!50001 DROP VIEW IF EXISTS `v1`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = latin1 */; +/*!50001 SET character_set_results = latin1 */; +/*!50001 SET collation_connection = latin1_swedish_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ +/*!50001 VIEW `v1` AS select ltrim(current_timestamp()) AS `a0`,lpad(current_timestamp(),10) AS `b0` */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; +/*!50001 DROP VIEW IF EXISTS `v2`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = latin1 */; +/*!50001 SET character_set_results = latin1 */; +/*!50001 SET collation_connection = latin1_swedish_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ +/*!50001 VIEW `v2` AS select oracle_schema.ltrim(current_timestamp()) AS `a0`,oracle_schema.lpad(current_timestamp(),10) AS `b0` */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; +DROP TABLE t1,t2; +DROP VIEW v1,v2; +SET sql_mode=DEFAULT; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` varchar(64) NOT NULL DEFAULT ltrim(current_timestamp()), + `a1` varchar(64) GENERATED ALWAYS AS (ltrim(`a0`)) STORED, + `b0` varchar(64) NOT NULL DEFAULT lpad(current_timestamp(),10), + `b1` varchar(64) GENERATED ALWAYS AS (lpad(`b0`,10)) STORED +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a0` varchar(64) NOT NULL DEFAULT ltrim_oracle(current_timestamp()), + `a1` varchar(64) GENERATED ALWAYS AS (ltrim_oracle(`a0`)) STORED, + `b0` varchar(64) NOT NULL DEFAULT lpad_oracle(current_timestamp(),10), + `b1` varchar(64) GENERATED ALWAYS AS (lpad_oracle(`b0`,10)) STORED +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select ltrim(current_timestamp()) AS `a0`,lpad(current_timestamp(),10) AS `b0` latin1 latin1_swedish_ci +SHOW CREATE VIEW v2; +View Create View character_set_client collation_connection +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select oracle_schema.ltrim(current_timestamp()) AS `a0`,oracle_schema.lpad(current_timestamp(),10) AS `b0` latin1 latin1_swedish_ci +DROP TABLE t1,t2; +DROP VIEW v1, v2; +# +# End of 10.4 tests +# diff --git a/mysql-test/suite/compat/oracle/r/ps.result b/mysql-test/suite/compat/oracle/r/ps.result index 818c97b06ab..2d0c4da9554 100644 --- a/mysql-test/suite/compat/oracle/r/ps.result +++ b/mysql-test/suite/compat/oracle/r/ps.result @@ -178,9 +178,9 @@ EXECUTE IMMEDIATE 'SELECT :1 FROM DUAL' USING 10; # Testing erroneous and diallowed prepare source # EXECUTE IMMEDIATE _latin1'SELECT 1 AS c FROM ' || _latin2 'DUAL'; -ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat_operator_oracle' +ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat' PREPARE stmt FROM _latin1'SELECT 1 AS c FROM ' || _latin2 'DUAL'; -ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat_operator_oracle' +ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat' EXECUTE IMMEDIATE (SELECT 'SELECT 1'); ERROR 42000: EXECUTE IMMEDIATE does not support subqueries or stored functions PREPARE stmt FROM (SELECT 'SELECT 1'); diff --git a/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result b/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result index 31d794c9f61..93300cc375b 100644 --- a/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result +++ b/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result @@ -758,7 +758,7 @@ END; END; $$ CALL p1(); -ERROR HY000: Illegal mix of collations (latin1_bin,EXPLICIT) and (latin1_swedish_ci,EXPLICIT) for operation 'concat_operator_oracle' +ERROR HY000: Illegal mix of collations (latin1_bin,EXPLICIT) and (latin1_swedish_ci,EXPLICIT) for operation 'concat' DROP PROCEDURE p1; # # Non-existing field diff --git a/mysql-test/suite/compat/oracle/r/vcol_innodb.result b/mysql-test/suite/compat/oracle/r/vcol_innodb.result new file mode 100644 index 00000000000..112d1b4ad53 --- /dev/null +++ b/mysql-test/suite/compat/oracle/r/vcol_innodb.result @@ -0,0 +1,54 @@ +# +# MDEV-27744 LPAD in vcol created in ORACLE mode makes table corrupted in non-ORACLE +# +FLUSH TABLES; +SET sql_mode=''; +CREATE TABLE t (d INT,b VARCHAR(1),c CHAR(1),g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL,PRIMARY KEY(b),KEY g(g)) ENGINE=InnoDB; +INSERT INTO t VALUES (0); +ERROR 21S01: Column count doesn't match value count at row 1 +SET sql_mode='ORACLE'; +INSERT INTO t SET c=REPEAT (1,0); +Warnings: +Warning 1364 Field 'b' doesn't have a default value +ALTER TABLE t CHANGE COLUMN a b INT; +ERROR 42S22: Unknown column 'a' in 't' +DELETE FROM t; +SET sql_mode=''; +FLUSH TABLES; +INSERT INTO t SET c='0'; +Warnings: +Warning 1364 Field 'b' doesn't have a default value +DROP TABLE t; +FLUSH TABLES; +SET sql_mode=''; +CREATE TABLE t (a INT(1),d INT(1),b VARCHAR(1),c CHAR(1),vadc INT(1) GENERATED ALWAYS AS ( (a + length (d))) STORED,vbc CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL,vbidxc CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL,PRIMARY KEY(b (1),a,d),KEY d (d),KEY a (a),KEY c_renamed (c (1),b (1)),KEY b (b (1),c (1),a),KEY vbidxc (vbidxc),KEY a_2 (a,vbidxc),KEY vbidxc_2 (vbidxc,d)) DEFAULT CHARSET=latin1 ENGINE=InnoDB; +INSERT INTO t VALUES (0,0,1,0,1,0,1,0,0); +ERROR 21S01: Column count doesn't match value count at row 1 +SET SESSION sql_mode='ORACLE'; +INSERT INTO t SET c=REPEAT (1,0); +Warnings: +Warning 1364 Field 'a' doesn't have a default value +Warning 1364 Field 'd' doesn't have a default value +Warning 1364 Field 'b' doesn't have a default value +ALTER TABLE t CHANGE COLUMN a b CHAR(1); +ERROR 42S21: Duplicate column name 'b' +DELETE FROM t; +SET SESSION sql_mode=DEFAULT; +DROP TABLE t; +SET sql_mode=''; +CREATE TABLE t1 (d INT,b VARCHAR(1),c CHAR(1),g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL,PRIMARY KEY(b),KEY g(g)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (0); +ERROR 21S01: Column count doesn't match value count at row 1 +SET sql_mode='ORACLE'; +INSERT INTO t1 SET c=REPEAT (1,0); +Warnings: +Warning 1364 Field 'b' doesn't have a default value +ALTER TABLE t1 CHANGE COLUMN a b INT; +ERROR 42S22: Unknown column 'a' in 't1' +DELETE FROM t1; +SET sql_mode=''; +FLUSH TABLES; +INSERT INTO t1 SET c='0'; +Warnings: +Warning 1364 Field 'b' doesn't have a default value +DROP TABLE t1; diff --git a/mysql-test/suite/compat/oracle/t/func_qualified.test b/mysql-test/suite/compat/oracle/t/func_qualified.test new file mode 100644 index 00000000000..842015dbbd6 --- /dev/null +++ b/mysql-test/suite/compat/oracle/t/func_qualified.test @@ -0,0 +1,247 @@ +--let $MYSQLD_DATADIR= `select @@datadir` + +--echo # +--echo # MDEV-27744 LPAD in vcol created in ORACLE mode makes table corrupted in non-ORACLE +--echo # + +# +# Testing that the error message for DECODE preserves +# the exact letter case as typed by the user +# + +SET sql_mode=DEFAULT; +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT decode_oracle(1); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT DECODE_ORACLE(1); + +SET sql_mode=ORACLE; +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT decode_oracle(1); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT DECODE_ORACLE(1); + +SET sql_mode=DEFAULT; +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT decode(1); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT DECODE(1); + +SET sql_mode=ORACLE; +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT decode(1); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT DECODE(1); + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT mariadb_schema.decode(1); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT mariadb_schema.DECODE(1); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT mariadb_schema.decode_oracle(1); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT mariadb_schema.DECODE_ORACLE(1); + +# +# Testing that REPLACE, SUBSTR, TRIM print the exact name +# as typed by the user in "Function .. is not defined" +# + +SET sql_mode=DEFAULT; + +--error ER_FUNC_INEXISTENT_NAME_COLLISION +SELECT unknown.TRIM(1); +--error ER_FUNC_INEXISTENT_NAME_COLLISION +SELECT unknown.trim(1); + +--error ER_FUNCTION_NOT_DEFINED +SELECT oracle_schema.TRIM(); +--error ER_FUNCTION_NOT_DEFINED +SELECT oracle_schema.TRIM('a','b'); +--error ER_FUNCTION_NOT_DEFINED +SELECT oracle_schema.TRIM('a','b','c','d'); + +--error ER_FUNC_INEXISTENT_NAME_COLLISION +SELECT unknown.SUBSTR('a',1,2); +--error ER_FUNC_INEXISTENT_NAME_COLLISION +SELECT unknown.substr('a',1,2); +--error ER_FUNC_INEXISTENT_NAME_COLLISION +SELECT unknown.SUBSTRING('a',1,2); +--error ER_FUNC_INEXISTENT_NAME_COLLISION +SELECT unknown.substring('a',1,2); + +--error ER_FUNC_INEXISTENT_NAME_COLLISION +SELECT unknown.REPLACE('a','b','c'); +--error ER_FUNC_INEXISTENT_NAME_COLLISION +SELECT unknown.replace('a','b','c'); + +--error ER_FUNCTION_NOT_DEFINED +SELECT oracle_schema.REPLACE(); +--error ER_FUNCTION_NOT_DEFINED +SELECT oracle_schema.REPLACE('a'); +--error ER_FUNCTION_NOT_DEFINED +SELECT oracle_schema.REPLACE('a','b'); +--error ER_FUNCTION_NOT_DEFINED +SELECT oracle_schema.REPLACE('a','b','c','d'); + +# +# Testing EXPLAIN EXTENDED SELECT +# + +SET sql_mode=DEFAULT; +DELIMITER $$; +CREATE PROCEDURE p1(sqlmode TEXT, qualifier TEXT, expr TEXT) +BEGIN + DECLARE query TEXT DEFAULT 'SELECT $(QUALIFIER)$(EXPR)'; + DECLARE errmsg TEXT DEFAULT NULL; + DECLARE CONTINUE HANDLER FOR 1064, 1128, 1305, 1582, 1630 + BEGIN + GET DIAGNOSTICS CONDITION 1 errmsg = MESSAGE_TEXT; + END; + + SET sql_mode=sqlmode; + SET query=REPLACE(query, '$(QUALIFIER)', qualifier); + SET query=REPLACE(query, '$(EXPR)', expr); + SET query= CONCAT('EXPLAIN EXTENDED ', query); + SELECT CONCAT('sql_mode=''',sqlmode,'''', ' ', + 'qualifier=''',qualifier,'''') AS `----------`; + SELECT query; + EXECUTE IMMEDIATE query; + IF errmsg IS NOT NULL THEN + SELECT CONCAT('ERROR: ', errmsg) AS errmsg; + ELSE + SHOW WARNINGS; + END IF; +END; +$$ +CREATE PROCEDURE p2(sqlmode TEXT, expr TEXT) +BEGIN + CALL p1(sqlmode, '', expr); + CALL p1(sqlmode, 'unknown_schema.', expr); + CALL p1(sqlmode, 'mariadb_schema.', expr); + CALL p1(sqlmode, 'maxdb_schema.', expr); + CALL p1(sqlmode, 'oracle_schema.', expr); +END; +$$ +CREATE PROCEDURE p3(expr TEXT) +BEGIN + CALL p2('', expr); + CALL p2('ORACLE', expr); +END; +$$ +DELIMITER ;$$ + +CALL p3('CONCAT(''a'')'); + +# MariaDB style +CALL p3('DECODE(''1'',''2'')'); +# Oracle style +CALL p3('DECODE(1,1,10)'); + +CALL p3('LTRIM(''a'')'); +CALL p3('RTRIM(''a'')'); + +CALL p3('LPAD(''a'',3)'); +CALL p3('LPAD(''a'',3, '' '')'); + +CALL p3('RPAD(''a'',3)'); +CALL p3('RPAD(''a'',3, '' '')'); + +CALL p3('REPLACE()'); +CALL p3('REPLACE(''a'',''b'')'); +CALL p3('REPLACE(''a'',''b'',''c'',''d'')'); +CALL p3('REPLACE(''a'',''b'',''c'')'); + +CALL p3('SUBSTR()'); +CALL p3('SUBSTR(''a'',1,2,3)'); +CALL p3('SUBSTR(''a'',1,2)'); +CALL p3('SUBSTR(''a'' FROM 1)'); + +CALL p3('SUBSTRING(''a'',1,2)'); +CALL p3('SUBSTRING(''a'' FROM 1)'); + +CALL p3('TRIM()'); +CALL p3('TRIM(1,2)'); +CALL p3('TRIM(''a'')'); +CALL p3('TRIM(BOTH '' '' FROM ''a'')'); + + +# Deprecated compatibility XXX_ORACLE functions. +# These functions are implemented as simple native functions +# and have no special grammar rules in sql_yacc.yy. +# So they support the qualified syntax automatically, +# which is not absolutely required, but is not harmful. + +CALL p3('CONCAT_OPERATOR_ORACLE(''a'')'); +CALL p3('DECODE_ORACLE(1,1,10)'); +CALL p3('LTRIM_ORACLE(''a'')'); +CALL p3('RTRIM_ORACLE(''a'')'); +CALL p3('LPAD_ORACLE(''a'',3)'); +CALL p3('RPAD_ORACLE(''a'',3)'); +CALL p3('REPLACE_ORACLE(''a'',''b'',''c'')'); +CALL p3('SUBSTR_ORACLE(''a'',1,2)'); + + +# Deprecated compatibility XXX_ORACLE variants for functions +# with a special syntax in sql_yacc.yy. +# These compatibility functions do not support qualified syntax. +# One should use a qualified variant without the _ORACLE suffix instead. + +--error ER_PARSE_ERROR +SELECT oracle_schema.SUBSTR_ORACLE('a' FROM 1 FOR 2); +# Use this instead: +SELECT oracle_schema.SUBSTR('a' FROM 1 FOR 2); + +--error ER_PARSE_ERROR +SELECT oracle_schema.TRIM_ORACLE(LEADING ' ' FROM 'a'); +# Use this instead: +SELECT oracle_schema.TRIM(LEADING ' ' FROM 'a'); + +--error ER_FUNCTION_NOT_DEFINED +SELECT oracle_schema.TRIM_ORACLE('a'); +# Use this instead: +SELECT oracle_schema.TRIM('a'); + + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP PROCEDURE p3; + + +SET sql_mode=''; +CREATE VIEW v1 AS SELECT + concat('a','b'), + decode('1','2'), + ltrim('1'), + rtrim('1'), + lpad('1','2', 3), + rpad('1','2', 3), + replace('1','2','3'), + substr('a',1,2), + trim(both 'a' FROM 'b'); +CREATE TABLE kv (v BLOB); +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +eval LOAD DATA INFILE '$MYSQLD_DATADIR/test/v1.frm' REPLACE INTO TABLE kv; +SELECT v FROM kv WHERE v RLIKE '^(query|view_body_utf8)=' ORDER BY v; +SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME='v1' AND TABLE_SCHEMA='test'; +DROP TABLE kv; +DROP VIEW v1; + +SET sql_mode='ORACLE'; +CREATE VIEW v1 AS SELECT + concat('a','b'), + decode('1',2,3), + ltrim('1'), + rtrim('1'), + lpad('1','2', 3), + rpad('1','2', 3), + replace('1','2','3'), + substr('a',1,2), + trim(both 'a' FROM 'b'); +CREATE TABLE kv (v BLOB); +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +eval LOAD DATA INFILE '$MYSQLD_DATADIR/test/v1.frm' REPLACE INTO TABLE kv; +SELECT v FROM kv WHERE v RLIKE '^(query|view_body_utf8)=' ORDER BY v; +SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME='v1' AND TABLE_SCHEMA='test'; +DROP TABLE kv; +DROP VIEW v1; diff --git a/mysql-test/suite/compat/oracle/t/mysqldump_restore_func_qualified.test b/mysql-test/suite/compat/oracle/t/mysqldump_restore_func_qualified.test new file mode 100644 index 00000000000..36ab3543ea1 --- /dev/null +++ b/mysql-test/suite/compat/oracle/t/mysqldump_restore_func_qualified.test @@ -0,0 +1,50 @@ +# See comments in mysql-test/main/mysqldump_restore.test +--source include/not_embedded.inc + +let $mysqldumpfile = $MYSQLTEST_VARDIR/tmp/mysqldump_func_qualified.sql; + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-27744 LPAD in vcol created in ORACLE mode makes table corrupted in non-ORACLE +--echo # + +SET sql_mode=DEFAULT; +CREATE TABLE t1 ( + a0 VARCHAR(64) NOT NULL DEFAULT LTRIM(now()), + a1 VARCHAR(64) AS (LTRIM(a0)) PERSISTENT, + b0 VARCHAR(64) NOT NULL DEFAULT LPAD(now(),10), + b1 VARCHAR(64) AS (LPAD(b0,10)) PERSISTENT +); +CREATE VIEW v1 AS SELECT + LTRIM(now()) AS a0, + LPAD(now(),10) AS b0; +SET sql_mode=ORACLE; +CREATE TABLE t2 ( + a0 VARCHAR(64) NOT NULL DEFAULT LTRIM(now()), + a1 VARCHAR(64) AS (LTRIM(a0)) PERSISTENT, + b0 VARCHAR(64) NOT NULL DEFAULT LPAD(now(),10), + b1 VARCHAR(64) AS (LPAD(b0,10)) PERSISTENT +); +CREATE VIEW v2 AS SELECT + LTRIM(now()) AS a0, + LPAD(now(),10) AS b0; +--exec $MYSQL_DUMP --skip-extended-insert test --skip-comments --compact t1 t2 v1 v2 +--exec $MYSQL_DUMP --skip-extended-insert test --skip-comments t1 t2 v1 v2 > $mysqldumpfile +DROP TABLE t1,t2; +DROP VIEW v1,v2; +--exec $MYSQL test < $mysqldumpfile +SET sql_mode=DEFAULT; +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +SHOW CREATE VIEW v1; +SHOW CREATE VIEW v2; +--remove_file $mysqldumpfile +DROP TABLE t1,t2; +DROP VIEW v1, v2; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/suite/compat/oracle/t/vcol_innodb.test b/mysql-test/suite/compat/oracle/t/vcol_innodb.test new file mode 100644 index 00000000000..bd923f9bec1 --- /dev/null +++ b/mysql-test/suite/compat/oracle/t/vcol_innodb.test @@ -0,0 +1,47 @@ +--source include/have_innodb.inc + +--echo # +--echo # MDEV-27744 LPAD in vcol created in ORACLE mode makes table corrupted in non-ORACLE +--echo # + +FLUSH TABLES; +SET sql_mode=''; +CREATE TABLE t (d INT,b VARCHAR(1),c CHAR(1),g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL,PRIMARY KEY(b),KEY g(g)) ENGINE=InnoDB; +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t VALUES (0); +SET sql_mode='ORACLE'; +INSERT INTO t SET c=REPEAT (1,0); +--error ER_BAD_FIELD_ERROR +ALTER TABLE t CHANGE COLUMN a b INT; +DELETE FROM t; +SET sql_mode=''; +FLUSH TABLES; +INSERT INTO t SET c='0'; +DROP TABLE t; +FLUSH TABLES; + +SET sql_mode=''; +CREATE TABLE t (a INT(1),d INT(1),b VARCHAR(1),c CHAR(1),vadc INT(1) GENERATED ALWAYS AS ( (a + length (d))) STORED,vbc CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL,vbidxc CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL,PRIMARY KEY(b (1),a,d),KEY d (d),KEY a (a),KEY c_renamed (c (1),b (1)),KEY b (b (1),c (1),a),KEY vbidxc (vbidxc),KEY a_2 (a,vbidxc),KEY vbidxc_2 (vbidxc,d)) DEFAULT CHARSET=latin1 ENGINE=InnoDB; +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t VALUES (0,0,1,0,1,0,1,0,0); +SET SESSION sql_mode='ORACLE'; +INSERT INTO t SET c=REPEAT (1,0); +--error ER_DUP_FIELDNAME +ALTER TABLE t CHANGE COLUMN a b CHAR(1); +DELETE FROM t; +SET SESSION sql_mode=DEFAULT; +DROP TABLE t; + +SET sql_mode=''; +CREATE TABLE t1 (d INT,b VARCHAR(1),c CHAR(1),g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL,PRIMARY KEY(b),KEY g(g)) ENGINE=InnoDB; +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t1 VALUES (0); +SET sql_mode='ORACLE'; +INSERT INTO t1 SET c=REPEAT (1,0); +--error ER_BAD_FIELD_ERROR +ALTER TABLE t1 CHANGE COLUMN a b INT; +DELETE FROM t1; +SET sql_mode=''; +FLUSH TABLES; +INSERT INTO t1 SET c='0'; +DROP TABLE t1; diff --git a/sql/item.h b/sql/item.h index cefd23df0f1..4e756f81c3f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -28,6 +28,7 @@ #include "field.h" /* Derivation */ #include "sql_type.h" #include "sql_time.h" +#include "sql_schema.h" #include "mem_root_array.h" C_MODE_START @@ -1727,7 +1728,8 @@ public: QT_ITEM_IDENT_SKIP_DB_NAMES | QT_ITEM_IDENT_SKIP_TABLE_NAMES | QT_NO_DATA_EXPANSION | - QT_TO_SYSTEM_CHARSET), + QT_TO_SYSTEM_CHARSET | + QT_FOR_FRM), LOWEST_PRECEDENCE); } virtual void print(String *str, enum_query_type query_type); @@ -5301,6 +5303,14 @@ public: return true; return (this->*processor)(arg); } + /* + Built-in schema, e.g. mariadb_schema, oracle_schema, maxdb_schema + */ + virtual const Schema *schema() const + { + // A function does not belong to a built-in schema by default + return NULL; + } /* This method is used for debug purposes to print the name of an item to the debug log. The second use of this method is as diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 8e6ca318d11..2a1fc3f90d3 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -3406,7 +3406,13 @@ void Item_func_case_simple::print(String *str, enum_query_type query_type) void Item_func_decode_oracle::print(String *str, enum_query_type query_type) { - str->append(func_name()); + if (query_type & QT_FOR_FRM) + { + // 10.3 downgrade compatibility for FRM + str->append(STRING_WITH_LEN("decode_oracle")); + } + else + print_sql_mode_qualified_name(str, query_type); str->append('('); args[0]->print(str, query_type); for (uint i= 1, count= when_count() ; i <= count; i++) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 6706c2edf40..9731eb7755d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -2281,7 +2281,8 @@ public: Item_func_decode_oracle(THD *thd, List &list) :Item_func_case_simple(thd, list) { } - const char *func_name() const { return "decode_oracle"; } + const Schema *schema() const { return &oracle_schema_ref; } + const char *func_name() const { return "decode"; } void print(String *str, enum_query_type query_type); bool fix_length_and_dec(); Item *find_item(); diff --git a/sql/item_create.cc b/sql/item_create.cc index 89569412a37..43c869c05ef 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -626,9 +626,6 @@ 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); @@ -2302,9 +2299,7 @@ public: virtual Item *create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { - return thd->variables.sql_mode & MODE_ORACLE ? - create_native_oracle(thd, name, item_list) : - create_native_std(thd, name, item_list); + return create_native_std(thd, name, item_list); } static Create_func_lpad s_singleton; @@ -2780,9 +2775,7 @@ public: virtual Item *create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { - return thd->variables.sql_mode & MODE_ORACLE ? - create_native_oracle(thd, name, item_list) : - create_native_std(thd, name, item_list); + return create_native_std(thd, name, item_list); } static Create_func_rpad s_singleton; @@ -4075,9 +4068,7 @@ Create_func_concat::create_native(THD *thd, const LEX_CSTRING *name, return NULL; } - return thd->variables.sql_mode & MODE_ORACLE ? - new (thd->mem_root) Item_func_concat_operator_oracle(thd, *item_list) : - new (thd->mem_root) Item_func_concat(thd, *item_list); + return new (thd->mem_root) Item_func_concat(thd, *item_list); } Create_func_concat_operator_oracle @@ -5915,10 +5906,7 @@ Create_func_length Create_func_length::s_singleton; Item* Create_func_length::create_1_arg(THD *thd, Item *arg1) { - if (thd->variables.sql_mode & MODE_ORACLE) - return new (thd->mem_root) Item_func_char_length(thd, arg1); - else - return new (thd->mem_root) Item_func_octet_length(thd, arg1); + return new (thd->mem_root) Item_func_octet_length(thd, arg1); } Create_func_octet_length Create_func_octet_length::s_singleton; @@ -6136,7 +6124,7 @@ Create_func_ltrim Create_func_ltrim::s_singleton; Item* Create_func_ltrim::create_1_arg(THD *thd, Item *arg1) { - return Lex_trim(TRIM_LEADING, arg1).make_item_func_trim(thd); + return Lex_trim(TRIM_LEADING, arg1).make_item_func_trim_std(thd); } @@ -6691,7 +6679,7 @@ Create_func_rtrim Create_func_rtrim::s_singleton; Item* Create_func_rtrim::create_1_arg(THD *thd, Item *arg1) { - return Lex_trim(TRIM_TRAILING, arg1).make_item_func_trim(thd); + return Lex_trim(TRIM_TRAILING, arg1).make_item_func_trim_std(thd); } @@ -7621,9 +7609,25 @@ const Native_func_registry func_array[] = }; +const Native_func_registry func_array_oracle_overrides[] = +{ + { { STRING_WITH_LEN("CONCAT") }, BUILDER(Create_func_concat_operator_oracle)}, + { { STRING_WITH_LEN("DECODE") }, BUILDER(Create_func_decode_oracle)}, + { { STRING_WITH_LEN("LENGTH") }, BUILDER(Create_func_char_length)}, + { { STRING_WITH_LEN("LPAD") }, BUILDER(Create_func_lpad_oracle)}, + { { STRING_WITH_LEN("LTRIM") }, BUILDER(Create_func_ltrim_oracle)}, + { { STRING_WITH_LEN("RPAD") }, BUILDER(Create_func_rpad_oracle)}, + { { STRING_WITH_LEN("RTRIM") }, BUILDER(Create_func_rtrim_oracle)}, + + { {0, 0}, NULL} +}; + + const size_t func_array_length= sizeof(func_array) / sizeof(Native_func_registry) - 1; Native_functions_hash native_functions_hash; +Native_functions_hash native_functions_hash_oracle; + extern "C" uchar* get_native_fct_hash_key(const uchar *buff, size_t *length, @@ -7735,13 +7739,19 @@ Native_functions_hash::find(THD *thd, const LEX_CSTRING &name) const int item_create_init() { - return native_functions_hash.init(func_array, array_elements(func_array)); + return + native_functions_hash.init(func_array, array_elements(func_array)) || + native_functions_hash_oracle.init(array_elements(func_array) + + array_elements(func_array_oracle_overrides)) || + native_functions_hash_oracle.append(func_array) || + native_functions_hash_oracle.replace(func_array_oracle_overrides); } void item_create_cleanup() { native_functions_hash.cleanup(); + native_functions_hash_oracle.cleanup(); } diff --git a/sql/item_create.h b/sql/item_create.h index 60a757b95d8..fe4f9cc3c6d 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -220,6 +220,12 @@ public: } bool append(const Native_func_registry array[]); bool remove(const Native_func_registry array[]); + bool replace(const Native_func_registry array[]) + { + DBUG_ENTER("Native_functions_hash::replace"); + remove(array); + DBUG_RETURN(append(array)); + } void cleanup(); /** Find the native function builder associated with a given function name. @@ -231,6 +237,7 @@ public: }; extern MYSQL_PLUGIN_IMPORT Native_functions_hash native_functions_hash; +extern MYSQL_PLUGIN_IMPORT Native_functions_hash native_functions_hash_oracle; extern const Native_func_registry func_array[]; extern const size_t func_array_length; diff --git a/sql/item_func.cc b/sql/item_func.cc index 56bc2e9b29c..31c81eb7463 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -131,6 +131,16 @@ Item_args::Item_args(THD *thd, const Item_args *other) } +void Item_func::wrong_param_count_error(const LEX_CSTRING &schema_name, + const LEX_CSTRING &func_name) +{ + DBUG_ASSERT(schema_name.length); + Database_qualified_name qname(schema_name, func_name); + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), + ErrConvDQName(&qname).ptr()); +} + + void Item_func::sync_with_sum_func_and_with_field(List &list) { List_iterator_fast li(list); @@ -607,13 +617,12 @@ table_map Item_func::not_null_tables() const void Item_func::print(String *str, enum_query_type query_type) { str->append(func_name()); - str->append('('); - print_args(str, 0, query_type); - str->append(')'); + print_args_parenthesized(str, query_type); } -void Item_func::print_args(String *str, uint from, enum_query_type query_type) +void Item_func::print_args(String *str, uint from, + enum_query_type query_type) const { for (uint i=from ; i < arg_count ; i++) { diff --git a/sql/item_func.h b/sql/item_func.h index 76a997c33fb..cdbefb82541 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -56,8 +56,40 @@ protected: bool check_argument_types_can_return_date(uint start, uint end) const; bool check_argument_types_can_return_time(uint start, uint end) const; void print_cast_temporal(String *str, enum_query_type query_type); + + void print_schema_qualified_name(String *to, + const LEX_CSTRING &schema_name, + const char *function_name) const + { + // e.g. oracle_schema.func() + to->append(schema_name); + to->append('.'); + to->append(function_name); + } + + void print_sql_mode_qualified_name(String *to, + enum_query_type query_type, + const char *function_name) const + { + const Schema *func_schema= schema(); + if (!func_schema || func_schema == Schema::find_implied(current_thd)) + to->append(function_name); + else + print_schema_qualified_name(to, func_schema->name(), function_name); + } + + void print_sql_mode_qualified_name(String *to, enum_query_type query_type) + const + { + return print_sql_mode_qualified_name(to, query_type, func_name()); + } + public: + // Print an error message for a builtin-schema qualified function call + static void wrong_param_count_error(const LEX_CSTRING &schema_name, + const LEX_CSTRING &func_name); + table_map not_null_tables_cache; enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC, @@ -179,7 +211,13 @@ public: List &fields, uint flags); virtual void print(String *str, enum_query_type query_type); void print_op(String *str, enum_query_type query_type); - void print_args(String *str, uint from, enum_query_type query_type); + void print_args(String *str, uint from, enum_query_type query_type) const; + void print_args_parenthesized(String *str, enum_query_type query_type) const + { + str->append('('); + print_args(str, 0, query_type); + str->append(')'); + } bool is_null() { update_null_value(); return null_value; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index ae078dbb22f..92d5e196da4 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2170,13 +2170,31 @@ bool Item_func_trim::fix_length_and_dec() void Item_func_trim::print(String *str, enum_query_type query_type) { + LEX_CSTRING suffix= {STRING_WITH_LEN("_oracle")}; if (arg_count == 1) { - Item_func::print(str, query_type); + if (query_type & QT_FOR_FRM) + { + // 10.3 downgrade compatibility for FRM + str->append(func_name()); + if (schema() == &oracle_schema_ref) + str->append(suffix); + } + else + print_sql_mode_qualified_name(str, query_type, func_name()); + print_args_parenthesized(str, query_type); return; } - str->append(Item_func_trim::func_name()); - str->append(func_name_ext()); + + if (query_type & QT_FOR_FRM) + { + // 10.3 downgrade compatibility for FRM + str->append(Item_func_trim::func_name()); + if (schema() == &oracle_schema_ref) + str->append(suffix); + } + else + print_sql_mode_qualified_name(str, query_type, Item_func_trim::func_name()); str->append('('); str->append(mode_name()); str->append(' '); diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index ee2c59c973f..826c7f784af 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -261,6 +261,12 @@ public: Item_func_concat(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} String *val_str(String *); bool fix_length_and_dec(); + const Schema *schema() const { return &mariadb_schema; } + void print(String *str, enum_query_type query_type) + { + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } const char *func_name() const { return "concat"; } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } @@ -281,7 +287,18 @@ public: :Item_func_concat(thd, a, b) { } String *val_str(String *); - const char *func_name() const { return "concat_operator_oracle"; } + const Schema *schema() const { return &oracle_schema_ref; } + void print(String *str, enum_query_type query_type) + { + if (query_type & QT_FOR_FRM) + { + // 10.3 downgrade compatibility for FRM + str->append(STRING_WITH_LEN("concat_operator_oracle")); + } + else + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } Item *get_copy(THD *thd) { return get_item_copy(thd, this); @@ -342,6 +359,12 @@ public: String *val_str(String *to) { return val_str_internal(to, NULL); }; bool fix_length_and_dec(); String *val_str_internal(String *str, String *empty_string_for_null); + const Schema *schema() const { return &mariadb_schema; } + void print(String *str, enum_query_type query_type) + { + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } const char *func_name() const { return "replace"; } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } @@ -355,7 +378,18 @@ public: Item_func_replace_oracle(THD *thd, Item *org, Item *find, Item *replace): Item_func_replace(thd, org, find, replace) {} String *val_str(String *to) { return val_str_internal(to, &tmp_emtpystr); }; - const char *func_name() const { return "replace_oracle"; } + const Schema *schema() const { return &oracle_schema_ref; } + void print(String *str, enum_query_type query_type) + { + if (query_type & QT_FOR_FRM) + { + // 10.3 downgrade compatibility for FRM + str->append(STRING_WITH_LEN("replace_oracle")); + } + else + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } }; @@ -492,8 +526,16 @@ public: Item_func_substr(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} Item_func_substr(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {} + Item_func_substr(THD *thd, List &list) + :Item_str_func(thd, list) {} String *val_str(String *); bool fix_length_and_dec(); + const Schema *schema() const { return &mariadb_schema; } + void print(String *str, enum_query_type query_type) + { + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } const char *func_name() const { return "substr"; } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } @@ -511,13 +553,26 @@ public: Item_func_substr(thd, a, b) {} Item_func_substr_oracle(THD *thd, Item *a, Item *b, Item *c): Item_func_substr(thd, a, b, c) {} + Item_func_substr_oracle(THD *thd, List &list) + :Item_func_substr(thd, list) {} bool fix_length_and_dec() { bool res= Item_func_substr::fix_length_and_dec(); maybe_null= true; return res; } - const char *func_name() const { return "substr_oracle"; } + const Schema *schema() const { return &oracle_schema_ref; } + void print(String *str, enum_query_type query_type) + { + if (query_type & QT_FOR_FRM) + { + // 10.3 downgrade compatibility for FRM + str->append(STRING_WITH_LEN("substr_oracle")); + } + else + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } }; @@ -560,13 +615,13 @@ protected: { return trimmed_value(res, 0, res->length()); } - virtual const char *func_name_ext() const { return ""; } public: Item_func_trim(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} Item_func_trim(THD *thd, Item *a): Item_str_func(thd, a) {} Sql_mode_dependency value_depends_on_sql_mode() const; String *val_str(String *); bool fix_length_and_dec(); + const Schema *schema() const { return &mariadb_schema; } const char *func_name() const { return "trim"; } void print(String *str, enum_query_type query_type); virtual const char *mode_name() const { return "both"; } @@ -580,12 +635,11 @@ class Item_func_trim_oracle :public Item_func_trim protected: String *make_empty_result(String *str) { null_value= 1; return NULL; } - const char *func_name_ext() const { return "_oracle"; } public: Item_func_trim_oracle(THD *thd, Item *a, Item *b): Item_func_trim(thd, a, b) {} Item_func_trim_oracle(THD *thd, Item *a): Item_func_trim(thd, a) {} - const char *func_name() const { return "trim_oracle"; } + const Schema *schema() const { return &oracle_schema_ref; } bool fix_length_and_dec() { bool res= Item_func_trim::fix_length_and_dec(); @@ -607,6 +661,7 @@ public: return Item_func::value_depends_on_sql_mode(); } String *val_str(String *); + const Schema *schema() const { return &mariadb_schema; } const char *func_name() const { return "ltrim"; } const char *mode_name() const { return "leading"; } Item *get_copy(THD *thd) @@ -619,12 +674,11 @@ class Item_func_ltrim_oracle :public Item_func_ltrim protected: String *make_empty_result(String *str) { null_value= 1; return NULL; } - const char *func_name_ext() const { return "_oracle"; } public: Item_func_ltrim_oracle(THD *thd, Item *a, Item *b): Item_func_ltrim(thd, a, b) {} Item_func_ltrim_oracle(THD *thd, Item *a): Item_func_ltrim(thd, a) {} - const char *func_name() const { return "ltrim_oracle"; } + const Schema *schema() const { return &oracle_schema_ref; } bool fix_length_and_dec() { bool res= Item_func_ltrim::fix_length_and_dec(); @@ -642,6 +696,7 @@ public: Item_func_rtrim(THD *thd, Item *a, Item *b): Item_func_trim(thd, a, b) {} Item_func_rtrim(THD *thd, Item *a): Item_func_trim(thd, a) {} String *val_str(String *); + const Schema *schema() const { return &mariadb_schema; } const char *func_name() const { return "rtrim"; } const char *mode_name() const { return "trailing"; } Item *get_copy(THD *thd) @@ -654,12 +709,11 @@ class Item_func_rtrim_oracle :public Item_func_rtrim protected: String *make_empty_result(String *str) { null_value= 1; return NULL; } - const char *func_name_ext() const { return "_oracle"; } public: Item_func_rtrim_oracle(THD *thd, Item *a, Item *b): Item_func_rtrim(thd, a, b) {} Item_func_rtrim_oracle(THD *thd, Item *a): Item_func_rtrim(thd, a) {} - const char *func_name() const { return "rtrim_oracle"; } + const Schema *schema() const { return &oracle_schema_ref; } bool fix_length_and_dec() { bool res= Item_func_rtrim::fix_length_and_dec(); @@ -821,6 +875,12 @@ class Item_func_decode :public Item_func_encode { public: Item_func_decode(THD *thd, Item *a, Item *seed_arg): Item_func_encode(thd, a, seed_arg) {} + const Schema *schema() const { return &mariadb_schema; } + void print(String *str, enum_query_type query_type) + { + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } const char *func_name() const { return "decode"; } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } @@ -1126,6 +1186,8 @@ public: Item_str_func(thd, arg1, arg2, arg3) {} Item_func_pad(THD *thd, Item *arg1, Item *arg2): Item_str_func(thd, arg1, arg2) {} + Item_func_pad(THD *thd, List &list): + Item_str_func(thd,list) {} bool fix_length_and_dec(); }; @@ -1137,7 +1199,15 @@ public: Item_func_pad(thd, arg1, arg2, arg3) {} Item_func_rpad(THD *thd, Item *arg1, Item *arg2): Item_func_pad(thd, arg1, arg2) {} + Item_func_rpad(THD *thd, List &list): + Item_func_pad(thd,list) {} String *val_str(String *); + const Schema *schema() const { return &mariadb_schema; } + void print(String *str, enum_query_type query_type) + { + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } const char *func_name() const { return "rpad"; } Sql_mode_dependency value_depends_on_sql_mode() const; Item *get_copy(THD *thd) @@ -1154,13 +1224,26 @@ public: Item_func_rpad(thd, arg1, arg2, arg3) {} Item_func_rpad_oracle(THD *thd, Item *arg1, Item *arg2): Item_func_rpad(thd, arg1, arg2) {} + Item_func_rpad_oracle(THD *thd, List &list): + Item_func_rpad(thd,list) {} bool fix_length_and_dec() { bool res= Item_func_rpad::fix_length_and_dec(); maybe_null= true; return res; } - const char *func_name() const { return "rpad_oracle"; } + const Schema *schema() const { return &oracle_schema_ref; } + void print(String *str, enum_query_type query_type) + { + if (query_type & QT_FOR_FRM) + { + // 10.3 downgrade compatibility for FRM + str->append(STRING_WITH_LEN("rpad_oracle")); + } + else + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } }; @@ -1173,7 +1256,15 @@ public: Item_func_pad(thd, arg1, arg2, arg3) {} Item_func_lpad(THD *thd, Item *arg1, Item *arg2): Item_func_pad(thd, arg1, arg2) {} + Item_func_lpad(THD *thd, List &list): + Item_func_pad(thd,list) {} String *val_str(String *); + const Schema *schema() const { return &mariadb_schema; } + void print(String *str, enum_query_type query_type) + { + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } const char *func_name() const { return "lpad"; } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } @@ -1189,13 +1280,26 @@ public: Item_func_lpad(thd, arg1, arg2, arg3) {} Item_func_lpad_oracle(THD *thd, Item *arg1, Item *arg2): Item_func_lpad(thd, arg1, arg2) {} + Item_func_lpad_oracle(THD *thd, List &list): + Item_func_lpad(thd,list) {} bool fix_length_and_dec() { bool res= Item_func_lpad::fix_length_and_dec(); maybe_null= true; return res; } - const char *func_name() const { return "lpad_oracle"; } + const Schema *schema() const { return &oracle_schema_ref; } + void print(String *str, enum_query_type query_type) + { + if (query_type & QT_FOR_FRM) + { + // 10.3 downgrade compatibility for FRM + str->append(STRING_WITH_LEN("lpad_oracle")); + } + else + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } }; diff --git a/sql/mysqld.h b/sql/mysqld.h index f521ea23638..90535e3deb2 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -757,6 +757,10 @@ enum enum_query_type QT_NO_DATA_EXPANSION= (1 << 9), // Remove wrappers added for TVC when creating or showing view QT_NO_WRAPPERS_FOR_TVC_IN_VIEW= (1 << 11), + + /// Print for FRM file. Focus on parse-back. + /// e.g. VIEW expressions and virtual column expressions + QT_FOR_FRM= (1 << 12) }; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 79fb86fe14b..4b0a5da2ad5 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -942,7 +942,7 @@ bool is_lex_native_function(const LEX_CSTRING *name) bool is_native_function(THD *thd, const LEX_CSTRING *name) { - if (native_functions_hash.find(thd, *name)) + if (mariadb_schema.find_native_function_builder(thd, *name)) return true; if (is_lex_native_function(name)) @@ -1618,7 +1618,18 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd) if (lex->parsing_options.lookup_keywords_after_qualifier) next_state= MY_LEX_IDENT_OR_KEYWORD; else - next_state= MY_LEX_IDENT_START; // Next is ident (not keyword) + { + /* + Next is: + - A qualified func with a special syntax: + mariadb_schema.REPLACE('a','b','c') + mariadb_schema.SUSTRING('a',1,2) + mariadb_schema.TRIM('a') + - Or an identifier otherwise. No keyword lookup is done, + all keywords are treated as identifiers. + */ + next_state= MY_LEX_IDENT_OR_QUALIFIED_SPECIAL_FUNC; + } if (!ident_map[(uchar) yyPeek()]) // Probably ` or " next_state= MY_LEX_START; return((int) c); @@ -2062,7 +2073,12 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd) We should now be able to handle: [(global | local | session) .]variable_name */ - return scan_ident_sysvar(thd, &yylval->ident_cli); + return scan_ident_common(thd, &yylval->ident_cli, + GENERAL_KEYWORD_OR_FUNC_LPAREN); + + case MY_LEX_IDENT_OR_QUALIFIED_SPECIAL_FUNC: + return scan_ident_common(thd, &yylval->ident_cli, + QUALIFIED_SPECIAL_FUNC_LPAREN); } } } @@ -2084,7 +2100,64 @@ bool Lex_input_stream::get_7bit_or_8bit_ident(THD *thd, uchar *last_char) } -int Lex_input_stream::scan_ident_sysvar(THD *thd, Lex_ident_cli_st *str) +/* + Resolve special SQL functions that have a qualified syntax in sql_yacc.yy. + These functions are not listed in the native function registry + because of a special syntax, or a reserved keyword: + + mariadb_schema.SUBSTRING('a' FROM 1 FOR 2) -- Special syntax + mariadb_schema.TRIM(BOTH ' ' FROM 'a') -- Special syntax + mariadb_schema.REPLACE('a','b','c') -- Verb keyword +*/ + +int Lex_input_stream::find_keyword_qualified_special_func(Lex_ident_cli_st *str, + uint length) const +{ + /* + There are many other special functions, see the following grammar rules: + function_call_keyword + function_call_nonkeyword + Here we resolve only those that have a qualified syntax to handle + different behavior in different @@sql_mode settings. + + Other special functions do not work in qualified context: + SELECT mariadb_schema.year(now()); -- Function year is not defined + SELECT mariadb_schema.now(); -- Function now is not defined + + We don't resolve TRIM_ORACLE here, because it does not have + a qualified syntax yet. Search for "trim_operands" in sql_yacc.yy + to find more comments. + */ + static LEX_CSTRING funcs[]= + { + {STRING_WITH_LEN("SUBSTRING")}, + {STRING_WITH_LEN("SUBSTR")}, + {STRING_WITH_LEN("TRIM")}, + {STRING_WITH_LEN("REPLACE")} + }; + + int tokval= find_keyword(str, length, true); + if (!tokval) + return 0; + for (size_t i= 0; i < array_elements(funcs); i++) + { + CHARSET_INFO *cs= system_charset_info; + /* + Check length equality to avoid non-ASCII variants + compared as equal to ASCII variants. + */ + if (length == funcs[i].length && + !cs->coll->strnncollsp(cs, + (const uchar *) m_tok_start, length, + (const uchar *) funcs[i].str, funcs[i].length)) + return tokval; + } + return 0; +} + + +int Lex_input_stream::scan_ident_common(THD *thd, Lex_ident_cli_st *str, + Ident_mode mode) { uchar last_char; uint length; @@ -2098,10 +2171,41 @@ int Lex_input_stream::scan_ident_sysvar(THD *thd, Lex_ident_cli_st *str) next_state= MY_LEX_IDENT_SEP; if (!(length= yyLength())) return ABORT_SYM; // Names must be nonempty. - if ((tokval= find_keyword(str, length, 0))) - { - yyUnget(); // Put back 'c' - return tokval; // Was keyword + + switch (mode) { + case GENERAL_KEYWORD_OR_FUNC_LPAREN: + /* + We can come here inside a system variable after "@@", + e.g. @@global.character_set_client. + We resolve all general purpose keywords here. + + We can come here when LEX::parsing_options.lookup_keywords_after_qualifier + is true, i.e. within the "field_spec" Bison rule. + We need to resolve functions that have special rules inside sql_yacc.yy, + such as SUBSTR, REPLACE, TRIM, to make this work: + c2 varchar(4) GENERATED ALWAYS AS (mariadb_schema.substr(c1,1,4)) + */ + if ((tokval= find_keyword(str, length, last_char == '('))) + { + yyUnget(); // Put back 'c' + return tokval; // Was keyword + } + break; + case QUALIFIED_SPECIAL_FUNC_LPAREN: + /* + We come here after '.' in various contexts: + SELECT @@global.character_set_client; + SELECT t1.a FROM t1; + SELECT test.f1() FROM t1; + SELECT mariadb_schema.trim('a'); + */ + if (last_char == '(' && + (tokval= find_keyword_qualified_special_func(str, length))) + { + yyUnget(); // Put back 'c' + return tokval; // Was keyword + } + break; } yyUnget(); // ptr points now after last token char @@ -8644,6 +8748,136 @@ bool LEX::add_grant_command(THD *thd, enum_sql_command sql_command_arg, } +const Schema * +LEX::find_func_schema_by_name_or_error(const Lex_ident_sys &schema, + const Lex_ident_sys &func) +{ + Schema *res= Schema::find_by_name(schema); + if (res) + return res; + Database_qualified_name qname(schema, func); + my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), ErrConvDQName(&qname).ptr()); + return NULL; +} + + +Item *LEX::make_item_func_substr(THD *thd, + const Lex_ident_cli_st &schema_name_cli, + const Lex_ident_cli_st &func_name_cli, + const Lex_substring_spec_st &spec) +{ + Lex_ident_sys schema_name(thd, &schema_name_cli); + Lex_ident_sys func_name(thd, &func_name_cli); + if (schema_name.is_null() || func_name.is_null()) + return NULL; // EOM + const Schema *schema= find_func_schema_by_name_or_error(schema_name, + func_name); + return schema ? schema->make_item_func_substr(thd, spec) : NULL; +} + + +Item *LEX::make_item_func_substr(THD *thd, + const Lex_ident_cli_st &schema_name_cli, + const Lex_ident_cli_st &func_name_cli, + List *item_list) +{ + Lex_ident_sys schema_name(thd, &schema_name_cli); + Lex_ident_sys func_name(thd, &func_name_cli); + if (schema_name.is_null() || func_name.is_null()) + return NULL; // EOM + Schema *schema; + if (item_list && + (item_list->elements == 2 || item_list->elements == 3) && + (schema= Schema::find_by_name(schema_name))) + { + Item_args args(thd, *item_list); + Lex_substring_spec_st spec= + Lex_substring_spec_st::init(args.arguments()[0], + args.arguments()[1], + item_list->elements == 3 ? + args.arguments()[2] : NULL); + return schema->make_item_func_substr(thd, spec); + } + return make_item_func_call_generic(thd, schema_name, func_name, item_list); +} + + +Item *LEX::make_item_func_replace(THD *thd, + const Lex_ident_cli_st &schema_name_cli, + const Lex_ident_cli_st &func_name_cli, + Item *org, + Item *find, + Item *replace) +{ + Lex_ident_sys schema_name(thd, &schema_name_cli); + Lex_ident_sys func_name(thd, &func_name_cli); + if (schema_name.is_null() || func_name.is_null()) + return NULL; // EOM + const Schema *schema= find_func_schema_by_name_or_error(schema_name, + func_name); + return schema ? schema->make_item_func_replace(thd, org, find, replace) : + NULL; +} + + +Item *LEX::make_item_func_replace(THD *thd, + const Lex_ident_cli_st &schema_name_cli, + const Lex_ident_cli_st &func_name_cli, + List *item_list) +{ + Lex_ident_sys schema_name(thd, &schema_name_cli); + Lex_ident_sys func_name(thd, &func_name_cli); + if (schema_name.is_null() || func_name.is_null()) + return NULL; // EOM + const Schema *schema; + if (item_list && item_list->elements == 3 && + (schema= Schema::find_by_name(schema_name))) + { + Item_args args(thd, *item_list); + return schema->make_item_func_replace(thd, args.arguments()[0], + args.arguments()[1], + args.arguments()[2]); + } + return make_item_func_call_generic(thd, schema_name, func_name, item_list); +} + + +Item *LEX::make_item_func_trim(THD *thd, + const Lex_ident_cli_st &schema_name_cli, + const Lex_ident_cli_st &func_name_cli, + const Lex_trim_st &spec) +{ + Lex_ident_sys schema_name(thd, &schema_name_cli); + Lex_ident_sys func_name(thd, &func_name_cli); + if (schema_name.is_null() || func_name.is_null()) + return NULL; // EOM + const Schema *schema= find_func_schema_by_name_or_error(schema_name, + func_name); + return schema ? schema->make_item_func_trim(thd, spec) : NULL; +} + + +Item *LEX::make_item_func_trim(THD *thd, + const Lex_ident_cli_st &schema_name_cli, + const Lex_ident_cli_st &func_name_cli, + List *item_list) +{ + Lex_ident_sys schema_name(thd, &schema_name_cli); + Lex_ident_sys func_name(thd, &func_name_cli); + if (schema_name.is_null() || func_name.is_null()) + return NULL; // EOM + const Schema *schema; + if (item_list && item_list->elements == 1 && + (schema= Schema::find_by_name(schema_name))) + { + Item_args args(thd, *item_list); + Lex_trim spec(TRIM_BOTH, args.arguments()[0]); + return schema->make_item_func_trim(thd, spec); + } + return make_item_func_call_generic(thd, schema_name, func_name, item_list); +} + + bool SELECT_LEX::vers_push_field(THD *thd, TABLE_LIST *table, const LEX_CSTRING field_name) { @@ -8722,16 +8956,10 @@ Item *Lex_trim_st::make_item_func_trim_oracle(THD *thd) const } -Item *Lex_trim_st::make_item_func_trim(THD *thd) const -{ - return (thd->variables.sql_mode & MODE_ORACLE) ? - make_item_func_trim_oracle(thd) : - make_item_func_trim_std(thd); -} - - -Item *LEX::make_item_func_call_generic(THD *thd, Lex_ident_cli_st *cdb, - Lex_ident_cli_st *cname, List *args) +Item *LEX::make_item_func_call_generic(THD *thd, + const Lex_ident_cli_st *cdb, + const Lex_ident_cli_st *cname, + List *args) { Lex_ident_sys db(thd, cdb), name(thd, cname); if (db.is_null() || name.is_null()) @@ -8758,6 +8986,19 @@ Item *LEX::make_item_func_call_generic(THD *thd, Lex_ident_cli_st *cdb, if (check_routine_name(&name)) return NULL; + return make_item_func_call_generic(thd, db, name, args); +} + + +Item *LEX::make_item_func_call_generic(THD *thd, + const Lex_ident_sys &db, + const Lex_ident_sys &name, + List *args) +{ + const Schema *schema= Schema::find_by_name(db); + if (schema) + return schema->make_item_func_call_native(thd, name, args); + Create_qfunc *builder= find_qualified_function_builder(thd); DBUG_ASSERT(builder); return builder->create_with_db(thd, &db, &name, true, args); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 6bcfd1bb5a9..97be0571903 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2407,6 +2407,15 @@ public: void reduce_digest_token(uint token_left, uint token_right); private: + + enum Ident_mode + { + GENERAL_KEYWORD_OR_FUNC_LPAREN, + QUALIFIED_SPECIAL_FUNC_LPAREN + }; + + int scan_ident_common(THD *thd, Lex_ident_cli_st *str, Ident_mode mode); + /** Set the echo mode. @@ -2733,8 +2742,8 @@ private: bool consume_comment(int remaining_recursions_permitted); int lex_one_token(union YYSTYPE *yylval, THD *thd); int find_keyword(Lex_ident_cli_st *str, uint len, bool function) const; + int find_keyword_qualified_special_func(Lex_ident_cli_st *str, uint len) const; LEX_CSTRING get_token(uint skip, uint length); - int scan_ident_sysvar(THD *thd, Lex_ident_cli_st *str); int scan_ident_start(THD *thd, Lex_ident_cli_st *str); int scan_ident_middle(THD *thd, Lex_ident_cli_st *str, CHARSET_INFO **cs, my_lex_states *); @@ -4045,8 +4054,41 @@ public: Item *create_item_query_expression(THD *thd, st_select_lex_unit *unit); - Item *make_item_func_call_generic(THD *thd, Lex_ident_cli_st *db, - Lex_ident_cli_st *name, List *args); + static const Schema * + find_func_schema_by_name_or_error(const Lex_ident_sys &schema_name, + const Lex_ident_sys &func_name); + Item *make_item_func_replace(THD *thd, + const Lex_ident_cli_st &schema_name, + const Lex_ident_cli_st &func_name, + Item *org, Item *find, Item *replace); + Item *make_item_func_replace(THD *thd, + const Lex_ident_cli_st &schema_name, + const Lex_ident_cli_st &func_name, + List *args); + Item *make_item_func_substr(THD *thd, + const Lex_ident_cli_st &schema_name, + const Lex_ident_cli_st &func_name, + const Lex_substring_spec_st &spec); + Item *make_item_func_substr(THD *thd, + const Lex_ident_cli_st &schema_name, + const Lex_ident_cli_st &func_name, + List *args); + Item *make_item_func_trim(THD *thd, + const Lex_ident_cli_st &schema_name, + const Lex_ident_cli_st &func_name, + const Lex_trim_st &spec); + Item *make_item_func_trim(THD *thd, + const Lex_ident_cli_st &schema_name, + const Lex_ident_cli_st &func_name, + List *args); + Item *make_item_func_call_generic(THD *thd, + const Lex_ident_cli_st *db, + const Lex_ident_cli_st *name, + List *args); + Item *make_item_func_call_generic(THD *thd, + const Lex_ident_sys &db, + const Lex_ident_sys &name, + List *args); Item *make_item_func_call_generic(THD *thd, Lex_ident_cli_st *db, Lex_ident_cli_st *pkg, diff --git a/sql/sql_schema.cc b/sql/sql_schema.cc index f08204d272d..7a6c0c99398 100644 --- a/sql/sql_schema.cc +++ b/sql/sql_schema.cc @@ -33,6 +33,12 @@ public: return src; } + Create_func *find_native_function_builder(THD *thd, const LEX_CSTRING &name) + const + { + return native_functions_hash_oracle.find(thd, name); + } + Item *make_item_func_replace(THD *thd, Item *subj, Item *find, @@ -64,6 +70,7 @@ Schema mariadb_schema(Lex_cstring(STRING_WITH_LEN("mariadb_schema"))); Schema_oracle oracle_schema(Lex_cstring(STRING_WITH_LEN("oracle_schema"))); Schema_maxdb maxdb_schema(Lex_cstring(STRING_WITH_LEN("maxdb_schema"))); +const Schema &oracle_schema_ref= oracle_schema; Schema *Schema::find_by_name(const LEX_CSTRING &name) { @@ -88,6 +95,26 @@ Schema *Schema::find_implied(THD *thd) } +Create_func * +Schema::find_native_function_builder(THD *thd, const LEX_CSTRING &name) const +{ + return native_functions_hash.find(thd, name); +} + + +Item *Schema::make_item_func_call_native(THD *thd, + const Lex_ident_sys &name, + List *args) const +{ + Create_func *builder= find_native_function_builder(thd, name); + if (builder) + return builder->create_func(thd, &name, args); + my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), name.str); + return NULL; +} + + + Item *Schema::make_item_func_replace(THD *thd, Item *subj, Item *find, diff --git a/sql/sql_schema.h b/sql/sql_schema.h index 1174bc7a83f..2c52646f2ea 100644 --- a/sql/sql_schema.h +++ b/sql/sql_schema.h @@ -19,6 +19,9 @@ #include "mysqld.h" #include "lex_string.h" +class Lex_ident_sys; +class Create_func; + class Schema { LEX_CSTRING m_name; @@ -34,6 +37,24 @@ public: return src; } + /** + Find a native function builder, return an error if not found, + build an Item otherwise. + */ + Item *make_item_func_call_native(THD *thd, + const Lex_ident_sys &name, + List *args) const; + + /** + Find the native function builder associated with a given function name. + @param thd The current thread + @param name The native function name + @return The native function builder associated with the name, or NULL + */ + virtual Create_func *find_native_function_builder(THD *thd, + const LEX_CSTRING &name) + const; + // Builders for native SQL function with a special syntax in sql_yacc.yy virtual Item *make_item_func_replace(THD *thd, Item *subj, @@ -77,5 +98,6 @@ public: extern Schema mariadb_schema; +extern const Schema &oracle_schema_ref; #endif // SQL_SCHEMA_H_INCLUDED diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 6eaf739a417..3651bad7067 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -954,7 +954,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, { Sql_mode_save_for_frm_handling sql_mode_save(thd); - lex->unit.print(&view_query, enum_query_type(QT_VIEW_INTERNAL | + lex->unit.print(&view_query, enum_query_type(QT_FOR_FRM | + QT_VIEW_INTERNAL | QT_ITEM_ORIGINAL_FUNC_NULLIF | QT_NO_WRAPPERS_FOR_TVC_IN_VIEW)); lex->unit.print(&is_query, enum_query_type(QT_TO_SYSTEM_CHARSET | diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 048741b6ca1..0b893c952bd 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2174,8 +2174,17 @@ END_OF_INPUT %type sp_param_name sp_param_name_and_type %type sp_for_loop_index_and_bounds %type sp_for_loop_bounds -%type trim_operands -%type substring_operands + +%type + trim_operands + trim_operands_regular + trim_operands_special + +%type + substring_operands + substring_operands_regular + substring_operands_special + %type opt_sp_for_loop_direction %type sp_opt_inout %type index_hint_type @@ -10531,8 +10540,16 @@ explicit_cursor_attr: trim_operands: + trim_operands_regular + | trim_operands_special + ; + +trim_operands_regular: expr { $$.set(TRIM_BOTH, $1); } - | LEADING expr FROM expr { $$.set(TRIM_LEADING, $2, $4); } + ; + +trim_operands_special: + LEADING expr FROM expr { $$.set(TRIM_LEADING, $2, $4); } | TRAILING expr FROM expr { $$.set(TRIM_TRAILING, $2, $4); } | BOTH expr FROM expr { $$.set(TRIM_BOTH, $2, $4); } | LEADING FROM expr { $$.set(TRIM_LEADING, $3); } @@ -10941,6 +10958,11 @@ function_call_keyword: ; substring_operands: + substring_operands_regular + | substring_operands_special + ; + +substring_operands_regular: expr ',' expr ',' expr { $$= Lex_substring_spec_st::init($1, $3, $5); @@ -10949,7 +10971,10 @@ substring_operands: { $$= Lex_substring_spec_st::init($1, $3); } - | expr FROM expr FOR_SYM expr + ; + +substring_operands_special: + expr FROM expr FOR_SYM expr { $$= Lex_substring_spec_st::init($1, $3, $5); } @@ -11470,7 +11495,8 @@ function_call_generic: This will be revised with WL#2128 (SQL PATH) */ - builder= native_functions_hash.find(thd, $1); + builder= Schema::find_implied(thd)-> + find_native_function_builder(thd, $1); if (builder) { item= builder->create_func(thd, &$1, $4); @@ -11512,6 +11538,43 @@ function_call_generic: if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, &$5, $7)))) MYSQL_YYABORT; } + | ident_cli '.' REPLACE '(' opt_expr_list ')' + { + if (unlikely(!($$= Lex->make_item_func_replace(thd, $1, $3, $5)))) + MYSQL_YYABORT; + } + | ident_cli '.' SUBSTRING '(' opt_expr_list ')' + { + if (unlikely(!($$= Lex->make_item_func_substr(thd, $1, $3, $5)))) + MYSQL_YYABORT; + } + | ident_cli '.' SUBSTRING '(' substring_operands_special ')' + { + if (unlikely(!($$= Lex->make_item_func_substr(thd, $1, $3, $5)))) + MYSQL_YYABORT; + } + | ident_cli '.' TRIM '(' opt_expr_list ')' + { + if (unlikely(!($$= Lex->make_item_func_trim(thd, $1, $3, $5)))) + MYSQL_YYABORT; + } + | ident_cli '.' TRIM '(' trim_operands_special ')' + { + if (unlikely(!($$= Lex->make_item_func_trim(thd, $1, $3, $5)))) + MYSQL_YYABORT; + } + /* + We don't add a qualified syntax for TRIM_ORACLE here, + as this syntax is not absolutely required: + SELECT mariadb_schema.TRIM_ORACLE(..); + What absolutely required is only: + SELECT mariadb_schema.TRIM(..); + Adding a qualified syntax for TRIM_ORACLE would be tricky because + it is a non-reserved keyword. To avoid new shift/reduce conflicts + it would require grammar changes, like introducing a new rule + ident_step2_cli (which would include everything that ident_cli + includes but TRIM_ORACLE). + */ ; fulltext_options: diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 325ca4ccdc6..10fd486dc16 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -1675,8 +1675,17 @@ END_OF_INPUT %type sp_param_name sp_param_name_and_type %type sp_for_loop_index_and_bounds %type sp_for_loop_bounds -%type trim_operands -%type substring_operands + +%type + trim_operands + trim_operands_regular + trim_operands_special + +%type + substring_operands + substring_operands_regular + substring_operands_special + %type opt_sp_for_loop_direction %type sp_opt_inout %type index_hint_type @@ -10646,8 +10655,16 @@ explicit_cursor_attr: trim_operands: + trim_operands_regular + | trim_operands_special + ; + +trim_operands_regular: expr { $$.set(TRIM_BOTH, $1); } - | LEADING expr FROM expr { $$.set(TRIM_LEADING, $2, $4); } + ; + +trim_operands_special: + LEADING expr FROM expr { $$.set(TRIM_LEADING, $2, $4); } | TRAILING expr FROM expr { $$.set(TRIM_TRAILING, $2, $4); } | BOTH expr FROM expr { $$.set(TRIM_BOTH, $2, $4); } | LEADING FROM expr { $$.set(TRIM_LEADING, $3); } @@ -11056,6 +11073,11 @@ function_call_keyword: ; substring_operands: + substring_operands_regular + | substring_operands_special + ; + +substring_operands_regular: expr ',' expr ',' expr { $$= Lex_substring_spec_st::init($1, $3, $5); @@ -11064,7 +11086,10 @@ substring_operands: { $$= Lex_substring_spec_st::init($1, $3); } - | expr FROM expr FOR_SYM expr + ; + +substring_operands_special: + expr FROM expr FOR_SYM expr { $$= Lex_substring_spec_st::init($1, $3, $5); } @@ -11585,7 +11610,8 @@ function_call_generic: This will be revised with WL#2128 (SQL PATH) */ - builder= native_functions_hash.find(thd, $1); + builder= Schema::find_implied(thd)-> + find_native_function_builder(thd, $1); if (builder) { item= builder->create_func(thd, &$1, $4); @@ -11627,6 +11653,31 @@ function_call_generic: if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, &$5, $7)))) MYSQL_YYABORT; } + | ident_cli '.' REPLACE '(' opt_expr_list ')' + { + if (unlikely(!($$= Lex->make_item_func_replace(thd, $1, $3, $5)))) + MYSQL_YYABORT; + } + | ident_cli '.' SUBSTRING '(' opt_expr_list ')' + { + if (unlikely(!($$= Lex->make_item_func_substr(thd, $1, $3, $5)))) + MYSQL_YYABORT; + } + | ident_cli '.' SUBSTRING '(' substring_operands_special ')' + { + if (unlikely(!($$= Lex->make_item_func_substr(thd, $1, $3, $5)))) + MYSQL_YYABORT; + } + | ident_cli '.' TRIM '(' opt_expr_list ')' + { + if (unlikely(!($$= Lex->make_item_func_trim(thd, $1, $3, $5)))) + MYSQL_YYABORT; + } + | ident_cli '.' TRIM '(' trim_operands_special ')' + { + if (unlikely(!($$= Lex->make_item_func_trim(thd, $1, $3, $5)))) + MYSQL_YYABORT; + } ; fulltext_options: diff --git a/sql/structs.h b/sql/structs.h index 7d8aed43786..2412c581b25 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -33,6 +33,7 @@ struct TABLE; class Type_handler; class Field; class Index_statistics; +struct Lex_ident_cli_st; class THD; @@ -776,12 +777,6 @@ public: } Item *make_item_func_trim_std(THD *thd) const; Item *make_item_func_trim_oracle(THD *thd) const; - /* - This method is still used to handle LTRIM and RTRIM, - while the special syntax TRIM(... BOTH|LEADING|TRAILING) - is now handled by Schema::make_item_func_trim(). - */ - Item *make_item_func_trim(THD *thd) const; }; From 169774746112228acde0dcf9fe7861866bd0eacc Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Tue, 7 Nov 2023 12:20:02 +0300 Subject: [PATCH 213/477] 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 214/477] 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 215/477] 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 1f7ab85644675718518fa64084fb11eb3327d5b9 Mon Sep 17 00:00:00 2001 From: Dave Gosselin Date: Tue, 31 Oct 2023 14:17:24 -0400 Subject: [PATCH 216/477] MDEV-31116 SIGSEGV in test_if_skip_sort_order|JOIN::optimize_stage2 test_if_skip_sort_order() should check that the 'select' pointer (=tab->select) is not NULL before dereferencing it when invoking the test_quick_select method. The check was erroneously removed by: 1c88ac60cf5 Simple cleanup of removing QQ comments from sql_select.cc --- mysql-test/main/order_by_innodb.result | 10 ++++++++++ mysql-test/main/order_by_innodb.test | 9 +++++++++ sql/sql_select.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/order_by_innodb.result b/mysql-test/main/order_by_innodb.result index ad4acad3319..79938715539 100644 --- a/mysql-test/main/order_by_innodb.result +++ b/mysql-test/main/order_by_innodb.result @@ -296,3 +296,13 @@ a b c 6 2 26 6 3 36 drop table t1; +# +# MDEV-31116: SIGSEGV in test_if_skip_sort_order|JOIN::optimize_stage2 +# +CREATE TABLE t1 (a BINARY (2),b BINARY (1),KEY(a)) ENGINE=innodb; +INSERT INTO t1 select 'ab', NULL from seq_1_to_14; +SELECT * FROM t1 WHERE a IN (SELECT a FROM t1 WHERE a >'') ORDER BY a LIMIT 1; +a b +ab NULL +DROP TABLE t1; +# End of 11.0 tests diff --git a/mysql-test/main/order_by_innodb.test b/mysql-test/main/order_by_innodb.test index acce96c7603..9ad9cc20337 100644 --- a/mysql-test/main/order_by_innodb.test +++ b/mysql-test/main/order_by_innodb.test @@ -250,3 +250,12 @@ explain select * from t1 force index(r) order by a,b limit 20; explain select * from t1 force index(r) order by a desc,b limit 20; select * from t1 force index(r) order by a desc,b limit 20; drop table t1; + +--echo # +--echo # MDEV-31116: SIGSEGV in test_if_skip_sort_order|JOIN::optimize_stage2 +--echo # +CREATE TABLE t1 (a BINARY (2),b BINARY (1),KEY(a)) ENGINE=innodb; +INSERT INTO t1 select 'ab', NULL from seq_1_to_14; +SELECT * FROM t1 WHERE a IN (SELECT a FROM t1 WHERE a >'') ORDER BY a LIMIT 1; +DROP TABLE t1; +--echo # End of 11.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 94ae6491f77..ec87acea678 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -26478,7 +26478,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, !table->is_clustering_key(best_key))) goto use_filesort; - if (table->opt_range_keys.is_set(best_key) && best_key != ref_key) + if (select && table->opt_range_keys.is_set(best_key) && best_key != ref_key) { key_map tmp_map; tmp_map.clear_all(); // Force the creation of quick select From 2a4c57333910345b312f305f00dd1f90228e49fc Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Wed, 8 Nov 2023 13:55:03 +0100 Subject: [PATCH 217/477] 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)); } } From 62d80652be7c19f4ad2bf68d6ffbb4e1eb1d77ea Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 30 Oct 2023 12:13:00 +0400 Subject: [PATCH 218/477] MDEV-29110 mariabackup has wrong or missing plugin-dir default? Problem: The file backup-my.cnf from the backup directory was loaded by "mariabackup --prepare" only in case of the explicit --target-dir given. It was not loaded from the default directory ./xtrabackup_backupfiles/ in case if the explicit --target-dir was missing. In other words, it worked as follows: 1. When started as "mariabackup --prepare --target-dir=DIR", mariabackup: a. loads defaults from "DIR/backup-my.cnf" b. processes data files in the specified directory DIR 2. When started as "mariabackup --prepare", mariabackup: a. does not load defaults from "./xtrabackup_backupfiles/backup-my.cnf" b. processes data files in the default directory "./xtrabackup_backupfiles/" This patch fixes the second scenario, so it works as follows: 2. When started as "mariabackup --prepare", mariabackup: a. loads defaults from "./xtrabackup_backupfiles/backup-my.cnf" b. processes data files in the default directory "./xtrabackup_backupfiles/" This change fixes (among others) the problem with the "Can't open shared library '/file_key_management.so'" error reported when "mariabackup --prepare" is used without --target-dir in combinaton with the encryption plugin. --- extra/mariabackup/xtrabackup.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 103aee8b64f..0c018b97d29 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -122,7 +122,8 @@ int sd_notifyf() { return 0; } int sys_var_init(); /* === xtrabackup specific options === */ -char xtrabackup_real_target_dir[FN_REFLEN] = "./xtrabackup_backupfiles/"; +#define DEFAULT_TARGET_DIR "./xtrabackup_backupfiles/" +char xtrabackup_real_target_dir[FN_REFLEN] = DEFAULT_TARGET_DIR; char *xtrabackup_target_dir= xtrabackup_real_target_dir; static my_bool xtrabackup_version; static my_bool verbose; @@ -6756,9 +6757,10 @@ void handle_options(int argc, char **argv, char ***argv_server, server_default_groups.push_back(NULL); snprintf(conf_file, sizeof(conf_file), "my"); - if (prepare && target_dir) { + if (prepare) { snprintf(conf_file, sizeof(conf_file), - "%s/backup-my.cnf", target_dir); + "%s/backup-my.cnf", target_dir ? target_dir: + DEFAULT_TARGET_DIR); if (!strncmp(argv[1], "--defaults-file=", 16)) { /* Remove defaults-file*/ for (int i = 2; ; i++) { From e0c65784aa78ea91f7e0ef400bbda9562d07c0e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 9 Nov 2023 11:06:17 +0200 Subject: [PATCH 219/477] MDEV-32737 innodb.log_file_name fails on Assertion `after_apply || !(blocks).end in recv_sys_t::clear recv_group_scan_log_recs(): Set the debug flag recv_sys.after_apply after actually completing the log scan. In the test, suppress some errors that may be reported when the crash recovery of RENAME TABLE t1 TO t2 is preceded by copying t2.ibd to t1.ibd. --- mysql-test/suite/innodb/t/log_file_name.test | 2 ++ storage/innobase/log/log0recv.cc | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/t/log_file_name.test b/mysql-test/suite/innodb/t/log_file_name.test index c153c38e54b..11eca0a7a12 100644 --- a/mysql-test/suite/innodb/t/log_file_name.test +++ b/mysql-test/suite/innodb/t/log_file_name.test @@ -170,6 +170,8 @@ call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' \(init function returned error\|registration as a STORAGE ENGINE failed\)"); call mtr.add_suppression("InnoDB: Table test/u[123] in the InnoDB data dictionary has tablespace id [1-9][0-9]*, but tablespace with that id or name does not exist\\. Have you deleted or moved \\.ibd files\\?"); call mtr.add_suppression("InnoDB: Cannot replay rename of tablespace.*"); +call mtr.add_suppression("InnoDB: Attempted to open a previously opened tablespace"); +call mtr.add_suppression("InnoDB: Recovery cannot access file"); FLUSH TABLES; --enable_query_log diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index a213b4842ce..59c4682552f 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3203,7 +3203,6 @@ recv_group_scan_log_recs( log_sys.log.scanned_lsn = end_lsn = *contiguous_lsn = ut_uint64_align_down(*contiguous_lsn, OS_FILE_LOG_BLOCK_SIZE); - ut_d(recv_sys.after_apply = last_phase); do { if (last_phase && store == STORE_NO) { @@ -3226,6 +3225,7 @@ recv_group_scan_log_recs( DBUG_RETURN(false); } + ut_d(recv_sys.after_apply = last_phase); DBUG_PRINT("ib_log", ("%s " LSN_PF " completed", last_phase ? "rescan" : "scan", log_sys.log.scanned_lsn)); From d6872f9cbbfa83f6aba82d8c7d5204c16f09d89e Mon Sep 17 00:00:00 2001 From: Andrei Date: Thu, 9 Nov 2023 14:36:46 +0200 Subject: [PATCH 220/477] MDEV-32365: post-fixes to rpl_semi_sync_slave_reply_fail --- mysql-test/suite/rpl/r/rpl_semi_sync_slave_reply_fail.result | 2 +- mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 f026a1c9db4..e482da7d0fc 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 @@ -32,7 +32,7 @@ connection 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 @save_debug_master= @@global.debug_dbug; SET GLOBAL debug_dbug="+d,semisync_corrupt_magic"; insert into t1 values (11); connection slave; 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 948537997dd..2ebc092e33d 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 @@ -78,7 +78,7 @@ insert into t1 values (10); --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 @save_debug_master= @@global.debug_dbug; SET GLOBAL debug_dbug="+d,semisync_corrupt_magic"; insert into t1 values (11); From 1710b6454bde34c2038eb248bc9c2d9f653681b4 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 1 Oct 2021 17:12:00 +0400 Subject: [PATCH 221/477] MDEV-26743 InnoDB: CHAR+nopad does not work well The patch for "MDEV-25440: Indexed CHAR ... broken with NO_PAD collations" fixed these scenarios from MDEV-26743: - Basic latin letter vs equal accented letter - Two letters vs equal (but space padded) expansion However, this scenario was still broken: - Basic latin letter (but followed by an ignorable character) vs equal accented letter Fix: When processing for a NOPAD collation a string with trailing ignorable characters, like: '' the string gets virtually converted to: '...' After the fix the code works differently in these two cases: 1. fits into the "nchars" limit 2. does not fit into the "nchars" limit Details: 1. If "nchars" is large enough (4+ in this example), return weights as follows: '[weight-for-non-ignorable, 1 char] [weight-for-space-character, 3 chars]' i.e. the weight for the virtual trailing space character now indicates that it corresponds to total 3 characters: - two ignorable characters - one virtual trailing space character 2. If "nchars" is small (3), then the virtual trailing space character does not fit into the "nchar" limit, so return 0x00 as weight, e.g.: '[weight-for-non-ignorable, 1 char] [0x00, 2 chars]' Adding corresponding MTR tests and unit tests. --- mysql-test/suite/innodb/r/no_pad.result | 46 +++++++++++++++++++++++++ mysql-test/suite/innodb/t/no_pad.test | 46 +++++++++++++++++++++++++ strings/ctype-uca.inl | 14 +++++++- unittest/strings/strings-t.c | 26 ++++++++++++++ 4 files changed, 131 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/r/no_pad.result b/mysql-test/suite/innodb/r/no_pad.result index 0c039c30a5e..2af5eb0207f 100644 --- a/mysql-test/suite/innodb/r/no_pad.result +++ b/mysql-test/suite/innodb/r/no_pad.result @@ -5,3 +5,49 @@ ALTER TABLE t1 ROW_FORMAT=DYNAMIC; INSERT INTO t1 VALUES ('',2); ALTER TABLE t1 ROW_FORMAT=REDUNDANT; DROP TABLE t1; +# +# MDEV-26743 InnoDB: CHAR+nopad does not work well +# +# +# Basic Latin letter vs equal accented letter +# +SET NAMES utf8mb3; +CREATE TABLE t1 (a CHAR(2), PRIMARY KEY(a)) COLLATE utf8_unicode_nopad_ci ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 VALUES ('a'),('ä'); +ERROR 23000: Duplicate entry 'ä' for key 'PRIMARY' +DROP TABLE t1; +# +# Two letters vs equal (but space padded) expansion +# +CREATE TABLE t1 (a CHAR(2), PRIMARY KEY(a)) COLLATE utf8_unicode_nopad_ci ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 VALUES ('ss'),('ß'); +SET sql_mode=PAD_CHAR_TO_FULL_LENGTH; +SELECT HEX(a) FROM t1; +HEX(a) +7373 +C39F20 +SET sql_mode=DEFAULT; +DROP TABLE t1; +# +# Basic Latin letter (but followed by an ignorable character) vs equal accented letter +# +SET NAMES utf8mb3; +CREATE TABLE t1 (a CHAR(3), PRIMARY KEY(a)) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_nopad_ci ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 VALUES (CONCAT('a',_utf8mb3 0x01)),('ä'); +SET sql_mode=PAD_CHAR_TO_FULL_LENGTH; +SELECT HEX(a) FROM t1 ORDER BY HEX(a); +HEX(a) +610120 +C3A42020 +SET sql_mode=DEFAULT; +DROP TABLE t1; +SET NAMES utf8mb3; +CREATE TABLE t1 (a CHAR(2), PRIMARY KEY(a)) COLLATE utf8_unicode_nopad_ci ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 VALUES (CONCAT('a',_utf8mb3 0x01)),('ä'); +SET sql_mode=PAD_CHAR_TO_FULL_LENGTH; +SELECT HEX(a) FROM t1 ORDER BY HEX(a); +HEX(a) +6101 +C3A420 +SET sql_mode=DEFAULT; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/no_pad.test b/mysql-test/suite/innodb/t/no_pad.test index 1be1972c9ca..15ab71b6c7f 100644 --- a/mysql-test/suite/innodb/t/no_pad.test +++ b/mysql-test/suite/innodb/t/no_pad.test @@ -8,3 +8,49 @@ ALTER TABLE t1 ROW_FORMAT=DYNAMIC; INSERT INTO t1 VALUES ('',2); ALTER TABLE t1 ROW_FORMAT=REDUNDANT; DROP TABLE t1; + + +--echo # +--echo # MDEV-26743 InnoDB: CHAR+nopad does not work well +--echo # + +--echo # +--echo # Basic Latin letter vs equal accented letter +--echo # + +SET NAMES utf8mb3; +CREATE TABLE t1 (a CHAR(2), PRIMARY KEY(a)) COLLATE utf8_unicode_nopad_ci ENGINE=InnoDB ROW_FORMAT=COMPACT; +--error ER_DUP_ENTRY +INSERT INTO t1 VALUES ('a'),('ä'); +DROP TABLE t1; + +--echo # +--echo # Two letters vs equal (but space padded) expansion +--echo # + +CREATE TABLE t1 (a CHAR(2), PRIMARY KEY(a)) COLLATE utf8_unicode_nopad_ci ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 VALUES ('ss'),('ß'); +SET sql_mode=PAD_CHAR_TO_FULL_LENGTH; +SELECT HEX(a) FROM t1; +SET sql_mode=DEFAULT; +DROP TABLE t1; + +--echo # +--echo # Basic Latin letter (but followed by an ignorable character) vs equal accented letter +--echo # + +SET NAMES utf8mb3; +CREATE TABLE t1 (a CHAR(3), PRIMARY KEY(a)) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_nopad_ci ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 VALUES (CONCAT('a',_utf8mb3 0x01)),('ä'); +SET sql_mode=PAD_CHAR_TO_FULL_LENGTH; +SELECT HEX(a) FROM t1 ORDER BY HEX(a); +SET sql_mode=DEFAULT; +DROP TABLE t1; + +SET NAMES utf8mb3; +CREATE TABLE t1 (a CHAR(2), PRIMARY KEY(a)) COLLATE utf8_unicode_nopad_ci ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 VALUES (CONCAT('a',_utf8mb3 0x01)),('ä'); +SET sql_mode=PAD_CHAR_TO_FULL_LENGTH; +SELECT HEX(a) FROM t1 ORDER BY HEX(a); +SET sql_mode=DEFAULT; +DROP TABLE t1; diff --git a/strings/ctype-uca.inl b/strings/ctype-uca.inl index 55b2c1ef7ce..48573ae2eed 100644 --- a/strings/ctype-uca.inl +++ b/strings/ctype-uca.inl @@ -335,8 +335,20 @@ MY_FUNCTION_NAME(scanner_next_pad_trim)(my_uca_scanner *scanner, flags & MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES ? my_space_weight(scanner->level) : 0; - res.nchars= 1; (*generated)++; + res.nchars++; /* Count all ignorable characters and the padded space */ + if (res.nchars > nchars) + { + /* + We scanned a number of ignorable characters at the end of the + string and reached the "nchars" limit, so the virtual padded space + does not fit. This is possible with CONCAT('a', x'00') with + nchars=2 on the second iteration when we scan the x'00'. + */ + if (scanner->cs->state & MY_CS_NOPAD) + res.weight= 0; + res.nchars= (uint) nchars; + } } else if (res.nchars > nchars) { diff --git a/unittest/strings/strings-t.c b/unittest/strings/strings-t.c index f5563247f17..e2d2fb465db 100644 --- a/unittest/strings/strings-t.c +++ b/unittest/strings/strings-t.c @@ -911,6 +911,19 @@ static STRNNCOLLSP_CHAR_PARAM strnncollsp_char_utf8mb3_unicode_ci[]= {{CSTR("ss")}, {CSTR(UTF8_sz)}, 4, TCHAR, 0}, {{CSTR("ss")}, {CSTR(UTF8_sz)}, 100, TCHAR, 0}, + {{CSTR("a" "\x01")}, {CSTR(UTF8_auml)}, 0, TCHAR, 0}, + {{CSTR("a" "\x01")}, {CSTR(UTF8_auml)}, 1, TCHAR, 0}, + {{CSTR("a" "\x01")}, {CSTR(UTF8_auml)}, 2, TCHAR, 0}, + {{CSTR("a" "\x01")}, {CSTR(UTF8_auml)}, 3, TCHAR, 0}, + {{CSTR("a" "\x01")}, {CSTR(UTF8_auml)}, 100, TCHAR, 0}, + + {{CSTR("a" "\x01\x01")}, {CSTR(UTF8_auml)}, 0, TCHAR, 0}, + {{CSTR("a" "\x01\x01")}, {CSTR(UTF8_auml)}, 1, TCHAR, 0}, + {{CSTR("a" "\x01\x01")}, {CSTR(UTF8_auml)}, 2, TCHAR, 0}, + {{CSTR("a" "\x01\x01")}, {CSTR(UTF8_auml)}, 3, TCHAR, 0}, + {{CSTR("a" "\x01\x01")}, {CSTR(UTF8_auml)}, 4, TCHAR, 0}, + {{CSTR("a" "\x01\x01")}, {CSTR(UTF8_auml)}, 100, TCHAR, 0}, + {{NULL, 0}, {NULL, 0}, 0, 0, 0} }; @@ -938,6 +951,19 @@ static STRNNCOLLSP_CHAR_PARAM strnncollsp_char_utf8mb3_unicode_nopad_ci[]= {{CSTR("ss")}, {CSTR(UTF8_sz)}, 4, TVCHAR, 0}, {{CSTR("ss")}, {CSTR(UTF8_sz)}, 100, TVCHAR, 0}, + {{CSTR("a" "\x01")}, {CSTR(UTF8_auml)}, 0, TCHAR, 0}, + {{CSTR("a" "\x01")}, {CSTR(UTF8_auml)}, 1, TCHAR, 0}, + {{CSTR("a" "\x01")}, {CSTR(UTF8_auml)}, 2, TCHAR, -1}, + {{CSTR("a" "\x01")}, {CSTR(UTF8_auml)}, 3, TCHAR, 0}, + {{CSTR("a" "\x01")}, {CSTR(UTF8_auml)}, 100, TCHAR, 0}, + + {{CSTR("a" "\x01\x01")}, {CSTR(UTF8_auml)}, 0, TCHAR, 0}, + {{CSTR("a" "\x01\x01")}, {CSTR(UTF8_auml)}, 1, TCHAR, 0}, + {{CSTR("a" "\x01\x01")}, {CSTR(UTF8_auml)}, 2, TCHAR, -1}, + {{CSTR("a" "\x01\x01")}, {CSTR(UTF8_auml)}, 3, TCHAR, -1}, + {{CSTR("a" "\x01\x01")}, {CSTR(UTF8_auml)}, 4, TCHAR, 0}, + {{CSTR("a" "\x01\x01")}, {CSTR(UTF8_auml)}, 100, TCHAR, 0}, + {{NULL, 0}, {NULL, 0}, 0, 0, 0} }; From 9d8f659f80ec096ab61c393f807b4dae185d7fd1 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Fri, 10 Nov 2023 12:40:21 +0100 Subject: [PATCH 222/477] galera: post-fix after migrating changes from 10.4 --- sql/rpl_gtid.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 26a86c60608..3f519f67eb6 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -703,6 +703,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, if (WSREP_ON_ && wsrep_thd_is_local(thd)) { thd->wsrep_ignore_table= false; + table->file->row_logging= 1; // replication requires binary logging wsrep_start_trx_if_not_started(thd); } else From e53e7cd1343a8a3bccf5627fe1f69be1c820d4d2 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 9 Nov 2023 16:26:11 +0300 Subject: [PATCH 223/477] MDEV-20545 Assertion col.vers_sys_end() in dict_index_t::vers_history_row Index values for row_start/row_end was wrongly calculated for inplace ALTER for some layout of virtual fields. Possible impact 1. history row is not detected upon build clustered index for inplace ALTER which may lead to duplicate key errors on auto-increment and FTS index add. 2. foreign key constraint may falsely fail. 3. after inplace ALTER before server restart trx-based system versioning can cause server crash or incorrect data written upon UPDATE. --- mysql-test/suite/versioning/r/alter.result | 59 ++++++++++++++++++++ mysql-test/suite/versioning/t/alter.test | 62 ++++++++++++++++++++++ sql/field.h | 10 ++++ storage/innobase/handler/handler0alter.cc | 10 ++-- 4 files changed, 137 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/versioning/r/alter.result b/mysql-test/suite/versioning/r/alter.result index a026b68a11b..7891fa60024 100644 --- a/mysql-test/suite/versioning/r/alter.result +++ b/mysql-test/suite/versioning/r/alter.result @@ -786,3 +786,62 @@ with system versioning, modify row_start varchar(8); ERROR HY000: PERIOD FOR SYSTEM_TIME must use columns `row_start` and `row_end` drop table t1; +# +# MDEV-20545 Assertion (col.vers_sys_end()) upon inplace ALTER with virtual columns +# +create table t1 ( +a int, +va int as (a) virtual, +b int, +vb int as (b) virtual, +c int, +vc int as (c) virtual, +d int, +e int, +index(va) +) engine=innodb with system versioning; +replace into t1 () values (),(); +set statement system_versioning_alter_history=keep for alter table t1 drop e; +alter table t1 algorithm=inplace, drop system versioning; +drop table t1; +# +# MDEV-20765 Assertion (type.vers_sys_end()) upon inplace ALTER with virtual columns +# +create table t1 ( +a int, +b int as (a) virtual, +c int, +d int as (c) virtual, +e int, +f int as (e) virtual, +g int, +h int, +i int, +index(d), +key(h), +foreign key (g) references t1 (h) +) engine=innodb with system versioning; +set system_versioning_alter_history= keep; +alter table t1 drop column i; +insert into t1 (g,h) values (1,1); +drop table t1; +# +# MDEV-29034 Assertion (o->ind == vers_start) upon inplace ALTER with virtual columns +# +create table b ( +pk integer auto_increment, +col_int_key integer, +col_varchar_key varchar(1), +o bit, n bit, +h float as ( n + 2 ) virtual, +v bit, +primary key (pk), +key (col_varchar_key, col_int_key) +) engine = innodb; +set `system_versioning_alter_history`= keep; +alter table `b` add system versioning; +alter table `b` add column if not exists ( w bit, v serial ); +Warnings: +Note 1060 Duplicate column name 'v' +alter table `b` add column if not exists ( p bit ); +drop table `b`; diff --git a/mysql-test/suite/versioning/t/alter.test b/mysql-test/suite/versioning/t/alter.test index 311f2d97bdf..ed52d179eaa 100644 --- a/mysql-test/suite/versioning/t/alter.test +++ b/mysql-test/suite/versioning/t/alter.test @@ -677,3 +677,65 @@ alter table t1 modify row_start varchar(8); # cleanup drop table t1; + +--echo # +--echo # MDEV-20545 Assertion (col.vers_sys_end()) upon inplace ALTER with virtual columns +--echo # +create table t1 ( + a int, + va int as (a) virtual, + b int, + vb int as (b) virtual, + c int, + vc int as (c) virtual, + d int, + e int, + index(va) +) engine=innodb with system versioning; +replace into t1 () values (),(); +set statement system_versioning_alter_history=keep for alter table t1 drop e; +alter table t1 algorithm=inplace, drop system versioning; +# cleanup +drop table t1; + +--echo # +--echo # MDEV-20765 Assertion (type.vers_sys_end()) upon inplace ALTER with virtual columns +--echo # +create table t1 ( + a int, + b int as (a) virtual, + c int, + d int as (c) virtual, + e int, + f int as (e) virtual, + g int, + h int, + i int, + index(d), + key(h), + foreign key (g) references t1 (h) +) engine=innodb with system versioning; +set system_versioning_alter_history= keep; +alter table t1 drop column i; +insert into t1 (g,h) values (1,1); +# cleanup +drop table t1; + +--echo # +--echo # MDEV-29034 Assertion (o->ind == vers_start) upon inplace ALTER with virtual columns +--echo # +create table b ( + pk integer auto_increment, + col_int_key integer, + col_varchar_key varchar(1), + o bit, n bit, + h float as ( n + 2 ) virtual, + v bit, + primary key (pk), + key (col_varchar_key, col_int_key) +) engine = innodb; +set `system_versioning_alter_history`= keep; +alter table `b` add system versioning; +alter table `b` add column if not exists ( w bit, v serial ); +alter table `b` add column if not exists ( p bit ); +drop table `b`; diff --git a/sql/field.h b/sql/field.h index a8bb9e2c9cb..8d23a05e720 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1612,6 +1612,16 @@ public: return flags & (VERS_ROW_START | VERS_ROW_END); } + bool vers_sys_start() const + { + return flags & VERS_ROW_START; + } + + bool vers_sys_end() const + { + return flags & VERS_ROW_END; + } + bool vers_update_unversioned() const { return flags & VERS_UPDATE_UNVERSIONED_FLAG; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 6b2356ff6b3..b61949620f7 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -4556,10 +4556,12 @@ innobase_build_col_map( col_map[old_i - num_old_v] = i; if (old_table->versioned() && altered_table->versioned()) { - if (old_i == old_table->vers_start) { - new_table->vers_start = i + num_v; - } else if (old_i == old_table->vers_end) { - new_table->vers_end = i + num_v; + if (old_i - num_old_v == old_table->vers_start) { + ut_ad(field->vers_sys_start()); + new_table->vers_start = i; + } else if (old_i - num_old_v == old_table->vers_end) { + ut_ad(field->vers_sys_end()); + new_table->vers_end = i; } } goto found_col; From 74883f5e2f4c0e09f4f4e9e272a8e5bfd91a9489 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 9 Nov 2023 16:26:11 +0300 Subject: [PATCH 224/477] MDEV-32082 Server crash in find_field_in_table Attempt to resolve FOR SYSTEM_TIME expression as field for derived table is done before derived table is fully prepared, so we fail on assertion that table_list->table is missing. Actually Vers_history_point::resolve_unit() is done under the call of mysql_derived_prepare() itself (sql_derived.cc:824) and the table is assigned later at 867. The fix disables unit resolution for field type in FOR SYSTEM_TIME expression as it does a little sense in any case: making historical queries based on variable field values produces the result of multiple time points. fix_fields_if_needed() in resolve_units() was introduced by 46be31982a4 --- mysql-test/suite/versioning/r/select.result | 11 ++++++++++- mysql-test/suite/versioning/t/select.test | 12 +++++++++++- sql/table.cc | 5 +++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result index aa46d810ed1..e53e417c6ee 100644 --- a/mysql-test/suite/versioning/r/select.result +++ b/mysql-test/suite/versioning/r/select.result @@ -444,7 +444,7 @@ create or replace table t1 (x int) with system versioning; select * from t1 for system_time as of current_timestamp; x select * from t1 for system_time as of now; -ERROR 42S22: Unknown column 'now' in 'FOR SYSTEM_TIME' +ERROR HY000: Illegal parameter data type now for operation 'FOR SYSTEM_TIME' ### Issue #405, NATURAL JOIN failure create or replace table t1 (a int) with system versioning; create or replace table t2 (b int); @@ -708,3 +708,12 @@ No A B C D 32 1 1 1 1 33 1 1 1 1 34 1 1 1 1 +# +# MDEV-32082 Server crash in find_field_in_table +# +create table t0 (c0 int) with system versioning; +select x0 from ( +select c0 x0 from t0 +) for system_time as of nowasdf deriv; +ERROR HY000: Illegal parameter data type nowasdf for operation 'FOR SYSTEM_TIME' +drop table t0; diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test index 1d5d0f323be..c81470f5c1c 100644 --- a/mysql-test/suite/versioning/t/select.test +++ b/mysql-test/suite/versioning/t/select.test @@ -307,7 +307,7 @@ select * from t1 where (a, 2) in ((1, 1), (2, 2)) and b = 1; --echo ### Issue #398, NOW is now non-magic create or replace table t1 (x int) with system versioning; select * from t1 for system_time as of current_timestamp; ---error ER_BAD_FIELD_ERROR +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION select * from t1 for system_time as of now; --echo ### Issue #405, NATURAL JOIN failure @@ -471,4 +471,14 @@ drop tables x, x_p; call verify_trt_dummy(34); +--echo # +--echo # MDEV-32082 Server crash in find_field_in_table +--echo # +create table t0 (c0 int) with system versioning; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +select x0 from ( + select c0 x0 from t0 +) for system_time as of nowasdf deriv; +drop table t0; + -- source suite/versioning/common_finish.inc diff --git a/sql/table.cc b/sql/table.cc index eafeb6185a3..96a97b0e950 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -9965,6 +9965,11 @@ bool Vers_history_point::resolve_unit(THD *thd) { if (!item) return false; + if (item->real_type() == Item::FIELD_ITEM) + { + bad_expression_data_type_error(item->full_name()); + return true; + } if (item->fix_fields_if_needed(thd, &item)) return true; return item->this_item()->real_type_handler()-> From ebb6f575689773a831bbf54d3d706a7856d88230 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 9 Nov 2023 16:26:11 +0300 Subject: [PATCH 225/477] MDEV-23294 Segfault or assertion upon MyISAM repair When computing vcol expression some items use current_thd and that was not set in MyISAM repair thread. Since all the repair threads belong to one connection and items should not write into THD we can utilize table THD for that. --- include/myisamchk.h | 1 + .../suite/vcol/r/vcol_keys_myisam.result | 37 +++++++++++++++++++ mysql-test/suite/vcol/t/vcol_keys_myisam.test | 29 +++++++++++++++ storage/myisam/ha_myisam.cc | 11 ++++++ storage/myisam/sort.c | 5 +++ 5 files changed, 83 insertions(+) diff --git a/include/myisamchk.h b/include/myisamchk.h index 5876d67ca5f..eaff2c9ffdd 100644 --- a/include/myisamchk.h +++ b/include/myisamchk.h @@ -117,6 +117,7 @@ typedef struct st_handler_check_param uint progress_counter; /* How often to call _report_progress() */ ulonglong progress, max_progress; + void (*init_fix_record)(void *); int (*fix_record)(struct st_myisam_info *info, uchar *record, int keynum); mysql_mutex_t print_msg_mutex; diff --git a/mysql-test/suite/vcol/r/vcol_keys_myisam.result b/mysql-test/suite/vcol/r/vcol_keys_myisam.result index cbee8b733ed..74d733948af 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_keys_myisam.result @@ -418,3 +418,40 @@ create or replace table t2 (pk int, b int, c int as (b) virtual, primary key (pk insert into t2 (pk) select a from t1; ERROR 23000: Duplicate entry '1' for key 'PRIMARY' drop tables t1, t2; +# +# MDEV-23294 Segfault or assertion upon MyISAM repair +# +set @old_mode= @@sql_mode; +set @old_myisam_repair_threads= @@myisam_repair_threads; +set sql_mode='', myisam_repair_threads=2; +create table t (a binary,b blob,c blob as (concat (a,b)),h char,index (c)) engine=innodb; +Warnings: +Warning 1286 Unknown storage engine 'innodb' +Warning 1266 Using storage engine MyISAM for table 't' +Note 1071 Specified key was too long; max key length is 1000 bytes +insert into t values (0,0,default,0); +create table ti like t; +alter table ti engine=myisam; +insert into ti select * from t; +Warnings: +Warning 1906 The value specified for generated column 'c' in table 'ti' has been ignored +drop tables ti, t; +create table t (id int,a varchar(1),b varchar(1),c varchar(1) generated always as (concat (a,b)),key(c)) engine=myisam; +insert into t values (0,0,9687,0); +Warnings: +Warning 1265 Data truncated for column 'b' at row 1 +Warning 1906 The value specified for generated column 'c' in table 't' has been ignored +Warning 1265 Data truncated for column 'c' at row 1 +repair table t quick; +Table Op Msg_type Msg_text +test.t repair status OK +drop table t; +create table t1 (b varchar(1024), c char(3), unique(b,c)) engine=myisam; +insert into t1 values ('foo','baz'); +alter table t1 disable keys; +set session myisam_repair_threads= 2; +insert into t1 select 'qux'; +ERROR 21S01: Column count doesn't match value count at row 1 +drop table t1; +set sql_mode= @old_mode; +set myisam_repair_threads= @old_myisam_repair_threads; diff --git a/mysql-test/suite/vcol/t/vcol_keys_myisam.test b/mysql-test/suite/vcol/t/vcol_keys_myisam.test index 2a5aa3cd479..724cb8e510c 100644 --- a/mysql-test/suite/vcol/t/vcol_keys_myisam.test +++ b/mysql-test/suite/vcol/t/vcol_keys_myisam.test @@ -313,3 +313,32 @@ create or replace table t2 (pk int, b int, c int as (b) virtual, primary key (pk --error ER_DUP_ENTRY insert into t2 (pk) select a from t1; drop tables t1, t2; + +--echo # +--echo # MDEV-23294 Segfault or assertion upon MyISAM repair +--echo # +set @old_mode= @@sql_mode; +set @old_myisam_repair_threads= @@myisam_repair_threads; +set sql_mode='', myisam_repair_threads=2; +create table t (a binary,b blob,c blob as (concat (a,b)),h char,index (c)) engine=innodb; +insert into t values (0,0,default,0); +create table ti like t; +alter table ti engine=myisam; +insert into ti select * from t; +drop tables ti, t; + +create table t (id int,a varchar(1),b varchar(1),c varchar(1) generated always as (concat (a,b)),key(c)) engine=myisam; +insert into t values (0,0,9687,0); +repair table t quick; +drop table t; + +create table t1 (b varchar(1024), c char(3), unique(b,c)) engine=myisam; +insert into t1 values ('foo','baz'); +alter table t1 disable keys; +set session myisam_repair_threads= 2; +--error ER_WRONG_VALUE_COUNT_ON_ROW +insert into t1 select 'qux'; +# cleanup +drop table t1; +set sql_mode= @old_mode; +set myisam_repair_threads= @old_myisam_repair_threads; diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index ddab8bcf741..0db7179e7e9 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -709,6 +709,16 @@ my_bool mi_killed_in_mariadb(MI_INFO *info) return (((TABLE*) (info->external_ref))->in_use->killed != 0); } +static void init_compute_vcols(void *table) +{ + /* + To evaluate vcols we must have current_thd set. + This will set current_thd in all threads to the same THD, but it's + safe, because vcols are always evaluated under info->s->intern_lock. + */ + set_current_thd(static_cast
(table)->in_use); +} + static int compute_vcols(MI_INFO *info, uchar *record, int keynum) { /* This mutex is needed for parallel repair */ @@ -1010,6 +1020,7 @@ void ha_myisam::setup_vcols_for_repair(HA_CHECK *param) } DBUG_ASSERT(file->s->base.reclength < file->s->vreclength || !table->s->stored_fields); + param->init_fix_record= init_compute_vcols; param->fix_record= compute_vcols; table->use_all_columns(); } diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index e586543363b..f4729f75895 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -503,6 +503,11 @@ pthread_handler_t thr_find_all_keys(void *arg) { MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg; my_bool error= FALSE; + + MI_SORT_INFO *si= sort_param->sort_info; + if (si->param->init_fix_record) + si->param->init_fix_record(si->info->external_ref); + /* If my_thread_init fails */ if (my_thread_init() || thr_find_all_keys_exec(sort_param)) error= TRUE; From 56e479107c8769490c040b77f59d89f41d9f15c5 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 9 Nov 2023 16:26:11 +0300 Subject: [PATCH 226/477] MDEV-28127 EXCHANGE PARTITION with non-matching vcol expression segfault mysql_compare_tables() treated all columns non-virtual. Now it properly checks if the columns are virtual and matches expressions. --- mysql-test/suite/vcol/r/partition.result | 22 ++++++++++++++++++++++ mysql-test/suite/vcol/t/partition.test | 21 +++++++++++++++++++++ sql/sql_table.cc | 8 ++++++++ 3 files changed, 51 insertions(+) diff --git a/mysql-test/suite/vcol/r/partition.result b/mysql-test/suite/vcol/r/partition.result index d7c5052b72a..74c1e3bfee0 100644 --- a/mysql-test/suite/vcol/r/partition.result +++ b/mysql-test/suite/vcol/r/partition.result @@ -101,3 +101,25 @@ partition pn values less than (maxvalue)); insert into t1 (x, b) values (1, ''), (2, ''), (3, 'a'), (4, 'b'); update t1 set b= 'bar' where x > 0 order by v limit 2; drop table t1; +# +# MDEV-28127 EXCHANGE PARTITION with non-matching vcol expression segfault +# +set @old_mode= @@sql_mode; +set sql_mode=''; +create table t1 (a int, key(a)) partition by range (a) (partition p values less than (1)); +create table t (a int generated always as (1) virtual, key(a)); +alter table t1 exchange partition p with table t; +ERROR HY000: Tables have different definitions +create or replace table t (a int, key(a)); +alter table t1 exchange partition p with table t; +create or replace table t1 (a int generated always as (1) virtual, key(a)) partition by range (a) (partition p values less than (1)); +create or replace table t (a int generated always as (1) virtual, key(a)); +alter table t1 exchange partition p with table t; +create or replace table t (a int generated always as (1) stored, key(a)); +alter table t1 exchange partition p with table t; +ERROR HY000: Tables have different definitions +insert into t values (1); +Warnings: +Warning 1906 The value specified for generated column 'a' in table 't' has been ignored +drop tables t1, t; +set sql_mode= @old_mode; diff --git a/mysql-test/suite/vcol/t/partition.test b/mysql-test/suite/vcol/t/partition.test index 408990b20a6..019618b00b1 100644 --- a/mysql-test/suite/vcol/t/partition.test +++ b/mysql-test/suite/vcol/t/partition.test @@ -78,3 +78,24 @@ partition by range columns (x) ( insert into t1 (x, b) values (1, ''), (2, ''), (3, 'a'), (4, 'b'); update t1 set b= 'bar' where x > 0 order by v limit 2; drop table t1; + +--echo # +--echo # MDEV-28127 EXCHANGE PARTITION with non-matching vcol expression segfault +--echo # +set @old_mode= @@sql_mode; +set sql_mode=''; +create table t1 (a int, key(a)) partition by range (a) (partition p values less than (1)); +create table t (a int generated always as (1) virtual, key(a)); +--error ER_TABLES_DIFFERENT_METADATA +alter table t1 exchange partition p with table t; +create or replace table t (a int, key(a)); +alter table t1 exchange partition p with table t; +create or replace table t1 (a int generated always as (1) virtual, key(a)) partition by range (a) (partition p values less than (1)); +create or replace table t (a int generated always as (1) virtual, key(a)); +alter table t1 exchange partition p with table t; +create or replace table t (a int generated always as (1) stored, key(a)); +--error ER_TABLES_DIFFERENT_METADATA +alter table t1 exchange partition p with table t; +insert into t values (1); +drop tables t1, t; +set sql_mode= @old_mode; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 84ef23bf828..1a239b7d105 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7538,6 +7538,14 @@ bool mysql_compare_tables(TABLE *table, (uint) (field->flags & NOT_NULL_FLAG)) DBUG_RETURN(false); + if (field->vcol_info) + { + if (!tmp_new_field->field->vcol_info) + DBUG_RETURN(false); + if (!field->vcol_info->is_equal(tmp_new_field->field->vcol_info)) + DBUG_RETURN(false); + } + /* mysql_prepare_alter_table() clears HA_OPTION_PACK_RECORD bit when preparing description of existing table. In ALTER TABLE it is later From f7552313d4e54a1cbfa5cb9bb9d06a55df7d0e95 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 9 Nov 2023 16:26:11 +0300 Subject: [PATCH 227/477] MDEV-29932 Invalid expr in cleanup_session_expr() upon INSERT DELAYED There are two TABLE objects in each thread: first one is created in delayed thread by Delayed_insert::open_and_lock_table(), second one is created in connection thread by Delayed_insert::get_local_table(). It is copied from the delayed thread table. When the second table is copied copy-assignment operator copies vcol_refix_list which is already filled with an item from delayed thread. Then get_local_table() adds its own item. Thus both tables contains the same list with two items which is wrong. Then connection thread finishes and its item freed. Then delayed thread tries to access it in vcol_cleanup_expr(). The fix just clears vcol_refix_list in the copied table. Another problem is that copied table contains the same mem_root, any allocations on it will be invalid if the original table is freed (and that is indeterministic as it is done in another thread). Since copied table is allocated in connection THD and lives not longer than thd->mem_root we may assign its mem_root from thd->mem_root. Third, it doesn't make sense to do open_and_lock_tables() on NULL pointer. --- mysql-test/suite/vcol/r/vcol_syntax.result | 10 ++++++++++ mysql-test/suite/vcol/t/vcol_syntax.test | 10 ++++++++++ sql/sql_insert.cc | 5 ++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/vcol/r/vcol_syntax.result b/mysql-test/suite/vcol/r/vcol_syntax.result index f1a850e8f7c..09d471ddd17 100644 --- a/mysql-test/suite/vcol/r/vcol_syntax.result +++ b/mysql-test/suite/vcol/r/vcol_syntax.result @@ -234,3 +234,13 @@ Warning 1292 Incorrect datetime value: '1' for column `test`.`t`.`c2` at row 1 Warning 1292 Incorrect datetime value: '0' for column `test`.`t`.`c2` at row 1 drop trigger tr; drop table t; +# +# MDEV-29932 Invalid expr in cleanup_session_expr() upon INSERT DELAYED +# +create table t (f timestamp default from_unixtime(1), g timestamp as (from_unixtime(2))); +insert delayed into t values (); +flush table t; +select unix_timestamp(f), unix_timestamp(g) from t; +unix_timestamp(f) unix_timestamp(g) +1 2 +drop table t; diff --git a/mysql-test/suite/vcol/t/vcol_syntax.test b/mysql-test/suite/vcol/t/vcol_syntax.test index cb741bc6def..da3ce15eee9 100644 --- a/mysql-test/suite/vcol/t/vcol_syntax.test +++ b/mysql-test/suite/vcol/t/vcol_syntax.test @@ -185,3 +185,13 @@ insert into t values (1, 1, 1); drop trigger tr; drop table t; + +--echo # +--echo # MDEV-29932 Invalid expr in cleanup_session_expr() upon INSERT DELAYED +--echo # +create table t (f timestamp default from_unixtime(1), g timestamp as (from_unixtime(2))); +insert delayed into t values (); +flush table t; +select unix_timestamp(f), unix_timestamp(g) from t; +# Cleanup +drop table t; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index c3acce2f4a5..1bc2d9ccb00 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -579,7 +579,8 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list) Open tables used for sub-selects or in stored functions, will also cache these functions. */ - if (open_and_lock_tables(thd, table_list->next_global, TRUE, 0)) + if (table_list->next_global && + open_and_lock_tables(thd, table_list->next_global, TRUE, 0)) { end_delayed_insert(thd); error= TRUE; @@ -2632,6 +2633,8 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) /* Copy the TABLE object. */ copy= new (copy_tmp) TABLE; *copy= *table; + copy->vcol_refix_list.empty(); + copy->mem_root= *client_thd->mem_root; /* We don't need to change the file handler here */ /* Assign the pointers for the field pointers array and the record. */ From 28cdbab16372537b62f61ffa10917bf816572bf0 Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Sat, 4 Nov 2023 20:43:17 +0700 Subject: [PATCH 228/477] MDEV-29681 Server crashes when optimizing SQL with ORDER BY When parsing statements like (SELECT .. FROM ..) ORDER BY , there is a step LEX::add_tail_to_query_expression_body_ext_parens() which calls LEX::wrap_unit_into_derived(). After that the statement looks like SELECT * FROM (SELECT .. FROM ..), and parser's Lex_order_limit_lock structure (ORDER BY ) is assigned to the new SELECT. But what is missing here is that Items in Lex_order_limit_lock are left with their original name resolution contexts, and fix_fields() later resolves the names incorrectly. For example, when processing (SELECT * FROM t1 JOIN t2 ON a=b) ORDER BY a Item_field 'a' in the ORDER BY clause is left with the name resolution context of the derived table (first_name_resolution_table='t1'), so it is resolved to 't1.a', which is incorrect. After LEX::wrap_unit_into_derived() the statement looks like SELECT * FROM (SELECT * FROM t1 JOIN t2 ON a=b) AS '__2' ORDER BY a, and the name resolution context for Item_field 'a' in the ORDER BY must be set to the wrapping SELECT's one. This commit fixes the issue by changing context for Items in Lex_order_limit_lock after LEX::wrap_unit_into_derived(). --- mysql-test/main/order_by.result | 120 ++++++++++++++++++++++++++++++++ mysql-test/main/order_by.test | 59 ++++++++++++++++ sql/sql_lex.cc | 9 +++ 3 files changed, 188 insertions(+) diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result index 9d83805c9c3..a4651331941 100644 --- a/mysql-test/main/order_by.result +++ b/mysql-test/main/order_by.result @@ -3725,4 +3725,124 @@ 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; +# +# MDEV-29681 Server crashes when optimizing SQL with ORDER BY +# +CREATE TABLE t1 (b INT); +CREATE TABLE t2 (a INT, c INT); +# First test empty tables +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a+1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY system NULL NULL NULL NULL 0 0.00 Const row not found +2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table +Warnings: +Note 1003 /* select#1 */ select NULL AS `b`,NULL AS `a`,NULL AS `c` from ((/* select#2 */ select NULL AS `b`,NULL AS `a`,NULL AS `c` from `test`.`t1` join `test`.`t2` where 0 limit 3)) `__2` order by NULL + 1 +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a=2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY system NULL NULL NULL NULL 0 0.00 Const row not found +2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table +Warnings: +Note 1003 /* select#1 */ select NULL AS `b`,NULL AS `a`,NULL AS `c` from ((/* select#2 */ select NULL AS `b`,NULL AS `a`,NULL AS `c` from `test`.`t1` join `test`.`t2` where 0 limit 3)) `__2` order by NULL = 2 +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) +ORDER BY a+1, a-b DESC, c<>a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY system NULL NULL NULL NULL 0 0.00 Const row not found +2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table +Warnings: +Note 1003 /* select#1 */ select NULL AS `b`,NULL AS `a`,NULL AS `c` from ((/* select#2 */ select NULL AS `b`,NULL AS `a`,NULL AS `c` from `test`.`t1` join `test`.`t2` where 0 limit 3)) `__2` order by NULL + 1,NULL - NULL desc,NULL <> NULL +# Insert some data +INSERT INTO t1 VALUES (1),(2),(3),(4); +INSERT INTO t2 VALUES (1,1),(2,2),(3,3),(4,4); +(SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a=b, a-10 DESC, b+a, c+a+a+b; +b a c +1 1 1 +2 2 2 +3 3 3 +(SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a=2; +b a c +1 1 1 +2 2 2 +3 3 3 +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) +ORDER BY a=b, a-10, b+a, c+a+a+b; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 Using filesort +2 DERIVED t1 ALL NULL NULL NULL NULL 4 100.00 +2 DERIVED t2 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) +Warnings: +Note 1003 /* select#1 */ select `__2`.`b` AS `b`,`__2`.`a` AS `a`,`__2`.`c` AS `c` from ((/* select#2 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` limit 3)) `__2` order by `__2`.`a` = `__2`.`b`,`__2`.`a` - 10,`__2`.`b` + `__2`.`a`,`__2`.`c` + `__2`.`a` + `__2`.`a` + `__2`.`b` +# When there is no LIMIT clause the derived table must be merged +(SELECT * FROM t1 JOIN t2 ON a=b) ORDER BY a+16, b+a, c<>b; +b a c +1 1 1 +2 2 2 +3 3 3 +4 4 4 +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b) ORDER BY a+16 DESC, b+a, c<>b; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using temporary; Using filesort +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) +Warnings: +Note 1003 (select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` order by `test`.`t2`.`a` + 16 desc,`test`.`t1`.`b` + `test`.`t2`.`a`,`test`.`t2`.`c` <> `test`.`t1`.`b`) +# Test UNIONs: +(SELECT * FROM t1 JOIN t2 ON a=b UNION +SELECT * FROM t1 JOIN t2 ON a!=b +LIMIT 3) +ORDER BY a+16, b+a, c<>b; +b a c +1 1 1 +2 2 2 +3 3 3 +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b UNION +SELECT * FROM t1 JOIN t2 ON a!=b +LIMIT 3) +ORDER BY a+16, b+a, c<>b; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 32 100.00 Using filesort +2 DERIVED t1 ALL NULL NULL NULL NULL 4 100.00 +2 DERIVED t2 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) +3 UNION t1 ALL NULL NULL NULL NULL 4 100.00 +3 UNION t2 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) +NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 /* select#1 */ select `__3`.`b` AS `b`,`__3`.`a` AS `a`,`__3`.`c` AS `c` from (/* select#2 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` union /* select#3 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` <> `test`.`t1`.`b` limit 3) `__3` order by `__3`.`a` + 16,`__3`.`b` + `__3`.`a`,`__3`.`c` <> `__3`.`b` +(SELECT * FROM t1 JOIN t2 ON a=b UNION +SELECT NULL, NULL, NULL +LIMIT 3) +ORDER BY b-a-c; +b a c +1 1 1 +2 2 2 +3 3 3 +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b UNION +SELECT NULL, NULL, NULL +LIMIT 3) +ORDER BY b-a-c; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 16 100.00 Using filesort +2 DERIVED t1 ALL NULL NULL NULL NULL 4 100.00 +2 DERIVED t2 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) +3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 /* select#1 */ select `__3`.`b` AS `b`,`__3`.`a` AS `a`,`__3`.`c` AS `c` from (/* select#2 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` union /* select#3 */ select NULL AS `NULL`,NULL AS `NULL`,NULL AS `NULL` limit 3) `__3` order by `__3`.`b` - `__3`.`a` - `__3`.`c` +(SELECT * FROM t1 JOIN t2 ON a=b UNION +SELECT NULL, NULL, NULL +ORDER BY a LIMIT 3) +ORDER BY b-a-c LIMIT 1; +b a c +NULL NULL NULL +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b UNION +SELECT NULL, NULL, NULL +ORDER BY a LIMIT 3) +ORDER BY b-a-c LIMIT 1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 16 100.00 Using filesort +2 DERIVED t1 ALL NULL NULL NULL NULL 4 100.00 +2 DERIVED t2 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) +3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL Using filesort +Warnings: +Note 1003 /* select#1 */ select `__3`.`b` AS `b`,`__3`.`a` AS `a`,`__3`.`c` AS `c` from (/* select#2 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` union /* select#3 */ select NULL AS `NULL`,NULL AS `NULL`,NULL AS `NULL` order by `a` limit 3) `__3` order by `__3`.`b` - `__3`.`a` - `__3`.`c` limit 1 +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 ec10375e57c..d52a78a8cdd 100644 --- a/mysql-test/main/order_by.test +++ b/mysql-test/main/order_by.test @@ -2468,4 +2468,63 @@ EXPLAIN SELECT (SELECT 1 FROM t1 WHERE t1.a=t2.b ORDER BY t1.b LIMIT 1) AS c FRO DROP TABLE t1,t2; +--echo # +--echo # MDEV-29681 Server crashes when optimizing SQL with ORDER BY +--echo # +CREATE TABLE t1 (b INT); +CREATE TABLE t2 (a INT, c INT); + +--echo # First test empty tables +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a+1; +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a=2; +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) + ORDER BY a+1, a-b DESC, c<>a; + +--echo # Insert some data +INSERT INTO t1 VALUES (1),(2),(3),(4); +INSERT INTO t2 VALUES (1,1),(2,2),(3,3),(4,4); + +--sorted_result +(SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a=b, a-10 DESC, b+a, c+a+a+b; +--sorted_result +(SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) ORDER BY a=2; + +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b LIMIT 3) + ORDER BY a=b, a-10, b+a, c+a+a+b; + +--echo # When there is no LIMIT clause the derived table must be merged +--sorted_result +(SELECT * FROM t1 JOIN t2 ON a=b) ORDER BY a+16, b+a, c<>b; +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b) ORDER BY a+16 DESC, b+a, c<>b; + +--echo # Test UNIONs: +--sorted_result +(SELECT * FROM t1 JOIN t2 ON a=b UNION + SELECT * FROM t1 JOIN t2 ON a!=b + LIMIT 3) + ORDER BY a+16, b+a, c<>b; +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b UNION + SELECT * FROM t1 JOIN t2 ON a!=b + LIMIT 3) + ORDER BY a+16, b+a, c<>b; +--sorted_result +(SELECT * FROM t1 JOIN t2 ON a=b UNION + SELECT NULL, NULL, NULL + LIMIT 3) + ORDER BY b-a-c; +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b UNION + SELECT NULL, NULL, NULL + LIMIT 3) + ORDER BY b-a-c; +--sorted_result +(SELECT * FROM t1 JOIN t2 ON a=b UNION + SELECT NULL, NULL, NULL + ORDER BY a LIMIT 3) + ORDER BY b-a-c LIMIT 1; +EXPLAIN EXTENDED (SELECT * FROM t1 JOIN t2 ON a=b UNION + SELECT NULL, NULL, NULL + ORDER BY a LIMIT 3) + ORDER BY b-a-c LIMIT 1; +DROP TABLE t1, t2; + --echo # End of 10.4 tests diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 4b0a5da2ad5..582494a0fd6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -9414,8 +9414,17 @@ bool Lex_order_limit_lock::set_to(SELECT_LEX *sel) "CUBE/ROLLUP", "ORDER BY"); return TRUE; } + for (ORDER *order= order_list->first; order; order= order->next) + (*order->item)->walk(&Item::change_context_processor, FALSE, + &sel->context); sel->order_list= *(order_list); } + if (limit.select_limit) + limit.select_limit->walk(&Item::change_context_processor, FALSE, + &sel->context); + if (limit.offset_limit) + limit.offset_limit->walk(&Item::change_context_processor, FALSE, + &sel->context); sel->is_set_query_expr_tail= true; return FALSE; } From c3fdfbdbd82c43f867ed82232e3b3077c485c5e1 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Fri, 10 Nov 2023 13:54:25 +0100 Subject: [PATCH 229/477] MDEV-31413: post-fix for 10.5+ (galera_restart_replica test failures) --- mysql-test/suite/galera/t/galera_restart_replica.test | 2 +- sql/rpl_gtid.cc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/galera/t/galera_restart_replica.test b/mysql-test/suite/galera/t/galera_restart_replica.test index 2cc3a1dcff2..37cfd9bc0f9 100644 --- a/mysql-test/suite/galera/t/galera_restart_replica.test +++ b/mysql-test/suite/galera/t/galera_restart_replica.test @@ -3,9 +3,9 @@ # # The galera/galera_2node_slave.cnf describes the setup of the nodes # ---source include/big_test.inc --source include/force_restart.inc --source include/galera_cluster.inc +--source include/have_innodb.inc --source include/have_sequence.inc # As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 26a86c60608..3f519f67eb6 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -703,6 +703,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, if (WSREP_ON_ && wsrep_thd_is_local(thd)) { thd->wsrep_ignore_table= false; + table->file->row_logging= 1; // replication requires binary logging wsrep_start_trx_if_not_started(thd); } else From 9da247b2e727ce87c1c10d81ec54601d473ca896 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Sat, 11 Nov 2023 15:37:29 +0100 Subject: [PATCH 230/477] galera: cleanup of the lists of disabled tests --- mysql-test/suite/galera/disabled.def | 14 ++++++++------ mysql-test/suite/galera_3nodes/disabled.def | 7 +++---- mysql-test/suite/galera_3nodes_sr/disabled.def | 2 +- mysql-test/suite/galera_sr/disabled.def | 3 +-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 104a631f8b7..c5412874929 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -14,9 +14,11 @@ galera_as_slave_ctas : MDEV-28378 timeout galera_pc_recovery : MDEV-25199 cluster fails to start up 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_shutdown : MDEV-29918 Assertion failure on galera_bf_abort_shutdown -galera_var_ignore_apply_errors : 28: "Server did not transition to READY state" -versioning_trx_id : MDEV-18590: galera.versioning_trx_id: Test failure: mysqltest: Result content mismatch -MDEV-27713 : test is using get_lock(), which is now rejected in cluster -galera_bf_abort_group_commit : MDEV-30855 PR to remove the test exists +galera_sequences : MDEV-32561 WSREP FSM failure: no such a transition REPLICATING -> COMMITTED +galera_shutdown_nonprim : MDEV-32635 galera_shutdown_nonprim: mysql_shutdown failed +versioning_trx_id : MDEV-18590 : galera.versioning_trx_id: Test failure: mysqltest: Result content mismatch +galera_concurrent_ctas : MDEV-32779 galera_concurrent_ctas: assertion in the galera::ReplicatorSMM::finish_cert() +galera_as_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() +galera_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() +galera_bf_lock_wait : MDEV-32781 galera_bf_lock_wait test failed +galera_sst_mysqldump_with_key : MDEV-32782 galera_sst_mysqldump_with_key test failed diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index dc08e0981bd..3986bc69dcf 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -10,8 +10,7 @@ # ############################################################################## - -galera_2_cluster : MDEV-29877 Galera test failure on galera_2_cluster -galera_gtid_2_cluster : MDEV-29877 Galera test failure on galera_2_cluster +galera_2_cluster : MDEV-32631 galera_2_cluster: before_rollback(): Assertion `0' failed +galera_gtid_2_cluster : MDEV-32633 galera_gtid_2_cluster: Assertion `thd->wsrep_next_trx_id() != (0x7fffffffffffffffLL * 2ULL + 1)' galera_vote_rejoin_mysqldump : MDEV-24481: galera_3nodes.galera_vote_rejoin_mysqldump MTR failed: mysql_shutdown failed -galera_ssl_reload : MDEV-30172 At line 50: mysql_shutdown failed +galera_ssl_reload : MDEV-32778 galera_ssl_reload failed with warning message diff --git a/mysql-test/suite/galera_3nodes_sr/disabled.def b/mysql-test/suite/galera_3nodes_sr/disabled.def index df2277fb8ad..4472d960d9f 100644 --- a/mysql-test/suite/galera_3nodes_sr/disabled.def +++ b/mysql-test/suite/galera_3nodes_sr/disabled.def @@ -10,4 +10,4 @@ # ############################################################################## -galera_sr_kill_slave_after_apply_rollback2 : MDEV-29892 Galera test failure on galera_sr_kill_slave_after_apply_rollback2 \ No newline at end of file +galera_sr_kill_slave_after_apply_rollback2 : MDEV-29892 Galera test failure on galera_sr_kill_slave_after_apply_rollback2 diff --git a/mysql-test/suite/galera_sr/disabled.def b/mysql-test/suite/galera_sr/disabled.def index 1132a0097c4..fa62168d474 100644 --- a/mysql-test/suite/galera_sr/disabled.def +++ b/mysql-test/suite/galera_sr/disabled.def @@ -10,6 +10,5 @@ # ############################################################################## -GCF-1060 : MDEV-26528 wrong usage of mutex LOCK_thd_kill and LOCK_thd_kill +GCF-1060 : MDEV-32160 GCF-1060 test failure due to wsrep MDL conflict galera_sr_cc_master : MDEV-29882 Galera test failure on galera_sr_cc_master -mysql-wsrep-features#138 : At line 25: query 'DROP TABLE t1' failed: 2013: Lost connection to MySQL server during query From 561093701be39e978bf1a46637a6bd07bc4f4af5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 13 Nov 2023 09:27:01 +0200 Subject: [PATCH 231/477] MDEV-29180 fixup: 32-bit tests This fixes up commit 01031f43d8918dc21bbf27f73a7e73e832ccb4d6 --- .../r/sysvars_server_embedded,32bit.rdiff | 276 +++++++++--------- .../r/sysvars_server_notembedded,32bit.rdiff | 4 +- 2 files changed, 138 insertions(+), 142 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff index d869b2812f0..ba6957d05d8 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff @@ -1,6 +1,4 @@ ---- ../../mysql-test/suite/sys_vars/r/sysvars_server_embedded.result 2022-01-27 20:42:19.039084441 +0200 -+++ ../../mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.result~ 2022-01-28 16:12:40.038627481 +0200 -@@ -34,7 +34,7 @@ READ_ONLY NO +@@ -34,7 +34,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_BLOCK_SIZE VARIABLE_SCOPE GLOBAL @@ -9,7 +7,7 @@ VARIABLE_COMMENT Block size to be used for Aria index pages. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 32768 -@@ -44,7 +44,7 @@ READ_ONLY YES +@@ -44,7 +44,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_CHECKPOINT_INTERVAL VARIABLE_SCOPE GLOBAL @@ -18,7 +16,7 @@ VARIABLE_COMMENT Interval between tries to do an automatic checkpoints. In seconds; 0 means 'no automatic checkpoints' which makes sense only for testing. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -54,7 +54,7 @@ READ_ONLY NO +@@ -54,7 +54,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_CHECKPOINT_LOG_ACTIVITY VARIABLE_SCOPE GLOBAL @@ -27,7 +25,7 @@ VARIABLE_COMMENT Number of bytes that the transaction log has to grow between checkpoints before a new checkpoint is written to the log. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -74,7 +74,7 @@ READ_ONLY NO +@@ -74,7 +74,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME ARIA_FORCE_START_AFTER_RECOVERY_FAILURES VARIABLE_SCOPE GLOBAL @@ -36,7 +34,7 @@ VARIABLE_COMMENT Number of consecutive log recovery failures after which logs will be automatically deleted to cure the problem; 0 (the default) disables the feature. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -94,7 +94,7 @@ READ_ONLY NO +@@ -94,7 +94,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_GROUP_COMMIT_INTERVAL VARIABLE_SCOPE GLOBAL @@ -45,7 +43,7 @@ VARIABLE_COMMENT Interval between commite in microseconds (1/1000000c). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -114,7 +114,7 @@ READ_ONLY YES +@@ -114,7 +114,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_LOG_FILE_SIZE VARIABLE_SCOPE GLOBAL @@ -54,7 +52,7 @@ VARIABLE_COMMENT Limit for transaction log size NUMERIC_MIN_VALUE 8388608 NUMERIC_MAX_VALUE 4294967295 -@@ -144,10 +144,10 @@ READ_ONLY NO +@@ -144,10 +144,10 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_PAGECACHE_AGE_THRESHOLD VARIABLE_SCOPE GLOBAL @@ -67,7 +65,7 @@ NUMERIC_BLOCK_SIZE 100 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -164,7 +164,7 @@ READ_ONLY YES +@@ -164,7 +164,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_PAGECACHE_DIVISION_LIMIT VARIABLE_SCOPE GLOBAL @@ -76,7 +74,7 @@ VARIABLE_COMMENT The minimum percentage of warm blocks in key cache NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100 -@@ -174,7 +174,7 @@ READ_ONLY NO +@@ -174,7 +174,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_PAGECACHE_FILE_HASH_SIZE VARIABLE_SCOPE GLOBAL @@ -85,7 +83,7 @@ VARIABLE_COMMENT Number of hash buckets for open and changed files. If you have a lot of Aria files open you should increase this for faster flush of changes. A good value is probably 1/10 of number of possible open Aria files. NUMERIC_MIN_VALUE 128 NUMERIC_MAX_VALUE 16384 -@@ -204,7 +204,7 @@ READ_ONLY NO +@@ -204,7 +204,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME ARIA_REPAIR_THREADS VARIABLE_SCOPE SESSION @@ -94,7 +92,7 @@ VARIABLE_COMMENT Number of threads to use when repairing Aria tables. The value of 1 disables parallel repair. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 128 -@@ -217,7 +217,7 @@ VARIABLE_SCOPE SESSION +@@ -217,7 +217,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE. NUMERIC_MIN_VALUE 16376 @@ -103,7 +101,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -274,7 +274,7 @@ READ_ONLY NO +@@ -274,7 +274,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME AUTO_INCREMENT_INCREMENT VARIABLE_SCOPE SESSION @@ -112,7 +110,7 @@ VARIABLE_COMMENT Auto-increment columns are incremented by this NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 65535 -@@ -284,7 +284,7 @@ READ_ONLY NO +@@ -284,7 +284,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME AUTO_INCREMENT_OFFSET VARIABLE_SCOPE SESSION @@ -121,7 +119,7 @@ VARIABLE_COMMENT Offset added to Auto-increment columns. Used when auto-increment-increment != 1 NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 65535 -@@ -294,7 +294,7 @@ READ_ONLY NO +@@ -294,7 +294,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME BACK_LOG VARIABLE_SCOPE GLOBAL @@ -130,7 +128,7 @@ VARIABLE_COMMENT The number of outstanding connection requests MariaDB can have. This comes into play when the main MariaDB thread gets very many connection requests in a very short time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -347,7 +347,7 @@ VARIABLE_SCOPE GLOBAL +@@ -347,7 +347,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the transactional cache for updates to transactional engines for the binary log. If you often use transactions containing many statements, you can increase this to get more performance NUMERIC_MIN_VALUE 4096 @@ -139,7 +137,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -364,20 +364,20 @@ READ_ONLY NO +@@ -364,20 +364,20 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME BINLOG_COMMIT_WAIT_COUNT VARIABLE_SCOPE GLOBAL @@ -164,7 +162,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -397,7 +397,7 @@ VARIABLE_SCOPE GLOBAL +@@ -397,7 +397,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of file cache for the binary log NUMERIC_MIN_VALUE 8192 @@ -173,7 +171,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -437,7 +437,7 @@ VARIABLE_SCOPE GLOBAL +@@ -437,7 +437,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the statement cache for updates to non-transactional engines for the binary log. If you often use statements updating a great number of rows, you can increase this to get more performance. NUMERIC_MIN_VALUE 4096 @@ -182,7 +180,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -447,7 +447,7 @@ VARIABLE_SCOPE SESSION +@@ -447,7 +447,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread! NUMERIC_MIN_VALUE 0 @@ -191,7 +189,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -634,7 +634,7 @@ READ_ONLY NO +@@ -634,7 +634,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME CONNECT_TIMEOUT VARIABLE_SCOPE GLOBAL @@ -200,7 +198,7 @@ VARIABLE_COMMENT The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake' NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 31536000 -@@ -684,7 +684,7 @@ READ_ONLY YES +@@ -684,7 +684,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DEADLOCK_SEARCH_DEPTH_LONG VARIABLE_SCOPE SESSION @@ -209,7 +207,7 @@ VARIABLE_COMMENT Long search depth for the two-step deadlock detection NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 33 -@@ -694,7 +694,7 @@ READ_ONLY NO +@@ -694,7 +694,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DEADLOCK_SEARCH_DEPTH_SHORT VARIABLE_SCOPE SESSION @@ -218,7 +216,7 @@ VARIABLE_COMMENT Short search depth for the two-step deadlock detection NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 32 -@@ -704,7 +704,7 @@ READ_ONLY NO +@@ -704,7 +704,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DEADLOCK_TIMEOUT_LONG VARIABLE_SCOPE SESSION @@ -227,7 +225,7 @@ VARIABLE_COMMENT Long timeout for the two-step deadlock detection (in microseconds) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -714,7 +714,7 @@ READ_ONLY NO +@@ -714,7 +714,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DEADLOCK_TIMEOUT_SHORT VARIABLE_SCOPE SESSION @@ -236,7 +234,7 @@ VARIABLE_COMMENT Short timeout for the two-step deadlock detection (in microseconds) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -764,7 +764,7 @@ READ_ONLY NO +@@ -764,7 +764,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME DEFAULT_WEEK_FORMAT VARIABLE_SCOPE SESSION @@ -245,7 +243,7 @@ VARIABLE_COMMENT The default week format used by WEEK() functions NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 7 -@@ -774,7 +774,7 @@ READ_ONLY NO +@@ -774,7 +774,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_INSERT_LIMIT VARIABLE_SCOPE GLOBAL @@ -254,7 +252,7 @@ VARIABLE_COMMENT After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -784,7 +784,7 @@ READ_ONLY NO +@@ -784,7 +784,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_INSERT_TIMEOUT VARIABLE_SCOPE GLOBAL @@ -263,7 +261,7 @@ VARIABLE_COMMENT How long a INSERT DELAYED thread should wait for INSERT statements before terminating NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -794,7 +794,7 @@ READ_ONLY NO +@@ -794,7 +794,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME DELAYED_QUEUE_SIZE VARIABLE_SCOPE GLOBAL @@ -272,7 +270,7 @@ VARIABLE_COMMENT What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -824,7 +824,7 @@ READ_ONLY NO +@@ -824,7 +824,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME DIV_PRECISION_INCREMENT VARIABLE_SCOPE SESSION @@ -281,7 +279,7 @@ VARIABLE_COMMENT Precision of the result of '/' operator will be increased on that value NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 38 -@@ -904,7 +904,7 @@ READ_ONLY NO +@@ -904,7 +904,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME EXPIRE_LOGS_DAYS VARIABLE_SCOPE GLOBAL @@ -290,7 +288,7 @@ VARIABLE_COMMENT If non-zero, binary logs will be purged after expire_logs_days days; possible purges happen at startup and at binary log rotation NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 99 -@@ -934,7 +934,7 @@ READ_ONLY YES +@@ -934,7 +934,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME EXTRA_MAX_CONNECTIONS VARIABLE_SCOPE GLOBAL @@ -299,7 +297,7 @@ VARIABLE_COMMENT The number of connections on extra-port NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100000 -@@ -964,7 +964,7 @@ READ_ONLY NO +@@ -964,7 +964,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME FLUSH_TIME VARIABLE_SCOPE GLOBAL @@ -308,7 +306,7 @@ VARIABLE_COMMENT A dedicated thread is created to flush all tables at the given interval NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -994,7 +994,7 @@ READ_ONLY NO +@@ -994,7 +994,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_MAX_WORD_LEN VARIABLE_SCOPE GLOBAL @@ -317,7 +315,7 @@ VARIABLE_COMMENT The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 84 -@@ -1004,7 +1004,7 @@ READ_ONLY YES +@@ -1004,7 +1004,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_MIN_WORD_LEN VARIABLE_SCOPE GLOBAL @@ -326,7 +324,7 @@ VARIABLE_COMMENT The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 84 -@@ -1014,7 +1014,7 @@ READ_ONLY YES +@@ -1014,7 +1014,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME FT_QUERY_EXPANSION_LIMIT VARIABLE_SCOPE GLOBAL @@ -335,7 +333,7 @@ VARIABLE_COMMENT Number of best matches to use for query expansion NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1000 -@@ -1184,7 +1184,7 @@ READ_ONLY YES +@@ -1184,7 +1184,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME HISTOGRAM_SIZE VARIABLE_SCOPE SESSION @@ -344,7 +342,7 @@ VARIABLE_COMMENT Number of bytes used for a histogram. If set to 0, no histograms are created by ANALYZE. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -1214,7 +1214,7 @@ READ_ONLY YES +@@ -1214,7 +1214,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME HOST_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -353,7 +351,7 @@ VARIABLE_COMMENT How many host names should be cached to avoid resolving. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65536 -@@ -1324,7 +1324,7 @@ READ_ONLY NO +@@ -1324,7 +1324,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME INTERACTIVE_TIMEOUT VARIABLE_SCOPE SESSION @@ -362,7 +360,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on an interactive connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -1357,7 +1357,7 @@ VARIABLE_SCOPE SESSION +@@ -1357,7 +1357,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the buffer that is used for joins NUMERIC_MIN_VALUE 128 @@ -371,7 +369,7 @@ NUMERIC_BLOCK_SIZE 128 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1374,7 +1374,7 @@ READ_ONLY NO +@@ -1374,7 +1374,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME JOIN_CACHE_LEVEL VARIABLE_SCOPE SESSION @@ -380,7 +378,7 @@ VARIABLE_COMMENT Controls what join operations can be executed with join buffers. Odd numbers are used for plain join buffers while even numbers are used for linked buffers NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 8 -@@ -1397,7 +1397,7 @@ VARIABLE_SCOPE GLOBAL +@@ -1397,7 +1397,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford NUMERIC_MIN_VALUE 0 @@ -389,7 +387,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1554,7 +1554,7 @@ READ_ONLY YES +@@ -1554,7 +1554,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME LOCK_WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -398,7 +396,7 @@ VARIABLE_COMMENT Timeout in seconds to wait for a lock before returning an error. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -1674,7 +1674,7 @@ READ_ONLY NO +@@ -1674,7 +1674,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_SLOW_RATE_LIMIT VARIABLE_SCOPE SESSION @@ -407,16 +405,16 @@ VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1704,7 +1704,7 @@ READ_ONLY NO +@@ -1704,7 +1704,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME LOG_WARNINGS VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity + VARIABLE_COMMENT Log some non critical warnings to the error log.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1754,7 +1754,7 @@ READ_ONLY NO +@@ -1754,7 +1754,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MAX_ALLOWED_PACKET VARIABLE_SCOPE SESSION @@ -425,7 +423,7 @@ VARIABLE_COMMENT Max packet length to send to or receive from the server NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -1767,14 +1767,14 @@ VARIABLE_SCOPE GLOBAL +@@ -1767,14 +1767,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the total size of the transactional cache NUMERIC_MIN_VALUE 4096 @@ -442,7 +440,7 @@ VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 1073741824 -@@ -1787,14 +1787,14 @@ VARIABLE_SCOPE GLOBAL +@@ -1787,14 +1787,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the total size of the statement cache NUMERIC_MIN_VALUE 4096 @@ -459,7 +457,7 @@ VARIABLE_COMMENT The number of simultaneous clients allowed NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 100000 -@@ -1804,7 +1804,7 @@ READ_ONLY NO +@@ -1804,7 +1804,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_CONNECT_ERRORS VARIABLE_SCOPE GLOBAL @@ -468,7 +466,7 @@ VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1814,7 +1814,7 @@ READ_ONLY NO +@@ -1814,7 +1814,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_DELAYED_THREADS VARIABLE_SCOPE SESSION @@ -477,7 +475,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -1834,7 +1834,7 @@ READ_ONLY YES +@@ -1834,7 +1834,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_ERROR_COUNT VARIABLE_SCOPE SESSION @@ -486,7 +484,7 @@ VARIABLE_COMMENT Max number of errors/warnings to store for a statement NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -1847,14 +1847,14 @@ VARIABLE_SCOPE SESSION +@@ -1847,14 +1847,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't allow creation of heap tables bigger than this NUMERIC_MIN_VALUE 16384 @@ -503,7 +501,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -1874,7 +1874,7 @@ READ_ONLY NO +@@ -1874,7 +1874,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_LENGTH_FOR_SORT_DATA VARIABLE_SCOPE SESSION @@ -512,7 +510,7 @@ VARIABLE_COMMENT Max number of bytes in sorted records NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -1884,7 +1884,7 @@ READ_ONLY NO +@@ -1884,7 +1884,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_LONG_DATA_SIZE VARIABLE_SCOPE GLOBAL @@ -521,7 +519,7 @@ VARIABLE_COMMENT The maximum BLOB length to send to server from mysql_send_long_data API. Deprecated option; use max_allowed_packet instead. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -1914,7 +1914,7 @@ READ_ONLY NO +@@ -1914,7 +1914,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_RECURSIVE_ITERATIONS VARIABLE_SCOPE SESSION @@ -530,7 +528,7 @@ VARIABLE_COMMENT Maximum number of iterations when executing recursive queries NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1927,14 +1927,14 @@ VARIABLE_SCOPE SESSION +@@ -1927,14 +1927,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The maximum size of the container of a rowid filter NUMERIC_MIN_VALUE 1024 @@ -547,7 +545,7 @@ VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1954,7 +1954,7 @@ READ_ONLY NO +@@ -1954,7 +1954,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SORT_LENGTH VARIABLE_SCOPE SESSION @@ -556,7 +554,7 @@ VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) NUMERIC_MIN_VALUE 64 NUMERIC_MAX_VALUE 8388608 -@@ -1964,7 +1964,7 @@ READ_ONLY NO +@@ -1964,7 +1964,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SP_RECURSION_DEPTH VARIABLE_SCOPE SESSION @@ -565,7 +563,7 @@ VARIABLE_COMMENT Maximum stored procedure recursion depth NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -1984,7 +1984,7 @@ READ_ONLY NO +@@ -1984,7 +1984,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_TMP_TABLES VARIABLE_SCOPE SESSION @@ -574,7 +572,7 @@ VARIABLE_COMMENT Unused, will be removed. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2004,7 +2004,7 @@ READ_ONLY NO +@@ -2004,7 +2004,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_WRITE_LOCK_COUNT VARIABLE_SCOPE GLOBAL @@ -583,7 +581,7 @@ VARIABLE_COMMENT After this many write locks, allow some read locks to run in between NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2014,7 +2014,7 @@ READ_ONLY NO +@@ -2014,7 +2014,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME METADATA_LOCKS_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -592,7 +590,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -2024,7 +2024,7 @@ READ_ONLY YES +@@ -2024,7 +2024,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME METADATA_LOCKS_HASH_INSTANCES VARIABLE_SCOPE GLOBAL @@ -601,7 +599,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -2034,7 +2034,7 @@ READ_ONLY YES +@@ -2034,7 +2034,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MIN_EXAMINED_ROW_LIMIT VARIABLE_SCOPE SESSION @@ -610,7 +608,7 @@ VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2044,7 +2044,7 @@ READ_ONLY NO +@@ -2044,7 +2044,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MRR_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -619,7 +617,7 @@ VARIABLE_COMMENT Size of buffer to use when using MRR with range access NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2054,17 +2054,17 @@ READ_ONLY NO +@@ -2054,17 +2054,17 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MULTI_RANGE_COUNT VARIABLE_SCOPE SESSION @@ -640,7 +638,7 @@ VARIABLE_COMMENT Block size to be used for MyISAM index pages NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 16384 -@@ -2074,7 +2074,7 @@ READ_ONLY YES +@@ -2074,7 +2074,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_DATA_POINTER_SIZE VARIABLE_SCOPE GLOBAL @@ -649,7 +647,7 @@ VARIABLE_COMMENT Default pointer size to be used for MyISAM tables NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 7 -@@ -2097,7 +2097,7 @@ VARIABLE_SCOPE GLOBAL +@@ -2097,7 +2097,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Restricts the total memory used for memory mapping of MySQL tables NUMERIC_MIN_VALUE 7 @@ -658,7 +656,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -2114,10 +2114,10 @@ READ_ONLY YES +@@ -2114,10 +2114,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME MYISAM_REPAIR_THREADS VARIABLE_SCOPE SESSION @@ -671,7 +669,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2127,7 +2127,7 @@ VARIABLE_SCOPE SESSION +@@ -2127,7 +2127,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE NUMERIC_MIN_VALUE 4096 @@ -680,7 +678,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2164,7 +2164,7 @@ READ_ONLY NO +@@ -2164,7 +2164,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME NET_BUFFER_LENGTH VARIABLE_SCOPE SESSION @@ -689,7 +687,7 @@ VARIABLE_COMMENT Buffer length for TCP/IP and socket communication NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1048576 -@@ -2174,7 +2174,7 @@ READ_ONLY NO +@@ -2174,7 +2174,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_READ_TIMEOUT VARIABLE_SCOPE SESSION @@ -698,7 +696,7 @@ VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2184,7 +2184,7 @@ READ_ONLY NO +@@ -2184,7 +2184,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_RETRY_COUNT VARIABLE_SCOPE SESSION @@ -707,7 +705,7 @@ VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2194,7 +2194,7 @@ READ_ONLY NO +@@ -2194,7 +2194,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME NET_WRITE_TIMEOUT VARIABLE_SCOPE SESSION @@ -716,7 +714,7 @@ VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2244,7 +2244,7 @@ READ_ONLY NO +@@ -2244,7 +2244,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL @@ -725,7 +723,7 @@ VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2254,7 +2254,7 @@ READ_ONLY YES +@@ -2254,7 +2254,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_PRUNE_LEVEL VARIABLE_SCOPE SESSION @@ -734,7 +732,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1 -@@ -2264,7 +2264,7 @@ READ_ONLY NO +@@ -2264,7 +2264,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SEARCH_DEPTH VARIABLE_SCOPE SESSION @@ -743,7 +741,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2274,7 +2274,7 @@ READ_ONLY NO +@@ -2274,7 +2274,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SELECTIVITY_SAMPLING_LIMIT VARIABLE_SCOPE SESSION @@ -752,7 +750,7 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2304,17 +2304,17 @@ READ_ONLY NO +@@ -2304,17 +2304,17 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_TRACE_MAX_MEM_SIZE VARIABLE_SCOPE SESSION @@ -773,7 +771,7 @@ VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2334,7 +2334,7 @@ READ_ONLY YES +@@ -2334,7 +2334,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME PERFORMANCE_SCHEMA_ACCOUNTS_SIZE VARIABLE_SCOPE GLOBAL @@ -782,7 +780,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2344,7 +2344,7 @@ READ_ONLY YES +@@ -2344,7 +2344,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_DIGESTS_SIZE VARIABLE_SCOPE GLOBAL @@ -791,7 +789,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2354,7 +2354,7 @@ READ_ONLY YES +@@ -2354,7 +2354,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -800,7 +798,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2364,7 +2364,7 @@ READ_ONLY YES +@@ -2364,7 +2364,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -809,7 +807,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2374,7 +2374,7 @@ READ_ONLY YES +@@ -2374,7 +2374,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -818,7 +816,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2384,7 +2384,7 @@ READ_ONLY YES +@@ -2384,7 +2384,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -827,7 +825,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2394,7 +2394,7 @@ READ_ONLY YES +@@ -2394,7 +2394,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -836,7 +834,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2404,7 +2404,7 @@ READ_ONLY YES +@@ -2404,7 +2404,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -845,7 +843,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2414,7 +2414,7 @@ READ_ONLY YES +@@ -2414,7 +2414,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_HOSTS_SIZE VARIABLE_SCOPE GLOBAL @@ -854,7 +852,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2424,7 +2424,7 @@ READ_ONLY YES +@@ -2424,7 +2424,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_CLASSES VARIABLE_SCOPE GLOBAL @@ -863,7 +861,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2434,7 +2434,7 @@ READ_ONLY YES +@@ -2434,7 +2434,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_INSTANCES VARIABLE_SCOPE GLOBAL @@ -872,7 +870,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2444,7 +2444,7 @@ READ_ONLY YES +@@ -2444,7 +2444,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_DIGEST_LENGTH VARIABLE_SCOPE GLOBAL @@ -881,7 +879,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2454,7 +2454,7 @@ READ_ONLY YES +@@ -2454,7 +2454,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_CLASSES VARIABLE_SCOPE GLOBAL @@ -890,7 +888,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2464,7 +2464,7 @@ READ_ONLY YES +@@ -2464,7 +2464,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_HANDLES VARIABLE_SCOPE GLOBAL @@ -899,7 +897,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2474,7 +2474,7 @@ READ_ONLY YES +@@ -2474,7 +2474,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -908,7 +906,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2484,7 +2484,7 @@ READ_ONLY YES +@@ -2484,7 +2484,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_CLASSES VARIABLE_SCOPE GLOBAL @@ -917,7 +915,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2494,7 +2494,7 @@ READ_ONLY YES +@@ -2494,7 +2494,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_INSTANCES VARIABLE_SCOPE GLOBAL @@ -926,7 +924,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2504,7 +2504,7 @@ READ_ONLY YES +@@ -2504,7 +2504,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_CLASSES VARIABLE_SCOPE GLOBAL @@ -935,7 +933,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2514,7 +2514,7 @@ READ_ONLY YES +@@ -2514,7 +2514,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_INSTANCES VARIABLE_SCOPE GLOBAL @@ -944,7 +942,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2524,7 +2524,7 @@ READ_ONLY YES +@@ -2524,7 +2524,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_CLASSES VARIABLE_SCOPE GLOBAL @@ -953,7 +951,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2534,7 +2534,7 @@ READ_ONLY YES +@@ -2534,7 +2534,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_INSTANCES VARIABLE_SCOPE GLOBAL @@ -962,7 +960,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2544,7 +2544,7 @@ READ_ONLY YES +@@ -2544,7 +2544,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STAGE_CLASSES VARIABLE_SCOPE GLOBAL @@ -971,7 +969,7 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2554,7 +2554,7 @@ READ_ONLY YES +@@ -2554,7 +2554,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES VARIABLE_SCOPE GLOBAL @@ -980,7 +978,7 @@ VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2564,7 +2564,7 @@ READ_ONLY YES +@@ -2564,7 +2564,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_HANDLES VARIABLE_SCOPE GLOBAL @@ -989,7 +987,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2574,7 +2574,7 @@ READ_ONLY YES +@@ -2574,7 +2574,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -998,7 +996,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2584,7 +2584,7 @@ READ_ONLY YES +@@ -2584,7 +2584,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_CLASSES VARIABLE_SCOPE GLOBAL @@ -1007,7 +1005,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2594,7 +2594,7 @@ READ_ONLY YES +@@ -2594,7 +2594,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1016,7 +1014,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2604,7 +2604,7 @@ READ_ONLY YES +@@ -2604,7 +2604,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SESSION_CONNECT_ATTRS_SIZE VARIABLE_SCOPE GLOBAL @@ -1025,7 +1023,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2614,7 +2614,7 @@ READ_ONLY YES +@@ -2614,7 +2614,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_ACTORS_SIZE VARIABLE_SCOPE GLOBAL @@ -1034,7 +1032,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -2624,7 +2624,7 @@ READ_ONLY YES +@@ -2624,7 +2624,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_OBJECTS_SIZE VARIABLE_SCOPE GLOBAL @@ -1043,7 +1041,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2634,7 +2634,7 @@ READ_ONLY YES +@@ -2634,7 +2634,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_USERS_SIZE VARIABLE_SCOPE GLOBAL @@ -1052,7 +1050,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2684,7 +2684,7 @@ READ_ONLY YES +@@ -2684,7 +2684,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PRELOAD_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1061,7 +1059,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -2704,7 +2704,7 @@ READ_ONLY NO +@@ -2704,7 +2704,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME PROFILING_HISTORY_SIZE VARIABLE_SCOPE SESSION @@ -1070,7 +1068,7 @@ VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -2714,7 +2714,7 @@ READ_ONLY NO +@@ -2714,7 +2714,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PROGRESS_REPORT_TIME VARIABLE_SCOPE SESSION @@ -1079,7 +1077,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2774,7 +2774,7 @@ READ_ONLY NO +@@ -2774,7 +2774,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME QUERY_ALLOC_BLOCK_SIZE VARIABLE_SCOPE SESSION @@ -1088,7 +1086,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -2784,7 +2784,7 @@ READ_ONLY NO +@@ -2784,7 +2784,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_LIMIT VARIABLE_SCOPE GLOBAL @@ -1097,7 +1095,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2794,7 +2794,7 @@ READ_ONLY NO +@@ -2794,7 +2794,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_MIN_RES_UNIT VARIABLE_SCOPE GLOBAL @@ -1106,7 +1104,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2807,7 +2807,7 @@ VARIABLE_SCOPE GLOBAL +@@ -2807,7 +2807,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1115,7 +1113,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2844,7 +2844,7 @@ READ_ONLY NO +@@ -2844,7 +2844,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME QUERY_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1124,7 +1122,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -2857,7 +2857,7 @@ VARIABLE_SCOPE SESSION ONLY +@@ -2857,7 +2857,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1133,7 +1131,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2867,14 +2867,14 @@ VARIABLE_SCOPE SESSION ONLY +@@ -2867,14 +2867,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1150,7 +1148,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -2884,7 +2884,7 @@ READ_ONLY NO +@@ -2884,7 +2884,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME READ_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1159,7 +1157,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2904,7 +2904,7 @@ READ_ONLY NO +@@ -2904,7 +2904,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME READ_RND_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1168,7 +1166,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -2914,10 +2914,10 @@ READ_ONLY NO +@@ -2914,10 +2914,10 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ROWID_MERGE_BUFF_SIZE VARIABLE_SCOPE SESSION @@ -1181,7 +1179,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2954,7 +2954,7 @@ READ_ONLY YES +@@ -2954,7 +2954,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SERVER_ID VARIABLE_SCOPE SESSION @@ -1190,7 +1188,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -3024,7 +3024,7 @@ READ_ONLY NO +@@ -3024,7 +3024,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET VARIABLE_SCOPE GLOBAL @@ -1199,7 +1197,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3034,7 +3034,7 @@ READ_ONLY NO +@@ -3034,7 +3034,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLOW_LAUNCH_TIME VARIABLE_SCOPE GLOBAL @@ -1208,7 +1206,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -3077,7 +3077,7 @@ VARIABLE_SCOPE SESSION +@@ -3077,7 +3077,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1217,7 +1215,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3284,7 +3284,7 @@ READ_ONLY NO +@@ -3284,7 +3284,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME STORED_PROGRAM_CACHE VARIABLE_SCOPE GLOBAL @@ -1226,7 +1224,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -3364,7 +3364,7 @@ READ_ONLY NO +@@ -3364,7 +3364,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TABLE_DEFINITION_CACHE VARIABLE_SCOPE GLOBAL @@ -1235,7 +1233,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 2097152 -@@ -3374,7 +3374,7 @@ READ_ONLY NO +@@ -3374,7 +3374,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TABLE_OPEN_CACHE VARIABLE_SCOPE GLOBAL @@ -1244,7 +1242,7 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 1048576 -@@ -3434,7 +3434,7 @@ READ_ONLY NO +@@ -3434,7 +3434,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME THREAD_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -1253,7 +1251,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -3444,7 +3444,7 @@ READ_ONLY NO +@@ -3444,7 +3444,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_CONCURRENCY VARIABLE_SCOPE GLOBAL @@ -1262,7 +1260,7 @@ VARIABLE_COMMENT Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.This variable has no effect, and is deprecated. It will be removed in a future release. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 512 -@@ -3537,7 +3537,7 @@ VARIABLE_SCOPE SESSION +@@ -3537,7 +3537,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Max size for data for an internal temporary on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1271,7 +1269,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3547,7 +3547,7 @@ VARIABLE_SCOPE SESSION +@@ -3547,7 +3547,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. Same as tmp_table_size. NUMERIC_MIN_VALUE 1024 @@ -1280,7 +1278,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3557,14 +3557,14 @@ VARIABLE_SCOPE SESSION +@@ -3557,14 +3557,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Alias for tmp_memory_table_size. If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1297,7 +1295,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -3574,7 +3574,7 @@ READ_ONLY NO +@@ -3574,7 +3574,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TRANSACTION_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1306,7 +1304,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -3714,7 +3714,7 @@ READ_ONLY YES +@@ -3714,7 +3714,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -1315,7 +1313,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -3741,7 +3741,7 @@ order by variable_name; +@@ -3741,7 +3741,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff index 11f8189b592..b5793f70046 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff @@ -1,5 +1,3 @@ ---- suite/sys_vars/r/sysvars_server_notembedded.result 2023-05-02 23:37:10.180795104 +0300 -+++ suite/sys_vars/r/sysvars_server_notembedded,32bit.reject 2023-05-24 15:07:00.882252929 +0300 @@ -34,7 +34,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_BLOCK_SIZE @@ -413,7 +411,7 @@ VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity + VARIABLE_COMMENT Log some non critical warnings to the error log.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 @@ -1904,7 +1904,7 @@ From dec4d0badc2ef79eb3746f8bfa2a29d351e8b6e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 13 Nov 2023 14:35:33 +0200 Subject: [PATCH 232/477] MDEV-32788: Debug build failure with SUX_LOCK_GENERIC Fixes up commit 2027c482de0a75ff09fd08704cdbe36dcf5db91e --- storage/innobase/trx/trx0purge.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 592b8a5371c..0f55892a105 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -852,7 +852,9 @@ void purge_sys_t::rseg_get_next_history_log() { fil_addr_t prev_log_addr; +#ifndef SUX_LOCK_GENERIC ut_ad(rseg->latch.is_write_locked()); +#endif ut_a(rseg->last_page_no != FIL_NULL); tail.trx_no= rseg->last_trx_no() + 1; @@ -968,7 +970,9 @@ 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()); +#ifndef SUX_LOCK_GENERIC ut_ad(rseg->latch.is_write_locked()); +#endif if (!offset) { From be55051b6b6503b00ead636cf87a82ef6fab7961 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Mon, 13 Nov 2023 13:19:39 -0500 Subject: [PATCH 233/477] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 203fc146cec..ed7e2ff7acf 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=4 -MYSQL_VERSION_PATCH=32 +MYSQL_VERSION_PATCH=33 SERVER_MATURITY=stable From 8b84fb13837d0964211d52916e2eea82bb3d2e16 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Mon, 13 Nov 2023 13:21:35 -0500 Subject: [PATCH 234/477] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0f8a4608896..e7b29db2217 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=23 +MYSQL_VERSION_PATCH=24 SERVER_MATURITY=stable From 91835ef3788a76d7396b00335458610b315517b7 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Mon, 13 Nov 2023 13:22:44 -0500 Subject: [PATCH 235/477] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index c8596588b6b..9402abb61e9 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=6 -MYSQL_VERSION_PATCH=16 +MYSQL_VERSION_PATCH=17 SERVER_MATURITY=stable From ecce948ad7e0a25f920c9312a12dfb7e47eab4a9 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Mon, 13 Nov 2023 14:39:41 -0500 Subject: [PATCH 236/477] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 1db717e2370..7dd56698644 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=11 -MYSQL_VERSION_PATCH=6 +MYSQL_VERSION_PATCH=7 SERVER_MATURITY=stable From 7f2fae7b212ec6ed13ec30ec80208f6c770a16dd Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Mon, 13 Nov 2023 14:40:46 -0500 Subject: [PATCH 237/477] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 18b3c9acff0..45539fc57d9 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=11 MYSQL_VERSION_MINOR=0 -MYSQL_VERSION_PATCH=4 +MYSQL_VERSION_PATCH=5 SERVER_MATURITY=stable From 28c86f81f43c765bb1b1f82515111dda36dbe9e3 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Mon, 13 Nov 2023 14:41:25 -0500 Subject: [PATCH 238/477] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index d48d63e88e4..b69af7f8e25 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=11 MYSQL_VERSION_MINOR=1 -MYSQL_VERSION_PATCH=3 +MYSQL_VERSION_PATCH=4 SERVER_MATURITY=stable From 6cf776b68d2671bd78c012b8dd9f55623144652e Mon Sep 17 00:00:00 2001 From: Ian Gilfillan Date: Mon, 13 Nov 2023 19:34:26 +0200 Subject: [PATCH 239/477] Update earliest verson in PR template --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index c97f9827e59..b519bfd8f3c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -32,7 +32,7 @@ Without automated tests, future regressions in the expected behavior can't be au If the changes are not amenable to automated testing, please explain why not and carefully describe how to test manually. ## Basing the PR against the correct MariaDB version - [ ] *This is a new feature and the PR is based against the latest MariaDB development branch.* From 09fba0e89f1b7c15bbf0336134366d35d340c919 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Mon, 13 Nov 2023 14:40:46 -0500 Subject: [PATCH 240/477] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 18b3c9acff0..45539fc57d9 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=11 MYSQL_VERSION_MINOR=0 -MYSQL_VERSION_PATCH=4 +MYSQL_VERSION_PATCH=5 SERVER_MATURITY=stable From 5b9a7871cad5025b581db2d5f6ba66cb1d29298d Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 14 Nov 2023 07:12:23 +1100 Subject: [PATCH 241/477] MDEV-32776 plugin disks getmntinfo64 deprecated on macOS The getmntinfo64 interface is deprected in MacOSX12.1.sdk. Using getmntinfo instead. Thanks heyingquay for reporting the bug and testing the fix. --- plugin/disks/CMakeLists.txt | 3 +-- plugin/disks/information_schema_disks.cc | 7 +------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/plugin/disks/CMakeLists.txt b/plugin/disks/CMakeLists.txt index 4e40842cad0..e4cf0dc1de3 100644 --- a/plugin/disks/CMakeLists.txt +++ b/plugin/disks/CMakeLists.txt @@ -4,7 +4,6 @@ CHECK_SYMBOL_EXISTS (getmntent "mntent.h" HAVE_GETMNTENT) CHECK_SYMBOL_EXISTS (getmntent "sys/mnttab.h" HAVE_GETMNTENT_IN_SYS_MNTAB) CHECK_SYMBOL_EXISTS (setmntent "mntent.h" HAVE_SETMNTENT) CHECK_SYMBOL_EXISTS (getmntinfo "sys/types.h;sys/mount.h" HAVE_GETMNTINFO) -CHECK_SYMBOL_EXISTS (getmntinfo64 "sys/types.h;sys/mount.h" HAVE_GETMNTINFO64) IF (HAVE_GETMNTINFO) CHECK_CXX_SOURCE_COMPILES(" @@ -18,7 +17,7 @@ int main() " HAVE_GETMNTINFO_TAKES_statvfs) ENDIF() IF (HAVE_GETMNTENT OR HAVE_GETMNTENT_IN_SYS_MNTAB OR - HAVE_GETMNTINFO OR HAVE_GETMNTINFO64) + HAVE_GETMNTINFO) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql) MYSQL_ADD_PLUGIN(DISKS information_schema_disks.cc MODULE_ONLY RECOMPILE_FOR_EMBEDDED) ENDIF() diff --git a/plugin/disks/information_schema_disks.cc b/plugin/disks/information_schema_disks.cc index bfae81eceac..01c6c0e173f 100644 --- a/plugin/disks/information_schema_disks.cc +++ b/plugin/disks/information_schema_disks.cc @@ -37,8 +37,7 @@ This intends to support *BSD's, macOS, Solaris, AIX, HP-UX, and Linux. specificly: - FreeBSD/OpenBSD/DragonFly (statfs) NetBSD (statvfs) uses getmntinfo(). - macOS uses getmntinfo64(). + FreeBSD/OpenBSD/DragonFly/macOS (statfs) NetBSD (statvfs) uses getmntinfo(). Linux can use getmntent_r(), but we've just used getmntent for simplification. Linux/Solaris/AIX/HP-UX uses setmntent()/getmntent(). Solaris uses getmntent() with a diffent prototype, return structure, and @@ -46,8 +45,6 @@ */ #if defined(HAVE_GETMNTINFO_TAKES_statvfs) || defined(HAVE_GETMNTENT) typedef struct statvfs st_info; -#elif defined(HAVE_GETMNTINFO64) -typedef struct statfs64 st_info; #else // GETMNTINFO typedef struct statfs st_info; #endif @@ -148,8 +145,6 @@ static int disks_fill_table(THD* pThd, TABLE_LIST* pTables, Item* pCond) #if defined(HAVE_GETMNTINFO_TAKES_statvfs) count= getmntinfo(&s, ST_WAIT); -#elif defined(HAVE_GETMNTINFO64) - count= getmntinfo64(&s, MNT_WAIT); #else count= getmntinfo(&s, MNT_WAIT); #endif From 93bdb6db4d71f19348a412d065c2d9a89fa9765a Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Fri, 10 Nov 2023 17:46:19 +0700 Subject: [PATCH 242/477] MDEV-32733: Two JSON related tests running in PS mode fail on server built with -DWITH_PROTECT_STATEMENT_MEMROOT=YES The tests main.func_json and json.json_no_table fail on server built with the option -DWITH_PROTECT_STATEMENT_MEMROOT=YES by the reason that a memory is allocated on the statement's memory root on the second execution of a query that uses the function json_contains_path(). The reason that a memory is allocated on second execution of a prepared statement that ivokes the function json_contains_path() is that a memory allocated on every call of the method Item_json_str_multipath::fix_fields To fix the issue, memory allocation should be done only once on first call of the method Item_json_str_multipath::fix_fields. Simmilar issue take place inside the method Item_func_json_contains_path::fix_fields. Both methods are modified to make memory allocation only once on its first execution and later re-use the allocated memory. Before this patch the memory referenced by the pointers stored in the array tmp_paths were released by the method Item_func_json_contains_path::cleanup that is called on finishing execution of a prepared statement. Now that memory allocation performed inside the method Item_json_str_multipath::fix_fields is done only once, the item clean up has degenerate form and can be delegated to the cleanup() method of the base class and memory deallocation can be performed in the destructor. --- mysql-test/main/ps_mem_leaks.result | 12 ++++++ mysql-test/main/ps_mem_leaks.test | 11 +++++ sql/item_jsonfunc.cc | 67 +++++++++++++++++++++-------- sql/item_jsonfunc.h | 21 +++++++-- 4 files changed, 91 insertions(+), 20 deletions(-) diff --git a/mysql-test/main/ps_mem_leaks.result b/mysql-test/main/ps_mem_leaks.result index df4a55b9ed2..6a1155dbafe 100644 --- a/mysql-test/main/ps_mem_leaks.result +++ b/mysql-test/main/ps_mem_leaks.result @@ -45,4 +45,16 @@ a b DEALLOCATE PREPARE stmt; DROP TABLE t1,t2; +# +# MDEV-32733: Two JSON related tests running in PS mode fail on server +# built with -DWITH_PROTECT_STATEMENT_MEMROOT=YES +# +PREPARE stmt FROM "select json_contains_path('{\"key1\":1}', 'oNE', '$.key2[1]') as exp"; +EXECUTE stmt; +exp +0 +EXECUTE stmt; +exp +0 +DEALLOCATE PREPARE stmt; # End of 10.4 tests diff --git a/mysql-test/main/ps_mem_leaks.test b/mysql-test/main/ps_mem_leaks.test index 169631146fe..90de38ad482 100644 --- a/mysql-test/main/ps_mem_leaks.test +++ b/mysql-test/main/ps_mem_leaks.test @@ -58,4 +58,15 @@ DEALLOCATE PREPARE stmt; DROP TABLE t1,t2; +--echo # +--echo # MDEV-32733: Two JSON related tests running in PS mode fail on server +--echo # built with -DWITH_PROTECT_STATEMENT_MEMROOT=YES +--echo # +PREPARE stmt FROM "select json_contains_path('{\"key1\":1}', 'oNE', '$.key2[1]') as exp"; + +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; + --echo # End of 10.4 tests diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index ece35a40835..ffa43f542ed 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -859,21 +859,47 @@ static void mark_constant_paths(json_path_with_flags *p, } -bool Item_json_str_multipath::fix_fields(THD *thd, Item **ref) -{ - return alloc_tmp_paths(thd, get_n_paths(), &paths, &tmp_paths) || - Item_str_func::fix_fields(thd, ref); -} - - -void Item_json_str_multipath::cleanup() +Item_json_str_multipath::~Item_json_str_multipath() { if (tmp_paths) { - for (uint i= get_n_paths(); i>0; i--) + for (uint i= n_paths; i>0; i--) tmp_paths[i-1].free(); } - Item_str_func::cleanup(); +} + + +bool Item_json_str_multipath::fix_fields(THD *thd, Item **ref) +{ + if (!tmp_paths) + { + /* + Remember the number of paths and allocate required memory on first time + the method fix_fields() is invoked. For prepared statements the method + fix_fields can be called several times for the same item because its + clean up is performed every item a prepared statement finishing its + execution. In result, the data member fixed is reset and the method + fix_field() is invoked on next time the same prepared statement be + executed. On the other side, any memory allocations on behalf of + the prepared statement must be performed only once on its first execution. + The data member tmp_path is kind a guard to do these activities only once + on first time the method fix_field() is called. + */ + n_paths= get_n_paths(); + + if (alloc_tmp_paths(thd, n_paths, &paths, &tmp_paths)) + return true; + } + +#ifdef PROTECT_STATEMENT_MEMROOT + /* + Check that the number of paths remembered on first run of a statement + never changed later. + */ + DBUG_ASSERT(n_paths == get_n_paths()); +#endif + + return Item_str_func::fix_fields(thd, ref); } @@ -1404,10 +1430,19 @@ return_null: bool Item_func_json_contains_path::fix_fields(THD *thd, Item **ref) { - return alloc_tmp_paths(thd, arg_count-2, &paths, &tmp_paths) || - (p_found= (bool *) alloc_root(thd->mem_root, - (arg_count-2)*sizeof(bool))) == NULL || - Item_int_func::fix_fields(thd, ref); + /* + See comments on Item_json_str_multipath::fix_fields regarding + the aim of the condition 'if (!tmp_paths)'. + */ + if (!tmp_paths) + { + if (alloc_tmp_paths(thd, arg_count-2, &paths, &tmp_paths) || + (p_found= (bool *) alloc_root(thd->mem_root, + (arg_count-2)*sizeof(bool))) == NULL) + return true; + } + + return Item_int_func::fix_fields(thd, ref); } @@ -1420,8 +1455,7 @@ bool Item_func_json_contains_path::fix_length_and_dec() return Item_bool_func::fix_length_and_dec(); } - -void Item_func_json_contains_path::cleanup() +Item_func_json_contains_path::~Item_func_json_contains_path() { if (tmp_paths) { @@ -1429,7 +1463,6 @@ void Item_func_json_contains_path::cleanup() tmp_paths[i-1].free(); tmp_paths= 0; } - Item_int_func::cleanup(); } diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h index b44207ec73f..24de77a2bc1 100644 --- a/sql/item_jsonfunc.h +++ b/sql/item_jsonfunc.h @@ -144,11 +144,26 @@ class Item_json_str_multipath: public Item_str_func protected: json_path_with_flags *paths; String *tmp_paths; +private: + /** + Number of paths returned by calling virtual method get_n_paths() and + remembered inside fix_fields(). It is used by the virtual destructor + ~Item_json_str_multipath() to iterate along allocated memory chunks stored + in the array tmp_paths and free every of them. The virtual method + get_n_paths() can't be used for this goal from within virtual destructor. + We could get rid of the virtual method get_n_paths() and store the number + of paths directly in the constructor of classes derived from the class + Item_json_str_multipath but presence of the method get_n_paths() allows + to check invariant that the number of arguments not changed between + sequential runs of the same prepared statement that seems to be useful. + */ + uint n_paths; public: Item_json_str_multipath(THD *thd, List &list): - Item_str_func(thd, list), tmp_paths(0) {} + Item_str_func(thd, list), paths(NULL), tmp_paths(0), n_paths(0) {} + virtual ~Item_json_str_multipath(); + bool fix_fields(THD *thd, Item **ref); - void cleanup(); virtual uint get_n_paths() const = 0; bool is_json_type() { return true; } }; @@ -208,10 +223,10 @@ protected: public: Item_func_json_contains_path(THD *thd, List &list): Item_bool_func(thd, list), tmp_paths(0) {} + virtual ~Item_func_json_contains_path(); const char *func_name() const { return "json_contains_path"; } bool fix_fields(THD *thd, Item **ref); bool fix_length_and_dec(); - void cleanup(); longlong val_int(); Item *get_copy(THD *thd) { return get_item_copy(thd, this); } From ae0afad56ffc86f69555ae31d681232b1cd04825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 14 Nov 2023 14:21:41 +0200 Subject: [PATCH 243/477] MDEV-32746 SIGSEGV on recovery when using innodb_encrypt_log and PMEM recv_ring::copy_if_needed(): If len==0, do not decrypt anything, to avoid unnecessary work and a possible crash. This is similar to the condition recv_buf::copy_if_needed() where a similar condition was present since the beginning (commit 685d958e38b825ad9829be311f26729cccf37c46). Tested by: Matthias Leich --- storage/innobase/log/log0recv.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 3c3fe41e965..a4522dc17dc 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2409,7 +2409,7 @@ struct recv_ring : public recv_buf { const size_t s(*this - start); ut_ad(s + len <= srv_page_size); - if (!log_sys.is_encrypted()) + if (!len || !log_sys.is_encrypted()) { if (start.ptr + s == ptr && ptr + len <= end()) return ptr; From c638051d808a7b29b10e231c9eae97d5909d17f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 14 Nov 2023 14:35:51 +0200 Subject: [PATCH 244/477] MDEV-32798 innodb_fast_shutdown=0 hang after incomplete startup innodb_preshutdown(): Only wait for active transactions to be terminated if InnoDB was started and innodb_force_recovery=3 or larger does not prevent a rollback. This fixes the following: ./mtr --parallel=auto --mysqld=--innodb-fast-shutdown=0 \ innodb.log_file_size innodb.innodb_force_recovery \ innodb.read_only_recovery innodb.read_only_recover_committed \ mariabackup.apply-log-only-incr --- 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 9b8ce4b2fa8..6f40df82f8f 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1995,7 +1995,7 @@ void innodb_preshutdown() better prevent any further changes from being buffered. */ innodb_change_buffering= 0; - if (trx_sys.is_initialised()) + if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO && srv_was_started) while (trx_sys.any_active_transactions()) os_thread_sleep(1000); } From edb98da79a6487d93546d2059cd7c048e120e8aa Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 14 Nov 2023 19:22:56 +0530 Subject: [PATCH 245/477] MDEV-32050 Fixup - Fixing mariabackup.full_backup test case --- mysql-test/suite/mariabackup/full_backup.result | 8 ++++++++ mysql-test/suite/mariabackup/full_backup.test | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/mysql-test/suite/mariabackup/full_backup.result b/mysql-test/suite/mariabackup/full_backup.result index 1d0dffd528d..71525c22080 100644 --- a/mysql-test/suite/mariabackup/full_backup.result +++ b/mysql-test/suite/mariabackup/full_backup.result @@ -18,6 +18,12 @@ DROP TABLE t; # call mtr.add_suppression("InnoDB: innodb_undo_tablespaces=0 disables dedicated undo log tablespaces"); call mtr.add_suppression("InnoDB: Cannot change innodb_undo_tablespaces=0 because previous shutdown was not with innodb_fast_shutdown=0"); +call mtr.add_suppression("Found 1 prepared XA transactions"); +CREATE TABLE t(f1 INT NOT NULL)ENGINE=InnoDB; +XA START 'zombie'; +INSERT INTO t VALUES(1); +XA END 'zombie'; +XA PREPARE 'zombie'; # restart: --innodb_undo_tablespaces=0 # xtrabackup backup # xtrabackup prepare @@ -28,3 +34,5 @@ call mtr.add_suppression("InnoDB: Cannot change innodb_undo_tablespaces=0 becaus # Display undo log files from target directory undo001 undo002 +XA COMMIT 'zombie'; +DROP TABLE t; diff --git a/mysql-test/suite/mariabackup/full_backup.test b/mysql-test/suite/mariabackup/full_backup.test index fb043f63be0..c6a21112b60 100644 --- a/mysql-test/suite/mariabackup/full_backup.test +++ b/mysql-test/suite/mariabackup/full_backup.test @@ -35,6 +35,13 @@ rmdir $targetdir; --echo # call mtr.add_suppression("InnoDB: innodb_undo_tablespaces=0 disables dedicated undo log tablespaces"); call mtr.add_suppression("InnoDB: Cannot change innodb_undo_tablespaces=0 because previous shutdown was not with innodb_fast_shutdown=0"); +call mtr.add_suppression("Found 1 prepared XA transactions"); + +CREATE TABLE t(f1 INT NOT NULL)ENGINE=InnoDB; +XA START 'zombie'; +INSERT INTO t VALUES(1); +XA END 'zombie'; +XA PREPARE 'zombie'; let $restart_parameters=--innodb_undo_tablespaces=0; --source include/restart_mysqld.inc @@ -53,4 +60,6 @@ exec $XTRABACKUP --prepare --target-dir=$targetdir; --echo # Display undo log files from target directory list_files $targetdir undo*; +XA COMMIT 'zombie'; +DROP TABLE t; rmdir $targetdir; From c11610f5900cdb35e1a5410ed0b4ff9d684c9729 Mon Sep 17 00:00:00 2001 From: Tuukka Pasanen Date: Mon, 6 Nov 2023 09:06:00 +0200 Subject: [PATCH 246/477] MDEV-32689: Remove Ubuntu Bionic Commit Removed Ubuntu Bionic from debian/autobake-debs.sh as it's not used anymore to build official MariaDB images --- debian/autobake-deb.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/debian/autobake-deb.sh b/debian/autobake-deb.sh index 0ceabf8b1de..4213593a4b2 100755 --- a/debian/autobake-deb.sh +++ b/debian/autobake-deb.sh @@ -122,10 +122,6 @@ in # there is intentionally no customizations whatsoever. ;; # Ubuntu - "bionic") - remove_rocksdb_tools - [ "$architecture" != amd64 ] && disable_pmem - ;& "focal") replace_uring_with_aio ;& From d59d88363162fb272c28a2d3390b35deb3b7cb7a Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Mon, 13 Nov 2023 15:28:19 +0100 Subject: [PATCH 247/477] MDEV-32771 Server crash upon online alter with concurrent XA In case of a non-recovery XA rollback/commit in the same connection, thon->rollback is called instead of rollback_by_xid, Though previously, thd_ha_data was moved to thd->transaction->xid_state.xid in hton->prepare. Like it wasn't enough, XA PREPARE can be skipped upon user and thus we can end up in hton->commit/rollback with and unprepared XA, so checking xid_state.is_explicit_XA is not enough -- we should check xid_state.get_state_code() == XA_PREPARED, which will also guarantee is_explicit_XA() == true. --- .../main/alter_table_online_debug.result | 110 ++++++++++++++++ mysql-test/main/alter_table_online_debug.test | 119 ++++++++++++++++++ sql/online_alter.cc | 34 ++++- 3 files changed, 257 insertions(+), 6 deletions(-) diff --git a/mysql-test/main/alter_table_online_debug.result b/mysql-test/main/alter_table_online_debug.result index 06f23732365..37b80fe08c4 100644 --- a/mysql-test/main/alter_table_online_debug.result +++ b/mysql-test/main/alter_table_online_debug.result @@ -1675,6 +1675,116 @@ connect con1, localhost, root,,; connection default; drop table t; set debug_sync= reset; +# MDEV-32771 Server crash upon online alter with concurrent XA +create table t (a int primary key); +insert t values(1),(2),(3); +# First, check that nothing from the rollbacked statement commits +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +alter table t add b int default (555), algorithm=copy; +connection con1; +set debug_sync= 'now wait_for downgraded'; +xa start 'xid'; +update t set a = 0; +ERROR 23000: Duplicate entry '0' for key 'PRIMARY' +xa end 'xid'; +xa prepare 'xid'; +xa commit 'xid'; +set debug_sync= 'now signal go'; +connection default; +select * from t; +a b +1 555 +2 555 +3 555 +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +alter table t add c int default(777), algorithm=copy; +connection con1; +set debug_sync= 'now wait_for downgraded'; +xa start 'xid'; +update t set a = 0; +ERROR 23000: Duplicate entry '0' for key 'PRIMARY' +xa end 'xid'; +xa prepare 'xid'; +xa rollback 'xid'; +set debug_sync= 'now signal go'; +connection default; +select * from t; +a b c +1 555 777 +2 555 777 +3 555 777 +# Same, but add one successful statement into transaction +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +alter table t drop b, algorithm=copy; +connection con1; +set debug_sync= 'now wait_for downgraded'; +xa start 'xid'; +update t set a = 10 where a = 1; +update t set a = 0; +ERROR 23000: Duplicate entry '0' for key 'PRIMARY' +xa end 'xid'; +xa prepare 'xid'; +xa rollback 'xid'; +set debug_sync= 'now signal go'; +connection default; +select * from t; +a c +1 777 +2 777 +3 777 +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +alter table t drop primary key, algorithm=copy; +connection con1; +set debug_sync= 'now wait_for downgraded'; +xa start 'xid'; +# This statement will take effect. +update t set a = 10 where a = 1; +update t set a = 0; +ERROR 23000: Duplicate entry '0' for key 'PRIMARY' +xa end 'xid'; +xa prepare 'xid'; +xa commit 'xid'; +set debug_sync= 'now signal go'; +connection default; +select * from t; +a c +10 777 +2 777 +3 777 +# The only statement succeeds (test both commit and rollback) +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +alter table t add d text default ('qwe'), algorithm=copy; +connection con1; +set debug_sync= 'now wait_for downgraded'; +xa start 'xid'; +update t set a = 0; +xa end 'xid'; +xa prepare 'xid'; +xa rollback 'xid'; +set debug_sync= 'now signal go'; +connection default; +select * from t; +a c d +10 777 qwe +2 777 qwe +3 777 qwe +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +alter table t drop c, algorithm=copy; +connection con1; +set debug_sync= 'now wait_for downgraded'; +xa start 'xid'; +update t set a = 0; +xa end 'xid'; +xa prepare 'xid'; +xa commit 'xid'; +set debug_sync= 'now signal go'; +connection default; +select * from t; +a d +0 qwe +0 qwe +0 qwe +drop table t; set global default_storage_engine= MyISAM; disconnect con1; disconnect con2; diff --git a/mysql-test/main/alter_table_online_debug.test b/mysql-test/main/alter_table_online_debug.test index c8386c6d8ab..26b33af24ce 100644 --- a/mysql-test/main/alter_table_online_debug.test +++ b/mysql-test/main/alter_table_online_debug.test @@ -1922,6 +1922,125 @@ select * from t; --connection default drop table t; set debug_sync= reset; + +--echo # MDEV-32771 Server crash upon online alter with concurrent XA + +create table t (a int primary key); +insert t values(1),(2),(3); + +--echo # First, check that nothing from the rollbacked statement commits + +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +send alter table t add b int default (555), algorithm=copy; + +--connection con1 +set debug_sync= 'now wait_for downgraded'; +xa start 'xid'; +--error ER_DUP_ENTRY +update t set a = 0; +xa end 'xid'; +xa prepare 'xid'; +xa commit 'xid'; +set debug_sync= 'now signal go'; + +--connection default +--reap +select * from t; + +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +send alter table t add c int default(777), algorithm=copy; + +--connection con1 +set debug_sync= 'now wait_for downgraded'; +xa start 'xid'; +--error ER_DUP_ENTRY +update t set a = 0; +xa end 'xid'; +xa prepare 'xid'; +xa rollback 'xid'; +set debug_sync= 'now signal go'; + +--connection default +--reap +select * from t; + +--echo # Same, but add one successful statement into transaction + +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +send alter table t drop b, algorithm=copy; + +--connection con1 +set debug_sync= 'now wait_for downgraded'; +xa start 'xid'; +update t set a = 10 where a = 1; +--error ER_DUP_ENTRY +update t set a = 0; +xa end 'xid'; +xa prepare 'xid'; +xa rollback 'xid'; +set debug_sync= 'now signal go'; + +--connection default +--reap +select * from t; + +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +send alter table t drop primary key, algorithm=copy; + +--connection con1 +set debug_sync= 'now wait_for downgraded'; +xa start 'xid'; +--echo # This statement will take effect. +update t set a = 10 where a = 1; +--error ER_DUP_ENTRY +update t set a = 0; +xa end 'xid'; +xa prepare 'xid'; +xa commit 'xid'; +set debug_sync= 'now signal go'; + +--connection default +--reap +select * from t; + + +--echo # The only statement succeeds (test both commit and rollback) + +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +send alter table t add d text default ('qwe'), algorithm=copy; + +--connection con1 +set debug_sync= 'now wait_for downgraded'; +xa start 'xid'; +update t set a = 0; +xa end 'xid'; +xa prepare 'xid'; +xa rollback 'xid'; +set debug_sync= 'now signal go'; + +--connection default +--reap +select * from t; + +set debug_sync= 'alter_table_online_downgraded signal downgraded wait_for go'; +send alter table t drop c, algorithm=copy; + +--connection con1 +set debug_sync= 'now wait_for downgraded'; +xa start 'xid'; +update t set a = 0; +xa end 'xid'; +xa prepare 'xid'; +xa commit 'xid'; +set debug_sync= 'now signal go'; + +--connection default +--reap +select * from t; + +drop table t; + + eval set global default_storage_engine= $default_storage_engine; --disconnect con1 diff --git a/sql/online_alter.cc b/sql/online_alter.cc index bdf813f62dd..e0afe602ca8 100644 --- a/sql/online_alter.cc +++ b/sql/online_alter.cc @@ -315,17 +315,39 @@ int online_alter_savepoint_rollback(handlerton *hton, THD *thd, sv_id_t sv_id) static int online_alter_commit(handlerton *hton, THD *thd, bool all) { - int res= online_alter_end_trans(get_cache_list(hton, thd), thd, - ending_trans(thd, all), true); - cleanup_tables(thd); + int res; + bool is_ending_transaction= ending_trans(thd, all); + if (is_ending_transaction + && thd->transaction->xid_state.get_state_code() == XA_PREPARED) + { + res= hton->commit_by_xid(hton, thd->transaction->xid_state.get_xid()); + // cleanup was already done by prepare() + } + else + { + res= online_alter_end_trans(get_cache_list(hton, thd), thd, + is_ending_transaction, true); + cleanup_tables(thd); + } return res; }; static int online_alter_rollback(handlerton *hton, THD *thd, bool all) { - int res= online_alter_end_trans(get_cache_list(hton, thd), thd, - ending_trans(thd, all), false); - cleanup_tables(thd); + int res; + bool is_ending_transaction= ending_trans(thd, all); + if (is_ending_transaction + && thd->transaction->xid_state.get_state_code() == XA_PREPARED) + { + res= hton->rollback_by_xid(hton, thd->transaction->xid_state.get_xid()); + // cleanup was already done by prepare() + } + else + { + res= online_alter_end_trans(get_cache_list(hton, thd), thd, + is_ending_transaction, false); + cleanup_tables(thd); + } return res; }; From e6acddf121ab4312a8da73b2d47fecb497b6ae33 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Tue, 14 Nov 2023 11:20:49 +0100 Subject: [PATCH 248/477] main.alter_table_online_debug: fix race in XA tests --- .../main/alter_table_online_debug.result | 20 +++++++++---------- mysql-test/main/alter_table_online_debug.test | 20 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/mysql-test/main/alter_table_online_debug.result b/mysql-test/main/alter_table_online_debug.result index 37b80fe08c4..1d20d40e7e4 100644 --- a/mysql-test/main/alter_table_online_debug.result +++ b/mysql-test/main/alter_table_online_debug.result @@ -1577,10 +1577,10 @@ xa begin 'x1'; update t set a = 2 where a = 1; xa end 'x1'; xa prepare 'x1'; -set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +set debug_sync= 'thread_end signal xa_detach wait_for close'; disconnect con1; connection con2; -set debug_sync= 'now wait_for xa_detach'; +set debug_sync= 'now signal close wait_for xa_detach'; xa commit 'x1'; set debug_sync= 'now signal go'; connection default; @@ -1596,10 +1596,10 @@ xa begin 'x2'; insert into t values (53); xa end 'x2'; xa prepare 'x2'; -set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +set debug_sync= 'thread_end signal xa_detach wait_for close'; disconnect con1; connection con2; -set debug_sync= 'now wait_for xa_detach'; +set debug_sync= 'now signal close wait_for xa_detach'; xa rollback 'x2'; set debug_sync= 'now signal go'; connection default; @@ -1618,11 +1618,11 @@ insert into t values (3); xa end 'xuncommitted'; xa prepare 'xuncommitted'; set debug_sync= 'now signal go'; -set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +set debug_sync= 'thread_end signal xa_detach wait_for close'; disconnect con1; connection default; ERROR HY000: Lock wait timeout exceeded; try restarting transaction -set debug_sync= 'now wait_for xa_detach'; +set debug_sync= 'now signal close wait_for xa_detach'; xa rollback 'xuncommitted'; select * from t; a @@ -1638,11 +1638,11 @@ insert into t values (3); xa end 'committed_later'; xa prepare 'committed_later'; set debug_sync= 'now signal go'; -set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +set debug_sync= 'thread_end signal xa_detach wait_for close'; disconnect con1; connection default; ERROR HY000: Lock wait timeout exceeded; try restarting transaction -set debug_sync= 'now wait_for xa_detach'; +set debug_sync= 'now signal close wait_for xa_detach'; xa commit 'committed_later'; select * from t; a @@ -1659,10 +1659,10 @@ ERROR 23000: Duplicate entry '3' for key 'PRIMARY' insert into t values (5); xa end 'x1'; xa prepare 'x1'; -set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +set debug_sync= 'thread_end signal xa_detach wait_for close'; disconnect con1; connection con2; -set debug_sync= 'now wait_for xa_detach'; +set debug_sync= 'now signal close wait_for xa_detach'; xa commit 'x1'; set debug_sync= 'now signal go'; connection default; diff --git a/mysql-test/main/alter_table_online_debug.test b/mysql-test/main/alter_table_online_debug.test index 26b33af24ce..cf0062da269 100644 --- a/mysql-test/main/alter_table_online_debug.test +++ b/mysql-test/main/alter_table_online_debug.test @@ -1810,11 +1810,11 @@ xa begin 'x1'; update t set a = 2 where a = 1; xa end 'x1'; xa prepare 'x1'; -set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +set debug_sync= 'thread_end signal xa_detach wait_for close'; --disconnect con1 --connection con2 -set debug_sync= 'now wait_for xa_detach'; +set debug_sync= 'now signal close wait_for xa_detach'; xa commit 'x1'; set debug_sync= 'now signal go'; --connection default @@ -1832,11 +1832,11 @@ xa begin 'x2'; insert into t values (53); xa end 'x2'; xa prepare 'x2'; -set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +set debug_sync= 'thread_end signal xa_detach wait_for close'; --disconnect con1 --connection con2 -set debug_sync= 'now wait_for xa_detach'; +set debug_sync= 'now signal close wait_for xa_detach'; xa rollback 'x2'; set debug_sync= 'now signal go'; --connection default @@ -1858,13 +1858,13 @@ insert into t values (3); xa end 'xuncommitted'; xa prepare 'xuncommitted'; set debug_sync= 'now signal go'; -set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +set debug_sync= 'thread_end signal xa_detach wait_for close'; --disconnect con1 --connection default --error ER_LOCK_WAIT_TIMEOUT --reap # alter table -set debug_sync= 'now wait_for xa_detach'; +set debug_sync= 'now signal close wait_for xa_detach'; xa rollback 'xuncommitted'; select * from t; @@ -1882,13 +1882,13 @@ insert into t values (3); xa end 'committed_later'; xa prepare 'committed_later'; set debug_sync= 'now signal go'; -set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +set debug_sync= 'thread_end signal xa_detach wait_for close'; --disconnect con1 --connection default --error ER_LOCK_WAIT_TIMEOUT --reap # alter table -set debug_sync= 'now wait_for xa_detach'; +set debug_sync= 'now signal close wait_for xa_detach'; xa commit 'committed_later'; @@ -1906,11 +1906,11 @@ insert into t values (4), (3); insert into t values (5); xa end 'x1'; xa prepare 'x1'; -set debug_sync= 'THD_cleanup_after_trans_cleanup signal xa_detach'; +set debug_sync= 'thread_end signal xa_detach wait_for close'; --disconnect con1 --connection con2 -set debug_sync= 'now wait_for xa_detach'; +set debug_sync= 'now signal close wait_for xa_detach'; xa commit 'x1'; set debug_sync= 'now signal go'; --connection default From 73a38b68dc2a117642e3bddff086d075326cace6 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Tue, 14 Nov 2023 15:36:42 +0100 Subject: [PATCH 249/477] MDEV-11018: rpl.rpl_mariadb_slave_capability fails sporadically in buildbot The test was missing a wait_for_binlog_checkpoint.inc, making it non-deterministic Signed-off-by: Kristian Nielsen --- mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test index 046a65f77db..a3dfab61f9a 100644 --- a/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test +++ b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test @@ -20,6 +20,7 @@ SET @@global.debug_dbug='+d,simulate_slave_capability_none'; connection master; FLUSH LOGS; +--source include/wait_for_binlog_checkpoint.inc CREATE TABLE t1 (a INT PRIMARY KEY); INSERT INTO t1 VALUES (0); sync_slave_with_master; From 15bb8acf8f84c10a8c977d70a412ed1e756dd54a Mon Sep 17 00:00:00 2001 From: Tuukka Pasanen Date: Wed, 15 Nov 2023 10:49:39 +0200 Subject: [PATCH 250/477] MDEV-32689: Remove Ubuntu Bionic from 10.5 Commit Removed Ubuntu Bionic from debian/autobake-debs.sh as it's not used anymore to build official MariaDB images REMINDER TO MERGER: This commit should not be merged up to 10.6 or forward --- debian/autobake-deb.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/debian/autobake-deb.sh b/debian/autobake-deb.sh index aa5a6651cea..994167a826b 100755 --- a/debian/autobake-deb.sh +++ b/debian/autobake-deb.sh @@ -76,9 +76,6 @@ case "${LSBNAME}" in # need to match here to avoid the default Error however ;; # UBUNTU - bionic) - remove_rocksdb_tools - ;& focal) ;& impish|jammy|kinetic) From a0f02f743848fb6ef6d2a51960f77e1e38da1682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 15 Nov 2023 12:23:35 +0200 Subject: [PATCH 251/477] MDEV-32757 innodb_undo_log_truncate=ON is not crash safe trx_purge_truncate_history(): Do not prematurely mark dirty pages as clean. This will be done in mtr_t::commit_shrink() as part of Shrink::operator()(mtr_memo_slot_t*). Also, register each dirty page only once in the mini-transaction. fsp_page_create(): Adjust and simplify the page creation during undo tablespace truncation. We can directly reuse pages that are already in buf_pool.page_hash. This fixes a regression that was caused by commit f5794e1dc6e3d27405daeae850b8e69fd631b62d (MDEV-26445). Tested by: Matthias Leich Reviewed by: Thirunarayanan Balathandayuthapani --- storage/innobase/fsp/fsp0fsp.cc | 50 ++++++++++++++++++++++--------- storage/innobase/trx/trx0purge.cc | 15 ++++------ 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 134c0bbb8db..c5d04a19662 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -1054,7 +1054,7 @@ static buf_block_t* fsp_page_create(fil_space_t *space, page_no_t offset, mtr_t *mtr) { - buf_block_t *block, *free_block; + buf_block_t *block; if (UNIV_UNLIKELY(space->is_being_truncated)) { @@ -1063,26 +1063,48 @@ fsp_page_create(fil_space_t *space, page_no_t offset, mtr_t *mtr) mysql_mutex_lock(&buf_pool.mutex); block= reinterpret_cast (buf_pool.page_hash_get_low(page_id, fold)); - if (block && block->page.oldest_modification() <= 1) - block= nullptr; + if (!block) + { + mysql_mutex_unlock(&buf_pool.mutex); + goto create; + } + + buf_block_buf_fix_inc(block, __FILE__, __LINE__); mysql_mutex_unlock(&buf_pool.mutex); - if (block) + ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE); + ut_ad(!block->page.ibuf_exist); +#ifdef BTR_CUR_HASH_ADAPT + ut_ad(!block->index); +#endif + + if (mtr->have_x_latch(*block)) { + buf_block_buf_fix_dec(block); ut_ad(block->page.buf_fix_count() >= 1); ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1); - ut_ad(mtr->have_x_latch(*block)); - free_block= block; - goto got_free_block; + } + else + { + rw_lock_x_lock(&block->lock); + if (UNIV_UNLIKELY(block->page.id() != page_id)) + { + buf_block_buf_fix_dec(block); + rw_lock_x_unlock(&block->lock); + goto create; + } + mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX); } } - - free_block= buf_LRU_get_free_block(false); -got_free_block: - block= buf_page_create(space, static_cast(offset), - space->zip_size(), mtr, free_block); - if (UNIV_UNLIKELY(block != free_block)) - buf_pool.free_block(free_block); + else + { + create: + buf_block_t *free_block= buf_LRU_get_free_block(false); + block= buf_page_create(space, static_cast(offset), + space->zip_size(), mtr, free_block); + if (UNIV_UNLIKELY(block != free_block)) + buf_pool.free_block(free_block); + } fsp_init_file_page(space, block, mtr); return block; diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index a297ca4921e..4a98dee573e 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -659,13 +659,12 @@ void trx_purge_truncate_history() buf_page_t *prev= UT_LIST_GET_PREV(list, bpage); - if (bpage->id().space() == space.id && - bpage->oldest_modification() != 1) + if (bpage->oldest_modification() > 2 && + bpage->id().space() == space.id) { ut_ad(bpage->state() == BUF_BLOCK_FILE_PAGE); auto block= reinterpret_cast(bpage); - block->fix(); - ut_ad(rw_lock_s_lock_nowait(block->debug_latch, __FILE__, __LINE__)); + buf_block_buf_fix_inc(block, __FILE__, __LINE__); buf_pool.flush_hp.set(prev); mysql_mutex_unlock(&buf_pool.flush_list_mutex); @@ -676,15 +675,13 @@ void trx_purge_truncate_history() mysql_mutex_lock(&buf_pool.flush_list_mutex); ut_ad(bpage->io_fix() == BUF_IO_NONE); - if (bpage->oldest_modification() > 1) - { - bpage->clear_oldest_modification(false); + if (bpage->oldest_modification() > 2 && + !mtr.have_x_latch(*reinterpret_cast(bpage))) mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX); - } else { + buf_block_buf_fix_dec(block); rw_lock_x_unlock(&block->lock); - block->unfix(); } if (prev != buf_pool.flush_hp.get()) From 64a743fc8173415f7948452ff7ddd98499686c9b Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Wed, 15 Nov 2023 11:40:05 +0100 Subject: [PATCH 252/477] MDEV-16951: binlog_encryption.rpl_checksum failed in buildbot with wrong result Wait for the binlog checkpoint event to fix non-determinism in the testcase. Signed-off-by: Kristian Nielsen --- mysql-test/suite/rpl/t/rpl_checksum.test | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql-test/suite/rpl/t/rpl_checksum.test b/mysql-test/suite/rpl/t/rpl_checksum.test index 17a986dc308..36cd382eaad 100644 --- a/mysql-test/suite/rpl/t/rpl_checksum.test +++ b/mysql-test/suite/rpl/t/rpl_checksum.test @@ -89,6 +89,9 @@ flush logs; flush logs; -- source include/wait_for_binlog_checkpoint.inc flush logs; +# The binlog position here is output in the error message from +# wait_for_slave_io_error below, so make sure it's deterministic. +-- source include/wait_for_binlog_checkpoint.inc sync_slave_with_master; #connection slave; From de0324c1462493401133c18699a7792b1428ad1a Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Wed, 15 Nov 2023 13:09:03 +0100 Subject: [PATCH 253/477] MDEV-29402: Test sequence binlog.binlog_mdev717 binlog.binlog_mysqlbinlog_raw_flush fails Reset the GTID sequence at the start of test so earlier run tests does not influence the expected GTID sequence. Signed-off-by: Kristian Nielsen --- mysql-test/suite/binlog/r/binlog_mysqlbinlog_raw_flush.result | 1 + mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test | 2 ++ 2 files changed, 3 insertions(+) diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_raw_flush.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_raw_flush.result index 294e96e5997..d697788047f 100644 --- a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_raw_flush.result +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_raw_flush.result @@ -1,3 +1,4 @@ +RESET MASTER; # # MDEV-30698 Cover missing test cases for mariadb-binlog options # --raw [and] --flashback diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test index 252a8577b6c..677395005ab 100644 --- a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test @@ -20,6 +20,8 @@ --source include/linux.inc --source include/have_log_bin.inc +# Test needs to reset the binlog as it is checking specific GTID. +RESET MASTER; --echo # --echo # MDEV-30698 Cover missing test cases for mariadb-binlog options From ea6ca0139745068d2c6fe06ecc8d71cc0d371d47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 15 Nov 2023 14:11:38 +0200 Subject: [PATCH 254/477] MDEV-32757: rollback crash on corruption trx_undo_free_page(): Detect a case of corrupted TRX_UNDO_PAGE_LIST. trx_undo_truncate_end(): Stop attempts to truncate a corrupted log. trx_t::commit_empty(): Add an error message of a corrupted log. Reviewed by: Thirunarayanan Balathandayuthapani --- storage/innobase/trx/trx0trx.cc | 8 +++++++- storage/innobase/trx/trx0undo.cc | 14 +++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 1ffc8c76189..1bd24870a0c 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -976,7 +976,13 @@ void trx_t::commit_empty(mtr_t *mtr) trx_undo_t *&undo= rsegs.m_redo.undo; ut_ad(undo->state == TRX_UNDO_ACTIVE || undo->state == TRX_UNDO_PREPARED); - ut_ad(undo->size == 1); + + if (UNIV_UNLIKELY(undo->size != 1)) + { + sql_print_error("InnoDB: Undo log for transaction " TRX_ID_FMT + " is corrupted (" UINT32PF "!=1)", id, undo->size); + ut_ad("corrupted undo log" == 0); + } if (buf_block_t *u= buf_page_get(page_id_t(rseg->space->id, undo->hdr_page_no), 0, diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index 203edd9f537..63da2982fec 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -740,6 +740,14 @@ trx_undo_free_page( return FIL_NULL; } + const fil_addr_t last_addr = flst_get_last( + TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + + header_block->page.frame); + if (UNIV_UNLIKELY(last_addr.page == page_no)) { + *err = DB_CORRUPTION; + return FIL_NULL; + } + *err = fseg_free_page(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + header_block->page.frame, rseg->space, page_no, mtr); @@ -748,9 +756,6 @@ trx_undo_free_page( } buf_page_free(rseg->space, page_no, mtr); - const fil_addr_t last_addr = flst_get_last( - TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST - + header_block->page.frame); rseg->curr_size--; if (!in_history) { @@ -794,6 +799,9 @@ static dberr_t trx_undo_truncate_end(trx_undo_t &undo, undo_no_t limit, { ut_ad(is_temp == !undo.rseg->is_persistent()); + if (UNIV_UNLIKELY(undo.last_page_no == FIL_NULL)) + return DB_CORRUPTION; + for (mtr_t mtr;;) { mtr.start(); From 6960dc74cd23c8188a747559e959ecbc677fee3f Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Wed, 15 Nov 2023 16:13:46 +0100 Subject: [PATCH 255/477] MDEV-30064: binlog.binlog_mysqlbinlog_raw_flush sometimes fails with Errcode: 2 "No such file or directory" Increase a 1-second timeout, which is a bit too small for slow buildbot builders. Signed-off-by: Kristian Nielsen --- mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test index 677395005ab..539a8fe5e28 100644 --- a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test @@ -37,7 +37,7 @@ FLUSH LOGS; INSERT INTO t1 VALUES (1); # Read binlog data from master to intermediary result file ---let TIMEOUT=1 +--let TIMEOUT=5 --echo # timeout TIMEOUT MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=MASTER_MYPORT --stop-never --result-file=MYSQLTEST_VARDIR/tmp/ master-bin.000001 --error 124 # Error 124 means timeout was reached --exec timeout $TIMEOUT $MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --stop-never --result-file=$MYSQLTEST_VARDIR/tmp/ master-bin.000001 From 8b509a5d64106dcd737a71921b8fc74ae3dd4130 Mon Sep 17 00:00:00 2001 From: Rex Date: Mon, 25 Sep 2023 12:56:30 +1100 Subject: [PATCH 256/477] Merge 10.4 into 10.5 --- mysql-test/main/cte_nonrecursive.result | 260 ++++++++++++++++++++++++ mysql-test/main/cte_nonrecursive.test | 158 ++++++++++++++ sql/sql_cte.cc | 2 +- sql/sql_derived.cc | 7 + sql/sql_lex.cc | 67 ++++++ sql/sql_lex.h | 8 + sql/sql_select.cc | 20 ++ 7 files changed, 521 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result index f7871d4f929..e05120fa60d 100644 --- a/mysql-test/main/cte_nonrecursive.result +++ b/mysql-test/main/cte_nonrecursive.result @@ -2339,4 +2339,264 @@ set sql_mode="oracle"; with data as (select 1 as id) select id into @myid from data; set sql_mode= @save_sql_mode; +# +# MDEV-31995 Bogus error executing PS for query using CTE with renaming of columns +# +create table t1 (a int, b int); +insert into t1 values (1,1),(1,2),(1,3),(2,1),(2,2); +create table t2 (a int, b int); +insert into t2 values (3,1),(3,2),(3,3),(4,1),(4,2); +with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 group by col1) +select * from cte; +c1 c2 +1 6 +2 3 +prepare st from "with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 group by col1) +select * from cte"; +execute st; +c1 c2 +1 6 +2 3 +execute st; +c1 c2 +1 6 +2 3 +drop prepare st; +create procedure sp() with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 group by col1) +select * from cte; +call sp(); +c1 c2 +1 6 +2 3 +call sp(); +c1 c2 +1 6 +2 3 +drop procedure sp; +with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 order by col1) +select * from cte; +c1 c2 +1 9 +prepare st from "with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 order by col1) +select * from cte"; +execute st; +c1 c2 +1 9 +execute st; +c1 c2 +1 9 +drop prepare st; +create procedure sp() with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 order by col1) +select * from cte; +call sp(); +c1 c2 +1 9 +call sp(); +c1 c2 +1 9 +drop procedure sp; +with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 where a > 1 group by col1 +union select a as col3, sum(b) as col4 from t2 where b > 2 group by col3), +cte2 (c3, c4) as +(select a as col5, sum(b) as col6 from t1 where a <= 1 group by col5 +union select a as col7, sum(b) as col8 from t2 where b <= 2 group by col7) +select * from cte where c1=1 union select * from cte2 where c3=3; +c1 c2 +3 3 +prepare st from "with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 where a > 1 group by col1 +union select a as col3, sum(b) as col4 from t2 where b > 2 group by col3), +cte2 (c3, c4) as +(select a as col5, sum(b) as col6 from t1 where a <= 1 group by col5 +union select a as col7, sum(b) as col8 from t2 where b <= 2 group by col7) +select * from cte where c1=1 union select * from cte2 where c3=3"; +execute st; +c1 c2 +3 3 +execute st; +c1 c2 +3 3 +drop prepare st; +create procedure sp() with cte (c1,c2) as +(select a as col1, sum(b) as col2 from t1 where a > 1 group by col1 +union select a as col3, sum(b) as col4 from t2 where b > 2 group by col3), +cte2 (c3, c4) as +(select a as col5, sum(b) as col6 from t1 where a <= 1 group by col5 +union select a as col7, sum(b) as col8 from t2 where b <= 2 group by col7) +select * from cte where c1=1 union select * from cte2 where c3=3; +call sp(); +c1 c2 +3 3 +call sp(); +c1 c2 +3 3 +drop procedure sp; +with cte (c1,c2) as (select * from t1) +select cte.c1+1 as col1 , cte.c2 as col2 from cte where cte.c1 > 1 +union +select cte.c1 as col3, cte.c2+1 as col4 from cte where cte.c1 < 0; +col1 col2 +3 1 +3 2 +prepare st from "with cte (c1,c2) as (select * from t1) +select cte.c1+1 as col1 , cte.c2 as col2 from cte where cte.c1 > 1 +union +select cte.c1 as col3, cte.c2+1 as col4 from cte where cte.c1 < 0"; +execute st; +col1 col2 +3 1 +3 2 +execute st; +col1 col2 +3 1 +3 2 +save this to the end to test errors >drop prepare st; +create procedure sp() with cte (c1,c2) as (select * from t1) +select cte.c1+1 as col1 , cte.c2 as col2 from cte where cte.c1 > 1 +union +select cte.c1 as col3, cte.c2+1 as col4 from cte where cte.c1 < 0; +call sp(); +col1 col2 +3 1 +3 2 +call sp(); +col1 col2 +3 1 +3 2 +drop procedure sp; +insert into t1 select * from t2; +with cte (c1, c2) +as (select a, sum(b) from t1 where b > 1 group by a having sum(b) < 5) +select * from cte where c1 < 4 and c2 > 1; +c1 c2 +2 2 +# Check pushdown conditions in JSON output +explain format=json with cte (c1, c2) +as (select a, sum(b) from t1 where b > 1 group by a having sum(b) < 5) +select * from cte where c1 < 4 and c2 > 1; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 10, + "filtered": 100, + "attached_condition": "cte.c1 < 4 and cte.c2 > 1", + "materialized": { + "query_block": { + "select_id": 2, + "having_condition": "sum(t1.b) < 5 and c2 > 1", + "filesort": { + "sort_key": "t1.a", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 10, + "filtered": 100, + "attached_condition": "t1.b > 1 and t1.a < 4" + } + } + } + } + } + } + } +} +alter table t1 add column c int; +execute st; +ERROR HY000: WITH column list and SELECT field list have different column counts +drop prepare st; +drop table t1,t2; +Test out recursive CTEs +create table distances (src char(1), dest char(1), distance int); +create table city_population (city char(1), population int); +INSERT INTO `distances` VALUES ('A','A',0),('B','A',593),('C','A',800), +('D','A',221),('E','A',707),('F','A',869),('G','A',225),('H','A',519), +('A','B',919),('B','B',0),('C','B',440),('D','B',79),('E','B',79), +('F','B',154),('G','B',537),('H','B',220),('A','C',491),('B','C',794), +('C','C',0),('D','C',100),('E','C',350),('F','C',748),('G','C',712), +('H','C',315),('A','D',440),('B','D',256),('C','D',958),('D','D',0), +('E','D',255),('F','D',161),('G','D',63),('H','D',831),('A','E',968), +('B','E',345),('C','E',823),('D','E',81),('E','E',0),('F','E',436), +('G','E',373),('H','E',558),('A','F',670),('B','F',677),('C','F',375), +('D','F',843),('E','F',90),('F','F',0),('G','F',328),('H','F',881), +('A','G',422),('B','G',467),('C','G',67),('D','G',936),('E','G',480), +('F','G',592),('G','G',0),('H','G',819),('A','H',537),('B','H',229), +('C','H',534),('D','H',984),('E','H',319),('F','H',643),('G','H',257), +('H','H',0); +insert into city_population values ('A', 5000), ('B', 6000), ('C', 100000), +('D', 80000), ('E', 7000), ('F', 1000), ('G', 100), ('H', -80000); +#find the biggest city within 300 kellikams of 'E' +with recursive travel (src, path, dest, distance, population) as ( +select city, cast('' as varchar(10)), city, +0, population +from city_population where city='E' + union all +select src.src, concat(src.path, dst.dest), dst.dest, +src.distance + dst.distance, dstc.population +from travel src +join distances dst on src.dest != dst.dest +join city_population dstc on dst.dest = dstc.city +where dst.src = src.dest and src.distance + dst.distance < 300 +and length(path) < 10 +) +select * from travel where dest != 'E' order by population desc, distance +limit 1; +src path dest distance population +E FD D 251 80000 +prepare st from "with recursive travel (src, path, dest, distance, population) as ( +select city, cast('' as varchar(10)), city, +0, population +from city_population where city='E' + union all +select src.src, concat(src.path, dst.dest), dst.dest, +src.distance + dst.distance, dstc.population +from travel src +join distances dst on src.dest != dst.dest +join city_population dstc on dst.dest = dstc.city +where dst.src = src.dest and src.distance + dst.distance < 300 +and length(path) < 10 +) +select * from travel where dest != 'E' order by population desc, distance +limit 1"; +execute st; +src path dest distance population +E FD D 251 80000 +execute st; +src path dest distance population +E FD D 251 80000 +drop prepare st; +create procedure sp() with recursive travel (src, path, dest, distance, population) as ( +select city, cast('' as varchar(10)), city, +0, population +from city_population where city='E' + union all +select src.src, concat(src.path, dst.dest), dst.dest, +src.distance + dst.distance, dstc.population +from travel src +join distances dst on src.dest != dst.dest +join city_population dstc on dst.dest = dstc.city +where dst.src = src.dest and src.distance + dst.distance < 300 +and length(path) < 10 +) +select * from travel where dest != 'E' order by population desc, distance +limit 1; +call sp(); +src path dest distance population +E FD D 251 80000 +call sp(); +src path dest distance population +E FD D 251 80000 +drop procedure sp; +drop table distances, city_population; # End of 10.4 tests diff --git a/mysql-test/main/cte_nonrecursive.test b/mysql-test/main/cte_nonrecursive.test index c420a5e0483..1d29f3d4caa 100644 --- a/mysql-test/main/cte_nonrecursive.test +++ b/mysql-test/main/cte_nonrecursive.test @@ -1796,4 +1796,162 @@ with data as (select 1 as id) select id into @myid from data; set sql_mode= @save_sql_mode; + + +--echo # +--echo # MDEV-31995 Bogus error executing PS for query using CTE with renaming of columns +--echo # + +create table t1 (a int, b int); +insert into t1 values (1,1),(1,2),(1,3),(2,1),(2,2); +create table t2 (a int, b int); +insert into t2 values (3,1),(3,2),(3,3),(4,1),(4,2); + +let $q= +with cte (c1,c2) as + (select a as col1, sum(b) as col2 from t1 group by col1) +select * from cte; + +eval $q; + +eval prepare st from "$q"; +execute st; +execute st; +drop prepare st; + +eval create procedure sp() $q; +call sp(); +call sp(); +drop procedure sp; + +let $q= +with cte (c1,c2) as + (select a as col1, sum(b) as col2 from t1 order by col1) +select * from cte; + +eval $q; + +eval prepare st from "$q"; +execute st; +execute st; +drop prepare st; + +eval create procedure sp() $q; +call sp(); +call sp(); +drop procedure sp; + +let $q= +with cte (c1,c2) as + (select a as col1, sum(b) as col2 from t1 where a > 1 group by col1 + union select a as col3, sum(b) as col4 from t2 where b > 2 group by col3), +cte2 (c3, c4) as + (select a as col5, sum(b) as col6 from t1 where a <= 1 group by col5 + union select a as col7, sum(b) as col8 from t2 where b <= 2 group by col7) +select * from cte where c1=1 union select * from cte2 where c3=3; + +eval $q; + +eval prepare st from "$q"; +execute st; +execute st; +drop prepare st; + +eval create procedure sp() $q; +call sp(); +call sp(); +drop procedure sp; + +let $q= +with cte (c1,c2) as (select * from t1) +select cte.c1+1 as col1 , cte.c2 as col2 from cte where cte.c1 > 1 +union +select cte.c1 as col3, cte.c2+1 as col4 from cte where cte.c1 < 0; + +eval $q; + +eval prepare st from "$q"; +execute st; +execute st; +--echo save this to the end to test errors >drop prepare st; + +eval create procedure sp() $q; +call sp(); +call sp(); +drop procedure sp; + +insert into t1 select * from t2; + +let $q= +with cte (c1, c2) + as (select a, sum(b) from t1 where b > 1 group by a having sum(b) < 5) +select * from cte where c1 < 4 and c2 > 1; + +eval $q; + +--echo # Check pushdown conditions in JSON output +--source include/analyze-format.inc +eval explain format=json $q; + +alter table t1 add column c int; + +--error ER_WITH_COL_WRONG_LIST +execute st; + +drop prepare st; +drop table t1,t2; + +--echo Test out recursive CTEs + +create table distances (src char(1), dest char(1), distance int); +create table city_population (city char(1), population int); +INSERT INTO `distances` VALUES ('A','A',0),('B','A',593),('C','A',800), +('D','A',221),('E','A',707),('F','A',869),('G','A',225),('H','A',519), +('A','B',919),('B','B',0),('C','B',440),('D','B',79),('E','B',79), +('F','B',154),('G','B',537),('H','B',220),('A','C',491),('B','C',794), +('C','C',0),('D','C',100),('E','C',350),('F','C',748),('G','C',712), +('H','C',315),('A','D',440),('B','D',256),('C','D',958),('D','D',0), +('E','D',255),('F','D',161),('G','D',63),('H','D',831),('A','E',968), +('B','E',345),('C','E',823),('D','E',81),('E','E',0),('F','E',436), +('G','E',373),('H','E',558),('A','F',670),('B','F',677),('C','F',375), +('D','F',843),('E','F',90),('F','F',0),('G','F',328),('H','F',881), +('A','G',422),('B','G',467),('C','G',67),('D','G',936),('E','G',480), +('F','G',592),('G','G',0),('H','G',819),('A','H',537),('B','H',229), +('C','H',534),('D','H',984),('E','H',319),('F','H',643),('G','H',257), +('H','H',0); +insert into city_population values ('A', 5000), ('B', 6000), ('C', 100000), +('D', 80000), ('E', 7000), ('F', 1000), ('G', 100), ('H', -80000); + +--echo #find the biggest city within 300 kellikams of 'E' +let $q= +with recursive travel (src, path, dest, distance, population) as ( + select city, cast('' as varchar(10)), city, + 0, population + from city_population where city='E' + union all + select src.src, concat(src.path, dst.dest), dst.dest, + src.distance + dst.distance, dstc.population + from travel src + join distances dst on src.dest != dst.dest + join city_population dstc on dst.dest = dstc.city + where dst.src = src.dest and src.distance + dst.distance < 300 + and length(path) < 10 + ) +select * from travel where dest != 'E' order by population desc, distance +limit 1; + +eval $q; + +eval prepare st from "$q"; +execute st; +execute st; +drop prepare st; + +eval create procedure sp() $q; +call sp(); +call sp(); +drop procedure sp; + +drop table distances, city_population; + --echo # End of 10.4 tests diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index e22aa1ebd6f..ab9a3db5099 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -1199,7 +1199,7 @@ With_element::process_columns_of_derived_unit(THD *thd, /* Rename the columns of the first select in the unit */ while ((item= it++, name= nm++)) { - item->set_name(thd, *name); + lex_string_set(&item->name, name->str); item->common_flags&= ~IS_AUTO_GENERATED_NAME; } diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index e5a5b27840b..a5c1590ecfb 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1334,6 +1334,13 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) (derived->alias.str ? derived->alias.str : ""), derived->get_unit())); st_select_lex_unit *unit= derived->get_unit(); + st_select_lex *sl= unit->first_select(); + + // reset item names to that saved after wildcard expansion in JOIN::prepare + do + { + sl->restore_item_list_names(); + } while ((sl= sl->next_select())); derived->merged_for_insert= FALSE; unit->unclean(); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 246076d0b4a..739811af9c5 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2958,6 +2958,7 @@ void st_select_lex::init_query() in_tvc= false; versioned_tables= 0; pushdown_select= 0; + orig_names_of_item_list_elems= 0; } void st_select_lex::init_select() @@ -3005,6 +3006,7 @@ void st_select_lex::init_select() versioned_tables= 0; is_tvc_wrapper= false; nest_flags= 0; + orig_names_of_item_list_elems= 0; } /* @@ -11080,6 +11082,71 @@ exit: } +/** + @brief + Save the original names of items from the item list. + + @retval + true - if an error occurs + false - otherwise +*/ + +bool st_select_lex::save_item_list_names(THD *thd) +{ + if (orig_names_of_item_list_elems) + return false; + + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); + + if (unlikely(!(orig_names_of_item_list_elems= new(thd->mem_root) + List))) + return true; + + List_iterator_fast li(item_list); + Item *item; + + while ((item= li++)) + { + if (unlikely(orig_names_of_item_list_elems->push_back( + new Lex_ident_sys(item->name.str, item->name.length)))) + { + if (arena) + thd->restore_active_arena(arena, &backup); + orig_names_of_item_list_elems= 0; + return true; + } + } + + if (arena) + thd->restore_active_arena(arena, &backup); + + return false; +} + + +/** + @brief + Restore the name of each item in the item_list of this st_select_lex + from orig_names_of_item_list_elems. +*/ + +void st_select_lex::restore_item_list_names() +{ + if (!orig_names_of_item_list_elems) + return; + + DBUG_ASSERT(item_list.elements == orig_names_of_item_list_elems->elements); + + List_iterator_fast it(*orig_names_of_item_list_elems); + Lex_ident_sys *new_name; + List_iterator_fast li(item_list); + Item *item; + + while ((item= li++) && (new_name= it++)) + lex_string_set( &item->name, new_name->str); +} + bool LEX::stmt_install_plugin(const DDL_options_st &opt, const Lex_ident_sys_st &name, const LEX_CSTRING &soname) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index abe5e34ca17..6c7ce6e98da 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1410,6 +1410,9 @@ public: bool straight_fl); TABLE_LIST *convert_right_join(); List* get_item_list(); + bool save_item_list_names(THD *thd); + void restore_item_list_names(); + ulong get_table_join_options(); void set_lock_for_tables(thr_lock_type lock_type, bool for_update); /* @@ -1604,6 +1607,11 @@ private: index_clause_map current_index_hint_clause; /* a list of USE/FORCE/IGNORE INDEX */ List *index_hints; + /* + This list is used to restore the names of items + from item_list after each execution of the statement. + */ + List *orig_names_of_item_list_elems; public: inline void add_where_field(st_select_lex *sel) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 016aef4e483..62766cdb9cf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1317,6 +1317,26 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num, if (setup_wild(thd, tables_list, fields_list, &all_fields, select_lex, false)) DBUG_RETURN(-1); + /* + If the select_lex is immediately contained within a derived table + AND this derived table is a CTE + WITH supplied column names + AND we have the correct number of elements in both lists + (mismatches found in mysql_derived_prepare/rename_columns_of_derived_unit) + THEN NOW is the time to take a copy of these item_names for + later restoration if required. + */ + TABLE_LIST *derived= select_lex->master_unit()->derived; + + if (derived && + derived->with && + derived->with->column_list.elements && + (derived->with->column_list.elements == select_lex->item_list.elements)) + { + if (select_lex->save_item_list_names(thd)) + DBUG_RETURN(-1); + } + if (thd->lex->current_select->first_cond_optimization) { if ( conds && ! thd->lex->current_select->merged_into) From d4be70afb4eaffbd1c2dd3326e19752770b08bc6 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sat, 21 Oct 2023 16:51:15 +1100 Subject: [PATCH 257/477] MDEV-30236 set TaskMax=99% in the MariaDB systemd unit Originally requested to be infinity, but rolled back to 99% to allow for a remote ssh connection or the odd needed system job. This is up from 15% which is the effective default of DefaultTasksMax. Thanks Rick Pizzi for the bug report. --- support-files/mariadb.service.in | 6 ++++++ support-files/mariadb@.service.in | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/support-files/mariadb.service.in b/support-files/mariadb.service.in index b7a55596029..533737090ce 100644 --- a/support-files/mariadb.service.in +++ b/support-files/mariadb.service.in @@ -140,6 +140,12 @@ PrivateTmp=false TimeoutStartSec=900 TimeoutStopSec=900 +# Set the maximium number of tasks (threads) to 99% of what the system can +# handle as set by the kernel, reserve the 1% for a remote ssh connection, +# some monitoring, or that backup cron job. Without the directive this would +# be 15% (see DefaultTasksMax in systemd man pages). +TasksMax=99% + ## ## Options previously available to be set via [mysqld_safe] ## that now needs to be set by systemd config files as mysqld_safe diff --git a/support-files/mariadb@.service.in b/support-files/mariadb@.service.in index 8878ff27703..c36fc5aabd6 100644 --- a/support-files/mariadb@.service.in +++ b/support-files/mariadb@.service.in @@ -252,6 +252,12 @@ PrivateTmp=false TimeoutStartSec=900 TimeoutStopSec=900 +# Set the maximium number of tasks (threads) to 99% of what the system can +# handle as set by the kernel, reserve the 1% for a remote ssh connection, +# some monitoring, or that backup cron job. Without the directive this would +# be 15% (see DefaultTasksMax in systemd man pages). +TasksMax=99% + # Controlling how multiple instances are separated. See top of this file. # Note: This service isn't User=mysql by default so we need to be explicit. # It is as an option here as a user may want to use the MYSQLD_MULTI_INSTANCE From 6c34245963db18d46260e72cd14dd13b24a522ae Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Thu, 16 Nov 2023 14:41:25 +0530 Subject: [PATCH 258/477] MDEV-32811 Potentially broken crash recovery if a mini-transaction frees a page, not modifying previously clean pages - The 11.2 test innodb.sys_truncate_debug fails while executing insert statement. Reason for the failure is that same mini-transaction does freeing, allocating and freeing the same page. Page initialization clears the FIL_PAGE_LSN on the page, fails to set the FIL_PAGE_LSN after freeing the same page. This issue is caused by commit f46efb4476d4cb7401ea73e4c452d9460bdd0f33 mtr_t::commit(): Should set the FIL_PAGE_LSN even though page is freed --- storage/innobase/mtr/mtr0mtr.cc | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 1834a164d23..df7c5fb000e 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -420,13 +420,10 @@ void mtr_t::commit() ut_ad(s < buf_page_t::READ_FIX); ut_ad(mach_read_from_8(bpage->frame + FIL_PAGE_LSN) <= m_commit_lsn); - if (s >= buf_page_t::UNFIXED) - { - mach_write_to_8(bpage->frame + FIL_PAGE_LSN, m_commit_lsn); - if (UNIV_LIKELY_NULL(bpage->zip.data)) - memcpy_aligned<8>(FIL_PAGE_LSN + bpage->zip.data, - FIL_PAGE_LSN + bpage->frame, 8); - } + mach_write_to_8(bpage->frame + FIL_PAGE_LSN, m_commit_lsn); + if (UNIV_LIKELY_NULL(bpage->zip.data)) + memcpy_aligned<8>(FIL_PAGE_LSN + bpage->zip.data, + FIL_PAGE_LSN + bpage->frame, 8); modified++; } switch (auto latch= slot.type & ~MTR_MEMO_MODIFY) { From a7d186a17d35b2651f3ebee8aa3e49b68ded4d64 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Mon, 18 Sep 2023 17:18:01 +0200 Subject: [PATCH 259/477] MDEV-32168: slave_error_param condition is never checked from the wait_for_slave_param.inc - Reviewer: --- .../include/wait_for_slave_io_error.inc | 2 +- mysql-test/include/wait_for_slave_param.inc | 7 +---- ...d_master_switch_to_unencrypted_coords.test | 2 ++ ...ted_master_switch_to_unencrypted_gtid.test | 2 ++ .../binlog_encryption/rpl_parallel.result | 1 - .../rpl_parallel_ignored_errors.result | 1 + .../suite/multi_source/gtid_slave_pos.result | 3 +- .../suite/multi_source/gtid_slave_pos.test | 5 ++- .../rpl/include/mdev-31448_conservative.inc | 4 +-- .../rpl/include/mdev-31448_optimistic.inc | 4 +-- .../include/rpl_binlog_max_cache_size.test | 4 +++ .../rpl/include/rpl_shutdown_wait_slaves.inc | 9 ++++++ .../rpl/include/rpl_start_stop_slave.test | 1 + .../rpl/include/rpl_stop_middle_group.test | 7 +++-- .../rpl_domain_id_filter_master_crash.result | 4 +-- .../suite/rpl/r/rpl_fail_register.result | 5 +-- .../suite/rpl/r/rpl_gtid_delete_domain.result | 2 +- mysql-test/suite/rpl/r/rpl_mdev_17614.result | 4 +-- mysql-test/suite/rpl/r/rpl_parallel.result | 1 - .../rpl/r/rpl_parallel_ignored_errors.result | 1 + .../suite/rpl/r/rpl_parallel_kill.result | 6 ++-- .../suite/rpl/r/rpl_row_idempotency.result | 16 +++++----- .../r/rpl_semi_sync_master_shutdown.result | 8 ++--- .../rpl_shutdown_wait_semisync_slaves.result | 3 ++ .../rpl/r/rpl_shutdown_wait_slaves.result | 3 ++ .../suite/rpl/r/rpl_slave_status.result | 1 - mysql-test/suite/rpl/r/rpl_ssl1.result | 2 +- .../rpl/r/rpl_stm_stop_middle_group.result | 4 +-- ...mdev-31448_kill_ooo_finish_optimistic.test | 1 + mysql-test/suite/rpl/t/rpl_connection.test | 1 + .../rpl/t/rpl_domain_id_filter_io_crash.test | 2 +- .../t/rpl_domain_id_filter_master_crash.test | 6 ++-- mysql-test/suite/rpl/t/rpl_fail_register.test | 9 ++++-- .../suite/rpl/t/rpl_gtid_errorhandling.test | 2 +- mysql-test/suite/rpl/t/rpl_gtid_errorlog.test | 2 +- mysql-test/suite/rpl/t/rpl_gtid_startpos.test | 1 + .../suite/rpl/t/rpl_gtid_stop_start.test | 2 +- .../suite/rpl/t/rpl_heartbeat_basic.test | 1 + mysql-test/suite/rpl/t/rpl_mdev_17614.test | 6 ++-- mysql-test/suite/rpl/t/rpl_parallel.test | 2 +- .../rpl/t/rpl_parallel_ignored_errors.test | 3 ++ .../suite/rpl/t/rpl_parallel_retry.test | 1 + .../suite/rpl/t/rpl_row_corruption.test | 1 + .../suite/rpl/t/rpl_row_idempotency.test | 31 ++++++++++++++----- .../rpl/t/rpl_semi_sync_master_shutdown.test | 12 +++++-- .../t/rpl_semi_sync_shutdown_await_ack.inc | 2 ++ mysql-test/suite/rpl/t/rpl_slave_status.test | 3 +- mysql-test/suite/rpl/t/rpl_ssl1.test | 4 ++- .../suite/rpl/t/semisync_future-7591.test | 1 + sql/slave.cc | 8 ++++- 50 files changed, 142 insertions(+), 71 deletions(-) diff --git a/mysql-test/include/wait_for_slave_io_error.inc b/mysql-test/include/wait_for_slave_io_error.inc index 96844106fa9..158594304ea 100644 --- a/mysql-test/include/wait_for_slave_io_error.inc +++ b/mysql-test/include/wait_for_slave_io_error.inc @@ -59,7 +59,7 @@ let $_wfsie_errno= query_get_value(SHOW SLAVE STATUS, Last_IO_Errno, 1); if ($slave_io_errno == '') { --echo !!!ERROR IN TEST: you must set \$slave_io_errno before you source - --echo !!!wait_for_slave_sql_error.inc. The error we got this time was '$_wfsie_errno', + --echo !!!wait_for_slave_io_error.inc. The error we got this time was '$_wfsie_errno', --echo !!!so you probably want to add the following line to your test case: --echo !!! --let \$slave_io_errno= $_wfsie_errno --die !!!ERROR IN TEST: you must set \$slave_io_errno before sourcing wait_for_slave_io_error.inc diff --git a/mysql-test/include/wait_for_slave_param.inc b/mysql-test/include/wait_for_slave_param.inc index b06dee3c640..8b21bf4d019 100644 --- a/mysql-test/include/wait_for_slave_param.inc +++ b/mysql-test/include/wait_for_slave_param.inc @@ -56,11 +56,6 @@ if (!$_slave_timeout) } } -if ($slave_error_param == '') -{ - --let $slave_error_param= 1 -} - let $_slave_param_comparison= $slave_param_comparison; if (!$_slave_param_comparison) { @@ -90,7 +85,7 @@ while ($_slave_continue) --let $_show_slave_status_value= query_get_value("SHOW SLAVE STATUS", $slave_param, 1) # Check if an error condition is reached. - if (!$slave_error_param) + if ($slave_error_param) { --let $_show_slave_status_error_value= query_get_value("SHOW SLAVE STATUS", $slave_error_param, 1) if ($_show_slave_status_error_value) diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test index a34c9715239..c9dbc5c0e96 100644 --- a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test @@ -136,6 +136,8 @@ start slave; SHOW TABLES; --disable_connect_log +# IO thread is stopped, stop SQL thread only +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc --enable_connect_log reset slave; diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.test b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.test index f882e8f3440..b96d11c998a 100644 --- a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.test +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.test @@ -132,6 +132,8 @@ if (`SELECT strcmp("$gsp","")`) SHOW TABLES; --disable_connect_log +# IO thread is stopped, wait for SQL thread to be stopped +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc --enable_connect_log reset slave; diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel.result b/mysql-test/suite/binlog_encryption/rpl_parallel.result index b24ff7ba53d..56bbe37ade9 100644 --- a/mysql-test/suite/binlog_encryption/rpl_parallel.result +++ b/mysql-test/suite/binlog_encryption/rpl_parallel.result @@ -897,7 +897,6 @@ connection con2; SET debug_sync='RESET'; connection server_2; include/wait_for_slave_sql_error.inc [errno=1062] -include/wait_for_slave_sql_to_stop.inc SELECT * FROM t3 WHERE a >= 110 ORDER BY a; a b 110 1 diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.result b/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.result index 3dd5a3ea83c..f1e8c78d1d1 100644 --- a/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.result +++ b/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.result @@ -35,6 +35,7 @@ connection server_2; connection con_temp2; COMMIT; connection server_2; +include/wait_for_slave_sql_error.inc [errno=1062] include/stop_slave.inc include/assert.inc [table t1 should have zero rows where a>32] SELECT * FROM t1 WHERE a>32; diff --git a/mysql-test/suite/multi_source/gtid_slave_pos.result b/mysql-test/suite/multi_source/gtid_slave_pos.result index d57cfc17959..6daed494c55 100644 --- a/mysql-test/suite/multi_source/gtid_slave_pos.result +++ b/mysql-test/suite/multi_source/gtid_slave_pos.result @@ -97,8 +97,9 @@ set default_master_connection = 'slave1'; STOP SLAVE; include/wait_for_slave_to_stop.inc set default_master_connection = 'slave2'; +include/wait_for_slave_sql_error.inc [errno=1942] STOP SLAVE; -include/wait_for_slave_to_stop.inc +include/stop_slave.inc set default_master_connection = 'slave1'; START SLAVE; include/wait_for_slave_to_start.inc diff --git a/mysql-test/suite/multi_source/gtid_slave_pos.test b/mysql-test/suite/multi_source/gtid_slave_pos.test index c01130f8cd5..8c8decc476e 100644 --- a/mysql-test/suite/multi_source/gtid_slave_pos.test +++ b/mysql-test/suite/multi_source/gtid_slave_pos.test @@ -118,8 +118,11 @@ set default_master_connection = 'slave1'; STOP SLAVE; --source include/wait_for_slave_to_stop.inc set default_master_connection = 'slave2'; +--let $slave_sql_errno= 1942 +--source include/wait_for_slave_sql_error.inc STOP SLAVE; ---source include/wait_for_slave_to_stop.inc +--let $rpl_only_running_threads= 1 +--source include/stop_slave.inc set default_master_connection = 'slave1'; START SLAVE; --source include/wait_for_slave_to_start.inc diff --git a/mysql-test/suite/rpl/include/mdev-31448_conservative.inc b/mysql-test/suite/rpl/include/mdev-31448_conservative.inc index 9a2884439f6..53c0444886e 100644 --- a/mysql-test/suite/rpl/include/mdev-31448_conservative.inc +++ b/mysql-test/suite/rpl/include/mdev-31448_conservative.inc @@ -50,8 +50,8 @@ insert into t1 values (3); commit; --connection slave ---let $slave_timeout=1032 ---source include/wait_for_slave_sql_to_stop.inc +--let $slave_sql_errno=1032 +--source include/wait_for_slave_sql_error.inc update t1 set a=1 where a=2; set @@global.slave_parallel_threads = @save.slave_parallel_threads; diff --git a/mysql-test/suite/rpl/include/mdev-31448_optimistic.inc b/mysql-test/suite/rpl/include/mdev-31448_optimistic.inc index 9b72181d249..23ddcbd5e6f 100644 --- a/mysql-test/suite/rpl/include/mdev-31448_optimistic.inc +++ b/mysql-test/suite/rpl/include/mdev-31448_optimistic.inc @@ -75,8 +75,8 @@ drop table t2; commit; --connection slave ---let $slave_timeout=1032 ---source include/wait_for_slave_sql_to_stop.inc +--let $slave_sql_errno=1032 +--source include/wait_for_slave_sql_error.inc update t1 set a=1 where a=2; set @@global.slave_parallel_threads = @save.slave_parallel_threads; diff --git a/mysql-test/suite/rpl/include/rpl_binlog_max_cache_size.test b/mysql-test/suite/rpl/include/rpl_binlog_max_cache_size.test index d750554b4ec..9d0a5685926 100644 --- a/mysql-test/suite/rpl/include/rpl_binlog_max_cache_size.test +++ b/mysql-test/suite/rpl/include/rpl_binlog_max_cache_size.test @@ -411,6 +411,8 @@ while ($n) COMMIT; --connection slave +# Multi-statement transaction raised ER_TRANS_CACHE_FULL (4096=128x32) +# that will stop SQL slave thread --let $slave_sql_errno= 1197 if (`SELECT @@binlog_format = 'ROW'`) { @@ -430,6 +432,8 @@ source include/show_binlog_events.inc; --replace_result $old_binlog_stmt_cache_size ORIGINAL_VALUE --eval SET GLOBAL binlog_stmt_cache_size= $old_binlog_stmt_cache_size +# SQL slave is stopped, stop only IO thread +--let $rpl_only_running_threads= 1 source include/stop_slave.inc; source include/start_slave.inc; diff --git a/mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc b/mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc index 4726bbe1889..964eb3e0262 100644 --- a/mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc +++ b/mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc @@ -75,17 +75,26 @@ EOF --connection server_1 DROP TABLE t1; +# Slaves IO thread will receive the disconnect error when master was shutdown +# so we are allowing error on start. --connection server_2 --disable_warnings +--let rpl_allow_error=1 +--source include/wait_for_slave_io_to_start.inc + --source include/start_slave.inc --enable_warnings --connection server_3 --disable_warnings +--let rpl_allow_error=1 +--source include/wait_for_slave_io_to_start.inc --source include/start_slave.inc --enable_warnings --connection server_4 --disable_warnings +--let rpl_allow_error=1 +--source include/wait_for_slave_io_to_start.inc --source include/start_slave.inc --enable_warnings diff --git a/mysql-test/suite/rpl/include/rpl_start_stop_slave.test b/mysql-test/suite/rpl/include/rpl_start_stop_slave.test index 32f33b2a31d..793ec159082 100644 --- a/mysql-test/suite/rpl/include/rpl_start_stop_slave.test +++ b/mysql-test/suite/rpl/include/rpl_start_stop_slave.test @@ -207,6 +207,7 @@ START SLAVE; --let $status_items= Last_IO_Errno, Last_IO_Error --source include/show_slave_status.inc +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc RESET SLAVE; diff --git a/mysql-test/suite/rpl/include/rpl_stop_middle_group.test b/mysql-test/suite/rpl/include/rpl_stop_middle_group.test index ac01fb04d16..6bc872cabe5 100644 --- a/mysql-test/suite/rpl/include/rpl_stop_middle_group.test +++ b/mysql-test/suite/rpl/include/rpl_stop_middle_group.test @@ -82,7 +82,9 @@ connection slave; # slave will catch the killed status, won't shut down immediately # but does it eventually having the whole group unfinished (not committed) -source include/wait_for_slave_sql_to_stop.inc; +# ER_SLAVE_FATAL_ERROR +--let slave_sql_errno= 1593 +source include/wait_for_slave_sql_error.inc; # checking: the error and group unfinished @@ -120,7 +122,8 @@ connection slave; # but does it eventually having the whole group unfinished (not committed) # -source include/wait_for_slave_sql_to_stop.inc; +--let slave_sql_errno= 1593 +source include/wait_for_slave_sql_error.inc; # checking: the error and group unfinished diff --git a/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result b/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result index 0a414cb3b1f..4169a2ddc26 100644 --- a/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result +++ b/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result @@ -38,8 +38,8 @@ connection master; include/rpl_start_server.inc [server_number=1] # Master has restarted successfully connection slave; -include/stop_slave.inc -include/start_slave.inc +include/wait_for_slave_io_to_start.inc +include/wait_for_slave_sql_to_start.inc select * from ti; a 1 diff --git a/mysql-test/suite/rpl/r/rpl_fail_register.result b/mysql-test/suite/rpl/r/rpl_fail_register.result index 2cddc796314..0398220c4d0 100644 --- a/mysql-test/suite/rpl/r/rpl_fail_register.result +++ b/mysql-test/suite/rpl/r/rpl_fail_register.result @@ -1,14 +1,15 @@ include/master-slave.inc [connection master] connection slave; +CALL mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: Debug Induced Error"); set @old_dbug=@@global.debug_dbug; set global debug_dbug='d,fail_com_register_slave'; stop slave; reset slave; include/wait_for_slave_to_stop.inc start slave; -stop slave; -include/wait_for_slave_to_stop.inc +include/wait_for_slave_io_error.inc [errno=1597] +include/stop_slave_sql.inc set global debug_dbug=@old_dbug; connection master; kill DUMP_THREAD; diff --git a/mysql-test/suite/rpl/r/rpl_gtid_delete_domain.result b/mysql-test/suite/rpl/r/rpl_gtid_delete_domain.result index 9c36973427a..9e788e8f965 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_delete_domain.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_delete_domain.result @@ -52,7 +52,7 @@ Waiting until 'Slave_IO_Running' = 'Yes' [$slave_error_param='Last_IO_Errno'] .. con='slave' warn='1' qlog='1' rlog='1' aborterr='1' ...==== BEGIN include/wait_for_slave_param.inc [Slave_SQL_Running] ==== ... con='slave' warn='1' qlog='1' rlog='1' aborterr='1' -Waiting until 'Slave_SQL_Running' = 'Yes' [$slave_error_param='1'] +Waiting until 'Slave_SQL_Running' = 'Yes' [$slave_error_param=''] [connection slave] ...==== END include/wait_for_slave_param.inc [Slave_SQL_Running] ==== ... con='slave' warn='1' qlog='1' rlog='1' aborterr='1' diff --git a/mysql-test/suite/rpl/r/rpl_mdev_17614.result b/mysql-test/suite/rpl/r/rpl_mdev_17614.result index ba077111522..66aec55fe67 100644 --- a/mysql-test/suite/rpl/r/rpl_mdev_17614.result +++ b/mysql-test/suite/rpl/r/rpl_mdev_17614.result @@ -30,7 +30,7 @@ a b c 1 1 1 2 2 3 stop slave; -include/wait_for_slave_to_stop.inc +include/stop_slave.inc reset slave; connection master; reset master; @@ -190,7 +190,7 @@ a b c 1 1 1 2 2 3 stop slave; -include/wait_for_slave_to_stop.inc +include/stop_slave.inc reset slave; connection master; reset master; diff --git a/mysql-test/suite/rpl/r/rpl_parallel.result b/mysql-test/suite/rpl/r/rpl_parallel.result index ef89d954faa..6aa43b4791d 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel.result +++ b/mysql-test/suite/rpl/r/rpl_parallel.result @@ -896,7 +896,6 @@ connection con2; SET debug_sync='RESET'; connection server_2; include/wait_for_slave_sql_error.inc [errno=1062] -include/wait_for_slave_sql_to_stop.inc SELECT * FROM t3 WHERE a >= 110 ORDER BY a; a b 110 1 diff --git a/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.result b/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.result index 3dd5a3ea83c..f1e8c78d1d1 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.result @@ -35,6 +35,7 @@ connection server_2; connection con_temp2; COMMIT; connection server_2; +include/wait_for_slave_sql_error.inc [errno=1062] include/stop_slave.inc include/assert.inc [table t1 should have zero rows where a>32] SELECT * FROM t1 WHERE a>32; diff --git a/mysql-test/suite/rpl/r/rpl_parallel_kill.result b/mysql-test/suite/rpl/r/rpl_parallel_kill.result index 7e6b065725b..8772ac9955d 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_kill.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_kill.result @@ -30,7 +30,7 @@ kill $t3_tid; connection slave1; commit; connection slave; -include/wait_for_slave_sql_to_stop.inc +include/wait_for_slave_sql_error.inc [errno=1032] update t1 set a=1 where a=2; set @@global.slave_parallel_threads = @save.slave_parallel_threads; set @@global.slave_parallel_mode = @save.slave_parallel_mode; @@ -78,7 +78,7 @@ include/wait_for_slave_param.inc [Last_Errno] connection slave1; commit; connection slave; -include/wait_for_slave_sql_to_stop.inc +include/wait_for_slave_sql_error.inc [errno=1032] update t1 set a=1 where a=2; set @@global.slave_parallel_threads = @save.slave_parallel_threads; set @@global.slave_parallel_mode = @save.slave_parallel_mode; @@ -127,7 +127,7 @@ include/wait_for_slave_param.inc [Last_Errno] connection slave1; commit; connection slave; -include/wait_for_slave_sql_to_stop.inc +include/wait_for_slave_sql_error.inc [errno=1032] update t1 set a=1 where a=2; set @@global.slave_parallel_threads = @save.slave_parallel_threads; set @@global.slave_parallel_mode = @save.slave_parallel_mode; diff --git a/mysql-test/suite/rpl/r/rpl_row_idempotency.result b/mysql-test/suite/rpl/r/rpl_row_idempotency.result index c655ae67185..061cc8363bf 100644 --- a/mysql-test/suite/rpl/r/rpl_row_idempotency.result +++ b/mysql-test/suite/rpl/r/rpl_row_idempotency.result @@ -89,7 +89,7 @@ b 3 *** slave must stop (Trying to delete a referenced foreing key) connection slave; -include/wait_for_slave_sql_to_stop.inc +include/wait_for_slave_sql_error.inc [errno=1451] Last_SQL_Error 1451 select * from ti1 order by b /* must be (1),(2),(3) - not deleted */; @@ -114,7 +114,7 @@ connection master; insert into ti2 set a=3, b=3 /* offending write event */; *** slave must stop (Trying to insert an invalid foreign key) connection slave; -include/wait_for_slave_sql_to_stop.inc +include/wait_for_slave_sql_error.inc [errno=1452] Last_SQL_Error 1452 select * from ti2 order by b /* must be (2,2) */; @@ -139,9 +139,9 @@ a b insert into ti1 set b=1; connection master; insert into ti1 set b=1 /* offending write event */; -*** slave must stop (Trying to insert a dupliacte key) +*** slave must stop (Trying to insert a duplicate key) connection slave; -include/wait_for_slave_sql_to_stop.inc +include/wait_for_slave_sql_error.inc [errno=1062] Last_SQL_Error 1062 set foreign_key_checks= 0; @@ -164,7 +164,7 @@ connection master; DELETE FROM t1 WHERE a = -2; *** slave must stop (Key was not found) connection slave; -include/wait_for_slave_sql_to_stop.inc +include/wait_for_slave_sql_error.inc [errno=1032] Last_SQL_Error 1032 set global slave_exec_mode='IDEMPOTENT'; @@ -176,7 +176,7 @@ connection master; DELETE FROM t2 WHERE a = -2; *** slave must stop (Key was not found) connection slave; -include/wait_for_slave_sql_to_stop.inc +include/wait_for_slave_sql_error.inc [errno=1032] Last_SQL_Error 1032 set global slave_exec_mode='IDEMPOTENT'; @@ -190,7 +190,7 @@ connection master; UPDATE t1 SET a = 1 WHERE a = -1; *** slave must stop (Key was not found) connection slave; -include/wait_for_slave_sql_to_stop.inc +include/wait_for_slave_sql_error.inc [errno=1032] Last_SQL_Error 1032 set global slave_exec_mode='IDEMPOTENT'; @@ -202,7 +202,7 @@ connection master; UPDATE t2 SET a = 1 WHERE a = -1; *** slave must stop (Key was not found) connection slave; -include/wait_for_slave_sql_to_stop.inc +include/wait_for_slave_sql_error.inc [errno=1032] Last_SQL_Error 1032 set global slave_exec_mode='IDEMPOTENT'; diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result b/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result index 786e1682bb0..6124ba01679 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result @@ -14,14 +14,12 @@ connection master; # Shutdown master include/rpl_stop_server.inc [server_number=1] connection slave; -include/stop_slave.inc +include/wait_for_slave_io_error.inc [errno=2003] # Restart master include/rpl_start_server.inc [server_number=1] connection slave; -include/stop_slave.inc -Warnings: -Note 1255 Slave already has been stopped -include/start_slave.inc +include/wait_for_slave_sql_to_start.inc +include/wait_for_slave_io_to_start.inc connection master; SET @@GLOBAL.debug_dbug=""; SET @@GLOBAL. rpl_semi_sync_master_enabled = 0; diff --git a/mysql-test/suite/rpl/r/rpl_shutdown_wait_semisync_slaves.result b/mysql-test/suite/rpl/r/rpl_shutdown_wait_semisync_slaves.result index cecc3daf340..6837ca60733 100644 --- a/mysql-test/suite/rpl/r/rpl_shutdown_wait_semisync_slaves.result +++ b/mysql-test/suite/rpl/r/rpl_shutdown_wait_semisync_slaves.result @@ -34,10 +34,13 @@ connection server_1; connection server_1; DROP TABLE t1; connection server_2; +include/wait_for_slave_io_to_start.inc include/start_slave.inc connection server_3; +include/wait_for_slave_io_to_start.inc include/start_slave.inc connection server_4; +include/wait_for_slave_io_to_start.inc include/start_slave.inc connection server_2; include/stop_slave.inc diff --git a/mysql-test/suite/rpl/r/rpl_shutdown_wait_slaves.result b/mysql-test/suite/rpl/r/rpl_shutdown_wait_slaves.result index 3b238332462..f4084bb3ecf 100644 --- a/mysql-test/suite/rpl/r/rpl_shutdown_wait_slaves.result +++ b/mysql-test/suite/rpl/r/rpl_shutdown_wait_slaves.result @@ -21,9 +21,12 @@ connection server_1; connection server_1; DROP TABLE t1; connection server_2; +include/wait_for_slave_io_to_start.inc include/start_slave.inc connection server_3; +include/wait_for_slave_io_to_start.inc include/start_slave.inc connection server_4; +include/wait_for_slave_io_to_start.inc include/start_slave.inc include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_slave_status.result b/mysql-test/suite/rpl/r/rpl_slave_status.result index 1c81cec2577..ef122b9ca92 100644 --- a/mysql-test/suite/rpl/r/rpl_slave_status.result +++ b/mysql-test/suite/rpl/r/rpl_slave_status.result @@ -36,7 +36,6 @@ connection slave; include/stop_slave.inc START SLAVE; include/wait_for_slave_sql_to_start.inc -include/wait_for_slave_io_to_stop.inc ==== Verify that Slave IO thread stopped with error ==== include/wait_for_slave_io_error.inc [errno=1045] ==== Cleanup (Note that slave IO thread is not running) ==== diff --git a/mysql-test/suite/rpl/r/rpl_ssl1.result b/mysql-test/suite/rpl/r/rpl_ssl1.result index 1d55fe1259e..7cecabc6aac 100644 --- a/mysql-test/suite/rpl/r/rpl_ssl1.result +++ b/mysql-test/suite/rpl/r/rpl_ssl1.result @@ -15,7 +15,7 @@ connection slave; select * from t1; t stop slave; -include/wait_for_slave_to_stop.inc +include/wait_for_slave_io_error.inc [errno=1045] change master to master_ssl=1 , master_ssl_ca ='MYSQL_TEST_DIR/std_data/cacert.pem', master_ssl_cert='MYSQL_TEST_DIR/std_data/client-cert.pem', master_ssl_key='MYSQL_TEST_DIR/std_data/client-key.pem'; start slave; include/wait_for_slave_to_start.inc diff --git a/mysql-test/suite/rpl/r/rpl_stm_stop_middle_group.result b/mysql-test/suite/rpl/r/rpl_stm_stop_middle_group.result index 0afe1992fb9..86c90ff33dd 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_stop_middle_group.result +++ b/mysql-test/suite/rpl/r/rpl_stm_stop_middle_group.result @@ -43,7 +43,7 @@ Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction commit; connection slave; -include/wait_for_slave_sql_to_stop.inc +include/wait_for_slave_sql_error.inc [errno=1593] SELECT "Fatal error: ... Slave SQL Thread stopped with incomplete event group having non-transactional changes. If the group consists solely of row-based events, you can try to restart the slave with --slave-exec-mode=IDEMPOTENT, which ignores duplicate key, key not found, and similar errors (see documentation for details)." AS Last_SQL_Error, @check as `true`; Last_SQL_Error true Fatal error: ... Slave SQL Thread stopped with incomplete event group having non-transactional changes. If the group consists solely of row-based events, you can try to restart the slave with --slave-exec-mode=IDEMPOTENT, which ignores duplicate key, key not found, and similar errors (see documentation for details). 1 @@ -63,7 +63,7 @@ set @@global.debug_dbug="d,stop_slave_middle_group,incomplete_group_in_relay_log connection master; update tm as t1, ti as t2 set t1.a=t1.a * 2, t2.a=t2.a * 2; connection slave; -include/wait_for_slave_sql_to_stop.inc +include/wait_for_slave_sql_error.inc [errno=1593] SELECT "Fatal error: ... Slave SQL Thread stopped with incomplete event group having non-transactional changes. If the group consists solely of row-based events, you can try to restart the slave with --slave-exec-mode=IDEMPOTENT, which ignores duplicate key, key not found, and similar errors (see documentation for details)." AS Last_SQL_Error, @check as `true`; Last_SQL_Error true Fatal error: ... Slave SQL Thread stopped with incomplete event group having non-transactional changes. If the group consists solely of row-based events, you can try to restart the slave with --slave-exec-mode=IDEMPOTENT, which ignores duplicate key, key not found, and similar errors (see documentation for details). 1 diff --git a/mysql-test/suite/rpl/t/mdev-31448_kill_ooo_finish_optimistic.test b/mysql-test/suite/rpl/t/mdev-31448_kill_ooo_finish_optimistic.test index ae15ed64a65..ab2f846f33c 100644 --- a/mysql-test/suite/rpl/t/mdev-31448_kill_ooo_finish_optimistic.test +++ b/mysql-test/suite/rpl/t/mdev-31448_kill_ooo_finish_optimistic.test @@ -81,6 +81,7 @@ DROP TABLE t1; --connection slave --echo # --echo # Cleanup +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc eval set @@global.slave_parallel_threads= $save_slave_parallel_threads; eval set @@global.slave_parallel_mode= $save_slave_parallel_mode; diff --git a/mysql-test/suite/rpl/t/rpl_connection.test b/mysql-test/suite/rpl/t/rpl_connection.test index 310240061d1..8eee639cd34 100644 --- a/mysql-test/suite/rpl/t/rpl_connection.test +++ b/mysql-test/suite/rpl/t/rpl_connection.test @@ -16,6 +16,7 @@ CHANGE MASTER TO MASTER_USER= '', MASTER_PASSWORD= ''; START SLAVE; --let $slave_io_errno= 1045, 1593 --source include/wait_for_slave_io_error.inc +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc CHANGE MASTER TO MASTER_USER= 'root', MASTER_PASSWORD= ''; diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test index a949da0cc25..22331c39f1d 100644 --- a/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test @@ -149,7 +149,7 @@ connection slave; SELECT * FROM t1; SET @@global.debug_dbug=@saved_dbug; - +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test index 6dafab192a0..b1fa9af33a4 100644 --- a/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test @@ -67,8 +67,10 @@ connection master; save_master_pos; --connection slave ---source include/stop_slave.inc ---source include/start_slave.inc +--let rpl_allow_error=1 +--source include/wait_for_slave_io_to_start.inc +--let rpl_allow_error= +--source include/wait_for_slave_sql_to_start.inc sync_with_master; select * from ti; select * from tm; diff --git a/mysql-test/suite/rpl/t/rpl_fail_register.test b/mysql-test/suite/rpl/t/rpl_fail_register.test index d95a5c5f1c3..5f86a33c9aa 100644 --- a/mysql-test/suite/rpl/t/rpl_fail_register.test +++ b/mysql-test/suite/rpl/t/rpl_fail_register.test @@ -3,7 +3,7 @@ source include/have_binlog_format_mixed.inc; source include/master-slave.inc; connection slave; - +CALL mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: Debug Induced Error"); set @old_dbug=@@global.debug_dbug; set global debug_dbug='d,fail_com_register_slave'; @@ -11,8 +11,11 @@ stop slave; reset slave; source include/wait_for_slave_to_stop.inc; start slave; -stop slave; -source include/wait_for_slave_to_stop.inc; +# Debug point will raise IO thread error ER_SLAVE_MASTER_COM_FAILURE +# so we will wait for that and manually stop the SQL thread +--let $slave_io_errno= 1597 +--source include/wait_for_slave_io_error.inc +--source include/stop_slave_sql.inc set global debug_dbug=@old_dbug; connection master; diff --git a/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test index c02e2670c92..eec7a275e03 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test @@ -19,7 +19,7 @@ INSERT INTO t1 VALUES (1); CALL mtr.add_suppression("Slave: Failed to open mysql.gtid_slave_pos"); --let $slave_sql_errno=1944 --source include/wait_for_slave_sql_error.inc - +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc ALTER TABLE mysql.gtid_slave_pos CHANGE seq_no seq_no BIGINT UNSIGNED NOT NULL; ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY; diff --git a/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test b/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test index ea321062100..c8c63cf5e6e 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test @@ -31,7 +31,7 @@ SET sql_log_bin=1; START SLAVE; --let $slave_sql_errno=1062 --source include/wait_for_slave_sql_error.inc - +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc # Skip the problem event from the master. SET GLOBAL gtid_slave_pos= "0-1-100"; diff --git a/mysql-test/suite/rpl/t/rpl_gtid_startpos.test b/mysql-test/suite/rpl/t/rpl_gtid_startpos.test index 100d75a8cdc..834efdc6a2d 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_startpos.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_startpos.test @@ -50,6 +50,7 @@ eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, START SLAVE; --let $slave_io_errno= 1236 --source include/wait_for_slave_io_error.inc +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc --replace_result $MASTER_MYPORT MASTER_PORT diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test index 25452346523..8e41d6162ea 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test @@ -207,7 +207,7 @@ SET sql_log_bin=0; call mtr.add_suppression("Failed to load slave replication state from table"); call mtr.add_suppression("Unable to load replication GTID slave state"); SET sql_log_bin=1; - +--let rpl_allow_error= 1 --source include/start_slave.inc --connection server_1 INSERT INTO t1 VALUES (9); diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test index 4c8d3a1fedb..cae7a0e59ed 100644 --- a/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test +++ b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test @@ -327,6 +327,7 @@ sleep 4; let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) > 0 AS Result, Result, 1); --echo Heartbeat events are received while sql thread stopped (1 means 'yes'): $result +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc DROP TABLE t1; --echo diff --git a/mysql-test/suite/rpl/t/rpl_mdev_17614.test b/mysql-test/suite/rpl/t/rpl_mdev_17614.test index c11aad3305e..da70d3ef451 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev_17614.test +++ b/mysql-test/suite/rpl/t/rpl_mdev_17614.test @@ -41,7 +41,8 @@ SELECT * FROM t1; # restart replication for the next testcase stop slave; ---source include/wait_for_slave_to_stop.inc +--let $rpl_only_running_threads= 1 +--source include/stop_slave.inc reset slave; connection master; reset master; @@ -160,7 +161,8 @@ SELECT * FROM t1; # restart replication for the next testcase stop slave; ---source include/wait_for_slave_to_stop.inc +--let $rpl_only_running_threads= 1 +--source include/stop_slave.inc reset slave; connection master; reset master; diff --git a/mysql-test/suite/rpl/t/rpl_parallel.test b/mysql-test/suite/rpl/t/rpl_parallel.test index d43cec4df34..925dfe5b335 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel.test +++ b/mysql-test/suite/rpl/t/rpl_parallel.test @@ -1175,9 +1175,9 @@ SET debug_sync='RESET'; --save_master_pos --connection server_2 +# SQL thread stopped --let $slave_sql_errno= 1062 --source include/wait_for_slave_sql_error.inc ---source include/wait_for_slave_sql_to_stop.inc # We should not see the row (112,3) here, it should be rolled back due to # error signal from the prior transaction. SELECT * FROM t3 WHERE a >= 110 ORDER BY a; diff --git a/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test b/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test index 7a6a758a508..6303c5c6ddd 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test @@ -93,6 +93,9 @@ COMMIT; # Clean up. --connection server_2 +--let $slave_sql_errno= 1062 +--source include/wait_for_slave_sql_error.inc +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc --let $assert_cond= COUNT(*) = 0 FROM t1 WHERE a>32 --let $assert_text= table t1 should have zero rows where a>32 diff --git a/mysql-test/suite/rpl/t/rpl_parallel_retry.test b/mysql-test/suite/rpl/t/rpl_parallel_retry.test index 97a3a709eb5..0c42600e14c 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_retry.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_retry.test @@ -469,6 +469,7 @@ if (`SELECT count(*) = 1 FROM t1 WHERE a = 2`) # Clean up # --connection server_2 +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc SET @@GLOBAL.slave_parallel_threads=@old_parallel_threads; SET @@GLOBAL.slave_parallel_mode=@old_parallel_mode; diff --git a/mysql-test/suite/rpl/t/rpl_row_corruption.test b/mysql-test/suite/rpl/t/rpl_row_corruption.test index d78df905ccb..52828a639ed 100644 --- a/mysql-test/suite/rpl/t/rpl_row_corruption.test +++ b/mysql-test/suite/rpl/t/rpl_row_corruption.test @@ -39,6 +39,7 @@ SET @@global.debug_dbug="d,inject_tblmap_same_id_maps_diff_table"; # wait for error 1593 (ER_SLAVE_FATAL_ERROR) --let $slave_sql_errno=1593 --source include/wait_for_slave_sql_error.inc +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc # clean up diff --git a/mysql-test/suite/rpl/t/rpl_row_idempotency.test b/mysql-test/suite/rpl/t/rpl_row_idempotency.test index 85775832b2b..326f94ecbc3 100644 --- a/mysql-test/suite/rpl/t/rpl_row_idempotency.test +++ b/mysql-test/suite/rpl/t/rpl_row_idempotency.test @@ -139,7 +139,9 @@ select * from ti1 order by b /* must be (2),(3) */; --echo *** slave must stop (Trying to delete a referenced foreing key) connection slave; -source include/wait_for_slave_sql_to_stop.inc; +# ER_ROW_IS_REFERENCED_2 # Cannot add or update a child row: a foreign key constraint fails +--let slave_sql_errno= 1451 +source include/wait_for_slave_sql_error.inc; let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); disable_query_log; @@ -173,7 +175,9 @@ insert into ti2 set a=3, b=3 /* offending write event */; --echo *** slave must stop (Trying to insert an invalid foreign key) connection slave; -source include/wait_for_slave_sql_to_stop.inc; +# ER_NO_REFERENCED_ROW_2 # Cannot add or update a parent row: a foreign key constraint fails +--let slave_sql_errno= 1452 +source include/wait_for_slave_sql_error.inc; let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); disable_query_log; @@ -210,9 +214,11 @@ insert into ti1 set b=1; connection master; insert into ti1 set b=1 /* offending write event */; ---echo *** slave must stop (Trying to insert a dupliacte key) +--echo *** slave must stop (Trying to insert a duplicate key) connection slave; -source include/wait_for_slave_sql_to_stop.inc; +# ER_DUP_ENTRY # Duplicate entry for key +--let slave_sql_errno= 1062 +source include/wait_for_slave_sql_error.inc; let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); disable_query_log; @@ -247,7 +253,10 @@ DELETE FROM t1 WHERE a = -2; --echo *** slave must stop (Key was not found) connection slave; -source include/wait_for_slave_sql_to_stop.inc; +# ER_KEY_NOT_FOUND # Can't find record +--let slave_sql_errno= 1032 +source include/wait_for_slave_sql_error.inc; + let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); disable_query_log; @@ -265,7 +274,9 @@ connection master; DELETE FROM t2 WHERE a = -2; --echo *** slave must stop (Key was not found) connection slave; -source include/wait_for_slave_sql_to_stop.inc; +# ER_KEY_NOT_FOUND # Can't find record +--let slave_sql_errno= 1032 +source include/wait_for_slave_sql_error.inc; let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); disable_query_log; @@ -287,7 +298,9 @@ UPDATE t1 SET a = 1 WHERE a = -1; --echo *** slave must stop (Key was not found) connection slave; -source include/wait_for_slave_sql_to_stop.inc; +# ER_KEY_NOT_FOUND # Can't find record +--let slave_sql_errno= 1032 +source include/wait_for_slave_sql_error.inc; let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); disable_query_log; @@ -307,7 +320,9 @@ UPDATE t2 SET a = 1 WHERE a = -1; --echo *** slave must stop (Key was not found) connection slave; -source include/wait_for_slave_sql_to_stop.inc; +# ER_KEY_NOT_FOUND # Can't find record +--let slave_sql_errno= 1032 +source include/wait_for_slave_sql_error.inc; let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); disable_query_log; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test index 2224f78d6d0..05e6fcca143 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test @@ -30,8 +30,12 @@ connection master; --let $rpl_server_number=1 source include/rpl_stop_server.inc; +# After stoping the master, slave receives the disconnect error (2003) --connection slave ---source include/stop_slave.inc +--let $slave_io_errno=2003 +--let $slave_io_error_is_nonfatal=1 +--source include/wait_for_slave_io_error.inc +--let $slave_io_error_is_nonfatal=0 #connection master; --echo # Restart master @@ -42,8 +46,10 @@ source include/rpl_start_server.inc; # Clean up # --connection slave ---source include/stop_slave.inc ---source include/start_slave.inc +--source include/wait_for_slave_sql_to_start.inc +--let rpl_allow_error=1 +--source include/wait_for_slave_io_to_start.inc +#--source include/start_slave.inc --connection master SET @@GLOBAL.debug_dbug=""; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc index a232f68540d..252541ae13b 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc @@ -116,11 +116,13 @@ show status like 'Rpl_semi_sync_master_no_tx'; --connection server_2 --eval SET @@GLOBAL.debug_dbug= "$sav_server_2_dbug" --eval SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0 +--let $rpl_only_running_threads= 1 source include/stop_slave.inc; --connection server_3 --eval SET @@GLOBAL.debug_dbug= "$sav_server_3_dbug" --eval SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0 +--let $rpl_only_running_threads= 1 source include/stop_slave.inc; --echo #-- Bring the master back up diff --git a/mysql-test/suite/rpl/t/rpl_slave_status.test b/mysql-test/suite/rpl/t/rpl_slave_status.test index 63e37216926..fb552d6477d 100644 --- a/mysql-test/suite/rpl/t/rpl_slave_status.test +++ b/mysql-test/suite/rpl/t/rpl_slave_status.test @@ -59,7 +59,6 @@ sync_slave_with_master; source include/stop_slave.inc; START SLAVE; source include/wait_for_slave_sql_to_start.inc; -source include/wait_for_slave_io_to_stop.inc; --echo ==== Verify that Slave IO thread stopped with error ==== # 1045 = ER_ACCESS_DENIED_ERROR @@ -68,7 +67,7 @@ source include/wait_for_slave_io_to_stop.inc; --echo ==== Cleanup (Note that slave IO thread is not running) ==== -# cleanup: slave io thread has is stopped so we reset replication +# cleanup: slave io thread is stopped so we reset replication --source include/stop_slave_sql.inc CHANGE MASTER TO MASTER_USER = 'root', MASTER_PASSWORD = ''; # clear Slave_IO_Errno diff --git a/mysql-test/suite/rpl/t/rpl_ssl1.test b/mysql-test/suite/rpl/t/rpl_ssl1.test index d994dd21c1d..3a4958857e2 100644 --- a/mysql-test/suite/rpl/t/rpl_ssl1.test +++ b/mysql-test/suite/rpl/t/rpl_ssl1.test @@ -30,7 +30,9 @@ select * from t1; #showing that replication could work with ssl params stop slave; ---source include/wait_for_slave_to_stop.inc +--let $slave_io_errno=1045 +--source include/wait_for_slave_io_error.inc + --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR eval change master to master_ssl=1 , master_ssl_ca ='$MYSQL_TEST_DIR/std_data/cacert.pem', master_ssl_cert='$MYSQL_TEST_DIR/std_data/client-cert.pem', master_ssl_key='$MYSQL_TEST_DIR/std_data/client-key.pem'; start slave; diff --git a/mysql-test/suite/rpl/t/semisync_future-7591.test b/mysql-test/suite/rpl/t/semisync_future-7591.test index 866041d2579..dd003486495 100644 --- a/mysql-test/suite/rpl/t/semisync_future-7591.test +++ b/mysql-test/suite/rpl/t/semisync_future-7591.test @@ -19,6 +19,7 @@ insert into t1 values (1); reset master; --connection slave +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc reset slave; --source include/start_slave.inc diff --git a/sql/slave.cc b/sql/slave.cc index 3b9b5d6a83b..0e1cd97414e 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4775,7 +4775,13 @@ connected: goto err; goto connected; } - DBUG_EXECUTE_IF("fail_com_register_slave", goto err;); + DBUG_EXECUTE_IF("fail_com_register_slave", + { + mi->report(ERROR_LEVEL, ER_SLAVE_MASTER_COM_FAILURE, NULL, + ER(ER_SLAVE_MASTER_COM_FAILURE), "COM_REGISTER_SLAVE", + "Debug Induced Error"); + goto err; + }); } DBUG_PRINT("info",("Starting reading binary log from master")); From 55a96c055a1c03595f414f4718ff417ae5c5d718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 16 Nov 2023 16:39:02 +0200 Subject: [PATCH 260/477] MDEV-32050 fixup: innodb.instant_alter_crash This test occasionally fails with a failure to purge history. Let us try to purge everything before starting the interesting part, to make that occasional failure go away. --- mysql-test/suite/innodb/r/instant_alter_crash.result | 1 + mysql-test/suite/innodb/t/instant_alter_crash.test | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/suite/innodb/r/instant_alter_crash.result b/mysql-test/suite/innodb/r/instant_alter_crash.result index c6f7d3898be..b92f8ee8724 100644 --- a/mysql-test/suite/innodb/r/instant_alter_crash.result +++ b/mysql-test/suite/innodb/r/instant_alter_crash.result @@ -27,6 +27,7 @@ SELECT * FROM t2; id c2 c3 2 1 De finibus bonorum 3 4 accusantium doloremque laudantium +InnoDB 0 transactions not purged BEGIN; DELETE FROM t1; ROLLBACK; diff --git a/mysql-test/suite/innodb/t/instant_alter_crash.test b/mysql-test/suite/innodb/t/instant_alter_crash.test index b687664dbcc..8eb03b39a1b 100644 --- a/mysql-test/suite/innodb/t/instant_alter_crash.test +++ b/mysql-test/suite/innodb/t/instant_alter_crash.test @@ -38,6 +38,7 @@ disconnect ddl; SELECT * FROM t1; SELECT * FROM t2; +--source include/wait_all_purged.inc BEGIN; DELETE FROM t1; ROLLBACK; From 5a1f821b939997be02702a695d6830d650629137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 16 Nov 2023 16:57:42 +0200 Subject: [PATCH 261/477] MDEV-31861 Empty INSERT crashes with innodb_force_recovery=6 or innodb_read_only=ON ha_innobase::extra(): Do not invoke log_buffer_flush_to_disk() if high_level_read_only holds. log_buffer_flush_to_disk(): Remove an assertion that duplicates one at the start of log_write_up_to(). --- mysql-test/suite/innodb/r/read_only_recovery.result | 2 ++ mysql-test/suite/innodb/t/read_only_recovery.test | 2 ++ storage/innobase/handler/ha_innodb.cc | 3 ++- storage/innobase/log/log0log.cc | 1 - 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/read_only_recovery.result b/mysql-test/suite/innodb/r/read_only_recovery.result index add0da94cab..2cde58189d5 100644 --- a/mysql-test/suite/innodb/r/read_only_recovery.result +++ b/mysql-test/suite/innodb/r/read_only_recovery.result @@ -37,6 +37,8 @@ SELECT * FROM t; a 3 SET GLOBAL innodb_max_purge_lag_wait=0; +INSERT INTO mysql.innodb_index_stats +SELECT * FROM mysql.innodb_index_stats LIMIT 0; # restart SELECT * FROM t; a diff --git a/mysql-test/suite/innodb/t/read_only_recovery.test b/mysql-test/suite/innodb/t/read_only_recovery.test index 47146213090..d011b3aa5e3 100644 --- a/mysql-test/suite/innodb/t/read_only_recovery.test +++ b/mysql-test/suite/innodb/t/read_only_recovery.test @@ -39,6 +39,8 @@ SELECT * FROM t; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SELECT * FROM t; SET GLOBAL innodb_max_purge_lag_wait=0; +INSERT INTO mysql.innodb_index_stats +SELECT * FROM mysql.innodb_index_stats LIMIT 0; --let $restart_parameters= --source include/restart_mysqld.inc SELECT * FROM t; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 188f703f33c..d5cc2311a2b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -15797,7 +15797,8 @@ ha_innobase::extra( break; case HA_EXTRA_END_ALTER_COPY: m_prebuilt->table->skip_alter_undo = 0; - if (!m_prebuilt->table->is_temporary()) { + if (!m_prebuilt->table->is_temporary() + && !high_level_read_only) { log_buffer_flush_to_disk(); } break; diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index e9ef36b4b84..3f8703beb3e 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -871,7 +871,6 @@ repeat: @param sync whether to wait for a durable write to complete */ void log_buffer_flush_to_disk(bool sync) { - ut_ad(!srv_read_only_mode); log_write_up_to(log_sys.get_lsn(std::memory_order_acquire), sync); } From a3d0d5fc33d3fd248f2d09faedd1ba6daf7a2596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 16 Nov 2023 17:45:18 +0200 Subject: [PATCH 262/477] MDEV-26055: Improve adaptive flushing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a 10.5 backport from 10.6 commit 9593cccf285ee348fc9a2743c1ed7d24c768439b. Adaptive flushing is enabled by setting innodb_max_dirty_pages_pct_lwm>0 (not default) and innodb_adaptive_flushing=ON (default). There is also the parameter innodb_adaptive_flushing_lwm (default: 10 per cent of the log capacity). It should enable some adaptive flushing even when innodb_max_dirty_pages_pct_lwm=0. That is not being changed here. This idea was first presented by Inaam Rana several years ago, and I discussed it with Jean-François Gagné at FOSDEM 2023. buf_flush_page_cleaner(): When we are not near the log capacity limit (neither buf_flush_async_lsn nor buf_flush_sync_lsn are set), also try to move clean blocks from the buf_pool.LRU list to buf_pool.free or initiate writes (but not the eviction) of dirty blocks, until the remaining I/O capacity has been consumed. buf_flush_LRU_list_batch(): Add the parameter bool evict, to specify whether dirty least recently used pages (from buf_pool.LRU) should be evicted immediately after they have been written out. Callers outside buf_flush_page_cleaner() will pass evict=true, to retain the existing behaviour. buf_do_LRU_batch(): Add the parameter bool evict. Return counts of evicted and flushed pages. buf_flush_LRU(): Add the parameter bool evict. Assume that the caller holds buf_pool.mutex and will invoke buf_dblwr.flush_buffered_writes() afterwards. buf_flush_list_holding_mutex(): A low-level variant of buf_flush_list() whose caller must hold buf_pool.mutex and invoke buf_dblwr.flush_buffered_writes() afterwards. buf_flush_wait_batch_end_acquiring_mutex(): Remove. It is enough to have buf_flush_wait_batch_end(). page_cleaner_flush_pages_recommendation(): Avoid some floating-point arithmetics. buf_flush_page(), buf_flush_check_neighbor(), buf_flush_check_neighbors(), buf_flush_try_neighbors(): Rename the parameter "bool lru" to "bool evict". buf_free_from_unzip_LRU_list_batch(): Remove the parameter. Only actual page writes will contribute towards the limit. buf_LRU_free_page(): Evict freed pages of temporary tables. buf_pool.done_free: Broadcast whenever a block is freed (and buf_pool.try_LRU_scan is set). buf_pool_t::io_buf_t::reserve(): Retry indefinitely. During the test encryption.innochecksum we easily run out of these buffers for PAGE_COMPRESSED or ENCRYPTED pages. Tested by Matthias Leich and Axel Schwenke --- storage/innobase/buf/buf0buf.cc | 78 ++++-- storage/innobase/buf/buf0flu.cc | 401 ++++++++++++++--------------- storage/innobase/buf/buf0lru.cc | 66 +++-- storage/innobase/include/buf0buf.h | 51 ++-- storage/innobase/include/buf0flu.h | 13 +- storage/innobase/include/ut0new.h | 1 + 6 files changed, 311 insertions(+), 299 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index c510d320759..f762cf65a01 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -410,9 +410,11 @@ static bool buf_page_decrypt_after_read(buf_page_t *bpage, return (true); } + buf_tmp_buffer_t* slot; + if (node.space->purpose == FIL_TYPE_TEMPORARY && innodb_encrypt_temporary_tables) { - buf_tmp_buffer_t* slot = buf_pool.io_buf_reserve(); + slot = buf_pool.io_buf_reserve(); ut_a(slot); slot->allocate(); @@ -431,7 +433,6 @@ static bool buf_page_decrypt_after_read(buf_page_t *bpage, tablespace and page contains used key_version. This is true also for pages first compressed and then encrypted. */ - buf_tmp_buffer_t* slot; uint key_version = buf_page_get_key_version(dst_frame, flags); if (page_compressed && !key_version) { @@ -444,7 +445,6 @@ decompress: } slot = buf_pool.io_buf_reserve(); - ut_a(slot); slot->allocate(); decompress_with_slot: @@ -472,7 +472,6 @@ decrypt_failed: } slot = buf_pool.io_buf_reserve(); - ut_a(slot); slot->allocate(); ut_d(fil_page_type_validate(node.space, dst_frame)); @@ -1494,6 +1493,41 @@ inline bool buf_pool_t::realloc(buf_block_t *block) return(true); /* free_list was enough */ } +void buf_pool_t::io_buf_t::create(ulint n_slots) +{ + this->n_slots= n_slots; + slots= static_cast + (ut_malloc_nokey(n_slots * sizeof *slots)); + memset((void*) slots, 0, n_slots * sizeof *slots); +} + +void buf_pool_t::io_buf_t::close() +{ + for (buf_tmp_buffer_t *s= slots, *e= slots + n_slots; s != e; s++) + { + aligned_free(s->crypt_buf); + aligned_free(s->comp_buf); + } + ut_free(slots); + slots= nullptr; + n_slots= 0; +} + +buf_tmp_buffer_t *buf_pool_t::io_buf_t::reserve() +{ + for (;;) + { + for (buf_tmp_buffer_t *s= slots, *e= slots + n_slots; s != e; s++) + if (s->acquire()) + return s; + os_aio_wait_until_no_pending_writes(); + for (buf_tmp_buffer_t *s= slots, *e= slots + n_slots; s != e; s++) + if (s->acquire()) + return s; + os_aio_wait_until_no_pending_reads(); + } +} + /** Sets the global variable that feeds MySQL's innodb_buffer_pool_resize_status to the specified string. The format and the following parameters are the same as the ones used for printf(3). @@ -1564,15 +1598,18 @@ inline bool buf_pool_t::withdraw_blocks() block = next_block; } - mysql_mutex_unlock(&mutex); /* reserve free_list length */ if (UT_LIST_GET_LEN(withdraw) < withdraw_target) { ulint n_flushed = buf_flush_LRU( std::max(withdraw_target - UT_LIST_GET_LEN(withdraw), - srv_LRU_scan_depth)); - buf_flush_wait_batch_end_acquiring_mutex(true); + srv_LRU_scan_depth), + true); + mysql_mutex_unlock(&buf_pool.mutex); + buf_dblwr.flush_buffered_writes(); + mysql_mutex_lock(&buf_pool.mutex); + buf_flush_wait_batch_end(true); if (n_flushed) { MONITOR_INC_VALUE_CUMULATIVE( @@ -1586,12 +1623,12 @@ inline bool buf_pool_t::withdraw_blocks() /* relocate blocks/buddies in withdrawn area */ ulint count2 = 0; - mysql_mutex_lock(&mutex); - buf_page_t* bpage; - bpage = UT_LIST_GET_FIRST(LRU); - while (bpage != NULL) { - buf_page_t* next_bpage = UT_LIST_GET_NEXT(LRU, bpage); - if (bpage->zip.data != NULL + buf_pool_mutex_exit_forbid(); + for (buf_page_t* bpage = UT_LIST_GET_FIRST(LRU), *next_bpage; + bpage; bpage = next_bpage) { + ut_ad(bpage->in_file()); + next_bpage = UT_LIST_GET_NEXT(LRU, bpage); + if (UNIV_LIKELY_NULL(bpage->zip.data) && will_be_withdrawn(bpage->zip.data) && bpage->can_relocate()) { buf_pool_mutex_exit_forbid(); @@ -2667,11 +2704,6 @@ buf_page_get_low( || (rw_latch == RW_X_LATCH) || (rw_latch == RW_SX_LATCH) || (rw_latch == RW_NO_LATCH)); - ut_ad(!allow_ibuf_merge - || mode == BUF_GET - || mode == BUF_GET_POSSIBLY_FREED - || mode == BUF_GET_IF_IN_POOL - || mode == BUF_GET_IF_IN_POOL_OR_WATCH); if (err) { *err = DB_SUCCESS; @@ -2685,15 +2717,15 @@ buf_page_get_low( replace any old pages, which were not evicted during DISCARD. Skip the assertion on space_page_size. */ break; - case BUF_PEEK_IF_IN_POOL: + default: + ut_ad(!allow_ibuf_merge); + ut_ad(mode == BUF_PEEK_IF_IN_POOL); + break; + case BUF_GET_POSSIBLY_FREED: case BUF_GET_IF_IN_POOL: /* The caller may pass a dummy page size, because it does not really matter. */ break; - default: - ut_error; - case BUF_GET_POSSIBLY_FREED: - break; case BUF_GET_NO_LATCH: ut_ad(rw_latch == RW_NO_LATCH); /* fall through */ diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 3ee2ea97534..f95af0819b4 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -372,13 +372,12 @@ void buf_page_write_complete(const IORequest &request) if (request.is_LRU()) { buf_LRU_free_page(bpage, true); + buf_pool.try_LRU_scan= true; + pthread_cond_signal(&buf_pool.done_free); ut_ad(buf_pool.n_flush_LRU_); if (!--buf_pool.n_flush_LRU_) - { pthread_cond_broadcast(&buf_pool.done_flush_LRU); - pthread_cond_signal(&buf_pool.done_free); - } } else { @@ -805,10 +804,10 @@ inline void buf_pool_t::release_freed_page(buf_page_t *bpage) /** Write a flushable page from buf_pool to a file. buf_pool.mutex must be held. @param bpage buffer control block -@param lru true=buf_pool.LRU; false=buf_pool.flush_list +@param evict whether to evict the page on write completion @param space tablespace @return whether the page was flushed and buf_pool.mutex was released */ -static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) +static bool buf_flush_page(buf_page_t *bpage, bool evict, fil_space_t *space) { ut_ad(bpage->in_file()); ut_ad(bpage->ready_for_flush()); @@ -817,7 +816,7 @@ static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) ut_ad(space->purpose == FIL_TYPE_TABLESPACE || space->atomic_write_supported); ut_ad(space->referenced()); - ut_ad(lru || space != fil_system.temp_space); + ut_ad(evict || space != fil_system.temp_space); rw_lock_t *rw_lock; @@ -840,7 +839,7 @@ static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) if (status != buf_page_t::FREED) { - if (lru) + if (evict) buf_pool.n_flush_LRU_++; else buf_pool.n_flush_list_++; @@ -858,7 +857,7 @@ static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) the buffer pool or removed from flush_list or LRU_list. */ DBUG_PRINT("ib_buf", ("%s %u page %u:%u", - lru ? "LRU" : "flush_list", + evict ? "LRU" : "flush_list", bpage->id().space(), bpage->id().page_no())); ut_ad(bpage->io_fix() == BUF_IO_WRITE); ut_d(const lsn_t oldest_modification= bpage->oldest_modification()); @@ -868,7 +867,7 @@ static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) ut_ad(bpage->state() == (rw_lock ? BUF_BLOCK_FILE_PAGE : BUF_BLOCK_ZIP_PAGE)); ut_ad(ULINT_UNDEFINED > - (lru ? buf_pool.n_flush_LRU_ : buf_pool.n_flush_list_)); + (evict ? buf_pool.n_flush_LRU_ : buf_pool.n_flush_list_)); mysql_mutex_unlock(&buf_pool.mutex); buf_block_t *block= reinterpret_cast(bpage); @@ -895,7 +894,8 @@ static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) #if defined HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || defined _WIN32 size_t orig_size; #endif - IORequest::Type type= lru ? IORequest::WRITE_LRU : IORequest::WRITE_ASYNC; + IORequest::Type type= evict + ? IORequest::WRITE_LRU : IORequest::WRITE_ASYNC; if (UNIV_UNLIKELY(!rw_lock)) /* ROW_FORMAT=COMPRESSED */ { @@ -934,7 +934,7 @@ static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) #if defined HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || defined _WIN32 if (size != orig_size && space->punch_hole) - type= lru ? IORequest::PUNCH_LRU : IORequest::PUNCH; + type= evict ? IORequest::PUNCH_LRU : IORequest::PUNCH; #endif frame=page; } @@ -968,9 +968,10 @@ static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) /** Check whether a page can be flushed from the buf_pool. @param id page identifier @param fold id.fold() -@param lru true=buf_pool.LRU; false=buf_pool.flush_list +@param evict true=buf_pool.LRU; false=buf_pool.flush_list @return whether the page can be flushed */ -static bool buf_flush_check_neighbor(const page_id_t id, ulint fold, bool lru) +static bool buf_flush_check_neighbor(const page_id_t id, ulint fold, + bool evict) { mysql_mutex_assert_owner(&buf_pool.mutex); ut_ad(fold == id.fold()); @@ -980,9 +981,9 @@ static bool buf_flush_check_neighbor(const page_id_t id, ulint fold, bool lru) if (!bpage || buf_pool.watch_is_sentinel(*bpage)) return false; - /* We avoid flushing 'non-old' blocks in an LRU flush, because the + /* We avoid flushing 'non-old' blocks in an eviction flush, because the flushed blocks are soon freed */ - if (lru && !bpage->is_old()) + if (evict && !bpage->is_old()) return false; return bpage->oldest_modification() > 1 && bpage->ready_for_flush(); @@ -992,11 +993,11 @@ static bool buf_flush_check_neighbor(const page_id_t id, ulint fold, bool lru) @param space tablespace @param id page identifier of a dirty page @param contiguous whether to consider contiguous areas of pages -@param lru true=buf_pool.LRU; false=buf_pool.flush_list +@param evict true=buf_pool.LRU; false=buf_pool.flush_list @return last page number that can be flushed */ static page_id_t buf_flush_check_neighbors(const fil_space_t &space, page_id_t &id, bool contiguous, - bool lru) + bool evict) { ut_ad(id.page_no() < space.size + (space.physical_size() == 2048 ? 1 @@ -1029,7 +1030,7 @@ static page_id_t buf_flush_check_neighbors(const fil_space_t &space, for (page_id_t i= id - 1;; --i) { fold--; - if (!buf_flush_check_neighbor(i, fold, lru)) + if (!buf_flush_check_neighbor(i, fold, evict)) { low= i + 1; break; @@ -1045,7 +1046,7 @@ static page_id_t buf_flush_check_neighbors(const fil_space_t &space, while (++i < high) { ++fold; - if (!buf_flush_check_neighbor(i, fold, lru)) + if (!buf_flush_check_neighbor(i, fold, evict)) break; } @@ -1120,20 +1121,20 @@ and also write zeroes or punch the hole for the freed ranges of pages. @param space tablespace @param page_id page identifier @param contiguous whether to consider contiguous areas of pages -@param lru true=buf_pool.LRU; false=buf_pool.flush_list +@param evict true=buf_pool.LRU; false=buf_pool.flush_list @param n_flushed number of pages flushed so far in this batch @param n_to_flush maximum number of pages we are allowed to flush @return number of pages flushed */ static ulint buf_flush_try_neighbors(fil_space_t *space, const page_id_t page_id, - bool contiguous, bool lru, + bool contiguous, bool evict, ulint n_flushed, ulint n_to_flush) { ut_ad(space->id == page_id.space()); ulint count= 0; page_id_t id= page_id; - page_id_t high= buf_flush_check_neighbors(*space, id, contiguous, lru); + page_id_t high= buf_flush_check_neighbors(*space, id, contiguous, evict); ut_ad(page_id >= id); ut_ad(page_id < high); @@ -1156,13 +1157,13 @@ static ulint buf_flush_try_neighbors(fil_space_t *space, if (buf_page_t *bpage= buf_pool.page_hash_get_low(id, id_fold)) { ut_ad(bpage->in_file()); - /* We avoid flushing 'non-old' blocks in an LRU flush, + /* We avoid flushing 'non-old' blocks in an eviction flush, because the flushed blocks are soon freed */ - if (!lru || id == page_id || bpage->is_old()) + if (!evict || id == page_id || bpage->is_old()) { if (!buf_pool.watch_is_sentinel(*bpage) && - bpage->oldest_modification() > 1 && - bpage->ready_for_flush() && buf_flush_page(bpage, lru, space)) + bpage->oldest_modification() > 1 && bpage->ready_for_flush() && + buf_flush_page(bpage, evict, space)) { ++count; continue; @@ -1188,12 +1189,8 @@ This utility moves the uncompressed frames of pages to the free list. Note that this function does not actually flush any data to disk. It just detaches the uncompressed frames from the compressed pages at the tail of the unzip_LRU and puts those freed frames in the free list. -Note that it is a best effort attempt and it is not guaranteed that -after a call to this function there will be 'max' blocks in the free -list. -@param[in] max desired number of blocks in the free_list @return number of blocks moved to the free list. */ -static ulint buf_free_from_unzip_LRU_list_batch(ulint max) +static ulint buf_free_from_unzip_LRU_list_batch() { ulint scanned = 0; ulint count = 0; @@ -1203,7 +1200,6 @@ static ulint buf_free_from_unzip_LRU_list_batch(ulint max) buf_block_t* block = UT_LIST_GET_LAST(buf_pool.unzip_LRU); while (block - && count < max && UT_LIST_GET_LEN(buf_pool.free) < srv_LRU_scan_depth && UT_LIST_GET_LEN(buf_pool.unzip_LRU) > UT_LIST_GET_LEN(buf_pool.LRU) / 10) { @@ -1281,10 +1277,13 @@ static void buf_flush_discard_page(buf_page_t *bpage) buf_LRU_free_page(bpage, true); } -/** Flush dirty blocks from the end of the LRU list. -@param max maximum number of blocks to make available in buf_pool.free -@param n counts of flushed and evicted pages */ -static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) +/** Flush dirty blocks from the end buf_pool.LRU, +and move clean blocks to buf_pool.free. +@param max maximum number of blocks to flush +@param evict whether dirty pages are to be evicted after flushing them +@param n counts of flushed and evicted pages */ +static void buf_flush_LRU_list_batch(ulint max, bool evict, + flush_counters_t *n) { ulint scanned= 0; ulint free_limit= srv_LRU_scan_depth; @@ -1296,6 +1295,7 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) const auto neighbors= UT_LIST_GET_LEN(buf_pool.LRU) < BUF_LRU_OLD_MIN_LEN ? 0 : srv_flush_neighbors; fil_space_t *space= nullptr; + bool do_evict= evict; uint32_t last_space_id= FIL_NULL; static_assert(FIL_NULL > SRV_TMP_SPACE_ID, "consistency"); static_assert(FIL_NULL > SRV_SPACE_ID_UPPER_BOUND, "consistency"); @@ -1303,8 +1303,7 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.LRU); bpage && ((UT_LIST_GET_LEN(buf_pool.LRU) > BUF_LRU_MIN_LEN && - UT_LIST_GET_LEN(buf_pool.free) < free_limit && - n->flushed + n->evicted < max) || + UT_LIST_GET_LEN(buf_pool.free) < free_limit) || recv_recovery_is_on()); ++scanned) { buf_page_t *prev= UT_LIST_GET_PREV(LRU, bpage); @@ -1320,8 +1319,8 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) } else if (oldest_modification > 1 && bpage->ready_for_flush()) { - /* Block is ready for flush. Dispatch an IO request. The IO - helper thread will put it on free list in IO completion routine. */ + /* Block is ready for flush. Dispatch an IO request. + If evict=true, the page will be evicted by buf_page_write_complete(). */ const page_id_t page_id(bpage->id()); const uint32_t space_id= page_id.space(); if (!space || space->id != space_id) @@ -1334,6 +1333,9 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) space->release(); auto p= buf_flush_space(space_id); space= p.first; + /* For the temporary tablespace, LRU flushing will always + evict pages upon completing the write. */ + do_evict= evict || space == fil_system.temp_space; last_space_id= space_id; mysql_mutex_lock(&buf_pool.mutex); if (p.second) @@ -1355,11 +1357,13 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) { mysql_mutex_unlock(&buf_pool.mutex); n->flushed+= buf_flush_try_neighbors(space, page_id, neighbors == 1, - true, n->flushed, max); + do_evict, n->flushed, max); reacquire_mutex: mysql_mutex_lock(&buf_pool.mutex); } - else if (buf_flush_page(bpage, true, space)) + else if (n->flushed >= max && !recv_recovery_is_on()) + break; + else if (buf_flush_page(bpage, do_evict, space)) { ++n->flushed; goto reacquire_mutex; @@ -1393,27 +1397,24 @@ reacquire_mutex: /** Flush and move pages from LRU or unzip_LRU list to the free list. Whether LRU or unzip_LRU is used depends on the state of the system. -@param max maximum number of blocks to make available in buf_pool.free -@return number of flushed pages */ -static ulint buf_do_LRU_batch(ulint max) +@param max maximum number of blocks to flush +@param evict whether dirty pages are to be evicted after flushing them +@param n counts of flushed and evicted pages */ +static void buf_do_LRU_batch(ulint max, bool evict, flush_counters_t *n) { - const ulint n_unzip_LRU_evicted= buf_LRU_evict_from_unzip_LRU() - ? buf_free_from_unzip_LRU_list_batch(max) - : 0; - flush_counters_t n; - n.flushed= 0; - n.evicted= n_unzip_LRU_evicted; - buf_flush_LRU_list_batch(max, &n); + if (buf_LRU_evict_from_unzip_LRU()) + buf_free_from_unzip_LRU_list_batch(); + n->evicted= 0; + n->flushed= 0; + buf_flush_LRU_list_batch(max, evict, n); - if (const ulint evicted= n.evicted - n_unzip_LRU_evicted) - { - MONITOR_INC_VALUE_CUMULATIVE(MONITOR_LRU_BATCH_EVICT_TOTAL_PAGE, - MONITOR_LRU_BATCH_EVICT_COUNT, - MONITOR_LRU_BATCH_EVICT_PAGES, - evicted); - } + mysql_mutex_assert_owner(&buf_pool.mutex); + buf_lru_flush_page_count+= n->flushed; - return n.flushed; + MONITOR_INC_VALUE_CUMULATIVE(MONITOR_LRU_BATCH_EVICT_TOTAL_PAGE, + MONITOR_LRU_BATCH_EVICT_COUNT, + MONITOR_LRU_BATCH_EVICT_PAGES, + n->evicted); } /** This utility flushes dirty blocks from the end of the flush_list. @@ -1469,7 +1470,7 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn) from buf_pool.flush_list must adjust the hazard pointer. Note: A concurrent execution of buf_flush_list_space() may - terminate this scan prematurely. The buf_pool.n_flush_list() + terminate this scan prematurely. The buf_pool.n_flush_list_ should prevent multiple threads from executing buf_do_flush_list_batch() concurrently, but buf_flush_list_space() is ignoring that. */ @@ -1576,46 +1577,53 @@ void buf_flush_wait_batch_end(bool lru) } /** Write out dirty blocks from buf_pool.flush_list. +The caller must invoke buf_dblwr.flush_buffered_writes() +after releasing buf_pool.mutex. @param max_n wished maximum mumber of blocks flushed @param lsn buf_pool.get_oldest_modification(LSN_MAX) target @return the number of processed pages @retval 0 if a buf_pool.flush_list batch is already running */ -static ulint buf_flush_list(ulint max_n= ULINT_UNDEFINED, lsn_t lsn= LSN_MAX) +static ulint buf_flush_list_holding_mutex(ulint max_n= ULINT_UNDEFINED, + lsn_t lsn= LSN_MAX) { ut_ad(lsn); + mysql_mutex_assert_owner(&buf_pool.mutex); - if (buf_pool.n_flush_list()) + if (buf_pool.n_flush_list_) return 0; - mysql_mutex_lock(&buf_pool.mutex); - const bool running= buf_pool.n_flush_list_ != 0; /* FIXME: we are performing a dirty read of buf_pool.flush_list.count while not holding buf_pool.flush_list_mutex */ - if (running || !UT_LIST_GET_LEN(buf_pool.flush_list)) + if (!UT_LIST_GET_LEN(buf_pool.flush_list)) { - if (!running) - pthread_cond_broadcast(&buf_pool.done_flush_list); - mysql_mutex_unlock(&buf_pool.mutex); + pthread_cond_broadcast(&buf_pool.done_flush_list); return 0; } buf_pool.n_flush_list_++; const ulint n_flushed= buf_do_flush_list_batch(max_n, lsn); - const ulint n_flushing= --buf_pool.n_flush_list_; - - buf_pool.try_LRU_scan= true; - - mysql_mutex_unlock(&buf_pool.mutex); - - if (!n_flushing) + if (!--buf_pool.n_flush_list_) pthread_cond_broadcast(&buf_pool.done_flush_list); - buf_dblwr.flush_buffered_writes(); - DBUG_PRINT("ib_buf", ("flush_list completed, " ULINTPF " pages", n_flushed)); return n_flushed; } +/** Write out dirty blocks from buf_pool.flush_list. +@param max_n wished maximum mumber of blocks flushed +@param lsn buf_pool.get_oldest_modification(LSN_MAX) target +@return the number of processed pages +@retval 0 if a buf_pool.flush_list batch is already running */ +static ulint buf_flush_list(ulint max_n= ULINT_UNDEFINED, + lsn_t lsn= LSN_MAX) +{ + mysql_mutex_lock(&buf_pool.mutex); + ulint n= buf_flush_list_holding_mutex(max_n, lsn); + mysql_mutex_unlock(&buf_pool.mutex); + buf_dblwr.flush_buffered_writes(); + return n; +} + /** Try to flush all the dirty pages that belong to a given tablespace. @param space tablespace @param n_flushed number of pages written @@ -1716,7 +1724,7 @@ bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed) mysql_mutex_unlock(&buf_pool.flush_list_mutex); buf_pool.try_LRU_scan= true; - + pthread_cond_broadcast(&buf_pool.done_free); mysql_mutex_unlock(&buf_pool.mutex); if (acquired) @@ -1730,43 +1738,41 @@ bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed) return may_have_skipped; } -/** Write out dirty blocks from buf_pool.LRU. +/** Write out dirty blocks from buf_pool.LRU, +and move clean blocks to buf_pool.free. +The caller must invoke buf_dblwr.flush_buffered_writes() +after releasing buf_pool.mutex. @param max_n wished maximum mumber of blocks flushed -@return the number of processed pages +@param evict whether to evict pages after flushing +@return evict ? number of processed pages : number of pages written @retval 0 if a buf_pool.LRU batch is already running */ -ulint buf_flush_LRU(ulint max_n) +ulint buf_flush_LRU(ulint max_n, bool evict) { - if (buf_pool.n_flush_LRU()) - return 0; + mysql_mutex_assert_owner(&buf_pool.mutex); - log_buffer_flush_to_disk(true); - - mysql_mutex_lock(&buf_pool.mutex); - if (buf_pool.n_flush_LRU_) + if (evict) { - mysql_mutex_unlock(&buf_pool.mutex); - return 0; + if (buf_pool.n_flush_LRU_) + return 0; + buf_pool.n_flush_LRU_= 1; } - buf_pool.n_flush_LRU_++; - ulint n_flushed= buf_do_LRU_batch(max_n); + flush_counters_t n; + buf_do_LRU_batch(max_n, evict, &n); - const ulint n_flushing= --buf_pool.n_flush_LRU_; - - buf_pool.try_LRU_scan= true; - - mysql_mutex_unlock(&buf_pool.mutex); - - if (!n_flushing) + if (n.evicted) { - pthread_cond_broadcast(&buf_pool.done_flush_LRU); + buf_pool.try_LRU_scan= true; pthread_cond_signal(&buf_pool.done_free); } - buf_dblwr.flush_buffered_writes(); + if (!evict) + return n.flushed; - DBUG_PRINT("ib_buf", ("LRU flush completed, " ULINTPF " pages", n_flushed)); - return n_flushed; + if (!--buf_pool.n_flush_LRU_) + pthread_cond_broadcast(&buf_pool.done_flush_LRU); + + return n.evicted + n.flushed; } /** Initiate a log checkpoint, discarding the start of the log. @@ -1928,7 +1934,9 @@ ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn) { mysql_mutex_unlock(&buf_pool.flush_list_mutex); ulint n_pages= buf_flush_list(srv_max_io_capacity, sync_lsn); - buf_flush_wait_batch_end_acquiring_mutex(false); + mysql_mutex_lock(&buf_pool.mutex); + buf_flush_wait_batch_end(false); + mysql_mutex_unlock(&buf_pool.mutex); if (n_pages) { MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_SYNC_TOTAL_PAGE, @@ -1994,17 +2002,6 @@ ATTRIBUTE_COLD void buf_flush_ahead(lsn_t lsn, bool furious) } } -/** Wait for pending flushes to complete. */ -void buf_flush_wait_batch_end_acquiring_mutex(bool lru) -{ - if (lru ? buf_pool.n_flush_LRU() : buf_pool.n_flush_list()) - { - mysql_mutex_lock(&buf_pool.mutex); - buf_flush_wait_batch_end(lru); - mysql_mutex_unlock(&buf_pool.mutex); - } -} - /** Conduct checkpoint-related flushing for innodb_flush_sync=ON, and try to initiate checkpoints until the target is met. @param lsn minimum value of buf_pool.get_oldest_modification(LSN_MAX) */ @@ -2116,8 +2113,9 @@ af_get_pct_for_lsn( / 7.5)); } -/** This function is called approximately once every second by the -page_cleaner thread if innodb_adaptive_flushing=ON. +/** This function is called approximately once every second by +buf_flush_page_cleaner() if innodb_max_dirty_pages_pct_lwm>0 +and innodb_adaptive_flushing=ON. Based on various factors it decides if there is a need to do flushing. @return number of pages recommended to be flushed @param last_pages_in number of pages flushed in previous batch @@ -2155,52 +2153,43 @@ static ulint page_cleaner_flush_pages_recommendation(ulint last_pages_in, n_pages= std::min(srv_io_capacity, dirty_blocks); } +func_exit: + page_cleaner.flush_pass++; return n_pages; } sum_pages += last_pages_in; - double time_elapsed = difftime(curr_time, prev_time); + const ulint time_elapsed = std::max(curr_time - prev_time, 1); - /* We update our variables every srv_flushing_avg_loops + /* We update our variables every innodb_flushing_avg_loops iterations to smooth out transition in workload. */ if (++n_iterations >= srv_flushing_avg_loops - || time_elapsed >= static_cast(srv_flushing_avg_loops)) { + || time_elapsed >= srv_flushing_avg_loops) { - if (time_elapsed < 1) { - time_elapsed = 1; - } - - avg_page_rate = static_cast( - ((static_cast(sum_pages) - / time_elapsed) - + static_cast(avg_page_rate)) / 2); + avg_page_rate = (sum_pages / time_elapsed + avg_page_rate) / 2; /* How much LSN we have generated since last call. */ - lsn_rate = static_cast( - static_cast(cur_lsn - prev_lsn) - / time_elapsed); + lsn_rate = (cur_lsn - prev_lsn) / time_elapsed; lsn_avg_rate = (lsn_avg_rate + lsn_rate) / 2; - ulint flush_tm = page_cleaner.flush_time; - ulint flush_pass = page_cleaner.flush_pass; - - page_cleaner.flush_time = 0; - page_cleaner.flush_pass = 0; - - if (flush_pass) { - flush_tm /= flush_pass; + if (page_cleaner.flush_pass) { + page_cleaner.flush_time /= page_cleaner.flush_pass; } - MONITOR_SET(MONITOR_FLUSH_ADAPTIVE_AVG_TIME, flush_tm); - MONITOR_SET(MONITOR_FLUSH_ADAPTIVE_AVG_PASS, flush_pass); - prev_lsn = cur_lsn; prev_time = curr_time; - n_iterations = 0; + MONITOR_SET(MONITOR_FLUSH_ADAPTIVE_AVG_TIME, + page_cleaner.flush_time); + MONITOR_SET(MONITOR_FLUSH_ADAPTIVE_AVG_PASS, + page_cleaner.flush_pass); + page_cleaner.flush_time = 0; + page_cleaner.flush_pass = 0; + + n_iterations = 0; sum_pages = 0; } @@ -2250,7 +2239,7 @@ static ulint page_cleaner_flush_pages_recommendation(ulint last_pages_in, MONITOR_SET(MONITOR_FLUSH_PCT_FOR_DIRTY, pct_for_dirty); MONITOR_SET(MONITOR_FLUSH_PCT_FOR_LSN, pct_for_lsn); - return(n_pages); + goto func_exit; } /******************************************************************//** @@ -2281,7 +2270,7 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) if (UNIV_UNLIKELY(lsn_limit != 0)) { -furious_flush: + furious_flush: if (UNIV_LIKELY(srv_flush_sync)) { buf_flush_sync_for_checkpoint(lsn_limit); @@ -2299,7 +2288,8 @@ furious_flush: if (buf_pool.page_cleaner_idle() && (!UT_LIST_GET_LEN(buf_pool.flush_list) || srv_max_dirty_pages_pct_lwm == 0.0)) - my_cond_wait(&buf_pool.do_flush_list, &buf_pool.flush_list_mutex.m_mutex); + my_cond_wait(&buf_pool.do_flush_list, + &buf_pool.flush_list_mutex.m_mutex); else my_cond_timedwait(&buf_pool.do_flush_list, &buf_pool.flush_list_mutex.m_mutex, &abstime); @@ -2327,19 +2317,25 @@ furious_flush: /* wake up buf_flush_wait() */ pthread_cond_broadcast(&buf_pool.done_flush_list); } -unemployed: + unemployed: buf_flush_async_lsn= 0; + set_idle: buf_pool.page_cleaner_set_idle(true); - - DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", continue;); - DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", continue;); - mysql_mutex_unlock(&buf_pool.flush_list_mutex); + end_of_batch: + buf_dblwr.flush_buffered_writes(); - if (!recv_recovery_is_on() && - !srv_startup_is_before_trx_rollback_phase && - srv_operation <= SRV_OPERATION_EXPORT_RESTORED) - log_checkpoint(); + do + { + DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", continue;); + DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", continue;); + + if (!recv_recovery_is_on() && + !srv_startup_is_before_trx_rollback_phase && + srv_operation <= SRV_OPERATION_EXPORT_RESTORED) + log_checkpoint(); + } + while (false); mysql_mutex_lock(&buf_pool.flush_list_mutex); continue; @@ -2390,57 +2386,40 @@ unemployed: if (!lsn_limit) lsn_limit= soft_lsn_limit; - ulint n_flushed; + ulint n_flushed= 0, n; if (UNIV_UNLIKELY(lsn_limit != 0)) { - n_flushed= buf_flush_list(srv_max_io_capacity, lsn_limit); - /* wake up buf_flush_wait() */ - pthread_cond_broadcast(&buf_pool.done_flush_list); - goto try_checkpoint; + n= srv_max_io_capacity; + goto background_flush; } else if (idle_flush || !srv_adaptive_flushing) { - n_flushed= buf_flush_list(srv_io_capacity); -try_checkpoint: - if (n_flushed) - { - MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_BACKGROUND_TOTAL_PAGE, - MONITOR_FLUSH_BACKGROUND_COUNT, - MONITOR_FLUSH_BACKGROUND_PAGES, - n_flushed); -do_checkpoint: - /* The periodic log_checkpoint() call here makes it harder to - reproduce bugs in crash recovery or mariabackup --prepare, or - in code that writes the redo log records. Omitting the call - here should not affect correctness, because log_free_check() - should still be invoking checkpoints when needed. */ - DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", goto next;); - DBUG_EXECUTE_IF("ib_log_checkpoint_avoid_hard", goto next;); - - if (!recv_recovery_is_on() - && srv_operation <= SRV_OPERATION_EXPORT_RESTORED) - log_checkpoint(); - } + n= srv_io_capacity; + lsn_limit= LSN_MAX; + background_flush: + mysql_mutex_lock(&buf_pool.mutex); + n_flushed= buf_flush_list_holding_mutex(n, lsn_limit); + /* wake up buf_flush_wait() */ + pthread_cond_broadcast(&buf_pool.done_flush_list); + MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_BACKGROUND_TOTAL_PAGE, + MONITOR_FLUSH_BACKGROUND_COUNT, + MONITOR_FLUSH_BACKGROUND_PAGES, + n_flushed); } - else if (ulint n= page_cleaner_flush_pages_recommendation(last_pages, - oldest_lsn, - dirty_blocks, - dirty_pct)) + else if ((n= page_cleaner_flush_pages_recommendation(last_pages, + oldest_lsn, + dirty_blocks, + dirty_pct)) != 0) { - page_cleaner.flush_pass++; const ulint tm= ut_time_ms(); - last_pages= n_flushed= buf_flush_list(n); + mysql_mutex_lock(&buf_pool.mutex); + last_pages= n_flushed= buf_flush_list_holding_mutex(n); page_cleaner.flush_time+= ut_time_ms() - tm; - - if (n_flushed) - { - MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_ADAPTIVE_TOTAL_PAGE, - MONITOR_FLUSH_ADAPTIVE_COUNT, - MONITOR_FLUSH_ADAPTIVE_PAGES, - n_flushed); - goto do_checkpoint; - } + MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_ADAPTIVE_TOTAL_PAGE, + MONITOR_FLUSH_ADAPTIVE_COUNT, + MONITOR_FLUSH_ADAPTIVE_PAGES, + n_flushed); } else if (buf_flush_async_lsn <= oldest_lsn) { @@ -2448,24 +2427,29 @@ do_checkpoint: goto unemployed; } -#ifndef DBUG_OFF -next: -#endif /* !DBUG_OFF */ - mysql_mutex_lock(&buf_pool.flush_list_mutex); + n= buf_flush_LRU(n >= n_flushed ? n - n_flushed : 0, false); + mysql_mutex_unlock(&buf_pool.mutex); + last_pages+= n; + + if (!idle_flush) + goto end_of_batch; /* when idle flushing kicks in page_cleaner is marked active. reset it back to idle since the it was made active as part of idle flushing stage. */ - if (idle_flush) - buf_pool.page_cleaner_set_idle(true); + mysql_mutex_lock(&buf_pool.flush_list_mutex); + goto set_idle; } mysql_mutex_unlock(&buf_pool.flush_list_mutex); if (srv_fast_shutdown != 2) { - buf_flush_wait_batch_end_acquiring_mutex(true); - buf_flush_wait_batch_end_acquiring_mutex(false); + buf_dblwr.flush_buffered_writes(); + mysql_mutex_lock(&buf_pool.mutex); + buf_flush_wait_batch_end(true); + buf_flush_wait_batch_end(false); + mysql_mutex_unlock(&buf_pool.mutex); } mysql_mutex_lock(&buf_pool.flush_list_mutex); @@ -2520,20 +2504,23 @@ ATTRIBUTE_COLD void buf_flush_buffer_pool() while (buf_pool.get_oldest_modification(0)) { mysql_mutex_unlock(&buf_pool.flush_list_mutex); - buf_flush_list(srv_max_io_capacity); - if (buf_pool.n_flush_list()) + mysql_mutex_lock(&buf_pool.mutex); + buf_flush_list_holding_mutex(srv_max_io_capacity); + if (buf_pool.n_flush_list_) { + mysql_mutex_unlock(&buf_pool.mutex); timespec abstime; service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, "Waiting to flush " ULINTPF " pages", buf_flush_list_length()); set_timespec(abstime, INNODB_EXTEND_TIMEOUT_INTERVAL / 2); + buf_dblwr.flush_buffered_writes(); mysql_mutex_lock(&buf_pool.mutex); while (buf_pool.n_flush_list_) my_cond_timedwait(&buf_pool.done_flush_list, &buf_pool.mutex.m_mutex, &abstime); - mysql_mutex_unlock(&buf_pool.mutex); } + mysql_mutex_unlock(&buf_pool.mutex); mysql_mutex_lock(&buf_pool.flush_list_mutex); } diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 0e9f834f127..34d737b3103 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -413,6 +413,7 @@ buf_block_t *buf_LRU_get_free_block(bool have_mutex) && recv_sys.apply_log_recs) { goto flush_lru; }); +get_mutex: mysql_mutex_lock(&buf_pool.mutex); got_mutex: buf_LRU_check_size_of_non_data_objects(); @@ -501,15 +502,18 @@ not_found: #ifndef DBUG_OFF flush_lru: #endif - if (!buf_flush_LRU(innodb_lru_flush_size)) { + mysql_mutex_lock(&buf_pool.mutex); + + if (!buf_flush_LRU(innodb_lru_flush_size, true)) { MONITOR_INC(MONITOR_LRU_SINGLE_FLUSH_FAILURE_COUNT); ++flush_failures; } n_iterations++; - mysql_mutex_lock(&buf_pool.mutex); buf_pool.stat.LRU_waits++; - goto got_mutex; + mysql_mutex_unlock(&buf_pool.mutex); + buf_dblwr.flush_buffered_writes(); + goto get_mutex; } /** Move the LRU_old pointer so that the length of the old blocks list @@ -815,52 +819,60 @@ bool buf_LRU_free_page(buf_page_t *bpage, bool zip) const ulint fold = id.fold(); page_hash_latch* hash_lock = buf_pool.page_hash.lock_get(fold); hash_lock->write_lock(); - lsn_t oldest_modification = bpage->oldest_modification_acquire(); + const lsn_t oldest_modification = bpage->oldest_modification_acquire(); if (UNIV_UNLIKELY(!bpage->can_relocate())) { /* Do not free buffer fixed and I/O-fixed blocks. */ goto func_exit; } - if (oldest_modification == 1) { + switch (oldest_modification) { + case 2: + ut_ad(id.space() == SRV_TMP_SPACE_ID); + ut_ad(!bpage->zip.data); + if (bpage->status != buf_page_t::FREED) { + goto func_exit; + } + bpage->clear_oldest_modification(); + break; + case 1: mysql_mutex_lock(&buf_pool.flush_list_mutex); - oldest_modification = bpage->oldest_modification(); - if (oldest_modification) { - ut_ad(oldest_modification == 1); + if (const lsn_t om = bpage->oldest_modification()) { + ut_ad(om == 1); buf_pool.delete_from_flush_list(bpage); } mysql_mutex_unlock(&buf_pool.flush_list_mutex); ut_ad(!bpage->oldest_modification()); - oldest_modification = 0; - } - - if (zip || !bpage->zip.data) { - /* This would completely free the block. */ - /* Do not completely free dirty blocks. */ - - if (oldest_modification) { - goto func_exit; + /* fall through */ + case 0: + if (zip || !bpage->zip.data + || bpage->state() != BUF_BLOCK_FILE_PAGE) { + break; } - } else if (oldest_modification - && bpage->state() != BUF_BLOCK_FILE_PAGE) { -func_exit: - hash_lock->write_unlock(); - return(false); - - } else if (bpage->state() == BUF_BLOCK_FILE_PAGE) { - b = buf_page_alloc_descriptor(); +relocate_compressed: + b = static_cast(ut_zalloc_nokey(sizeof *b)); ut_a(b); mysql_mutex_lock(&buf_pool.flush_list_mutex); new (b) buf_page_t(*bpage); b->set_state(BUF_BLOCK_ZIP_PAGE); + break; + default: + if (zip || !bpage->zip.data + || bpage->state() != BUF_BLOCK_FILE_PAGE) { + /* This would completely free the block. */ + /* Do not completely free dirty blocks. */ +func_exit: + hash_lock->write_unlock(); + return(false); + } + goto relocate_compressed; } mysql_mutex_assert_owner(&buf_pool.mutex); ut_ad(bpage->in_file()); ut_ad(bpage->in_LRU_list); - DBUG_PRINT("ib_buf", ("free page %u:%u", - id.space(), id.page_no())); + DBUG_PRINT("ib_buf", ("free page %u:%u", id.space(), id.page_no())); ut_ad(bpage->can_relocate()); diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index a84ea047a54..def7641db1d 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -1786,16 +1786,13 @@ public: MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) mysql_mutex_t mutex; /** Number of pending LRU flush; protected by mutex. */ ulint n_flush_LRU_; - /** broadcast when n_flush_LRU reaches 0; protected by mutex */ + /** broadcast when n_flush_LRU_ reaches 0; protected by mutex */ pthread_cond_t done_flush_LRU; /** Number of pending flush_list flush; protected by mutex */ ulint n_flush_list_; - /** broadcast when n_flush_list reaches 0; protected by mutex */ + /** broadcast when n_flush_list_ reaches 0; protected by mutex */ pthread_cond_t done_flush_list; - TPOOL_SUPPRESS_TSAN ulint n_flush_LRU() const { return n_flush_LRU_; } - TPOOL_SUPPRESS_TSAN ulint n_flush_list() const { return n_flush_list_; } - /** @name General fields */ /* @{ */ ulint curr_pool_size; /*!< Current pool size in bytes */ @@ -1949,7 +1946,7 @@ public: last_activity_count= activity_count; } - // n_flush_LRU() + n_flush_list() + // n_flush_LRU_ + n_flush_list_ // is approximately COUNT(io_fix()==BUF_IO_WRITE) in flush_list unsigned freed_page_clock;/*!< a sequence number used @@ -1979,7 +1976,8 @@ public: UT_LIST_BASE_NODE_T(buf_page_t) free; /*!< base node of the free block list */ - /** signaled each time when the free list grows; protected by mutex */ + /** signaled each time when the free list grows and + broadcast each time try_LRU_scan is set; protected by mutex */ pthread_cond_t done_free; UT_LIST_BASE_NODE_T(buf_page_t) withdraw; @@ -2045,9 +2043,9 @@ public: return any_pending; } /** @return total amount of pending I/O */ - ulint io_pending() const + TPOOL_SUPPRESS_TSAN ulint io_pending() const { - return n_pend_reads + n_flush_LRU() + n_flush_list(); + return n_pend_reads + n_flush_LRU_ + n_flush_list_; } private: @@ -2080,34 +2078,12 @@ private: /** array of slots */ buf_tmp_buffer_t *slots; - void create(ulint n_slots) - { - this->n_slots= n_slots; - slots= static_cast - (ut_malloc_nokey(n_slots * sizeof *slots)); - memset((void*) slots, 0, n_slots * sizeof *slots); - } + void create(ulint n_slots); - void close() - { - for (buf_tmp_buffer_t *s= slots, *e= slots + n_slots; s != e; s++) - { - aligned_free(s->crypt_buf); - aligned_free(s->comp_buf); - } - ut_free(slots); - slots= nullptr; - n_slots= 0; - } + void close(); /** Reserve a buffer */ - buf_tmp_buffer_t *reserve() - { - for (buf_tmp_buffer_t *s= slots, *e= slots + n_slots; s != e; s++) - if (s->acquire()) - return s; - return nullptr; - } + buf_tmp_buffer_t *reserve(); } io_buf; /** whether resize() is in the critical path */ @@ -2218,7 +2194,10 @@ inline void buf_page_t::set_oldest_modification(lsn_t lsn) /** Clear oldest_modification after removing from buf_pool.flush_list */ inline void buf_page_t::clear_oldest_modification() { - mysql_mutex_assert_owner(&buf_pool.flush_list_mutex); +#ifdef SAFE_MUTEX + if (oldest_modification() != 2) + mysql_mutex_assert_owner(&buf_pool.flush_list_mutex); +#endif /* SAFE_MUTEX */ ut_d(const auto state= state_); ut_ad(state == BUF_BLOCK_FILE_PAGE || state == BUF_BLOCK_ZIP_PAGE || state == BUF_BLOCK_REMOVE_HASH); @@ -2337,7 +2316,7 @@ MEMORY: is not in free list, LRU list, or flush list, nor page hash table FILE_PAGE: space and offset are defined, is in page hash table if io_fix == BUF_IO_WRITE, - buf_pool.n_flush_LRU() || buf_pool.n_flush_list() + buf_pool.n_flush_LRU_ || buf_pool.n_flush_list_ (1) if buf_fix_count == 0, then is in LRU list, not in free list diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h index c772f84147d..8f18a45cb7a 100644 --- a/storage/innobase/include/buf0flu.h +++ b/storage/innobase/include/buf0flu.h @@ -85,11 +85,15 @@ buf_flush_init_for_writing( bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed= nullptr) MY_ATTRIBUTE((warn_unused_result)); -/** Write out dirty blocks from buf_pool.LRU. +/** Write out dirty blocks from buf_pool.LRU, +and move clean blocks to buf_pool.free. +The caller must invoke buf_dblwr.flush_buffered_writes() +after releasing buf_pool.mutex. @param max_n wished maximum mumber of blocks flushed -@return the number of processed pages +@param evict whether to evict pages after flushing +@return evict ? number of processed pages : number of pages written @retval 0 if a buf_pool.LRU batch is already running */ -ulint buf_flush_LRU(ulint max_n); +ulint buf_flush_LRU(ulint max_n, bool evict); /** Wait until a flush batch ends. @param lru true=buf_pool.LRU; false=buf_pool.flush_list */ @@ -119,9 +123,6 @@ buf_flush_note_modification( /** Initialize page_cleaner. */ ATTRIBUTE_COLD void buf_flush_page_cleaner_init(); -/** Wait for pending flushes to complete. */ -void buf_flush_wait_batch_end_acquiring_mutex(bool lru); - /** Flush the buffer pool on shutdown. */ ATTRIBUTE_COLD void buf_flush_buffer_pool(); diff --git a/storage/innobase/include/ut0new.h b/storage/innobase/include/ut0new.h index 4c8d2cf7a61..01bf34dc856 100644 --- a/storage/innobase/include/ut0new.h +++ b/storage/innobase/include/ut0new.h @@ -843,6 +843,7 @@ constexpr const char* const auto_event_names[] = "buf0buf", "buf0dblwr", "buf0dump", + "buf0lru", "dict0dict", "dict0mem", "dict0stats", From 9a545eb67ca8a666b87fc0aa8d22fe0a01c4d9d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 16 Nov 2023 17:45:37 +0200 Subject: [PATCH 263/477] MDEV-26055: Correct the formula for adaptive flushing This is a 10.5 backport of 10.6 commit d4265fbde587bd79b6fe3793225d3f4798ee955e. page_cleaner_flush_pages_recommendation(): If dirty_pct is between innodb_max_dirty_pages_pct_lwm and innodb_max_dirty_pages_pct, scale the effort relative to how close we are to innodb_max_dirty_pages_pct. The previous formula was missing a multiplication by 100. --- storage/innobase/buf/buf0flu.cc | 54 +++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index f95af0819b4..77008312727 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -2120,10 +2120,12 @@ Based on various factors it decides if there is a need to do flushing. @return number of pages recommended to be flushed @param last_pages_in number of pages flushed in previous batch @param oldest_lsn buf_pool.get_oldest_modification(0) +@param pct_lwm innodb_max_dirty_pages_pct_lwm, or 0 to ignore it @param dirty_blocks UT_LIST_GET_LEN(buf_pool.flush_list) @param dirty_pct 100*flush_list.count / (LRU.count + free.count) */ static ulint page_cleaner_flush_pages_recommendation(ulint last_pages_in, lsn_t oldest_lsn, + double pct_lwm, ulint dirty_blocks, double dirty_pct) { @@ -2193,11 +2195,17 @@ func_exit: sum_pages = 0; } - const ulint pct_for_dirty = srv_max_dirty_pages_pct_lwm == 0 - ? (dirty_pct >= max_pct ? 100 : 0) - : static_cast - (max_pct > 0.0 ? dirty_pct / max_pct : dirty_pct); - ulint pct_total = std::max(pct_for_dirty, pct_for_lsn); + MONITOR_SET(MONITOR_FLUSH_PCT_FOR_LSN, pct_for_lsn); + + double total_ratio; + if (pct_lwm == 0.0 || max_pct == 0.0) { + total_ratio = 1; + } else { + total_ratio = std::max(double(pct_for_lsn) / 100, + (dirty_pct / max_pct)); + } + + MONITOR_SET(MONITOR_FLUSH_PCT_FOR_DIRTY, ulint(total_ratio * 100)); /* Estimate pages to be flushed for the lsn progress */ lsn_t target_lsn = oldest_lsn @@ -2223,7 +2231,7 @@ func_exit: pages_for_lsn = 1; } - n_pages = (ulint(double(srv_io_capacity) * double(pct_total) / 100.0) + n_pages = (ulint(double(srv_io_capacity) * total_ratio) + avg_page_rate + pages_for_lsn) / 3; if (n_pages > srv_max_io_capacity) { @@ -2236,8 +2244,6 @@ func_exit: MONITOR_SET(MONITOR_FLUSH_AVG_PAGE_RATE, avg_page_rate); MONITOR_SET(MONITOR_FLUSH_LSN_AVG_RATE, lsn_avg_rate); - MONITOR_SET(MONITOR_FLUSH_PCT_FOR_DIRTY, pct_for_dirty); - MONITOR_SET(MONITOR_FLUSH_PCT_FOR_LSN, pct_for_lsn); goto func_exit; } @@ -2349,15 +2355,17 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) const double dirty_pct= double(dirty_blocks) * 100.0 / double(UT_LIST_GET_LEN(buf_pool.LRU) + UT_LIST_GET_LEN(buf_pool.free)); - bool idle_flush= false; + double pct_lwm= 0.0; - if (lsn_limit || soft_lsn_limit); - else if (af_needed_for_redo(oldest_lsn)); - else if (srv_max_dirty_pages_pct_lwm != 0.0) + if (srv_max_dirty_pages_pct_lwm != 0.0) { + const double lwm= srv_max_dirty_pages_pct_lwm; const ulint activity_count= srv_get_activity_count(); if (activity_count != last_activity_count) + { last_activity_count= activity_count; + goto maybe_unemployed; + } else if (buf_pool.page_cleaner_idle() && buf_pool.n_pend_reads == 0) { /* reaching here means 3 things: @@ -2365,15 +2373,22 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) (no trx_t::commit activity) - page cleaner is idle (dirty_pct < srv_max_dirty_pages_pct_lwm) - there are no pending reads but there are dirty pages to flush */ - idle_flush= true; buf_pool.update_last_activity_count(activity_count); + pct_lwm= lwm; + } + else + { + maybe_unemployed: + const bool below{dirty_pct < pct_lwm}; + pct_lwm= 0.0; + if (below) + goto possibly_unemployed; } - - if (!idle_flush && dirty_pct < srv_max_dirty_pages_pct_lwm) - goto unemployed; } else if (dirty_pct < srv_max_buf_pool_modified_pct) - goto unemployed; + possibly_unemployed: + if (!lsn_limit && !soft_lsn_limit && !af_needed_for_redo(oldest_lsn)) + goto set_idle; if (UNIV_UNLIKELY(lsn_limit != 0) && oldest_lsn >= lsn_limit) lsn_limit= buf_flush_sync_lsn= 0; @@ -2393,7 +2408,7 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) n= srv_max_io_capacity; goto background_flush; } - else if (idle_flush || !srv_adaptive_flushing) + else if (pct_lwm != 0.0 || !srv_adaptive_flushing) { n= srv_io_capacity; lsn_limit= LSN_MAX; @@ -2409,6 +2424,7 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) } else if ((n= page_cleaner_flush_pages_recommendation(last_pages, oldest_lsn, + pct_lwm, dirty_blocks, dirty_pct)) != 0) { @@ -2431,7 +2447,7 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) mysql_mutex_unlock(&buf_pool.mutex); last_pages+= n; - if (!idle_flush) + if (pct_lwm == 0.0) goto end_of_batch; /* when idle flushing kicks in page_cleaner is marked active. From 8c1dcb2579e778807ce488a2c19f6566a5a57b16 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 4 Oct 2023 10:36:06 +1100 Subject: [PATCH 264/477] MDEV-26247 Remove some unused spider methods Two methods from spider_fields. There are probably more of these conn_holder related methods that can be removed reappend_tables_part() reappend_tables() --- storage/spider/spd_db_include.h | 11 ----- storage/spider/spd_db_mysql.cc | 64 -------------------------- storage/spider/spd_db_mysql.h | 9 ---- storage/spider/spd_group_by_handler.cc | 18 -------- 4 files changed, 102 deletions(-) diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index 74b1a186355..0dd30fc35bb 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -689,8 +689,6 @@ public: long access_balance ); SPIDER_CONN_HOLDER *create_conn_holder(); - void set_pos_to_first_conn_holder(); - SPIDER_CONN_HOLDER *get_next_conn_holder(); bool has_conn_holder(); void clear_conn_holder_from_conn(); bool check_conn_same_conn( @@ -923,11 +921,6 @@ public: TABLE_LIST *table_list, uint table_count ) = 0; - virtual int reappend_tables( - spider_fields *fields, - SPIDER_LINK_IDX_CHAIN *link_idx_chain, - spider_string *str - ) = 0; virtual int append_where( spider_string *str ) = 0; @@ -1754,10 +1747,6 @@ public: spider_fields *fields, ulong sql_type ) = 0; - virtual int reappend_tables_part( - spider_fields *fields, - ulong sql_type - ) = 0; virtual int append_where_part( ulong sql_type ) = 0; diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index eb85c80e525..c859f37a809 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -7320,45 +7320,6 @@ int spider_db_mbase_util::append_from_and_tables( DBUG_RETURN(0); } -int spider_db_mbase_util::reappend_tables( - spider_fields *fields, - SPIDER_LINK_IDX_CHAIN *link_idx_chain, - spider_string *str -) { - int error_num; - uint32 length; - ha_spider *spider; - spider_mbase_share *db_share; - spider_mbase_handler *dbton_hdl; - SPIDER_TABLE_HOLDER *table_holder; - SPIDER_LINK_IDX_HOLDER *link_idx_holder; - DBUG_ENTER("spider_db_mbase_util::reappend_tables"); - DBUG_PRINT("info",("spider this=%p", this)); - length = str->length(); - fields->set_pos_to_first_table_on_link_idx_chain(link_idx_chain); - fields->set_pos_to_first_table_holder(); - while ((table_holder = fields->get_next_table_holder())) - { - link_idx_holder = - fields->get_next_table_on_link_idx_chain(link_idx_chain); - spider = table_holder->spider; - db_share = (spider_mbase_share *) - spider->share->dbton_share[dbton_id]; - if (!db_share->same_db_table_name) - { - dbton_hdl = (spider_mbase_handler *) spider->dbton_handler[dbton_id]; - str->length(dbton_hdl->table_name_pos); - if ((error_num = db_share->append_table_name_with_adjusting(str, - spider->conn_link_idx[link_idx_holder->link_idx]))) - { - DBUG_RETURN(error_num); - } - } - } - str->length(length); - DBUG_RETURN(0); -} - int spider_db_mbase_util::append_where( spider_string *str ) { @@ -13544,14 +13505,10 @@ int spider_mbase_handler::set_sql_for_exec( int link_idx, SPIDER_LINK_IDX_CHAIN *link_idx_chain ) { - int error_num; DBUG_ENTER("spider_mbase_handler::set_sql_for_exec"); DBUG_PRINT("info",("spider this=%p", this)); if (sql_type & SPIDER_SQL_TYPE_SELECT_SQL) { - if ((error_num = spider_db_mbase_utility->reappend_tables( - spider->fields, link_idx_chain, &sql))) - DBUG_RETURN(error_num); exec_sql = &sql; } DBUG_RETURN(0); @@ -15691,27 +15648,6 @@ int spider_mbase_handler::append_from_and_tables_part( DBUG_RETURN(error_num); } -int spider_mbase_handler::reappend_tables_part( - spider_fields *fields, - ulong sql_type -) { - int error_num; - spider_string *str; - DBUG_ENTER("spider_mbase_handler::reappend_tables_part"); - DBUG_PRINT("info",("spider this=%p", this)); - switch (sql_type) - { - case SPIDER_SQL_TYPE_SELECT_SQL: - str = &sql; - break; - default: - DBUG_RETURN(0); - } - error_num = spider_db_mbase_utility->reappend_tables(fields, - link_idx_chain, str); - DBUG_RETURN(error_num); -} - int spider_mbase_handler::append_where_part( ulong sql_type ) { diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h index 7305aec5d82..876d9e72aa1 100644 --- a/storage/spider/spd_db_mysql.h +++ b/storage/spider/spd_db_mysql.h @@ -198,11 +198,6 @@ public: TABLE_LIST *table_list, uint table_count ) override; - int reappend_tables( - spider_fields *fields, - SPIDER_LINK_IDX_CHAIN *link_idx_chain, - spider_string *str - ) override; int append_where( spider_string *str ) override; @@ -1608,10 +1603,6 @@ public: spider_fields *fields, ulong sql_type ); - int reappend_tables_part( - spider_fields *fields, - ulong sql_type - ); int append_where_part( ulong sql_type ); diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index dd39c5e48d4..0b06661d98f 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -650,24 +650,6 @@ SPIDER_CONN_HOLDER *spider_fields::create_conn_holder( DBUG_RETURN(return_conn_holder); } -void spider_fields::set_pos_to_first_conn_holder( -) { - DBUG_ENTER("spider_fields::set_pos_to_first_conn_holder"); - DBUG_PRINT("info",("spider this=%p", this)); - current_conn_holder = first_conn_holder; - DBUG_VOID_RETURN; -} - -SPIDER_CONN_HOLDER *spider_fields::get_next_conn_holder( -) { - SPIDER_CONN_HOLDER *return_conn_holder = current_conn_holder; - DBUG_ENTER("spider_fields::get_next_conn_holder"); - DBUG_PRINT("info",("spider this=%p", this)); - if (current_conn_holder) - current_conn_holder = current_conn_holder->next; - DBUG_RETURN(return_conn_holder); -} - bool spider_fields::has_conn_holder( ) { DBUG_ENTER("spider_fields::has_conn_holder"); From 2d1e09a77f004df4a14b3770fd45d9bc22c1260d Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 13 Oct 2023 14:54:45 +1100 Subject: [PATCH 265/477] MDEV-26247 Clean up spider_fields Spider gbh query rewrite should get table for fields in a simple way. Add a method spider_fields::find_table that searches its table holders to find table for a given field. This way we will be able to get rid of the first pass during the gbh creation where field_chains and field_holders are created. We also check that the field belongs to a spider table while walking through the query, so we could remove all_query_fields_are_query_table_members(). However, this requires an earlier creation of the table_holder so that tables are added before checking. We do that, and in doing so, also decouple table_holder and spider_fields Remove unused methods and fields. Add comments. --- storage/spider/spd_db_conn.cc | 40 +-- storage/spider/spd_db_include.h | 47 +--- storage/spider/spd_db_mysql.cc | 3 +- storage/spider/spd_db_mysql.h | 3 + storage/spider/spd_group_by_handler.cc | 361 ++++++------------------- 5 files changed, 115 insertions(+), 339 deletions(-) diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index cc8637ca488..69825b696a9 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -9167,19 +9167,20 @@ int spider_db_open_item_ident( } else { if (str) { - SPIDER_FIELD_CHAIN *field_chain = fields->get_next_field_chain(); - SPIDER_FIELD_HOLDER *field_holder = field_chain->field_holder; - spider = field_holder->spider; + SPIDER_TABLE_HOLDER *table= fields->find_table(field); + /* If table or table->spider is NULL the GBH creation + would have been skipped the first pass (see below). */ + spider = table->spider; share = spider->share; if ((error_num = share->dbton_share[dbton_id]-> append_column_name_with_alias(str, field->field_index, - field_holder->alias->ptr(), field_holder->alias->length()))) + table->alias->ptr(), table->alias->length()))) DBUG_RETURN(error_num); - } else { - if ((error_num = fields->add_field(field))) - { - DBUG_RETURN(error_num); - } + } else + { + SPIDER_TABLE_HOLDER *table= fields->find_table(field); + if (!table || !table->spider) + DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); } } } @@ -9298,21 +9299,20 @@ int spider_db_open_item_field( } else { if (str) { - SPIDER_FIELD_CHAIN *field_chain = fields->get_next_field_chain(); - SPIDER_FIELD_HOLDER *field_holder = field_chain->field_holder; - spider = field_holder->spider; + SPIDER_TABLE_HOLDER *table= fields->find_table(field); + /* If table or table->spider is NULL the GBH creation + would have been skipped the first pass (see below). */ + spider = table->spider; share = spider->share; - field = spider->field_exchange(field); - DBUG_ASSERT(field); if ((error_num = share->dbton_share[dbton_id]-> append_column_name_with_alias(str, field->field_index, - field_holder->alias->ptr(), field_holder->alias->length()))) + table->alias->ptr(), table->alias->length()))) DBUG_RETURN(error_num); - } else { - if ((error_num = fields->add_field(field))) - { - DBUG_RETURN(error_num); - } + } else + { + SPIDER_TABLE_HOLDER *table= fields->find_table(field); + if (!table || !table->spider) + DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); } DBUG_RETURN(0); } diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index 0dd30fc35bb..ee6202bf334 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -604,34 +604,26 @@ typedef struct spider_conn_holder spider_conn_holder *next; } SPIDER_CONN_HOLDER; +/* Record information of a local (spider) table, for use of the spider +group by handler. */ typedef struct spider_table_holder { TABLE *table; ha_spider *spider; + /* alias of the table, in the form of tk, where k is the index of + the table from `query->from' indexed by next_local. */ spider_string *alias; } SPIDER_TABLE_HOLDER; -typedef struct spider_field_holder -{ - Field *field; - ha_spider *spider; - spider_string *alias; - spider_field_holder *next; -} SPIDER_FIELD_HOLDER; - -typedef struct spider_field_chain -{ - spider_field_holder *field_holder; - spider_field_chain *next; -} SPIDER_FIELD_CHAIN; - +/* For use of the spider group by handler. */ class spider_fields { uint dbton_count; uint current_dbton_num; uint dbton_ids[SPIDER_DBTON_SIZE]; + /* Number of tables in `query->from'. */ uint table_count; - uint current_table_num; + /* All tables in `query->from', in the same order by next_local. */ SPIDER_TABLE_HOLDER *table_holder; SPIDER_LINK_IDX_CHAIN *first_link_idx_chain; SPIDER_LINK_IDX_CHAIN *last_link_idx_chain; @@ -640,13 +632,6 @@ class spider_fields SPIDER_CONN_HOLDER *first_conn_holder; SPIDER_CONN_HOLDER *last_conn_holder; SPIDER_CONN_HOLDER *current_conn_holder; - SPIDER_FIELD_HOLDER *first_field_holder; - SPIDER_FIELD_HOLDER *last_field_holder; - SPIDER_FIELD_HOLDER *current_field_holder; - SPIDER_FIELD_CHAIN *first_field_chain; - SPIDER_FIELD_CHAIN *last_field_chain; - SPIDER_FIELD_CHAIN *current_field_chain; - Field **first_field_ptr; Field **current_field_ptr; public: spider_fields(); @@ -702,24 +687,14 @@ public: void free_conn_holder( SPIDER_CONN_HOLDER *conn_holder_arg ); - SPIDER_TABLE_HOLDER *add_table( - ha_spider *spider_arg - ); - bool all_query_fields_are_query_table_members(); - int create_table_holder( + SPIDER_TABLE_HOLDER *find_table(Field *field); + void set_table_holder( + SPIDER_TABLE_HOLDER *table_holder_arg, uint table_count_arg ); - void set_pos_to_first_table_holder(); - SPIDER_TABLE_HOLDER *get_next_table_holder(); + SPIDER_TABLE_HOLDER *get_first_table_holder(); SPIDER_TABLE_HOLDER *get_table_holder(TABLE *table); uint get_table_count(); - int add_field(Field *field_arg); - SPIDER_FIELD_HOLDER *create_field_holder(); - void set_pos_to_first_field_holder(); - SPIDER_FIELD_HOLDER *get_next_field_holder(); - SPIDER_FIELD_CHAIN *create_field_chain(); - void set_pos_to_first_field_chain(); - SPIDER_FIELD_CHAIN *get_next_field_chain(); void set_field_ptr(Field **field_arg); Field **get_next_field_ptr(); int ping_table_mon_from_table( diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index c859f37a809..cbdde148787 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -15639,8 +15639,7 @@ int spider_mbase_handler::append_from_and_tables_part( default: DBUG_RETURN(0); } - fields->set_pos_to_first_table_holder(); - table_holder = fields->get_next_table_holder(); + table_holder = fields->get_first_table_holder(); table_list = table_holder->table->pos_in_table_list; error_num = spider_db_mbase_utility->append_from_and_tables( table_holder->spider, fields, str, diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h index 876d9e72aa1..acb87d632d1 100644 --- a/storage/spider/spd_db_mysql.h +++ b/storage/spider/spd_db_mysql.h @@ -676,8 +676,11 @@ public: spider_string *show_table_status; spider_string *show_records; spider_string *show_index; + /* The remote table names */ spider_string *table_names_str; + /* The remote db names */ spider_string *db_names_str; + /* fixme: this field looks useless */ spider_string *db_table_str; #ifdef SPIDER_HAS_HASH_VALUE_TYPE my_hash_value_type *db_table_str_hash_value; diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index 0b06661d98f..fbccbea34ee 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -46,11 +46,9 @@ extern SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE]; spider_fields::spider_fields() : dbton_count(0), current_dbton_num(0), - table_count(0), current_table_num(0), table_holder(NULL), + table_count(0), table_holder(NULL), first_link_idx_chain(NULL), last_link_idx_chain(NULL), current_link_idx_chain(NULL), - first_conn_holder(NULL), last_conn_holder(NULL), current_conn_holder(NULL), - first_field_holder(NULL), last_field_holder(NULL), current_field_holder(NULL), - first_field_chain(NULL), last_field_chain(NULL), current_field_chain(NULL) + first_conn_holder(NULL), last_conn_holder(NULL), current_conn_holder(NULL) { DBUG_ENTER("spider_fields::spider_fields"); DBUG_PRINT("info",("spider this=%p", this)); @@ -69,24 +67,6 @@ spider_fields::~spider_fields() spider_free(spider_current_trx, current_link_idx_chain, MYF(0)); } } - if (first_field_chain) - { - while ((current_field_chain = first_field_chain)) - { - first_field_chain = current_field_chain->next; - spider_free(spider_current_trx, current_field_chain, MYF(0)); - } - } - if (first_field_holder) - { - while ((current_field_holder = first_field_holder)) - { - first_field_holder = current_field_holder->next; - spider_free(spider_current_trx, current_field_holder, MYF(0)); - } - } - if (table_holder) - spider_free(spider_current_trx, table_holder, MYF(0)); if (first_conn_holder) { while ((current_conn_holder = first_conn_holder)) @@ -475,7 +455,6 @@ int spider_fields::get_ok_link_idx( void spider_fields::set_first_link_idx( ) { - SPIDER_TABLE_HOLDER *table_holder; SPIDER_LINK_IDX_HOLDER *link_idx_holder; SPIDER_LINK_IDX_CHAIN *link_idx_chain; uint dbton_id; @@ -497,11 +476,10 @@ void spider_fields::set_first_link_idx( DBUG_ASSERT(link_idx_chain); set_pos_to_first_table_on_link_idx_chain(link_idx_chain); - set_pos_to_first_table_holder(); - while ((table_holder = get_next_table_holder())) + for (uint i= 0; i < table_count; i++) { link_idx_holder = get_next_table_on_link_idx_chain(link_idx_chain); - spider = table_holder->spider; + spider = table_holder[i].spider; dbton_hdl = spider->dbton_handler[dbton_id]; dbton_hdl->first_link_idx = link_idx_holder->link_idx; } @@ -848,19 +826,17 @@ void spider_fields::free_conn_holder( DBUG_VOID_RETURN; } -SPIDER_TABLE_HOLDER *spider_fields::add_table( - ha_spider *spider_arg +/* Add the table associated with an ha_spider to a table_holder. +Return the table_holder. */ +static SPIDER_TABLE_HOLDER *spider_add_table_holder( + ha_spider *spider_arg, + SPIDER_TABLE_HOLDER *table_holder ) { spider_string *str; uint length; char tmp_buf[SPIDER_SQL_INT_LEN + 2]; SPIDER_TABLE_HOLDER *return_table_holder; - SPIDER_FIELD_HOLDER *field_holder; - TABLE *table = spider_arg->get_table(); - Field *field; DBUG_ENTER("spider_fields::add_table"); - DBUG_PRINT("info",("spider this=%p", this)); - DBUG_PRINT("info",("spider table_count=%u", table_count)); DBUG_PRINT("info",("spider idx_for_direct_join=%u", spider_arg->idx_for_direct_join)); length = my_sprintf(tmp_buf, (tmp_buf, "t%u", @@ -879,90 +855,49 @@ SPIDER_TABLE_HOLDER *spider_fields::add_table( return_table_holder->spider = spider_arg; return_table_holder->alias = str; - set_pos_to_first_field_holder(); - while ((field_holder = get_next_field_holder())) - { - if (!field_holder->spider) - { - field = field_holder->field; - if ( - field->field_index < table->s->fields && - field == table->field[field->field_index] - ) { - field_holder->spider = spider_arg; - field_holder->alias = str; - } - } - } DBUG_RETURN(return_table_holder); } -/** - Verify that all fields in the query are members of tables that are in the - query. - - @return TRUE All fields in the query are members of tables - that are in the query. - FALSE At least one field in the query is not a - member of a table that is in the query. -*/ - -bool spider_fields::all_query_fields_are_query_table_members() +/* Return the table that field belongs to, or NULL if none exists. */ +SPIDER_TABLE_HOLDER *spider_fields::find_table(Field *field) { - SPIDER_FIELD_HOLDER *field_holder; - DBUG_ENTER("spider_fields::all_query_fields_are_query_table_members"); - DBUG_PRINT("info",("spider this=%p", this)); - - set_pos_to_first_field_holder(); - while ((field_holder = get_next_field_holder())) - { - if (!field_holder->spider) - { - DBUG_PRINT("info", ("spider field is not a member of a query table")); - DBUG_RETURN(FALSE); - } - } - - DBUG_RETURN(TRUE); + for (uint i = 0; i < table_count; i++) + if (field->table == table_holder[i].table) + return &table_holder[i]; + return NULL; } -int spider_fields::create_table_holder( +void spider_fields::set_table_holder(SPIDER_TABLE_HOLDER *table_holder_arg, + uint table_count_arg) +{ + table_holder= table_holder_arg; + table_count= table_count_arg; +} + +/* Allocate space for table_count_arg table holders. */ +static SPIDER_TABLE_HOLDER *spider_create_table_holder( uint table_count_arg ) { - DBUG_ENTER("spider_fields::create_table_holder"); - DBUG_PRINT("info",("spider this=%p", this)); - DBUG_ASSERT(!table_holder); + SPIDER_TABLE_HOLDER* table_holder; + DBUG_ENTER("spider_create_table_holder"); + if (table_count_arg == 0) + DBUG_RETURN(0); table_holder = (SPIDER_TABLE_HOLDER *) spider_malloc(spider_current_trx, 249, table_count_arg * sizeof(SPIDER_TABLE_HOLDER), MYF(MY_WME | MY_ZEROFILL)); - if (!table_holder) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - table_count = table_count_arg; - current_table_num = 0; - DBUG_RETURN(0); + DBUG_RETURN(table_holder); } -void spider_fields::set_pos_to_first_table_holder( -) { - DBUG_ENTER("spider_fields::set_pos_to_first_table_holder"); - DBUG_PRINT("info",("spider this=%p", this)); - current_table_num = 0; - DBUG_VOID_RETURN; -} - -SPIDER_TABLE_HOLDER *spider_fields::get_next_table_holder( -) { - SPIDER_TABLE_HOLDER *return_table_holder; - DBUG_ENTER("spider_fields::get_next_table_holder"); - DBUG_PRINT("info",("spider this=%p", this)); - if (current_table_num >= table_count) - DBUG_RETURN(NULL); - return_table_holder = &table_holder[current_table_num]; - ++current_table_num; - DBUG_RETURN(return_table_holder); +/* Return pointer to the first table holder. */ +SPIDER_TABLE_HOLDER *spider_fields::get_first_table_holder() +{ + DBUG_ENTER("spider_fields::get_first_spider"); + DBUG_RETURN(table_holder); } +/* Return the first table holder associated with a given table, or +NULL if not found. */ SPIDER_TABLE_HOLDER *spider_fields::get_table_holder(TABLE *table) { uint table_num; @@ -982,117 +917,12 @@ uint spider_fields::get_table_count() DBUG_RETURN(table_count); } -int spider_fields::add_field( - Field *field_arg -) { - SPIDER_FIELD_HOLDER *field_holder; - SPIDER_FIELD_CHAIN *field_chain; - DBUG_ENTER("spider_fields::add_field"); - DBUG_PRINT("info",("spider this=%p", this)); - DBUG_PRINT("info",("spider field=%p", field_arg)); - if (!first_field_holder) - { - field_holder = create_field_holder(); - DBUG_PRINT("info",("spider field_holder=%p", field_holder)); - if (!field_holder) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - field_holder->field = field_arg; - first_field_holder = field_holder; - last_field_holder = field_holder; - } else { - field_holder = first_field_holder; - do { - if (field_holder->field == field_arg) - break; - } while ((field_holder = field_holder->next)); - if (!field_holder) - { - field_holder = create_field_holder(); - DBUG_PRINT("info",("spider field_holder=%p", field_holder)); - if (!field_holder) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - field_holder->field = field_arg; - last_field_holder->next = field_holder; - last_field_holder = field_holder; - } - } - field_chain = create_field_chain(); - DBUG_PRINT("info",("spider field_chain=%p", field_chain)); - if (!field_chain) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - field_chain->field_holder = field_holder; - if (!first_field_chain) - { - first_field_chain = field_chain; - last_field_chain = field_chain; - } else { - last_field_chain->next = field_chain; - last_field_chain = field_chain; - } - DBUG_RETURN(0); -} - -SPIDER_FIELD_HOLDER *spider_fields::create_field_holder( -) { - DBUG_ENTER("spider_fields::create_field_holder"); - DBUG_PRINT("info",("spider this=%p", this)); - DBUG_RETURN((SPIDER_FIELD_HOLDER *) - spider_malloc(spider_current_trx, 250, sizeof(SPIDER_FIELD_HOLDER), - MYF(MY_WME | MY_ZEROFILL))); -} - -void spider_fields::set_pos_to_first_field_holder( -) { - DBUG_ENTER("spider_fields::set_pos_to_first_field_holder"); - DBUG_PRINT("info",("spider this=%p", this)); - current_field_holder = first_field_holder; - DBUG_VOID_RETURN; -} - -SPIDER_FIELD_HOLDER *spider_fields::get_next_field_holder( -) { - SPIDER_FIELD_HOLDER *return_field_holder = current_field_holder; - DBUG_ENTER("spider_fields::get_next_field_holder"); - DBUG_PRINT("info",("spider this=%p", this)); - if (current_field_holder) - current_field_holder = current_field_holder->next; - DBUG_RETURN(return_field_holder); -} - -SPIDER_FIELD_CHAIN *spider_fields::create_field_chain( -) { - DBUG_ENTER("spider_fields::create_field_chain"); - DBUG_PRINT("info",("spider this=%p", this)); - DBUG_RETURN((SPIDER_FIELD_CHAIN *) - spider_malloc(spider_current_trx, 251, sizeof(SPIDER_FIELD_CHAIN), - MYF(MY_WME | MY_ZEROFILL))); -} - -void spider_fields::set_pos_to_first_field_chain( -) { - DBUG_ENTER("spider_fields::set_pos_to_first_field_chain"); - DBUG_PRINT("info",("spider this=%p", this)); - current_field_chain = first_field_chain; - DBUG_VOID_RETURN; -} - -SPIDER_FIELD_CHAIN *spider_fields::get_next_field_chain( -) { - SPIDER_FIELD_CHAIN *return_field_chain = current_field_chain; - DBUG_ENTER("spider_fields::get_next_field_chain"); - DBUG_PRINT("info",("spider this=%p", this)); - if (current_field_chain) - current_field_chain = current_field_chain->next; - DBUG_RETURN(return_field_chain); -} - void spider_fields::set_field_ptr( Field **field_arg ) { DBUG_ENTER("spider_fields::set_field_ptr"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider field_ptr=%p", field_arg)); - first_field_ptr = field_arg; current_field_ptr = field_arg; DBUG_VOID_RETURN; } @@ -1115,15 +945,13 @@ int spider_fields::ping_table_mon_from_table( ha_spider *tmp_spider; SPIDER_SHARE *tmp_share; int tmp_link_idx; - SPIDER_TABLE_HOLDER *table_holder; SPIDER_LINK_IDX_HOLDER *link_idx_holder; DBUG_ENTER("spider_fields::ping_table_mon_from_table"); set_pos_to_first_table_on_link_idx_chain(link_idx_chain); - set_pos_to_first_table_holder(); - while ((table_holder = get_next_table_holder())) + for (uint i= 0; i < table_count; i++) { link_idx_holder = get_next_table_on_link_idx_chain(link_idx_chain); - tmp_spider = table_holder->spider; + tmp_spider = table_holder[i].spider; tmp_link_idx = link_idx_holder->link_idx; tmp_share = tmp_spider->share; if (tmp_share->monitoring_kind[tmp_link_idx]) @@ -1160,9 +988,7 @@ spider_group_by_handler::spider_group_by_handler( query(*query_arg), fields(fields_arg) { DBUG_ENTER("spider_group_by_handler::spider_group_by_handler"); - fields->set_pos_to_first_table_holder(); - SPIDER_TABLE_HOLDER *table_holder = fields->get_next_table_holder(); - spider = table_holder->spider; + spider = fields->get_first_table_holder()->spider; trx = spider->trx; DBUG_VOID_RETURN; } @@ -1170,6 +996,7 @@ spider_group_by_handler::spider_group_by_handler( spider_group_by_handler::~spider_group_by_handler() { DBUG_ENTER("spider_group_by_handler::~spider_group_by_handler"); + spider_free(spider_current_trx, fields->get_first_table_holder(), MYF(0)); delete fields; DBUG_VOID_RETURN; } @@ -1286,7 +1113,6 @@ int spider_group_by_handler::init_scan() { dbton_hdl = spider->dbton_handler[dbton_id]; result_list->direct_distinct = query.distinct; - fields->set_pos_to_first_field_chain(); if ((error_num = dbton_hdl->reset_sql(SPIDER_SQL_TYPE_SELECT_SQL))) { DBUG_RETURN(error_num); @@ -1596,7 +1422,8 @@ group_by_handler *spider_create_group_by_handler( bool keep_going; bool find_dbton = FALSE; spider_fields *fields = NULL, *fields_arg = NULL; - uint table_idx, dbton_id; + SPIDER_TABLE_HOLDER *table_holder; + uint table_idx, dbton_id, table_count= 0; long tgt_link_status; DBUG_ENTER("spider_create_group_by_handler"); @@ -1618,6 +1445,7 @@ group_by_handler *spider_create_group_by_handler( DBUG_PRINT("info",("spider from=%p", from)); if (from->table->const_table) continue; + ++table_count; if (from->table->part_info) { DBUG_PRINT("info",("spider partition handler")); @@ -1639,6 +1467,9 @@ group_by_handler *spider_create_group_by_handler( } while ((from = from->next_local)); #endif + if (!(table_holder= spider_create_table_holder(table_count))) + DBUG_RETURN(NULL); + table_idx = 0; from = query->from; while (from && from->table->const_table) @@ -1648,7 +1479,7 @@ group_by_handler *spider_create_group_by_handler( if (!from) { /* all tables are const_table */ - DBUG_RETURN(NULL); + goto skip_free_table_holder; } #if defined(PARTITION_HAS_GET_CHILD_HANDLERS) if (from->table->part_info) @@ -1667,6 +1498,11 @@ group_by_handler *spider_create_group_by_handler( share = spider->share; spider->idx_for_direct_join = table_idx; ++table_idx; + if (!spider_add_table_holder(spider, table_holder)) + { + DBUG_PRINT("info",("spider can not add a table")); + goto skip_free_table_holder; + } memset(dbton_bitmap, 0, spider_bitmap_size(SPIDER_DBTON_SIZE)); for (roop_count = 0; roop_count < (int) share->use_dbton_count; ++roop_count) { @@ -1699,6 +1535,11 @@ group_by_handler *spider_create_group_by_handler( share = spider->share; spider->idx_for_direct_join = table_idx; ++table_idx; + if (!spider_add_table_holder(spider, table_holder)) + { + DBUG_PRINT("info",("spider can not add a table")); + goto skip_free_table_holder; + } memset(dbton_bitmap_tmp, 0, spider_bitmap_size(SPIDER_DBTON_SIZE)); for (roop_count = 0; roop_count < (int) share->use_dbton_count; ++roop_count) { @@ -1752,10 +1593,9 @@ group_by_handler *spider_create_group_by_handler( { fields_arg = new spider_fields(); if (!fields_arg) - { - DBUG_RETURN(NULL); - } + goto skip_free_table_holder; } + fields_arg->set_table_holder(table_holder, table_count); keep_going = TRUE; it.init(*query->select); while ((item = it++)) @@ -1862,15 +1702,7 @@ group_by_handler *spider_create_group_by_handler( } } if (!find_dbton) - { - DBUG_RETURN(NULL); - } - - if (fields->create_table_holder(table_idx)) - { - delete fields; - DBUG_RETURN(NULL); - } + goto skip_free_table_holder; from = query->from; while (from->table->const_table) @@ -1901,12 +1733,6 @@ group_by_handler *spider_create_group_by_handler( } DBUG_PRINT("info",("spider s->db=%s", from->table->s->db.str)); DBUG_PRINT("info",("spider s->table_name=%s", from->table->s->table_name.str)); - if (!fields->add_table(spider)) - { - DBUG_PRINT("info",("spider can not add a table")); - delete fields; - DBUG_RETURN(NULL); - } for ( roop_count = spider_conn_link_idx_next(share->link_statuses, spider->conn_link_idx, -1, share->link_count, @@ -1920,10 +1746,7 @@ group_by_handler *spider_create_group_by_handler( { DBUG_PRINT("info",("spider direct_join does not support use_handler")); if (lock_mode) - { - delete fields; - DBUG_RETURN(NULL); - } + goto skip_free_fields; continue; } conn = spider->conns[roop_count]; @@ -1935,8 +1758,7 @@ group_by_handler *spider_create_group_by_handler( DBUG_PRINT("info",("spider direct_join does not support with lock tables yet")); if (lock_mode) { - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } continue; } @@ -1944,20 +1766,17 @@ group_by_handler *spider_create_group_by_handler( share->access_balances[spider->conn_link_idx[roop_count]])) { DBUG_PRINT("info",("spider can not create conn_holder")); - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } if (fields->add_link_idx(conn->conn_holder_for_direct_join, spider, roop_count)) { DBUG_PRINT("info",("spider can not create link_idx_holder")); - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } } if (!fields->has_conn_holder()) { - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } while ((from = from->next_local)) @@ -1981,12 +1800,6 @@ group_by_handler *spider_create_group_by_handler( } #endif share = spider->share; - if (!fields->add_table(spider)) - { - DBUG_PRINT("info",("spider can not add a table")); - delete fields; - DBUG_RETURN(NULL); - } DBUG_PRINT("info",("spider s->db=%s", from->table->s->db.str)); DBUG_PRINT("info",("spider s->table_name=%s", from->table->s->table_name.str)); for ( @@ -2003,10 +1816,7 @@ group_by_handler *spider_create_group_by_handler( { DBUG_PRINT("info",("spider direct_join does not support use_handler")); if (lock_mode) - { - delete fields; - DBUG_RETURN(NULL); - } + goto skip_free_fields; continue; } conn = spider->conns[roop_count]; @@ -2016,17 +1826,13 @@ group_by_handler *spider_create_group_by_handler( DBUG_PRINT("info",("spider connection %p can not be used for this query with locking", conn)); if (lock_mode) - { - delete fields; - DBUG_RETURN(NULL); - } + goto skip_free_fields; continue; } if (fields->add_link_idx(conn->conn_holder_for_direct_join, spider, roop_count)) { DBUG_PRINT("info",("spider can not create link_idx_holder")); - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } } @@ -2035,30 +1841,20 @@ group_by_handler *spider_create_group_by_handler( if (lock_mode) { DBUG_PRINT("info",("spider some connections can not be used for this query with locking")); - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } } if (!fields->has_conn_holder()) { - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } } - if (!fields->all_query_fields_are_query_table_members()) - { - DBUG_PRINT("info", ("spider found a query field that is not a query table member")); - delete fields; - DBUG_RETURN(NULL); - } - fields->check_support_dbton(dbton_bitmap); if (!fields->has_conn_holder()) { DBUG_PRINT("info",("spider all chosen connections can't match dbton_id")); - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } /* choose a connection */ @@ -2070,16 +1866,14 @@ group_by_handler *spider_create_group_by_handler( if (fields->make_link_idx_chain(tgt_link_status)) { DBUG_PRINT("info",("spider can not create link_idx_chain")); - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } /* choose link_id */ if (fields->check_link_ok_chain()) { DBUG_PRINT("info",("spider do not have link ok status")); - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } fields->set_first_link_idx(); @@ -2087,8 +1881,7 @@ group_by_handler *spider_create_group_by_handler( if (!(group_by_handler = new spider_group_by_handler(thd, query, fields))) { DBUG_PRINT("info",("spider can't create group_by_handler")); - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } query->distinct = FALSE; query->where = NULL; @@ -2096,5 +1889,11 @@ group_by_handler *spider_create_group_by_handler( query->having = NULL; query->order_by = NULL; DBUG_RETURN(group_by_handler); + +skip_free_fields: + delete fields; +skip_free_table_holder: + spider_free(spider_current_trx, table_holder, MYF(0)); + DBUG_RETURN(NULL); } #endif From 0bacef7617732279c895d46d8b03af2f941f9f0a Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 4 Oct 2023 18:35:30 +1100 Subject: [PATCH 266/477] MDEV-26247 clean up spider_group_by_handler::init_scan() --- storage/spider/spd_group_by_handler.cc | 188 ++++++++++++------------- 1 file changed, 92 insertions(+), 96 deletions(-) diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index fbccbea34ee..bd1aa1ea906 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -1001,38 +1001,16 @@ spider_group_by_handler::~spider_group_by_handler() DBUG_VOID_RETURN; } -int spider_group_by_handler::init_scan() +static int spider_prepare_init_scan( + const Query& query, spider_fields *fields, ha_spider *spider, + SPIDER_TRX *trx, longlong& offset_limit, THD *thd) { int error_num, link_idx; - uint dbton_id; - spider_db_handler *dbton_hdl; - st_select_lex *select_lex; - longlong select_limit; - longlong direct_order_limit; - SPIDER_SHARE *share = spider->share; - SPIDER_CONN *conn; SPIDER_RESULT_LIST *result_list = &spider->result_list; - SPIDER_LINK_IDX_CHAIN *link_idx_chain; - SPIDER_LINK_IDX_HOLDER *link_idx_holder; - DBUG_ENTER("spider_group_by_handler::init_scan"); - store_error = 0; -#ifndef DBUG_OFF - Field **field; - for ( - field = table->field; - *field; - field++ - ) { - DBUG_PRINT("info",("spider field_name=%s", - SPIDER_field_name_str(*field))); - } -#endif - - if (trx->thd->killed) - { - my_error(ER_QUERY_INTERRUPTED, MYF(0)); - DBUG_RETURN(ER_QUERY_INTERRUPTED); - } + st_select_lex *select_lex; + longlong select_limit, direct_order_limit; + SPIDER_SHARE *share = spider->share; + DBUG_ENTER("spider_prepare_init_scan"); spider->use_fields = TRUE; spider->fields = fields; @@ -1106,85 +1084,87 @@ int spider_group_by_handler::init_scan() } else { offset_limit = 0; } + DBUG_RETURN(0); +} + +static int spider_make_query(const Query& query, spider_fields* fields, ha_spider *spider, TABLE *table) +{ + uint dbton_id; + spider_db_handler* dbton_hdl; + SPIDER_RESULT_LIST *result_list = &spider->result_list; + int error_num; + DBUG_ENTER("spider_make_query"); - /* making a query */ fields->set_pos_to_first_dbton_id(); while ((dbton_id = fields->get_next_dbton_id()) < SPIDER_DBTON_SIZE) { dbton_hdl = spider->dbton_handler[dbton_id]; result_list->direct_distinct = query.distinct; if ((error_num = dbton_hdl->reset_sql(SPIDER_SQL_TYPE_SELECT_SQL))) - { DBUG_RETURN(error_num); - } if ((error_num = dbton_hdl->append_select_part(SPIDER_SQL_TYPE_SELECT_SQL))) - { DBUG_RETURN(error_num); - } fields->set_field_ptr(table->field); if ((error_num = dbton_hdl->append_list_item_select_part( - query.select, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL))) - { + query.select, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL))) DBUG_RETURN(error_num); - } if ((error_num = dbton_hdl->append_from_and_tables_part( - fields, SPIDER_SQL_TYPE_SELECT_SQL))) - { + fields, SPIDER_SQL_TYPE_SELECT_SQL))) DBUG_RETURN(error_num); - } if (query.where) { if ((error_num = - dbton_hdl->append_where_part(SPIDER_SQL_TYPE_SELECT_SQL))) - { + dbton_hdl->append_where_part(SPIDER_SQL_TYPE_SELECT_SQL))) DBUG_RETURN(error_num); - } if ((error_num = dbton_hdl->append_item_type_part( - query.where, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL))) - { + query.where, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL))) DBUG_RETURN(error_num); - } } if (query.group_by) { if ((error_num = dbton_hdl->append_group_by_part( - query.group_by, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL))) - { + query.group_by, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL))) DBUG_RETURN(error_num); - } } if (query.having) { if ((error_num = - dbton_hdl->append_having_part(SPIDER_SQL_TYPE_SELECT_SQL))) - { + dbton_hdl->append_having_part(SPIDER_SQL_TYPE_SELECT_SQL))) DBUG_RETURN(error_num); - } if ((error_num = dbton_hdl->append_item_type_part( - query.having, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL))) - { + query.having, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL))) DBUG_RETURN(error_num); - } } if (query.order_by) { if ((error_num = dbton_hdl->append_order_by_part( - query.order_by, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL))) - { + query.order_by, NULL, 0, TRUE, fields, + SPIDER_SQL_TYPE_SELECT_SQL))) DBUG_RETURN(error_num); - } } - if ((error_num = dbton_hdl->append_limit_part(result_list->internal_offset, - result_list->limit_num, SPIDER_SQL_TYPE_SELECT_SQL))) - { + if ((error_num = dbton_hdl->append_limit_part( + result_list->internal_offset, result_list->limit_num, + SPIDER_SQL_TYPE_SELECT_SQL))) DBUG_RETURN(error_num); - } if ((error_num = dbton_hdl->append_select_lock_part( - SPIDER_SQL_TYPE_SELECT_SQL))) - { + SPIDER_SQL_TYPE_SELECT_SQL))) DBUG_RETURN(error_num); - } } + DBUG_RETURN(0); +} + +static int spider_send_query( + spider_fields *fields, ha_spider *spider, SPIDER_TRX *trx, TABLE *table, + int& store_error) +{ + int error_num, link_idx; + spider_db_handler *dbton_hdl; + SPIDER_RESULT_LIST *result_list = &spider->result_list; + SPIDER_SHARE *share = spider->share; + SPIDER_CONN *conn; + SPIDER_LINK_IDX_CHAIN *link_idx_chain; + SPIDER_LINK_IDX_HOLDER *link_idx_holder; + DBUG_ENTER("spider_send_query"); fields->set_pos_to_first_link_idx_chain(); while ((link_idx_chain = fields->get_next_link_idx_chain())) @@ -1204,12 +1184,8 @@ int spider_group_by_handler::init_scan() dbton_hdl->first_link_idx, TRUE, FALSE, !fields->is_first_link_ok_chain(link_idx_chain)))) { - if ( - error_num != HA_ERR_END_OF_FILE && - spider->need_mons[link_idx] - ) { + if (error_num != HA_ERR_END_OF_FILE && spider->need_mons[link_idx]) error_num = fields->ping_table_mon_from_table(link_idx_chain); - } if ((error_num = spider->check_error_mode_eof(error_num)) == HA_ERR_END_OF_FILE) { store_error = HA_ERR_END_OF_FILE; @@ -1220,12 +1196,9 @@ int spider_group_by_handler::init_scan() } else { #endif pthread_mutex_assert_not_owner(&conn->mta_conn_mutex); - if ((error_num = - dbton_hdl->set_sql_for_exec(SPIDER_SQL_TYPE_SELECT_SQL, link_idx, - link_idx_chain))) - { + if ((error_num = dbton_hdl->set_sql_for_exec( + SPIDER_SQL_TYPE_SELECT_SQL, link_idx, link_idx_chain))) DBUG_RETURN(error_num); - } pthread_mutex_lock(&conn->mta_conn_mutex); SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos); conn->need_mon = &spider->need_mons[link_idx]; @@ -1235,6 +1208,7 @@ int spider_group_by_handler::init_scan() conn->mta_conn_mutex_unlock_later = TRUE; if ((error_num = spider_db_set_names(spider, conn, link_idx))) + if ((error_num = spider_db_set_names(spider, conn, link_idx))) { DBUG_ASSERT(conn->mta_conn_mutex_lock_already); DBUG_ASSERT(conn->mta_conn_mutex_unlock_later); @@ -1242,37 +1216,32 @@ int spider_group_by_handler::init_scan() conn->mta_conn_mutex_unlock_later = FALSE; SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); - if ( - spider->need_mons[link_idx] - ) { + if (spider->need_mons[link_idx]) error_num = fields->ping_table_mon_from_table(link_idx_chain); - } - if ((error_num = spider->check_error_mode_eof(error_num)) == HA_ERR_END_OF_FILE) + if ((error_num = spider->check_error_mode_eof(error_num)) == + HA_ERR_END_OF_FILE) { store_error = HA_ERR_END_OF_FILE; error_num = 0; } DBUG_RETURN(error_num); } - spider_conn_set_timeout_from_share(conn, link_idx, - trx->thd, share); + spider_conn_set_timeout_from_share(conn, link_idx, trx->thd, share); if (dbton_hdl->execute_sql( SPIDER_SQL_TYPE_SELECT_SQL, conn, spider->result_list.quick_mode, - &spider->need_mons[link_idx]) - ) { + &spider->need_mons[link_idx])) + { DBUG_ASSERT(conn->mta_conn_mutex_lock_already); DBUG_ASSERT(conn->mta_conn_mutex_unlock_later); conn->mta_conn_mutex_lock_already = FALSE; conn->mta_conn_mutex_unlock_later = FALSE; error_num = spider_db_errorno(conn); - if ( - spider->need_mons[link_idx] - ) { + if (spider->need_mons[link_idx]) error_num = fields->ping_table_mon_from_table(link_idx_chain); - } - if ((error_num = spider->check_error_mode_eof(error_num)) == HA_ERR_END_OF_FILE) + if ((error_num = spider->check_error_mode_eof(error_num)) == + HA_ERR_END_OF_FILE) { store_error = HA_ERR_END_OF_FILE; error_num = 0; @@ -1288,13 +1257,10 @@ int spider_group_by_handler::init_scan() { if ((error_num = spider_db_store_result(spider, link_idx, table))) { - if ( - error_num != HA_ERR_END_OF_FILE && - spider->need_mons[link_idx] - ) { + if (error_num != HA_ERR_END_OF_FILE && spider->need_mons[link_idx]) error_num = fields->ping_table_mon_from_table(link_idx_chain); - } - if ((error_num = spider->check_error_mode_eof(error_num)) == HA_ERR_END_OF_FILE) + if ((error_num = spider->check_error_mode_eof(error_num)) == + HA_ERR_END_OF_FILE) { store_error = HA_ERR_END_OF_FILE; error_num = 0; @@ -1303,7 +1269,8 @@ int spider_group_by_handler::init_scan() } spider->result_link_idx = link_idx; spider->result_link_idx_chain = link_idx_chain; - } else { + } else + { spider_db_discard_result(spider, link_idx, conn); SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); pthread_mutex_unlock(&conn->mta_conn_mutex); @@ -1312,6 +1279,35 @@ int spider_group_by_handler::init_scan() } #endif } + DBUG_RETURN(0); +} + +int spider_group_by_handler::init_scan() +{ + int error_num; + DBUG_ENTER("spider_group_by_handler::init_scan"); + store_error = 0; +#ifndef DBUG_OFF + Field **field; + for (field = table->field; *field; field++) + DBUG_PRINT("info",("spider field_name=%s", SPIDER_field_name_str(*field))); +#endif + + if (trx->thd->killed) + { + my_error(ER_QUERY_INTERRUPTED, MYF(0)); + DBUG_RETURN(ER_QUERY_INTERRUPTED); + } + + if ((error_num = spider_prepare_init_scan( + query, fields, spider, trx, offset_limit, thd))) + DBUG_RETURN(error_num); + + if ((error_num = spider_make_query(query, fields, spider, table))) + DBUG_RETURN(error_num); + + if ((error_num = spider_send_query(fields, spider, trx, table, store_error))) + DBUG_RETURN(error_num); first = TRUE; DBUG_RETURN(0); From 178396573a1d1bf67680c821ace170bb911a3437 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 17 Nov 2023 11:07:50 +1100 Subject: [PATCH 267/477] MDEV-26247 Re-implement spider gbh query rewrite of tables Spider GBH's query rewrite of table joins is overly complex and error-prone. We replace it with something closer to what dbug_print() (more specifically, print_join()) does, but catered to spider. More specifically, we replace the body of spider_db_mbase_util::append_from_and_tables() with a call to spider_db_mbase_util::append_join(), and remove downstream append_X functions. We make it handle const tables by rewriting them as (select 1). This fixes the main issue in MDEV-26247. We also ban semijoin from spider gbh, which fixes MDEV-31645 and MDEV-30392, as semi-join is an "internal" join, and "semi join" does not parse, and it is different from "join" in that it deduplicates the right hand side Not all queries passed to a group by handler are valid (MDEV-32273), for example, a join on expr may refer outer fields not in the current context. We detect this during the handler creation when walking the join. See also gbh_outer_fields_in_join.test. It also skips eliminated tables, which fixes MDEV-26193. --- .../bugfix/r/gbh_outer_fields_in_join.result | 50 ++ .../spider/bugfix/r/mdev_19866.result | 2 + .../spider/bugfix/r/mdev_26247.result | 90 +++ .../spider/bugfix/r/mdev_29163.result | 23 + .../spider/bugfix/r/mdev_30392.result | 22 + .../spider/bugfix/r/mdev_31645.result | 22 + .../r/spider_join_with_non_spider.result | 23 + .../spider/bugfix/r/subquery.result | 24 + .../bugfix/t/gbh_outer_fields_in_join.cnf | 3 + .../bugfix/t/gbh_outer_fields_in_join.test | 46 ++ .../mysql-test/spider/bugfix/t/mdev_26247.cnf | 3 + .../spider/bugfix/t/mdev_26247.test | 78 ++ .../spider/bugfix/t/mdev_29163.test | 31 + .../spider/bugfix/t/mdev_30392.test | 28 + .../spider/bugfix/t/mdev_31645.test | 26 + .../bugfix/t/spider_join_with_non_spider.test | 28 + .../mysql-test/spider/bugfix/t/subquery.test | 30 + .../mysql-test/spider/r/direct_join.result | 2 +- .../r/direct_left_right_join_nullable.result | 2 +- ...irect_left_right_left_join_nullable.result | 2 +- .../spider/r/direct_right_join.result | 2 +- .../r/direct_right_join_nullable.result | 2 +- .../r/direct_right_left_join_nullable.result | 2 +- ...rect_right_left_right_join_nullable.result | 2 +- ..._join_pushdown_for_single_partition.result | 2 + .../e1121/r/direct_join_by_pkey_key.result | 2 +- storage/spider/spd_db_mysql.cc | 715 ++++++------------ storage/spider/spd_db_mysql.h | 40 +- storage/spider/spd_group_by_handler.cc | 28 +- 29 files changed, 787 insertions(+), 543 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/gbh_outer_fields_in_join.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_26247.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/spider_join_with_non_spider.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/subquery.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/gbh_outer_fields_in_join.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/gbh_outer_fields_in_join.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_26247.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_26247.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/spider_join_with_non_spider.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/subquery.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/gbh_outer_fields_in_join.result b/storage/spider/mysql-test/spider/bugfix/r/gbh_outer_fields_in_join.result new file mode 100644 index 00000000000..75c2f2c2751 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/gbh_outer_fields_in_join.result @@ -0,0 +1,50 @@ +# +# MDEV-26247 Spider: Valid LEFT JOIN results in ERROR 1064 +# +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +connection child2_1; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +CREATE TABLE t1 (a int) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 (a int) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t3 (a int) ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1), (2); +INSERT INTO t3 VALUES (1), (2), (3); +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +CREATE TABLE t1 (a int) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='srv "s_2_1", table "t1"'; +CREATE TABLE t2 (a int) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='srv "s_2_1", table "t2"'; +CREATE TABLE t3 (a int) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='srv "s_2_1", table "t3"'; +select * from t3 left join t1 on t3.a = t1.a left join t2 on t3.a = t2.a; +a a a +1 1 1 +2 NULL 2 +3 NULL NULL +select * from t1 left join t2 on t1.a = t2.a right join t3 on t3.a = t1.a; +a a a +1 1 1 +NULL NULL 2 +NULL NULL 3 +select * from t3 left join (t1 left join t2 on t1.a = t2.a) on t3.a = t1.a; +a a a +1 1 1 +2 NULL NULL +3 NULL NULL +drop table t1, t2, t3; +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result index 5d483481edd..edb45e4a62a 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result @@ -72,6 +72,7 @@ SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument select `pkey`,`val` from `auto_test_remote`.`tbl_a` select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 1 +select 1 from (select 1) t0 select `pkey`,`val` from `auto_test_remote`.`tbl_a` select `pkey`,`val` from `auto_test_remote`.`tbl_a` SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' @@ -85,6 +86,7 @@ argument select `pkey`,`val` from `auto_test_remote2`.`tbl_a` select `pkey`,`val` from `auto_test_remote2`.`tbl_a` select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 2 +select 1 from (select 1) t0 select `pkey`,`val` from `auto_test_remote2`.`tbl_a` SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT pkey, val FROM tbl_a ORDER BY pkey; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_26247.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_26247.result new file mode 100644 index 00000000000..6eddf9a733e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_26247.result @@ -0,0 +1,90 @@ +# +# MDEV-26247 Spider: Valid LEFT JOIN results in ERROR 1064 +# +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +connection child2_1; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +CREATE TABLE t1 ( +a11 int, +primary key (a11) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( +a21 int, +a22 int, +primary key (a21, a22) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t3 ( +a31 int, +a32 int, +primary key (a31, a32) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (1, 11), (2, 22), (3, 33); +INSERT INTO t3 VALUES (1, 111), (2, 222), (3, 333); +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +CREATE TABLE t1 ( +a11 int, +primary key (a11) +) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='srv "s_2_1", table "t1"'; +CREATE TABLE t2 ( +a21 int, +a22 int, +primary key (a21, a22) +) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='srv "s_2_1", table "t2"'; +CREATE TABLE t3 ( +a31 int, +a32 int, +primary key (a31, a32) +) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='srv "s_2_1", table "t3"'; +SELECT a22 FROM t1 LEFT JOIN t2 ON a11 = a21 WHERE a11 IN (1); +a22 +11 +SELECT a22 FROM t1 LEFT JOIN t2 ON a11 = a21 - a21 WHERE a11 IN (1); +a22 +NULL +SELECT a22 FROM t2 RIGHT JOIN t1 ON a21 = a11 WHERE a11 IN (1); +a22 +11 +SELECT a22 FROM t2 RIGHT JOIN t1 ON a21 = a11 WHERE a11 IN (1,2); +a22 +11 +22 +SELECT a22, a32 FROM t1 LEFT JOIN t2 ON a11 = a21 RIGHT JOIN t3 on a21 = a31 WHERE a11 IN (1); +a22 a32 +11 111 +SELECT a22, a32 FROM t1 LEFT JOIN t2 ON a11 = a21 - a21 RIGHT JOIN t3 on a21 = a31 - a31 WHERE a11 IN (1); +a22 a32 +SELECT a22, a32 FROM t1 LEFT JOIN t2 ON a11 = a21 RIGHT JOIN t3 on a21 = a31 WHERE a11 IN (1,2); +a22 a32 +11 111 +22 222 +SELECT a22 FROM t2 LEFT JOIN t1 ON a11 = a21 WHERE a11 IN (1); +a22 +11 +SELECT a22 FROM t2 LEFT JOIN t1 ON a11 = a21 - a21 WHERE a11 IN (1); +a22 +SELECT a22 FROM t1 RIGHT JOIN t2 ON a21 = a11 WHERE a11 IN (1); +a22 +11 +SELECT a22 FROM t1 RIGHT JOIN t2 ON a21 = a11 WHERE a11 IN (1,2); +a22 +11 +22 +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result new file mode 100644 index 00000000000..af4bef1efa9 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result @@ -0,0 +1,23 @@ +# +# MDEV-29163 Server crash with SIGSEGV or dynamic-stack-buffer-overflow in spider_db_mbase_util::append_table +# +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); +CREATE TABLE t2 (b INT); +CREATE TABLE t3 (c INT, PRIMARY KEY(c)); +CREATE TABLE t1_spider (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't1'"; +CREATE TABLE t2_spider (b INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't2'"; +CREATE TABLE t3_spider (c INT, PRIMARY KEY(c)) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't3'"; +SELECT t1_spider.* FROM t1_spider LEFT JOIN t2_spider LEFT JOIN t3_spider ON b = c ON a = b; +a +DROP TABLE t1_spider, t2_spider, t3_spider, t1, t2, t3; +drop server s; +for master_1 +for child2 +for child3 +# +# end of test mdev_29163 +# diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result new file mode 100644 index 00000000000..58873d2c6e5 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result @@ -0,0 +1,22 @@ +# +# MDEV-30392 Syntax error upon query with subquery from Spider table +# +for master_1 +for child2 +for child3 +CREATE SERVER srv 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 t2 (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 'srv', table 't1'"; +SELECT a FROM t2 WHERE a IN ( SELECT a FROM t2 ); +a +1 +2 +DROP TABLE t1, t2; +DROP SERVER srv; +for master_1 +for child2 +for child3 +# +# end of test mdev_30392 +# diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result new file mode 100644 index 00000000000..94b76de7df4 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result @@ -0,0 +1,22 @@ +# +# MDEV-31645 Spider doesn't recognize semi JOIN +# +for master_1 +for child2 +for child3 +CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE TABLE t1 ( a bigint(20) NOT NULL, b bigint(20) DEFAULT 0, PRIMARY KEY (a)); +CREATE TABLE t2 ( a bigint(20) NOT NULL, b bigint(20) DEFAULT 0, PRIMARY KEY (a)) ENGINE=SPIDER COMMENT='srv "srv", WRAPPER "mysql", TABLE "t1"'; +SELECT * FROM t2 WHERE b IN (SELECT b FROM t2 WHERE a > 10); +a b +SELECT * FROM t2 +WHERE A BETWEEN 0 AND 10 AND B IN(SELECT B FROM t2 WHERE A BETWEEN 11 AND 20); +a b +drop table t1, t2; +drop server srv; +for master_1 +for child2 +for child3 +# +# end of test mdev_31645 +# diff --git a/storage/spider/mysql-test/spider/bugfix/r/spider_join_with_non_spider.result b/storage/spider/mysql-test/spider/bugfix/r/spider_join_with_non_spider.result new file mode 100644 index 00000000000..b9c1c5c9de5 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/spider_join_with_non_spider.result @@ -0,0 +1,23 @@ +# +# Test joining a spider table with a non-spider table +# +for master_1 +for child2 +for child3 +CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t1 (c int); +create table t2 (d int); +insert into t2 values (1), (2); +create table t3 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +insert into t3 values (2), (3); +select c from t3 join t2 on c = d; +c +2 +drop table t1, t2, t3; +drop server srv; +for master_1 +for child2 +for child3 +# +# end of test spider_join_with_non_spider +# diff --git a/storage/spider/mysql-test/spider/bugfix/r/subquery.result b/storage/spider/mysql-test/spider/bugfix/r/subquery.result new file mode 100644 index 00000000000..c6ea45e2dc0 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/subquery.result @@ -0,0 +1,24 @@ +# +# Test spider select with subqueries +# +for master_1 +for child2 +for child3 +CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t1 (c1 int); +create table t2 (c2 int); +insert into t1 values (1), (2); +insert into t2 values (0), (1), (2); +create table t1s (c1 int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +create table t2s (c2 int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +select c1 from t1s, (select c2 from t2s where c2 > 0) t where c1 + 1 = c2; +c1 +1 +drop table t1, t2, t1s, t2s; +drop server srv; +for master_1 +for child2 +for child3 +# +# end of test subquery +# diff --git a/storage/spider/mysql-test/spider/bugfix/t/gbh_outer_fields_in_join.cnf b/storage/spider/mysql-test/spider/bugfix/t/gbh_outer_fields_in_join.cnf new file mode 100644 index 00000000000..05dfd8a0bce --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/gbh_outer_fields_in_join.cnf @@ -0,0 +1,3 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/gbh_outer_fields_in_join.test b/storage/spider/mysql-test/spider/bugfix/t/gbh_outer_fields_in_join.test new file mode 100644 index 00000000000..f60abc3049d --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/gbh_outer_fields_in_join.test @@ -0,0 +1,46 @@ +--echo # +--echo # MDEV-26247 Spider: Valid LEFT JOIN results in ERROR 1064 +--echo # + +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +--connection child2_1 +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +eval CREATE TABLE t1 (a int) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +eval CREATE TABLE t2 (a int) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +eval CREATE TABLE t3 (a int) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; + +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1), (2); +INSERT INTO t3 VALUES (1), (2), (3); + +--connection master_1 +CREATE DATABASE auto_test_local; +USE auto_test_local; + +eval CREATE TABLE t1 (a int) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='srv "s_2_1", table "t1"'; +eval CREATE TABLE t2 (a int) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='srv "s_2_1", table "t2"'; +eval CREATE TABLE t3 (a int) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='srv "s_2_1", table "t3"'; + +select * from t3 left join t1 on t3.a = t1.a left join t2 on t3.a = t2.a; +select * from t1 left join t2 on t1.a = t2.a right join t3 on t3.a = t1.a; +select * from t3 left join (t1 left join t2 on t1.a = t2.a) on t3.a = t1.a; + +drop table t1, t2, t3; + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; + +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_query_log +--enable_result_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_26247.cnf b/storage/spider/mysql-test/spider/bugfix/t/mdev_26247.cnf new file mode 100644 index 00000000000..05dfd8a0bce --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_26247.cnf @@ -0,0 +1,3 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_26247.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_26247.test new file mode 100644 index 00000000000..80328e05fd6 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_26247.test @@ -0,0 +1,78 @@ +--echo # +--echo # MDEV-26247 Spider: Valid LEFT JOIN results in ERROR 1064 +--echo # + +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +--connection child2_1 +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +eval CREATE TABLE t1 ( + a11 int, + primary key (a11) +) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; + +eval CREATE TABLE t2 ( + a21 int, + a22 int, + primary key (a21, a22) +) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; + +eval CREATE TABLE t3 ( + a31 int, + a32 int, + primary key (a31, a32) +) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; + +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (1, 11), (2, 22), (3, 33); +INSERT INTO t3 VALUES (1, 111), (2, 222), (3, 333); + +--connection master_1 +CREATE DATABASE auto_test_local; +USE auto_test_local; + +eval CREATE TABLE t1 ( + a11 int, + primary key (a11) +) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='srv "s_2_1", table "t1"'; + +eval CREATE TABLE t2 ( + a21 int, + a22 int, + primary key (a21, a22) +) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='srv "s_2_1", table "t2"'; + +eval CREATE TABLE t3 ( + a31 int, + a32 int, + primary key (a31, a32) +) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='srv "s_2_1", table "t3"'; + +SELECT a22 FROM t1 LEFT JOIN t2 ON a11 = a21 WHERE a11 IN (1); +SELECT a22 FROM t1 LEFT JOIN t2 ON a11 = a21 - a21 WHERE a11 IN (1); +SELECT a22 FROM t2 RIGHT JOIN t1 ON a21 = a11 WHERE a11 IN (1); +SELECT a22 FROM t2 RIGHT JOIN t1 ON a21 = a11 WHERE a11 IN (1,2); +SELECT a22, a32 FROM t1 LEFT JOIN t2 ON a11 = a21 RIGHT JOIN t3 on a21 = a31 WHERE a11 IN (1); +SELECT a22, a32 FROM t1 LEFT JOIN t2 ON a11 = a21 - a21 RIGHT JOIN t3 on a21 = a31 - a31 WHERE a11 IN (1); +SELECT a22, a32 FROM t1 LEFT JOIN t2 ON a11 = a21 RIGHT JOIN t3 on a21 = a31 WHERE a11 IN (1,2); +SELECT a22 FROM t2 LEFT JOIN t1 ON a11 = a21 WHERE a11 IN (1); +SELECT a22 FROM t2 LEFT JOIN t1 ON a11 = a21 - a21 WHERE a11 IN (1); +SELECT a22 FROM t1 RIGHT JOIN t2 ON a21 = a11 WHERE a11 IN (1); +SELECT a22 FROM t1 RIGHT JOIN t2 ON a21 = a11 WHERE a11 IN (1,2); + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; + +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_query_log +--enable_result_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test new file mode 100644 index 00000000000..ac116fd0e4f --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test @@ -0,0 +1,31 @@ +--echo # +--echo # MDEV-29163 Server crash with SIGSEGV or dynamic-stack-buffer-overflow in spider_db_mbase_util::append_table +--echo # +--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); +CREATE TABLE t2 (b INT); +CREATE TABLE t3 (c INT, PRIMARY KEY(c)); + +CREATE TABLE t1_spider (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't1'"; +CREATE TABLE t2_spider (b INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't2'"; +CREATE TABLE t3_spider (c INT, PRIMARY KEY(c)) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't3'"; + +SELECT t1_spider.* FROM t1_spider LEFT JOIN t2_spider LEFT JOIN t3_spider ON b = c ON a = b; + +# Cleanup +DROP TABLE t1_spider, t2_spider, t3_spider, t1, t2, t3; +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_29163 +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test new file mode 100644 index 00000000000..03417013b07 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test @@ -0,0 +1,28 @@ +--echo # +--echo # MDEV-30392 Syntax error upon query with subquery from Spider table +--echo # +--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'); + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 'srv', table 't1'"; + +SELECT a FROM t2 WHERE a IN ( SELECT a FROM t2 ); + +# Cleanup + +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 mdev_30392 +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test new file mode 100644 index 00000000000..bec9dd6c316 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test @@ -0,0 +1,26 @@ +--echo # +--echo # MDEV-31645 Spider doesn't recognize semi JOIN +--echo # +--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'); + +CREATE TABLE t1 ( a bigint(20) NOT NULL, b bigint(20) DEFAULT 0, PRIMARY KEY (a)); +CREATE TABLE t2 ( a bigint(20) NOT NULL, b bigint(20) DEFAULT 0, PRIMARY KEY (a)) ENGINE=SPIDER COMMENT='srv "srv", WRAPPER "mysql", TABLE "t1"'; + +SELECT * FROM t2 WHERE b IN (SELECT b FROM t2 WHERE a > 10); +SELECT * FROM t2 +WHERE A BETWEEN 0 AND 10 AND B IN(SELECT B FROM t2 WHERE A BETWEEN 11 AND 20); +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 mdev_31645 +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/spider_join_with_non_spider.test b/storage/spider/mysql-test/spider/bugfix/t/spider_join_with_non_spider.test new file mode 100644 index 00000000000..7b5d38014ed --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/spider_join_with_non_spider.test @@ -0,0 +1,28 @@ +--echo # +--echo # Test joining a spider table with a non-spider table +--echo # + +--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'); +create table t1 (c int); +create table t2 (d int); +insert into t2 values (1), (2); +create table t3 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +insert into t3 values (2), (3); +select c from t3 join t2 on c = d; +drop table t1, t2, t3; +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 spider_join_with_non_spider +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/subquery.test b/storage/spider/mysql-test/spider/bugfix/t/subquery.test new file mode 100644 index 00000000000..7a50719603d --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/subquery.test @@ -0,0 +1,30 @@ +--echo # +--echo # Test spider select with subqueries +--echo # +--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'); +create table t1 (c1 int); +create table t2 (c2 int); + +insert into t1 values (1), (2); +insert into t2 values (0), (1), (2); + +create table t1s (c1 int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +create table t2s (c2 int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; + +select c1 from t1s, (select c2 from t2s where c2 > 0) t where c1 + 1 = c2; + +drop table t1, t2, t1s, t2s; +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 subquery +--echo # diff --git a/storage/spider/mysql-test/spider/r/direct_join.result b/storage/spider/mysql-test/spider/r/direct_join.result index 278b2eddfdf..5c0f4c808a0 100644 --- a/storage/spider/mysql-test/spider/r/direct_join.result +++ b/storage/spider/mysql-test/spider/r/direct_join.result @@ -167,7 +167,7 @@ connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument select `id`,`hr_status`,`region_code`,`region` from `auto_test_remote`.`tbl_person` where `id` = '24FC3F0A5119432BAE13DD65AABAA39C' and `region` = 510411 -select count(0) `count(0)` from `auto_test_remote`.`tbl_ncd_cm_person` t0 where ((t0.`person_id` = '24FC3F0A5119432BAE13DD65AABAA39C') and (t0.`diseaseKind_id` = '52A0328740914BCE86ED10A4D2521816')) +select count(0) `count(0)` from (select 1) t0 join `auto_test_remote`.`tbl_ncd_cm_person` t1 where ((t1.`person_id` = '24FC3F0A5119432BAE13DD65AABAA39C') and (t1.`diseaseKind_id` = '52A0328740914BCE86ED10A4D2521816')) SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT * FROM tbl_person; id hr_status region_code region diff --git a/storage/spider/mysql-test/spider/r/direct_left_right_join_nullable.result b/storage/spider/mysql-test/spider/r/direct_left_right_join_nullable.result index f3c6e189444..6c995258f24 100644 --- a/storage/spider/mysql-test/spider/r/direct_left_right_join_nullable.result +++ b/storage/spider/mysql-test/spider/r/direct_left_right_join_nullable.result @@ -87,7 +87,7 @@ NULL NULL NULL 3 connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument -select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_no_idx` t3 left join (`auto_test_remote`.`ta_r_auto_inc` t2 join `auto_test_remote`.`ta_r_3` t1 join `auto_test_remote`.`ta_r` t0) on ((t2.`b` = t3.`b`) and (t2.`c` = t1.`c`) and (t0.`a` = t1.`a`) and (t1.`a` is not null) and (t3.`b` is not null)) where 1 order by t3.`a` desc +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_no_idx` t3 left join (`auto_test_remote`.`ta_r` t0 join `auto_test_remote`.`ta_r_3` t1 join `auto_test_remote`.`ta_r_auto_inc` t2) on ((t2.`b` = t3.`b`) and (t2.`c` = t1.`c`) and (t0.`a` = t1.`a`) and (t1.`a` is not null) and (t3.`b` is not null)) where 1 order by t3.`a` desc SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; a b date_format(c, '%Y-%m-%d %H:%i:%s') diff --git a/storage/spider/mysql-test/spider/r/direct_left_right_left_join_nullable.result b/storage/spider/mysql-test/spider/r/direct_left_right_left_join_nullable.result index 88205fb0f65..4597fd5464a 100644 --- a/storage/spider/mysql-test/spider/r/direct_left_right_left_join_nullable.result +++ b/storage/spider/mysql-test/spider/r/direct_left_right_left_join_nullable.result @@ -86,7 +86,7 @@ NULL c 2000-01-03 00:00:00 3 connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument -select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_auto_inc` t2 left join (`auto_test_remote`.`ta_r_3` t1 join `auto_test_remote`.`ta_r` t0) on ((t1.`c` = t2.`c`) and (t0.`a` = t1.`a`) and (t1.`a` is not null)) left join `auto_test_remote`.`ta_r_no_idx` t3 on (t3.`b` = t2.`b`) where 1 order by t3.`a` desc +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_auto_inc` t2 left join (`auto_test_remote`.`ta_r` t0 join `auto_test_remote`.`ta_r_3` t1) on ((t1.`c` = t2.`c`) and (t0.`a` = t1.`a`) and (t1.`a` is not null)) left join `auto_test_remote`.`ta_r_no_idx` t3 on (t3.`b` = t2.`b`) where 1 order by t3.`a` desc SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; a b date_format(c, '%Y-%m-%d %H:%i:%s') diff --git a/storage/spider/mysql-test/spider/r/direct_right_join.result b/storage/spider/mysql-test/spider/r/direct_right_join.result index 8edfb682292..b42e40031e3 100644 --- a/storage/spider/mysql-test/spider/r/direct_right_join.result +++ b/storage/spider/mysql-test/spider/r/direct_right_join.result @@ -79,7 +79,7 @@ a b c connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument -select t0.`b` `b`,t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r_int` t2 left join (`auto_test_remote`.`ta_r` t0 join `auto_test_remote`.`ta_r_3` t1) on ((t0.`a` = t2.`a`) and (t1.`a` = t2.`a`)) where 1 order by t0.`b` desc +select t0.`b` `b`,t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r_int` t2 left join (`auto_test_remote`.`ta_r_3` t1 join `auto_test_remote`.`ta_r` t0) on ((t0.`a` = t2.`a`) and (t1.`a` = t2.`a`)) where 1 order by t0.`b` desc SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; a b date_format(c, '%Y-%m-%d %H:%i:%s') diff --git a/storage/spider/mysql-test/spider/r/direct_right_join_nullable.result b/storage/spider/mysql-test/spider/r/direct_right_join_nullable.result index a05781cb6d6..0c448734598 100644 --- a/storage/spider/mysql-test/spider/r/direct_right_join_nullable.result +++ b/storage/spider/mysql-test/spider/r/direct_right_join_nullable.result @@ -87,7 +87,7 @@ NULL c 2000-01-03 00:00:00 3 connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument -select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_no_idx` t3 left join `auto_test_remote`.`ta_r_auto_inc` t2 on ((t2.`b` = t3.`b`) and (t3.`b` is not null)) left join `auto_test_remote`.`ta_r_3` t1 on (t1.`c` = t2.`c`) left join `auto_test_remote`.`ta_r` t0 on ((t0.`a` = t1.`a`) and (t1.`a` is not null)) where 1 order by t3.`a` desc +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_no_idx` t3 left join (`auto_test_remote`.`ta_r_auto_inc` t2 left join (`auto_test_remote`.`ta_r_3` t1 left join `auto_test_remote`.`ta_r` t0 on ((t0.`a` = t1.`a`) and (t1.`a` is not null))) on (t1.`c` = t2.`c`)) on ((t2.`b` = t3.`b`) and (t3.`b` is not null)) where 1 order by t3.`a` desc SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; a b date_format(c, '%Y-%m-%d %H:%i:%s') diff --git a/storage/spider/mysql-test/spider/r/direct_right_left_join_nullable.result b/storage/spider/mysql-test/spider/r/direct_right_left_join_nullable.result index 25e0913ba06..f33c699b30a 100644 --- a/storage/spider/mysql-test/spider/r/direct_right_left_join_nullable.result +++ b/storage/spider/mysql-test/spider/r/direct_right_left_join_nullable.result @@ -86,7 +86,7 @@ NULL c 2000-01-03 00:00:00 3 connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument -select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_auto_inc` t2 left join `auto_test_remote`.`ta_r_3` t1 on (t1.`c` = t2.`c`) left join `auto_test_remote`.`ta_r` t0 on ((t0.`a` = t1.`a`) and (t1.`a` is not null)) left join `auto_test_remote`.`ta_r_no_idx` t3 on (t3.`b` = t2.`b`) where 1 order by t3.`a` desc +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_auto_inc` t2 left join (`auto_test_remote`.`ta_r_3` t1 left join `auto_test_remote`.`ta_r` t0 on ((t0.`a` = t1.`a`) and (t1.`a` is not null))) on (t1.`c` = t2.`c`) left join `auto_test_remote`.`ta_r_no_idx` t3 on (t3.`b` = t2.`b`) where 1 order by t3.`a` desc SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; a b date_format(c, '%Y-%m-%d %H:%i:%s') diff --git a/storage/spider/mysql-test/spider/r/direct_right_left_right_join_nullable.result b/storage/spider/mysql-test/spider/r/direct_right_left_right_join_nullable.result index 48cd9c2c75f..a29422f6325 100644 --- a/storage/spider/mysql-test/spider/r/direct_right_left_right_join_nullable.result +++ b/storage/spider/mysql-test/spider/r/direct_right_left_right_join_nullable.result @@ -87,7 +87,7 @@ NULL c 2000-01-03 00:00:00 3 connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument -select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_no_idx` t3 left join (`auto_test_remote`.`ta_r_auto_inc` t2 join `auto_test_remote`.`ta_r_3` t1 left join `auto_test_remote`.`ta_r` t0 on ((t0.`a` = t1.`a`) and (t1.`a` is not null))) on ((t2.`b` = t3.`b`) and (t2.`c` = t1.`c`) and (t3.`b` is not null)) where 1 order by t3.`a` desc +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_no_idx` t3 left join (`auto_test_remote`.`ta_r_3` t1 left join `auto_test_remote`.`ta_r` t0 on ((t0.`a` = t1.`a`) and (t1.`a` is not null)) join `auto_test_remote`.`ta_r_auto_inc` t2) on ((t2.`b` = t3.`b`) and (t2.`c` = t1.`c`) and (t3.`b` is not null)) where 1 order by t3.`a` desc SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; a b date_format(c, '%Y-%m-%d %H:%i:%s') diff --git a/storage/spider/mysql-test/spider/r/partition_join_pushdown_for_single_partition.result b/storage/spider/mysql-test/spider/r/partition_join_pushdown_for_single_partition.result index 899788ae1c1..5026025dfd0 100644 --- a/storage/spider/mysql-test/spider/r/partition_join_pushdown_for_single_partition.result +++ b/storage/spider/mysql-test/spider/r/partition_join_pushdown_for_single_partition.result @@ -86,8 +86,10 @@ SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument select `value` from `auto_test_remote2`.`tbl_a` where `value` = 5 select `value2` from `auto_test_remote2`.`tbl_b` where `value2` = 5 +select sum('5') `sum(a.value)`,count('5') `count(b.value2)` from (select 1) t0 join (select 1) t1 select `value` from `auto_test_remote2`.`tbl_a` where `value` = 5 select `value2` from `auto_test_remote2`.`tbl_b` where `value2` = 5 +select sum('5') `sum(a.value)`,count('5') `count(b.value2)` from (select 1) t0 join (select 1) t1 SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT value FROM tbl_a ORDER BY value; value diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/direct_join_by_pkey_key.result b/storage/spider/mysql-test/spider/regression/e1121/r/direct_join_by_pkey_key.result index 4b04b71aee2..8177d9b7c86 100644 --- a/storage/spider/mysql-test/spider/regression/e1121/r/direct_join_by_pkey_key.result +++ b/storage/spider/mysql-test/spider/regression/e1121/r/direct_join_by_pkey_key.result @@ -46,7 +46,7 @@ connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%' ; SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_b`%'; argument -select t0.`val` `val`,t0.`akey` `akey` from `auto_test_remote`.`tbl_a` t0 where (t0.`akey` = '4') +select t0.`val` `val`,t0.`akey` `akey` from `auto_test_remote`.`tbl_a` t0 join (select 1) t1 where (t0.`akey` = '4') SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%' ; SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_b`%' argument diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index cbdde148787..eef7f7e0c2f 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -6807,519 +6807,268 @@ int spider_db_mbase_util::append_escaped_util( } #ifdef SPIDER_HAS_GROUP_BY_HANDLER -int spider_db_mbase_util::append_table( - ha_spider *spider, - spider_fields *fields, - spider_string *str, - TABLE_LIST *table_list, - TABLE_LIST **used_table_list, - uint *current_pos, - TABLE_LIST **cond_table_list_ptr, - bool top_down, - bool first -) { - int error_num; - bool use_cond_table_list = FALSE; - spider_mbase_share *db_share; - spider_mbase_handler *dbton_hdl; - SPIDER_TABLE_HOLDER *table_holder; - TABLE_LIST *cond_table_list = *cond_table_list_ptr; - ha_spider *spd; - DBUG_ENTER("spider_db_mbase_util::append_table"); - DBUG_PRINT("info",("spider table_list=%p", table_list)); - DBUG_PRINT("info",("spider table_list->outer_join=%u", - table_list->outer_join)); - DBUG_PRINT("info",("spider table_list->on_expr=%p", - table_list->on_expr)); - DBUG_PRINT("info",("spider table_list->join_using_fields=%p", - table_list->join_using_fields)); - DBUG_PRINT("info",("spider table_list->table=%p", - table_list->table)); - if (!top_down && table_list->embedding) +/* + Walk a TABLE_LIST, or format it to a string and append it. + + If str is NULL, walk the nested join (if any) to determine whether + to create a group by handler. Otherwise, format the TABLE_LIST to a + string and append it to str. + + Adapted from TABLE_LIST::print(). +*/ +int spider_db_mbase_util::append_table_list(spider_fields *fields, + spider_string *str, + TABLE_LIST *table, + table_map *upper_usable_tables, + table_map eliminated_tables) +{ + DBUG_ENTER("spider_db_mbase_util::append_table_list"); + /* Eliminated tables were removed from append_join(). */ + DBUG_ASSERT(!is_eliminated_table(eliminated_tables, table)); + if (!str) /* First pass (GBH creation) */ { - if ((error_num = append_embedding_tables(spider, fields, str, - table_list->embedding, used_table_list, current_pos, - cond_table_list_ptr))) - DBUG_RETURN(error_num); - } else if (!table_list->table) - { - if ((error_num = append_tables_top_down(spider, fields, str, table_list, - used_table_list, current_pos, cond_table_list_ptr))) - DBUG_RETURN(error_num); - } else { - if ( - table_list->outer_join || - table_list->on_expr || - table_list->join_using_fields - ) { - DBUG_PRINT("info",("spider use table_list")); - if (table_list->outer_join & JOIN_TYPE_LEFT) - { - if (str) - { - if (str->reserve(SPIDER_SQL_LEFT_JOIN_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_LEFT_JOIN_STR, SPIDER_SQL_LEFT_JOIN_LEN); - } - } else { - if (str) - { - if (str->reserve(SPIDER_SQL_JOIN_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_JOIN_STR, SPIDER_SQL_JOIN_LEN); - } - } - } else if ( - cond_table_list && - ( - cond_table_list->outer_join || - cond_table_list->on_expr || - cond_table_list->join_using_fields - ) - ) { - DBUG_PRINT("info",("spider use cond_table_list")); - if (cond_table_list->outer_join & (JOIN_TYPE_LEFT | JOIN_TYPE_RIGHT)) - { - if (str) - { - if (str->reserve(SPIDER_SQL_LEFT_JOIN_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_LEFT_JOIN_STR, SPIDER_SQL_LEFT_JOIN_LEN); - } - } else { - if (str) - { - if (str->reserve(SPIDER_SQL_JOIN_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_JOIN_STR, SPIDER_SQL_JOIN_LEN); - } - } - use_cond_table_list = TRUE; - } else if (*current_pos > 0 && !first) - { - DBUG_PRINT("info",("spider no condition")); - if (str) - { - if (str->reserve(SPIDER_SQL_JOIN_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_JOIN_STR, SPIDER_SQL_JOIN_LEN); - } - } - - if (str) - { - table_holder = fields->get_table_holder(table_list->table); - spd = table_holder->spider; - db_share = (spider_mbase_share *) - spd->share->dbton_share[dbton_id]; - dbton_hdl = (spider_mbase_handler *) - spd->dbton_handler[dbton_id]; - - dbton_hdl->table_name_pos = str->length(); - - if (str->reserve( - db_share->db_nm_max_length + - SPIDER_SQL_DOT_LEN + /* SPIDER_SQL_NAME_QUOTE_LEN */ 4 + - db_share->table_nm_max_length + SPIDER_SQL_SPACE_LEN + - table_holder->alias->length() - SPIDER_SQL_DOT_LEN - )) { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - - if ((error_num = db_share->append_table_name_with_adjusting(str, - spd->conn_link_idx[dbton_hdl->first_link_idx]))) - { - DBUG_RETURN(error_num); - } - str->q_append(SPIDER_SQL_SPACE_STR, SPIDER_SQL_SPACE_LEN); - str->q_append(table_holder->alias->ptr(), - table_holder->alias->length() - SPIDER_SQL_DOT_LEN); - } - used_table_list[(*current_pos)++] = table_list; - - if (str) - { - List *join_using_fields = table_list->join_using_fields; - if (!join_using_fields && cond_table_list) - { - join_using_fields = cond_table_list->join_using_fields; - } - - if (join_using_fields) - { - if (str->reserve(SPIDER_SQL_USING_LEN + SPIDER_SQL_OPEN_PAREN_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_USING_STR, SPIDER_SQL_USING_LEN); - str->q_append(SPIDER_SQL_OPEN_PAREN_STR, - SPIDER_SQL_OPEN_PAREN_LEN); - List_iterator_fast it2(*join_using_fields); - String *ptr; - while ((ptr = it2++)) - { - if (str->reserve(ptr->length() + SPIDER_SQL_COMMA_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(ptr->ptr(), ptr->length()); - str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); - } - str->length(str->length() - SPIDER_SQL_COMMA_LEN); - if (str->reserve(SPIDER_SQL_CLOSE_PAREN_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, - SPIDER_SQL_CLOSE_PAREN_LEN); - } - } - - Item *on_expr = table_list->on_expr; - if (!on_expr && cond_table_list) - { - on_expr = cond_table_list->on_expr; - } - - if (on_expr) - { - if (str) - { - if (str->reserve(SPIDER_SQL_ON_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_ON_STR, SPIDER_SQL_ON_LEN); - } - if ((error_num = spider_db_print_item_type(on_expr, NULL, - spider, str, NULL, 0, dbton_id, TRUE, fields))) - { - DBUG_RETURN(error_num); - } - } - - if (use_cond_table_list) - { - (*cond_table_list_ptr) = NULL; - DBUG_PRINT("info",("spider cond_table_list=%p", (*cond_table_list_ptr))); - } + DBUG_ASSERT(upper_usable_tables); + if (table->nested_join) + DBUG_RETURN(append_join(fields, str, + &table->nested_join->join_list, + upper_usable_tables, eliminated_tables)); + /* jtbm is a kind of semi join, and TABLE_LIST::print() adds an + extra " " annotation. */ + if (table->jtbm_subselect) + DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); + /* TODO: These conditions are printed in a different way in + TABLE_LIST::print(), but they do not seem to occur very often. + Let's not worry about them now. */ + if (table->view_name.str || table->derived) + DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); + *upper_usable_tables |= table->table->map; + DBUG_RETURN(0); } + /* Second pass (query execution) */ + DBUG_ASSERT(!upper_usable_tables); + if (table->nested_join) + { + if (str->append("(")) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + if (int error_num= append_join( + fields, str, &table->nested_join->join_list, + upper_usable_tables, eliminated_tables)) + DBUG_RETURN(error_num); + if (str->append(")")) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + DBUG_RETURN(0); + } + /* These have been ruled out during the creation of the group by + handler, see above. */ + DBUG_ASSERT(!table->jtbm_subselect); + DBUG_ASSERT(!table->view_name.str); + DBUG_ASSERT(!table->derived); + /* We have a "normal" table. Print it and append to str. */ + SPIDER_TABLE_HOLDER *table_holder = fields->get_table_holder(table->table); + ha_spider *spd = table_holder->spider; + spider_mbase_share *db_share = + (spider_mbase_share *) spd->share->dbton_share[dbton_id]; + spider_mbase_handler *dbton_hdl = + (spider_mbase_handler *) spd->dbton_handler[dbton_id]; + if (table->table->const_table) + { + if (str->append(STRING_WITH_LEN("(select 1)"))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + else + if (int error_num= db_share->append_table_name( + str, spd->conn_link_idx[dbton_hdl->first_link_idx])) + DBUG_RETURN(error_num); + if (str->append(" ") || + str->append(table_holder->alias->ptr(), + /* Don't append the trailing dot */ + table_holder->alias->length() - 1)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); DBUG_RETURN(0); } -int spider_db_mbase_util::append_tables_top_down( - ha_spider *spider, - spider_fields *fields, - spider_string *str, - TABLE_LIST *table_list, - TABLE_LIST **used_table_list, - uint *current_pos, - TABLE_LIST **cond_table_list_ptr -) { - int error_num; - uint outer_join_backup; - TABLE_LIST *cur_table_list, *prev_table_list = NULL, *cond_table_list = NULL; - bool first = TRUE; - DBUG_ENTER("spider_db_mbase_util::append_tables_top_down"); - DBUG_PRINT("info",("spider this=%p", this)); - if ( - table_list->outer_join || - table_list->on_expr || - table_list->join_using_fields - ) { - DBUG_ASSERT(!(*cond_table_list_ptr)); - (*cond_table_list_ptr) = table_list; - DBUG_PRINT("info",("spider cond_table_list=%p", table_list)); - } - List_iterator_fast it1(table_list->nested_join->join_list); - cur_table_list = it1++; - if (cur_table_list->outer_join & JOIN_TYPE_RIGHT) - { - first = FALSE; - prev_table_list = cur_table_list; - cur_table_list = it1++; - } else if (*cond_table_list_ptr) - { - first = TRUE; - cond_table_list = (*cond_table_list_ptr); - (*cond_table_list_ptr) = NULL; - if (cond_table_list->outer_join & JOIN_TYPE_LEFT) - { - if (str) - { - if (str->reserve(SPIDER_SQL_LEFT_JOIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_LEFT_JOIN_STR, SPIDER_SQL_LEFT_JOIN_LEN); - str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); - } - } else { - if (str) - { - if (str->reserve(SPIDER_SQL_JOIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_JOIN_STR, SPIDER_SQL_JOIN_LEN); - str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); - } - } - } +/* + Walk an array of TABLE_LIST's, or format it to a string and append it. - do { - if (cur_table_list->outer_join & JOIN_TYPE_RIGHT) + If str is NULL, walk each TABLE_LIST to determine whether to create + a group by handler. Otherwise, format the TABLE_LISTs to a string + and append it to str. + + Adapted from print_table_array(). +*/ +int spider_db_mbase_util::append_table_array(spider_fields *fields, + spider_string *str, + TABLE_LIST **table, + TABLE_LIST **end, + table_map *upper_usable_tables, + table_map eliminated_tables) +{ + DBUG_ENTER("spider_db_mbase_util::append_table_array"); + if (str) + { + DBUG_ASSERT(!upper_usable_tables); + if (int error_num= append_table_list(fields, str, *table, NULL, + eliminated_tables)) + DBUG_RETURN(error_num); + + for (TABLE_LIST **tbl= table + 1; tbl < end; tbl++) { - prev_table_list = cur_table_list; - } else { - if ((error_num = append_table(spider, fields, str, cur_table_list, - used_table_list, current_pos, cond_table_list_ptr, TRUE, first))) - DBUG_RETURN(error_num); - first = FALSE; - if (prev_table_list) + TABLE_LIST *curr= *tbl; + + /* JOIN_TYPE_OUTER is just a marker unrelated to real join */ + if (curr->outer_join & (JOIN_TYPE_LEFT|JOIN_TYPE_RIGHT)) { - outer_join_backup = prev_table_list->outer_join; - prev_table_list->outer_join = JOIN_TYPE_LEFT; - if ((error_num = append_table(spider, fields, str, prev_table_list, - used_table_list, current_pos, cond_table_list_ptr, TRUE, FALSE))) - { - prev_table_list->outer_join = outer_join_backup; + /* MySQL converts right to left joins */ + if (str->append(STRING_WITH_LEN(" left join "))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + else if (curr->straight) + { + if (str->append(STRING_WITH_LEN(" straight_join "))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + /* semi join should already have been ruled out during the + creation of the group by handler. */ + else if (curr->sj_inner_tables) + DBUG_ASSERT(0); + else + if (str->append(STRING_WITH_LEN(" join "))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + + if (int error_num= append_table_list(fields, str, curr, NULL, + eliminated_tables)) + DBUG_RETURN(error_num); + + if (curr->on_expr) + { + if (str->append(STRING_WITH_LEN(" on "))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + if (int error_num= + spider_db_print_item_type(curr->on_expr, NULL, + fields->get_first_table_holder()->spider, + str, NULL, 0, dbton_id, TRUE, fields)) DBUG_RETURN(error_num); - } - prev_table_list->outer_join = outer_join_backup; - prev_table_list = NULL; - } - } - } while ((cur_table_list = it1++)); - - if (cond_table_list) - { - if (str) - { - if (str->reserve(SPIDER_SQL_CLOSE_PAREN_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, - SPIDER_SQL_CLOSE_PAREN_LEN); - - List *join_using_fields = cond_table_list->join_using_fields; - if (join_using_fields) - { - if (str->reserve(SPIDER_SQL_USING_LEN + SPIDER_SQL_OPEN_PAREN_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_USING_STR, SPIDER_SQL_USING_LEN); - str->q_append(SPIDER_SQL_OPEN_PAREN_STR, - SPIDER_SQL_OPEN_PAREN_LEN); - List_iterator_fast it2(*join_using_fields); - String *ptr; - while ((ptr = it2++)) - { - if (str->reserve(ptr->length() + SPIDER_SQL_COMMA_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(ptr->ptr(), ptr->length()); - str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); - } - str->length(str->length() - SPIDER_SQL_COMMA_LEN); - if (str->reserve(SPIDER_SQL_CLOSE_PAREN_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, - SPIDER_SQL_CLOSE_PAREN_LEN); - } - } - - Item *on_expr = cond_table_list->on_expr; - if (on_expr) - { - if (str) - { - if (str->reserve(SPIDER_SQL_ON_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_ON_STR, SPIDER_SQL_ON_LEN); - } - if ((error_num = spider_db_print_item_type(on_expr, NULL, - spider, str, NULL, 0, dbton_id, TRUE, fields))) - { - DBUG_RETURN(error_num); } } } - DBUG_RETURN(0); -} - -int spider_db_mbase_util::append_tables_top_down_check( - TABLE_LIST *table_list, - TABLE_LIST **used_table_list, - uint *current_pos -) { - int error_num; - TABLE_LIST *cur_table_list; - DBUG_ENTER("spider_db_mbase_util::append_tables_top_down_check"); - DBUG_PRINT("info",("spider this=%p", this)); - List_iterator_fast it1(table_list->nested_join->join_list); - while ((cur_table_list = it1++)) + else /* str == NULL */ { - if (!cur_table_list->table) - { - if ((error_num = append_tables_top_down_check( - cur_table_list, used_table_list, current_pos))) - DBUG_RETURN(error_num); - } else { - used_table_list[(*current_pos)++] = cur_table_list; - } - } - DBUG_RETURN(0); -} - -int spider_db_mbase_util::append_embedding_tables( - ha_spider *spider, - spider_fields *fields, - spider_string *str, - TABLE_LIST *table_list, - TABLE_LIST **used_table_list, - uint *current_pos, - TABLE_LIST **cond_table_list_ptr -) { - int error_num; - TABLE_LIST *embedding = table_list->embedding; - DBUG_ENTER("spider_db_mbase_util::append_embedding_tables"); - DBUG_PRINT("info",("spider this=%p", this)); - if (embedding) - { - DBUG_PRINT("info",("spider embedding=%p", embedding)); - DBUG_PRINT("info",("spider embedding->outer_join=%u", - embedding->outer_join)); - DBUG_PRINT("info",("spider embedding->on_expr=%p", - embedding->on_expr)); - DBUG_PRINT("info",("spider embedding->join_using_fields=%p", - embedding->join_using_fields)); - DBUG_PRINT("info",("spider embedding->table=%p", - embedding->table)); - if ((error_num = append_embedding_tables(spider, fields, str, embedding, - used_table_list, current_pos, cond_table_list_ptr))) + table_map usable_tables= 0; + if (int error_num= append_table_list(fields, str, *table, + &usable_tables, eliminated_tables)) DBUG_RETURN(error_num); - } else { - DBUG_PRINT("info",("spider table_list=%p", table_list)); - DBUG_PRINT("info",("spider table_list->outer_join=%u", - table_list->outer_join)); - DBUG_PRINT("info",("spider table_list->on_expr=%p", - table_list->on_expr)); - DBUG_PRINT("info",("spider table_list->join_using_fields=%p", - table_list->join_using_fields)); - DBUG_PRINT("info",("spider table_list->table=%p", - table_list->table)); - if (table_list->outer_join & JOIN_TYPE_RIGHT) + for (TABLE_LIST **tbl= table + 1; tbl < end; tbl++) { - if ((error_num = append_tables_top_down_check(table_list, - used_table_list, current_pos))) - DBUG_RETURN(error_num); - DBUG_ASSERT(!(*cond_table_list_ptr)); - (*cond_table_list_ptr) = table_list; - DBUG_PRINT("info",("spider cond_table_list=%p", table_list)); - } else { - if ((error_num = append_tables_top_down(spider, fields, str, table_list, - used_table_list, current_pos, cond_table_list_ptr))) + TABLE_LIST *curr= *tbl; + /* semi join is an "internal" join and is unsupported. */ + if (curr->sj_inner_tables) + DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); + if (int error_num= append_table_list(fields, str, curr, + &usable_tables, eliminated_tables)) DBUG_RETURN(error_num); + if (curr->on_expr) + { + /* The join refers to fields outside of the current context, + and cannot be handled by a group by handler. */ + if ((curr->on_expr->used_tables() & usable_tables) != + curr->on_expr->used_tables()) + DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); + if (int error_num= + spider_db_print_item_type(curr->on_expr, NULL, + fields->get_first_table_holder()->spider, + str, NULL, 0, dbton_id, TRUE, fields)) + DBUG_RETURN(error_num); + } } + /* Update usable tables in the outer context. */ + if (upper_usable_tables) + *upper_usable_tables |= usable_tables; } DBUG_RETURN(0); } +/* + Walk a join, or format it to a string and append the string. + + Skip all eliminated tables. + + If str is NULL, walk the tables to determine whether to create a + group by handler. Otherwise, format the join to a string and append + it to str. + + Adapted from print_join(). +*/ +int spider_db_mbase_util::append_join(spider_fields *fields, + spider_string *str, + List *tables, + table_map *upper_usable_tables, + table_map eliminated_tables) +{ + /* List is reversed => we should reverse it before using */ + List_iterator_fast ti(*tables); + TABLE_LIST **table; + THD *thd= fields->get_first_table_holder()->spider->trx->thd; + DBUG_ENTER("spider_db_mbase_util::append_join"); + + size_t tables_to_print= 0; + + for (TABLE_LIST *t= ti++; t ; t= ti++) + { + /* optimized_away implies const_table */ + DBUG_ASSERT(!t->optimized_away || t->table->const_table); + if (!is_eliminated_table(eliminated_tables, t)) + tables_to_print++; + } + if (tables_to_print == 0) + { + if (str && str->append(STRING_WITH_LEN("dual"))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + DBUG_RETURN(0); + } + ti.rewind(); + + if (!(table= static_cast(thd->alloc(sizeof(TABLE_LIST*) * + tables_to_print)))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + + TABLE_LIST *tmp, **t= table + (tables_to_print - 1); + while ((tmp= ti++)) + if (!is_eliminated_table(eliminated_tables, tmp)) + *t--= tmp; + + DBUG_ASSERT(tables->elements >= 1); + if ((*table)->sj_inner_tables) + { + /* Semi join is not supported. */ + if (!str) + DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); + /* Semi join should have been skipped in the first pass. */ + else + DBUG_ASSERT(0); + } + int error_num= append_table_array( + fields, str, table, table + tables_to_print, upper_usable_tables, + eliminated_tables); + DBUG_RETURN(error_num); +} + int spider_db_mbase_util::append_from_and_tables( ha_spider *spider, spider_fields *fields, spider_string *str, TABLE_LIST *table_list, uint table_count -) { - int error_num; - uint current_pos = 0, roop_count, backup_pos, outer_join_backup; - TABLE *table; - TABLE_LIST **used_table_list, *prev_table_list = NULL, - *cond_table_list = NULL; +) +{ DBUG_ENTER("spider_db_mbase_util::append_from_and_tables"); - DBUG_PRINT("info",("spider this=%p", this)); - used_table_list = (TABLE_LIST **) - my_alloca(sizeof(TABLE_LIST *) * table_count); - if (!used_table_list) + if (str && str->append(" from ")) DBUG_RETURN(HA_ERR_OUT_OF_MEM); - - if (str) - { - if (str->reserve(SPIDER_SQL_FROM_LEN)) - { - my_afree(used_table_list); - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - str->q_append(SPIDER_SQL_FROM_STR, SPIDER_SQL_FROM_LEN); - } - - do { - table = table_list->table; - if (table->const_table) - continue; - - for (roop_count = 0; roop_count < current_pos; ++roop_count) - { - if (used_table_list[roop_count] == table_list) - break; - } - if (roop_count < current_pos) - continue; - - if (prev_table_list) - current_pos = backup_pos; - else - backup_pos = current_pos; - if ((error_num = append_table(spider, fields, str, table_list, used_table_list, - ¤t_pos, &cond_table_list, FALSE, FALSE))) - { - my_afree(used_table_list); - DBUG_RETURN(error_num); - } - if (prev_table_list) - { - outer_join_backup = prev_table_list->outer_join; - prev_table_list->outer_join = JOIN_TYPE_LEFT; - if ((error_num = append_table(spider, fields, str, prev_table_list, - used_table_list, ¤t_pos, &cond_table_list, FALSE, FALSE))) - { - prev_table_list->outer_join = outer_join_backup; - my_afree(used_table_list); - DBUG_RETURN(error_num); - } - prev_table_list->outer_join = outer_join_backup; - prev_table_list = NULL; - } - if (cond_table_list && (cond_table_list->outer_join & JOIN_TYPE_RIGHT)) - { - prev_table_list = cond_table_list; - cond_table_list = NULL; - DBUG_PRINT("info",("spider cond_table_list=%p", cond_table_list)); - } - } while ((table_list = table_list->next_local)); - my_afree(used_table_list); - DBUG_RETURN(0); + const table_map eliminated_tables= table_list->select_lex->join ? + table_list->select_lex->join->eliminated_tables : 0; + int error_num = append_join(fields, str, table_list->select_lex->join_list, + NULL, eliminated_tables); + DBUG_RETURN(error_num); } - int spider_db_mbase_util::append_where( spider_string *str ) { diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h index acb87d632d1..0a12a25df3e 100644 --- a/storage/spider/spd_db_mysql.h +++ b/storage/spider/spd_db_mysql.h @@ -157,40 +157,22 @@ public: String *from ) override; #ifdef SPIDER_HAS_GROUP_BY_HANDLER - int append_table( - ha_spider *spider, - spider_fields *fields, - spider_string *str, - TABLE_LIST *table_list, - TABLE_LIST **used_table_list, - uint *current_pos, - TABLE_LIST **cond_table_list_ptr, - bool top_down, - bool first - ); - int append_tables_top_down( - ha_spider *spider, - spider_fields *fields, - spider_string *str, - TABLE_LIST *table_list, - TABLE_LIST **used_table_list, - uint *current_pos, - TABLE_LIST **cond_table_list_ptr - ); int append_tables_top_down_check( TABLE_LIST *table_list, TABLE_LIST **used_table_list, uint *current_pos ); - int append_embedding_tables( - ha_spider *spider, - spider_fields *fields, - spider_string *str, - TABLE_LIST *table_list, - TABLE_LIST **used_table_list, - uint *current_pos, - TABLE_LIST **cond_table_list_ptr - ); + int append_table_list(spider_fields *fields, + spider_string *str, TABLE_LIST *table, + table_map *upper_usable_tables, + table_map eliminated_tables); + int append_table_array(spider_fields *fields, + spider_string *str, TABLE_LIST **table, + TABLE_LIST **end, table_map *upper_usable_tables, + table_map eliminated_tables); + int append_join(spider_fields *fields, spider_string *str, + List *tables, table_map *upper_usable_tables, + table_map eliminated_tables); int append_from_and_tables( ha_spider *spider, spider_fields *fields, diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index bd1aa1ea906..d2112bedcb3 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -25,6 +25,7 @@ #include "probes_mysql.h" #include "sql_class.h" #include "sql_partition.h" +#include "sql_select.h" #include "ha_partition.h" #endif #include "sql_common.h" @@ -1282,14 +1283,16 @@ static int spider_send_query( DBUG_RETURN(0); } +/* + Prepare and send query to data nodes and store the query results. +*/ int spider_group_by_handler::init_scan() { int error_num; DBUG_ENTER("spider_group_by_handler::init_scan"); store_error = 0; #ifndef DBUG_OFF - Field **field; - for (field = table->field; *field; field++) + for (Field **field = table->field; *field; field++) DBUG_PRINT("info",("spider field_name=%s", SPIDER_field_name_str(*field))); #endif @@ -1439,8 +1442,6 @@ group_by_handler *spider_create_group_by_handler( from = query->from; do { DBUG_PRINT("info",("spider from=%p", from)); - if (from->table->const_table) - continue; ++table_count; if (from->table->part_info) { @@ -1468,15 +1469,6 @@ group_by_handler *spider_create_group_by_handler( table_idx = 0; from = query->from; - while (from && from->table->const_table) - { - from = from->next_local; - } - if (!from) - { - /* all tables are const_table */ - goto skip_free_table_holder; - } #if defined(PARTITION_HAS_GET_CHILD_HANDLERS) if (from->table->part_info) { @@ -1512,8 +1504,6 @@ group_by_handler *spider_create_group_by_handler( } while ((from = from->next_local)) { - if (from->table->const_table) - continue; #if defined(PARTITION_HAS_GET_CHILD_HANDLERS) if (from->table->part_info) { @@ -1556,8 +1546,6 @@ group_by_handler *spider_create_group_by_handler( from = query->from; do { - if (from->table->const_table) - continue; #if defined(PARTITION_HAS_GET_CHILD_HANDLERS) if (from->table->part_info) { @@ -1701,10 +1689,6 @@ group_by_handler *spider_create_group_by_handler( goto skip_free_table_holder; from = query->from; - while (from->table->const_table) - { - from = from->next_local; - } #if defined(PARTITION_HAS_GET_CHILD_HANDLERS) if (from->table->part_info) { @@ -1777,8 +1761,6 @@ group_by_handler *spider_create_group_by_handler( while ((from = from->next_local)) { - if (from->table->const_table) - continue; fields->clear_conn_holder_from_conn(); #if defined(PARTITION_HAS_GET_CHILD_HANDLERS) From 52a5b16b5739cd06ba6e7238c29b4694909ba863 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 13 Oct 2023 17:16:57 +1100 Subject: [PATCH 268/477] MDEV-29963 MDEV-31357 Spider should clear its lock lists when locking fails Spider populates its lock lists (a hash) in store_lock(), and normally clears them in the actual lock_tables(). However, if lock_tables() fails, there's no reset_lock() method for storage engine handlers, which can cause bad things to happen. For example, if one of the table involved is dropped and recreated, or simply TRUNCATEd, when executing LOCK TABLES again, the lock lists would be queried again in store_lock(), which could cause access to freed space associated with the dropped table. --- .../spider/bugfix/r/mdev_29963.result | 43 +++++++++++++++ .../spider/bugfix/t/mdev_29963.test | 55 +++++++++++++++++++ storage/spider/spd_trx.cc | 8 +++ 3 files changed, 106 insertions(+) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result new file mode 100644 index 00000000000..17390346a99 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result @@ -0,0 +1,43 @@ +# +# MDEV-29963 SIGSEGV in spider_db_mbase::append_lock_tables on LOCK TABLES +# +for master_1 +for child2 +for child3 +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE TABLE t (a INT) ENGINE=Spider; +CREATE TABLE t2 (b INT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; +LOCK TABLES t AS a READ,t2 AS b LOW_PRIORITY WRITE,t2 AS c WRITE; +ERROR HY000: Unable to connect to foreign data source: localhost +DROP TABLE t2; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; +LOCK TABLES t2 WRITE; +ERROR HY000: Unable to connect to foreign data source: localhost +DROP TABLE t2,t; +CREATE TABLE t (a INT); +CREATE TABLE t1 (a INT) ENGINE=Spider; +CREATE TABLE t2 (b INT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; +LOCK TABLES t1 READ, t2 WRITE; +ERROR HY000: Unable to connect to foreign data source: localhost +DROP TABLE t2; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; +LOCK TABLES t2 WRITE; +UNLOCK TABLES; +DROP TABLE t, t1, t2; +CREATE TABLE t1 (c INT) ENGINE=Spider; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT="WRAPPER 'mysql',srv 'srv',TABLE 't1'"; +LOCK TABLES t1 WRITE,t2 WRITE; +ERROR HY000: Unable to connect to foreign data source: localhost +TRUNCATE t2; +ERROR HY000: Unable to connect to foreign data source: localhost +LOCK TABLES t2 AS o WRITE; +ERROR HY000: Unable to connect to foreign data source: localhost +drop table t1, t2; +drop server srv; +for master_1 +for child2 +for child3 +# +# end of test mdev_29963 +# diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test new file mode 100644 index 00000000000..ab7a4ded07c --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test @@ -0,0 +1,55 @@ +--echo # +--echo # MDEV-29963 SIGSEGV in spider_db_mbase::append_lock_tables on LOCK TABLES +--echo # +--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'); + +CREATE TABLE t (a INT) ENGINE=Spider; +CREATE TABLE t2 (b INT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +LOCK TABLES t AS a READ,t2 AS b LOW_PRIORITY WRITE,t2 AS c WRITE; +DROP TABLE t2; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +LOCK TABLES t2 WRITE; +DROP TABLE t2,t; + +# A less complex scenario +CREATE TABLE t (a INT); +CREATE TABLE t1 (a INT) ENGINE=Spider; +CREATE TABLE t2 (b INT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +LOCK TABLES t1 READ, t2 WRITE; +DROP TABLE t2; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; +LOCK TABLES t2 WRITE; +UNLOCK TABLES; +DROP TABLE t, t1, t2; + +# MDEV-31357 +CREATE TABLE t1 (c INT) ENGINE=Spider; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT="WRAPPER 'mysql',srv 'srv',TABLE 't1'"; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +LOCK TABLES t1 WRITE,t2 WRITE; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +TRUNCATE t2; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +LOCK TABLES t2 AS o WRITE; +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 mdev_29963 +--echo # diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index 311c78ccb5c..cfdbedee069 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -3462,6 +3462,14 @@ int spider_rollback( trx->bulk_access_conn_first = NULL; #endif + /* In case the rollback happens due to failure of LOCK TABLE, we + need to clear the list of tables to lock. */ + for (uint i= 0; i < trx->trx_conn_hash.records; i++) + { + conn= (SPIDER_CONN *) my_hash_element(&trx->trx_conn_hash, i); + conn->db_conn->reset_lock_table_hash(); + } + if (all || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { if (trx->trx_start) From 0381197855c58e339ab5034b871ea9c0c2d61522 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 20 Oct 2023 18:05:54 +1100 Subject: [PATCH 269/477] MDEV-30014 Spider should not second guess server when locking / unlocking This fixes MDEV-30014, MDEV-29456, MDEV-29667, and MDEV-30049. The server may ask storage engines to unlock when the original sql command is not UNLOCK. This patch makes sure that spider honours these requests, so that the server has the correct idea which tables are locked and which are not. MDEV-29456, MDEV-29667, MDEV-30049: a later LOCK statement would, as the first step, unlock locked tables and clear the OPTION_TABLE_LOCK bit in thd->variables.option_bits, as well as locked_tables_list, indicating no tables are locked. If Spider does not unlock because the sql command is not UNLOCK, and if after this the LOCK statement fails to lock any tables, these indications that no tables are locked remains, so a later UNLOCK TABLES; statement would not try to unlock any table. Causing later statements requiring mdl locks to hang on waiting until lock_wait_timeout (default 1h) has passed. MDEV-30014: when a LOCK statement tries to lock more than one tables, say t2 and t3 as in mdev_30014.test, and t2 succeeds but t3 fails, the sql layer would try to undo by unlocking t2, and again, if Spider does not honour this request, the sql layer would assume t2 has been unlocked, but later actions on t2 or t2's remote table could hang on waiting for the mdl. --- storage/spider/ha_spider.cc | 9 +--- .../spider/bugfix/r/mdev_29456.result | 41 +++++++++++++++ .../spider/bugfix/r/mdev_29667.result | 40 ++++++++++++++ .../spider/bugfix/r/mdev_30014.result | 38 ++++++++++++++ .../spider/bugfix/t/mdev_29456.test | 52 +++++++++++++++++++ .../mysql-test/spider/bugfix/t/mdev_29667.cnf | 3 ++ .../spider/bugfix/t/mdev_29667.test | 44 ++++++++++++++++ .../spider/bugfix/t/mdev_30014.test | 45 ++++++++++++++++ 8 files changed, 265 insertions(+), 7 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_29667.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_29667.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_29667.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index ac586479d8c..db49c20096f 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -1265,11 +1265,6 @@ int ha_spider::external_lock( #ifdef HA_CAN_BULK_ACCESS external_lock_cnt++; #endif - if ( - lock_type == F_UNLCK && - sql_command != SQLCOM_UNLOCK_TABLES - ) - DBUG_RETURN(0); if (store_error_num) DBUG_RETURN(store_error_num); #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) @@ -1306,7 +1301,7 @@ int ha_spider::external_lock( ) { if (sql_command == SQLCOM_TRUNCATE) DBUG_RETURN(0); - else if (sql_command != SQLCOM_UNLOCK_TABLES) + else if (lock_type != F_UNLCK) { DBUG_PRINT("info",("spider conns[%d]->join_trx=%u", roop_count, conns[roop_count]->join_trx)); @@ -1428,7 +1423,7 @@ int ha_spider::external_lock( } if (conns[roop_count]->table_lock == 2) conns[roop_count]->table_lock = 1; - } else if (sql_command == SQLCOM_UNLOCK_TABLES || + } else if (lock_type == F_UNLCK || spider_param_internal_unlock(thd) == 1) { if (conns[roop_count]->table_lock == 1) diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result new file mode 100644 index 00000000000..4d9095830d1 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result @@ -0,0 +1,41 @@ +# +# MDEV-29456 Spider hangs in 'Waiting for table metadata lock' state on CREATE TABLE after LOCK TABLES +# +for master_1 +for child2 +for child3 +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t1 (c int); +create table t2 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +CREATE TABLE t3 (c INT KEY) ENGINE=Spider; +LOCK TABLE t2 WRITE; +LOCK TABLE t3 WRITE; +ERROR HY000: Unable to connect to foreign data source: localhost +UNLOCK TABLES; +drop table t1, t2, t3; +CREATE TABLE t (c INT) ENGINE=InnoDB; +CREATE TABLE t1 (c INT) ENGINE=Spider; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; +LOCK TABLES t2 WRITE; +LOCK TABLES t1 READ; +ERROR HY000: Unable to connect to foreign data source: localhost +CREATE TABLE t (c INT) ENGINE=Spider; +ERROR 42S01: Table 't' already exists +drop table t, t1, t2; +CREATE TABLE t (c INT) ENGINE=InnoDB; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; +CREATE TABLE t3 (c INT) ENGINE=InnoDB; +LOCK TABLES t2 WRITE; +LOCK TABLES mysql.proc WRITE,mysql.user WRITE; +ERROR HY000: You can't combine write-locking of system tables with other tables or lock types +INSERT INTO t3 SELECT * FROM t; +drop table t, t2, t3; +drop server srv; +for master_1 +for child2 +for child3 +# +# end of test mdev_29456 +# diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29667.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29667.result new file mode 100644 index 00000000000..f2e90760ed4 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29667.result @@ -0,0 +1,40 @@ +# +# MDEV-29667 Server hangs on DROP DATABASE after failing LOCK TABLES on Spider table +# +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +connection child2_1; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +CREATE TABLE tbl_a ( +a INT +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +CREATE TABLE tbl_a ( +a INT +) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='table "tbl_a", srv "s_2_1"'; +CREATE TABLE tbl_b ( +a INT +) ENGINE=Spider DEFAULT CHARSET=utf8; +LOCK TABLES tbl_a WRITE; +LOCK TABLES tbl_b READ, tbl_a READ; +ERROR HY000: Unable to connect to foreign data source: localhost +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +# +# end of test mdev_29667 +# diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result new file mode 100644 index 00000000000..e1dca495047 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result @@ -0,0 +1,38 @@ +# +# MDEV-30014 heap-use-after-free in ha_spider::lock_tables(), highly sporadic SIGSEGV in intern_close_table +# +for master_1 +for child2 +for child3 +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t1 (c int); +create table t2 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +CREATE TABLE t3 (c INT KEY) ENGINE=Spider; +LOCK TABLE t2 WRITE,t3 WRITE; +ERROR HY000: Unable to connect to foreign data source: localhost +CREATE TABLE t4 (c INT) ENGINE=Spider; +FLUSH NO_WRITE_TO_BINLOG TABLES t4 WITH READ LOCK; +Warnings: +Error 1429 Unable to connect to foreign data source: localhost +Error 1429 Unable to connect to foreign data source: localhost +Error 1429 Unable to connect to foreign data source: localhost +Error 1429 Unable to connect to foreign data source: localhost +UNLOCK TABLES; +drop table t1, t2, t3, t4; +create table t1 (c int); +create table t2 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +CREATE TABLE t3 (c INT KEY) ENGINE=Spider; +LOCK TABLE t2 WRITE, t3 WRITE; +ERROR HY000: Unable to connect to foreign data source: localhost +UNLOCK TABLES; +drop table t1, t2, t3; +drop server srv; +for master_1 +for child2 +for child3 +# +# end of test mdev_30014 +# diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test new file mode 100644 index 00000000000..16291f82075 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test @@ -0,0 +1,52 @@ +--echo # +--echo # MDEV-29456 Spider hangs in 'Waiting for table metadata lock' state on CREATE TABLE after LOCK TABLES +--echo # +--source include/have_innodb.inc +--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'); + +create table t1 (c int); +create table t2 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +CREATE TABLE t3 (c INT KEY) ENGINE=Spider; +LOCK TABLE t2 WRITE; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +LOCK TABLE t3 WRITE; +UNLOCK TABLES; +drop table t1, t2, t3; + +CREATE TABLE t (c INT) ENGINE=InnoDB; +CREATE TABLE t1 (c INT) ENGINE=Spider; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; +LOCK TABLES t2 WRITE; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +LOCK TABLES t1 READ; +--error ER_TABLE_EXISTS_ERROR +CREATE TABLE t (c INT) ENGINE=Spider; +drop table t, t1, t2; + +# MDEV-30049 +CREATE TABLE t (c INT) ENGINE=InnoDB; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; +CREATE TABLE t3 (c INT) ENGINE=InnoDB; +LOCK TABLES t2 WRITE; +--error 1428 +LOCK TABLES mysql.proc WRITE,mysql.user WRITE; # ERROR 1428 (HY000): You can't combine write-locking of system tables with other tables or lock types +INSERT INTO t3 SELECT * FROM t; +drop table t, t2, t3; + +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 mdev_29456 +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29667.cnf b/storage/spider/mysql-test/spider/bugfix/t/mdev_29667.cnf new file mode 100644 index 00000000000..05dfd8a0bce --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29667.cnf @@ -0,0 +1,3 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29667.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29667.test new file mode 100644 index 00000000000..c96eb60efc5 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29667.test @@ -0,0 +1,44 @@ +--echo # +--echo # MDEV-29667 Server hangs on DROP DATABASE after failing LOCK TABLES on Spider table +--echo # +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +--connection child2_1 +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +eval CREATE TABLE tbl_a ( + a INT +) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; + +--connection master_1 +CREATE DATABASE auto_test_local; +USE auto_test_local; +eval CREATE TABLE tbl_a ( + a INT +) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='table "tbl_a", srv "s_2_1"'; +eval CREATE TABLE tbl_b ( + a INT +) $MASTER_1_ENGINE $MASTER_1_CHARSET; + +LOCK TABLES tbl_a WRITE; +--error 1429 +LOCK TABLES tbl_b READ, tbl_a READ; + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; + +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_query_log +--enable_result_log +--echo # +--echo # end of test mdev_29667 +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test new file mode 100644 index 00000000000..4dc3dafab24 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test @@ -0,0 +1,45 @@ +--echo # +--echo # MDEV-30014 heap-use-after-free in ha_spider::lock_tables(), highly sporadic SIGSEGV in intern_close_table +--echo # +--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'); + +create table t1 (c int); +create table t2 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +CREATE TABLE t3 (c INT KEY) ENGINE=Spider; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +LOCK TABLE t2 WRITE,t3 WRITE; +CREATE TABLE t4 (c INT) ENGINE=Spider; +FLUSH NO_WRITE_TO_BINLOG TABLES t4 WITH READ LOCK; +UNLOCK TABLES; + +drop table t1, t2, t3, t4; + +# This is a test case in MDEV-29456 but it is more like the above +# case. +create table t1 (c int); +create table t2 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +CREATE TABLE t3 (c INT KEY) ENGINE=Spider; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +LOCK TABLE t2 WRITE, t3 WRITE; +UNLOCK TABLES; +drop table t1, t2, t3; + +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 mdev_30014 +--echo # From f5fdb9cec52e415628c2b8a353641e425d720695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 17 Nov 2023 14:12:48 +0200 Subject: [PATCH 270/477] MDEV-16660: Increase the DEFAULT_THREAD_STACK for ASAN To allow cmake -DWITH_ASAN=ON to work out of the box when using newer compilers, we must increase the default thread stack size. By design, AddressSanitizer will allocate some "sentinel" areas in stack frames so that it can better catch buffer overflows, by trapping access to memory addresses that reside between stack-allocated variables. Apparently, some parameters related to this have been changed recently, possibly to allow -fsanitize=address to catch more errors. --- include/my_pthread.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/include/my_pthread.h b/include/my_pthread.h index 65498d185c5..8a9e5f17ef7 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -704,11 +704,19 @@ extern void my_mutex_end(void); We need to have at least 256K stack to handle calls to myisamchk_init() with the current number of keys and key parts. */ -#if defined(__SANITIZE_ADDRESS__) || defined(WITH_UBSAN) -#define DEFAULT_THREAD_STACK (383*1024L) /* 392192 */ -#else -#define DEFAULT_THREAD_STACK (292*1024L) /* 299008 */ -#endif +# if defined(__SANITIZE_ADDRESS__) || defined(WITH_UBSAN) +/* + Optimized WITH_ASAN=ON executables produced + by GCC 12.3.0, GCC 13.2.0, or clang 16.0.6 + would fail ./mtr main.1st when the stack size is 5 MiB. + The minimum is more than 6 MiB for CMAKE_BUILD_TYPE=RelWithDebInfo and + more than 8 MiB for CMAKE_BUILD_TYPE=Debug. + Let us add some safety margin. +*/ +# define DEFAULT_THREAD_STACK (10L<<20) +# else +# define DEFAULT_THREAD_STACK (292*1024L) /* 299008 */ +# endif #endif #define MY_PTHREAD_LOCK_READ 0 From eb1f8b291911fee931acfd8883b4d6876d8689ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 17 Nov 2023 15:07:51 +0200 Subject: [PATCH 271/477] MDEV-32027 Opening all .ibd files on InnoDB startup can be slow dict_find_max_space_id(): Return SELECT MAX(SPACE) FROM SYS_TABLES. dict_check_tablespaces_and_store_max_id(): In the normal case (no encryption plugin has been loaded and the change buffer is empty), invoke dict_find_max_space_id() and do not open any .ibd files. If a std::set has been specified, open the files whose tablespace ID is mentioned. Else, open all data files that are identified by SYS_TABLES records. fil_ibd_open(): Remove a call to os_file_get_last_error() that can report a misleading error, such as EINVAL inside my_realpath() that is not an actual error. This could be invoked when a data file is found but the FSP_SPACE_FLAGS are incorrect, such as is the case for table test.td in ./mtr --mysqld=--innodb-buffer-pool-dump-at-shutdown=0 innodb.table_flags buf_load(): If any tablespaces could not be found, invoke dict_check_tablespaces_and_store_max_id() on the missing tablespaces. dict_load_tablespace(): Try to load the tablespace unless it was found to be futile. This fixes failures related to FTS_*.ibd files for FULLTEXT INDEX. btr_cur_t::search_leaf(): Prevent a crash when the tablespace does not exist. This was caught by the test innodb_fts.fts_concurrent_insert when the change to dict_load_tablespaces() was not present. We modify a few tests to ensure that tables will not be loaded at startup. For some fault injection tests this means that the corrupted tables will not be loaded, because dict_load_tablespace() would perform stricter checks than dict_check_tablespaces_and_store_max_id(). Tested by: Matthias Leich Reviewed by: Thirunarayanan Balathandayuthapani --- .../innodb/r/row_format_redundant.result | 3 +- mysql-test/suite/innodb/r/table_flags.result | 12 +-- .../suite/innodb/t/row_format_redundant.opt | 2 + mysql-test/suite/innodb/t/table_flags.opt | 1 + mysql-test/suite/innodb/t/table_flags.test | 2 + mysql-test/suite/innodb_zip/r/restart.result | 37 --------- mysql-test/suite/innodb_zip/t/restart.opt | 7 +- storage/innobase/btr/btr0cur.cc | 26 +++--- storage/innobase/buf/buf0dump.cc | 18 +++- storage/innobase/dict/dict0load.cc | 82 +++++++++++-------- storage/innobase/fil/fil0fil.cc | 2 - storage/innobase/include/dict0load.h | 16 ++-- storage/innobase/srv/srv0start.cc | 12 +-- 13 files changed, 104 insertions(+), 116 deletions(-) diff --git a/mysql-test/suite/innodb/r/row_format_redundant.result b/mysql-test/suite/innodb/r/row_format_redundant.result index d95c37f18cc..e3356c633df 100644 --- a/mysql-test/suite/innodb/r/row_format_redundant.result +++ b/mysql-test/suite/innodb/r/row_format_redundant.result @@ -68,9 +68,8 @@ DROP TABLE t1; Warnings: Warning 1932 Table 'test.t1' doesn't exist in engine DROP TABLE t2,t3; -FOUND 6 /\[ERROR\] InnoDB: Table test/t1 in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=1 SYS_TABLES\.MIX_LEN=511\b/ in mysqld.1.err +FOUND 5 /\[ERROR\] InnoDB: Table test/t1 in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=1 SYS_TABLES\.MIX_LEN=511\b/ in mysqld.1.err # restart -ib_buffer_pool ib_logfile0 ibdata1 db.opt diff --git a/mysql-test/suite/innodb/r/table_flags.result b/mysql-test/suite/innodb/r/table_flags.result index 779990351c6..cc32472f39c 100644 --- a/mysql-test/suite/innodb/r/table_flags.result +++ b/mysql-test/suite/innodb/r/table_flags.result @@ -101,13 +101,9 @@ ERROR 42S02: Table 'test.tc' doesn't exist in engine SELECT * FROM tc; ERROR 42S02: Table 'test.tc' doesn't exist in engine SHOW CREATE TABLE td; -Table Create Table -td CREATE TABLE `td` ( - `a` int(11) NOT NULL, - PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC +ERROR HY000: Got error 194 "Tablespace is missing for a table" from storage engine InnoDB SELECT * FROM td; -a +ERROR HY000: Got error 194 "Tablespace is missing for a table" from storage engine InnoDB SHOW CREATE TABLE tz; Table Create Table tz CREATE TABLE `tz` ( @@ -122,8 +118,8 @@ a 42 SHOW CREATE TABLE tp; ERROR 42S02: Table 'test.tp' doesn't exist in engine -FOUND 5 /InnoDB: Table test/t[cp] in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649/ in mysqld.1.err -FOUND 2 /InnoDB: Table test/tr in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=65 SYS_TABLES\.MIX_LEN=4294967295\b/ in mysqld.1.err +FOUND 3 /InnoDB: Table test/t[cp] in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649/ in mysqld.1.err +FOUND 1 /InnoDB: Table test/tr in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=65 SYS_TABLES\.MIX_LEN=4294967295\b/ in mysqld.1.err Restoring SYS_TABLES clustered index root page (8) # restart: with restart_parameters SHOW CREATE TABLE tr; diff --git a/mysql-test/suite/innodb/t/row_format_redundant.opt b/mysql-test/suite/innodb/t/row_format_redundant.opt index c44c611ed60..d1d93da09fb 100644 --- a/mysql-test/suite/innodb/t/row_format_redundant.opt +++ b/mysql-test/suite/innodb/t/row_format_redundant.opt @@ -1 +1,3 @@ --innodb-checksum-algorithm=crc32 +--skip-innodb-fast-shutdown +--skip-innodb-buffer-pool-dump-at-shutdown diff --git a/mysql-test/suite/innodb/t/table_flags.opt b/mysql-test/suite/innodb/t/table_flags.opt index bca674950d2..8f6c7db5f01 100644 --- a/mysql-test/suite/innodb/t/table_flags.opt +++ b/mysql-test/suite/innodb/t/table_flags.opt @@ -1,2 +1,3 @@ --innodb-checksum-algorithm=crc32 --skip-innodb-read-only-compressed +--skip-innodb-buffer-pool-dump-at-shutdown diff --git a/mysql-test/suite/innodb/t/table_flags.test b/mysql-test/suite/innodb/t/table_flags.test index 34204ae11f4..511d3c241ba 100644 --- a/mysql-test/suite/innodb/t/table_flags.test +++ b/mysql-test/suite/innodb/t/table_flags.test @@ -157,7 +157,9 @@ SHOW CREATE TABLE tr; SHOW CREATE TABLE tc; --error ER_NO_SUCH_TABLE_IN_ENGINE SELECT * FROM tc; +--error ER_GET_ERRNO SHOW CREATE TABLE td; +--error ER_GET_ERRNO SELECT * FROM td; # This table was converted to NO_ROLLBACK due to the SYS_TABLES.TYPE change. SHOW CREATE TABLE tz; diff --git a/mysql-test/suite/innodb_zip/r/restart.result b/mysql-test/suite/innodb_zip/r/restart.result index eb1bfe67c5d..8bd3f73f8e0 100644 --- a/mysql-test/suite/innodb_zip/r/restart.result +++ b/mysql-test/suite/innodb_zip/r/restart.result @@ -527,15 +527,6 @@ Variable_name Value innodb_file_per_table ON === information_schema.innodb_sys_tablespaces and innodb_sys_datafiles === Space_Name Page_Size Zip_Size Path -test/t4_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t4_restart.ibd -test/t6_restart#p#p0 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t6_restart#p#p0.ibd -test/t6_restart#p#p1 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t6_restart#p#p1.ibd -test/t7_restart#p#p0#sp#s0 DEFAULT DEFAULT MYSQL_TMP_DIR/alt_dir/test/t7_restart#p#p0#sp#s0.ibd -test/t7_restart#p#p0#sp#s1 DEFAULT DEFAULT MYSQL_TMP_DIR/alt_dir/test/t7_restart#p#p0#sp#s1.ibd -test/t5_restart DEFAULT DEFAULT MYSQL_TMP_DIR/alt_dir/test/t5_restart.ibd -test/t6_restart#p#p2 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t6_restart#p#p2.ibd -test/t7_restart#p#p1#sp#s2 DEFAULT DEFAULT MYSQL_TMP_DIR/alt_dir/test/t7_restart#p#p1#sp#s2.ibd -test/t7_restart#p#p1#sp#s3 DEFAULT DEFAULT MYSQL_TMP_DIR/alt_dir/test/t7_restart#p#p1#sp#s3.ibd innodb_temporary DEFAULT DEFAULT MYSQLD_DATADIR/ibtmp1 SELECT count(*) FROM t5_restart; count(*) @@ -629,7 +620,6 @@ RENAME TABLE t6_restart TO t66_restart; RENAME TABLE t7_restart TO t77_restart; === information_schema.innodb_sys_tablespaces and innodb_sys_datafiles === Space_Name Page_Size Zip_Size Path -test/t4_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t4_restart.ibd test/t66_restart#p#p0 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t66_restart#p#p0.ibd test/t66_restart#p#p1 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t66_restart#p#p1.ibd test/t77_restart#p#p0#sp#s0 DEFAULT DEFAULT MYSQL_TMP_DIR/alt_dir/test/t77_restart#p#p0#sp#s0.ibd @@ -728,15 +718,6 @@ Variable_name Value innodb_file_per_table ON === information_schema.innodb_sys_tablespaces and innodb_sys_datafiles === Space_Name Page_Size Zip_Size Path -test/t4_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t4_restart.ibd -test/t66_restart#p#p0 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t66_restart#p#p0.ibd -test/t66_restart#p#p1 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t66_restart#p#p1.ibd -test/t77_restart#p#p0#sp#s0 DEFAULT DEFAULT MYSQL_TMP_DIR/alt_dir/test/t77_restart#p#p0#sp#s0.ibd -test/t77_restart#p#p0#sp#s1 DEFAULT DEFAULT MYSQL_TMP_DIR/alt_dir/test/t77_restart#p#p0#sp#s1.ibd -test/t55_restart DEFAULT DEFAULT MYSQL_TMP_DIR/alt_dir/test/t55_restart.ibd -test/t66_restart#p#p2 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t66_restart#p#p2.ibd -test/t77_restart#p#p1#sp#s2 DEFAULT DEFAULT MYSQL_TMP_DIR/alt_dir/test/t77_restart#p#p1#sp#s2.ibd -test/t77_restart#p#p1#sp#s3 DEFAULT DEFAULT MYSQL_TMP_DIR/alt_dir/test/t77_restart#p#p1#sp#s3.ibd innodb_temporary DEFAULT DEFAULT MYSQLD_DATADIR/ibtmp1 INSERT INTO t55_restart (SELECT 0, c2, c3, c4, c5 FROM t55_restart); SELECT count(*) FROM t55_restart; @@ -863,15 +844,6 @@ t77_restart#p#p1#sp#s3.ibd # restart === information_schema.innodb_sys_tablespaces and innodb_sys_datafiles === Space_Name Page_Size Zip_Size Path -test/t4_restart DEFAULT DEFAULT MYSQL_TMP_DIR/new_dir/test/t4_restart.ibd -test/t66_restart#p#p0 DEFAULT 2048 MYSQL_TMP_DIR/new_dir/test/t66_restart#p#p0.ibd -test/t66_restart#p#p1 DEFAULT 2048 MYSQL_TMP_DIR/new_dir/test/t66_restart#p#p1.ibd -test/t77_restart#p#p0#sp#s0 DEFAULT DEFAULT MYSQL_TMP_DIR/new_dir/test/t77_restart#p#p0#sp#s0.ibd -test/t77_restart#p#p0#sp#s1 DEFAULT DEFAULT MYSQL_TMP_DIR/new_dir/test/t77_restart#p#p0#sp#s1.ibd -test/t55_restart DEFAULT DEFAULT MYSQL_TMP_DIR/new_dir/test/t55_restart.ibd -test/t66_restart#p#p2 DEFAULT 2048 MYSQL_TMP_DIR/new_dir/test/t66_restart#p#p2.ibd -test/t77_restart#p#p1#sp#s2 DEFAULT DEFAULT MYSQL_TMP_DIR/new_dir/test/t77_restart#p#p1#sp#s2.ibd -test/t77_restart#p#p1#sp#s3 DEFAULT DEFAULT MYSQL_TMP_DIR/new_dir/test/t77_restart#p#p1#sp#s3.ibd innodb_temporary DEFAULT DEFAULT MYSQLD_DATADIR/ibtmp1 INSERT INTO t4_restart (SELECT 0, c2, c3, c4, c5 FROM t4_restart); SELECT count(*) FROM t4_restart; @@ -1002,15 +974,6 @@ t77_restart.par # restart === information_schema.innodb_sys_tablespaces and innodb_sys_datafiles === Space_Name Page_Size Zip_Size Path -test/t4_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t4_restart.ibd -test/t66_restart#p#p0 DEFAULT 2048 MYSQLD_DATADIR/test/t66_restart#p#p0.ibd -test/t66_restart#p#p1 DEFAULT 2048 MYSQLD_DATADIR/test/t66_restart#p#p1.ibd -test/t77_restart#p#p0#sp#s0 DEFAULT DEFAULT MYSQLD_DATADIR/test/t77_restart#p#p0#sp#s0.ibd -test/t77_restart#p#p0#sp#s1 DEFAULT DEFAULT MYSQLD_DATADIR/test/t77_restart#p#p0#sp#s1.ibd -test/t55_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t55_restart.ibd -test/t66_restart#p#p2 DEFAULT 2048 MYSQLD_DATADIR/test/t66_restart#p#p2.ibd -test/t77_restart#p#p1#sp#s2 DEFAULT DEFAULT MYSQLD_DATADIR/test/t77_restart#p#p1#sp#s2.ibd -test/t77_restart#p#p1#sp#s3 DEFAULT DEFAULT MYSQLD_DATADIR/test/t77_restart#p#p1#sp#s3.ibd innodb_temporary DEFAULT DEFAULT MYSQLD_DATADIR/ibtmp1 INSERT INTO t4_restart (SELECT 0, c2, c3, c4, c5 FROM t4_restart); SELECT count(*) FROM t4_restart; diff --git a/mysql-test/suite/innodb_zip/t/restart.opt b/mysql-test/suite/innodb_zip/t/restart.opt index d7564300c09..03fb84e94a6 100644 --- a/mysql-test/suite/innodb_zip/t/restart.opt +++ b/mysql-test/suite/innodb_zip/t/restart.opt @@ -1,2 +1,5 @@ ---loose-innodb-sys-tables ---loose-innodb-sys-tablespaces +--innodb-sys-tables +--innodb-sys-tablespaces +--skip-innodb-stats-persistent +--skip-innodb-buffer-pool-dump-at-shutdown +--skip-innodb-fast-shutdown diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 6f71ecee5e4..b05c9db787b 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -1155,6 +1155,19 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode, mtr_s_lock_index(index(), mtr); } + dberr_t err; + + if (!index()->table->space) + { + corrupted: + ut_ad("corrupted" == 0); // FIXME: remove this + err= DB_CORRUPTION; + func_exit: + if (UNIV_LIKELY_NULL(heap)) + mem_heap_free(heap); + return err; + } + const ulint zip_size= index()->table->space->zip_size(); /* Start with the root page. */ @@ -1168,7 +1181,6 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode, low_bytes= 0; ulint buf_mode= BUF_GET; search_loop: - dberr_t err; auto block_savepoint= mtr->get_savepoint(); buf_block_t *block= buf_page_get_gen(page_id, zip_size, rw_latch, guess, buf_mode, mtr, @@ -1180,10 +1192,7 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode, btr_decryption_failed(*index()); /* fall through */ default: - func_exit: - if (UNIV_LIKELY_NULL(heap)) - mem_heap_free(heap); - return err; + goto func_exit; case DB_SUCCESS: /* This must be a search to perform an insert, delete mark, or delete; try using the change buffer */ @@ -1250,12 +1259,7 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode, btr_page_get_index_id(block->page.frame) != index()->id || fil_page_get_type(block->page.frame) == FIL_PAGE_RTREE || !fil_page_index_page_check(block->page.frame)) - { - corrupted: - ut_ad("corrupted" == 0); // FIXME: remove this - err= DB_CORRUPTION; - goto func_exit; - } + goto corrupted; page_cur.block= block; ut_ad(block == mtr->at_savepoint(block_savepoint)); diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index 4703223adf4..f142263a0e4 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -33,7 +33,7 @@ Created April 08, 2011 Vasil Dimov #include "buf0rea.h" #include "buf0dump.h" -#include "dict0dict.h" +#include "dict0load.h" #include "os0file.h" #include "srv0srv.h" #include "srv0start.h" @@ -557,6 +557,22 @@ buf_load() if (!SHUTTING_DOWN()) { std::sort(dump, dump + dump_n); + std::set missing; + for (const page_id_t id : st_::span + (dump, dump_n)) { + missing.emplace(id.space()); + } + for (std::set::iterator i = missing.begin(); + i != missing.end(); ) { + auto j = i++; + if (fil_space_t* space = fil_space_t::get(*j)) { + space->release(); + missing.erase(j); + } + } + if (!missing.empty()) { + dict_check_tablespaces_and_store_max_id(&missing); + } } /* Avoid calling the expensive fil_space_t::get() for each diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 129a2539341..d79d3eab8c3 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -33,8 +33,8 @@ Created 4/24/1996 Heikki Tuuri #include "dict0boot.h" #include "dict0crea.h" #include "dict0dict.h" -#include "dict0mem.h" #include "dict0stats.h" +#include "ibuf0ibuf.h" #include "fsp0file.h" #include "fts0priv.h" #include "mach0data.h" @@ -867,18 +867,30 @@ err_exit: return READ_OK; } -/** Check each tablespace found in the data dictionary. -Then look at each table defined in SYS_TABLES that has a space_id > 0 -to find all the file-per-table tablespaces. +/** @return SELECT MAX(space) FROM sys_tables */ +static uint32_t dict_find_max_space_id(btr_pcur_t *pcur, mtr_t *mtr) +{ + uint32_t max_space_id= 0; -In a crash recovery we already have some tablespace objects created from -processing the REDO log. We will compare the -space_id information in the data dictionary to what we find in the -tablespace file. In addition, more validation will be done if recovery -was needed and force_recovery is not set. + for (const rec_t *rec= dict_startscan_system(pcur, mtr, dict_sys.sys_tables); + rec; rec= dict_getnext_system_low(pcur, mtr)) + if (!dict_sys_tables_rec_check(rec)) + { + ulint len; + const byte *field= + rec_get_nth_field_old(rec, DICT_FLD__SYS_TABLES__SPACE, &len); + ut_ad(len == 4); + max_space_id= std::max(max_space_id, mach_read_from_4(field)); + } -We also scan the biggest space id, and store it to fil_system. */ -void dict_check_tablespaces_and_store_max_id() + return max_space_id; +} + +/** Check MAX(SPACE) FROM SYS_TABLES and store it in fil_system. +Open each data file if an encryption plugin has been loaded. + +@param spaces set of tablespace files to open */ +void dict_check_tablespaces_and_store_max_id(const std::set *spaces) { ulint max_space_id = 0; btr_pcur_t pcur; @@ -890,6 +902,12 @@ void dict_check_tablespaces_and_store_max_id() dict_sys.lock(SRW_LOCK_CALL); + if (!spaces && ibuf.empty + && !encryption_key_id_exists(FIL_DEFAULT_ENCRYPTION_KEY)) { + max_space_id = dict_find_max_space_id(&pcur, &mtr); + goto done; + } + for (const rec_t *rec = dict_startscan_system(&pcur, &mtr, dict_sys.sys_tables); rec; rec = dict_getnext_system_low(&pcur, &mtr)) { @@ -921,14 +939,6 @@ void dict_check_tablespaces_and_store_max_id() continue; } - if (flags2 & DICT_TF2_DISCARDED) { - sql_print_information("InnoDB: Ignoring tablespace" - " for %.*s because " - "the DISCARD flag is set", - static_cast(len), field); - continue; - } - /* For tables or partitions using .ibd files, the flag DICT_TF2_USE_FILE_PER_TABLE was not set in MIX_LEN before MySQL 5.6.5. The flag should not have been @@ -941,6 +951,19 @@ void dict_check_tablespaces_and_store_max_id() continue; } + if (spaces && spaces->find(uint32_t(space_id)) + == spaces->end()) { + continue; + } + + if (flags2 & DICT_TF2_DISCARDED) { + sql_print_information("InnoDB: Ignoring tablespace" + " for %.*s because " + "the DISCARD flag is set", + static_cast(len), field); + continue; + } + const span name{field, len}; char* filepath = fil_make_filepath(nullptr, name, @@ -973,6 +996,7 @@ void dict_check_tablespaces_and_store_max_id() ut_free(filepath); } +done: mtr.commit(); fil_set_max_space_id_if_bigger(max_space_id); @@ -2248,22 +2272,10 @@ dict_load_tablespace( /* The tablespace may already be open. */ table->space = fil_space_for_table_exists_in_mem(table->space_id, table->flags); - if (table->space) { + if (table->space || table->file_unreadable) { return; } - if (ignore_err >= DICT_ERR_IGNORE_TABLESPACE) { - table->file_unreadable = true; - return; - } - - if (!(ignore_err & DICT_ERR_IGNORE_RECOVER_LOCK)) { - ib::error() << "Failed to find tablespace for table " - << table->name << " in the cache. Attempting" - " to load the tablespace with space id " - << table->space_id; - } - /* Use the remote filepath if needed. This parameter is optional in the call to fil_ibd_open(). If not supplied, it will be built from the table->name. */ @@ -2286,6 +2298,12 @@ dict_load_tablespace( if (!table->space) { /* We failed to find a sensible tablespace file */ table->file_unreadable = true; + + if (!(ignore_err & DICT_ERR_IGNORE_RECOVER_LOCK)) { + sql_print_error("InnoDB: Failed to load tablespace " + ULINTPF " for table %s", + table->space_id, table->name); + } } ut_free(filepath); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 02203ba3d7b..1e0b7a9c8c5 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -2221,8 +2221,6 @@ func_exit: goto corrupted; } - os_file_get_last_error(operation_not_for_export, - !operation_not_for_export); if (!operation_not_for_export) { goto corrupted; } diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h index f7d33d5b43b..3143aafdc6b 100644 --- a/storage/innobase/include/dict0load.h +++ b/storage/innobase/include/dict0load.h @@ -35,22 +35,16 @@ Created 4/24/1996 Heikki Tuuri #include "btr0types.h" #include +#include /** A stack of table names related through foreign key constraints */ typedef std::deque > dict_names_t; -/** Check each tablespace found in the data dictionary. -Then look at each table defined in SYS_TABLES that has a space_id > 0 -to find all the file-per-table tablespaces. +/** Check MAX(SPACE) FROM SYS_TABLES and store it in fil_system. +Open each data file if an encryption plugin has been loaded. -In a crash recovery we already have some tablespace objects created from -processing the REDO log. We will compare the -space_id information in the data dictionary to what we find in the -tablespace file. In addition, more validation will be done if recovery -was needed and force_recovery is not set. - -We also scan the biggest space id, and store it to fil_system. */ -void dict_check_tablespaces_and_store_max_id(); +@param spaces set of tablespace files to open */ +void dict_check_tablespaces_and_store_max_id(const std::set *spaces); /** Make sure the data_file_name is saved in dict_table_t if needed. @param[in,out] table Table object */ diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 96b6f2c83df..761330f59c9 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1819,21 +1819,13 @@ file_checked: } if (srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) { - /* The following call is necessary for the insert + /* The following call is necessary for the change buffer to work with multiple tablespaces. We must know the mapping between space id's and .ibd file names. - In a crash recovery, we check that the info in data - dictionary is consistent with what we already know - about space id's from the calls to fil_ibd_load(). - - In a normal startup, we create the space objects for - every table in the InnoDB data dictionary that has - an .ibd file. - We also determine the maximum tablespace id used. */ - dict_check_tablespaces_and_store_max_id(); + dict_check_tablespaces_and_store_max_id(nullptr); } if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO From c42aadc388f9c55c9c9b9b3abd262cba9f51ad9d Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 15 Nov 2023 08:11:35 -0800 Subject: [PATCH 272/477] MDEV-32628: Cryptic ERROR message & inconsistent behavior on incorrect SHOW BINLOG EVENTS FROM ... Calling SHOW BINLOG EVENTS FROM with an invalid offset writes error messages into the server log about invalid reads. The read errors that occur from this command should only be relayed back to the user though, and not written into the server log. This is because they are read-only and have no impact on server operation, and the client only need be informed to correct the parameter. This patch fixes this by omitting binary log read errors from the server when the invocation happens from SHOW BINLOG EVENTS. Additionally, redundant error messages are omitted when calling the string based read_log_event from the IO_Cache based read_log_event, as the later already will report the error of the former. Reviewed By: ============ Kristian Nielsen Andrei Elkin --- ...binlog_events_invalid_offset_silent.result | 21 ++++++++ ...w_binlog_events_invalid_offset_silent.test | 53 +++++++++++++++++++ sql/log_event.cc | 36 +++++++++---- sql/log_event.h | 6 ++- sql/sql_repl.cc | 8 ++- 5 files changed, 110 insertions(+), 14 deletions(-) create mode 100644 mysql-test/suite/binlog/r/binlog_show_binlog_events_invalid_offset_silent.result create mode 100644 mysql-test/suite/binlog/t/binlog_show_binlog_events_invalid_offset_silent.test diff --git a/mysql-test/suite/binlog/r/binlog_show_binlog_events_invalid_offset_silent.result b/mysql-test/suite/binlog/r/binlog_show_binlog_events_invalid_offset_silent.result new file mode 100644 index 00000000000..ec86cc8ea16 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_show_binlog_events_invalid_offset_silent.result @@ -0,0 +1,21 @@ +# +# Initialize test data +set @save_master_verify_checksum = @@global.master_verify_checksum; +set @@global.master_verify_checksum = 1; +create table t1 (a int); +insert into t1 values (1); +insert into t1 values (2); +SHOW BINLOG EVENTS FROM invalid_pos; +ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Wrong offset or I/O error +include/assert_grep.inc [Ensure the client error is not in the server log] +SHOW BINLOG EVENTS FROM 500; +ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Wrong offset or I/O error +include/assert_grep.inc [Ensure the client error is not in the server log] +SHOW BINLOG EVENTS FROM 498; +ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Wrong offset or I/O error +include/assert_grep.inc [Ensure the client error is not in the server log] +include/assert_grep.inc [Ensure there is not a specific checksum failure error] +# +# Cleanup +set @@global.master_verify_checksum = @save_master_verify_checksum; +drop table t1; diff --git a/mysql-test/suite/binlog/t/binlog_show_binlog_events_invalid_offset_silent.test b/mysql-test/suite/binlog/t/binlog_show_binlog_events_invalid_offset_silent.test new file mode 100644 index 00000000000..d3b31596051 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_show_binlog_events_invalid_offset_silent.test @@ -0,0 +1,53 @@ +# +# Ensure that calling SHOW BINLOG EVENTS FROM with an invalid offset +# will not result in error messages in the server log. That is, this call is a +# read operation for a user, and if it fails due to invalid usage, that is not +# a server error, but only one to report to the user. +# +# References: +# MDEV-32628: Cryptic ERROR message & inconsistent behavior on incorrect +# SHOW BINLOG EVENTS FROM ... +# +--source include/have_binlog_format_row.inc + +--echo # +--echo # Initialize test data +set @save_master_verify_checksum = @@global.master_verify_checksum; +set @@global.master_verify_checksum = 1; +create table t1 (a int); +insert into t1 values (1); +--let $middle_binlog_pos= query_get_value(SHOW BINARY LOGS, File_size, 1) +insert into t1 values (2); + +--let $assert_text= Ensure the client error is not in the server log +--let $assert_select= Error in Log_event +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let $assert_count= 0 +--let $assert_only_after = CURRENT_TEST: + + +# Pre MDEV-32628, this would write an event truncated error in the logs +--let $invalid_pos= `SELECT $middle_binlog_pos - 1` +--replace_result $invalid_pos invalid_pos +--error 1220 +--eval SHOW BINLOG EVENTS FROM $invalid_pos +--source include/assert_grep.inc + +# Pre MDEV-32628, this would write an event too big error in the logs +--error 1220 +SHOW BINLOG EVENTS FROM 500; +--source include/assert_grep.inc + + +# Pre MDEV-32628, this would write a checksum verification failed error in the logs +--error 1220 +SHOW BINLOG EVENTS FROM 498; +--source include/assert_grep.inc +--let $assert_text= Ensure there is not a specific checksum failure error +--let $assert_select= Replication event checksum verification failed while reading from a log file +--source include/assert_grep.inc + +--echo # +--echo # Cleanup +set @@global.master_verify_checksum = @save_master_verify_checksum; +drop table t1; diff --git a/sql/log_event.cc b/sql/log_event.cc index 10bf569d636..6a59a021efc 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1916,7 +1916,8 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, Log_event* Log_event::read_log_event(IO_CACHE* file, const Format_description_log_event *fdle, - my_bool crc_check) + my_bool crc_check, + my_bool print_errors) { DBUG_ENTER("Log_event::read_log_event(IO_CACHE*,Format_description_log_event*...)"); DBUG_ASSERT(fdle != 0); @@ -1955,8 +1956,12 @@ Log_event* Log_event::read_log_event(IO_CACHE* file, goto err; } + /* + print_errors is false to prevent redundant error messages cluttering up the + log, as it will be printed below (if _our_ print_errors is true) + */ if ((res= read_log_event(event.ptr(), event.length(), - &error, fdle, crc_check))) + &error, fdle, crc_check, false))) res->register_temp_buf(event.release(), true); err: @@ -1967,13 +1972,7 @@ err: if (force_opt) DBUG_RETURN(new Unknown_log_event()); #endif - if (event.length() >= OLD_HEADER_LEN) - sql_print_error("Error in Log_event::read_log_event(): '%s'," - " data_len: %lu, event_type: %u", error, - (ulong) uint4korr(&event[EVENT_LEN_OFFSET]), - (uint) (uchar)event[EVENT_TYPE_OFFSET]); - else - sql_print_error("Error in Log_event::read_log_event(): '%s'", error); + /* The SQL slave thread will check if file->error<0 to know if there was an I/O error. Even if there is no "low-level" I/O errors @@ -1983,6 +1982,19 @@ err: only corrupt the slave's databases. So stop. */ file->error= -1; + +#ifndef MYSQL_CLIENT + if (!print_errors) + DBUG_RETURN(res); +#endif + + if (event.length() >= OLD_HEADER_LEN) + sql_print_error("Error in Log_event::read_log_event(): '%s'," + " data_len: %lu, event_type: %u", error, + (ulong) uint4korr(&event[EVENT_LEN_OFFSET]), + (uint) (uchar)event[EVENT_TYPE_OFFSET]); + else + sql_print_error("Error in Log_event::read_log_event(): '%s'", error); } DBUG_RETURN(res); } @@ -1996,7 +2008,8 @@ err: Log_event* Log_event::read_log_event(const char* buf, uint event_len, const char **error, const Format_description_log_event *fdle, - my_bool crc_check) + my_bool crc_check, + my_bool print_errors) { Log_event* ev; enum enum_binlog_checksum_alg alg; @@ -2065,7 +2078,8 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, DBUG_RETURN(NULL); #else *error= ER_THD_OR_DEFAULT(current_thd, ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE); - sql_print_error("%s", *error); + if (print_errors) + sql_print_error("%s", *error); DBUG_RETURN(NULL); #endif } diff --git a/sql/log_event.h b/sql/log_event.h index 5cd303e288c..79e24f15751 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1322,7 +1322,8 @@ public: static Log_event* read_log_event(IO_CACHE* file, const Format_description_log_event *description_event, - my_bool crc_check); + my_bool crc_check, + my_bool print_errors= 1); /** Reads an event from a binlog or relay log. Used by the dump thread @@ -1465,7 +1466,8 @@ public: static Log_event* read_log_event(const char* buf, uint event_len, const char **error, const Format_description_log_event - *description_event, my_bool crc_check); + *description_event, my_bool crc_check, + my_bool print_errors= 1); /** Returns the human readable name of the given event type. */ diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 0d2e61f7f59..437c594450d 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -4208,11 +4208,17 @@ bool mysql_show_binlog_events(THD* thd) } } + /* + Omit error messages from server log in Log_event::read_log_event. That + is, we only need to notify the client to correct their 'from' offset; + writing about this in the server log would be confusing as it isn't + related to server operational status. + */ for (event_count = 0; (ev = Log_event::read_log_event(&log, description_event, (opt_master_verify_checksum || - verify_checksum_once))); ) + verify_checksum_once), false)); ) { if (event_count >= limit_start && ev->net_send(protocol, linfo.log_file_name, pos)) From d95fa7e33279c6c6849eb053d85f1faa1c77e269 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 17 Nov 2023 15:01:38 +0100 Subject: [PATCH 273/477] MDEV-32168: slave_error_param condition is never checked from the wait_for_slave_param.inc Fix a start/stop race that causes occasional test failure after more the more strict error check of MDEV-32168. Signed-off-by: Kristian Nielsen --- mysql-test/suite/rpl/r/rpl_row_until.result | 4 +++- mysql-test/suite/rpl/t/rpl_row_until.test | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_row_until.result b/mysql-test/suite/rpl/r/rpl_row_until.result index 82268ce72eb..d5085a4feaf 100644 --- a/mysql-test/suite/rpl/r/rpl_row_until.result +++ b/mysql-test/suite/rpl/r/rpl_row_until.result @@ -51,7 +51,9 @@ ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UN START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', MASTER_LOG_POS=MASTER_LOG_POS; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=MASTER_LOG_POS; -include/stop_slave.inc +include/wait_for_slave_io_to_start.inc +include/wait_for_slave_sql_to_stop.inc +include/stop_slave_io.inc RESET SLAVE; include/start_slave.inc include/rpl_reset.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_until.test b/mysql-test/suite/rpl/t/rpl_row_until.test index 478c2206a5a..5825d56f487 100644 --- a/mysql-test/suite/rpl/t/rpl_row_until.test +++ b/mysql-test/suite/rpl/t/rpl_row_until.test @@ -101,7 +101,12 @@ START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', MASTER_LOG_POS=561; --replace_result 740 MASTER_LOG_POS START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=740; ---source include/stop_slave.inc +# Explicit wait for slave thread start and then stop. Otherwise the STOP SLAVE +# command can abort the slave connecting to the master, and an error state +# left which makes stop_slave.inc throw an error. +--source include/wait_for_slave_io_to_start.inc +--source include/wait_for_slave_sql_to_stop.inc +--source include/stop_slave_io.inc RESET SLAVE; --source include/start_slave.inc From 17430d94d788d76dc9356362803c00c031ed15cf Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 17 Nov 2023 16:16:11 +0100 Subject: [PATCH 274/477] MDEV-32168: slave_error_param condition is never checked from the wait_for_slave_param.inc Test rpl.show_status_stop_slave_race-7126 now fails sporadically because it is expected to sometimes (but not always) leave an error condition after slave stop. Fix by explicitly allowing the error condition in this case. Signed-off-by: Kristian Nielsen --- mysql-test/include/wait_for_slave_io_to_stop.inc | 13 ++++++++++++- mysql-test/include/wait_for_slave_sql_to_stop.inc | 13 ++++++++++++- .../rpl/t/show_status_stop_slave_race-7126.test | 3 +++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/mysql-test/include/wait_for_slave_io_to_stop.inc b/mysql-test/include/wait_for_slave_io_to_stop.inc index d25c2ac071d..0ad18ffefa2 100644 --- a/mysql-test/include/wait_for_slave_io_to_stop.inc +++ b/mysql-test/include/wait_for_slave_io_to_stop.inc @@ -21,6 +21,14 @@ # $slave_timeout # See include/wait_for_slave_param.inc. # +# $rpl_allow_error +# By default, this file fails if there is an error in the IO +# thread. However, if an error in the IO thread is possible and allowed, +# setting $rpl_allow_error=1 will prevent this file from failing if +# there is an error in the IO thread. +# (If an error is _always_ expected, a better alternative might be to +# use wait_for_slave_io_error.inc instead of this file). +# # $rpl_debug # See include/rpl_init.inc @@ -31,7 +39,10 @@ --let $slave_param= Slave_IO_Running --let $slave_param_value= No ---let $slave_error_param= Last_IO_Errno +if (!$rpl_allow_error) +{ + --let $slave_error_param= Last_IO_Errno +} --source include/wait_for_slave_param.inc --let $slave_error_param= diff --git a/mysql-test/include/wait_for_slave_sql_to_stop.inc b/mysql-test/include/wait_for_slave_sql_to_stop.inc index 492b3237be5..0a05464ce42 100644 --- a/mysql-test/include/wait_for_slave_sql_to_stop.inc +++ b/mysql-test/include/wait_for_slave_sql_to_stop.inc @@ -21,6 +21,14 @@ # $slave_timeout # See include/wait_for_slave_param.inc # +# $rpl_allow_error +# By default, this file fails if there is an error in the SQL +# thread. However, if an error in the SQL thread is possible and allowed, +# setting $rpl_allow_error=1 will prevent this file from failing if +# there is an error in the SQL thread. +# (If an error is _always_ expected, a better alternative might be to +# use wait_for_slave_sql_error.inc instead of this file). +# # $rpl_debug # See include/rpl_init.inc @@ -31,7 +39,10 @@ --let $slave_param= Slave_SQL_Running --let $slave_param_value= No ---let $slave_error_param= Last_SQL_Errno +if (!$rpl_allow_error) +{ + --let $slave_error_param= Last_SQL_Errno +} --source include/wait_for_slave_param.inc --let $slave_error_param= diff --git a/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test b/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test index 12794dbd898..cd0f8aad106 100644 --- a/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test +++ b/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test @@ -15,6 +15,9 @@ call mtr.add_suppression("Master is configured to log replication events"); # All done. --connection slave +# The parallel START SLAVE can leave an error condition if the last START was +# aborted by the master due to conflicting server_id from multiple connections. +--let $rpl_allow_error= 1 --source include/wait_for_slave_to_stop.inc start slave; From 30ec1b3e78b0bf866f4e8b591a7a99e9ed38fbbc Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 17 Nov 2023 16:35:04 +0100 Subject: [PATCH 275/477] MDEV-32168: slave_error_param condition is never checked from the wait_for_slave_param.inc Fix sporadic test failures in rpl.rpl_set_statement_default_master and rpl.rpl_slave_load_tmpdir_not_exist. A race between START and STOP SLAVE could leave an error condition that causes test failure after MDEV-32168. Signed-off-by: Kristian Nielsen --- mysql-test/suite/rpl/r/rpl_set_statement_default_master.result | 1 + mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result | 1 + mysql-test/suite/rpl/t/rpl_set_statement_default_master.test | 1 + mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test | 1 + 4 files changed, 4 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_set_statement_default_master.result b/mysql-test/suite/rpl/r/rpl_set_statement_default_master.result index 828e171548d..46f5a7c927e 100644 --- a/mysql-test/suite/rpl/r/rpl_set_statement_default_master.result +++ b/mysql-test/suite/rpl/r/rpl_set_statement_default_master.result @@ -14,6 +14,7 @@ RESET SLAVE ALL; CHANGE MASTER 'm1' TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_MYPORT, MASTER_USER='root'; SET STATEMENT default_master_connection = 'm1' FOR START SLAVE; set default_master_connection = 'm1'; +include/wait_for_slave_to_start.inc stop slave; include/wait_for_slave_to_stop.inc reset slave all; diff --git a/mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result b/mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result index 249f3514c8a..e9a96fc41e1 100644 --- a/mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result +++ b/mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result @@ -4,6 +4,7 @@ connection slave; START SLAVE; call mtr.add_suppression("Slave SQL.*Unable to use slave.s temporary directory"); include/wait_for_slave_sql_error.inc [errno=12] +include/wait_for_slave_io_to_start.inc include/stop_slave_io.inc RESET SLAVE; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_set_statement_default_master.test b/mysql-test/suite/rpl/t/rpl_set_statement_default_master.test index 106cb4547f4..d30da61bee6 100644 --- a/mysql-test/suite/rpl/t/rpl_set_statement_default_master.test +++ b/mysql-test/suite/rpl/t/rpl_set_statement_default_master.test @@ -26,6 +26,7 @@ eval CHANGE MASTER 'm1' TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, SET STATEMENT default_master_connection = 'm1' FOR START SLAVE; set default_master_connection = 'm1'; +--source include/wait_for_slave_to_start.inc stop slave; --source include/wait_for_slave_to_stop.inc reset slave all; diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test index 16dcd8ecbd3..89b7c7f1744 100644 --- a/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test +++ b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test @@ -15,6 +15,7 @@ call mtr.add_suppression("Slave SQL.*Unable to use slave.s temporary directory") --let $slave_sql_errno= 12 source include/wait_for_slave_sql_error.inc; +--source include/wait_for_slave_io_to_start.inc --source include/stop_slave_io.inc RESET SLAVE; From 7e394d0b4a1e84927c3507c6d3c17ce58ce35182 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 17 Nov 2023 16:54:16 +0100 Subject: [PATCH 276/477] MDEV-32168: slave_error_param condition is never checked from the wait_for_slave_param.inc Fix sporadic test failure in rpl.rpl_ssl1. The test incorrectly did a STOP SLAVE too early, which could race with the expected 'Access denied' error. Signed-off-by: Kristian Nielsen --- mysql-test/suite/rpl/r/rpl_ssl1.result | 2 +- mysql-test/suite/rpl/t/rpl_ssl1.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_ssl1.result b/mysql-test/suite/rpl/r/rpl_ssl1.result index 7cecabc6aac..0cb21716e75 100644 --- a/mysql-test/suite/rpl/r/rpl_ssl1.result +++ b/mysql-test/suite/rpl/r/rpl_ssl1.result @@ -14,8 +14,8 @@ insert into t1 values (1); connection slave; select * from t1; t -stop slave; include/wait_for_slave_io_error.inc [errno=1045] +include/stop_slave_sql.inc change master to master_ssl=1 , master_ssl_ca ='MYSQL_TEST_DIR/std_data/cacert.pem', master_ssl_cert='MYSQL_TEST_DIR/std_data/client-cert.pem', master_ssl_key='MYSQL_TEST_DIR/std_data/client-key.pem'; start slave; include/wait_for_slave_to_start.inc diff --git a/mysql-test/suite/rpl/t/rpl_ssl1.test b/mysql-test/suite/rpl/t/rpl_ssl1.test index 3a4958857e2..04f6cfffa6c 100644 --- a/mysql-test/suite/rpl/t/rpl_ssl1.test +++ b/mysql-test/suite/rpl/t/rpl_ssl1.test @@ -29,9 +29,9 @@ connection slave; select * from t1; #showing that replication could work with ssl params -stop slave; --let $slave_io_errno=1045 --source include/wait_for_slave_io_error.inc +--source include/stop_slave_sql.inc --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR eval change master to master_ssl=1 , master_ssl_ca ='$MYSQL_TEST_DIR/std_data/cacert.pem', master_ssl_cert='$MYSQL_TEST_DIR/std_data/client-cert.pem', master_ssl_key='$MYSQL_TEST_DIR/std_data/client-key.pem'; From 0258ad545a27b53c831a4a6498261f4eb2f34657 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 17 Nov 2023 17:26:44 +0100 Subject: [PATCH 277/477] MDEV-32168: slave_error_param condition is never checked from the wait_for_slave_param.inc Fix wrong change to rpl.rpl_shutdown_wait_slaves. After shutting down the master, slaves may or may not succeed in reconnecting depending on the timing on their reconnect relative to master restart. So don't assume all IO threads will be running, just restart any slave that needs it. Signed-off-by: Kristian Nielsen --- mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc | 4 ---- .../suite/rpl/r/rpl_shutdown_wait_semisync_slaves.result | 3 --- mysql-test/suite/rpl/r/rpl_shutdown_wait_slaves.result | 3 --- 3 files changed, 10 deletions(-) diff --git a/mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc b/mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc index 964eb3e0262..f9c007b44ab 100644 --- a/mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc +++ b/mysql-test/suite/rpl/include/rpl_shutdown_wait_slaves.inc @@ -80,21 +80,17 @@ DROP TABLE t1; --connection server_2 --disable_warnings --let rpl_allow_error=1 ---source include/wait_for_slave_io_to_start.inc - --source include/start_slave.inc --enable_warnings --connection server_3 --disable_warnings --let rpl_allow_error=1 ---source include/wait_for_slave_io_to_start.inc --source include/start_slave.inc --enable_warnings --connection server_4 --disable_warnings --let rpl_allow_error=1 ---source include/wait_for_slave_io_to_start.inc --source include/start_slave.inc --enable_warnings diff --git a/mysql-test/suite/rpl/r/rpl_shutdown_wait_semisync_slaves.result b/mysql-test/suite/rpl/r/rpl_shutdown_wait_semisync_slaves.result index 6837ca60733..cecc3daf340 100644 --- a/mysql-test/suite/rpl/r/rpl_shutdown_wait_semisync_slaves.result +++ b/mysql-test/suite/rpl/r/rpl_shutdown_wait_semisync_slaves.result @@ -34,13 +34,10 @@ connection server_1; connection server_1; DROP TABLE t1; connection server_2; -include/wait_for_slave_io_to_start.inc include/start_slave.inc connection server_3; -include/wait_for_slave_io_to_start.inc include/start_slave.inc connection server_4; -include/wait_for_slave_io_to_start.inc include/start_slave.inc connection server_2; include/stop_slave.inc diff --git a/mysql-test/suite/rpl/r/rpl_shutdown_wait_slaves.result b/mysql-test/suite/rpl/r/rpl_shutdown_wait_slaves.result index f4084bb3ecf..3b238332462 100644 --- a/mysql-test/suite/rpl/r/rpl_shutdown_wait_slaves.result +++ b/mysql-test/suite/rpl/r/rpl_shutdown_wait_slaves.result @@ -21,12 +21,9 @@ connection server_1; connection server_1; DROP TABLE t1; connection server_2; -include/wait_for_slave_io_to_start.inc include/start_slave.inc connection server_3; -include/wait_for_slave_io_to_start.inc include/start_slave.inc connection server_4; -include/wait_for_slave_io_to_start.inc include/start_slave.inc include/rpl_end.inc From 36680b648aab158555efbde8bf1ec30e9a2ed9c9 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 17 Nov 2023 18:20:32 +0100 Subject: [PATCH 278/477] MDEV-20523: rpl.create_or_replace_mix, rpl.create_or_replace_statement failed in buildbot with wrong result Wait for the disconnect of the other connection to complete, before running SHOW BINLOG EVENTS. Otherwise the DROP TEMPORARY TABLE that is binlogged during disconnect may not have appeared yet depending on thread scheduling. Signed-off-by: Kristian Nielsen --- mysql-test/suite/rpl/t/create_or_replace.inc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mysql-test/suite/rpl/t/create_or_replace.inc b/mysql-test/suite/rpl/t/create_or_replace.inc index 35a6ead60ca..c07356f8b17 100644 --- a/mysql-test/suite/rpl/t/create_or_replace.inc +++ b/mysql-test/suite/rpl/t/create_or_replace.inc @@ -212,12 +212,19 @@ set @@session.binlog_format=default; drop temporary table if exists t9; --connect(con1,localhost,root,,) +--let $conid = `SELECT CONNECTION_ID()` set session binlog_format=default; create temporary table t9 (i int); --echo *** Must be no DROP logged for t9 when there was no CREATE, at disconnect too *** --disconnect con1 --connection server_1 +# The disconnect runs asynchroneously. Wait for it to complete, otherwise the +# DROP TEMPORARY TABLE may not have been binlogged yet when SHOW BINLOG EVENTS +# is run. +--let $wait_condition= SELECT COUNT(*)=0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID=$conid +--source include/wait_condition.inc + --source include/show_binlog_events.inc # Clean up From 2c1345ab278962caf4902cc69a9517589a8afdbc Mon Sep 17 00:00:00 2001 From: Rex Date: Fri, 17 Nov 2023 13:33:07 +1200 Subject: [PATCH 279/477] MDEV-31995 Fix2 allocate memory in mem_root properly. Lex_ident_sys had no new operator and was used incorrectly in save_item_list_names(), so leaked memory. --- sql/sql_lex.cc | 5 +++-- sql/sql_lex.h | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 582494a0fd6..2e8bf40003e 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -10697,8 +10697,9 @@ bool st_select_lex::save_item_list_names(THD *thd) while ((item= li++)) { - if (unlikely(orig_names_of_item_list_elems->push_back( - new Lex_ident_sys(item->name.str, item->name.length), thd->mem_root))) + Lex_ident_sys *name= new (thd->mem_root) Lex_ident_sys(thd, &item->name); + if (unlikely(!name || + orig_names_of_item_list_elems->push_back(name, thd->mem_root))) { if (arena) thd->restore_active_arena(arena, &backup); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 97be0571903..0f2e096fdc6 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -143,6 +143,11 @@ public: struct Lex_ident_sys_st: public LEX_CSTRING { public: + static void *operator new(size_t size, MEM_ROOT *mem_root) throw () + { return alloc_root(mem_root, size); } + static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } + static void operator delete(void *ptr, MEM_ROOT *mem_root) {} + bool copy_ident_cli(THD *thd, const Lex_ident_cli_st *str); bool copy_keyword(THD *thd, const Lex_ident_cli_st *str); bool copy_sys(THD *thd, const LEX_CSTRING *str); @@ -176,6 +181,10 @@ public: LEX_CSTRING tmp= {name, length}; set_valid_utf8(&tmp); } + Lex_ident_sys(THD *thd, const LEX_CSTRING *str) + { + set_valid_utf8(str); + } Lex_ident_sys & operator=(const Lex_ident_sys_st &name) { Lex_ident_sys_st::operator=(name); From 2323483528fbc5116c2990a208afddd775ee0e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 24 Oct 2023 09:47:46 +0300 Subject: [PATCH 280/477] MDEV-31953 madvise(..., MADV_FREE) is causing a performance regression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit buf_page_t::set_os_unused(): Remove the system call that had been added in commit 16c9718758cb3bbff76672405d4ce1bce6da6c6f and revised in commit c1fd082e9c7369f4511eb5a52e58cb15489caa74 for Microsoft Windows. buf_pool_t::garbage_collect(): A new function to collect any garbage from the InnoDB buffer pool that can be removed without writing any log or data files. This will also invoke madvise() for all of buf_pool.free. To trigger this the following MDEV is implemented: MDEV-24670 avoid OOM by linux kernel co-operative memory management To avoid frequent triggers that caused the MDEV-31953 regression, while still preserving the 10.11 functionality of non-greedy kernel memory usage, memory triggers are used. On the triggering of memory pressure, if supported in the Linux kernel, trigger the garbage collection of the innodb buffer pool. The hard coded triggers occur where there is: * some memory pressure in 5 of the last 10 seconds * a full stall on memory pressure for 10ms in the last 2 seconds The kernel will trigger only one in each of these time windows. To avoid mariadb being in a constant state of memory garbage collection, this has been limited to once per minute. For a small set of kernels in 2023 (6.5, 6.6), there was a limit requiring CAP_SYS_RESOURCE that was lifted[1] to support the use case of user memory pressure. It not currently possible to set CAP_SYS_RESOURCES in a systemd service as its setting a capability inside a usernamespace. Running under systemd v254+ requires the default MemoryPressureWatch=auto (or alternately "on"). Functionality was tested in a 6.4 kernel Fedora successfully under a systemd service. Running in a container requires that (unmask=)/sys/fs/cgroup be writable by the mariadbd process. To aid testing, the buf_pool_resize was a convient trigger point on which to trigger garbage collection. ref [1]: https://lore.kernel.org/all/CAMw=ZnQ56cm4Txgy5EhGYvR+Jt4s-KVgoA9_65HKWVMOXp7a9A@mail.gmail.com/T/#m3bd2a73c5ee49965cb73a830b1ccaa37ccf4e427 Co-Author: Daniel Black (on memory pressure trigger) Reviewed by: Marko Mäkelä, Vladislav Vaintroub, Vladislav Lesin, Thirunarayanan Balathandayuthapani Tested by: Matthias Leich --- mysql-test/suite/innodb/r/mem_pressure.result | 27 ++ mysql-test/suite/innodb/t/mem_pressure.test | 44 +++ storage/innobase/buf/buf0buf.cc | 327 +++++++++++++++++- storage/innobase/include/buf0buf.h | 10 +- 4 files changed, 402 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/innodb/r/mem_pressure.result create mode 100644 mysql-test/suite/innodb/t/mem_pressure.test diff --git a/mysql-test/suite/innodb/r/mem_pressure.result b/mysql-test/suite/innodb/r/mem_pressure.result new file mode 100644 index 00000000000..c732bee78f2 --- /dev/null +++ b/mysql-test/suite/innodb/r/mem_pressure.result @@ -0,0 +1,27 @@ +# +# MDEV-24670 avoid OOM by linux kernel co-operative memory management +# +set @save_dbug=@@debug_dbug; +set @save_limit=@@GLOBAL.innodb_limit_optimistic_insert_debug; +set @save_lag_wait=@@GLOBAL.innodb_max_purge_lag_wait; +set GLOBAL innodb_max_purge_lag_wait=0; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB; +SET GLOBAL innodb_limit_optimistic_insert_debug=2; +SET unique_checks=0, foreign_key_checks=0; +INSERT INTO t1 SELECT CONCAT(REPEAT('junk text', 500), CAST(seq AS CHAR)) FROM seq_1_to_1000; +SET GLOBAL innodb_limit_optimistic_insert_debug=@save_limit; +SET GLOBAL innodb_max_purge_lag_wait=@save_lag_wait; +DROP TABLE t1; +SELECT CAST(VARIABLE_VALUE AS INTEGER) INTO @dirty_prev +FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME='Innodb_buffer_pool_pages_dirty'; +set debug_dbug="d,trigger_garbage_collection"; +SET GLOBAL innodb_buffer_pool_size=@@innodb_buffer_pool_size; +SELECT CAST(VARIABLE_VALUE AS INTEGER) < @dirty_prev AS LESS_DIRTY_IS_GOOD +FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME='Innodb_buffer_pool_pages_dirty'; +LESS_DIRTY_IS_GOOD +1 +FOUND 1 /InnoDB: Memory pressure event freed/ in mysqld.1.err +set debug_dbug=@save_dbug; +# End of 10.11 tests diff --git a/mysql-test/suite/innodb/t/mem_pressure.test b/mysql-test/suite/innodb/t/mem_pressure.test new file mode 100644 index 00000000000..bd25b64c23e --- /dev/null +++ b/mysql-test/suite/innodb/t/mem_pressure.test @@ -0,0 +1,44 @@ +--source include/have_debug.inc +--source include/linux.inc +--source include/not_embedded.inc +--source include/have_innodb.inc +--source include/have_sequence.inc + +--echo # +--echo # MDEV-24670 avoid OOM by linux kernel co-operative memory management +--echo # + +set @save_dbug=@@debug_dbug; + +set @save_limit=@@GLOBAL.innodb_limit_optimistic_insert_debug; +set @save_lag_wait=@@GLOBAL.innodb_max_purge_lag_wait; +set GLOBAL innodb_max_purge_lag_wait=0; + +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB; +SET GLOBAL innodb_limit_optimistic_insert_debug=2; +SET unique_checks=0, foreign_key_checks=0; +INSERT INTO t1 SELECT CONCAT(REPEAT('junk text', 500), CAST(seq AS CHAR)) FROM seq_1_to_1000; + +SET GLOBAL innodb_limit_optimistic_insert_debug=@save_limit; +SET GLOBAL innodb_max_purge_lag_wait=@save_lag_wait; + +DROP TABLE t1; + +SELECT CAST(VARIABLE_VALUE AS INTEGER) INTO @dirty_prev +FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME='Innodb_buffer_pool_pages_dirty'; + +set debug_dbug="d,trigger_garbage_collection"; +SET GLOBAL innodb_buffer_pool_size=@@innodb_buffer_pool_size; + +SELECT CAST(VARIABLE_VALUE AS INTEGER) < @dirty_prev AS LESS_DIRTY_IS_GOOD +FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME='Innodb_buffer_pool_pages_dirty'; + +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; +let SEARCH_PATTERN= InnoDB: Memory pressure event freed; +--source include/search_pattern_in_file.inc + +set debug_dbug=@save_dbug; + +--echo # End of 10.11 tests diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 8ef18ee0a3b..c02d21851be 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -742,6 +742,219 @@ bool buf_page_is_corrupted(bool check_lsn, const byte *read_buf, #ifndef UNIV_INNOCHECKSUM +#ifdef __linux__ +#include +#include + +/** Memory Pressure + +based off https://www.kernel.org/doc/html/latest/accounting/psi.html#pressure-interface +and https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#memory */ +class mem_pressure +{ + /* triggers + pipe */ + struct pollfd m_fds[3]; + nfds_t m_num_fds; + int m_pipe[2]= {-1, -1}; + + std::thread m_thd; + /* mem pressure garbarge collection resticted to interval */ + static constexpr ulonglong max_interval_us= 60*1000000; +public: + mem_pressure() : m_num_fds(0) {} + + bool setup() + { + static_assert(array_elements(m_fds) == (array_elements(m_triggers) + 1), + "insufficient fds"); + std::string memcgroup{"/sys/fs/cgroup"}; + std::string cgroup; + { + std::ifstream selfcgroup("/proc/self/cgroup"); + std::getline(selfcgroup, cgroup, '\n'); + } + + cgroup.erase(0, 3); // Remove "0::" + memcgroup+= cgroup + "/memory.pressure"; + + m_num_fds= 0; + for (auto trig= std::begin(m_triggers); trig!= std::end(m_triggers); ++trig) + { + if ((m_fds[m_num_fds].fd= + open(memcgroup.c_str(), O_RDWR | O_NONBLOCK | O_CLOEXEC)) < 0) + { + switch (errno) { + case EPERM: + /* https://lore.kernel.org/all/CAMw=ZnQ56cm4Txgy5EhGYvR+Jt4s-KVgoA9_65HKWVMOXp7a9A@mail.gmail.com/T/#m3bd2a73c5ee49965cb73a830b1ccaa37ccf4e427 */ + sql_print_information("InnoDB: Failed to initialize memory pressure EPERM, " + "file permissions."); + break; + default: + sql_print_information("InnoDB: Failed to initialize memory pressure: %s", + strerror(errno)); + } + shutdown(); + return false; + } + my_register_filename(m_pipe[0], memcgroup.c_str(), FILE_BY_OPEN, 0, MYF(0)); + ssize_t slen= strlen(*trig); + if (write(m_fds[m_num_fds].fd, *trig, slen) < slen) + { + sql_print_warning("InnoDB: Failed create trigger for memory pressure \"%s\"", *trig); + my_close(m_fds[m_num_fds].fd, MYF(MY_WME)); + continue; + } + m_fds[m_num_fds].events= POLLPRI; + m_num_fds++; + } + if (m_num_fds < 1) + return false; + + if (pipe2(m_pipe, O_CLOEXEC | O_DIRECT)) + { + sql_print_warning("InnoDB: No memory pressure - can't create pipe"); + shutdown(); + return false; + } + my_register_filename(m_pipe[0], "mem_pressure_read", FILE_BY_DUP, 0, MYF(0)); + my_register_filename(m_pipe[1], "mem_pressure_write", FILE_BY_DUP, 0, MYF(0)); + m_fds[m_num_fds].fd= m_pipe[0]; + m_fds[m_num_fds].events= POLLIN; + m_num_fds++; + m_thd= std::thread(pressure_routine, this); + return true; + } + + void shutdown() + { + while (m_num_fds) + { + m_num_fds--; + my_close(m_fds[m_num_fds].fd, MYF(MY_WME)); + m_fds[m_num_fds].fd= -1; + } + /* note m_pipe[0] closed in above loop */ + if (m_pipe[1] >= 0) + { + my_close(m_pipe[1], MYF(MY_WME)); + m_pipe[1]= -1; + } + } + + static void pressure_routine(mem_pressure *m); + +#ifdef UNIV_DEBUG + void trigger_collection() + { + const char c= 'G'; + if (m_pipe[1] >=0 && write(m_pipe[1], &c, 1) < 1) + sql_print_information("InnoDB: (Debug) Failed to trigger memory pressure"); + else /* assumed failed to meet intialization criteria, so trigger directy */ + buf_pool.garbage_collect(); + } +#endif + + void quit() + { + const char c= 'Q'; + if (m_num_fds && write(m_pipe[1], &c, 1) < 1) + sql_print_warning("InnoDB: Failed to write memory pressure quit message"); + } + + void join() + { + if (m_thd.joinable()) + { + quit(); + m_thd.join(); + } + } + + static const char* const m_triggers[2]; +}; + + +/* + ref: https://docs.kernel.org/accounting/psi.html + maximum window size (second number) 10 seconds. + window size in multiples of 2 second interval required (for Unprivileged) + Time is in usec. +*/ +const char* const mem_pressure::m_triggers[]= + {"some 5000000 10000000", /* 5s out of 10s */ + "full 10000 2000000"}; /* 10ms out of 2s */ + +static mem_pressure mem_pressure_obj; + +void mem_pressure::pressure_routine(mem_pressure *m) +{ + DBUG_ASSERT(m == &mem_pressure_obj); + if (my_thread_init()) + { + m->shutdown(); + return; + } + + ulonglong last= microsecond_interval_timer() - max_interval_us; + while (1) + { + if (poll(&m->m_fds[0], m->m_num_fds, -1) < 0) + { + if (errno == EINTR) + continue; + else + { + sql_print_warning("InnoDB: memory pressure poll error %s", + strerror(errno)); + break; + } + } + for (pollfd &p : st_::span(m->m_fds, m->m_num_fds)) + { + if (p.revents & POLLPRI) + { + ulonglong now= microsecond_interval_timer(); + if ((now - last) > max_interval_us) + { + last= now; + buf_pool.garbage_collect(); + } + } + + if (p.revents & POLLIN) + { + char c= '\0'; + /* signal to quit */ + if (read(p.fd, &c, 1) >=0) + switch (c) { + case 'Q': + goto shutdown; +#ifdef UNIV_DEBUG + case 'G': + buf_pool.garbage_collect(); +#endif + } + } + } + } +shutdown: + m->shutdown(); + + my_thread_end(); +} + +/** Initialize mem pressure. */ +ATTRIBUTE_COLD void buf_mem_pressure_detect_init() +{ + mem_pressure_obj.setup(); +} + +ATTRIBUTE_COLD void buf_mem_pressure_shutdown() +{ + mem_pressure_obj.join(); +} +#endif /* __linux__ */ + #if defined(DBUG_OFF) && defined(HAVE_MADVISE) && defined(MADV_DODUMP) /** Enable buffers to be dumped to core files @@ -1099,6 +1312,10 @@ bool buf_pool_t::create() chunk_t::map_ref= chunk_t::map_reg; buf_LRU_old_ratio_update(100 * 3 / 8, false); btr_search_sys_create(); + +#ifdef __linux__ + buf_mem_pressure_detect_init(); +#endif ut_ad(is_initialised()); return false; } @@ -1536,6 +1753,7 @@ struct find_interesting_trx inline void buf_pool_t::resize() { ut_ad(this == &buf_pool); + ut_ad(srv_shutdown_state < SRV_SHUTDOWN_CLEANUP); bool warning = false; @@ -1878,6 +2096,100 @@ calc_buf_pool_size: return; } +#ifdef __linux__ +inline void buf_pool_t::garbage_collect() +{ + mysql_mutex_lock(&mutex); + size_t freed= 0; + +#ifdef BTR_CUR_HASH_ADAPT + /* buf_LRU_free_page() will temporarily release and reacquire + buf_pool.mutex for invoking btr_search_drop_page_hash_index(). Thus, + we must protect ourselves with the hazard pointer. */ +rescan: +#else + lru_hp.set(nullptr); +#endif + for (buf_page_t *bpage= UT_LIST_GET_LAST(LRU), *prev; bpage; bpage= prev) + { + prev= UT_LIST_GET_PREV(LRU, bpage); +#ifdef BTR_CUR_HASH_ADAPT + lru_hp.set(prev); +#endif + auto state= bpage->state(); + ut_ad(state >= buf_page_t::FREED); + ut_ad(bpage->in_LRU_list); + + /* We try to free any pages that can be freed without writing out + anything. */ + switch (bpage->oldest_modification()) { + case 0: + try_to_evict: + if (buf_LRU_free_page(bpage, true)) + { + evicted: + freed++; +#ifdef BTR_CUR_HASH_ADAPT + bpage= prev; + prev= lru_hp.get(); + if (!prev && bpage) + goto rescan; +#endif + } + continue; + case 1: + break; + default: + if (state >= buf_page_t::UNFIXED) + continue; + } + + if (state < buf_page_t::READ_FIX && bpage->lock.u_lock_try(true)) + { + ut_ad(!bpage->is_io_fixed()); + lsn_t oldest_modification= bpage->oldest_modification(); + switch (oldest_modification) { + case 1: + mysql_mutex_lock(&flush_list_mutex); + oldest_modification= bpage->oldest_modification(); + if (oldest_modification) + { + ut_ad(oldest_modification == 1); + delete_from_flush_list(bpage); + } + mysql_mutex_unlock(&flush_list_mutex); + /* fall through */ + case 0: + bpage->lock.u_unlock(true); + goto try_to_evict; + default: + if (bpage->state() < buf_page_t::UNFIXED && + oldest_modification <= log_sys.get_flushed_lsn()) + { + release_freed_page(bpage); + goto evicted; + } + else + bpage->lock.u_unlock(true); + } + } + } + +#if defined MADV_FREE + /* FIXME: Issue fewer calls for larger contiguous blocks of + memory. For now, we assume that this is acceptable, because this + code should be executed rarely. */ + for (buf_page_t *bpage= UT_LIST_GET_FIRST(free); bpage; + bpage= UT_LIST_GET_NEXT(list, bpage)) + madvise(bpage->frame, srv_page_size, MADV_FREE); +#endif + mysql_mutex_unlock(&mutex); + sql_print_information("InnoDB: Memory pressure event freed %zu pages", + freed); + return; +} +#endif /* __linux__ */ + /** Thread pool task invoked by innodb_buffer_pool_size changes. */ static void buf_resize_callback(void *) { @@ -1906,12 +2218,23 @@ static tpool::waitable_task buf_resize_task(buf_resize_callback, void buf_resize_start() { - srv_thread_pool->submit_task(&buf_resize_task); +#if !defined(DBUG_OFF) && defined(__linux__) + DBUG_EXECUTE_IF("trigger_garbage_collection", + { + mem_pressure_obj.trigger_collection(); + } + ); +#endif + + srv_thread_pool->submit_task(&buf_resize_task); } void buf_resize_shutdown() { - buf_resize_task.wait(); +#ifdef __linux__ + buf_mem_pressure_shutdown(); +#endif + buf_resize_task.wait(); } diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 332b2039ef2..35a0387ab84 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -656,12 +656,9 @@ public: access_time= 0; } - void set_os_unused() + void set_os_unused() const { MEM_NOACCESS(frame, srv_page_size); -#ifdef MADV_FREE - madvise(frame, srv_page_size, MADV_FREE); -#endif } void set_os_used() const @@ -1301,6 +1298,11 @@ public: /** Resize from srv_buf_pool_old_size to srv_buf_pool_size. */ inline void resize(); +#ifdef __linux__ + /** Collect garbage (release pages from the LRU list) */ + inline void garbage_collect(); +#endif + /** @return whether resize() is in progress */ bool resize_in_progress() const { From 4cf3a1b1ad73c0ce9ceb7463f452dd65c8bf494d Mon Sep 17 00:00:00 2001 From: Nayuta Yanagisawa Date: Thu, 31 Mar 2022 22:38:54 +0900 Subject: [PATCH 281/477] MDEV-21618 CREATE UNIQUE INDEX fails with "ERROR 1286 (42000): Unknown storage engine 'partition'" The server doesn't use the enforced storage engine in ALTER TABLE without ENGINE clause to avoid an unwanted engine change. However, the server tries to use the enforced engine in CREATE INDEX. As a result, the false positive error is raised. The server should not apply the enforced engine in CREATE INDEX too. --- mysql-test/main/enforce_storage_engine.result | 7 +++++++ mysql-test/main/enforce_storage_engine.test | 15 +++++++++++++-- sql/sql_table.cc | 19 ++++++++++++------- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/mysql-test/main/enforce_storage_engine.result b/mysql-test/main/enforce_storage_engine.result index c761277a5b0..cc91daa73b9 100644 --- a/mysql-test/main/enforce_storage_engine.result +++ b/mysql-test/main/enforce_storage_engine.result @@ -158,5 +158,12 @@ t3 CREATE TABLE `t3` ( PRIMARY KEY (`c1`) ) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci DROP TABLE t3; +# +# MDEV-21618 CREATE UNIQUE INDEX fails with "ERROR 1286 (42000): Unknown storage engine 'partition'" +# +SET SESSION enforce_storage_engine=MyISAM; +CREATE TABLE t4 (a INT) ENGINE=MyISAM PARTITION BY HASH(a); +CREATE INDEX x on t4 (a); +DROP TABLE t4; SET SESSION enforce_storage_engine=NULL; SET GLOBAL enforce_storage_engine=NULL; diff --git a/mysql-test/main/enforce_storage_engine.test b/mysql-test/main/enforce_storage_engine.test index 6b422477fe6..7768ed1bf46 100644 --- a/mysql-test/main/enforce_storage_engine.test +++ b/mysql-test/main/enforce_storage_engine.test @@ -1,4 +1,5 @@ --- source include/not_embedded.inc +--source include/not_embedded.inc +--source include/have_partition.inc set local sql_mode=""; set global sql_mode=""; @@ -107,5 +108,15 @@ ALTER TABLE t3 ADD COLUMN c3 INT; SHOW CREATE TABLE t3; DROP TABLE t3; +--echo # +--echo # MDEV-21618 CREATE UNIQUE INDEX fails with "ERROR 1286 (42000): Unknown storage engine 'partition'" +--echo # +SET SESSION enforce_storage_engine=MyISAM; + +CREATE TABLE t4 (a INT) ENGINE=MyISAM PARTITION BY HASH(a); +CREATE INDEX x on t4 (a); + +DROP TABLE t4; + SET SESSION enforce_storage_engine=NULL; -SET GLOBAL enforce_storage_engine=NULL; \ No newline at end of file +SET GLOBAL enforce_storage_engine=NULL; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1a239b7d105..f0d6084bc7e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -11528,13 +11528,18 @@ bool check_engine(THD *thd, const char *db_name, if (!*new_engine) DBUG_RETURN(true); - /* Enforced storage engine should not be used in - ALTER TABLE that does not use explicit ENGINE = x to - avoid unwanted unrelated changes.*/ - if (!(thd->lex->sql_command == SQLCOM_ALTER_TABLE && - !(create_info->used_fields & HA_CREATE_USED_ENGINE))) - enf_engine= thd->variables.enforced_table_plugin ? - plugin_hton(thd->variables.enforced_table_plugin) : NULL; + /* + Enforced storage engine should not be used in ALTER TABLE that does not + use explicit ENGINE = x to avoid unwanted unrelated changes. It should not + be used in CREATE INDEX too. + */ + if (!((thd->lex->sql_command == SQLCOM_ALTER_TABLE && + !(create_info->used_fields & HA_CREATE_USED_ENGINE)) || + thd->lex->sql_command == SQLCOM_CREATE_INDEX)) + { + plugin_ref enf_plugin= thd->variables.enforced_table_plugin; + enf_engine= enf_plugin ? plugin_hton(enf_plugin) : NULL; + } if (enf_engine && enf_engine != *new_engine) { From 929532a9426d085111c24c63de9c23cc54382259 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Thu, 16 Nov 2023 10:50:38 +0100 Subject: [PATCH 282/477] fix uninitialized field warnings --- sql/handler.cc | 2 +- sql/handler.h | 1 + sql/rpl_record.cc | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 117476eb47d..e0d0f6f5a1b 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2604,7 +2604,7 @@ static void xarecover_do_commit_or_rollback(handlerton *hton, // Populate xid using the server_id from original transaction x.set(member->xid, member->server_id); else - (XID)x= *member->full_xid; + x= *member->full_xid; rc= xarecover_decide_to_commit(member, ptr_commit_max) ? hton->commit_by_xid(hton, &x) : hton->rollback_by_xid(hton, &x); diff --git a/sql/handler.h b/sql/handler.h index 01ab2103703..41384fd6ad8 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -978,6 +978,7 @@ struct Online_alter_cache_list; struct XA_data: XID { Online_alter_cache_list *online_alter_cache= NULL; + XA_data &operator=(const XID &x) { XID::operator=(x); return *this; } }; /* diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 6098dc7daff..b4254b7b163 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -349,7 +349,7 @@ int unpack_row(const rpl_group_info *rgi, TABLE *table, uint const colcnt, st.next_null_byte(); if (!rpl_data.is_online_alter()) { - Field *result_field; + Field *result_field= NULL; for (; i < colcnt && (result_field= table->field[i]); i++) { /* From 8bbf6697cf262a76a6c544e45e3658cdfa5402ec Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 2 Nov 2023 14:57:37 +0100 Subject: [PATCH 283/477] MDEV-24784 JSON_ARRAYAGG charset issue set the proper charset for a temporary result --- mysql-test/main/func_json.result | 11 +++++++++++ mysql-test/main/func_json.test | 11 ++++++++++- sql/item_jsonfunc.cc | 7 +++++++ sql/item_jsonfunc.h | 1 + 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 29f8c383abb..540c8244611 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -1646,5 +1646,16 @@ SELECT JSON_OBJECTAGG('\\', 1); JSON_OBJECTAGG('\\', 1) {"\\":1} # +# MDEV-24784 JSON_ARRAYAGG charset issue +# +set names utf8; +select json_arrayagg('ä'), json_objectagg(1, 'ä'); +json_arrayagg('ä') json_objectagg(1, 'ä') +["ä"] {"1":"ä"} +set names latin1; +select json_arrayagg('ä'), json_objectagg(1, 'ä'); +json_arrayagg('ä') json_objectagg(1, 'ä') +["ä"] {"1":"ä"} +# # End of 10.5 tests # diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index c21fa8d05db..696ffa41a5a 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -1108,7 +1108,16 @@ SELECT JSON_OBJECTAGG('"', 1); SELECT JSON_OBJECTAGG('\"', 1); SELECT JSON_OBJECTAGG('\\', 1); +--echo # +--echo # MDEV-24784 JSON_ARRAYAGG charset issue +--echo # +--disable_service_connection +set names utf8; +select json_arrayagg('ä'), json_objectagg(1, 'ä'); +set names latin1; +select json_arrayagg('ä'), json_objectagg(1, 'ä'); +--enable_service_connection + --echo # --echo # End of 10.5 tests --echo # - diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index b85adeff05d..1105406c658 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -3907,6 +3907,13 @@ int Arg_comparator::compare_e_json_str_basic(Item *j, Item *s) return MY_TEST(sortcmp(res1, res2, compare_collation()) == 0); } +bool Item_func_json_arrayagg::fix_fields(THD *thd, Item **ref) +{ + bool res= Item_func_group_concat::fix_fields(thd, ref); + m_tmp_json.set_charset(collation.collation); + return res; +} + String *Item_func_json_arrayagg::get_str_from_item(Item *i, String *tmp) { diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h index 4aaf66ec695..77936fcc4f4 100644 --- a/sql/item_jsonfunc.h +++ b/sql/item_jsonfunc.h @@ -570,6 +570,7 @@ public: } const char *func_name() const override { return "json_arrayagg("; } + bool fix_fields(THD *thd, Item **ref) override; enum Sumfunctype sum_func() const override { return JSON_ARRAYAGG_FUNC; } String* val_str(String *str) override; From 8aa2076426471a7496d448ce78921e8497b7b2ef Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 13 Nov 2023 18:41:22 +0100 Subject: [PATCH 284/477] Revert "MDEV-22243 type_test.type_test_double fails with 'NUMERIC_SCALE NULL'" This reverts commit 9d19b6526917c94ca03ef1b4c57152882b192cfe. --- .../type_test/type_test_double.result | 2 +- sql/field.cc | 54 ------------------- sql/field.h | 43 +++++++++++++-- 3 files changed, 39 insertions(+), 60 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 edcfdc0eff8..6241ff95b8a 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 NULL +NUMERIC_SCALE 31 DATETIME_PRECISION NULL CHARACTER_SET_NAME NULL COLLATION_NAME NULL diff --git a/sql/field.cc b/sql/field.cc index 0337b1e634e..53dc5f2e15a 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4645,28 +4645,6 @@ 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; @@ -4815,38 +4793,6 @@ 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 057bd8453c5..804394c58a6 100644 --- a/sql/field.h +++ b/sql/field.h @@ -2842,9 +2842,22 @@ 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); + 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; + } Field_float(uint32 len_arg, bool maybe_null_arg, - const LEX_CSTRING *field_name_arg, uint8 dec_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 Type_handler *type_handler() const override { return &type_handler_float; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_FLOAT; } @@ -2877,12 +2890,32 @@ 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); + 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; + } Field_double(uint32 len_arg, bool maybe_null_arg, - const LEX_CSTRING *field_name_arg, uint8 dec_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; + } Field_double(uint32 len_arg, bool maybe_null_arg, const LEX_CSTRING *field_name_arg, - uint8 dec_arg, bool not_fixed_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; + } void init_for_tmp_table(Field *org_field, TABLE *new_table) override { Field::init_for_tmp_table(org_field, new_table); From 9b7a1c0e922a52759ed761152dfbf57d3cd55316 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 13 Nov 2023 23:38:47 +0100 Subject: [PATCH 285/477] MDEV-22243 type_test.type_test_double fails with 'NUMERIC_SCALE NULL' 1. fix useless correction of dec_arg *after it was used* 2. use DECIMAL_NOT_SPECIFIED instead of NOT_FIXED_DEC, because the latter is defined conditionally and has a wrong value in plugins --- .../type_test/type_test_double.result | 2 +- sql/field.h | 38 +++++++------------ 2 files changed, 14 insertions(+), 26 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.h b/sql/field.h index 804394c58a6..5a5184ed7d4 100644 --- a/sql/field.h +++ b/sql/field.h @@ -2105,7 +2105,7 @@ public: uchar null_bit_arg, utype unireg_check_arg, const LEX_CSTRING *field_name_arg, const DTCollation &collation); - uint decimals() const override { return is_created_from_null_item ? 0 : NOT_FIXED_DEC; } + uint decimals() const override { return is_created_from_null_item ? 0 : DECIMAL_NOT_SPECIFIED; } int save_in_field(Field *to) override { return save_in_field_str(to); } bool memcpy_field_possible(const Field *from) const override { @@ -2267,7 +2267,7 @@ public: Information_schema_numeric_attributes information_schema_numeric_attributes() const override { - return dec == NOT_FIXED_DEC ? + return dec == DECIMAL_NOT_SPECIFIED ? Information_schema_numeric_attributes(field_length) : Information_schema_numeric_attributes(field_length, dec); } @@ -2836,6 +2836,8 @@ public: integers. But in all other cases we treat it as TIME_RESULT! */ }; +static inline uint8 fix_dec_arg(uint8 dec_arg) +{ return dec_arg >= FLOATING_POINT_DECIMALS ? DECIMAL_NOT_SPECIFIED : dec_arg; } class Field_float final :public Field_real { public: @@ -2845,19 +2847,13 @@ public: 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; - } + fix_dec_arg(dec_arg), zero_arg, 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; - } + NONE, field_name_arg, fix_dec_arg(dec_arg), 0, 0) + { } const Type_handler *type_handler() const override { return &type_handler_float; } enum ha_base_keytype key_type() const override { return HA_KEYTYPE_FLOAT; } @@ -2893,28 +2889,20 @@ public: 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; - } + fix_dec_arg(dec_arg), zero_arg, 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; - } + NONE, field_name_arg, fix_dec_arg(dec_arg), 0, 0) + { } 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) + NONE, field_name_arg, fix_dec_arg(dec_arg), 0, 0) { not_fixed= not_fixed_arg; - if (dec_arg >= FLOATING_POINT_DECIMALS) - dec_arg= NOT_FIXED_DEC; } void init_for_tmp_table(Field *org_field, TABLE *new_table) override { From 0b36694ff8293ee3e6ae5bffd0c254cced0a4ff0 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 17 Nov 2023 17:00:08 +1100 Subject: [PATCH 286/477] MDEV-32524 Use enums for ids passed to spider mem alloc functions This will avoid issues like MDEV-32486 IDs used in - spider_alloc_calc_mem_init() - spider_string::init_calc_mem() - spider_malloc() - spider_bulk_alloc_mem() - spider_bulk_malloc() --- storage/spider/ha_spider.cc | 36 ++-- storage/spider/spd_conn.cc | 18 +- storage/spider/spd_copy_tables.cc | 14 +- storage/spider/spd_db_conn.cc | 36 ++-- storage/spider/spd_db_handlersocket.cc | 50 ++--- storage/spider/spd_db_mysql.cc | 112 +++++----- storage/spider/spd_db_oracle.cc | 110 +++++----- storage/spider/spd_direct_sql.cc | 18 +- storage/spider/spd_group_by_handler.cc | 8 +- storage/spider/spd_include.h | 271 +++++++++++++++++++++++++ storage/spider/spd_ping_table.cc | 14 +- storage/spider/spd_sys_table.cc | 2 +- storage/spider/spd_table.cc | 72 +++---- storage/spider/spd_trx.cc | 26 +-- 14 files changed, 529 insertions(+), 258 deletions(-) diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index db49c20096f..f037477ecad 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -73,7 +73,7 @@ ha_spider::ha_spider( { DBUG_ENTER("ha_spider::ha_spider"); DBUG_PRINT("info",("spider this=%p", this)); - spider_alloc_calc_mem_init(mem_calc, 139); + spider_alloc_calc_mem_init(mem_calc, SPD_MID_HA_SPIDER_HA_SPIDER_1); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); share = NULL; trx = NULL; @@ -185,7 +185,7 @@ ha_spider::ha_spider( { DBUG_ENTER("ha_spider::ha_spider"); DBUG_PRINT("info",("spider this=%p", this)); - spider_alloc_calc_mem_init(mem_calc, 0); + spider_alloc_calc_mem_init(mem_calc, SPD_MID_HA_SPIDER_HA_SPIDER_2); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); share = NULL; trx = NULL; @@ -394,7 +394,7 @@ int ha_spider::open( if (create_pt_handler_share) { if (!(searched_bitmap = (uchar *) - spider_bulk_malloc(spider_current_trx, 15, MYF(MY_WME), + spider_bulk_malloc(spider_current_trx, SPD_MID_HA_SPIDER_OPEN_1, MYF(MY_WME), &searched_bitmap, sizeof(uchar) * no_bytes_in_map(table->read_set), &ft_discard_bitmap, sizeof(uchar) * no_bytes_in_map(table->read_set), &position_bitmap, sizeof(uchar) * no_bytes_in_map(table->read_set), @@ -462,7 +462,7 @@ int ha_spider::open( } else { #endif if (!(searched_bitmap = (uchar *) - spider_bulk_malloc(spider_current_trx, 16, MYF(MY_WME), + spider_bulk_malloc(spider_current_trx, SPD_MID_HA_SPIDER_OPEN_2, MYF(MY_WME), &searched_bitmap, sizeof(uchar) * no_bytes_in_map(table->read_set), &ft_discard_bitmap, sizeof(uchar) * no_bytes_in_map(table->read_set), &position_bitmap, sizeof(uchar) * no_bytes_in_map(table->read_set), @@ -520,10 +520,10 @@ int ha_spider::open( } for (roop_count = 0; roop_count < (int) share->link_count; roop_count++) { - result_list.sqls[roop_count].init_calc_mem(80); - result_list.insert_sqls[roop_count].init_calc_mem(81); - result_list.update_sqls[roop_count].init_calc_mem(82); - result_list.tmp_sqls[roop_count].init_calc_mem(83); + result_list.sqls[roop_count].init_calc_mem(SPD_MID_HA_SPIDER_OPEN_3); + result_list.insert_sqls[roop_count].init_calc_mem(SPD_MID_HA_SPIDER_OPEN_4); + result_list.update_sqls[roop_count].init_calc_mem(SPD_MID_HA_SPIDER_OPEN_5); + result_list.tmp_sqls[roop_count].init_calc_mem(SPD_MID_HA_SPIDER_OPEN_6); uint all_link_idx = conn_link_idx[roop_count]; uint dbton_id = share->sql_dbton_ids[all_link_idx]; if (share->dbton_share[dbton_id]->need_change_db_table_name()) @@ -554,7 +554,7 @@ int ha_spider::open( } for (roop_count = 0; roop_count < (int) table_share->fields; roop_count++) { - blob_buff[roop_count].init_calc_mem(84); + blob_buff[roop_count].init_calc_mem(SPD_MID_HA_SPIDER_OPEN_7); blob_buff[roop_count].set_charset(table->field[roop_count]->charset()); } } @@ -5065,13 +5065,13 @@ int ha_spider::read_multi_range_first_internal( } #if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100000 if (!(multi_range_keys = (range_id_t *) - spider_malloc(spider_current_trx, 1, sizeof(range_id_t) * + spider_malloc(spider_current_trx, SPD_MID_HA_SPIDER_MULTI_RANGE_READ_NEXT_FIRST_1, sizeof(range_id_t) * (multi_range_num < result_list.multi_split_read ? multi_range_num : result_list.multi_split_read), MYF(MY_WME))) ) #else if (!(multi_range_keys = (char **) - spider_malloc(spider_current_trx, 1, sizeof(char *) * + spider_malloc(spider_current_trx, SPD_MID_HA_SPIDER_MULTI_RANGE_READ_NEXT_FIRST_2, sizeof(char *) * (multi_range_num < result_list.multi_split_read ? multi_range_num : result_list.multi_split_read), MYF(MY_WME))) ) @@ -5085,7 +5085,7 @@ int ha_spider::read_multi_range_first_internal( DBUG_RETURN(HA_ERR_OUT_OF_MEM); } for (roop_count = 0; roop_count < 2; roop_count++) - mrr_key_buff[roop_count].init_calc_mem(235); + mrr_key_buff[roop_count].init_calc_mem(SPD_MID_HA_SPIDER_MULTI_RANGE_READ_NEXT_FIRST_3); } #else multi_range_ranges = ranges; @@ -8201,7 +8201,7 @@ FT_INFO *ha_spider::ft_init_ext( if (!ft_current) { if (!(ft_current = (st_spider_ft_info *) - spider_malloc(spider_current_trx, 2, sizeof(st_spider_ft_info), + spider_malloc(spider_current_trx, SPD_MID_HA_SPIDER_FT_INIT_EXT_1, sizeof(st_spider_ft_info), MYF(MY_WME | MY_ZEROFILL)))) { my_error(HA_ERR_OUT_OF_MEM, MYF(0)); @@ -11479,7 +11479,7 @@ int ha_spider::create( if (form->s->keys > 0) { if (!(tmp_share.static_key_cardinality = (longlong *) - spider_bulk_malloc(spider_current_trx, 246, MYF(MY_WME), + spider_bulk_malloc(spider_current_trx, SPD_MID_HA_SPIDER_CREATE_1, MYF(MY_WME), &tmp_share.static_key_cardinality, sizeof(*tmp_share.static_key_cardinality) * form->s->keys, NullS)) @@ -11494,7 +11494,7 @@ int ha_spider::create( } } for (roop_count = 0; roop_count < form->s->keys; roop_count++) - tmp_share.key_hint[roop_count].init_calc_mem(85); + tmp_share.key_hint[roop_count].init_calc_mem(SPD_MID_HA_SPIDER_CREATE_2); DBUG_PRINT("info",("spider tmp_share.key_hint=%p", tmp_share.key_hint)); if ((error_num = spider_parse_connect_info(&tmp_share, form->s, #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -12216,7 +12216,7 @@ const COND *ha_spider::cond_push( { SPIDER_CONDITION *tmp_cond; if (!(tmp_cond = (SPIDER_CONDITION *) - spider_malloc(spider_current_trx, 3, sizeof(*tmp_cond), MYF(MY_WME))) + spider_malloc(spider_current_trx, SPD_MID_HA_SPIDER_COND_PUSH_1, sizeof(*tmp_cond), MYF(MY_WME))) ) DBUG_RETURN(cond); tmp_cond->cond = (COND *) cond; @@ -12290,7 +12290,7 @@ int ha_spider::info_push( if (hs_pushed_ret_fields) spider_free(spider_current_trx, hs_pushed_ret_fields, MYF(0)); if (!(hs_pushed_ret_fields = (uint32 *) - spider_bulk_malloc(spider_current_trx, 17, MYF(MY_WME), + spider_bulk_malloc(spider_current_trx, SPD_MID_HA_SPIDER_INFO_PUSH_1, MYF(MY_WME), &hs_pushed_ret_fields, sizeof(uint32) * hs_pushed_ret_fields_num, NullS)) ) { @@ -13853,7 +13853,7 @@ SPIDER_BULK_ACCESS_LINK *ha_spider::create_bulk_access_link() } */ if (!(bulk_access_link = (SPIDER_BULK_ACCESS_LINK *) - spider_bulk_malloc(spider_current_trx, 168, MYF(MY_WME), + spider_bulk_malloc(spider_current_trx, SPD_MID_HA_SPIDER_CREATE_BULK_ACCESS_LINK_1, MYF(MY_WME), &bulk_access_link, sizeof(SPIDER_BULK_ACCESS_LINK), &ref, ALIGN_SIZE(ref_length) * 2, NullS)) diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index 40fb155ac8e..ba8a579b1ac 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -475,7 +475,7 @@ SPIDER_CONN *spider_create_conn( { #endif if (!(conn = (SPIDER_CONN *) - spider_bulk_malloc(spider_current_trx, 18, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_CREATE_CONN_1, MYF(MY_WME | MY_ZEROFILL), &conn, sizeof(*conn), &tmp_name, share->conn_keys_lengths[link_idx] + 1, &tmp_host, share->tgt_hosts_lengths[link_idx] + 1, @@ -506,7 +506,7 @@ SPIDER_CONN *spider_create_conn( goto error_alloc_conn; } - conn->default_database.init_calc_mem(75); + conn->default_database.init_calc_mem(SPD_MID_CREATE_CONN_2); conn->conn_key_length = share->conn_keys_lengths[link_idx]; conn->conn_key = tmp_name; memcpy(conn->conn_key, share->conn_keys[link_idx], @@ -604,7 +604,7 @@ SPIDER_CONN *spider_create_conn( #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) } else if (conn_kind == SPIDER_CONN_KIND_HS_READ) { if (!(conn = (SPIDER_CONN *) - spider_bulk_malloc(spider_current_trx, 19, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_CREATE_CONN_3, MYF(MY_WME | MY_ZEROFILL), &conn, sizeof(*conn), &tmp_name, share->hs_read_conn_keys_lengths[link_idx] + 1, &tmp_host, share->tgt_hosts_lengths[link_idx] + 1, @@ -618,7 +618,7 @@ SPIDER_CONN *spider_create_conn( goto error_alloc_conn; } - conn->default_database.init_calc_mem(76); + conn->default_database.init_calc_mem(SPD_MID_CREATE_CONN_4); conn->conn_key_length = share->hs_read_conn_keys_lengths[link_idx]; conn->conn_key = tmp_name; memcpy(conn->conn_key, share->hs_read_conn_keys[link_idx], @@ -646,7 +646,7 @@ SPIDER_CONN *spider_create_conn( conn->dbton_id = share->hs_dbton_ids[link_idx]; } else { if (!(conn = (SPIDER_CONN *) - spider_bulk_malloc(spider_current_trx, 20, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_CREATE_CONN_5, MYF(MY_WME | MY_ZEROFILL), &conn, sizeof(*conn), &tmp_name, share->hs_write_conn_keys_lengths[link_idx] + 1, &tmp_host, share->tgt_hosts_lengths[link_idx] + 1, @@ -660,7 +660,7 @@ SPIDER_CONN *spider_create_conn( goto error_alloc_conn; } - conn->default_database.init_calc_mem(77); + conn->default_database.init_calc_mem(SPD_MID_CREATE_CONN_6); conn->conn_key_length = share->hs_write_conn_keys_lengths[link_idx]; conn->conn_key = tmp_name; memcpy(conn->conn_key, share->hs_write_conn_keys[link_idx], @@ -1930,7 +1930,7 @@ int spider_create_conn_thread( error_num = HA_ERR_OUT_OF_MEM; goto error_job_stack_init; } - spider_alloc_calc_mem_init(conn->bg_job_stack, 163); + spider_alloc_calc_mem_init(conn->bg_job_stack, SPD_MID_CREATE_CONN_THREAD_1); spider_alloc_calc_mem(spider_current_trx, conn->bg_job_stack, conn->bg_job_stack.max_element * @@ -3691,7 +3691,7 @@ int spider_create_mon_threads( char *buf = (char *) my_alloca(share->table_name_length + SPIDER_SQL_INT_LEN + 1); spider_string conv_name_str(buf, share->table_name_length + SPIDER_SQL_INT_LEN + 1, system_charset_info); - conv_name_str.init_calc_mem(105); + conv_name_str.init_calc_mem(SPD_MID_CREATE_MON_THREADS_1); conv_name_str.length(0); conv_name_str.q_append(share->table_name, share->table_name_length); for (roop_count = 0; roop_count < (int) share->all_link_count; @@ -3724,7 +3724,7 @@ int spider_create_mon_threads( } } if (!(share->bg_mon_thds = (THD **) - spider_bulk_malloc(spider_current_trx, 23, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_CREATE_MON_THREADS_2, MYF(MY_WME | MY_ZEROFILL), &share->bg_mon_thds, sizeof(THD *) * share->all_link_count, &share->bg_mon_threads, sizeof(pthread_t) * share->all_link_count, &share->bg_mon_mutexes, sizeof(pthread_mutex_t) * diff --git a/storage/spider/spd_copy_tables.cc b/storage/spider/spd_copy_tables.cc index 9128161dae9..6e9d1f2bcc6 100644 --- a/storage/spider/spd_copy_tables.cc +++ b/storage/spider/spd_copy_tables.cc @@ -286,7 +286,7 @@ int spider_udf_get_copy_tgt_tables( } do { if (!(table_conn = (SPIDER_COPY_TABLE_CONN *) - spider_bulk_malloc(spider_current_trx, 25, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_UDF_GET_COPY_TGT_TABLES_1, MYF(MY_WME | MY_ZEROFILL), &table_conn, sizeof(SPIDER_COPY_TABLE_CONN), &tmp_share, sizeof(SPIDER_SHARE), &tmp_connect_info, sizeof(char *) * SPIDER_TMP_SHARE_CHAR_PTR_COUNT, @@ -601,7 +601,7 @@ int spider_udf_copy_tables_create_table_list( } if (!(copy_tables->link_idxs[0] = (int *) - spider_bulk_malloc(spider_current_trx, 26, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_UDF_COPY_TABLES_CREATE_TABLE_LIST_1, MYF(MY_WME | MY_ZEROFILL), ©_tables->link_idxs[0], sizeof(int) * copy_tables->link_idx_count[0], ©_tables->link_idxs[1], @@ -802,7 +802,7 @@ long long spider_copy_tables_body( } if (!(copy_tables = (SPIDER_COPY_TABLES *) - spider_bulk_malloc(spider_current_trx, 27, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_COPY_TABLES_BODY_1, MYF(MY_WME | MY_ZEROFILL), ©_tables, sizeof(SPIDER_COPY_TABLES), NullS)) ) { @@ -1018,7 +1018,7 @@ long long spider_copy_tables_body( { tmp_spider = &spider[roop_count]; if (!(tmp_spider->dbton_handler = (spider_db_handler **) - spider_bulk_alloc_mem(spider_current_trx, 205, + spider_bulk_alloc_mem(spider_current_trx, SPD_MID_COPY_TABLES_BODY_2, __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &tmp_spider->dbton_handler, sizeof(spider_db_handler *) * SPIDER_DBTON_SIZE, @@ -1037,7 +1037,7 @@ long long spider_copy_tables_body( } */ tmp_spider->conns = &table_conn->conn; - tmp_sql[roop_count].init_calc_mem(122); + tmp_sql[roop_count].init_calc_mem(SPD_MID_COPY_TABLES_BODY_3); tmp_sql[roop_count].set_charset(copy_tables->access_charset); tmp_spider->result_list.sqls = &tmp_sql[roop_count]; tmp_spider->need_mons = &table_conn->need_mon; @@ -1062,7 +1062,7 @@ long long spider_copy_tables_body( { tmp_spider = &spider[roop_count]; if (!(tmp_spider->dbton_handler = (spider_db_handler **) - spider_bulk_alloc_mem(spider_current_trx, 206, + spider_bulk_alloc_mem(spider_current_trx, SPD_MID_COPY_TABLES_BODY_4, __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &tmp_spider->dbton_handler, sizeof(spider_db_handler *) * SPIDER_DBTON_SIZE, @@ -1081,7 +1081,7 @@ long long spider_copy_tables_body( } */ tmp_spider->conns = &table_conn->conn; - tmp_sql[roop_count].init_calc_mem(201); + tmp_sql[roop_count].init_calc_mem(SPD_MID_COPY_TABLES_BODY_5); tmp_sql[roop_count].set_charset(copy_tables->access_charset); tmp_spider->result_list.sqls = &tmp_sql[roop_count]; tmp_spider->need_mons = &table_conn->need_mon; diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 69825b696a9..5b96bfec3cd 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -280,7 +280,7 @@ int spider_db_conn_queue_action( spider_string sql_str(sql_buf, sizeof(sql_buf), system_charset_info); DBUG_ENTER("spider_db_conn_queue_action"); DBUG_PRINT("info", ("spider conn=%p", conn)); - sql_str.init_calc_mem(106); + sql_str.init_calc_mem(SPD_MID_DB_CONN_QUEUE_ACTION_1); sql_str.length(0); if (conn->queued_connect) { @@ -677,7 +677,7 @@ int spider_db_query( DBUG_RETURN(error_num); #ifndef DBUG_OFF spider_string tmp_query_str(sizeof(char) * (length + 1)); - tmp_query_str.init_calc_mem(107); + tmp_query_str.init_calc_mem(SPD_MID_DB_QUERY_1); char *tmp_query = (char *) tmp_query_str.c_ptr_safe(); memcpy(tmp_query, query, length); tmp_query[length] = '\0'; @@ -2813,7 +2813,7 @@ int spider_db_fetch_for_item_sum_func( { if (!spider->direct_aggregate_item_first) { - if (!spider_bulk_malloc(spider_current_trx, 240, MYF(MY_WME), + if (!spider_bulk_malloc(spider_current_trx, SPD_MID_DB_FETCH_FOR_ITEM_SUM_FUNC_1, MYF(MY_WME), &spider->direct_aggregate_item_first, sizeof(SPIDER_ITEM_HLD), NullS) ) { @@ -2831,7 +2831,7 @@ int spider_db_fetch_for_item_sum_func( } else { if (!spider->direct_aggregate_item_current->next) { - if (!spider_bulk_malloc(spider_current_trx, 241, MYF(MY_WME), + if (!spider_bulk_malloc(spider_current_trx, SPD_MID_DB_FETCH_FOR_ITEM_SUM_FUNC_2, MYF(MY_WME), &spider->direct_aggregate_item_current->next, sizeof(SPIDER_ITEM_HLD), NullS) ) { @@ -2891,7 +2891,7 @@ int spider_db_fetch_for_item_sum_func( } else { char buf[MAX_FIELD_WIDTH]; spider_string tmp_str(buf, MAX_FIELD_WIDTH, share->access_charset); - tmp_str.init_calc_mem(242); + tmp_str.init_calc_mem(SPD_MID_DB_FETCH_FOR_ITEM_SUM_FUNC_3); tmp_str.length(0); if ((error_num = row->append_to_str(&tmp_str))) DBUG_RETURN(error_num); @@ -3937,7 +3937,7 @@ int spider_db_store_result( if (!result_list->first) { if (!(result_list->first = (SPIDER_RESULT *) - spider_malloc(spider_current_trx, 4, sizeof(*result_list->first), + spider_malloc(spider_current_trx, SPD_MID_DB_STORE_RESULT_1, sizeof(*result_list->first), MYF(MY_WME | MY_ZEROFILL))) ) { if (!conn->mta_conn_mutex_unlock_later) @@ -3969,7 +3969,7 @@ int spider_db_store_result( if (result_list->bgs_current == result_list->last) { if (!(result_list->last = (SPIDER_RESULT *) - spider_malloc(spider_current_trx, 5, sizeof(*result_list->last), + spider_malloc(spider_current_trx, SPD_MID_DB_STORE_RESULT_2, sizeof(*result_list->last), MYF(MY_WME | MY_ZEROFILL))) ) { if (!conn->mta_conn_mutex_unlock_later) @@ -4013,7 +4013,7 @@ int spider_db_store_result( if (result_list->current == result_list->last) { if (!(result_list->last = (SPIDER_RESULT *) - spider_malloc(spider_current_trx, 6, sizeof(*result_list->last), + spider_malloc(spider_current_trx, SPD_MID_DB_STORE_RESULT_3, sizeof(*result_list->last), MYF(MY_WME | MY_ZEROFILL))) ) { if (!conn->mta_conn_mutex_unlock_later) @@ -4232,7 +4232,7 @@ int spider_db_store_result( } current->field_count = field_count; if (!(position = (SPIDER_POSITION *) - spider_bulk_malloc(spider_current_trx, 7, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_DB_STORE_RESULT_4, MYF(MY_WME | MY_ZEROFILL), &position, sizeof(SPIDER_POSITION) * page_size, &tmp_row, sizeof(char*) * field_count, NullS)) @@ -4295,7 +4295,7 @@ int spider_db_store_result( THD *thd = current_thd; char buf[MAX_FIELD_WIDTH]; spider_string tmp_str(buf, MAX_FIELD_WIDTH, &my_charset_bin); - tmp_str.init_calc_mem(120); + tmp_str.init_calc_mem(SPD_MID_DB_STORE_RESULT_5); DBUG_PRINT("info",("spider store result to temporary table")); DBUG_ASSERT(!current->result_tmp_tbl); @@ -9474,7 +9474,7 @@ int spider_db_open_item_string( char tmp_buf[MAX_FIELD_WIDTH]; spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset()); String *tmp_str2; - tmp_str.init_calc_mem(126); + tmp_str.init_calc_mem(SPD_MID_DB_OPEN_ITEM_STRING_1); if (!(tmp_str2 = item->val_str(tmp_str.get_str()))) { @@ -9591,7 +9591,7 @@ int spider_db_open_item_int( char tmp_buf[MAX_FIELD_WIDTH]; spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset()); String *tmp_str2; - tmp_str.init_calc_mem(127); + tmp_str.init_calc_mem(SPD_MID_DB_OPEN_ITEM_INT_1); if (!(tmp_str2 = item->val_str(tmp_str.get_str()))) { @@ -10716,8 +10716,8 @@ int spider_db_udf_ping_table( system_charset_info); spider_string where_str(where_buf, sizeof(where_buf), system_charset_info); - sql_str.init_calc_mem(128); - where_str.init_calc_mem(129); + sql_str.init_calc_mem(SPD_MID_DB_UDF_PING_TABLE_1); + where_str.init_calc_mem(SPD_MID_DB_UDF_PING_TABLE_2); sql_str.length(0); where_str.length(0); if ( @@ -10827,8 +10827,8 @@ int spider_db_udf_ping_table_append_mon_next( spider_string where_clause_str(where_clause ? where_clause : "", where_clause_length + 1, str->charset()); DBUG_ENTER("spider_db_udf_ping_table_append_mon_next"); - child_table_name_str.init_calc_mem(130); - where_clause_str.init_calc_mem(131); + child_table_name_str.init_calc_mem(SPD_MID_DB_UDF_PING_TABLE_APPEND_MON_NEXT_1); + where_clause_str.init_calc_mem(SPD_MID_DB_UDF_PING_TABLE_APPEND_MON_NEXT_2); child_table_name_str.length(child_table_name_length); where_clause_str.length(where_clause_length); limit_str_length = my_sprintf(limit_str, (limit_str, "%lld", limit)); @@ -10967,7 +10967,7 @@ int spider_db_udf_ping_table_mon_next( } spider_string sql_str(sql_buf, sizeof(sql_buf), thd->variables.character_set_client); - sql_str.init_calc_mem(132); + sql_str.init_calc_mem(SPD_MID_DB_UDF_PING_TABLE_MON_NEXT_1); sql_str.length(0); trx.thd = thd; spider.share = share; @@ -11126,7 +11126,7 @@ int spider_db_udf_copy_tables( int bulk_insert_interval; DBUG_ENTER("spider_db_udf_copy_tables"); if (!(last_row_pos = (ulong *) - spider_bulk_malloc(spider_current_trx, 30, MYF(MY_WME), + spider_bulk_malloc(spider_current_trx, SPD_MID_DB_UDF_COPY_TABLES_1, MYF(MY_WME), &last_row_pos, sizeof(ulong) * table->s->fields, &last_lengths, sizeof(ulong) * table->s->fields, NullS)) diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc index b8e4c0e705a..03d8b505bfe 100644 --- a/storage/spider/spd_db_handlersocket.cc +++ b/storage/spider/spd_db_handlersocket.cc @@ -211,7 +211,7 @@ int spider_db_hs_string_ref_buffer::init() { SPD_INIT_DYNAMIC_ARRAY2(&hs_conds, sizeof(SPIDER_HS_STRING_REF), NULL, 16, 16, MYF(MY_WME)); - spider_alloc_calc_mem_init(hs_conds, 159); + spider_alloc_calc_mem_init(hs_conds, SPD_MID_DB_HS_STRING_REF_BUFFER_INIT_1); spider_alloc_calc_mem(spider_current_trx, hs_conds, hs_conds.max_element * hs_conds.size_of_element); hs_da_init = TRUE; @@ -287,7 +287,7 @@ int spider_db_hs_str_buffer::init() { SPD_INIT_DYNAMIC_ARRAY2(&hs_conds, sizeof(spider_string *), NULL, 16, 16, MYF(MY_WME)); - spider_alloc_calc_mem_init(hs_conds, 160); + spider_alloc_calc_mem_init(hs_conds, SPD_MID_DB_HS_STR_BUFFER_INIT_1); spider_alloc_calc_mem(spider_current_trx, hs_conds, hs_conds.max_element * hs_conds.size_of_element); hs_da_init = TRUE; @@ -321,10 +321,10 @@ spider_string *spider_db_hs_str_buffer::add( DBUG_PRINT("info",("spider this=%p", this)); if (hs_conds.elements <= *strs_pos + 1) { - if (!(element = (spider_string *) spider_malloc(spider_current_trx, 8, + if (!(element = (spider_string *) spider_malloc(spider_current_trx, SPD_MID_DB_HS_STR_BUFFER_ADD_1, sizeof(spider_string), MYF(MY_WME | MY_ZEROFILL)))) DBUG_RETURN(NULL); - element->init_calc_mem(98); + element->init_calc_mem(SPD_MID_DB_HS_STR_BUFFER_ADD_2); element->set_charset(&my_charset_bin); if ((element->reserve(str_len + 1))) { @@ -392,7 +392,7 @@ int spider_db_handlersocket_row::store_to_field( #ifndef DBUG_OFF char buf[MAX_FIELD_WIDTH]; spider_string tmp_str(buf, MAX_FIELD_WIDTH, field->charset()); - tmp_str.init_calc_mem(119); + tmp_str.init_calc_mem(SPD_MID_DB_HANDLERSOCKET_ROW_STORE_TO_FIELD_1); tmp_str.length(0); tmp_str.append(hs_row->begin(), hs_row->size(), &my_charset_bin); DBUG_PRINT("info", ("spider val=%s", tmp_str.c_ptr_safe())); @@ -427,7 +427,7 @@ int spider_db_handlersocket_row::append_escaped_to_str( DBUG_ENTER("spider_db_handlersocket_row::append_escaped_to_str"); DBUG_PRINT("info",("spider this=%p", this)); spider_string tmp_str(hs_row->begin(), hs_row->size() + 1, &my_charset_bin); - tmp_str.init_calc_mem(172); + tmp_str.init_calc_mem(SPD_MID_DB_HANDLERSOCKET_ROW_APPEND_ESCAPED_TO_STR_1); tmp_str.length(hs_row->size()); if (str->reserve(hs_row->size() * 2 + 2)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -504,7 +504,7 @@ SPIDER_DB_ROW *spider_db_handlersocket_row::clone() { DBUG_RETURN(NULL); } - if (!spider_bulk_malloc(spider_current_trx, 169, MYF(MY_WME), + if (!spider_bulk_malloc(spider_current_trx, SPD_MID_DB_HANDLERSOCKET_ROW_CLONE_1, MYF(MY_WME), &clone_row->hs_row, sizeof(SPIDER_HS_STRING_REF) * field_count, &tmp_char, row_size, NullS) @@ -712,8 +712,8 @@ SPIDER_DB_ROW *spider_db_handlersocket_result::fetch_row_from_tmp_table( uint field_count; DBUG_ENTER("spider_db_handlersocket_result::fetch_row_from_tmp_table"); DBUG_PRINT("info",("spider this=%p", this)); - tmp_str1.init_calc_mem(171); - tmp_str2.init_calc_mem(173); + tmp_str1.init_calc_mem(SPD_MID_DB_HANDLERSOCKET_RESULT_FETCH_ROW_FROM_TMP_TABLE_1); + tmp_str2.init_calc_mem(SPD_MID_DB_HANDLERSOCKET_RESULT_FETCH_ROW_FROM_TMP_TABLE_2); tmp_table->field[0]->val_str(tmp_str1.get_str()); tmp_table->field[1]->val_str(tmp_str2.get_str()); tmp_str1.mem_calc(); @@ -906,7 +906,7 @@ int spider_db_handlersocket::init() ) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } - spider_alloc_calc_mem_init(handler_open_array, 79); + spider_alloc_calc_mem_init(handler_open_array, SPD_MID_DB_HANDLERSOCKET_INIT_1); spider_alloc_calc_mem(spider_current_trx, handler_open_array, handler_open_array.max_element * @@ -1110,7 +1110,7 @@ int spider_db_handlersocket::exec_query( spider_string tmp_query_str((*hs_conn_p)->get_writebuf_size() + conn->tgt_wrapper_length + tgt_len + (SPIDER_SQL_SPACE_LEN * 2)); - tmp_query_str.init_calc_mem(231); + tmp_query_str.init_calc_mem(SPD_MID_DB_HANDLERSOCKET_EXEC_QUERY_1); tmp_query_str.length(0); tmp_query_str.q_append(conn->tgt_wrapper, conn->tgt_wrapper_length); tmp_query_str.q_append(SPIDER_SQL_SPACE_STR, SPIDER_SQL_SPACE_LEN); @@ -2309,7 +2309,7 @@ int spider_db_handlersocket::append_request_key( request_key_reuse_last = NULL; } else { if (!(tmp_request_key = (st_spider_db_request_key *) - spider_malloc(spider_current_trx, 1, sizeof(st_spider_db_request_key), + spider_malloc(spider_current_trx, SPD_MID_DB_HANDLERSOCKET_APPEND_REQUEST_KEY_1, sizeof(st_spider_db_request_key), MYF(MY_WME))) ) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -2601,7 +2601,7 @@ int spider_db_handlersocket_util::append_column_value( String *ptr; uint length; DBUG_ENTER("spider_db_handlersocket_util::append_column_value"); - tmp_str.init_calc_mem(180); + tmp_str.init_calc_mem(SPD_MID_DB_HANDLERSOCKET_UTIL_APPEND_COLUMN_VALUE_1); if (new_ptr) { @@ -3292,7 +3292,7 @@ int spider_db_handlersocket_util::open_item_func( { char tmp_buf[MAX_FIELD_WIDTH], *tmp_ptr, *tmp_ptr2; spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset()); - tmp_str.init_calc_mem(123); + tmp_str.init_calc_mem(SPD_MID_DB_HANDLERSOCKET_UTIL_OPEN_ITEM_FUNC_1); tmp_str.length(0); str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); if (!merge_func) @@ -3426,7 +3426,7 @@ int spider_db_handlersocket_util::open_item_func( { char tmp_buf[MAX_FIELD_WIDTH], *tmp_ptr, *tmp_ptr2; spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset()); - tmp_str.init_calc_mem(124); + tmp_str.init_calc_mem(SPD_MID_DB_HANDLERSOCKET_UTIL_OPEN_ITEM_FUNC_2); tmp_str.length(0); str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); if (!merge_func) @@ -3580,7 +3580,7 @@ int spider_db_handlersocket_util::open_item_func( { char tmp_buf[MAX_FIELD_WIDTH], *tmp_ptr, *tmp_ptr2; spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset()); - tmp_str.init_calc_mem(125); + tmp_str.init_calc_mem(SPD_MID_DB_HANDLERSOCKET_UTIL_OPEN_ITEM_FUNC_3); tmp_str.length(0); str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); if (!merge_func) @@ -4083,7 +4083,7 @@ spider_handlersocket_share::spider_handlersocket_share( { DBUG_ENTER("spider_handlersocket_share::spider_handlersocket_share"); DBUG_PRINT("info",("spider this=%p", this)); - spider_alloc_calc_mem_init(mem_calc, 186); + spider_alloc_calc_mem_init(mem_calc, SPD_MID_HANDLERSOCKET_SHARE_SPIDER_HANDLERSOCKET_SHARE_1); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); DBUG_VOID_RETURN; } @@ -4111,7 +4111,7 @@ int spider_handlersocket_share::init() DBUG_PRINT("info",("spider this=%p", this)); #ifdef SPIDER_HAS_HASH_VALUE_TYPE if (!(db_table_str_hash_value = (my_hash_value_type *) - spider_bulk_alloc_mem(spider_current_trx, 203, + spider_bulk_alloc_mem(spider_current_trx, SPD_MID_HANDLERSOCKET_SHARE_INIT_1, __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &db_table_str_hash_value, sizeof(my_hash_value_type) * spider_share->all_link_count, @@ -4185,9 +4185,9 @@ int spider_handlersocket_share::create_table_names_str() for (roop_count = 0; roop_count < (int) spider_share->all_link_count; roop_count++) { - table_names_str[roop_count].init_calc_mem(86); - db_names_str[roop_count].init_calc_mem(87); - db_table_str[roop_count].init_calc_mem(88); + table_names_str[roop_count].init_calc_mem(SPD_MID_HANDLERSOCKET_SHARE_CREATE_TABLE_NAMES_STR_1); + db_names_str[roop_count].init_calc_mem(SPD_MID_HANDLERSOCKET_SHARE_CREATE_TABLE_NAMES_STR_2); + db_table_str[roop_count].init_calc_mem(SPD_MID_HANDLERSOCKET_SHARE_CREATE_TABLE_NAMES_STR_3); if (spider_share->sql_dbton_ids[roop_count] != dbton_id) continue; if (first_all_link_idx == -1) @@ -4329,7 +4329,7 @@ int spider_handlersocket_share::create_column_name_str() for (field = table_share->field, str = column_name_str; *field; field++, str++) { - str->init_calc_mem(202); + str->init_calc_mem(SPD_MID_HANDLERSOCKET_SHARE_CREATE_COLUMN_NAME_STR_1); str->set_charset(spider_share->access_charset); if ((error_num = spider_db_append_name_with_quote_str(str, (*field)->field_name, dbton_id))) @@ -4425,7 +4425,7 @@ spider_handlersocket_handler::spider_handlersocket_handler( { DBUG_ENTER("spider_handlersocket_handler::spider_handlersocket_handler"); DBUG_PRINT("info",("spider this=%p", this)); - spider_alloc_calc_mem_init(mem_calc, 187); + spider_alloc_calc_mem_init(mem_calc, SPD_MID_HANDLERSOCKET_HANDLER_SPIDER_HANDLERSOCKET_HANDLER_1); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); DBUG_VOID_RETURN; } @@ -4449,7 +4449,7 @@ int spider_handlersocket_handler::init() DBUG_ENTER("spider_handlersocket_handler::init"); DBUG_PRINT("info",("spider this=%p", this)); if (!(link_for_hash = (SPIDER_LINK_FOR_HASH *) - spider_bulk_alloc_mem(spider_current_trx, 204, + spider_bulk_alloc_mem(spider_current_trx, SPD_MID_HANDLERSOCKET_HANDLER_INIT_1, __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &link_for_hash, sizeof(SPIDER_LINK_FOR_HASH) * share->link_count, @@ -4471,7 +4471,7 @@ int spider_handlersocket_handler::init() handlersocket_share->db_table_str_hash_value[roop_count]; #endif } - hs_sql.init_calc_mem(63); + hs_sql.init_calc_mem(SPD_MID_HANDLERSOCKET_HANDLER_INIT_2); hs_sql.set_charset(share->access_charset); hs_keys.init(); hs_upds.init(); diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index eef7f7e0c2f..0bca68e0d4e 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -452,7 +452,7 @@ int spider_db_mbase_row::append_escaped_to_str( DBUG_ENTER("spider_db_mbase_row::append_escaped_to_str"); DBUG_PRINT("info",("spider this=%p", this)); spider_string tmp_str(*row, *lengths + 1, str->charset()); - tmp_str.init_calc_mem(133); + tmp_str.init_calc_mem(SPD_MID_DB_MBASE_ROW_APPEND_ESCAPED_TO_STR_1); tmp_str.length(*lengths); if (str->reserve(*lengths * 2 + 2)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -544,7 +544,7 @@ SPIDER_DB_ROW *spider_db_mbase_row::clone() } else { row_size = record_size + field_count; } - if (!spider_bulk_malloc(spider_current_trx, 29, MYF(MY_WME), + if (!spider_bulk_malloc(spider_current_trx, SPD_MID_DB_MBASE_ROW_CLONE_1, MYF(MY_WME), &clone_row->row, sizeof(char*) * field_count, &tmp_char, row_size, &clone_row->lengths, sizeof(ulong) * field_count, @@ -772,9 +772,9 @@ SPIDER_DB_ROW *spider_db_mbase_result::fetch_row_from_tmp_table( uint field_count; DBUG_ENTER("spider_db_mbase_result::fetch_row_from_tmp_table"); DBUG_PRINT("info",("spider this=%p", this)); - tmp_str1.init_calc_mem(117); - tmp_str2.init_calc_mem(118); - tmp_str3.init_calc_mem(170); + tmp_str1.init_calc_mem(SPD_MID_DB_MBASE_RESULT_FETCH_ROW_FROM_TMP_TABLE_1); + tmp_str2.init_calc_mem(SPD_MID_DB_MBASE_RESULT_FETCH_ROW_FROM_TMP_TABLE_2); + tmp_str3.init_calc_mem(SPD_MID_DB_MBASE_RESULT_FETCH_ROW_FROM_TMP_TABLE_3); tmp_table->field[0]->val_str(tmp_str1.get_str()); tmp_table->field[1]->val_str(tmp_str2.get_str()); tmp_table->field[2]->val_str(tmp_str3.get_str()); @@ -1870,7 +1870,7 @@ int spider_db_mbase::init() ) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } - spider_alloc_calc_mem_init(lock_table_hash, 140); + spider_alloc_calc_mem_init(lock_table_hash, SPD_MID_DB_MBASE_INIT_1); spider_alloc_calc_mem(spider_current_trx, lock_table_hash, lock_table_hash.array.max_element * @@ -1883,7 +1883,7 @@ int spider_db_mbase::init() ) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } - spider_alloc_calc_mem_init(handler_open_array, 162); + spider_alloc_calc_mem_init(handler_open_array, SPD_MID_DB_MBASE_INIT_2); spider_alloc_calc_mem(spider_current_trx, handler_open_array, handler_open_array.max_element * @@ -2119,7 +2119,7 @@ int spider_db_mbase::exec_query( const char *tgt_str = conn->tgt_host; uint32 tgt_len = conn->tgt_host_length; spider_string tmp_query_str; - tmp_query_str.init_calc_mem(230); + tmp_query_str.init_calc_mem(SPD_MID_DB_MBASE_EXEC_QUERY_1); if (tmp_query_str.reserve( length + conn->tgt_wrapper_length + tgt_len + (SPIDER_SQL_SPACE_LEN * 2))) @@ -2149,7 +2149,7 @@ int spider_db_mbase::exec_query( struct tm lt; struct tm *l_time = localtime_r(&cur_time, <); spider_string tmp_query_str; - tmp_query_str.init_calc_mem(243); + tmp_query_str.init_calc_mem(SPD_MID_DB_MBASE_EXEC_QUERY_2); uint query_length = thd->query_length(); if ((log_result_error_with_sql & 2) && query_length) { @@ -2692,7 +2692,7 @@ int spider_db_mbase::xa_end( spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); DBUG_ENTER("spider_db_mbase::xa_end"); DBUG_PRINT("info",("spider this=%p", this)); - sql_str.init_calc_mem(108); + sql_str.init_calc_mem(SPD_MID_DB_MBASE_XA_END_1); sql_str.length(0); sql_str.q_append(SPIDER_SQL_XA_END_STR, SPIDER_SQL_XA_END_LEN); @@ -2735,7 +2735,7 @@ int spider_db_mbase::xa_prepare( spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); DBUG_ENTER("spider_db_mbase::xa_prepare"); DBUG_PRINT("info",("spider this=%p", this)); - sql_str.init_calc_mem(109); + sql_str.init_calc_mem(SPD_MID_DB_MBASE_XA_PREPARE_1); sql_str.length(0); sql_str.q_append(SPIDER_SQL_XA_PREPARE_STR, SPIDER_SQL_XA_PREPARE_LEN); @@ -2778,7 +2778,7 @@ int spider_db_mbase::xa_commit( spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); DBUG_ENTER("spider_db_mbase::xa_commit"); DBUG_PRINT("info",("spider this=%p", this)); - sql_str.init_calc_mem(110); + sql_str.init_calc_mem(SPD_MID_DB_MBASE_XA_COMMIT_1); sql_str.length(0); sql_str.q_append(SPIDER_SQL_XA_COMMIT_STR, SPIDER_SQL_XA_COMMIT_LEN); @@ -2821,7 +2821,7 @@ int spider_db_mbase::xa_rollback( spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); DBUG_ENTER("spider_db_mbase::xa_rollback"); DBUG_PRINT("info",("spider this=%p", this)); - sql_str.init_calc_mem(111); + sql_str.init_calc_mem(SPD_MID_DB_MBASE_XA_ROLLBACK_1); sql_str.length(0); sql_str.q_append(SPIDER_SQL_XA_ROLLBACK_STR, SPIDER_SQL_XA_ROLLBACK_LEN); @@ -3158,7 +3158,7 @@ int spider_db_mbase::set_wait_timeout( spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); DBUG_ENTER("spider_db_mbase::set_wait_timeout"); DBUG_PRINT("info",("spider this=%p", this)); - sql_str.init_calc_mem(264); + sql_str.init_calc_mem(SPD_MID_DB_MBASE_SET_WAIT_TIMEOUT_1); sql_str.length(0); timeout_str_length = my_sprintf(timeout_str, (timeout_str, "%d", wait_timeout)); @@ -3212,7 +3212,7 @@ int spider_db_mbase::set_sql_mode( spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); DBUG_ENTER("spider_db_mbase::set_sql_mode"); DBUG_PRINT("info",("spider this=%p", this)); - sql_str.init_calc_mem(265); + sql_str.init_calc_mem(SPD_MID_DB_MBASE_SET_SQL_MODE_1); sql_str.length(0); if (sql_str.reserve(SPIDER_SQL_SQL_MODE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -3277,7 +3277,7 @@ int spider_db_mbase::set_time_zone( spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); DBUG_ENTER("spider_db_mbase::set_time_zone"); DBUG_PRINT("info",("spider this=%p", this)); - sql_str.init_calc_mem(214); + sql_str.init_calc_mem(SPD_MID_DB_MBASE_SET_TIME_ZONE_1); sql_str.length(0); if (sql_str.reserve(SPIDER_SQL_TIME_ZONE_LEN + tz_str->length() + SPIDER_SQL_VALUE_QUOTE_LEN)) @@ -4031,7 +4031,7 @@ int spider_db_mariadb_util::append_column_value(ha_spider *spider, THD *thd = field->table->in_use; Time_zone *saved_time_zone = thd->variables.time_zone; DBUG_ENTER("spider_db_mariadb_util::append_column_value"); - tmp_str.init_calc_mem(113); + tmp_str.init_calc_mem(SPD_MID_DB_MARIADB_UTIL_APPEND_COLUMN_VALUE_1); thd->variables.time_zone = UTC; @@ -4107,7 +4107,7 @@ int spider_db_mariadb_util::append_column_value(ha_spider *spider, DBUG_PRINT("info", ("spider append_escaped")); char buf2[MAX_FIELD_WIDTH]; spider_string tmp_str2(buf2, MAX_FIELD_WIDTH, field->charset()); - tmp_str2.init_calc_mem(114); + tmp_str2.init_calc_mem(SPD_MID_DB_MARIADB_UTIL_APPEND_COLUMN_VALUE_2); tmp_str2.length(0); if ( tmp_str2.append(ptr->ptr(), ptr->length(), field->charset()) || @@ -4175,7 +4175,7 @@ int spider_db_mysql_util::append_column_value( THD *thd = field->table->in_use; Time_zone *saved_time_zone = thd->variables.time_zone; DBUG_ENTER("spider_db_mysql_util::append_column_value"); - tmp_str.init_calc_mem(266); + tmp_str.init_calc_mem(SPD_MID_DB_MYSQL_UTIL_APPEND_COLUMN_VALUE_1); thd->variables.time_zone = UTC; @@ -4326,7 +4326,7 @@ int spider_db_mysql_util::append_column_value( DBUG_PRINT("info", ("spider append_escaped")); char buf2[MAX_FIELD_WIDTH]; spider_string tmp_str2(buf2, MAX_FIELD_WIDTH, field->charset()); - tmp_str2.init_calc_mem(267); + tmp_str2.init_calc_mem(SPD_MID_DB_MYSQL_UTIL_APPEND_COLUMN_VALUE_2); tmp_str2.length(0); if ( tmp_str2.append(ptr->ptr(), ptr->length(), field->charset()) || @@ -6118,7 +6118,7 @@ int spider_db_mbase_util::print_item_func( char *tmp_ptr, *tmp_ptr2; DBUG_ASSERT(tmp_str.length() == 0); tmp_str.set_charset(str->charset()); - tmp_str.init_calc_mem(123); + tmp_str.init_calc_mem(SPD_MID_DB_MBASE_UTIL_PRINT_ITEM_FUNC_1); tmp_str.reserve(MAX_FIELD_WIDTH); str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); if (!merge_func) @@ -6240,7 +6240,7 @@ int spider_db_mbase_util::print_item_func( char *tmp_ptr, *tmp_ptr2; DBUG_ASSERT(tmp_str.length() == 0); tmp_str.set_charset(str->charset()); - tmp_str.init_calc_mem(124); + tmp_str.init_calc_mem(SPD_MID_DB_MBASE_UTIL_PRINT_ITEM_FUNC_2); tmp_str.reserve(MAX_FIELD_WIDTH); str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); if (!merge_func) @@ -6375,7 +6375,7 @@ int spider_db_mbase_util::print_item_func( char *tmp_ptr, *tmp_ptr2; DBUG_ASSERT(tmp_str.length() == 0); tmp_str.set_charset(str->charset()); - tmp_str.init_calc_mem(125); + tmp_str.init_calc_mem(SPD_MID_DB_MBASE_UTIL_PRINT_ITEM_FUNC_3); tmp_str.reserve(MAX_FIELD_WIDTH); str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); if (!merge_func) @@ -7123,7 +7123,7 @@ spider_mbase_share::spider_mbase_share( { DBUG_ENTER("spider_mbase_share::spider_mbase_share"); DBUG_PRINT("info",("spider this=%p", this)); - spider_alloc_calc_mem_init(mem_calc, 71); + spider_alloc_calc_mem_init(mem_calc, SPD_MID_MBASE_SHARE_SPIDER_MBASE_SHARE_1); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); DBUG_VOID_RETURN; } @@ -7197,7 +7197,7 @@ int spider_mbase_share::init() DBUG_ENTER("spider_mbase_share::init"); DBUG_PRINT("info",("spider this=%p", this)); if (!(key_select_pos = (int *) - spider_bulk_alloc_mem(spider_current_trx, 112, + spider_bulk_alloc_mem(spider_current_trx, SPD_MID_MBASE_SHARE_INIT_1, __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &key_select_pos, sizeof(int) * keys, @@ -7217,7 +7217,7 @@ int spider_mbase_share::init() } for (roop_count = 0; roop_count < keys; roop_count++) { - key_hint[roop_count].init_calc_mem(189); + key_hint[roop_count].init_calc_mem(SPD_MID_MBASE_SHARE_INIT_2); key_hint[roop_count].set_charset(spider_share->access_charset); } DBUG_PRINT("info",("spider key_hint=%p", key_hint)); @@ -7241,13 +7241,13 @@ int spider_mbase_share::init() DBUG_RETURN(HA_ERR_OUT_OF_MEM); } - table_select->init_calc_mem(96); + table_select->init_calc_mem(SPD_MID_MBASE_SHARE_INIT_3); if (table_share && (error_num = append_table_select())) DBUG_RETURN(error_num); for (roop_count = 0; roop_count < keys; roop_count++) { - key_select[roop_count].init_calc_mem(97); + key_select[roop_count].init_calc_mem(SPD_MID_MBASE_SHARE_INIT_4); if ((error_num = append_key_select(roop_count))) DBUG_RETURN(error_num); } @@ -7398,9 +7398,9 @@ int spider_mbase_share::create_table_names_str() for (roop_count = 0; roop_count < (int) spider_share->all_link_count; roop_count++) { - table_names_str[roop_count].init_calc_mem(86); - db_names_str[roop_count].init_calc_mem(87); - db_table_str[roop_count].init_calc_mem(88); + table_names_str[roop_count].init_calc_mem(SPD_MID_MBASE_SHARE_CREATE_TABLE_NAMES_STR_1); + db_names_str[roop_count].init_calc_mem(SPD_MID_MBASE_SHARE_CREATE_TABLE_NAMES_STR_2); + db_table_str[roop_count].init_calc_mem(SPD_MID_MBASE_SHARE_CREATE_TABLE_NAMES_STR_3); if (spider_share->sql_dbton_ids[roop_count] != dbton_id) continue; if (first_all_link_idx == -1) @@ -7541,7 +7541,7 @@ int spider_mbase_share::create_column_name_str() for (field = table_share->field, str = column_name_str; *field; field++, str++) { - str->init_calc_mem(89); + str->init_calc_mem(SPD_MID_MBASE_SHARE_CREATE_COLUMN_NAME_STR_1); str->set_charset(spider_share->access_charset); if ((error_num = spider_db_append_name_with_quote_str(str, (*field)->field_name, dbton_id))) @@ -7609,8 +7609,8 @@ int spider_mbase_share::append_show_table_status() for (roop_count = 0; roop_count < (int) spider_share->all_link_count; roop_count++) { - show_table_status[0 + (2 * roop_count)].init_calc_mem(90); - show_table_status[1 + (2 * roop_count)].init_calc_mem(91); + show_table_status[0 + (2 * roop_count)].init_calc_mem(SPD_MID_MBASE_SHARE_APPEND_SHOW_TABLE_STATUS_1); + show_table_status[1 + (2 * roop_count)].init_calc_mem(SPD_MID_MBASE_SHARE_APPEND_SHOW_TABLE_STATUS_2); if (spider_share->sql_dbton_ids[roop_count] != dbton_id) continue; @@ -7690,7 +7690,7 @@ int spider_mbase_share::append_show_records() for (roop_count = 0; roop_count < (int) spider_share->all_link_count; roop_count++) { - show_records[roop_count].init_calc_mem(92); + show_records[roop_count].init_calc_mem(SPD_MID_MBASE_SHARE_APPEND_SHOW_RECORDS_1); if (spider_share->sql_dbton_ids[roop_count] != dbton_id) continue; @@ -7740,8 +7740,8 @@ int spider_mbase_share::append_show_index() for (roop_count = 0; roop_count < (int) spider_share->all_link_count; roop_count++) { - show_index[0 + (2 * roop_count)].init_calc_mem(93); - show_index[1 + (2 * roop_count)].init_calc_mem(94); + show_index[0 + (2 * roop_count)].init_calc_mem(SPD_MID_MBASE_SHARE_APPEND_SHOW_INDEX_1); + show_index[1 + (2 * roop_count)].init_calc_mem(SPD_MID_MBASE_SHARE_APPEND_SHOW_INDEX_2); if (spider_share->sql_dbton_ids[roop_count] != dbton_id) continue; @@ -7875,7 +7875,7 @@ int spider_mbase_share::discover_table_structure( uint strlen = str->length(); DBUG_ENTER("spider_mbase_share::discover_table_structure"); DBUG_PRINT("info",("spider this=%p", this)); - sql_str.init_calc_mem(228); + sql_str.init_calc_mem(SPD_MID_MBASE_SHARE_DISCOVER_TABLE_STRUCTURE_1); for (roop_count = 0; roop_count < (int) spider_share->all_link_count; roop_count++) { @@ -8210,7 +8210,7 @@ spider_mbase_handler::spider_mbase_handler( { DBUG_ENTER("spider_mbase_handler::spider_mbase_handler"); DBUG_PRINT("info",("spider this=%p", this)); - spider_alloc_calc_mem_init(mem_calc, 183); + spider_alloc_calc_mem_init(mem_calc, SPD_MID_MBASE_HANDLER_SPIDER_MBASE_HANDLER_1); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); DBUG_VOID_RETURN; } @@ -8283,14 +8283,14 @@ int spider_mbase_handler::init() TABLE *table = spider->get_table(); DBUG_ENTER("spider_mbase_handler::init"); DBUG_PRINT("info",("spider this=%p", this)); - sql.init_calc_mem(59); - sql_part.init_calc_mem(60); - sql_part2.init_calc_mem(61); - ha_sql.init_calc_mem(62); - insert_sql.init_calc_mem(64); - update_sql.init_calc_mem(65); - tmp_sql.init_calc_mem(66); - dup_update_sql.init_calc_mem(166); + sql.init_calc_mem(SPD_MID_MBASE_HANDLER_INIT_1); + sql_part.init_calc_mem(SPD_MID_MBASE_HANDLER_INIT_2); + sql_part2.init_calc_mem(SPD_MID_MBASE_HANDLER_INIT_3); + ha_sql.init_calc_mem(SPD_MID_MBASE_HANDLER_INIT_4); + insert_sql.init_calc_mem(SPD_MID_MBASE_HANDLER_INIT_5); + update_sql.init_calc_mem(SPD_MID_MBASE_HANDLER_INIT_6); + tmp_sql.init_calc_mem(SPD_MID_MBASE_HANDLER_INIT_7); + dup_update_sql.init_calc_mem(SPD_MID_MBASE_HANDLER_INIT_8); if ( (sql.real_alloc(init_sql_alloc_size)) || (insert_sql.real_alloc(init_sql_alloc_size)) || @@ -8310,7 +8310,7 @@ int spider_mbase_handler::init() upd_tmp_tbl_prm.init(); upd_tmp_tbl_prm.field_count = 1; if (!(link_for_hash = (SPIDER_LINK_FOR_HASH *) - spider_bulk_alloc_mem(spider_current_trx, 141, + spider_bulk_alloc_mem(spider_current_trx, SPD_MID_MBASE_HANDLER_INIT_9, __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &link_for_hash, sizeof(SPIDER_LINK_FOR_HASH) * share->link_count, @@ -8426,7 +8426,7 @@ int spider_mbase_handler::append_key_column_types( spider_string tmp_str(tmp_buf, sizeof(tmp_buf), system_charset_info); DBUG_ENTER("spider_mbase_handler::append_key_column_types"); DBUG_PRINT("info",("spider this=%p", this)); - tmp_str.init_calc_mem(115); + tmp_str.init_calc_mem(SPD_MID_MBASE_HANDLER_APPEND_KEY_COLUMN_TYPES_1); start_key_part_map = start_key->keypart_map & full_key_part_map; DBUG_PRINT("info", ("spider spider_user_defined_key_parts=%u", @@ -8556,7 +8556,7 @@ int spider_mbase_handler::append_tmp_table_and_sql_for_bka( const char *table_names[2], *table_aliases[2], *table_dot_aliases[2]; uint table_name_lengths[2], table_alias_lengths[2], table_dot_alias_lengths[2]; - tgt_table_name_str.init_calc_mem(99); + tgt_table_name_str.init_calc_mem(SPD_MID_MBASE_HANDLER_APPEND_TMP_TABLE_AND_SQL_FOR_BKA_1); tgt_table_name_str.length(0); create_tmp_bka_table_name(tmp_table_name, &tmp_table_name_length, first_link_idx); @@ -8809,7 +8809,7 @@ int spider_mbase_handler::append_union_table_and_sql_for_bka( const char *table_names[2], *table_aliases[2], *table_dot_aliases[2]; uint table_name_lengths[2], table_alias_lengths[2], table_dot_alias_lengths[2]; - tgt_table_name_str.init_calc_mem(233); + tgt_table_name_str.init_calc_mem(SPD_MID_MBASE_HANDLER_APPEND_UNION_TABLE_AND_SQL_FOR_BKA_1); tgt_table_name_str.length(0); if ((error_num = append_table_name_with_adjusting(&tgt_table_name_str, first_link_idx, SPIDER_SQL_TYPE_SELECT_SQL))) @@ -10911,7 +10911,7 @@ int spider_mbase_handler::append_match_against( char buf[MAX_FIELD_WIDTH]; spider_string tmp_str(buf, MAX_FIELD_WIDTH, share->access_charset); - tmp_str.init_calc_mem(116); + tmp_str.init_calc_mem(SPD_MID_MBASE_HANDLER_APPEND_MATCH_AGAINST_1); tmp_str.length(0); if ( tmp_str.append(ft_init_key->ptr(), ft_init_key->length(), @@ -13292,7 +13292,7 @@ int spider_mbase_handler::set_sql_for_exec( mysql_share->db_names_str[link_idx].charset()); const char *table_names[2], *table_aliases[2]; uint table_name_lengths[2], table_alias_lengths[2]; - tgt_table_name_str.init_calc_mem(104); + tgt_table_name_str.init_calc_mem(SPD_MID_MBASE_HANDLER_SET_SQL_FOR_EXEC_1); tgt_table_name_str.length(0); if (result_list->tmp_table_join && spider->bka_mode != 2) { @@ -15304,7 +15304,7 @@ int spider_mbase_handler::init_union_table_name_pos() DBUG_PRINT("info",("spider this=%p", this)); if (!union_table_name_pos_first) { - if (!spider_bulk_malloc(spider_current_trx, 236, MYF(MY_WME), + if (!spider_bulk_malloc(spider_current_trx, SPD_MID_MBASE_HANDLER_INIT_UNION_TABLE_NAME_POS_1, MYF(MY_WME), &union_table_name_pos_first, sizeof(SPIDER_INT_HLD), NullS) ) { @@ -15325,7 +15325,7 @@ int spider_mbase_handler::set_union_table_name_pos() { if (!union_table_name_pos_current->next) { - if (!spider_bulk_malloc(spider_current_trx, 237, MYF(MY_WME), + if (!spider_bulk_malloc(spider_current_trx, SPD_MID_MBASE_HANDLER_SET_UNION_TABLE_NAME_POS_1, MYF(MY_WME), &union_table_name_pos_current->next, sizeof(SPIDER_INT_HLD), NullS) ) { @@ -15729,7 +15729,7 @@ int spider_mbase_copy_table::init() { DBUG_ENTER("spider_mbase_copy_table::init"); DBUG_PRINT("info",("spider this=%p", this)); - sql.init_calc_mem(78); + sql.init_calc_mem(SPD_MID_MBASE_COPY_TABLE_INIT_1); DBUG_RETURN(0); } diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc index b7561ccb96e..6d52f3827ea 100644 --- a/storage/spider/spd_db_oracle.cc +++ b/storage/spider/spd_db_oracle.cc @@ -169,7 +169,7 @@ int spider_db_oracle_get_error( char buf2[SPIDER_ORACLE_ERR_BUF_LEN]; spider_string tmp_str(buf2, SPIDER_ORACLE_ERR_BUF_LEN, system_charset_info); DBUG_ENTER("spider_db_oracle_get_error"); - tmp_str.init_calc_mem(176); + tmp_str.init_calc_mem(SPD_MID_DB_ORACLE_GET_ERROR_1); tmp_str.length(0); switch (res) @@ -421,7 +421,7 @@ int spider_db_oracle_row::append_escaped_to_str( DBUG_PRINT("info",("spider this=%p", this)); /* spider_string tmp_str(*val, *rlen, str->charset()); - tmp_str.init_calc_mem(174); + tmp_str.init_calc_mem(SPD_MID_DB_ORACLE_ROW_APPEND_ESCAPED_TO_STR_1); tmp_str.length(*rlen); #ifndef DBUG_OFF tmp_str.c_ptr_safe(); @@ -587,7 +587,7 @@ int spider_db_oracle_row::init() DBUG_PRINT("info",("spider this=%p", this)); if ( !(ind = (sb2 *) - spider_bulk_malloc(spider_current_trx, 161, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_DB_ORACLE_ROW_INIT_1, MYF(MY_WME | MY_ZEROFILL), &ind, sizeof(sb2) * field_count, &rlen, sizeof(ub2) * field_count, &coltp, sizeof(ub2) * field_count, @@ -612,7 +612,7 @@ int spider_db_oracle_row::init() for (i = 0; i < field_count; i++) { val[i] = tmp_val; - val_str[i].init_calc_mem(177); + val_str[i].init_calc_mem(SPD_MID_DB_ORACLE_ROW_INIT_2); val_str[i].set(tmp_val, MAX_FIELD_WIDTH, access_charset); tmp_val += MAX_FIELD_WIDTH; } @@ -886,9 +886,9 @@ SPIDER_DB_ROW *spider_db_oracle_result::fetch_row_from_tmp_table( spider_string tmp_str1, tmp_str2, tmp_str3; DBUG_ENTER("spider_db_oracle_result::fetch_row_from_tmp_table"); DBUG_PRINT("info",("spider this=%p", this)); - tmp_str1.init_calc_mem(175); - tmp_str2.init_calc_mem(178); - tmp_str3.init_calc_mem(179); + tmp_str1.init_calc_mem(SPD_MID_DB_ORACLE_RESULT_FETCH_ROW_FROM_TMP_TABLE_1); + tmp_str2.init_calc_mem(SPD_MID_DB_ORACLE_RESULT_FETCH_ROW_FROM_TMP_TABLE_2); + tmp_str3.init_calc_mem(SPD_MID_DB_ORACLE_RESULT_FETCH_ROW_FROM_TMP_TABLE_3); tmp_table->field[0]->val_str(tmp_str1.get_str()); tmp_table->field[1]->val_str(tmp_str2.get_str()); tmp_table->field[2]->val_str(tmp_str3.get_str()); @@ -1153,7 +1153,7 @@ int spider_db_oracle::init() ) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } - spider_alloc_calc_mem_init(lock_table_hash, 199); + spider_alloc_calc_mem_init(lock_table_hash, SPD_MID_DB_ORACLE_INIT_1); spider_alloc_calc_mem(spider_current_trx, lock_table_hash, lock_table_hash.array.max_element * @@ -1166,7 +1166,7 @@ int spider_db_oracle::init() ) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } - spider_alloc_calc_mem_init(handler_open_array, 164); + spider_alloc_calc_mem_init(handler_open_array, SPD_MID_DB_ORACLE_INIT_2); spider_alloc_calc_mem(spider_current_trx, handler_open_array, handler_open_array.max_element * @@ -1460,7 +1460,7 @@ int spider_db_oracle::exec_query( uint32 tgt_len = conn->tgt_host_length; spider_string tmp_query_str(length + conn->tgt_wrapper_length + tgt_len + (SPIDER_SQL_SPACE_LEN * 2)); - tmp_query_str.init_calc_mem(232); + tmp_query_str.init_calc_mem(SPD_MID_DB_ORACLE_EXEC_QUERY_1); tmp_query_str.length(0); tmp_query_str.q_append(conn->tgt_wrapper, conn->tgt_wrapper_length); tmp_query_str.q_append(SPIDER_SQL_SPACE_STR, SPIDER_SQL_SPACE_LEN); @@ -2713,7 +2713,7 @@ int spider_db_oracle_util::append_column_value( uint length; Time_zone *saved_time_zone = thd->variables.time_zone; DBUG_ENTER("spider_db_oracle_util::append_column_value"); - tmp_str.init_calc_mem(181); + tmp_str.init_calc_mem(SPD_MID_DB_ORACLE_UTIL_APPEND_COLUMN_VALUE_1); thd->variables.time_zone = UTC; @@ -2850,7 +2850,7 @@ int spider_db_oracle_util::append_column_value( DBUG_PRINT("info", ("spider append_escaped")); char buf2[MAX_FIELD_WIDTH]; spider_string tmp_str2(buf2, MAX_FIELD_WIDTH, access_charset); - tmp_str2.init_calc_mem(182); + tmp_str2.init_calc_mem(SPD_MID_DB_ORACLE_UTIL_APPEND_COLUMN_VALUE_2); tmp_str2.length(0); if ( tmp_str2.append(ptr->ptr(), ptr->length(), field->charset()) || @@ -3538,7 +3538,7 @@ int spider_db_oracle_util::open_item_func( { char tmp_buf[MAX_FIELD_WIDTH], *tmp_ptr, *tmp_ptr2; spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset()); - tmp_str.init_calc_mem(123); + tmp_str.init_calc_mem(SPD_MID_DB_ORACLE_UTIL_OPEN_ITEM_FUNC_1); tmp_str.length(0); str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); if (!merge_func) @@ -3672,7 +3672,7 @@ int spider_db_oracle_util::open_item_func( { char tmp_buf[MAX_FIELD_WIDTH], *tmp_ptr, *tmp_ptr2; spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset()); - tmp_str.init_calc_mem(124); + tmp_str.init_calc_mem(SPD_MID_DB_ORACLE_UTIL_OPEN_ITEM_FUNC_2); tmp_str.length(0); str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); if (!merge_func) @@ -3962,7 +3962,7 @@ int spider_db_oracle_util::open_item_func( { char tmp_buf[MAX_FIELD_WIDTH], *tmp_ptr, *tmp_ptr2; spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset()); - tmp_str.init_calc_mem(125); + tmp_str.init_calc_mem(SPD_MID_DB_ORACLE_UTIL_OPEN_ITEM_FUNC_3); tmp_str.length(0); str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); if (!merge_func) @@ -4595,7 +4595,7 @@ spider_oracle_share::spider_oracle_share( { DBUG_ENTER("spider_oracle_share::spider_oracle_share"); DBUG_PRINT("info",("spider this=%p", this)); - spider_alloc_calc_mem_init(mem_calc, 220); + spider_alloc_calc_mem_init(mem_calc, SPD_MID_ORACLE_SHARE_SPIDER_ORACLE_SHARE_1); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); DBUG_VOID_RETURN; } @@ -4634,7 +4634,7 @@ int spider_oracle_share::init() DBUG_ENTER("spider_oracle_share::init"); DBUG_PRINT("info",("spider this=%p", this)); if (!(key_select_pos = (int *) - spider_bulk_alloc_mem(spider_current_trx, 221, + spider_bulk_alloc_mem(spider_current_trx, SPD_MID_ORACLE_SHARE_INIT_1, __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &key_select_pos, sizeof(int) * keys, @@ -4654,7 +4654,7 @@ int spider_oracle_share::init() } for (roop_count = 0; roop_count < keys; roop_count++) { - key_hint[roop_count].init_calc_mem(190); + key_hint[roop_count].init_calc_mem(SPD_MID_ORACLE_SHARE_INIT_2); key_hint[roop_count].set_charset(spider_share->access_charset); } DBUG_PRINT("info",("spider key_hint=%p", key_hint)); @@ -4680,13 +4680,13 @@ int spider_oracle_share::init() DBUG_RETURN(HA_ERR_OUT_OF_MEM); } - table_select->init_calc_mem(191); + table_select->init_calc_mem(SPD_MID_ORACLE_SHARE_INIT_3); if (table_share && (error_num = append_table_select())) DBUG_RETURN(error_num); for (roop_count = 0; roop_count < keys; roop_count++) { - key_select[roop_count].init_calc_mem(192); + key_select[roop_count].init_calc_mem(SPD_MID_ORACLE_SHARE_INIT_4); if ((error_num = append_key_select(roop_count))) DBUG_RETURN(error_num); } @@ -4838,9 +4838,9 @@ int spider_oracle_share::create_table_names_str() for (roop_count = 0; roop_count < (int) spider_share->all_link_count; roop_count++) { - table_names_str[roop_count].init_calc_mem(193); - db_names_str[roop_count].init_calc_mem(194); - db_table_str[roop_count].init_calc_mem(195); + table_names_str[roop_count].init_calc_mem(SPD_MID_ORACLE_SHARE_CREATE_TABLE_NAMES_STR_1); + db_names_str[roop_count].init_calc_mem(SPD_MID_ORACLE_SHARE_CREATE_TABLE_NAMES_STR_2); + db_table_str[roop_count].init_calc_mem(SPD_MID_ORACLE_SHARE_CREATE_TABLE_NAMES_STR_3); if (spider_share->sql_dbton_ids[roop_count] != dbton_id) continue; if (first_all_link_idx == -1) @@ -4982,7 +4982,7 @@ int spider_oracle_share::create_column_name_str() for (field = table_share->field, str = column_name_str; *field; field++, str++) { - str->init_calc_mem(196); + str->init_calc_mem(SPD_MID_ORACLE_SHARE_CREATE_COLUMN_NAME_STR_1); str->set_charset(spider_share->access_charset); if ((error_num = spider_db_append_name_with_quote_str(str, (*field)->field_name, dbton_id))) @@ -5051,8 +5051,8 @@ int spider_oracle_share::append_show_table_status() for (roop_count = 0; roop_count < (int) spider_share->all_link_count; roop_count++) { - show_table_status[0 + (2 * roop_count)].init_calc_mem(197); - show_table_status[1 + (2 * roop_count)].init_calc_mem(207); + show_table_status[0 + (2 * roop_count)].init_calc_mem(SPD_MID_ORACLE_SHARE_APPEND_SHOW_TABLE_STATUS_1); + show_table_status[1 + (2 * roop_count)].init_calc_mem(SPD_MID_ORACLE_SHARE_APPEND_SHOW_TABLE_STATUS_2); if (spider_share->sql_dbton_ids[roop_count] != dbton_id) continue; @@ -5133,7 +5133,7 @@ int spider_oracle_share::append_show_records() for (roop_count = 0; roop_count < (int) spider_share->all_link_count; roop_count++) { - show_records[roop_count].init_calc_mem(208); + show_records[roop_count].init_calc_mem(SPD_MID_ORACLE_SHARE_APPEND_SHOW_RECORDS_1); if (spider_share->sql_dbton_ids[roop_count] != dbton_id) continue; @@ -5191,7 +5191,7 @@ int spider_oracle_share::append_show_autoinc() for (roop_count = 0; roop_count < spider_share->all_link_count; roop_count++) { - show_autoinc[roop_count].init_calc_mem(224); + show_autoinc[roop_count].init_calc_mem(SPD_MID_ORACLE_SHARE_APPEND_SHOW_AUTOINC_1); if (spider_share->sql_dbton_ids[roop_count] != dbton_id) continue; @@ -5261,8 +5261,8 @@ int spider_oracle_share::append_show_last_insert_id() for (roop_count = 0; roop_count < spider_share->all_link_count; roop_count++) { - show_last_insert_id[roop_count].init_calc_mem(225); - nextval_str[roop_count].init_calc_mem(226); + show_last_insert_id[roop_count].init_calc_mem(SPD_MID_ORACLE_SHARE_APPEND_SHOW_LAST_INSERT_ID_1); + nextval_str[roop_count].init_calc_mem(SPD_MID_ORACLE_SHARE_APPEND_SHOW_LAST_INSERT_ID_2); if (spider_share->sql_dbton_ids[roop_count] != dbton_id) continue; @@ -5358,8 +5358,8 @@ int spider_oracle_share::append_show_index() for (roop_count = 0; roop_count < (int) spider_share->all_link_count; roop_count++) { - show_index[0 + (2 * roop_count)].init_calc_mem(209); - show_index[1 + (2 * roop_count)].init_calc_mem(210); + show_index[0 + (2 * roop_count)].init_calc_mem(SPD_MID_ORACLE_SHARE_APPEND_SHOW_INDEX_1); + show_index[1 + (2 * roop_count)].init_calc_mem(SPD_MID_ORACLE_SHARE_APPEND_SHOW_INDEX_2); if (spider_share->sql_dbton_ids[roop_count] != dbton_id) continue; @@ -5530,7 +5530,7 @@ spider_oracle_handler::spider_oracle_handler( { DBUG_ENTER("spider_oracle_handler::spider_oracle_handler"); DBUG_PRINT("info",("spider this=%p", this)); - spider_alloc_calc_mem_init(mem_calc, 222); + spider_alloc_calc_mem_init(mem_calc, SPD_MID_ORACLE_HANDLER_SPIDER_ORACLE_HANDLER_1); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); DBUG_VOID_RETURN; } @@ -5563,14 +5563,14 @@ int spider_oracle_handler::init() TABLE *table = spider->get_table(); DBUG_ENTER("spider_oracle_handler::init"); DBUG_PRINT("info",("spider this=%p", this)); - sql.init_calc_mem(67); - sql_part.init_calc_mem(68); - sql_part2.init_calc_mem(69); - ha_sql.init_calc_mem(70); - insert_sql.init_calc_mem(72); - update_sql.init_calc_mem(73); - tmp_sql.init_calc_mem(74); - dup_update_sql.init_calc_mem(167); + sql.init_calc_mem(SPD_MID_ORACLE_HANDLER_INIT_1); + sql_part.init_calc_mem(SPD_MID_ORACLE_HANDLER_INIT_2); + sql_part2.init_calc_mem(SPD_MID_ORACLE_HANDLER_INIT_3); + ha_sql.init_calc_mem(SPD_MID_ORACLE_HANDLER_INIT_4); + insert_sql.init_calc_mem(SPD_MID_ORACLE_HANDLER_INIT_5); + update_sql.init_calc_mem(SPD_MID_ORACLE_HANDLER_INIT_6); + tmp_sql.init_calc_mem(SPD_MID_ORACLE_HANDLER_INIT_7); + dup_update_sql.init_calc_mem(SPD_MID_ORACLE_HANDLER_INIT_8); if ( (sql.real_alloc(init_sql_alloc_size)) || (insert_sql.real_alloc(init_sql_alloc_size)) || @@ -5590,7 +5590,7 @@ int spider_oracle_handler::init() upd_tmp_tbl_prm.init(); upd_tmp_tbl_prm.field_count = 1; if (!(link_for_hash = (SPIDER_LINK_FOR_HASH *) - spider_bulk_alloc_mem(spider_current_trx, 223, + spider_bulk_alloc_mem(spider_current_trx, SPD_MID_ORACLE_HANDLER_INIT_9, __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &link_for_hash, sizeof(SPIDER_LINK_FOR_HASH) * share->link_count, @@ -5661,7 +5661,7 @@ int spider_oracle_handler::append_key_column_types( spider_string tmp_str(tmp_buf, sizeof(tmp_buf), system_charset_info); DBUG_ENTER("spider_oracle_handler::append_key_column_types"); DBUG_PRINT("info",("spider this=%p", this)); - tmp_str.init_calc_mem(227); + tmp_str.init_calc_mem(SPD_MID_ORACLE_HANDLER_APPEND_KEY_COLUMN_TYPES_1); start_key_part_map = start_key->keypart_map & full_key_part_map; DBUG_PRINT("info", ("spider spider_user_defined_key_parts=%u", @@ -5782,7 +5782,7 @@ int spider_oracle_handler::append_tmp_table_and_sql_for_bka( const char *table_names[2], *table_aliases[2], *table_dot_aliases[2]; uint table_name_lengths[2], table_alias_lengths[2], table_dot_alias_lengths[2]; - tgt_table_name_str.init_calc_mem(200); + tgt_table_name_str.init_calc_mem(SPD_MID_ORACLE_HANDLER_APPEND_TMP_TABLE_AND_SQL_FOR_BKA_1); tgt_table_name_str.length(0); create_tmp_bka_table_name(tmp_table_name, &tmp_table_name_length, first_link_idx); @@ -6031,7 +6031,7 @@ int spider_oracle_handler::append_union_table_and_sql_for_bka( const char *table_names[2], *table_aliases[2], *table_dot_aliases[2]; uint table_name_lengths[2], table_alias_lengths[2], table_dot_alias_lengths[2]; - tgt_table_name_str.init_calc_mem(234); + tgt_table_name_str.init_calc_mem(SPD_MID_ORACLE_HANDLER_APPEND_UNION_TABLE_AND_SQL_FOR_BKA_1); tgt_table_name_str.length(0); if ((error_num = append_table_name_with_adjusting(&tgt_table_name_str, first_link_idx, SPIDER_SQL_TYPE_SELECT_SQL))) @@ -8011,7 +8011,7 @@ int spider_oracle_handler::append_match_against( char buf[MAX_FIELD_WIDTH]; spider_string tmp_str(buf, MAX_FIELD_WIDTH, share->access_charset); - tmp_str.init_calc_mem(211); + tmp_str.init_calc_mem(SPD_MID_ORACLE_HANDLER_APPEND_MATCH_AGAINST_1); tmp_str.length(0); if ( tmp_str.append(ft_init_key->ptr(), ft_init_key->length(), @@ -10900,7 +10900,7 @@ int spider_oracle_handler::set_sql_for_exec( oracle_share->db_names_str[link_idx].charset()); const char *table_names[2], *table_aliases[2]; uint table_name_lengths[2], table_alias_lengths[2]; - tgt_table_name_str.init_calc_mem(212); + tgt_table_name_str.init_calc_mem(SPD_MID_ORACLE_HANDLER_SET_SQL_FOR_EXEC_1); tgt_table_name_str.length(0); if (result_list->tmp_table_join && spider->bka_mode != 2) { @@ -12654,7 +12654,7 @@ int spider_oracle_handler::init_union_table_name_pos() DBUG_PRINT("info",("spider this=%p", this)); if (!union_table_name_pos_first) { - if (!spider_bulk_malloc(spider_current_trx, 238, MYF(MY_WME), + if (!spider_bulk_malloc(spider_current_trx, SPD_MID_ORACLE_HANDLER_INIT_UNION_TABLE_NAME_POS_1, MYF(MY_WME), &union_table_name_pos_first, sizeof(SPIDER_INT_HLD), NullS) ) { @@ -12675,7 +12675,7 @@ int spider_oracle_handler::set_union_table_name_pos() { if (!union_table_name_pos_current->next) { - if (!spider_bulk_malloc(spider_current_trx, 239, MYF(MY_WME), + if (!spider_bulk_malloc(spider_current_trx, SPD_MID_ORACLE_HANDLER_SET_UNION_TABLE_NAME_POS_1, MYF(MY_WME), &union_table_name_pos_current->next, sizeof(SPIDER_INT_HLD), NullS) ) { @@ -13086,8 +13086,8 @@ int spider_oracle_copy_table::init() { DBUG_ENTER("spider_oracle_copy_table::init"); DBUG_PRINT("info",("spider this=%p", this)); - sql.init_calc_mem(213); - sql_part.init_calc_mem(215); + sql.init_calc_mem(SPD_MID_ORACLE_COPY_TABLE_INIT_1); + sql_part.init_calc_mem(SPD_MID_ORACLE_COPY_TABLE_INIT_2); DBUG_RETURN(0); } @@ -13687,7 +13687,7 @@ int spider_oracle_copy_table::copy_rows( { if (!(first_str = new spider_string[1])) DBUG_RETURN(HA_ERR_OUT_OF_MEM); - first_str->init_calc_mem(216); + first_str->init_calc_mem(SPD_MID_ORACLE_COPY_TABLE_COPY_ROWS_1); first_str->set_charset(sql.charset()); if (first_str->reserve(sql.length())) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -13701,7 +13701,7 @@ int spider_oracle_copy_table::copy_rows( { if (!(current_str->next = new spider_string[1])) DBUG_RETURN(HA_ERR_OUT_OF_MEM); - current_str->next->init_calc_mem(217); + current_str->next->init_calc_mem(SPD_MID_ORACLE_COPY_TABLE_COPY_ROWS_2); current_str->next->set_charset(sql.charset()); if (current_str->next->reserve(sql.length())) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -13753,7 +13753,7 @@ int spider_oracle_copy_table::copy_rows( { if (!(first_str = new spider_string[1])) DBUG_RETURN(HA_ERR_OUT_OF_MEM); - first_str->init_calc_mem(218); + first_str->init_calc_mem(SPD_MID_ORACLE_COPY_TABLE_COPY_ROWS_3); first_str->set_charset(sql.charset()); if (first_str->reserve(sql.length())) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -13767,7 +13767,7 @@ int spider_oracle_copy_table::copy_rows( { if (!(current_str->next = new spider_string[1])) DBUG_RETURN(HA_ERR_OUT_OF_MEM); - current_str->next->init_calc_mem(219); + current_str->next->init_calc_mem(SPD_MID_ORACLE_COPY_TABLE_COPY_ROWS_4); current_str->next->set_charset(sql.charset()); if (current_str->next->reserve(sql.length())) DBUG_RETURN(HA_ERR_OUT_OF_MEM); diff --git a/storage/spider/spd_direct_sql.cc b/storage/spider/spd_direct_sql.cc index 53578623cc8..6639fcee79c 100644 --- a/storage/spider/spd_direct_sql.cc +++ b/storage/spider/spd_direct_sql.cc @@ -116,7 +116,7 @@ int spider_udf_direct_sql_create_table_list( } #if MYSQL_VERSION_ID < 50500 if (!(direct_sql->db_names = (char**) - spider_bulk_malloc(spider_current_trx, 31, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_UDF_DIRECT_SQL_CREATE_TABLE_LIST_1, MYF(MY_WME | MY_ZEROFILL), &direct_sql->db_names, sizeof(char*) * table_count, &direct_sql->table_names, sizeof(char*) * table_count, &direct_sql->tables, sizeof(TABLE*) * table_count, @@ -130,7 +130,7 @@ int spider_udf_direct_sql_create_table_list( ) #else if (!(direct_sql->db_names = (char**) - spider_bulk_malloc(spider_current_trx, 31, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_UDF_DIRECT_SQL_CREATE_TABLE_LIST_2, MYF(MY_WME | MY_ZEROFILL), &direct_sql->db_names, sizeof(char*) * table_count, &direct_sql->table_names, sizeof(char*) * table_count, &direct_sql->tables, sizeof(TABLE*) * table_count, @@ -236,7 +236,7 @@ int spider_udf_direct_sql_create_conn_key( } #endif if (!(direct_sql->conn_key = (char *) - spider_malloc(spider_current_trx, 9, direct_sql->conn_key_length + 1, + spider_malloc(spider_current_trx, SPD_MID_UDF_DIRECT_SQL_CREATE_CONN_KEY_1, direct_sql->conn_key_length + 1, MYF(MY_WME | MY_ZEROFILL))) ) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -411,7 +411,7 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( { #endif if (!(conn = (SPIDER_CONN *) - spider_bulk_malloc(spider_current_trx, 32, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_UDF_DIRECT_SQL_CREATE_CONN_1, MYF(MY_WME | MY_ZEROFILL), &conn, sizeof(*conn), &tmp_name, direct_sql->conn_key_length + 1, &tmp_host, direct_sql->tgt_host_length + 1, @@ -434,11 +434,11 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( *error_num = HA_ERR_OUT_OF_MEM; goto error_alloc_conn; } - conn->default_database.init_calc_mem(138); + conn->default_database.init_calc_mem(SPD_MID_UDF_DIRECT_SQL_CREATE_CONN_2); #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) } else { if (!(conn = (SPIDER_CONN *) - spider_bulk_malloc(spider_current_trx, 33, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_UDF_DIRECT_SQL_CREATE_CONN_3, MYF(MY_WME | MY_ZEROFILL), &conn, sizeof(*conn), &tmp_name, direct_sql->conn_key_length + 1, &tmp_host, direct_sql->tgt_host_length + 1, @@ -450,7 +450,7 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( *error_num = HA_ERR_OUT_OF_MEM; goto error_alloc_conn; } - conn->default_database.init_calc_mem(103); + conn->default_database.init_calc_mem(SPD_MID_UDF_DIRECT_SQL_CREATE_CONN_4); } #endif @@ -1514,7 +1514,7 @@ long long spider_direct_sql_body( DBUG_ENTER("spider_direct_sql_body"); SPIDER_BACKUP_DASTATUS; if (!(direct_sql = (SPIDER_DIRECT_SQL *) - spider_bulk_malloc(spider_current_trx, 34, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_DIRECT_SQL_BODY_1, MYF(MY_WME | MY_ZEROFILL), &direct_sql, sizeof(SPIDER_DIRECT_SQL), &sql, sizeof(char) * args->lengths[0], NullS)) @@ -1775,7 +1775,7 @@ my_bool spider_direct_sql_init_body( if (bg) { if (!(bg_direct_sql = (SPIDER_BG_DIRECT_SQL *) - spider_malloc(spider_current_trx, 10, sizeof(SPIDER_BG_DIRECT_SQL), + spider_malloc(spider_current_trx, SPD_MID_DIRECT_SQL_INIT_BODY_1, sizeof(SPIDER_BG_DIRECT_SQL), MYF(MY_WME | MY_ZEROFILL))) ) { strcpy(message, "spider_bg_direct_sql() out of memory"); diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index d2112bedcb3..2985c9f1302 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -349,7 +349,7 @@ SPIDER_LINK_IDX_CHAIN *spider_fields::create_link_idx_chain( DBUG_ENTER("spider_fields::create_link_idx_chain"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN((SPIDER_LINK_IDX_CHAIN *) - spider_malloc(spider_current_trx, 254, sizeof(SPIDER_LINK_IDX_CHAIN), + spider_malloc(spider_current_trx, SPD_MID_FIELDS_CREATE_LINK_IDX_CHAIN_1, sizeof(SPIDER_LINK_IDX_CHAIN), MYF(MY_WME | MY_ZEROFILL))); } @@ -537,7 +537,7 @@ SPIDER_LINK_IDX_HOLDER *spider_fields::create_link_idx_holder( DBUG_ENTER("spider_fields::create_link_idx_holder"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN((SPIDER_LINK_IDX_HOLDER *) - spider_malloc(spider_current_trx, 253, sizeof(SPIDER_LINK_IDX_HOLDER), + spider_malloc(spider_current_trx, SPD_MID_FIELDS_CREATE_LINK_IDX_HOLDER_1, sizeof(SPIDER_LINK_IDX_HOLDER), MYF(MY_WME | MY_ZEROFILL))); } @@ -615,7 +615,7 @@ SPIDER_CONN_HOLDER *spider_fields::create_conn_holder( DBUG_ENTER("spider_fields::create_conn_holder"); DBUG_PRINT("info",("spider this=%p", this)); return_conn_holder = (SPIDER_CONN_HOLDER *) - spider_bulk_malloc(spider_current_trx, 252, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_FIELDS_CREATE_CONN_HOLDER_1, MYF(MY_WME | MY_ZEROFILL), &return_conn_holder, sizeof(SPIDER_CONN_HOLDER), &table_link_idx_holder, table_count * sizeof(SPIDER_TABLE_LINK_IDX_HOLDER), @@ -884,7 +884,7 @@ static SPIDER_TABLE_HOLDER *spider_create_table_holder( if (table_count_arg == 0) DBUG_RETURN(0); table_holder = (SPIDER_TABLE_HOLDER *) - spider_malloc(spider_current_trx, 249, + spider_malloc(spider_current_trx, SPD_MID_CREATE_TABLE_HOLDER_1, table_count_arg * sizeof(SPIDER_TABLE_HOLDER), MYF(MY_WME | MY_ZEROFILL)); DBUG_RETURN(table_holder); diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 9c49ace318e..c8b3eb979d7 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -268,6 +268,277 @@ const char SPIDER_empty_string = ""; #define SPIDER_MEM_CALC_LIST_NUM 268 #define SPIDER_CONN_META_BUF_LEN 64 +/* + IDs for spider mem alloc functions, including + - spider_alloc_calc_mem_init() + - spider_string::init_calc_mem() + - spider_malloc() + - spider_bulk_alloc_mem() + - spider_bulk_malloc() + In the format of + SPD_MID__ +*/ +enum spider_malloc_id { + SPD_MID_CHECK_HS_PK_UPDATE_1, + SPD_MID_COPY_TABLES_BODY_1, + SPD_MID_COPY_TABLES_BODY_2, + SPD_MID_COPY_TABLES_BODY_3, + SPD_MID_COPY_TABLES_BODY_4, + SPD_MID_COPY_TABLES_BODY_5, + SPD_MID_CREATE_CONN_1, + SPD_MID_CREATE_CONN_2, + SPD_MID_CREATE_CONN_3, + SPD_MID_CREATE_CONN_4, + SPD_MID_CREATE_CONN_5, + SPD_MID_CREATE_CONN_6, + SPD_MID_CREATE_CONN_KEYS_1, + SPD_MID_CREATE_CONN_THREAD_1, + SPD_MID_CREATE_LONGLONG_LIST_1, + SPD_MID_CREATE_LONG_LIST_1, + SPD_MID_CREATE_MON_THREADS_1, + SPD_MID_CREATE_MON_THREADS_2, + SPD_MID_CREATE_SHARE_1, + SPD_MID_CREATE_SHARE_2, + SPD_MID_CREATE_SPIDER_OBJECT_FOR_SHARE_1, + SPD_MID_CREATE_SPIDER_OBJECT_FOR_SHARE_2, + SPD_MID_CREATE_STRING_1, + SPD_MID_CREATE_STRING_LIST_1, + SPD_MID_CREATE_TABLE_HOLDER_1, + SPD_MID_CREATE_TABLE_NAME_STRING_1, + SPD_MID_CREATE_TRX_ALTER_TABLE_1, + SPD_MID_CREATE_TRX_HA_1, + SPD_MID_DB_CONN_QUEUE_ACTION_1, + SPD_MID_DB_FETCH_FOR_ITEM_SUM_FUNC_1, + SPD_MID_DB_FETCH_FOR_ITEM_SUM_FUNC_2, + SPD_MID_DB_FETCH_FOR_ITEM_SUM_FUNC_3, + SPD_MID_DB_HANDLERSOCKET_APPEND_REQUEST_KEY_1, + SPD_MID_DB_HANDLERSOCKET_EXEC_QUERY_1, + SPD_MID_DB_HANDLERSOCKET_INIT_1, + SPD_MID_DB_HANDLERSOCKET_RESULT_FETCH_ROW_FROM_TMP_TABLE_1, + SPD_MID_DB_HANDLERSOCKET_RESULT_FETCH_ROW_FROM_TMP_TABLE_2, + SPD_MID_DB_HANDLERSOCKET_ROW_APPEND_ESCAPED_TO_STR_1, + SPD_MID_DB_HANDLERSOCKET_ROW_CLONE_1, + SPD_MID_DB_HANDLERSOCKET_ROW_STORE_TO_FIELD_1, + SPD_MID_DB_HANDLERSOCKET_UTIL_APPEND_COLUMN_VALUE_1, + SPD_MID_DB_HANDLERSOCKET_UTIL_OPEN_ITEM_FUNC_1, + SPD_MID_DB_HANDLERSOCKET_UTIL_OPEN_ITEM_FUNC_2, + SPD_MID_DB_HANDLERSOCKET_UTIL_OPEN_ITEM_FUNC_3, + SPD_MID_DB_HS_STRING_REF_BUFFER_INIT_1, + SPD_MID_DB_HS_STR_BUFFER_ADD_1, + SPD_MID_DB_HS_STR_BUFFER_ADD_2, + SPD_MID_DB_HS_STR_BUFFER_INIT_1, + SPD_MID_DB_INIT_1, + SPD_MID_DB_INIT_10, + SPD_MID_DB_INIT_11, + SPD_MID_DB_INIT_12, + SPD_MID_DB_INIT_2, + SPD_MID_DB_INIT_3, + SPD_MID_DB_INIT_4, + SPD_MID_DB_INIT_5, + SPD_MID_DB_INIT_6, + SPD_MID_DB_INIT_7, + SPD_MID_DB_INIT_8, + SPD_MID_DB_INIT_9, + SPD_MID_DB_MARIADB_UTIL_APPEND_COLUMN_VALUE_1, + SPD_MID_DB_MARIADB_UTIL_APPEND_COLUMN_VALUE_2, + SPD_MID_DB_MBASE_EXEC_QUERY_1, + SPD_MID_DB_MBASE_EXEC_QUERY_2, + SPD_MID_DB_MBASE_INIT_1, + SPD_MID_DB_MBASE_INIT_2, + SPD_MID_DB_MBASE_RESULT_FETCH_ROW_FROM_TMP_TABLE_1, + SPD_MID_DB_MBASE_RESULT_FETCH_ROW_FROM_TMP_TABLE_2, + SPD_MID_DB_MBASE_RESULT_FETCH_ROW_FROM_TMP_TABLE_3, + SPD_MID_DB_MBASE_ROW_APPEND_ESCAPED_TO_STR_1, + SPD_MID_DB_MBASE_ROW_CLONE_1, + SPD_MID_DB_MBASE_SET_SQL_MODE_1, + SPD_MID_DB_MBASE_SET_TIME_ZONE_1, + SPD_MID_DB_MBASE_SET_WAIT_TIMEOUT_1, + SPD_MID_DB_MBASE_UTIL_PRINT_ITEM_FUNC_1, + SPD_MID_DB_MBASE_UTIL_PRINT_ITEM_FUNC_2, + SPD_MID_DB_MBASE_UTIL_PRINT_ITEM_FUNC_3, + SPD_MID_DB_MBASE_XA_COMMIT_1, + SPD_MID_DB_MBASE_XA_END_1, + SPD_MID_DB_MBASE_XA_PREPARE_1, + SPD_MID_DB_MBASE_XA_ROLLBACK_1, + SPD_MID_DB_MYSQL_UTIL_APPEND_COLUMN_VALUE_1, + SPD_MID_DB_MYSQL_UTIL_APPEND_COLUMN_VALUE_2, + SPD_MID_DB_OPEN_ITEM_INT_1, + SPD_MID_DB_OPEN_ITEM_STRING_1, + SPD_MID_DB_ORACLE_EXEC_QUERY_1, + SPD_MID_DB_ORACLE_GET_ERROR_1, + SPD_MID_DB_ORACLE_INIT_1, + SPD_MID_DB_ORACLE_INIT_2, + SPD_MID_DB_ORACLE_RESULT_FETCH_ROW_FROM_TMP_TABLE_1, + SPD_MID_DB_ORACLE_RESULT_FETCH_ROW_FROM_TMP_TABLE_2, + SPD_MID_DB_ORACLE_RESULT_FETCH_ROW_FROM_TMP_TABLE_3, + SPD_MID_DB_ORACLE_ROW_APPEND_ESCAPED_TO_STR_1, + SPD_MID_DB_ORACLE_ROW_INIT_1, + SPD_MID_DB_ORACLE_ROW_INIT_2, + SPD_MID_DB_ORACLE_UTIL_APPEND_COLUMN_VALUE_1, + SPD_MID_DB_ORACLE_UTIL_APPEND_COLUMN_VALUE_2, + SPD_MID_DB_ORACLE_UTIL_OPEN_ITEM_FUNC_1, + SPD_MID_DB_ORACLE_UTIL_OPEN_ITEM_FUNC_2, + SPD_MID_DB_ORACLE_UTIL_OPEN_ITEM_FUNC_3, + SPD_MID_DB_QUERY_1, + SPD_MID_DB_STORE_RESULT_1, + SPD_MID_DB_STORE_RESULT_2, + SPD_MID_DB_STORE_RESULT_3, + SPD_MID_DB_STORE_RESULT_4, + SPD_MID_DB_STORE_RESULT_5, + SPD_MID_DB_UDF_COPY_TABLES_1, + SPD_MID_DB_UDF_PING_TABLE_1, + SPD_MID_DB_UDF_PING_TABLE_2, + SPD_MID_DB_UDF_PING_TABLE_APPEND_MON_NEXT_1, + SPD_MID_DB_UDF_PING_TABLE_APPEND_MON_NEXT_2, + SPD_MID_DB_UDF_PING_TABLE_MON_NEXT_1, + SPD_MID_DIRECT_SQL_BODY_1, + SPD_MID_DIRECT_SQL_INIT_BODY_1, + SPD_MID_DISCOVER_TABLE_STRUCTURE_1, + SPD_MID_FIELDS_CREATE_CONN_HOLDER_1, + SPD_MID_FIELDS_CREATE_LINK_IDX_CHAIN_1, + SPD_MID_FIELDS_CREATE_LINK_IDX_HOLDER_1, + SPD_MID_GET_INIT_ERROR_TABLE_1, + SPD_MID_GET_LGTM_TBLHND_SHARE_1, + SPD_MID_GET_PING_TABLE_MON_1, + SPD_MID_GET_PING_TABLE_TGT_1, + SPD_MID_GET_PT_SHARE_1, + SPD_MID_GET_PT_SHARE_2, + SPD_MID_GET_SHARE_1, + SPD_MID_GET_SHARE_2, + SPD_MID_GET_TRX_1, + SPD_MID_GET_TRX_10, + SPD_MID_GET_TRX_2, + SPD_MID_GET_TRX_3, + SPD_MID_GET_TRX_4, + SPD_MID_GET_TRX_5, + SPD_MID_GET_TRX_6, + SPD_MID_GET_TRX_7, + SPD_MID_GET_TRX_8, + SPD_MID_GET_TRX_9, + SPD_MID_HANDLERSOCKET_HANDLER_INIT_1, + SPD_MID_HANDLERSOCKET_HANDLER_INIT_2, + SPD_MID_HANDLERSOCKET_HANDLER_SPIDER_HANDLERSOCKET_HANDLER_1, + SPD_MID_HANDLERSOCKET_SHARE_CREATE_COLUMN_NAME_STR_1, + SPD_MID_HANDLERSOCKET_SHARE_CREATE_TABLE_NAMES_STR_1, + SPD_MID_HANDLERSOCKET_SHARE_CREATE_TABLE_NAMES_STR_2, + SPD_MID_HANDLERSOCKET_SHARE_CREATE_TABLE_NAMES_STR_3, + SPD_MID_HANDLERSOCKET_SHARE_INIT_1, + SPD_MID_HANDLERSOCKET_SHARE_SPIDER_HANDLERSOCKET_SHARE_1, + SPD_MID_HA_SPIDER_COND_PUSH_1, + SPD_MID_HA_SPIDER_CREATE_1, + SPD_MID_HA_SPIDER_CREATE_2, + SPD_MID_HA_SPIDER_CREATE_BULK_ACCESS_LINK_1, + SPD_MID_HA_SPIDER_FT_INIT_EXT_1, + SPD_MID_HA_SPIDER_HA_SPIDER_1, + SPD_MID_HA_SPIDER_HA_SPIDER_2, + SPD_MID_HA_SPIDER_INFO_PUSH_1, + SPD_MID_HA_SPIDER_MULTI_RANGE_READ_NEXT_FIRST_1, + SPD_MID_HA_SPIDER_MULTI_RANGE_READ_NEXT_FIRST_2, + SPD_MID_HA_SPIDER_MULTI_RANGE_READ_NEXT_FIRST_3, + SPD_MID_HA_SPIDER_OPEN_1, + SPD_MID_HA_SPIDER_OPEN_2, + SPD_MID_HA_SPIDER_OPEN_3, + SPD_MID_HA_SPIDER_OPEN_4, + SPD_MID_HA_SPIDER_OPEN_5, + SPD_MID_HA_SPIDER_OPEN_6, + SPD_MID_HA_SPIDER_OPEN_7, + SPD_MID_INCREASE_LONGLONG_LIST_1, + SPD_MID_INCREASE_LONG_LIST_1, + SPD_MID_INCREASE_NULL_STRING_LIST_1, + SPD_MID_INCREASE_STRING_LIST_1, + SPD_MID_MBASE_COPY_TABLE_INIT_1, + SPD_MID_MBASE_HANDLER_APPEND_KEY_COLUMN_TYPES_1, + SPD_MID_MBASE_HANDLER_APPEND_MATCH_AGAINST_1, + SPD_MID_MBASE_HANDLER_APPEND_TMP_TABLE_AND_SQL_FOR_BKA_1, + SPD_MID_MBASE_HANDLER_APPEND_UNION_TABLE_AND_SQL_FOR_BKA_1, + SPD_MID_MBASE_HANDLER_INIT_1, + SPD_MID_MBASE_HANDLER_INIT_2, + SPD_MID_MBASE_HANDLER_INIT_3, + SPD_MID_MBASE_HANDLER_INIT_4, + SPD_MID_MBASE_HANDLER_INIT_5, + SPD_MID_MBASE_HANDLER_INIT_6, + SPD_MID_MBASE_HANDLER_INIT_7, + SPD_MID_MBASE_HANDLER_INIT_8, + SPD_MID_MBASE_HANDLER_INIT_9, + SPD_MID_MBASE_HANDLER_INIT_UNION_TABLE_NAME_POS_1, + SPD_MID_MBASE_HANDLER_SET_SQL_FOR_EXEC_1, + SPD_MID_MBASE_HANDLER_SET_UNION_TABLE_NAME_POS_1, + SPD_MID_MBASE_HANDLER_SPIDER_MBASE_HANDLER_1, + SPD_MID_MBASE_SHARE_APPEND_SHOW_INDEX_1, + SPD_MID_MBASE_SHARE_APPEND_SHOW_INDEX_2, + SPD_MID_MBASE_SHARE_APPEND_SHOW_RECORDS_1, + SPD_MID_MBASE_SHARE_APPEND_SHOW_TABLE_STATUS_1, + SPD_MID_MBASE_SHARE_APPEND_SHOW_TABLE_STATUS_2, + SPD_MID_MBASE_SHARE_CREATE_COLUMN_NAME_STR_1, + SPD_MID_MBASE_SHARE_CREATE_TABLE_NAMES_STR_1, + SPD_MID_MBASE_SHARE_CREATE_TABLE_NAMES_STR_2, + SPD_MID_MBASE_SHARE_CREATE_TABLE_NAMES_STR_3, + SPD_MID_MBASE_SHARE_DISCOVER_TABLE_STRUCTURE_1, + SPD_MID_MBASE_SHARE_INIT_1, + SPD_MID_MBASE_SHARE_INIT_2, + SPD_MID_MBASE_SHARE_INIT_3, + SPD_MID_MBASE_SHARE_INIT_4, + SPD_MID_MBASE_SHARE_SPIDER_MBASE_SHARE_1, + SPD_MID_OPEN_ALL_TABLES_1, + SPD_MID_OPEN_SYS_TABLE_1, + SPD_MID_ORACLE_COPY_TABLE_COPY_ROWS_1, + SPD_MID_ORACLE_COPY_TABLE_COPY_ROWS_2, + SPD_MID_ORACLE_COPY_TABLE_COPY_ROWS_3, + SPD_MID_ORACLE_COPY_TABLE_COPY_ROWS_4, + SPD_MID_ORACLE_COPY_TABLE_INIT_1, + SPD_MID_ORACLE_COPY_TABLE_INIT_2, + SPD_MID_ORACLE_HANDLER_APPEND_KEY_COLUMN_TYPES_1, + SPD_MID_ORACLE_HANDLER_APPEND_MATCH_AGAINST_1, + SPD_MID_ORACLE_HANDLER_APPEND_TMP_TABLE_AND_SQL_FOR_BKA_1, + SPD_MID_ORACLE_HANDLER_APPEND_UNION_TABLE_AND_SQL_FOR_BKA_1, + SPD_MID_ORACLE_HANDLER_INIT_1, + SPD_MID_ORACLE_HANDLER_INIT_2, + SPD_MID_ORACLE_HANDLER_INIT_3, + SPD_MID_ORACLE_HANDLER_INIT_4, + SPD_MID_ORACLE_HANDLER_INIT_5, + SPD_MID_ORACLE_HANDLER_INIT_6, + SPD_MID_ORACLE_HANDLER_INIT_7, + SPD_MID_ORACLE_HANDLER_INIT_8, + SPD_MID_ORACLE_HANDLER_INIT_9, + SPD_MID_ORACLE_HANDLER_INIT_UNION_TABLE_NAME_POS_1, + SPD_MID_ORACLE_HANDLER_SET_SQL_FOR_EXEC_1, + SPD_MID_ORACLE_HANDLER_SET_UNION_TABLE_NAME_POS_1, + SPD_MID_ORACLE_HANDLER_SPIDER_ORACLE_HANDLER_1, + SPD_MID_ORACLE_SHARE_APPEND_SHOW_AUTOINC_1, + SPD_MID_ORACLE_SHARE_APPEND_SHOW_INDEX_1, + SPD_MID_ORACLE_SHARE_APPEND_SHOW_INDEX_2, + SPD_MID_ORACLE_SHARE_APPEND_SHOW_LAST_INSERT_ID_1, + SPD_MID_ORACLE_SHARE_APPEND_SHOW_LAST_INSERT_ID_2, + SPD_MID_ORACLE_SHARE_APPEND_SHOW_RECORDS_1, + SPD_MID_ORACLE_SHARE_APPEND_SHOW_TABLE_STATUS_1, + SPD_MID_ORACLE_SHARE_APPEND_SHOW_TABLE_STATUS_2, + SPD_MID_ORACLE_SHARE_CREATE_COLUMN_NAME_STR_1, + SPD_MID_ORACLE_SHARE_CREATE_TABLE_NAMES_STR_1, + SPD_MID_ORACLE_SHARE_CREATE_TABLE_NAMES_STR_2, + SPD_MID_ORACLE_SHARE_CREATE_TABLE_NAMES_STR_3, + SPD_MID_ORACLE_SHARE_INIT_1, + SPD_MID_ORACLE_SHARE_INIT_2, + SPD_MID_ORACLE_SHARE_INIT_3, + SPD_MID_ORACLE_SHARE_INIT_4, + SPD_MID_ORACLE_SHARE_SPIDER_ORACLE_SHARE_1, + SPD_MID_PARSE_CONNECT_INFO_1, + SPD_MID_PING_TABLE_BODY_1, + SPD_MID_PING_TABLE_BODY_2, + SPD_MID_PING_TABLE_INIT_BODY_1, + SPD_MID_PING_TABLE_MON_FROM_TABLE_1, + SPD_MID_RELEASE_PING_TABLE_MON_LIST_1, + SPD_MID_TRX_ANOTHER_LOCK_TABLES_1, + SPD_MID_UDF_COPY_TABLES_CREATE_TABLE_LIST_1, + SPD_MID_UDF_DIRECT_SQL_CREATE_CONN_1, + SPD_MID_UDF_DIRECT_SQL_CREATE_CONN_2, + SPD_MID_UDF_DIRECT_SQL_CREATE_CONN_3, + SPD_MID_UDF_DIRECT_SQL_CREATE_CONN_4, + SPD_MID_UDF_DIRECT_SQL_CREATE_CONN_KEY_1, + SPD_MID_UDF_DIRECT_SQL_CREATE_TABLE_LIST_1, + SPD_MID_UDF_DIRECT_SQL_CREATE_TABLE_LIST_2, + SPD_MID_UDF_GET_COPY_TGT_TABLES_1 +}; + #define SPIDER_BACKUP_DASTATUS \ bool da_status; if (thd) da_status = thd->is_error(); else da_status = FALSE; #define SPIDER_RESTORE_DASTATUS \ diff --git a/storage/spider/spd_ping_table.cc b/storage/spider/spd_ping_table.cc index 83fe4593584..34d643d3555 100644 --- a/storage/spider/spd_ping_table.cc +++ b/storage/spider/spd_ping_table.cc @@ -248,7 +248,7 @@ int spider_release_ping_table_mon_list( } spider_string conv_name_str(buf, conv_name_length + link_idx_str_length + 1, system_charset_info); - conv_name_str.init_calc_mem(134); + conv_name_str.init_calc_mem(SPD_MID_RELEASE_PING_TABLE_MON_LIST_1); conv_name_str.length(0); conv_name_str.q_append(conv_name, conv_name_length); conv_name_str.q_append(link_idx_str, link_idx_str_length); @@ -366,7 +366,7 @@ create_table_mon: do { if (!(table_mon = (SPIDER_TABLE_MON *) - spider_bulk_malloc(spider_current_trx, 35, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_GET_PING_TABLE_MON_1, MYF(MY_WME | MY_ZEROFILL), &table_mon, sizeof(SPIDER_TABLE_MON), &tmp_share, sizeof(SPIDER_SHARE), &tmp_connect_info, sizeof(char *) * SPIDER_TMP_SHARE_CHAR_PTR_COUNT, @@ -490,7 +490,7 @@ SPIDER_TABLE_MON_LIST *spider_get_ping_table_tgt( SPD_INIT_ALLOC_ROOT(&mem_root, 4096, 0, MYF(MY_WME)); if (!(table_mon_list = (SPIDER_TABLE_MON_LIST *) - spider_bulk_malloc(spider_current_trx, 36, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_GET_PING_TABLE_TGT_1, MYF(MY_WME | MY_ZEROFILL), &table_mon_list, sizeof(SPIDER_TABLE_MON_LIST), &tmp_share, sizeof(SPIDER_SHARE), &tmp_connect_info, sizeof(char *) * SPIDER_TMP_SHARE_CHAR_PTR_COUNT, @@ -1028,8 +1028,8 @@ long long spider_ping_table_body( int static_link_id_length = 0; bool get_lock = FALSE, status_changed_to_ng = FALSE; DBUG_ENTER("spider_ping_table_body"); - conv_name.init_calc_mem(135); - tmp_str.init_calc_mem(247); + conv_name.init_calc_mem(SPD_MID_PING_TABLE_BODY_1); + tmp_str.init_calc_mem(SPD_MID_PING_TABLE_BODY_2); conv_name.length(0); #if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100002 server_id = global_system_variables.server_id; @@ -1489,7 +1489,7 @@ my_bool spider_ping_table_init_body( } if (!(mon_table_result = (SPIDER_MON_TABLE_RESULT *) - spider_malloc(spider_current_trx, 11, sizeof(SPIDER_MON_TABLE_RESULT), + spider_malloc(spider_current_trx, SPD_MID_PING_TABLE_INIT_BODY_1, sizeof(SPIDER_MON_TABLE_RESULT), MYF(MY_WME | MY_ZEROFILL))) ) { strcpy(message, "spider_ping_table() out of memory"); @@ -1632,7 +1632,7 @@ int spider_ping_table_mon_from_table( buf[conv_name_length + link_idx_str_length] = '\0'; spider_string conv_name_str(buf, conv_name_length + link_idx_str_length + 1, system_charset_info); - conv_name_str.init_calc_mem(136); + conv_name_str.init_calc_mem(SPD_MID_PING_TABLE_MON_FROM_TABLE_1); conv_name_str.length(0); conv_name_str.q_append(conv_name, conv_name_length); conv_name_str.q_append(link_idx_str, link_idx_str_length + 1); diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc index 6128a0137b1..c5abf7b0b3b 100644 --- a/storage/spider/spd_sys_table.cc +++ b/storage/spider/spd_sys_table.cc @@ -201,7 +201,7 @@ TABLE *spider_open_sys_table( } else { thd->reset_n_backup_open_tables_state(open_tables_backup); - if (!(table = (TABLE*) spider_malloc(spider_current_trx, 12, + if (!(table = (TABLE*) spider_malloc(spider_current_trx, SPD_MID_OPEN_SYS_TABLE_1, sizeof(*table), MYF(MY_WME)))) { *error_num = HA_ERR_OUT_OF_MEM; diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 4c56edc92e6..0f614a01ccf 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -1104,7 +1104,7 @@ int spider_create_string_list( } if (!(*string_list = (char**) - spider_bulk_malloc(spider_current_trx, 37, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_CREATE_STRING_LIST_1, MYF(MY_WME | MY_ZEROFILL), string_list, sizeof(char*) * (*list_length), string_length_list, sizeof(int) * (*list_length), NullS)) @@ -1218,7 +1218,7 @@ int spider_create_long_list( } if (!(*long_list = (long*) - spider_bulk_malloc(spider_current_trx, 38, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_CREATE_LONG_LIST_1, MYF(MY_WME | MY_ZEROFILL), long_list, sizeof(long) * (*list_length), NullS)) ) { @@ -1297,7 +1297,7 @@ int spider_create_longlong_list( } if (!(*longlong_list = (longlong *) - spider_bulk_malloc(spider_current_trx, 39, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_CREATE_LONGLONG_LIST_1, MYF(MY_WME | MY_ZEROFILL), longlong_list, sizeof(longlong) * (*list_length), NullS)) ) { @@ -1365,7 +1365,7 @@ int spider_increase_string_list( } if (!(tmp_str_list = (char**) - spider_bulk_malloc(spider_current_trx, 40, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_INCREASE_STRING_LIST_1, MYF(MY_WME | MY_ZEROFILL), &tmp_str_list, sizeof(char*) * link_count, &tmp_length_list, sizeof(uint) * link_count, NullS)) @@ -1428,7 +1428,7 @@ int spider_increase_null_string_list( DBUG_RETURN(0); if (!(tmp_str_list = (char**) - spider_bulk_malloc(spider_current_trx, 247, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_INCREASE_NULL_STRING_LIST_1, MYF(MY_WME | MY_ZEROFILL), &tmp_str_list, sizeof(char*) * link_count, &tmp_length_list, sizeof(uint) * link_count, NullS)) @@ -1486,7 +1486,7 @@ int spider_increase_long_list( tmp_long = -1; if (!(tmp_long_list = (long*) - spider_bulk_malloc(spider_current_trx, 41, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_INCREASE_LONG_LIST_1, MYF(MY_WME | MY_ZEROFILL), &tmp_long_list, sizeof(long) * link_count, NullS)) ) { @@ -1531,7 +1531,7 @@ int spider_increase_longlong_list( tmp_longlong = -1; if (!(tmp_longlong_list = (longlong*) - spider_bulk_malloc(spider_current_trx, 42, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_INCREASE_LONGLONG_LIST_1, MYF(MY_WME | MY_ZEROFILL), &tmp_longlong_list, sizeof(longlong) * link_count, NullS)) ) { @@ -2909,7 +2909,7 @@ int spider_parse_connect_info( share_alter = &share->alter_table; share_alter->all_link_count = share->all_link_count; if (!(share_alter->tmp_server_names = (char **) - spider_bulk_malloc(spider_current_trx, 43, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_PARSE_CONNECT_INFO_1, MYF(MY_WME | MY_ZEROFILL), &share_alter->tmp_server_names, sizeof(char *) * 16 * share->all_link_count, &share_alter->tmp_server_names_lengths, @@ -3873,7 +3873,7 @@ int spider_create_conn_keys( #endif } if (!(share->conn_keys = (char **) - spider_bulk_alloc_mem(spider_current_trx, 45, + spider_bulk_alloc_mem(spider_current_trx, SPD_MID_CREATE_CONN_KEYS_1, __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &share->conn_keys, sizeof(char *) * share->all_link_count, &share->conn_keys_lengths, sizeof(uint) * share->all_link_count, @@ -4177,7 +4177,7 @@ SPIDER_SHARE *spider_create_share( length = (uint) strlen(table_name); bitmap_size = spider_bitmap_size(table_share->fields); if (!(share = (SPIDER_SHARE *) - spider_bulk_malloc(spider_current_trx, 46, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_CREATE_SHARE_1, MYF(MY_WME | MY_ZEROFILL), &share, sizeof(*share), &tmp_name, length + 1, &tmp_static_key_cardinality, sizeof(*tmp_static_key_cardinality) * table_share->keys, @@ -4227,7 +4227,7 @@ SPIDER_SHARE *spider_create_share( goto error_init_hint_string; } for (roop_count = 0; roop_count < (int) table_share->keys; roop_count++) - share->key_hint[roop_count].init_calc_mem(95); + share->key_hint[roop_count].init_calc_mem(SPD_MID_CREATE_SHARE_2); DBUG_PRINT("info",("spider share->key_hint=%p", share->key_hint)); if ((*error_num = spider_parse_connect_info(share, table_share, @@ -4674,7 +4674,7 @@ SPIDER_SHARE *spider_get_share( #endif if (!(spider->conn_keys = (char **) - spider_bulk_alloc_mem(spider_current_trx, 47, + spider_bulk_alloc_mem(spider_current_trx, SPD_MID_GET_SHARE_1, __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &spider->conn_keys, sizeof(char *) * share->link_count, &tmp_name, sizeof(char) * share->conn_keys_charlen, @@ -5211,7 +5211,7 @@ SPIDER_SHARE *spider_get_share( #endif if (!(spider->conn_keys = (char **) - spider_bulk_alloc_mem(spider_current_trx, 49, + spider_bulk_alloc_mem(spider_current_trx, SPD_MID_GET_SHARE_2, __func__, __FILE__, __LINE__, MYF(MY_WME | MY_ZEROFILL), &spider->conn_keys, sizeof(char *) * share->link_count, &tmp_name, sizeof(char) * share->conn_keys_charlen, @@ -5749,7 +5749,7 @@ SPIDER_LGTM_TBLHND_SHARE *spider_get_lgtm_tblhnd_share( { DBUG_PRINT("info",("spider create new lgtm tblhnd share")); if (!(lgtm_tblhnd_share = (SPIDER_LGTM_TBLHND_SHARE *) - spider_bulk_malloc(spider_current_trx, 244, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_GET_LGTM_TBLHND_SHARE_1, MYF(MY_WME | MY_ZEROFILL), &lgtm_tblhnd_share, sizeof(*lgtm_tblhnd_share), &tmp_name, table_name_length + 1, NullS)) @@ -5859,7 +5859,7 @@ SPIDER_PARTITION_SHARE *spider_get_pt_share( { DBUG_PRINT("info",("spider create new pt share")); if (!(partition_share = (SPIDER_PARTITION_SHARE *) - spider_bulk_malloc(spider_current_trx, 51, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_GET_PT_SHARE_1, MYF(MY_WME | MY_ZEROFILL), &partition_share, sizeof(*partition_share), &tmp_name, table_share->path.length + 1, &tmp_cardinality, sizeof(*tmp_cardinality) * table_share->fields, @@ -5923,7 +5923,7 @@ SPIDER_PARTITION_SHARE *spider_get_pt_share( *error_num = HA_ERR_OUT_OF_MEM; goto error_init_pt_handler_hash; } - spider_alloc_calc_mem_init(partition_share->pt_handler_hash, 142); + spider_alloc_calc_mem_init(partition_share->pt_handler_hash, SPD_MID_GET_PT_SHARE_2); spider_alloc_calc_mem(spider_current_trx, partition_share->pt_handler_hash, partition_share->pt_handler_hash.array.max_element * @@ -6214,7 +6214,7 @@ int spider_open_all_tables( spider->lock_type = TL_READ_NO_INSERT; if (!(share = (SPIDER_SHARE *) - spider_bulk_malloc(spider_current_trx, 52, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_OPEN_ALL_TABLES_1, MYF(MY_WME | MY_ZEROFILL), &share, sizeof(*share), &connect_info, sizeof(char *) * SPIDER_TMP_SHARE_CHAR_PTR_COUNT, &connect_info_length, sizeof(uint) * SPIDER_TMP_SHARE_UINT_COUNT, @@ -6972,7 +6972,7 @@ int spider_db_init( (my_hash_get_key) spider_tbl_get_key, 0, 0)) goto error_open_tables_hash_init; - spider_alloc_calc_mem_init(spider_open_tables, 143); + spider_alloc_calc_mem_init(spider_open_tables, SPD_MID_DB_INIT_1); spider_alloc_calc_mem(NULL, spider_open_tables, spider_open_tables.array.max_element * @@ -6981,7 +6981,7 @@ int spider_db_init( (my_hash_get_key) spider_tbl_get_key, 0, 0)) goto error_init_error_tables_hash_init; - spider_alloc_calc_mem_init(spider_init_error_tables, 144); + spider_alloc_calc_mem_init(spider_init_error_tables, SPD_MID_DB_INIT_2); spider_alloc_calc_mem(NULL, spider_init_error_tables, spider_init_error_tables.array.max_element * @@ -6991,7 +6991,7 @@ int spider_db_init( (my_hash_get_key) spider_pt_share_get_key, 0, 0)) goto error_open_pt_share_hash_init; - spider_alloc_calc_mem_init(spider_open_pt_share, 145); + spider_alloc_calc_mem_init(spider_open_pt_share, SPD_MID_DB_INIT_3); spider_alloc_calc_mem(NULL, spider_open_pt_share, spider_open_pt_share.array.max_element * @@ -7003,7 +7003,7 @@ int spider_db_init( 0, 0)) goto error_lgtm_tblhnd_share_hash_init; - spider_alloc_calc_mem_init(spider_lgtm_tblhnd_share_hash, 245); + spider_alloc_calc_mem_init(spider_lgtm_tblhnd_share_hash, SPD_MID_DB_INIT_4); spider_alloc_calc_mem(NULL, spider_lgtm_tblhnd_share_hash, spider_lgtm_tblhnd_share_hash.array.max_element * @@ -7017,7 +7017,7 @@ int spider_db_init( spider_free_ipport_conn, 0)) goto error_ipport_conn__hash_init; - spider_alloc_calc_mem_init(spider_open_connections, 146); + spider_alloc_calc_mem_init(spider_open_connections, SPD_MID_DB_INIT_5); spider_alloc_calc_mem(NULL, spider_open_connections, spider_open_connections.array.max_element * @@ -7027,7 +7027,7 @@ int spider_db_init( (my_hash_get_key) spider_conn_get_key, 0, 0)) goto error_hs_r_conn_hash_init; - spider_alloc_calc_mem_init(spider_hs_r_conn_hash, 147); + spider_alloc_calc_mem_init(spider_hs_r_conn_hash, SPD_MID_DB_INIT_6); spider_alloc_calc_mem(NULL, spider_hs_r_conn_hash, spider_hs_r_conn_hash.array.max_element * @@ -7036,7 +7036,7 @@ int spider_db_init( (my_hash_get_key) spider_conn_get_key, 0, 0)) goto error_hs_w_conn_hash_init; - spider_alloc_calc_mem_init(spider_hs_w_conn_hash, 148); + spider_alloc_calc_mem_init(spider_hs_w_conn_hash, SPD_MID_DB_INIT_7); spider_alloc_calc_mem(NULL, spider_hs_w_conn_hash, spider_hs_w_conn_hash.array.max_element * @@ -7046,7 +7046,7 @@ int spider_db_init( (my_hash_get_key) spider_allocated_thds_get_key, 0, 0)) goto error_allocated_thds_hash_init; - spider_alloc_calc_mem_init(spider_allocated_thds, 149); + spider_alloc_calc_mem_init(spider_allocated_thds, SPD_MID_DB_INIT_8); spider_alloc_calc_mem(NULL, spider_allocated_thds, spider_allocated_thds.array.max_element * @@ -7056,14 +7056,14 @@ int spider_db_init( NULL, 64, 64, MYF(MY_WME))) goto error_mon_table_cache_array_init; - spider_alloc_calc_mem_init(spider_mon_table_cache, 165); + spider_alloc_calc_mem_init(spider_mon_table_cache, SPD_MID_DB_INIT_9); spider_alloc_calc_mem(NULL, spider_mon_table_cache, spider_mon_table_cache.max_element * spider_mon_table_cache.size_of_element); if (!(spider_udf_table_mon_mutexes = (pthread_mutex_t *) - spider_bulk_malloc(NULL, 53, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(NULL, SPD_MID_DB_INIT_10, MYF(MY_WME | MY_ZEROFILL), &spider_udf_table_mon_mutexes, sizeof(pthread_mutex_t) * spider_param_udf_table_mon_mutex_count(), &spider_udf_table_mon_conds, sizeof(pthread_cond_t) * @@ -7108,7 +7108,7 @@ int spider_db_init( (my_hash_get_key) spider_udf_tbl_mon_list_key, 0, 0)) goto error_init_udf_table_mon_list_hash; - spider_alloc_calc_mem_init(spider_udf_table_mon_list_hash, 150); + spider_alloc_calc_mem_init(spider_udf_table_mon_list_hash, SPD_MID_DB_INIT_11); spider_alloc_calc_mem(NULL, spider_udf_table_mon_list_hash, spider_udf_table_mon_list_hash[roop_count].array.max_element * @@ -7117,7 +7117,7 @@ int spider_db_init( #ifndef WITHOUT_SPIDER_BG_SEARCH if (!(spider_table_sts_threads = (SPIDER_THREAD *) - spider_bulk_malloc(NULL, 256, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(NULL, SPD_MID_DB_INIT_12, MYF(MY_WME | MY_ZEROFILL), &spider_table_sts_threads, sizeof(SPIDER_THREAD) * spider_param_table_sts_thread_count(), &spider_table_crd_threads, sizeof(SPIDER_THREAD) * @@ -7330,7 +7330,7 @@ char *spider_create_string( ) { char *res; DBUG_ENTER("spider_create_string"); - if (!(res = (char*) spider_malloc(spider_current_trx, 13, length + 1, + if (!(res = (char*) spider_malloc(spider_current_trx, SPD_MID_CREATE_STRING_1, length + 1, MYF(MY_WME)))) DBUG_RETURN(NULL); memcpy(res, str, length); @@ -7352,7 +7352,7 @@ char *spider_create_table_name_string( if (sub_name) length += sizeof("#SP#") - 1 + strlen(sub_name); } - if (!(res = (char*) spider_malloc(spider_current_trx, 14, length + 1, + if (!(res = (char*) spider_malloc(spider_current_trx, SPD_MID_CREATE_TABLE_NAME_STRING_1, length + 1, MYF(MY_WME)))) DBUG_RETURN(NULL); tmp = strmov(res, table_name); @@ -7816,7 +7816,7 @@ SPIDER_INIT_ERROR_TABLE *spider_get_init_error_table( DBUG_RETURN(NULL); } if (!(spider_init_error_table = (SPIDER_INIT_ERROR_TABLE *) - spider_bulk_malloc(spider_current_trx, 54, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_GET_INIT_ERROR_TABLE_1, MYF(MY_WME | MY_ZEROFILL), &spider_init_error_table, sizeof(*spider_init_error_table), &tmp_name, share->table_name_length + 1, NullS)) @@ -7930,7 +7930,7 @@ bool spider_check_hs_pk_update( tmp_str2(buf2, MAX_FIELD_WIDTH, &my_charset_bin); String *str, *str2; DBUG_ENTER("spider_check_hs_pk_update"); - tmp_str.init_calc_mem(137); + tmp_str.init_calc_mem(SPD_MID_CHECK_HS_PK_UPDATE_1); if (table_share->primary_key == MAX_KEY) DBUG_RETURN(FALSE); @@ -9122,7 +9122,7 @@ int spider_discover_table_structure( char buf[MAX_FIELD_WIDTH]; spider_string str(buf, sizeof(buf), system_charset_info); DBUG_ENTER("spider_discover_table_structure"); - str.init_calc_mem(229); + str.init_calc_mem(SPD_MID_DISCOVER_TABLE_STRUCTURE_1); str.length(0); if (str.reserve( SPIDER_SQL_CREATE_TABLE_LEN + share->db.length + @@ -9493,7 +9493,7 @@ int spider_create_spider_object_for_share( DBUG_PRINT("info",("spider spider=%p", (*spider))); #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) if (!(need_mons = (int *) - spider_bulk_malloc(spider_current_trx, 255, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_CREATE_SPIDER_OBJECT_FOR_SHARE_1, MYF(MY_WME | MY_ZEROFILL), &need_mons, (sizeof(int) * share->link_count), &conns, (sizeof(SPIDER_CONN *) * share->link_count), &conn_link_idx, (sizeof(uint) * share->link_count), @@ -9506,7 +9506,7 @@ int spider_create_spider_object_for_share( ) #else if (!(need_mons = (int *) - spider_bulk_malloc(spider_current_trx, 255, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_CREATE_SPIDER_OBJECT_FOR_SHARE_2, MYF(MY_WME | MY_ZEROFILL), &need_mons, (sizeof(int) * share->link_count), &conns, (sizeof(SPIDER_CONN *) * share->link_count), &conn_link_idx, (sizeof(uint) * share->link_count), diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index cfdbedee069..b39a398376c 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -251,7 +251,7 @@ int spider_trx_another_lock_tables( spider_string sql_str(sql_buf, sizeof(sql_buf), system_charset_info); DBUG_ENTER("spider_trx_another_lock_tables"); SPIDER_BACKUP_DASTATUS; - sql_str.init_calc_mem(188); + sql_str.init_calc_mem(SPD_MID_TRX_ANOTHER_LOCK_TABLES_1); sql_str.length(0); memset((void*)&tmp_spider, 0, sizeof(ha_spider)); memset((void*)&tmp_share, 0, sizeof(SPIDER_SHARE)); @@ -564,7 +564,7 @@ int spider_create_trx_alter_table( share_alter = &share->alter_table; if (!(alter_table = (SPIDER_ALTER_TABLE *) - spider_bulk_malloc(spider_current_trx, 55, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(spider_current_trx, SPD_MID_CREATE_TRX_ALTER_TABLE_1, MYF(MY_WME | MY_ZEROFILL), &alter_table, sizeof(*alter_table), &tmp_name, sizeof(char) * (share->table_name_length + 1), @@ -1177,7 +1177,7 @@ SPIDER_TRX *spider_get_trx( ) { DBUG_PRINT("info",("spider create new trx")); if (!(trx = (SPIDER_TRX *) - spider_bulk_malloc(NULL, 56, MYF(MY_WME | MY_ZEROFILL), + spider_bulk_malloc(NULL, SPD_MID_GET_TRX_1, MYF(MY_WME | MY_ZEROFILL), &trx, sizeof(*trx), &tmp_share, sizeof(SPIDER_SHARE), &udf_table_mutexes, sizeof(pthread_mutex_t) * @@ -1209,7 +1209,7 @@ SPIDER_TRX *spider_get_trx( (my_hash_get_key) spider_conn_get_key, 0, 0) ) goto error_init_hash; - spider_alloc_calc_mem_init(trx->trx_conn_hash, 151); + spider_alloc_calc_mem_init(trx->trx_conn_hash, SPD_MID_GET_TRX_2); spider_alloc_calc_mem( thd ? ((SPIDER_TRX *) thd_get_ha_data(thd, spider_hton_ptr)) : NULL, trx->trx_conn_hash, @@ -1221,7 +1221,7 @@ SPIDER_TRX *spider_get_trx( (my_hash_get_key) spider_conn_get_key, 0, 0) ) goto error_init_another_hash; - spider_alloc_calc_mem_init(trx->trx_another_conn_hash, 152); + spider_alloc_calc_mem_init(trx->trx_another_conn_hash, SPD_MID_GET_TRX_3); spider_alloc_calc_mem( thd ? ((SPIDER_TRX *) thd_get_ha_data(thd, spider_hton_ptr)) : NULL, trx->trx_another_conn_hash, @@ -1234,7 +1234,7 @@ SPIDER_TRX *spider_get_trx( (my_hash_get_key) spider_conn_get_key, 0, 0) ) goto error_hs_r_init_hash; - spider_alloc_calc_mem_init(trx->trx_hs_r_conn_hash, 153); + spider_alloc_calc_mem_init(trx->trx_hs_r_conn_hash, SPD_MID_GET_TRX_4); spider_alloc_calc_mem( thd ? ((SPIDER_TRX *) thd_get_ha_data(thd, spider_hton_ptr)) : NULL, trx->trx_hs_r_conn_hash, @@ -1246,7 +1246,7 @@ SPIDER_TRX *spider_get_trx( (my_hash_get_key) spider_conn_get_key, 0, 0) ) goto error_hs_w_init_hash; - spider_alloc_calc_mem_init(trx->trx_hs_w_conn_hash, 154); + spider_alloc_calc_mem_init(trx->trx_hs_w_conn_hash, SPD_MID_GET_TRX_5); spider_alloc_calc_mem( thd ? ((SPIDER_TRX *) thd_get_ha_data(thd, spider_hton_ptr)) : NULL, trx->trx_hs_w_conn_hash, @@ -1260,7 +1260,7 @@ SPIDER_TRX *spider_get_trx( 0, 0, (my_hash_get_key) spider_conn_get_key, 0, 0) ) goto error_direct_hs_r_init_hash; - spider_alloc_calc_mem_init(trx->trx_direct_hs_r_conn_hash, 155); + spider_alloc_calc_mem_init(trx->trx_direct_hs_r_conn_hash, SPD_MID_GET_TRX_6); spider_alloc_calc_mem( thd ? ((SPIDER_TRX *) thd_get_ha_data(thd, spider_hton_ptr)) : NULL, trx->trx_direct_hs_r_conn_hash, @@ -1272,7 +1272,7 @@ SPIDER_TRX *spider_get_trx( 0, 0, (my_hash_get_key) spider_conn_get_key, 0, 0) ) goto error_direct_hs_w_init_hash; - spider_alloc_calc_mem_init(trx->trx_direct_hs_w_conn_hash, 156); + spider_alloc_calc_mem_init(trx->trx_direct_hs_w_conn_hash, SPD_MID_GET_TRX_7); spider_alloc_calc_mem( thd ? ((SPIDER_TRX *) thd_get_ha_data(thd, spider_hton_ptr)) : NULL, trx->trx_direct_hs_w_conn_hash, @@ -1285,7 +1285,7 @@ SPIDER_TRX *spider_get_trx( (my_hash_get_key) spider_alter_tbl_get_key, 0, 0) ) goto error_init_alter_hash; - spider_alloc_calc_mem_init(trx->trx_alter_table_hash, 157); + spider_alloc_calc_mem_init(trx->trx_alter_table_hash, SPD_MID_GET_TRX_8); spider_alloc_calc_mem( thd ? ((SPIDER_TRX *) thd_get_ha_data(thd, spider_hton_ptr)) : NULL, trx->trx_alter_table_hash, @@ -1297,7 +1297,7 @@ SPIDER_TRX *spider_get_trx( (my_hash_get_key) spider_trx_ha_get_key, 0, 0) ) goto error_init_trx_ha_hash; - spider_alloc_calc_mem_init(trx->trx_ha_hash, 158); + spider_alloc_calc_mem_init(trx->trx_ha_hash, SPD_MID_GET_TRX_9); spider_alloc_calc_mem( thd ? ((SPIDER_TRX *) thd_get_ha_data(thd, spider_hton_ptr)) : NULL, trx->trx_ha_hash, @@ -1361,7 +1361,7 @@ SPIDER_TRX *spider_get_trx( for (roop_count2 = 0; roop_count2 < (int) trx->tmp_share->link_count; ++roop_count2) { - trx->tmp_spider->result_list.sqls[roop_count2].init_calc_mem(121); + trx->tmp_spider->result_list.sqls[roop_count2].init_calc_mem(SPD_MID_GET_TRX_10); trx->tmp_spider->result_list.sqls[roop_count2].set_charset( trx->tmp_share->access_charset); } @@ -4183,7 +4183,7 @@ int spider_create_trx_ha( if (need_create) { if (!(trx_ha = (SPIDER_TRX_HA *) - spider_bulk_malloc(spider_current_trx, 58, MYF(MY_WME), + spider_bulk_malloc(spider_current_trx, SPD_MID_CREATE_TRX_HA_1, MYF(MY_WME), &trx_ha, sizeof(SPIDER_TRX_HA), &tmp_name, sizeof(char *) * (share->table_name_length + 1), &conn_link_idx, sizeof(uint) * share->link_count, From 3ba041f9f5ef47bbc3c4a1d48306e2dfc3817f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 20 Nov 2023 13:44:47 +0200 Subject: [PATCH 287/477] MDEV-31953 fixup: Clean up the test Let us tolerate multiple "Memory pressure event freed" in case there a real memory pressure event occurred in addition to the one that this test simulates. Also, clean up some SET variables. --- mysql-test/suite/innodb/r/mem_pressure.result | 10 ++++------ mysql-test/suite/innodb/t/mem_pressure.test | 12 ++++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/mysql-test/suite/innodb/r/mem_pressure.result b/mysql-test/suite/innodb/r/mem_pressure.result index c732bee78f2..b1127db8673 100644 --- a/mysql-test/suite/innodb/r/mem_pressure.result +++ b/mysql-test/suite/innodb/r/mem_pressure.result @@ -3,14 +3,12 @@ # set @save_dbug=@@debug_dbug; set @save_limit=@@GLOBAL.innodb_limit_optimistic_insert_debug; -set @save_lag_wait=@@GLOBAL.innodb_max_purge_lag_wait; set GLOBAL innodb_max_purge_lag_wait=0; -CREATE TABLE t1 (t TEXT) ENGINE=InnoDB; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; SET GLOBAL innodb_limit_optimistic_insert_debug=2; -SET unique_checks=0, foreign_key_checks=0; -INSERT INTO t1 SELECT CONCAT(REPEAT('junk text', 500), CAST(seq AS CHAR)) FROM seq_1_to_1000; +SET STATEMENT unique_checks=0, foreign_key_checks=0 FOR +INSERT INTO t1 SELECT * FROM seq_1_to_1000; SET GLOBAL innodb_limit_optimistic_insert_debug=@save_limit; -SET GLOBAL innodb_max_purge_lag_wait=@save_lag_wait; DROP TABLE t1; SELECT CAST(VARIABLE_VALUE AS INTEGER) INTO @dirty_prev FROM INFORMATION_SCHEMA.GLOBAL_STATUS @@ -22,6 +20,6 @@ FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME='Innodb_buffer_pool_pages_dirty'; LESS_DIRTY_IS_GOOD 1 -FOUND 1 /InnoDB: Memory pressure event freed/ in mysqld.1.err +FOUND 1 /InnoDB: Memory pressure event freed.*/ in mysqld.1.err set debug_dbug=@save_dbug; # End of 10.11 tests diff --git a/mysql-test/suite/innodb/t/mem_pressure.test b/mysql-test/suite/innodb/t/mem_pressure.test index bd25b64c23e..91f75e65795 100644 --- a/mysql-test/suite/innodb/t/mem_pressure.test +++ b/mysql-test/suite/innodb/t/mem_pressure.test @@ -11,16 +11,16 @@ set @save_dbug=@@debug_dbug; set @save_limit=@@GLOBAL.innodb_limit_optimistic_insert_debug; -set @save_lag_wait=@@GLOBAL.innodb_max_purge_lag_wait; +# Wait for the undo logs to be empty from previous tests. +# This is not an actual parameter, so there is no need to restore it. set GLOBAL innodb_max_purge_lag_wait=0; -CREATE TABLE t1 (t TEXT) ENGINE=InnoDB; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; SET GLOBAL innodb_limit_optimistic_insert_debug=2; -SET unique_checks=0, foreign_key_checks=0; -INSERT INTO t1 SELECT CONCAT(REPEAT('junk text', 500), CAST(seq AS CHAR)) FROM seq_1_to_1000; +SET STATEMENT unique_checks=0, foreign_key_checks=0 FOR +INSERT INTO t1 SELECT * FROM seq_1_to_1000; SET GLOBAL innodb_limit_optimistic_insert_debug=@save_limit; -SET GLOBAL innodb_max_purge_lag_wait=@save_lag_wait; DROP TABLE t1; @@ -36,7 +36,7 @@ FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME='Innodb_buffer_pool_pages_dirty'; let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; -let SEARCH_PATTERN= InnoDB: Memory pressure event freed; +let SEARCH_PATTERN= InnoDB: Memory pressure event freed.*; --source include/search_pattern_in_file.inc set debug_dbug=@save_dbug; From 7aca66a36a804cde38bebae4692b8560f8df4fa2 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Mon, 14 Jun 2021 21:59:49 +0200 Subject: [PATCH 288/477] MDEV-25916: Compilation failed for compile-pentium64-gcov script - Commit e3bffd579f4a introduced the change - Fixed with commit 2d857144485f in 10.4 (no removal of `Wimplicit-fallthrough=2`) - Fixed with commit 4a75b480e99c945c1c9c41669b85c96096da058b in 10.5+ - Closing PR #2817 Reviewed by: --- BUILD/SETUP.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 546955b60a1..f4ffe128b2c 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -141,7 +141,7 @@ elif [ "x$warning_mode" = "xmaintainer" ]; then debug_extra_cflags="-g3" else # Both C and C++ warnings - warnings="-Wall -Wextra -Wunused -Wwrite-strings -Wno-uninitialized -Wno-strict-aliasing -Wimplicit-fallthrough=2 -Wformat-security -Wvla" + warnings="-Wall -Wextra -Wunused -Wwrite-strings -Wno-uninitialized -Wno-strict-aliasing -Wformat-security -Wvla" # For more warnings, uncomment the following line # warnings="$warnings -Wshadow" From cd04673a177d40f7c409284d87ead851ec775c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 20 Nov 2023 16:57:57 +0200 Subject: [PATCH 289/477] MDEV-32050 fixup: innodb.instant_alter_crash (take 2) We must disable persistent statistics, because a transaction commit from dict_stats_save() would occasionally interfere with this test. --- mysql-test/suite/innodb/r/instant_alter_crash.result | 7 +++---- mysql-test/suite/innodb/t/instant_alter_crash.test | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/innodb/r/instant_alter_crash.result b/mysql-test/suite/innodb/r/instant_alter_crash.result index b92f8ee8724..e423afe10a8 100644 --- a/mysql-test/suite/innodb/r/instant_alter_crash.result +++ b/mysql-test/suite/innodb/r/instant_alter_crash.result @@ -3,7 +3,7 @@ FLUSH TABLES; # MDEV-11369: Instant ADD COLUMN for InnoDB # CREATE TABLE t1(id INT PRIMARY KEY, c2 INT UNIQUE) -ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +ENGINE=InnoDB STATS_PERSISTENT=0 ROW_FORMAT=REDUNDANT; CREATE TABLE t2 LIKE t1; INSERT INTO t1 VALUES(0,2); INSERT INTO t2 VALUES(2,1); @@ -27,7 +27,6 @@ SELECT * FROM t2; id c2 c3 2 1 De finibus bonorum 3 4 accusantium doloremque laudantium -InnoDB 0 transactions not purged BEGIN; DELETE FROM t1; ROLLBACK; @@ -161,7 +160,7 @@ t1 CREATE TABLE `t1` ( `c2` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `c2` (`c2`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=REDUNDANT +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_PERSISTENT=0 ROW_FORMAT=REDUNDANT SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( @@ -169,7 +168,7 @@ t2 CREATE TABLE `t2` ( `c2` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `c2` (`c2`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=REDUNDANT +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_PERSISTENT=0 ROW_FORMAT=REDUNDANT SHOW CREATE TABLE t3; Table Create Table t3 CREATE TABLE `t3` ( diff --git a/mysql-test/suite/innodb/t/instant_alter_crash.test b/mysql-test/suite/innodb/t/instant_alter_crash.test index 8eb03b39a1b..f51f61e3c04 100644 --- a/mysql-test/suite/innodb/t/instant_alter_crash.test +++ b/mysql-test/suite/innodb/t/instant_alter_crash.test @@ -14,7 +14,7 @@ let MYSQLD_DATADIR=`select @@datadir`; --echo # CREATE TABLE t1(id INT PRIMARY KEY, c2 INT UNIQUE) -ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +ENGINE=InnoDB STATS_PERSISTENT=0 ROW_FORMAT=REDUNDANT; CREATE TABLE t2 LIKE t1; INSERT INTO t1 VALUES(0,2); INSERT INTO t2 VALUES(2,1); @@ -38,7 +38,6 @@ disconnect ddl; SELECT * FROM t1; SELECT * FROM t2; ---source include/wait_all_purged.inc BEGIN; DELETE FROM t1; ROLLBACK; From d415f600cde322288742596e870685a03ebc2ecf Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Mon, 20 Nov 2023 15:01:26 +0100 Subject: [PATCH 290/477] MDEV-32844: THD::rli_fake/rgi_fake not cleared on new connection Signed-off-by: Kristian Nielsen --- .../r/pseudo_slave_mode_notembedded.result | 14 +++++++++++++ .../t/pseudo_slave_mode_notembedded.test | 20 +++++++++++++++++++ sql/sql_class.cc | 15 ++++---------- 3 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 mysql-test/suite/sys_vars/r/pseudo_slave_mode_notembedded.result create mode 100644 mysql-test/suite/sys_vars/t/pseudo_slave_mode_notembedded.test diff --git a/mysql-test/suite/sys_vars/r/pseudo_slave_mode_notembedded.result b/mysql-test/suite/sys_vars/r/pseudo_slave_mode_notembedded.result new file mode 100644 index 00000000000..3246a309638 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/pseudo_slave_mode_notembedded.result @@ -0,0 +1,14 @@ +'### MDEV-32844: THD::rli_fake/rgi_fake not cleared on new connection' +connect con1,localhost,root,,; +BINLOG ' +6ENbZQ8BAAAA/AAAAAABAAAAAAQAMTAuMTEuNi1NYXJpYURCLWRlYnVnLWxvZwAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAADoQ1tlEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAEEwQADQgICAoKCgGbvv33 +'; +disconnect con1; +connect con1,localhost,root,,; +SET SESSION pseudo_slave_mode= 1; +disconnect con1; +connection default; diff --git a/mysql-test/suite/sys_vars/t/pseudo_slave_mode_notembedded.test b/mysql-test/suite/sys_vars/t/pseudo_slave_mode_notembedded.test new file mode 100644 index 00000000000..c18872dba0e --- /dev/null +++ b/mysql-test/suite/sys_vars/t/pseudo_slave_mode_notembedded.test @@ -0,0 +1,20 @@ +--source include/not_embedded.inc +--source include/load_sysvars.inc + +--echo '### MDEV-32844: THD::rli_fake/rgi_fake not cleared on new connection' +--connect(con1,localhost,root,,) +BINLOG ' +6ENbZQ8BAAAA/AAAAAABAAAAAAQAMTAuMTEuNi1NYXJpYURCLWRlYnVnLWxvZwAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAADoQ1tlEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAEEwQADQgICAoKCgGbvv33 +'; +--disconnect con1 +--connect(con1,localhost,root,,) +# The bug was that the THD::rli_fake was not cleared when the THD is re-used +# for the new connection, and we would get a warning from the following +# statement. +SET SESSION pseudo_slave_mode= 1; +--disconnect con1 +--connection default diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 0f83b3d4c08..bee793b7d0f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1593,6 +1593,10 @@ void THD::free_connection() vio_delete(net.vio); net.vio= nullptr; net_end(&net); + delete(rgi_fake); + rgi_fake= NULL; + delete(rli_fake); + rli_fake= NULL; #endif if (!cleanup_done) cleanup(); @@ -1695,17 +1699,6 @@ THD::~THD() dbug_sentry= THD_SENTRY_GONE; #endif #ifndef EMBEDDED_LIBRARY - if (rgi_fake) - { - delete rgi_fake; - rgi_fake= NULL; - } - if (rli_fake) - { - delete rli_fake; - rli_fake= NULL; - } - if (rgi_slave) rgi_slave->cleanup_after_session(); my_free(semisync_info); From 45fadb64c1c4ad7c71fea874d51c83b1d11b4e63 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 14 Nov 2023 12:13:04 +1100 Subject: [PATCH 291/477] MDEV-32753 Make spider init queries compatible with oracle sql mode Remove ORACLE from the (session) sql_mode in connections made with sql service to run init queries The connection is new and the global variable value takes effect rather than the session value from the caller of spider_db_init. --- .../spider/bugfix/r/mdev_32753.result | 10 +++++++++ .../bugfix/r/mdev_32753_after_start.result | 14 ++++++++++++ .../r/mdev_32753_after_start_session.result | 17 ++++++++++++++ .../mysql-test/spider/bugfix/t/mdev_32753.opt | 2 ++ .../spider/bugfix/t/mdev_32753.test | 12 ++++++++++ .../bugfix/t/mdev_32753_after_start.opt | 1 + .../bugfix/t/mdev_32753_after_start.test | 19 ++++++++++++++++ .../t/mdev_32753_after_start_session.test | 22 +++++++++++++++++++ .../spider/include/clean_up_spider.inc | 2 +- storage/spider/spd_init_query.h | 3 +++ 10 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_32753.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start_session.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_32753.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_32753.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start_session.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_32753.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_32753.result new file mode 100644 index 00000000000..4260d80f0cf --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_32753.result @@ -0,0 +1,10 @@ +# +# MDEV-32753 Spider engine does not load in ORACLE mode +# +select * from mysql.plugin; +name dl +create table t (c int) Engine=SPIDER; +drop table t; +# +# end of test mdev_32753 +# diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start.result new file mode 100644 index 00000000000..4e046d16708 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start.result @@ -0,0 +1,14 @@ +# +# MDEV-32753 Spider engine does not load in ORACLE mode +# +install soname 'ha_spider'; +select * from mysql.plugin; +name dl +SPIDER ha_spider.so +SPIDER_ALLOC_MEM ha_spider.so +SPIDER_WRAPPER_PROTOCOLS ha_spider.so +create table t (c int) Engine=SPIDER; +drop table t; +# +# end of test mdev_32753_after_start +# diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start_session.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start_session.result new file mode 100644 index 00000000000..b9d025633e2 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start_session.result @@ -0,0 +1,17 @@ +# +# MDEV-32753 Spider engine does not load in ORACLE mode +# +set @old_sql_mode=@@sql_mode; +SET @@sql_mode = CONCAT(@@sql_mode, ',ORACLE'); +install soname 'ha_spider'; +select * from mysql.plugin; +name dl +SPIDER ha_spider.so +SPIDER_ALLOC_MEM ha_spider.so +SPIDER_WRAPPER_PROTOCOLS ha_spider.so +create table t (c int) Engine=SPIDER; +drop table t; +set sql_mode=@old_sql_mode; +# +# end of test mdev_32753_after_start +# diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32753.opt b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753.opt new file mode 100644 index 00000000000..c3151b0e44a --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753.opt @@ -0,0 +1,2 @@ +--sql-mode=oracle +--plugin-load-add=ha_spider diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32753.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753.test new file mode 100644 index 00000000000..2be7289fd74 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753.test @@ -0,0 +1,12 @@ +--echo # +--echo # MDEV-32753 Spider engine does not load in ORACLE mode +--echo # + +# This test tests spider init during server startup under global +# ORACLE mode +select * from mysql.plugin; +create table t (c int) Engine=SPIDER; +drop table t; +--echo # +--echo # end of test mdev_32753 +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.opt b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.opt new file mode 100644 index 00000000000..a918abb90b9 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.opt @@ -0,0 +1 @@ +--sql-mode=oracle diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.test new file mode 100644 index 00000000000..281d2adce64 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.test @@ -0,0 +1,19 @@ +--echo # +--echo # MDEV-32753 Spider engine does not load in ORACLE mode +--echo # + +# This test tests spider init after startup under global ORACLE mode +install soname 'ha_spider'; +select * from mysql.plugin; +create table t (c int) Engine=SPIDER; +drop table t; + +--disable_query_log +--disable_result_log +--source ../../include/clean_up_spider.inc +--enable_result_log +--enable_query_log + +--echo # +--echo # end of test mdev_32753_after_start +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start_session.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start_session.test new file mode 100644 index 00000000000..bf7bdb4f884 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start_session.test @@ -0,0 +1,22 @@ +--echo # +--echo # MDEV-32753 Spider engine does not load in ORACLE mode +--echo # + +# This test tests spider init after startup under session ORACLE mode +set @old_sql_mode=@@sql_mode; +SET @@sql_mode = CONCAT(@@sql_mode, ',ORACLE'); +install soname 'ha_spider'; +select * from mysql.plugin; +create table t (c int) Engine=SPIDER; +drop table t; +set sql_mode=@old_sql_mode; + +--disable_query_log +--disable_result_log +--source ../../include/clean_up_spider.inc +--enable_result_log +--enable_query_log + +--echo # +--echo # end of test mdev_32753_after_start +--echo # diff --git a/storage/spider/mysql-test/spider/include/clean_up_spider.inc b/storage/spider/mysql-test/spider/include/clean_up_spider.inc index 1f0659dc98a..249606ec774 100644 --- a/storage/spider/mysql-test/spider/include/clean_up_spider.inc +++ b/storage/spider/mysql-test/spider/include/clean_up_spider.inc @@ -3,7 +3,7 @@ DROP FUNCTION spider_copy_tables; DROP FUNCTION spider_ping_table; DROP FUNCTION spider_bg_direct_sql; DROP FUNCTION spider_direct_sql; -UNINSTALL SONAME IF EXISTS "ha_spider"; +UNINSTALL SONAME IF EXISTS 'ha_spider'; DROP TABLE IF EXISTS mysql.spider_xa; DROP TABLE IF EXISTS mysql.spider_xa_member; DROP TABLE IF EXISTS mysql.spider_xa_failed_log; diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h index fdf6b22fe27..ef234ac6c6f 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -20,6 +20,9 @@ */ static LEX_STRING spider_init_queries[] = { + {C_STRING_WITH_LEN( + "SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'ORACLE', '');" + )}, {C_STRING_WITH_LEN( "create table if not exists mysql.spider_xa(" " format_id int not null default 0," From 9656573376516807b41066dd5f0ff7fa316946fc Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 8 Nov 2023 16:40:54 +1100 Subject: [PATCH 292/477] MDEV-27575 Remove thd from spider_db_done It is unused, and causing segfaults --- .../spider/bugfix/r/mdev_27575.result | 16 +++++++++++++ .../spider/bugfix/t/mdev_27575.test | 23 +++++++++++++++++++ storage/spider/spd_table.cc | 22 +----------------- 3 files changed, 40 insertions(+), 21 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result new file mode 100644 index 00000000000..91af2c8f1e0 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result @@ -0,0 +1,16 @@ +# +# MDEV-27575 Spider: UBSAN member access within null pointer of type 'struct st_plugin_int and SIGSEGV in intern_plugin_lock on SHUTDOWN when setting Spider as default storage engine (temporary or global) +# +for master_1 +for child2 +for child3 +SET GLOBAL default_tmp_storage_engine=spider; +# restart +SET GLOBAL default_storage_engine=Spider; +# restart +for master_1 +for child2 +for child3 +# +# end of test mdev_27575 +# diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test new file mode 100644 index 00000000000..79a08489bae --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test @@ -0,0 +1,23 @@ +--echo # +--echo # MDEV-27575 Spider: UBSAN member access within null pointer of type 'struct st_plugin_int and SIGSEGV in intern_plugin_lock on SHUTDOWN when setting Spider as default storage engine (temporary or global) +--echo # +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +SET GLOBAL default_tmp_storage_engine=spider; +--source include/restart_mysqld.inc + +SET GLOBAL default_storage_engine=Spider; +--source include/restart_mysqld.inc + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log +--echo # +--echo # end of test mdev_27575 +--echo # diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 0f614a01ccf..6f4882789fc 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -6451,26 +6451,13 @@ int spider_db_done( void *p ) { int roop_count; - bool do_delete_thd; - THD *thd = current_thd, *tmp_thd; + THD *tmp_thd; SPIDER_CONN *conn; SPIDER_INIT_ERROR_TABLE *spider_init_error_table; SPIDER_TABLE_MON_LIST *table_mon_list; SPIDER_LGTM_TBLHND_SHARE *lgtm_tblhnd_share; DBUG_ENTER("spider_db_done"); - /* Begin Spider plugin deinit */ - if (thd) - do_delete_thd = FALSE; - else - { - /* Create a thread for Spider plugin deinit */ - thd = spider_create_thd(); - if (!thd) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - do_delete_thd = TRUE; - } - for (roop_count = SPIDER_DBTON_SIZE - 1; roop_count >= 0; roop_count--) { if (spider_dbton[roop_count].deinit) @@ -6687,13 +6674,6 @@ int spider_db_done( )); } - /* End Spider plugin deinit */ - if (do_delete_thd) - spider_destroy_thd(thd); - -/* -DBUG_ASSERT(0); -*/ DBUG_RETURN(0); } From 84e0c027e03f016da9a7c9dd9ae69fa1303d1ae2 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 20 Nov 2023 14:58:28 +0530 Subject: [PATCH 293/477] MDEV-28613 LeakSanitizer caused by I_S query using LIMIT ROWS EXAMINED Problem: ======== - InnoDB fails to free the allocated buffer of stored cursor when information schema query is interrupted. Solution: ========= - In case of error handling, information schema query should free the allocated buffer to store the cursor. --- .../suite/innodb/r/innodb_stats_fetch.result | 22 +++ .../suite/innodb/t/innodb_stats_fetch.opt | 7 + .../suite/innodb/t/innodb_stats_fetch.test | 13 ++ storage/innobase/handler/i_s.cc | 153 ++++++++++++++---- 4 files changed, 160 insertions(+), 35 deletions(-) create mode 100644 mysql-test/suite/innodb/t/innodb_stats_fetch.opt diff --git a/mysql-test/suite/innodb/r/innodb_stats_fetch.result b/mysql-test/suite/innodb/r/innodb_stats_fetch.result index d7b7d78ec71..bcb3c48d4d9 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_fetch.result +++ b/mysql-test/suite/innodb/r/innodb_stats_fetch.result @@ -150,3 +150,25 @@ max_data_length 0 index_length 16384 DROP TABLE test_ps_fetch; set @@use_stat_tables = @save_use_stat_tables; +# +# MDEV-28613 LeakSanitizer caused by I_S query using LIMIT ROWS EXAMINED +# +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES LIMIT ROWS EXAMINED 5; +Warnings: +Level Warning +Code 1931 +Message Query execution was interrupted. The query exceeded LIMIT ROWS EXAMINED 5. The query result may be incomplete +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES LIMIT ROWS EXAMINED 5; +Warnings: +Level Warning +Code 1931 +Message Query execution was interrupted. The query exceeded LIMIT ROWS EXAMINED 5. The query result may be incomplete +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS LIMIT ROWS EXAMINED 5; +Warnings: +Level Warning +Code 1931 +Message Query execution was interrupted. The query exceeded LIMIT ROWS EXAMINED 5. The query result may be incomplete +SELECT SPACE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES LIMIT ROWS EXAMINED 5; +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_VIRTUAL LIMIT ROWS EXAMINED 5; +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN LIMIT ROWS EXAMINED 5; +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS LIMIT ROWS EXAMINED 5; diff --git a/mysql-test/suite/innodb/t/innodb_stats_fetch.opt b/mysql-test/suite/innodb/t/innodb_stats_fetch.opt new file mode 100644 index 00000000000..faa681c8dd7 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_stats_fetch.opt @@ -0,0 +1,7 @@ +--innodb_sys_tables +--innodb_sys_indexes +--innodb_sys_virtual +--innodb_sys_foreign +--innodb_sys_foreign_cols +--innodb_sys_tablestats +--innodb_sys_tablespaces diff --git a/mysql-test/suite/innodb/t/innodb_stats_fetch.test b/mysql-test/suite/innodb/t/innodb_stats_fetch.test index 549ad65feff..52946510304 100644 --- a/mysql-test/suite/innodb/t/innodb_stats_fetch.test +++ b/mysql-test/suite/innodb/t/innodb_stats_fetch.test @@ -81,3 +81,16 @@ FROM information_schema.tables WHERE table_name = 'test_ps_fetch'; DROP TABLE test_ps_fetch; set @@use_stat_tables = @save_use_stat_tables; + +--echo # +--echo # MDEV-28613 LeakSanitizer caused by I_S query using LIMIT ROWS EXAMINED +--echo # +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES LIMIT ROWS EXAMINED 5; +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES LIMIT ROWS EXAMINED 5; +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS LIMIT ROWS EXAMINED 5; +--disable_result_log +SELECT SPACE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES LIMIT ROWS EXAMINED 5; +--enable_result_log +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_VIRTUAL LIMIT ROWS EXAMINED 5; +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN LIMIT ROWS EXAMINED 5; +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS LIMIT ROWS EXAMINED 5; diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index f01c4162701..75f93000a34 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -5012,6 +5012,16 @@ i_s_dict_fill_sys_tables( DBUG_RETURN(0); } + +/** Handle the error for information schema query +@param err error value +@param thd thread +@return 0 if query is interrupted or error */ +static int i_s_sys_error_handling(int err, THD *thd) +{ + return thd_kill_level(thd) ? 0 : err; +} + /*******************************************************************//** Function to go through each record in SYS_TABLES table, and fill the information_schema.innodb_sys_tables table with related table information @@ -5028,6 +5038,7 @@ i_s_sys_tables_fill_table( const rec_t* rec; mem_heap_t* heap; mtr_t mtr; + int err = 0; DBUG_ENTER("i_s_sys_tables_fill_table"); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); @@ -5055,8 +5066,12 @@ i_s_sys_tables_fill_table( mutex_exit(&dict_sys.mutex); if (!err_msg) { - i_s_dict_fill_sys_tables(thd, table_rec, - tables->table); + err = i_s_dict_fill_sys_tables( + thd, table_rec, tables->table); + if (err) { + err = i_s_sys_error_handling(err, thd); + goto func_exit; + } } else { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANT_FIND_SYSTEM_REC, "%s", @@ -5077,9 +5092,11 @@ i_s_sys_tables_fill_table( mtr_commit(&mtr); mutex_exit(&dict_sys.mutex); +func_exit: mem_heap_free(heap); + ut_free(pcur.old_rec_buf); - DBUG_RETURN(0); + DBUG_RETURN(err); } /*******************************************************************//** @@ -5276,6 +5293,7 @@ i_s_sys_tables_fill_table_stats( const rec_t* rec; mem_heap_t* heap; mtr_t mtr; + int err = 0; DBUG_ENTER("i_s_sys_tables_fill_table_stats"); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); @@ -5311,8 +5329,13 @@ i_s_sys_tables_fill_table_stats( if (table_rec != NULL) { ut_ad(err_msg == NULL); - i_s_dict_fill_sys_tablestats(thd, table_rec, ref_count, - tables->table); + err = i_s_dict_fill_sys_tablestats( + thd, table_rec, ref_count, + tables->table); + if (err) { + err = i_s_sys_error_handling(err, thd); + goto func_exit; + } } else { ut_ad(err_msg != NULL); push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, @@ -5333,10 +5356,12 @@ i_s_sys_tables_fill_table_stats( mtr_commit(&mtr); mutex_exit(&dict_sys.mutex); +func_exit: rw_lock_s_unlock(&dict_sys.latch); mem_heap_free(heap); + ut_free(pcur.old_rec_buf); - DBUG_RETURN(0); + DBUG_RETURN(err); } /*******************************************************************//** @@ -5517,6 +5542,7 @@ i_s_sys_indexes_fill_table( const rec_t* rec; mem_heap_t* heap; mtr_t mtr; + int err = 0; DBUG_ENTER("i_s_sys_indexes_fill_table"); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); @@ -5552,11 +5578,13 @@ i_s_sys_indexes_fill_table( mutex_exit(&dict_sys.mutex); if (!err_msg) { - if (int err = i_s_dict_fill_sys_indexes( - thd, table_id, space_id, &index_rec, - tables->table)) { - mem_heap_free(heap); - DBUG_RETURN(err); + err = i_s_dict_fill_sys_indexes( + thd, table_id, space_id, + &index_rec, + tables->table); + if (err) { + err = i_s_sys_error_handling(err, thd); + goto func_exit; } } else { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, @@ -5574,9 +5602,11 @@ i_s_sys_indexes_fill_table( mtr_commit(&mtr); mutex_exit(&dict_sys.mutex); +func_exit: mem_heap_free(heap); + ut_free(pcur.old_rec_buf); - DBUG_RETURN(0); + DBUG_RETURN(err); } /*******************************************************************//** Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_indexes @@ -5734,6 +5764,7 @@ i_s_sys_columns_fill_table( const char* col_name; mem_heap_t* heap; mtr_t mtr; + int err = 0; DBUG_ENTER("i_s_sys_columns_fill_table"); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); @@ -5765,9 +5796,14 @@ i_s_sys_columns_fill_table( mutex_exit(&dict_sys.mutex); if (!err_msg) { - i_s_dict_fill_sys_columns(thd, table_id, col_name, - &column_rec, nth_v_col, - tables->table); + err = i_s_dict_fill_sys_columns( + thd, table_id, col_name, + &column_rec, nth_v_col, + tables->table); + if (err) { + err = i_s_sys_error_handling(err, thd); + goto func_exit; + } } else { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANT_FIND_SYSTEM_REC, "%s", @@ -5784,9 +5820,11 @@ i_s_sys_columns_fill_table( mtr_commit(&mtr); mutex_exit(&dict_sys.mutex); +func_exit: mem_heap_free(heap); + ut_free(pcur.old_rec_buf); - DBUG_RETURN(0); + DBUG_RETURN(err); } /*******************************************************************//** Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_columns @@ -5926,6 +5964,7 @@ i_s_sys_virtual_fill_table( ulint pos; ulint base_pos; mtr_t mtr; + int err = 0; DBUG_ENTER("i_s_sys_virtual_fill_table"); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); @@ -5954,8 +5993,13 @@ i_s_sys_virtual_fill_table( mutex_exit(&dict_sys.mutex); if (!err_msg) { - i_s_dict_fill_sys_virtual(thd, table_id, pos, base_pos, - tables->table); + err = i_s_dict_fill_sys_virtual( + thd, table_id, pos, base_pos, + tables->table); + if (err) { + err = i_s_sys_error_handling(err, thd); + goto func_exit; + } } else { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANT_FIND_SYSTEM_REC, "%s", @@ -5970,8 +6014,9 @@ i_s_sys_virtual_fill_table( mtr_commit(&mtr); mutex_exit(&dict_sys.mutex); - - DBUG_RETURN(0); +func_exit: + ut_free(pcur.old_rec_buf); + DBUG_RETURN(err); } /** Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_virtual @@ -6106,6 +6151,7 @@ i_s_sys_fields_fill_table( mem_heap_t* heap; index_id_t last_id; mtr_t mtr; + int err = 0; DBUG_ENTER("i_s_sys_fields_fill_table"); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); @@ -6141,8 +6187,13 @@ i_s_sys_fields_fill_table( mutex_exit(&dict_sys.mutex); if (!err_msg) { - i_s_dict_fill_sys_fields(thd, index_id, &field_rec, - pos, tables->table); + err = i_s_dict_fill_sys_fields( + thd, index_id, &field_rec, + pos, tables->table); + if (err) { + err = i_s_sys_error_handling(err, thd); + goto func_exit; + } last_id = index_id; } else { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, @@ -6160,9 +6211,11 @@ i_s_sys_fields_fill_table( mtr_commit(&mtr); mutex_exit(&dict_sys.mutex); +func_exit: mem_heap_free(heap); + ut_free(pcur.old_rec_buf); - DBUG_RETURN(0); + DBUG_RETURN(err); } /*******************************************************************//** Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_fields @@ -6305,6 +6358,7 @@ i_s_sys_foreign_fill_table( const rec_t* rec; mem_heap_t* heap; mtr_t mtr; + int err = 0; DBUG_ENTER("i_s_sys_foreign_fill_table"); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); @@ -6333,8 +6387,15 @@ i_s_sys_foreign_fill_table( mutex_exit(&dict_sys.mutex); if (!err_msg) { - i_s_dict_fill_sys_foreign(thd, &foreign_rec, - tables->table); + err = i_s_dict_fill_sys_foreign( + thd, &foreign_rec, tables->table); + if (err) { + ut_free(pcur.old_rec_buf); + if (thd_kill_level(thd)) { + err = 0; + } + goto func_exit; + } } else { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANT_FIND_SYSTEM_REC, "%s", @@ -6351,9 +6412,10 @@ i_s_sys_foreign_fill_table( mtr_commit(&mtr); mutex_exit(&dict_sys.mutex); +func_exit: mem_heap_free(heap); - DBUG_RETURN(0); + DBUG_RETURN(err); } /*******************************************************************//** @@ -6493,6 +6555,7 @@ i_s_sys_foreign_cols_fill_table( const rec_t* rec; mem_heap_t* heap; mtr_t mtr; + int err = 0; DBUG_ENTER("i_s_sys_foreign_cols_fill_table"); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); @@ -6523,9 +6586,13 @@ i_s_sys_foreign_cols_fill_table( mutex_exit(&dict_sys.mutex); if (!err_msg) { - i_s_dict_fill_sys_foreign_cols( - thd, name, for_col_name, ref_col_name, pos, - tables->table); + err = i_s_dict_fill_sys_foreign_cols( + thd, name, for_col_name, + ref_col_name, pos, tables->table); + if (err) { + err = i_s_sys_error_handling(err, thd); + goto func_exit; + } } else { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANT_FIND_SYSTEM_REC, "%s", @@ -6542,9 +6609,11 @@ i_s_sys_foreign_cols_fill_table( mtr_commit(&mtr); mutex_exit(&dict_sys.mutex); +func_exit: mem_heap_free(heap); + ut_free(pcur.old_rec_buf); - DBUG_RETURN(0); + DBUG_RETURN(err); } /*******************************************************************//** Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign_cols @@ -6773,6 +6842,7 @@ i_s_sys_tablespaces_fill_table( const rec_t* rec; mem_heap_t* heap; mtr_t mtr; + int err = 0; DBUG_ENTER("i_s_sys_tablespaces_fill_table"); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); @@ -6803,9 +6873,13 @@ i_s_sys_tablespaces_fill_table( mutex_exit(&dict_sys.mutex); if (!err_msg) { - i_s_dict_fill_sys_tablespaces( + err = i_s_dict_fill_sys_tablespaces( thd, space, name, flags, tables->table); + if (err) { + err = i_s_sys_error_handling(err, thd); + goto func_exit; + } } else { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANT_FIND_SYSTEM_REC, "%s", @@ -6821,14 +6895,16 @@ i_s_sys_tablespaces_fill_table( mtr_commit(&mtr); mutex_exit(&dict_sys.mutex); - mem_heap_free(heap); i_s_dict_fill_sys_tablespaces( thd, fil_system.temp_space->id, fil_system.temp_space->name, fil_system.temp_space->flags, tables->table); +func_exit: + mem_heap_free(heap); + ut_free(pcur.old_rec_buf); - DBUG_RETURN(0); + DBUG_RETURN(err); } /*******************************************************************//** Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES @@ -6956,6 +7032,7 @@ i_s_sys_datafiles_fill_table( const rec_t* rec; mem_heap_t* heap; mtr_t mtr; + int err = 0; DBUG_ENTER("i_s_sys_datafiles_fill_table"); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str); @@ -6984,8 +7061,12 @@ i_s_sys_datafiles_fill_table( mutex_exit(&dict_sys.mutex); if (!err_msg) { - i_s_dict_fill_sys_datafiles( + err = i_s_dict_fill_sys_datafiles( thd, space, path, tables->table); + if (err) { + err = i_s_sys_error_handling(err, thd); + goto func_exit; + } } else { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_CANT_FIND_SYSTEM_REC, "%s", @@ -7002,9 +7083,11 @@ i_s_sys_datafiles_fill_table( mtr_commit(&mtr); mutex_exit(&dict_sys.mutex); +func_exit: mem_heap_free(heap); + ut_free(pcur.old_rec_buf); - DBUG_RETURN(0); + DBUG_RETURN(err); } /*******************************************************************//** Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_DATAFILES From de31ca6a212118bd29876f964497050e446bda02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 21 Nov 2023 08:53:02 +0200 Subject: [PATCH 294/477] MDEV-32820 Race condition between trx_purge_free_segment() and trx_undo_create() trx_purge_free_segment(): If fseg_free_step_not_header() needs to be called multiple times, acquire an exclusive latch on the rollback segment header page after restarting the mini-transaction so that the rest of this function cannot execute concurrently with trx_undo_create() on the same rollback segment. This fixes a regression that was introduced in commit c14a39431b211017e6809bb79c4079b38ffc3dff (MDEV-30753). Note: The buffer-fixes that we are holding across the mini-transaction restart will prevent the pages from being evicted from the buffer pool. They may be accessed by other threads or written back to data files while we are not holding exclusive latches. Reviewed by: Vladislav Lesin --- storage/innobase/trx/trx0purge.cc | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 4a98dee573e..b06e3cb3e1b 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -365,8 +365,10 @@ void trx_purge_free_segment(mtr_t &mtr, trx_rseg_t* rseg, fil_addr_t hdr_addr) while (!fseg_free_step_not_header(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + block->frame, &mtr)) { - block->fix(); - const page_id_t id{block->page.id()}; + buf_block_buf_fix_inc(rseg_hdr, __FILE__, __LINE__); + buf_block_buf_fix_inc(block, __FILE__, __LINE__); + ut_d(const page_id_t rseg_hdr_id{rseg_hdr->page.id()}); + ut_d(const page_id_t id{block->page.id()}); mtr.commit(); /* NOTE: If the server is killed after the log that was produced up to this point was written, and before the log from the mtr.commit() @@ -376,19 +378,12 @@ void trx_purge_free_segment(mtr_t &mtr, trx_rseg_t* rseg, fil_addr_t hdr_addr) This does not matter when using multiple innodb_undo_tablespaces; innodb_undo_log_truncate=ON will be able to reclaim the space. */ mtr.start(); - ut_ad(rw_lock_s_lock_nowait(block->debug_latch, __FILE__, __LINE__)); + rw_lock_x_lock(&rseg_hdr->lock); rw_lock_x_lock(&block->lock); - if (UNIV_UNLIKELY(block->page.id() != id)) - { - block->unfix(); - rw_lock_x_unlock(&block->lock); - ut_d(rw_lock_s_unlock(block->debug_latch)); - block= buf_page_get(id, 0, RW_X_LATCH, &mtr); - if (!block) - return; - } - else - mtr_memo_push(&mtr, block, MTR_MEMO_PAGE_X_FIX); + ut_ad(rseg_hdr->page.id() == rseg_hdr_id); + ut_ad(block->page.id() == id); + mtr_memo_push(&mtr, rseg_hdr, MTR_MEMO_PAGE_X_FIX); + mtr_memo_push(&mtr, block, MTR_MEMO_PAGE_X_FIX); } while (!fseg_free_step(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + From 48017f057e33115818846283fff65945a3b73d22 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Sat, 11 Nov 2023 15:37:42 +0100 Subject: [PATCH 295/477] galera: cleanup of the lists of disabled tests --- mysql-test/suite/galera/disabled.def | 6 ++++++ mysql-test/suite/galera/t/galera_restart_replica.test | 2 +- mysql-test/suite/galera_3nodes/disabled.def | 1 + mysql-test/suite/galera_sr/disabled.def | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 2bf4db335f4..c5412874929 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -16,3 +16,9 @@ galera_sst_encrypted : MDEV-29876 Galera test failure on galera_sst_encrypted galera_var_node_address : MDEV-20485 Galera test failure galera_sequences : MDEV-32561 WSREP FSM failure: no such a transition REPLICATING -> COMMITTED galera_shutdown_nonprim : MDEV-32635 galera_shutdown_nonprim: mysql_shutdown failed +versioning_trx_id : MDEV-18590 : galera.versioning_trx_id: Test failure: mysqltest: Result content mismatch +galera_concurrent_ctas : MDEV-32779 galera_concurrent_ctas: assertion in the galera::ReplicatorSMM::finish_cert() +galera_as_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() +galera_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() +galera_bf_lock_wait : MDEV-32781 galera_bf_lock_wait test failed +galera_sst_mysqldump_with_key : MDEV-32782 galera_sst_mysqldump_with_key test failed diff --git a/mysql-test/suite/galera/t/galera_restart_replica.test b/mysql-test/suite/galera/t/galera_restart_replica.test index 2cc3a1dcff2..37cfd9bc0f9 100644 --- a/mysql-test/suite/galera/t/galera_restart_replica.test +++ b/mysql-test/suite/galera/t/galera_restart_replica.test @@ -3,9 +3,9 @@ # # The galera/galera_2node_slave.cnf describes the setup of the nodes # ---source include/big_test.inc --source include/force_restart.inc --source include/galera_cluster.inc +--source include/have_innodb.inc --source include/have_sequence.inc # As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index 00aaeccfb8d..2cec93fd3b7 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -12,3 +12,4 @@ galera_2_cluster : MDEV-32631 galera_2_cluster: before_rollback(): Assertion `0' failed galera_gtid_2_cluster : MDEV-32633 galera_gtid_2_cluster: Assertion `thd->wsrep_next_trx_id() != (0x7fffffffffffffffLL * 2ULL + 1)' +galera_ssl_reload : MDEV-32778 galera_ssl_reload failed with warning message diff --git a/mysql-test/suite/galera_sr/disabled.def b/mysql-test/suite/galera_sr/disabled.def index 0371f0f589f..fa62168d474 100644 --- a/mysql-test/suite/galera_sr/disabled.def +++ b/mysql-test/suite/galera_sr/disabled.def @@ -11,3 +11,4 @@ ############################################################################## GCF-1060 : MDEV-32160 GCF-1060 test failure due to wsrep MDL conflict +galera_sr_cc_master : MDEV-29882 Galera test failure on galera_sr_cc_master From bc07441cb307c24f4d7a1324a3d2cc7cb10f7002 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Wed, 15 Nov 2023 10:17:39 +0100 Subject: [PATCH 296/477] galera: wsrep-lib submodule update --- wsrep-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsrep-lib b/wsrep-lib index 07af42c0528..a5d95f0175f 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit 07af42c0528139e54a8018975cf55eee3daffab3 +Subproject commit a5d95f0175f10b6127ea039c542725f6c4aa5cb9 From 13666d831ce074d921ace927d16072835c8843de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 6 Nov 2023 07:37:34 +0200 Subject: [PATCH 297/477] MDEV-32634: wsrep_provider_options can be truncated on deep and long directory paths This is caused by fact that VARIABLE_VALUE is defined in variables_fields_info (sql_show.cc) as 2048. wsrep_provider_options contain few path variables and this could cause string truncation on deep and long directory paths. Signed-off-by: Julius Goryavsky --- mysql-test/main/show_check.result | 6 +++--- sql/sql_show.cc | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/main/show_check.result b/mysql-test/main/show_check.result index a68be20b997..7c0a3251e45 100644 --- a/mysql-test/main/show_check.result +++ b/mysql-test/main/show_check.result @@ -103,19 +103,19 @@ drop table t1; show variables like "wait_timeout%"; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def information_schema SESSION_VARIABLES SESSION_VARIABLES VARIABLE_NAME Variable_name 253 64 12 N 4097 0 8 -def information_schema SESSION_VARIABLES SESSION_VARIABLES VARIABLE_VALUE Value 253 2048 5 N 4097 0 8 +def information_schema SESSION_VARIABLES SESSION_VARIABLES VARIABLE_VALUE Value 253 4096 5 N 4097 0 8 Variable_name Value wait_timeout 28800 show variables like "WAIT_timeout%"; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def information_schema SESSION_VARIABLES SESSION_VARIABLES VARIABLE_NAME Variable_name 253 64 12 N 4097 0 8 -def information_schema SESSION_VARIABLES SESSION_VARIABLES VARIABLE_VALUE Value 253 2048 5 N 4097 0 8 +def information_schema SESSION_VARIABLES SESSION_VARIABLES VARIABLE_VALUE Value 253 4096 5 N 4097 0 8 Variable_name Value wait_timeout 28800 show variables like "this_doesn't_exists%"; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def information_schema SESSION_VARIABLES SESSION_VARIABLES VARIABLE_NAME Variable_name 253 64 0 N 4097 0 8 -def information_schema SESSION_VARIABLES SESSION_VARIABLES VARIABLE_VALUE Value 253 2048 0 N 4097 0 8 +def information_schema SESSION_VARIABLES SESSION_VARIABLES VARIABLE_VALUE Value 253 4096 0 N 4097 0 8 Variable_name Value show table status from test like "this_doesn't_exists%"; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2b3e8d41757..3d74cf333ce 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -9876,7 +9876,7 @@ ST_FIELD_INFO variables_fields_info[]= { {"VARIABLE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Variable_name", SKIP_OPEN_TABLE}, - {"VARIABLE_VALUE", 2048, MYSQL_TYPE_STRING, 0, 0, "Value", SKIP_OPEN_TABLE}, + {"VARIABLE_VALUE", 4096, MYSQL_TYPE_STRING, 0, 0, "Value", SKIP_OPEN_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; From 671f6654550b8a4696c62a90b6e586031e9ac789 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 21 Nov 2023 05:47:32 +0100 Subject: [PATCH 298/477] MDEV-32634: additional fix for funcs_1 mtr suite --- mysql-test/suite/funcs_1/r/is_columns_is.result | 16 ++++++++-------- .../funcs_1/r/is_columns_is_embedded.result | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) 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 50c16b54976..cc283722e2a 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is.result @@ -174,9 +174,9 @@ def information_schema GEOMETRY_COLUMNS MAX_PPR 12 NULL NO tinyint NULL NULL 3 0 def information_schema GEOMETRY_COLUMNS SRID 13 NULL NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) select NEVER NULL def information_schema GEOMETRY_COLUMNS STORAGE_TYPE 9 NULL NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) select NEVER NULL def information_schema GLOBAL_STATUS VARIABLE_NAME 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema GLOBAL_STATUS VARIABLE_VALUE 2 NULL NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema GLOBAL_STATUS VARIABLE_VALUE 2 NULL NO varchar 4096 12288 NULL NULL NULL utf8 utf8_general_ci varchar(4096) select NEVER NULL def information_schema GLOBAL_VARIABLES VARIABLE_NAME 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 NULL NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 NULL NO varchar 4096 12288 NULL NULL NULL utf8 utf8_general_ci varchar(4096) select NEVER NULL def information_schema INDEX_STATISTICS INDEX_NAME 3 NULL NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL def information_schema INDEX_STATISTICS ROWS_READ 4 NULL NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL def information_schema INDEX_STATISTICS TABLE_NAME 2 NULL NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select NEVER NULL @@ -335,9 +335,9 @@ def information_schema SCHEMA_PRIVILEGES PRIVILEGE_TYPE 4 NULL NO varchar 64 192 def information_schema SCHEMA_PRIVILEGES TABLE_CATALOG 2 NULL NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL def information_schema SCHEMA_PRIVILEGES TABLE_SCHEMA 3 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL def information_schema SESSION_STATUS VARIABLE_NAME 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SESSION_STATUS VARIABLE_VALUE 2 NULL NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema SESSION_STATUS VARIABLE_VALUE 2 NULL NO varchar 4096 12288 NULL NULL NULL utf8 utf8_general_ci varchar(4096) select NEVER NULL def information_schema SESSION_VARIABLES VARIABLE_NAME 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL -def information_schema SESSION_VARIABLES VARIABLE_VALUE 2 NULL NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select NEVER NULL +def information_schema SESSION_VARIABLES VARIABLE_VALUE 2 NULL NO varchar 4096 12288 NULL NULL NULL utf8 utf8_general_ci varchar(4096) select NEVER NULL def information_schema SPATIAL_REF_SYS AUTH_NAME 2 NULL NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL def information_schema SPATIAL_REF_SYS AUTH_SRID 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(5) select NEVER NULL def information_schema SPATIAL_REF_SYS SRID 1 NULL NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) select NEVER NULL @@ -718,9 +718,9 @@ NULL information_schema GEOMETRY_COLUMNS COORD_DIMENSION tinyint NULL NULL NULL NULL information_schema GEOMETRY_COLUMNS MAX_PPR tinyint NULL NULL NULL NULL tinyint(2) NULL information_schema GEOMETRY_COLUMNS SRID smallint NULL NULL NULL NULL smallint(5) 3.0000 information_schema GLOBAL_STATUS VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema GLOBAL_STATUS VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) +3.0000 information_schema GLOBAL_STATUS VARIABLE_VALUE varchar 4096 12288 utf8 utf8_general_ci varchar(4096) 3.0000 information_schema GLOBAL_VARIABLES VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema GLOBAL_VARIABLES VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) +3.0000 information_schema GLOBAL_VARIABLES VARIABLE_VALUE varchar 4096 12288 utf8 utf8_general_ci varchar(4096) 3.0000 information_schema INDEX_STATISTICS TABLE_SCHEMA varchar 192 576 utf8 utf8_general_ci varchar(192) 3.0000 information_schema INDEX_STATISTICS TABLE_NAME varchar 192 576 utf8 utf8_general_ci varchar(192) 3.0000 information_schema INDEX_STATISTICS INDEX_NAME varchar 192 576 utf8 utf8_general_ci varchar(192) @@ -879,9 +879,9 @@ NULL information_schema ROUTINES LAST_ALTERED datetime NULL NULL NULL NULL datet 3.0000 information_schema SCHEMA_PRIVILEGES PRIVILEGE_TYPE varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema SCHEMA_PRIVILEGES IS_GRANTABLE varchar 3 9 utf8 utf8_general_ci varchar(3) 3.0000 information_schema SESSION_STATUS VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema SESSION_STATUS VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) +3.0000 information_schema SESSION_STATUS VARIABLE_VALUE varchar 4096 12288 utf8 utf8_general_ci varchar(4096) 3.0000 information_schema SESSION_VARIABLES VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema SESSION_VARIABLES VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) +3.0000 information_schema SESSION_VARIABLES VARIABLE_VALUE varchar 4096 12288 utf8 utf8_general_ci varchar(4096) NULL information_schema SPATIAL_REF_SYS SRID smallint NULL NULL NULL NULL smallint(5) 3.0000 information_schema SPATIAL_REF_SYS AUTH_NAME varchar 512 1536 utf8 utf8_general_ci varchar(512) NULL information_schema SPATIAL_REF_SYS AUTH_SRID int NULL NULL NULL NULL int(5) 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 7b6da4e23c0..e73646dc21d 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 @@ -174,9 +174,9 @@ def information_schema GEOMETRY_COLUMNS MAX_PPR 12 NULL NO tinyint NULL NULL 3 0 def information_schema GEOMETRY_COLUMNS SRID 13 NULL NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) NEVER NULL def information_schema GEOMETRY_COLUMNS STORAGE_TYPE 9 NULL NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(2) NEVER NULL def information_schema GLOBAL_STATUS VARIABLE_NAME 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema GLOBAL_STATUS VARIABLE_VALUE 2 NULL NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema GLOBAL_STATUS VARIABLE_VALUE 2 NULL NO varchar 4096 12288 NULL NULL NULL utf8 utf8_general_ci varchar(4096) NEVER NULL def information_schema GLOBAL_VARIABLES VARIABLE_NAME 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 NULL NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 NULL NO varchar 4096 12288 NULL NULL NULL utf8 utf8_general_ci varchar(4096) NEVER NULL def information_schema INDEX_STATISTICS INDEX_NAME 3 NULL NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL def information_schema INDEX_STATISTICS ROWS_READ 4 NULL NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL def information_schema INDEX_STATISTICS TABLE_NAME 2 NULL NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) NEVER NULL @@ -335,9 +335,9 @@ def information_schema SCHEMA_PRIVILEGES PRIVILEGE_TYPE 4 NULL NO varchar 64 192 def information_schema SCHEMA_PRIVILEGES TABLE_CATALOG 2 NULL NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL def information_schema SCHEMA_PRIVILEGES TABLE_SCHEMA 3 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL def information_schema SESSION_STATUS VARIABLE_NAME 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SESSION_STATUS VARIABLE_VALUE 2 NULL NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema SESSION_STATUS VARIABLE_VALUE 2 NULL NO varchar 4096 12288 NULL NULL NULL utf8 utf8_general_ci varchar(4096) NEVER NULL def information_schema SESSION_VARIABLES VARIABLE_NAME 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL -def information_schema SESSION_VARIABLES VARIABLE_VALUE 2 NULL NO varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) NEVER NULL +def information_schema SESSION_VARIABLES VARIABLE_VALUE 2 NULL NO varchar 4096 12288 NULL NULL NULL utf8 utf8_general_ci varchar(4096) NEVER NULL def information_schema SPATIAL_REF_SYS AUTH_NAME 2 NULL NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL def information_schema SPATIAL_REF_SYS AUTH_SRID 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(5) NEVER NULL def information_schema SPATIAL_REF_SYS SRID 1 NULL NO smallint NULL NULL 5 0 NULL NULL NULL smallint(5) NEVER NULL @@ -718,9 +718,9 @@ NULL information_schema GEOMETRY_COLUMNS COORD_DIMENSION tinyint NULL NULL NULL NULL information_schema GEOMETRY_COLUMNS MAX_PPR tinyint NULL NULL NULL NULL tinyint(2) NULL information_schema GEOMETRY_COLUMNS SRID smallint NULL NULL NULL NULL smallint(5) 3.0000 information_schema GLOBAL_STATUS VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema GLOBAL_STATUS VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) +3.0000 information_schema GLOBAL_STATUS VARIABLE_VALUE varchar 4096 12288 utf8 utf8_general_ci varchar(4096) 3.0000 information_schema GLOBAL_VARIABLES VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema GLOBAL_VARIABLES VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) +3.0000 information_schema GLOBAL_VARIABLES VARIABLE_VALUE varchar 4096 12288 utf8 utf8_general_ci varchar(4096) 3.0000 information_schema INDEX_STATISTICS TABLE_SCHEMA varchar 192 576 utf8 utf8_general_ci varchar(192) 3.0000 information_schema INDEX_STATISTICS TABLE_NAME varchar 192 576 utf8 utf8_general_ci varchar(192) 3.0000 information_schema INDEX_STATISTICS INDEX_NAME varchar 192 576 utf8 utf8_general_ci varchar(192) @@ -879,9 +879,9 @@ NULL information_schema ROUTINES LAST_ALTERED datetime NULL NULL NULL NULL datet 3.0000 information_schema SCHEMA_PRIVILEGES PRIVILEGE_TYPE varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema SCHEMA_PRIVILEGES IS_GRANTABLE varchar 3 9 utf8 utf8_general_ci varchar(3) 3.0000 information_schema SESSION_STATUS VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema SESSION_STATUS VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) +3.0000 information_schema SESSION_STATUS VARIABLE_VALUE varchar 4096 12288 utf8 utf8_general_ci varchar(4096) 3.0000 information_schema SESSION_VARIABLES VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema SESSION_VARIABLES VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) +3.0000 information_schema SESSION_VARIABLES VARIABLE_VALUE varchar 4096 12288 utf8 utf8_general_ci varchar(4096) NULL information_schema SPATIAL_REF_SYS SRID smallint NULL NULL NULL NULL smallint(5) 3.0000 information_schema SPATIAL_REF_SYS AUTH_NAME varchar 512 1536 utf8 utf8_general_ci varchar(512) NULL information_schema SPATIAL_REF_SYS AUTH_SRID int NULL NULL NULL NULL int(5) From e39c497c809511bcc37a658405c7aa4b5be2cf6a Mon Sep 17 00:00:00 2001 From: Denis Protivensky Date: Fri, 27 Oct 2023 12:26:08 +0300 Subject: [PATCH 299/477] MDEV-22232: Fix CTAS replay & retry in case it gets BF-aborted - Add selected tables as shared keys for CTAS certification - Set proper security context on the replayer thread - Disallow CTAS command retry Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/MDEV-22232.result | 27 ++++++++ mysql-test/suite/galera/t/MDEV-22232.test | 72 +++++++++++++++++++++ sql/sql_insert.cc | 17 ++--- sql/sql_table.cc | 12 +++- sql/wsrep_client_service.cc | 8 +++ sql/wsrep_mysqld.cc | 36 ++++++++--- sql/wsrep_mysqld.h | 15 ++--- 7 files changed, 156 insertions(+), 31 deletions(-) create mode 100644 mysql-test/suite/galera/r/MDEV-22232.result create mode 100644 mysql-test/suite/galera/t/MDEV-22232.test diff --git a/mysql-test/suite/galera/r/MDEV-22232.result b/mysql-test/suite/galera/r/MDEV-22232.result new file mode 100644 index 00000000000..a6a619458f0 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-22232.result @@ -0,0 +1,27 @@ +connection node_2; +connection node_1; +connect con1,127.0.0.1,root,,test,$NODE_MYPORT_1; +--- CTAS with empty result set --- +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +SET DEBUG_SYNC = 'create_table_select_before_create SIGNAL may_alter WAIT_FOR bf_abort'; +CREATE TABLE t2 SELECT * FROM t1; +connection node_1; +SET DEBUG_SYNC = 'now WAIT_FOR may_alter'; +ALTER TABLE t1 DROP FOREIGN KEY b, ALGORITHM=COPY; +connection con1; +ERROR 70100: Query execution was interrupted +SET DEBUG_SYNC = 'RESET'; +--- CTAS with non-empty result set --- +INSERT INTO t1 VALUES (10), (20), (30); +SET DEBUG_SYNC = 'create_table_select_before_create SIGNAL may_alter WAIT_FOR bf_abort'; +CREATE TABLE t2 SELECT * FROM t1; +connection node_1; +SET DEBUG_SYNC = 'now WAIT_FOR may_alter'; +ALTER TABLE t1 DROP FOREIGN KEY b, ALGORITHM=COPY; +connection con1; +ERROR 70100: Query execution was interrupted +SET DEBUG_SYNC = 'RESET'; +DROP TABLE t1; +disconnect con1; +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera/t/MDEV-22232.test b/mysql-test/suite/galera/t/MDEV-22232.test new file mode 100644 index 00000000000..edb42ee603c --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-22232.test @@ -0,0 +1,72 @@ +# +# MDEV-22232: CTAS execution crashes during replay. +# +# There were multiple problems and two failing scenarios with empty result set +# and with non-empty result set: +# - CTAS didn't add shared keys for selected tables +# - Security context wasn't set on the replayer thread +# - CTAS was retried after failure - now retry disabled + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +--connect con1,127.0.0.1,root,,test,$NODE_MYPORT_1 + +# Scenario 1 +--echo --- CTAS with empty result set --- +CREATE TABLE t1 (a INT) ENGINE=InnoDB; + +# Run CTAS until the resulting table gets created, +# then it gets BF aborted by ALTER. +SET DEBUG_SYNC = 'create_table_select_before_create SIGNAL may_alter WAIT_FOR bf_abort'; +--send + CREATE TABLE t2 SELECT * FROM t1; + +# Wait for CTAS to reach the table create point, +# start executing ALTER and BF abort CTAS. +--connection node_1 +SET DEBUG_SYNC = 'now WAIT_FOR may_alter'; +--disable_result_log +--error ER_ERROR_ON_RENAME +ALTER TABLE t1 DROP FOREIGN KEY b, ALGORITHM=COPY; +--enable_result_log + +--connection con1 +# CTAS gets BF aborted. +--error ER_QUERY_INTERRUPTED +--reap + +# Cleanup +SET DEBUG_SYNC = 'RESET'; + + +# Scenario 2 +--echo --- CTAS with non-empty result set --- +INSERT INTO t1 VALUES (10), (20), (30); + +# Run CTAS until the resulting table gets created, +# then it gets BF aborted by ALTER. +SET DEBUG_SYNC = 'create_table_select_before_create SIGNAL may_alter WAIT_FOR bf_abort'; +--send + CREATE TABLE t2 SELECT * FROM t1; + +# Wait for CTAS to reach the table create point, +# start executing ALTER and BF abort CTAS. +--connection node_1 +SET DEBUG_SYNC = 'now WAIT_FOR may_alter'; +--disable_result_log +--error ER_ERROR_ON_RENAME +ALTER TABLE t1 DROP FOREIGN KEY b, ALGORITHM=COPY; +--enable_result_log + +--connection con1 +# CTAS gets BF aborted. +--error ER_QUERY_INTERRUPTED +--reap + +# Cleanup +SET DEBUG_SYNC = 'RESET'; +DROP TABLE t1; +--disconnect con1 +--source include/galera_end.inc diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 1bc2d9ccb00..99592d79f16 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -84,6 +84,7 @@ #include "debug_sync.h" #ifdef WITH_WSREP +#include "wsrep_mysqld.h" /* wsrep_append_table_keys() */ #include "wsrep_trans_observer.h" /* wsrep_start_transction() */ #endif /* WITH_WSREP */ @@ -4802,17 +4803,13 @@ bool select_create::send_eof() thd->wsrep_trx_id(), thd->thread_id, thd->query_id); /* - append table level exclusive key for CTAS + For CTAS, append table level exclusive key for created table + and table level shared key for selected table. */ - wsrep_key_arr_t key_arr= {0, 0}; - wsrep_prepare_keys_for_isolation(thd, - create_table->db.str, - create_table->table_name.str, - table_list, - &key_arr); - int rcode= wsrep_thd_append_key(thd, key_arr.keys, key_arr.keys_len, - WSREP_SERVICE_KEY_EXCLUSIVE); - wsrep_keys_free(&key_arr); + int rcode= wsrep_append_table_keys(thd, create_table, table_list, + WSREP_SERVICE_KEY_EXCLUSIVE); + rcode= rcode || wsrep_append_table_keys(thd, nullptr, select_tables, + WSREP_SERVICE_KEY_SHARED); if (rcode) { DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f0d6084bc7e..4514421b7d2 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -11634,8 +11634,18 @@ bool Sql_cmd_create_table_like::execute(THD *thd) Alter_info alter_info(lex->alter_info, thd->mem_root); #ifdef WITH_WSREP + bool wsrep_ctas= false; // If CREATE TABLE AS SELECT and wsrep_on - const bool wsrep_ctas= (select_lex->item_list.elements && WSREP(thd)); + if (WSREP(thd) && (select_lex->item_list.elements || + // Only CTAS may be applied not using TOI. + (wsrep_thd_is_applying(thd) && !wsrep_thd_is_toi(thd)))) + { + wsrep_ctas= true; + + // MDEV-22232: Disable CTAS retry by setting the retry counter to the + // threshold value. + thd->wsrep_retry_counter= thd->variables.wsrep_retry_autocommit; + } // This will be used in THD::decide_logging_format if CTAS Enable_wsrep_ctas_guard wsrep_ctas_guard(thd, wsrep_ctas); diff --git a/sql/wsrep_client_service.cc b/sql/wsrep_client_service.cc index 0d0443ad5f2..560508bb95e 100644 --- a/sql/wsrep_client_service.cc +++ b/sql/wsrep_client_service.cc @@ -283,6 +283,13 @@ enum wsrep::provider::status Wsrep_client_service::replay() original THD state during replication event applying. */ THD *replayer_thd= new THD(true, true); + // Replace the security context of the replayer with the security context + // of the original THD. Since security context class doesn't have proper + // copy constructors, we need to store the original one and set it back + // before destruction so that THD desctruction doesn't cause double-free + // on the replaced security context. + Security_context old_ctx = replayer_thd->main_security_ctx; + replayer_thd->main_security_ctx = m_thd->main_security_ctx; replayer_thd->thread_stack= m_thd->thread_stack; replayer_thd->real_id= pthread_self(); replayer_thd->prior_thr_create_utime= @@ -299,6 +306,7 @@ enum wsrep::provider::status Wsrep_client_service::replay() replayer_service.replay_status(ret); } + replayer_thd->main_security_ctx = old_ctx; delete replayer_thd; DBUG_RETURN(ret); } diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 6008bc0b72c..688b0061389 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1266,7 +1266,13 @@ bool wsrep_sync_wait(THD* thd, enum enum_sql_command command) return res; } -void wsrep_keys_free(wsrep_key_arr_t* key_arr) +typedef struct wsrep_key_arr +{ + wsrep_key_t* keys; + size_t keys_len; +} wsrep_key_arr_t; + +static void wsrep_keys_free(wsrep_key_arr_t* key_arr) { for (size_t i= 0; i < key_arr->keys_len; ++i) { @@ -1516,18 +1522,30 @@ err: } /* - * Prepare key list from db/table and table_list + * Prepare key list from db/table and table_list and append it to Wsrep + * with the given key type. * * Return zero in case of success, 1 in case of failure. */ - -bool wsrep_prepare_keys_for_isolation(THD* thd, - const char* db, - const char* table, - const TABLE_LIST* table_list, - wsrep_key_arr_t* ka) +int wsrep_append_table_keys(THD* thd, + TABLE_LIST* first_table, + TABLE_LIST* table_list, + Wsrep_service_key_type key_type) { - return wsrep_prepare_keys_for_isolation(thd, db, table, table_list, NULL, ka); + wsrep_key_arr_t key_arr= {0, 0}; + const char* db_name= first_table ? first_table->db.str : NULL; + const char* table_name= first_table ? first_table->table_name.str : NULL; + int rcode= wsrep_prepare_keys_for_isolation(thd, db_name, table_name, + table_list, NULL, &key_arr); + + if (!rcode && key_arr.keys_len) + { + rcode= wsrep_thd_append_key(thd, key_arr.keys, + key_arr.keys_len, key_type); + } + + wsrep_keys_free(&key_arr); + return rcode; } bool wsrep_prepare_key(const uchar* cache_key, size_t cache_key_len, diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 3d06f165c5c..921b75ae42d 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -347,17 +347,10 @@ int wsrep_must_ignore_error(THD* thd); bool wsrep_replicate_GTID(THD* thd); -typedef struct wsrep_key_arr -{ - wsrep_key_t* keys; - size_t keys_len; -} wsrep_key_arr_t; -bool wsrep_prepare_keys_for_isolation(THD* thd, - const char* db, - const char* table, - const TABLE_LIST* table_list, - wsrep_key_arr_t* ka); -void wsrep_keys_free(wsrep_key_arr_t* key_arr); +int wsrep_append_table_keys(THD* thd, + TABLE_LIST* first_table, + TABLE_LIST* table_list, + Wsrep_service_key_type key_type); extern void wsrep_handle_mdl_conflict(MDL_context *requestor_ctx, From 804b5974f5f0044c3eb70fcfc592610fe23c1747 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 14 Nov 2023 19:22:56 +0530 Subject: [PATCH 300/477] MDEV-32050 Fixup - Fixing mariabackup.full_backup test case --- mysql-test/suite/mariabackup/full_backup.result | 8 ++++++++ mysql-test/suite/mariabackup/full_backup.test | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/mysql-test/suite/mariabackup/full_backup.result b/mysql-test/suite/mariabackup/full_backup.result index 1d0dffd528d..71525c22080 100644 --- a/mysql-test/suite/mariabackup/full_backup.result +++ b/mysql-test/suite/mariabackup/full_backup.result @@ -18,6 +18,12 @@ DROP TABLE t; # call mtr.add_suppression("InnoDB: innodb_undo_tablespaces=0 disables dedicated undo log tablespaces"); call mtr.add_suppression("InnoDB: Cannot change innodb_undo_tablespaces=0 because previous shutdown was not with innodb_fast_shutdown=0"); +call mtr.add_suppression("Found 1 prepared XA transactions"); +CREATE TABLE t(f1 INT NOT NULL)ENGINE=InnoDB; +XA START 'zombie'; +INSERT INTO t VALUES(1); +XA END 'zombie'; +XA PREPARE 'zombie'; # restart: --innodb_undo_tablespaces=0 # xtrabackup backup # xtrabackup prepare @@ -28,3 +34,5 @@ call mtr.add_suppression("InnoDB: Cannot change innodb_undo_tablespaces=0 becaus # Display undo log files from target directory undo001 undo002 +XA COMMIT 'zombie'; +DROP TABLE t; diff --git a/mysql-test/suite/mariabackup/full_backup.test b/mysql-test/suite/mariabackup/full_backup.test index fb043f63be0..c6a21112b60 100644 --- a/mysql-test/suite/mariabackup/full_backup.test +++ b/mysql-test/suite/mariabackup/full_backup.test @@ -35,6 +35,13 @@ rmdir $targetdir; --echo # call mtr.add_suppression("InnoDB: innodb_undo_tablespaces=0 disables dedicated undo log tablespaces"); call mtr.add_suppression("InnoDB: Cannot change innodb_undo_tablespaces=0 because previous shutdown was not with innodb_fast_shutdown=0"); +call mtr.add_suppression("Found 1 prepared XA transactions"); + +CREATE TABLE t(f1 INT NOT NULL)ENGINE=InnoDB; +XA START 'zombie'; +INSERT INTO t VALUES(1); +XA END 'zombie'; +XA PREPARE 'zombie'; let $restart_parameters=--innodb_undo_tablespaces=0; --source include/restart_mysqld.inc @@ -53,4 +60,6 @@ exec $XTRABACKUP --prepare --target-dir=$targetdir; --echo # Display undo log files from target directory list_files $targetdir undo*; +XA COMMIT 'zombie'; +DROP TABLE t; rmdir $targetdir; From 4c16ec3e775e11d8b24e402e5b4329decec2b4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 21 Nov 2023 12:42:00 +0200 Subject: [PATCH 301/477] MDEV-32050 fixup: Stabilize tests In any test that uses wait_all_purged.inc, ensure that InnoDB tables will be created without persistent statistics. This is a follow-up to commit cd04673a177d40f7c409284d87ead851ec775c36 after a similar failure was observed in the innodb_zip.blob test. --- mysql-test/suite/gcol/r/gcol_partition_innodb.result | 5 ++++- mysql-test/suite/gcol/r/gcol_purge.result | 2 +- mysql-test/suite/gcol/r/gcol_update.result | 3 +++ mysql-test/suite/gcol/r/innodb_virtual_debug.result | 3 +++ mysql-test/suite/gcol/r/innodb_virtual_purge.result | 3 +++ mysql-test/suite/gcol/t/gcol_partition_innodb.test | 7 ++++++- mysql-test/suite/gcol/t/gcol_purge.test | 2 +- mysql-test/suite/gcol/t/gcol_update.test | 5 +++++ mysql-test/suite/gcol/t/innodb_virtual_debug.test | 6 ++++++ mysql-test/suite/gcol/t/innodb_virtual_purge.test | 5 +++++ mysql-test/suite/innodb/r/alter_kill.result | 1 + mysql-test/suite/innodb/r/dml_purge.result | 3 +++ mysql-test/suite/innodb/r/foreign_key.result | 4 ++++ mysql-test/suite/innodb/r/full_crc32_import.result | 3 +++ .../suite/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 + .../suite/innodb/r/innodb-system-table-view.result | 3 +++ mysql-test/suite/innodb/r/innodb_scrub.result | 2 +- .../suite/innodb/r/innodb_stats_persistent.result | 2 +- mysql-test/suite/innodb/r/instant_alter.result | 3 +++ mysql-test/suite/innodb/r/instant_alter_bugs.result | 4 ++++ .../innodb/r/instant_alter_debug,redundant.rdiff | 4 +++- mysql-test/suite/innodb/r/instant_alter_debug.result | 4 ++++ mysql-test/suite/innodb/r/instant_alter_purge.result | 2 +- .../suite/innodb/r/instant_alter_rollback.result | 1 + .../suite/innodb/r/page_id_innochecksum.result | 2 +- mysql-test/suite/innodb/r/purge.result | 3 +++ mysql-test/suite/innodb/r/purge_secondary.result | 4 ++++ mysql-test/suite/innodb/r/scrub_debug.result | 2 +- mysql-test/suite/innodb/r/truncate_crash.result | 2 +- mysql-test/suite/innodb/r/trx_id_future.result | 2 +- mysql-test/suite/innodb/r/undo_log.result | 3 +++ mysql-test/suite/innodb/t/alter_kill.test | 1 + mysql-test/suite/innodb/t/dml_purge.test | 5 +++++ mysql-test/suite/innodb/t/foreign_key.test | 7 +++++++ mysql-test/suite/innodb/t/full_crc32_import.test | 4 ++++ mysql-test/suite/innodb/t/index_merge_threshold.test | 5 +++++ mysql-test/suite/innodb/t/innodb-16k.test | 4 ++++ mysql-test/suite/innodb/t/innodb-32k.test | 1 + .../suite/innodb/t/innodb-system-table-view.test | 5 +++++ mysql-test/suite/innodb/t/innodb_scrub.test | 2 +- .../suite/innodb/t/innodb_stats_persistent.test | 2 +- mysql-test/suite/innodb/t/instant_alter.test | 4 ++++ mysql-test/suite/innodb/t/instant_alter_bugs.test | 7 +++++++ mysql-test/suite/innodb/t/instant_alter_debug.test | 7 +++++++ mysql-test/suite/innodb/t/instant_alter_purge.test | 2 +- .../suite/innodb/t/instant_alter_rollback.test | 2 ++ mysql-test/suite/innodb/t/page_id_innochecksum.test | 2 +- mysql-test/suite/innodb/t/purge.test | 5 +++++ mysql-test/suite/innodb/t/purge_secondary.test | 7 +++++++ mysql-test/suite/innodb/t/scrub_debug.test | 2 +- mysql-test/suite/innodb/t/truncate_crash.test | 2 +- mysql-test/suite/innodb/t/trx_id_future.test | 2 +- mysql-test/suite/innodb/t/undo_log.test | 5 +++++ mysql-test/suite/innodb/t/undo_space_dblwr.opt | 1 + mysql-test/suite/innodb_fts/r/crash_recovery.result | 2 +- mysql-test/suite/innodb_fts/t/crash_recovery.test | 2 +- mysql-test/suite/innodb_gis/r/rtree_add_index.result | 2 +- mysql-test/suite/innodb_gis/r/rtree_compress.result | 6 +++++- mysql-test/suite/innodb_gis/r/rtree_purge.result | 2 +- mysql-test/suite/innodb_gis/r/rtree_undo.result | 12 ++++++------ mysql-test/suite/innodb_gis/t/rtree_add_index.test | 2 +- mysql-test/suite/innodb_gis/t/rtree_compress.test | 6 +++++- mysql-test/suite/innodb_gis/t/rtree_purge.test | 2 +- mysql-test/suite/innodb_gis/t/rtree_undo.test | 4 ++-- mysql-test/suite/innodb_zip/r/blob.result | 2 +- mysql-test/suite/innodb_zip/t/blob.test | 2 +- .../mariabackup/unencrypted_page_compressed.result | 3 ++- .../mariabackup/unencrypted_page_compressed.test | 3 ++- .../suite/parts/r/partition_alter_innodb.result | 3 ++- mysql-test/suite/parts/r/partition_purge.result | 2 +- mysql-test/suite/parts/t/partition_alter_innodb.test | 3 ++- mysql-test/suite/parts/t/partition_purge.test | 2 +- mysql-test/suite/versioning/r/delete_history.result | 4 ++-- mysql-test/suite/versioning/t/delete_history.test | 4 ++-- 76 files changed, 207 insertions(+), 47 deletions(-) diff --git a/mysql-test/suite/gcol/r/gcol_partition_innodb.result b/mysql-test/suite/gcol/r/gcol_partition_innodb.result index 2bff33054a2..e6252b3dea5 100644 --- a/mysql-test/suite/gcol/r/gcol_partition_innodb.result +++ b/mysql-test/suite/gcol/r/gcol_partition_innodb.result @@ -1,4 +1,6 @@ -SET @@session.default_storage_engine = 'InnoDB'; +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; +SET default_storage_engine = 'InnoDB'; drop table if exists t1; # Case 1. Partitioning by RANGE based on a non-stored generated column. CREATE TABLE t1 ( @@ -126,6 +128,7 @@ Warnings: Warning 1906 The value specified for generated column 'vd' in table 't1' has been ignored DROP TABLE t1; InnoDB 0 transactions not purged +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; DROP VIEW IF EXISTS v1,v2; DROP TABLE IF EXISTS t1,t2,t3; DROP PROCEDURE IF EXISTS p1; diff --git a/mysql-test/suite/gcol/r/gcol_purge.result b/mysql-test/suite/gcol/r/gcol_purge.result index e16cf0dff54..19db34ac916 100644 --- a/mysql-test/suite/gcol/r/gcol_purge.result +++ b/mysql-test/suite/gcol/r/gcol_purge.result @@ -1,7 +1,7 @@ SET @save_dbug=@@GLOBAL.debug_dbug; 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; +primary key(f1), INDEX (f3))ENGINE=InnoDB STATS_PERSISTENT=0; connect con1,localhost,root,,,; InnoDB 0 transactions not purged START TRANSACTION WITH CONSISTENT SNAPSHOT; diff --git a/mysql-test/suite/gcol/r/gcol_update.result b/mysql-test/suite/gcol/r/gcol_update.result index 35e0b3e8219..54974826ebb 100644 --- a/mysql-test/suite/gcol/r/gcol_update.result +++ b/mysql-test/suite/gcol/r/gcol_update.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; connect purge_control,localhost,root; START TRANSACTION WITH CONSISTENT SNAPSHOT; connection default; @@ -37,3 +39,4 @@ InnoDB 0 transactions not purged disconnect purge_control; connection default; drop table t1; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/gcol/r/innodb_virtual_debug.result b/mysql-test/suite/gcol/r/innodb_virtual_debug.result index 3f3e3ea31d1..e1b87938e2c 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_debug.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_debug.result @@ -1,4 +1,6 @@ set default_storage_engine=innodb; +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; CREATE TABLE `t` ( `a` VARCHAR(100), `b` VARCHAR(100), @@ -145,3 +147,4 @@ DROP TABLE t1; disconnect con1; connection default; SET DEBUG_SYNC=RESET; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/gcol/r/innodb_virtual_purge.result b/mysql-test/suite/gcol/r/innodb_virtual_purge.result index 7951bd0ee6b..3f1c4413615 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_purge.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_purge.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; # # Bug#21869656 UNDO LOG DOES NOT CONTAIN ENOUGH INFORMATION # ON INDEXED VIRTUAL COLUMNS @@ -171,3 +173,4 @@ CHECK TABLE t EXTENDED; Table Op Msg_type Msg_text test.t check status OK DROP TABLE t; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/gcol/t/gcol_partition_innodb.test b/mysql-test/suite/gcol/t/gcol_partition_innodb.test index a8765970749..6bcd9d27118 100644 --- a/mysql-test/suite/gcol/t/gcol_partition_innodb.test +++ b/mysql-test/suite/gcol/t/gcol_partition_innodb.test @@ -29,7 +29,9 @@ ##### Storage engine to be tested # Set the session storage engine --source include/have_innodb.inc -eval SET @@session.default_storage_engine = 'InnoDB'; +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; +SET default_storage_engine = 'InnoDB'; ##### Workarounds for known open engine specific bugs # none @@ -58,6 +60,9 @@ REPLACE INTO t1 SELECT * FROM t1; DROP TABLE t1; --source suite/innodb/include/wait_all_purged.inc + +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; + #------------------------------------------------------------------------------# # Cleanup --source suite/gcol/inc/gcol_cleanup.inc diff --git a/mysql-test/suite/gcol/t/gcol_purge.test b/mysql-test/suite/gcol/t/gcol_purge.test index cfe20c4ad25..4ebb37ad3cc 100644 --- a/mysql-test/suite/gcol/t/gcol_purge.test +++ b/mysql-test/suite/gcol/t/gcol_purge.test @@ -4,7 +4,7 @@ SET @save_dbug=@@GLOBAL.debug_dbug; 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; + primary key(f1), INDEX (f3))ENGINE=InnoDB STATS_PERSISTENT=0; connect(con1,localhost,root,,,); --source ../innodb/include/wait_all_purged.inc START TRANSACTION WITH CONSISTENT SNAPSHOT; diff --git a/mysql-test/suite/gcol/t/gcol_update.test b/mysql-test/suite/gcol/t/gcol_update.test index 2076632f28e..86474f86c2e 100644 --- a/mysql-test/suite/gcol/t/gcol_update.test +++ b/mysql-test/suite/gcol/t/gcol_update.test @@ -1,5 +1,8 @@ --source include/have_innodb.inc +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + connect (purge_control,localhost,root); START TRANSACTION WITH CONSISTENT SNAPSHOT; @@ -60,3 +63,5 @@ disconnect purge_control; connection default; drop table t1; + +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_debug.test b/mysql-test/suite/gcol/t/innodb_virtual_debug.test index cd2b860400c..c359f3c8102 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_debug.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_debug.test @@ -4,6 +4,10 @@ --source include/count_sessions.inc set default_storage_engine=innodb; +# Ensure that the history list length will actually be decremented by purge. +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + CREATE TABLE `t` ( `a` VARCHAR(100), `b` VARCHAR(100), @@ -338,4 +342,6 @@ DROP TABLE t1; connection default; SET DEBUG_SYNC=RESET; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; + --source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/gcol/t/innodb_virtual_purge.test b/mysql-test/suite/gcol/t/innodb_virtual_purge.test index 99c7267c88b..5f3cae34057 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_purge.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_purge.test @@ -1,6 +1,9 @@ --source include/have_innodb.inc --source include/count_sessions.inc +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + --echo # --echo # Bug#21869656 UNDO LOG DOES NOT CONTAIN ENOUGH INFORMATION --echo # ON INDEXED VIRTUAL COLUMNS @@ -182,4 +185,6 @@ SET GLOBAL innodb_max_purge_lag_wait=0; CHECK TABLE t EXTENDED; DROP TABLE t; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; + --source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/r/alter_kill.result b/mysql-test/suite/innodb/r/alter_kill.result index ef13e996703..13e64683040 100644 --- a/mysql-test/suite/innodb/r/alter_kill.result +++ b/mysql-test/suite/innodb/r/alter_kill.result @@ -2,6 +2,7 @@ # Bug#16720368 INNODB CRASHES ON BROKEN #SQL*.IBD FILE AT STARTUP # SET GLOBAL innodb_file_per_table=1; +SET GLOBAL innodb_stats_persistent=0; 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/dml_purge.result b/mysql-test/suite/innodb/r/dml_purge.result index 2b345089f8f..1ef8a5ea1b9 100644 --- a/mysql-test/suite/innodb/r/dml_purge.result +++ b/mysql-test/suite/innodb/r/dml_purge.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; # # MDEV-12288 Reset DB_TRX_ID when the history is removed, # to speed up MVCC @@ -46,3 +48,4 @@ a b c 1 2 NULL 3 -3 NULL DROP TABLE t1; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index bfed09d4a70..adf528af6f3 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -1,3 +1,4 @@ +SET GLOBAL innodb_stats_persistent = 0; # # Bug #19027905 ASSERT RET.SECOND DICT_CREATE_FOREIGN_CONSTRAINTS_LOW # DICT_CREATE_FOREIGN_CONSTR @@ -154,6 +155,8 @@ INSERT INTO parent SET a=0; FLUSH TABLES; # restart disconnect incomplete; +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; INSERT INTO child SET a=0; INSERT INTO child SET a=1; ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON DELETE CASCADE) @@ -1074,3 +1077,4 @@ test.collections check status OK disconnect con1; DROP TABLE binaries, collections; # End of 10.6 tests +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/r/full_crc32_import.result b/mysql-test/suite/innodb/r/full_crc32_import.result index 32964be46d4..548e69c1c52 100644 --- a/mysql-test/suite/innodb/r/full_crc32_import.result +++ b/mysql-test/suite/innodb/r/full_crc32_import.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; FLUSH TABLES; # Treating compact format as dynamic format after import stmt CREATE TABLE t1 @@ -200,3 +202,4 @@ a 3 DROP TABLE t1; SET GLOBAL innodb_compression_algorithm=@save_algo; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/r/index_merge_threshold.result b/mysql-test/suite/innodb/r/index_merge_threshold.result index 41897b80a4e..83f7ab33f68 100644 --- a/mysql-test/suite/innodb/r/index_merge_threshold.result +++ b/mysql-test/suite/innodb/r/index_merge_threshold.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; 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'; @@ -1307,3 +1309,4 @@ name count_reset index_page_merge_attempts 2 index_page_merge_successful 2 DROP TABLE tab1; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/r/innodb-16k.result b/mysql-test/suite/innodb/r/innodb-16k.result index 3d62a2f802c..a7fbe8602e1 100644 --- a/mysql-test/suite/innodb/r/innodb-16k.result +++ b/mysql-test/suite/innodb/r/innodb-16k.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; call mtr.add_suppression("InnoDB: Cannot add field .* in table"); # Test 1) Show the page size from Information Schema SELECT variable_value FROM information_schema.global_status @@ -505,6 +507,7 @@ INSERT INTO t1 VALUES(REPEAT('A',512)),(REPEAT('B',512)); DROP TABLE t1; InnoDB 0 transactions not purged SET GLOBAL innodb_compression_level=@save_level; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge; DROP TABLE tlong; DROP TABLE tlong2; diff --git a/mysql-test/suite/innodb/r/innodb-32k.result b/mysql-test/suite/innodb/r/innodb-32k.result index b64ff332084..dd19616bf24 100644 --- a/mysql-test/suite/innodb/r/innodb-32k.result +++ b/mysql-test/suite/innodb/r/innodb-32k.result @@ -1,3 +1,4 @@ +SET GLOBAL innodb_stats_persistent = 0; 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 c770d106bdc..ac966d3f4a1 100644 --- a/mysql-test/suite/innodb/r/innodb-system-table-view.result +++ b/mysql-test/suite/innodb/r/innodb-system-table-view.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; 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 @@ -173,3 +175,4 @@ DROP TABLE parent; SELECT SPACE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE name like 'innodb_temporary'; SPACE 4294967294 +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/r/innodb_scrub.result b/mysql-test/suite/innodb/r/innodb_scrub.result index b4a418ce2ad..475d4e74c04 100644 --- a/mysql-test/suite/innodb/r/innodb_scrub.result +++ b/mysql-test/suite/innodb/r/innodb_scrub.result @@ -1,6 +1,6 @@ CREATE TABLE t1(f1 int auto_increment primary key, f2 varchar(256), -f3 text) engine = innodb; +f3 text) engine = innodb stats_persistent=0; FLUSH TABLE t1 FOR EXPORT; UNLOCK TABLES; FOUND 500500 /unicycle|repairman/ in t1.ibd diff --git a/mysql-test/suite/innodb/r/innodb_stats_persistent.result b/mysql-test/suite/innodb/r/innodb_stats_persistent.result index a691ab19b30..72cd4df5cb3 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_persistent.result +++ b/mysql-test/suite/innodb/r/innodb_stats_persistent.result @@ -57,7 +57,7 @@ connection con1; EXPLAIN SELECT * FROM t2 WHERE val=4; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref val val 4 const 1 Using index -InnoDB 0 transactions not purged +SET GLOBAL innodb_max_purge_lag_wait=0; # After COMMIT and purge, the DELETE must show up. EXPLAIN SELECT * FROM t1 WHERE val=4; id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/suite/innodb/r/instant_alter.result b/mysql-test/suite/innodb/r/instant_alter.result index 898981ef125..870ad23c7ff 100644 --- a/mysql-test/suite/innodb/r/instant_alter.result +++ b/mysql-test/suite/innodb/r/instant_alter.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; # # MDEV-11369: Instant ADD COLUMN for InnoDB # @@ -2937,3 +2939,4 @@ index(id, msg) FLUSH TABLES; ALTER TABLE mdev28822_100427_innodb ADD i1 INTEGER, ALGORITHM=INSTANT; DROP TABLE mdev28822_100427_innodb; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/r/instant_alter_bugs.result b/mysql-test/suite/innodb/r/instant_alter_bugs.result index feacaa6b40d..7d5f7e9cc4f 100644 --- a/mysql-test/suite/innodb/r/instant_alter_bugs.result +++ b/mysql-test/suite/innodb/r/instant_alter_bugs.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; # # MDEV-17821 Assertion `!page_rec_is_supremum(rec)' failed # in btr_pcur_store_position @@ -492,3 +494,5 @@ CREATE TABLE t1 (i int AS (0) STORED, j INT) ENGINE=InnoDB; ALTER TABLE t1 ADD COLUMN i INT GENERATED ALWAYS AS (1), DROP COLUMN i; DROP TABLE t1; # End of 10.4 tests +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; +# End of 10.6 tests diff --git a/mysql-test/suite/innodb/r/instant_alter_debug,redundant.rdiff b/mysql-test/suite/innodb/r/instant_alter_debug,redundant.rdiff index cff4ff18c70..f442e406ce4 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug,redundant.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_debug,redundant.rdiff @@ -1,6 +1,8 @@ -@@ -527,4 +527,4 @@ +@@ -527,6 +527,6 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -35 +36 + SET GLOBAL innodb_stats_persistent = @save_stats_persistent; + # End of 10.6 tests diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index 1bd362f35b5..0473b9c3204 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; SET @old_instant= (SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'); @@ -526,3 +528,5 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants 35 +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; +# End of 10.6 tests diff --git a/mysql-test/suite/innodb/r/instant_alter_purge.result b/mysql-test/suite/innodb/r/instant_alter_purge.result index 61cffc9aec5..4163bf3fdba 100644 --- a/mysql-test/suite/innodb/r/instant_alter_purge.result +++ b/mysql-test/suite/innodb/r/instant_alter_purge.result @@ -5,7 +5,7 @@ InnoDB 0 transactions not purged connect prevent_purge,localhost,root; START TRANSACTION WITH CONSISTENT SNAPSHOT; connection default; -CREATE TABLE t1 (f1 INT, f2 INT) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INT, f2 INT) ENGINE=InnoDB STATS_PERSISTENT=0; INSERT INTO t1 () VALUES (); ALTER TABLE t1 DROP f2, ADD COLUMN f2 INT; ALTER TABLE t1 DROP f1; diff --git a/mysql-test/suite/innodb/r/instant_alter_rollback.result b/mysql-test/suite/innodb/r/instant_alter_rollback.result index dd427b625c1..6e84580c672 100644 --- a/mysql-test/suite/innodb/r/instant_alter_rollback.result +++ b/mysql-test/suite/innodb/r/instant_alter_rollback.result @@ -1,3 +1,4 @@ +SET GLOBAL innodb_stats_persistent = 0; FLUSH TABLES; # # MDEV-11369: Instant ADD COLUMN for InnoDB diff --git a/mysql-test/suite/innodb/r/page_id_innochecksum.result b/mysql-test/suite/innodb/r/page_id_innochecksum.result index 7915a7babbe..bde986c07ef 100644 --- a/mysql-test/suite/innodb/r/page_id_innochecksum.result +++ b/mysql-test/suite/innodb/r/page_id_innochecksum.result @@ -1,5 +1,5 @@ # Set the environmental variables -create table t1(f1 int not null)engine=innodb; +create table t1(f1 int not null)engine=innodb stats_persistent=0; insert into t1 values(1), (2), (3); # Change the page offset FOUND 1 /page id mismatch/ in result.log diff --git a/mysql-test/suite/innodb/r/purge.result b/mysql-test/suite/innodb/r/purge.result index ed14fad74b1..9284fa18a7d 100644 --- a/mysql-test/suite/innodb/r/purge.result +++ b/mysql-test/suite/innodb/r/purge.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; # Bug #12429576 - Test an assertion failure on purge. CREATE TABLE t1_purge ( A int, @@ -115,4 +117,5 @@ t12963823 CREATE TABLE `t12963823` ( KEY `ndx_p` (`p`(500)) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC InnoDB 0 transactions not purged +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge, t12637786, t12963823; diff --git a/mysql-test/suite/innodb/r/purge_secondary.result b/mysql-test/suite/innodb/r/purge_secondary.result index 9801e985486..70d16f1f505 100644 --- a/mysql-test/suite/innodb/r/purge_secondary.result +++ b/mysql-test/suite/innodb/r/purge_secondary.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; 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, @@ -167,3 +169,5 @@ page 5: N_RECS=0x0001 UNLOCK TABLES; DROP TABLE t1; # End of 10.3 tests +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; +# End of 10.6 tests diff --git a/mysql-test/suite/innodb/r/scrub_debug.result b/mysql-test/suite/innodb/r/scrub_debug.result index 1e60fb73dad..7b0a9fd501c 100644 --- a/mysql-test/suite/innodb/r/scrub_debug.result +++ b/mysql-test/suite/innodb/r/scrub_debug.result @@ -4,7 +4,7 @@ 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, f2 VARCHAR(256) GENERATED ALWAYS as('repairman'), -INDEX idx(f2))ENGINE= InnoDB; +INDEX idx(f2))ENGINE= InnoDB STATS_PERSISTENT=0; INSERT INTO t1(f1) SELECT seq FROM seq_1_to_50; FLUSH TABLE t1 FOR EXPORT; FOUND 108 /repairman/ in t1.ibd diff --git a/mysql-test/suite/innodb/r/truncate_crash.result b/mysql-test/suite/innodb/r/truncate_crash.result index 5e7380e3286..7df461ec3a7 100644 --- a/mysql-test/suite/innodb/r/truncate_crash.result +++ b/mysql-test/suite/innodb/r/truncate_crash.result @@ -1,5 +1,5 @@ FLUSH TABLES; -CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB STATS_PERSISTENT=0; INSERT INTO t1 VALUES (1),(2); connect wait,localhost,root,,test; SET DEBUG_SYNC='before_trx_state_committed_in_memory SIGNAL c WAIT_FOR ever'; diff --git a/mysql-test/suite/innodb/r/trx_id_future.result b/mysql-test/suite/innodb/r/trx_id_future.result index c9beb17b81c..487fa82c50c 100644 --- a/mysql-test/suite/innodb/r/trx_id_future.result +++ b/mysql-test/suite/innodb/r/trx_id_future.result @@ -2,7 +2,7 @@ # Bug #20445525 ADD A CONSISTENCY CHECK AGAINST DB_TRX_ID BEING # IN THE FUTURE # -CREATE TABLE t1(a INT) row_format=redundant engine=innoDB; +CREATE TABLE t1(a INT) row_format=redundant engine=innoDB stats_persistent=0; INSERT INTO t1 VALUES(1); InnoDB 0 transactions not purged call mtr.add_suppression("\\[Warning\\] InnoDB: A transaction id in a record of table `test`\\.`t1` is newer than the system-wide maximum"); diff --git a/mysql-test/suite/innodb/r/undo_log.result b/mysql-test/suite/innodb/r/undo_log.result index 6e377951960..014b1210ec0 100644 --- a/mysql-test/suite/innodb/r/undo_log.result +++ b/mysql-test/suite/innodb/r/undo_log.result @@ -1,3 +1,5 @@ +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; SET innodb_strict_mode=OFF; CREATE TABLE test_tab ( a_str_18 mediumtext, @@ -154,3 +156,4 @@ ROLLBACK; InnoDB 0 transactions not purged DROP TABLE t1; DROP TABLE t2; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/t/alter_kill.test b/mysql-test/suite/innodb/t/alter_kill.test index 3e0152ec458..01b9776fd2c 100644 --- a/mysql-test/suite/innodb/t/alter_kill.test +++ b/mysql-test/suite/innodb/t/alter_kill.test @@ -27,6 +27,7 @@ call mtr.add_suppression("InnoDB: Table `test`\\.`bug16720368` is corrupted"); -- echo # SET GLOBAL innodb_file_per_table=1; +SET GLOBAL innodb_stats_persistent=0; CREATE TABLE bug16720368_1 (a INT PRIMARY KEY) ENGINE=InnoDB; diff --git a/mysql-test/suite/innodb/t/dml_purge.test b/mysql-test/suite/innodb/t/dml_purge.test index 463ae3908b9..78c6c50ae71 100644 --- a/mysql-test/suite/innodb/t/dml_purge.test +++ b/mysql-test/suite/innodb/t/dml_purge.test @@ -1,5 +1,8 @@ --source include/innodb_page_size.inc +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + let INNODB_PAGE_SIZE=`select @@innodb_page_size`; let MYSQLD_DATADIR=`select @@datadir`; @@ -76,3 +79,5 @@ EOF UNLOCK TABLES; SELECT * FROM t1; DROP TABLE t1; + +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 06da1b6fe9d..35b88434323 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -2,6 +2,8 @@ --source include/count_sessions.inc --source include/default_charset.inc +SET GLOBAL innodb_stats_persistent = 0; + --echo # --echo # Bug #19027905 ASSERT RET.SECOND DICT_CREATE_FOREIGN_CONSTRAINTS_LOW --echo # DICT_CREATE_FOREIGN_CONSTR @@ -126,6 +128,9 @@ FLUSH TABLES; --let $shutdown_timeout= disconnect incomplete; +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + INSERT INTO child SET a=0; --error ER_NO_REFERENCED_ROW_2 INSERT INTO child SET a=1; @@ -1132,4 +1137,6 @@ DROP TABLE binaries, collections; --echo # End of 10.6 tests +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; + --source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/full_crc32_import.test b/mysql-test/suite/innodb/t/full_crc32_import.test index b79fd95471b..0eb31f8d63f 100644 --- a/mysql-test/suite/innodb/t/full_crc32_import.test +++ b/mysql-test/suite/innodb/t/full_crc32_import.test @@ -2,6 +2,9 @@ # This test is slow on buildbot. --source include/big_test.inc +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + FLUSH TABLES; let $MYSQLD_TMPDIR = `SELECT @@tmpdir`; @@ -222,3 +225,4 @@ SELECT * FROM t1; DROP TABLE t1; SET GLOBAL innodb_compression_algorithm=@save_algo; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/t/index_merge_threshold.test b/mysql-test/suite/innodb/t/index_merge_threshold.test index a60ecf51dca..cb8e117d453 100644 --- a/mysql-test/suite/innodb/t/index_merge_threshold.test +++ b/mysql-test/suite/innodb/t/index_merge_threshold.test @@ -13,6 +13,9 @@ --source include/have_innodb_16k.inc --source include/have_partition.inc +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + # Check index merge threshold by create index on all datatypes CREATE TABLE tab(a BIGINT PRIMARY KEY,c1 TINYTEXT,c2 TEXT,c3 MEDIUMTEXT, @@ -186,3 +189,5 @@ 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_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/t/innodb-16k.test b/mysql-test/suite/innodb/t/innodb-16k.test index 8bec62544c3..fd024047114 100644 --- a/mysql-test/suite/innodb/t/innodb-16k.test +++ b/mysql-test/suite/innodb/t/innodb-16k.test @@ -3,6 +3,9 @@ --source include/have_innodb.inc --source include/have_innodb_16k.inc +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + call mtr.add_suppression("InnoDB: Cannot add field .* in table"); let $MYSQLD_DATADIR= `select @@datadir`; @@ -457,6 +460,7 @@ DROP TABLE t1; --source include/wait_all_purged.inc SET GLOBAL innodb_compression_level=@save_level; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge; DROP TABLE tlong; diff --git a/mysql-test/suite/innodb/t/innodb-32k.test b/mysql-test/suite/innodb/t/innodb-32k.test index 496977c1bda..6e765ee833d 100644 --- a/mysql-test/suite/innodb/t/innodb-32k.test +++ b/mysql-test/suite/innodb/t/innodb-32k.test @@ -3,6 +3,7 @@ --source include/have_innodb.inc --source include/have_innodb_32k.inc +SET GLOBAL innodb_stats_persistent = 0; 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 659c42f0e09..663b76a1f18 100644 --- a/mysql-test/suite/innodb/t/innodb-system-table-view.test +++ b/mysql-test/suite/innodb/t/innodb-system-table-view.test @@ -4,6 +4,9 @@ --source include/innodb_page_size_small.inc +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + LET $MYSQLD_DATADIR = `select @@datadir`; LET $INNODB_PAGE_SIZE = `select @@innodb_page_size`; @@ -144,3 +147,5 @@ DROP TABLE parent; --echo # temporary tablespace information --echo # SELECT SPACE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE name like 'innodb_temporary'; + +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/t/innodb_scrub.test b/mysql-test/suite/innodb/t/innodb_scrub.test index 8fe460da4d3..cf6b92e1a75 100644 --- a/mysql-test/suite/innodb/t/innodb_scrub.test +++ b/mysql-test/suite/innodb/t/innodb_scrub.test @@ -4,7 +4,7 @@ let $MYSQLD_DATADIR=`select @@datadir`; CREATE TABLE t1(f1 int auto_increment primary key, f2 varchar(256), - f3 text) engine = innodb; + f3 text) engine = innodb stats_persistent=0; let $numinserts = 500; --disable_query_log begin; diff --git a/mysql-test/suite/innodb/t/innodb_stats_persistent.test b/mysql-test/suite/innodb/t/innodb_stats_persistent.test index a8a311a60c9..b923b49637e 100644 --- a/mysql-test/suite/innodb/t/innodb_stats_persistent.test +++ b/mysql-test/suite/innodb/t/innodb_stats_persistent.test @@ -49,7 +49,7 @@ SELECT COUNT(*) FROM t2; connection con1; EXPLAIN SELECT * FROM t2 WHERE val=4; ---source include/wait_all_purged.inc +SET GLOBAL innodb_max_purge_lag_wait=0; --echo # After COMMIT and purge, the DELETE must show up. EXPLAIN SELECT * FROM t1 WHERE val=4; diff --git a/mysql-test/suite/innodb/t/instant_alter.test b/mysql-test/suite/innodb/t/instant_alter.test index 5b6d3f874c1..d6d7a988d96 100644 --- a/mysql-test/suite/innodb/t/instant_alter.test +++ b/mysql-test/suite/innodb/t/instant_alter.test @@ -3,6 +3,9 @@ let $datadir=`select @@datadir`; +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + --echo # --echo # MDEV-11369: Instant ADD COLUMN for InnoDB --echo # @@ -964,3 +967,4 @@ remove_file $datadir/test/mdev28822_100427_innodb.frm; copy_file std_data/mysql_upgrade/mdev28822_100427_innodb.frm $datadir/test/mdev28822_100427_innodb.frm; ALTER TABLE mdev28822_100427_innodb ADD i1 INTEGER, ALGORITHM=INSTANT; DROP TABLE mdev28822_100427_innodb; +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/t/instant_alter_bugs.test b/mysql-test/suite/innodb/t/instant_alter_bugs.test index 81d36849abd..5a83eb16e1c 100644 --- a/mysql-test/suite/innodb/t/instant_alter_bugs.test +++ b/mysql-test/suite/innodb/t/instant_alter_bugs.test @@ -1,5 +1,8 @@ --source include/have_innodb.inc +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + --echo # --echo # MDEV-17821 Assertion `!page_rec_is_supremum(rec)' failed --echo # in btr_pcur_store_position @@ -527,3 +530,7 @@ ALTER TABLE t1 ADD COLUMN i INT GENERATED ALWAYS AS (1), DROP COLUMN i; DROP TABLE t1; --echo # End of 10.4 tests + +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; + +--echo # End of 10.6 tests diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index 2b34d829738..ab30eb0c7c9 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -3,6 +3,9 @@ --source include/have_debug_sync.inc --source include/have_sequence.inc +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + SET @old_instant= (SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'); @@ -607,3 +610,7 @@ SET DEBUG_SYNC=RESET; SELECT variable_value-@old_instant instants FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; + +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; + +--echo # End of 10.6 tests diff --git a/mysql-test/suite/innodb/t/instant_alter_purge.test b/mysql-test/suite/innodb/t/instant_alter_purge.test index 445cae4d03e..5fbd4da8818 100644 --- a/mysql-test/suite/innodb/t/instant_alter_purge.test +++ b/mysql-test/suite/innodb/t/instant_alter_purge.test @@ -14,7 +14,7 @@ connect (prevent_purge,localhost,root); START TRANSACTION WITH CONSISTENT SNAPSHOT; connection default; -CREATE TABLE t1 (f1 INT, f2 INT) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INT, f2 INT) ENGINE=InnoDB STATS_PERSISTENT=0; INSERT INTO t1 () VALUES (); ALTER TABLE t1 DROP f2, ADD COLUMN f2 INT; ALTER TABLE t1 DROP f1; diff --git a/mysql-test/suite/innodb/t/instant_alter_rollback.test b/mysql-test/suite/innodb/t/instant_alter_rollback.test index a4608001a25..491f63463c5 100644 --- a/mysql-test/suite/innodb/t/instant_alter_rollback.test +++ b/mysql-test/suite/innodb/t/instant_alter_rollback.test @@ -3,6 +3,8 @@ # The embedded server tests do not support restarting. --source include/not_embedded.inc +SET GLOBAL innodb_stats_persistent = 0; + # Flush any open myisam tables from previous tests FLUSH TABLES; diff --git a/mysql-test/suite/innodb/t/page_id_innochecksum.test b/mysql-test/suite/innodb/t/page_id_innochecksum.test index 902d2aba2af..9d8114d1720 100644 --- a/mysql-test/suite/innodb/t/page_id_innochecksum.test +++ b/mysql-test/suite/innodb/t/page_id_innochecksum.test @@ -6,7 +6,7 @@ let MYSQLD_BASEDIR= `SELECT @@basedir`; let MYSQLD_DATADIR= `SELECT @@datadir`; let INNODB_PAGE_SIZE=`select @@innodb_page_size`; -create table t1(f1 int not null)engine=innodb; +create table t1(f1 int not null)engine=innodb stats_persistent=0; insert into t1 values(1), (2), (3); let $resultlog=$MYSQLTEST_VARDIR/tmp/result.log; diff --git a/mysql-test/suite/innodb/t/purge.test b/mysql-test/suite/innodb/t/purge.test index 97c0fb86105..1dc2b1175dc 100644 --- a/mysql-test/suite/innodb/t/purge.test +++ b/mysql-test/suite/innodb/t/purge.test @@ -1,6 +1,9 @@ --source include/have_innodb.inc --source include/have_innodb_16k.inc +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + --echo # Bug #12429576 - Test an assertion failure on purge. CREATE TABLE t1_purge ( A int, @@ -110,4 +113,6 @@ SHOW CREATE TABLE t12963823; # We need to activate the purge thread before DROP TABLE. -- source include/wait_all_purged.inc + +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge, t12637786, t12963823; diff --git a/mysql-test/suite/innodb/t/purge_secondary.test b/mysql-test/suite/innodb/t/purge_secondary.test index 4e664109e8b..8a38a418877 100644 --- a/mysql-test/suite/innodb/t/purge_secondary.test +++ b/mysql-test/suite/innodb/t/purge_secondary.test @@ -1,6 +1,9 @@ --source include/have_innodb.inc --source include/have_sequence.inc +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + --disable_query_log call mtr.add_suppression("InnoDB: Difficult to find free blocks in the buffer pool"); --enable_query_log @@ -170,3 +173,7 @@ UNLOCK TABLES; DROP TABLE t1; --echo # End of 10.3 tests + +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; + +--echo # End of 10.6 tests diff --git a/mysql-test/suite/innodb/t/scrub_debug.test b/mysql-test/suite/innodb/t/scrub_debug.test index a1f0b38e3ae..8cebfca6106 100644 --- a/mysql-test/suite/innodb/t/scrub_debug.test +++ b/mysql-test/suite/innodb/t/scrub_debug.test @@ -10,7 +10,7 @@ SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=2; let $MYSQLD_DATADIR=`select @@datadir`; CREATE TABLE t1(f1 INT AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(256) GENERATED ALWAYS as('repairman'), - INDEX idx(f2))ENGINE= InnoDB; + INDEX idx(f2))ENGINE= InnoDB STATS_PERSISTENT=0; INSERT INTO t1(f1) SELECT seq FROM seq_1_to_50; FLUSH TABLE t1 FOR EXPORT; let SEARCH_PATTERN= repairman; diff --git a/mysql-test/suite/innodb/t/truncate_crash.test b/mysql-test/suite/innodb/t/truncate_crash.test index c5156b4b3fd..8a11b1ed531 100644 --- a/mysql-test/suite/innodb/t/truncate_crash.test +++ b/mysql-test/suite/innodb/t/truncate_crash.test @@ -4,7 +4,7 @@ --source include/not_embedded.inc FLUSH TABLES; -CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB STATS_PERSISTENT=0; INSERT INTO t1 VALUES (1),(2); connect (wait,localhost,root,,test); diff --git a/mysql-test/suite/innodb/t/trx_id_future.test b/mysql-test/suite/innodb/t/trx_id_future.test index 1aeb1372eed..049e8f2c6f3 100644 --- a/mysql-test/suite/innodb/t/trx_id_future.test +++ b/mysql-test/suite/innodb/t/trx_id_future.test @@ -8,7 +8,7 @@ let PAGE_SIZE=`select @@innodb_page_size`; -CREATE TABLE t1(a INT) row_format=redundant engine=innoDB; +CREATE TABLE t1(a INT) row_format=redundant engine=innoDB stats_persistent=0; INSERT INTO t1 VALUES(1); let MYSQLD_DATADIR=`select @@datadir`; diff --git a/mysql-test/suite/innodb/t/undo_log.test b/mysql-test/suite/innodb/t/undo_log.test index 2dbc9191f33..60da94c39eb 100644 --- a/mysql-test/suite/innodb/t/undo_log.test +++ b/mysql-test/suite/innodb/t/undo_log.test @@ -1,5 +1,8 @@ --source include/have_innodb.inc +SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; +SET GLOBAL innodb_stats_persistent = 0; + SET innodb_strict_mode=OFF; CREATE TABLE test_tab ( a_str_18 mediumtext, @@ -151,3 +154,5 @@ ROLLBACK; --source include/wait_all_purged.inc DROP TABLE t1; DROP TABLE t2; + +SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/t/undo_space_dblwr.opt b/mysql-test/suite/innodb/t/undo_space_dblwr.opt index 0b4f59176f3..f498dd1fc93 100644 --- a/mysql-test/suite/innodb/t/undo_space_dblwr.opt +++ b/mysql-test/suite/innodb/t/undo_space_dblwr.opt @@ -1,2 +1,3 @@ --innodb_undo_tablespaces=3 --innodb_sys_tablespaces +--innodb-stats-persistent=0 diff --git a/mysql-test/suite/innodb_fts/r/crash_recovery.result b/mysql-test/suite/innodb_fts/r/crash_recovery.result index c6fc9dfaab9..b6319014256 100644 --- a/mysql-test/suite/innodb_fts/r/crash_recovery.result +++ b/mysql-test/suite/innodb_fts/r/crash_recovery.result @@ -33,7 +33,7 @@ connection default; disconnect ddl1; disconnect ddl2; disconnect ddl3; -InnoDB 0 transactions not purged +SET GLOBAL innodb_max_purge_lag_wait=0; 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 dd8a07f8de9..ac3f038559b 100644 --- a/mysql-test/suite/innodb_fts/t/crash_recovery.test +++ b/mysql-test/suite/innodb_fts/t/crash_recovery.test @@ -113,7 +113,7 @@ disconnect ddl3; # 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_max_purge_lag_wait=0; 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 ba552e278d4..be15d97ad16 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_add_index.result +++ b/mysql-test/suite/innodb_gis/r/rtree_add_index.result @@ -1,4 +1,4 @@ -CREATE TABLE t1 (g MULTIPOINT NOT NULL) ENGINE=InnoDB; +CREATE TABLE t1 (g MULTIPOINT NOT NULL) ENGINE=InnoDB STATS_PERSISTENT=0; INSERT INTO t1 VALUES (''); connect purge_control,localhost,root; START TRANSACTION WITH CONSISTENT SNAPSHOT; diff --git a/mysql-test/suite/innodb_gis/r/rtree_compress.result b/mysql-test/suite/innodb_gis/r/rtree_compress.result index fce42319b55..db9d5bd634c 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_compress.result +++ b/mysql-test/suite/innodb_gis/r/rtree_compress.result @@ -1,4 +1,6 @@ -create table t1 (c1 int, c2 geometry not null, spatial index (c2))engine=innodb ROW_FORMAT=COMPRESSED; +create table t1 (c1 int, c2 geometry not null, spatial index (c2))engine=innodb ROW_FORMAT=COMPRESSED STATS_PERSISTENT=0; +lock tables t1 write; +start transaction; insert into t1 values(1, Point(1,1)); insert into t1 values(2, Point(2,2)); insert into t1 values(3, Point(3,3)); @@ -18,6 +20,8 @@ insert into t1 select * from t1; insert into t1 select * from t1; insert into t1 select * from t1; insert into t1 select * from t1; +commit; +unlock tables; start transaction; insert into t1 select * from t1; select count(*) from t1; diff --git a/mysql-test/suite/innodb_gis/r/rtree_purge.result b/mysql-test/suite/innodb_gis/r/rtree_purge.result index 4c39cc988c6..35953c326c3 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_purge.result +++ b/mysql-test/suite/innodb_gis/r/rtree_purge.result @@ -1,5 +1,5 @@ create table t ( b point not null,d point not null, spatial key (d),spatial key (b) -) engine=innodb; +) engine=innodb stats_persistent=0; InnoDB 0 transactions not purged drop table t; diff --git a/mysql-test/suite/innodb_gis/r/rtree_undo.result b/mysql-test/suite/innodb_gis/r/rtree_undo.result index d0e1564133f..1f44542fc64 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_undo.result +++ b/mysql-test/suite/innodb_gis/r/rtree_undo.result @@ -4,7 +4,7 @@ CREATE TABLE t1 ( p INT NOT NULL AUTO_INCREMENT, g LINESTRING NOT NULL, PRIMARY KEY(p) -) ENGINE=InnoDB; +) ENGINE=InnoDB STATS_PERSISTENT=0; ALTER TABLE t1 ADD INDEX prefix_idx (g(767)); INSERT INTO t1(g) VALUES(ST_linefromtext('linestring(-5 -576,0 -576,0 -571,0 -571,5 -568,6 -564,6 -565,6 -563)')); INSERT INTO t1(g) VALUES(ST_linefromtext(concat('linestring','(18 106,19 106,24 111,27 108,32 104,37 107,42 107,44 112,44 116,40 118,43 114,46 114,42 118,44 123,45 123,49 123,53 119,50 123,50 124,54 126,58 125,59 126,64 127,65 127,69 131,74 132,75 135,78 139,2078 141,2075 143,2077 143,2079 143,2084 143,2085 147,2090 -1853,2086 -1852,2086 -1856,2089 -1852,2093 -1850,2090 -1851,2090 -1852,2091 -1851,2092 -1850,2097 -1847,2102 -1848,2100 -1852,2100 -1852,7100 -1851,7103 -1850,7104 -1847,7109 -1842,65 127,67 131,66 131,61 132,61 133,62 137,65 1137,2065 1135,2061 1135,2064 1135,5064 1135,5066 1135,5070 1136,5070 1141,5071 1138,5074 1141,5075 1141,5074 1137,5076 1137,5071 1139,5066 1142,5065 2142,5068 2147,5073 2151,5069 2156,5071 2157,5072 2162,5074 2165,5069 2169,5072 2169,5076 2173,5074 2169,5078 2169,5076 2170,76 2175,74 2179,75 2184,80 2188,83 2190,87 2189,84 2193,87 2189,86 2190,87 2195,87 2200,87 1200,85 1202,86 1199,87 1200,87 1201,91 1206,92 1204,94 1204,98 1206,102 1208,105 1211,102 1216,105 1220,109 1224,110 1224,114 1225,117 1224,118 1229,117 1232,122 1237,123 1236,120 1235,124 1237,121 1236,122 1240,126 1244,127 1246,126 1249,125 5249,123 5251,127 5251,131 5251,135 5256,138 5257,135 5257,139 5257,138 5258,141 5260,146 5260,146 5260,143 10260,147 10265,151 10270,156 10266,157 10269,162 10273,166 12273,168 12274,163 12270,168 12275,170 12277,170 12277,-3830 12277,-3825 12277,-3824 12278,-3825 12276,-3825 12278,-3822 12277,-3825 12275,-3829 12278,-3828 12275,-3824 12280,-3827 12280,-3826 12282,-3822 12283,-3822 12286,-3820 12288,-3818 12289,-3816 12294,-3817 12297,-3819 12300,-3816 12297,-3813 12295,-3811 12299,-3811 12297,-3806 12298,-3806 12298,-3804 12301,-3801 12306,-3803 17306,-3803 17306,-3798 17306,-3803 17310,-3801 17314,-3798 17317,-3797 17317,-797 17321,-797 17323,-796 17325,-793 17326,-792 17322,-789 17327,-784 17331,-780 17335,-776 17339,-774 17339,-771 17342,-770 17345,-765 17348,-765 17349,-763 17353,-760 17350,-760 22350,-756 22346,-752 22349,-748 22352,-752 22348,-748 22347,-746 22345,-745 27345,-743 27346,257 27350,260 27349,261 27352,266 27348,266 22348,269 22347,271 22347,272 22347,273 22348,273 22352,278 22348,279 22344,282 22345,282 22342,283 22347,283 22347,288 22349,292 22347,292 22348,293 22348,298 22348,303 22351,306 22352,309 22352,308 22354,310 22356,311 22361,311 22358,311 22360,311 22360,315 22356,320 22358,325 22363,326 22366,321 22371,318 22373,318 22375,314 22375,316 22375,321 22376,321 22376,322 22372,32 104,36 109,40 114,40 113,40 117,44 119,49 123,49 126,49 129,53 133,50 137,50 139,49 137,48 138,43 138,42 139,46 142,46 138,41 139,45 141,4045 5141,4045 5146,4042 5147,4043 10147,4041 10150,4042 10152,4045 10152,4041 10156,4041 10152,4041 10152,4046 10153,4049 10156,4046 10155,4051 10157,4055 10159,4055 10160,4056 10161,4055 10166,4054 10169,4054 10172,4054 15172,4051 15176,4047 15177,4049 15174,4047 15176,4047 15176,4046 15177,4046 15180,4043 15184,4043 15187,4038 15190,4040 15194,4040 15199,4045 15196,4047 15197,4050 15200,4050 15204,4050 15208,4047 15212,4047 15215,4049 15216,4046 15218,4042 15223,4042 15228,4042 15232,4047 15235,4050 15236,4050 15239,4051 15243,4053 15243,4050 17243,4052 17243,4052 18243,4057 18247,4061 18249,4064 18249,4067 20249,4067 20250,4067 20255,4066 20259,4066 20259,4067 20255,4069 20256,4071 20258,4072 20254,4067 20257,4067 20260,4069 20265,4065 20267,4069 20266,4070 20267,4071 20264,4074 20259,4070 20264,4073 20260,4074 20263,4077 20268,4082 20271,4084 20273,4084 20277,4081 18277,4085 18279,4086 18276,4087 18273,4087 18275,4092 18277,4093 18279,4093 18280,4095 18280,4091 18283,4092 18281,4094 18283,4090 18287,4094 18287,138 5257,138 5255,138 5258,-1862 5254,-1860 5256,-1856 5258,-1851 5255,-1850 5260,-1847 5260,-1847 5263,-1847 5258,-1850 5257,-1850 5259,-1851 5257,-1855 5258,-1853 5261,-1849 5261,-1849 5258,-1849 5259,-1845 5264,-1847 5264,-1850 5268,-1852 5266,-1853 5270,-1856 5265,-1852 5262,-1847 5263,-1842 5263,-1842 5260,-1842 5265,-1841 5265,-1844 5265,-1842 5270,-1837 5274,-1838 5279,-1843 5275,-1842 5280,-1838 5281,-1838 5285,-1833 5285,-1828 5288,-1824 5289,-1828 5291,-1831 5291,-1826 5291,-1830 5293,-1826 5296,-1822 5301,-1826 5302,-1826 5302,-1826 5302,-1825 5297,-1820 5299,-1816 5303,-1816 5299,-3811 12299,-3809 12302,-3806 12302,-3806 12302,-3803 12304,-3798 12304,-3797 12304,-3793 12306,-3788 12306,-3783 12309,-3816 12294,-3811 12299,-3809 12297,7100 -1851,7098 -1854,7102 -1854,7107 -1856,7107 -1858,7110 -1854,7110 -1851,7113 -1851,7115 -1851,7120 -1851,7123 -1847,7124 -1852,7125 -1852,7127 -1852,7131 -1852,7129 1148,7129 1145,7133 1150,7137 1148,7138 1147,7143 1149,7147 1154,8147 1155,8152 3155,8147 3157,8143 3158,8144 3160,8144 3164,11144 3167,11146 3167,11148 3163,11152 3161,11148 3159,11149 3163,11150 3161,11151 3166,11154 3171,11154 3170,8144 3160,8144 3163,8144 3166,8145 3166,8146 3171,8146 3174,8144 3174,8144 3174,8145 3176,8141 3180,3141 3182,7141 3183,7141 7183,7136 7185,7136 7185,7133 7187,7136 7187,7131 7190,7136 7194,7137 7197,7141 7196,7139 7199,12139 7200,12143 7200,12143 7199,12144 7203,12145 7200,12141 7200,12136 7195,12136 7191,12137 7191,12137 7196,12139 7197,12140 7197,12137 7201,12140 7204,12140 7209,12143 7209,12145 7210,12147 7214,12148 9214,12152 9218,12149 9218,12149 9221,12149 9220,12150 9222,12153 10222,12153 10226,12156 10227,12159 10223,12160 10220,12161 10225,12161 10227,12163 10224,12163 10223,12158 10224,12158 10227,12158 10231,12155 12231,12157 12226,7136 7185,7139 7189,7139 7189,7139 7188,7137 7191,7139 7191,7140 7189,7143 7191,7144 7189,7144 7190,7149 7193,7152 7194,7154 7198,7153 7203,7148 7207,12148 7209,12146 7209,12145 7213,12140 7217,12139 7219,12141 7219,12138 7218,12143 7218,13143 7220,13140 7224,13142 7228,13137 7231,13142 7235,13146 7239,13149 7243,13148 7247,13150 7248,13155 7249,13155 7253,13155 7253,13155 7258,13157 7260,13162 7255,13159 7255,13163 7258,13164 7258,13164 7263,13167 7264,13167 8264,13165 8265,13169 8265,13171 13265,13175 13261,13176 13259,13176 13259,13180 13262,13181 13262,13183 13262,13188 13265,13191 13267,13191 13265,13194 13267,13191 13269,13192 13264,13196 13269,13198 13272,13200 13272,13202 13270,13207 11270,13211 11270,13211 11273,13213 11274,13217 11275,13222 11276,13222 11272,13226 11274,13231 11277,13233 11282,13236 11284,13238 11284,13236 11286,13236 11288,13236 11283,13236 11284,13238 11289,13241 11292,13244 11292,13245 11289,13241 11294,13244 11298,13249 11301,320 22358,324 24358,328 24358,327 24363,326 24359,327 24361,329 24365,334 24367,-666 24367,-670 24368,49 123,46 127,46 129,49 131,49 136,47 135,45 138,3045 135,3042 138,3044 139,3044 144,3049 144,3053 142,3055 137,3058 136,3053 139,3048 142,7048 138,7048 3138,7048 3139,7048 3140,7050 3145,7053 1145,7050 1146,7053 5146,7048 5150,7047 5146,10047 5147,10043 5147,10047 5147,10050 5152,10052 5155,10054 5156,10056 5157,10056 5159,10058 5162,10062 5164,10062 5169,10066 9169,10068 9168,10063 9164,10063 9169,10061 9171,14061 9172,14061 9174,282 22342,287 22347,288 22347,288 22343,285 22339,280 22338,278 22341,279 25341,284 25343,13241 11294,13246 11296,13243 11296,13244 11291,13245 11291,13244 11291,13246 11295,13251 11300,13253 11305,13253 11306,13258 11305,13255 11306,13256 11309,13256 11311,13261 11307,13265 11303,13267 11305,13270 11301,13275 11298,13271 11300,15271 11302,15276 11306,15279 11303,15284 11305,15286 11305,15289 11307,15290 11302,15292 11305,15296 11309,15297 11313,15298 11316,15300 11317,15304 11320,15306 11324,15306 11320,15307 11320,15312 11320,15313 11319,15317 11317,15315 11321,15317 11323,15317 11328,15319 11333,15322 11336,15322 11337,15322 11337,15324 11341,15324 11345,15325 14345,15328 13345,17328 13346,17333 13349,17337 13354,17338 13358,17342 13358,17346 13353,17348 13353,17345 13353,17348 13354,17347 13354,17347 13354,17347 13355,22347 13358,22349 13355,22351 13355,22356 13354,22358 13354,22361 13355,22362 13355,22358 13355,22359 13359,22364 13364,22369 13369,22372 13373,22376 13371,22377 13371,22377 13369,22381 13374,22386 13379,22387 13376,22387 13380,22392 13378,22390 13374,22392 13378,22391 13378,22391 13375,22392 13378,22390 13380,22393 13382,22398 13387,22398 10387,22402 10391,22399 10392,22400 10392,22400 10394,22404 10391,22403 15391,22405 15392,22407 15392,22412 15387,22412 15390,22412 15394,22408 15396,26408 15398,26407 20398,26411 20402,26415 20406,26417 20411,26420 20407,26422 20407,31422 16407,31421 16405,31421 16410,31423 16410,31426 16414,31426 16410,31430 16415,31430 16418,31435 16419,31437 16420,31438 16422,31438 16425,31438 16425,31441 16427,31439 16431,31441 16436,36441 16436,36443 18436,36442 18437,36440 18440,36440 18436,36440 18440,36442 18445,36443 18446,36447 18451,37447 23451,37452 23456,37456 23455,37458 23459,37456 23461,37458 23463,37460 23466,37464 23469,37460 23474,37462 23476,37461 26476,37466 26479,37470 26483,37471 26488,37474 26489,37474 26485,37474 26483,37474 26488,37470 26492,37474 26497,37474 26499,37478 26495,37483 26499,37483 26501,37488 26496,37491 26499,37495 26495,37500 26496,37500 26497,37500 26501,37497 26499,37497 26499,37495 26504,37498 26504,37494 26509,37497 26514,37495 26515,37498 26514,37503 26514,37508 26512,37510 26516,37511 26519,37509 26523,37506 26528,37507 26532,37512 26536,37513 26538,37510 26542,37512 26544,37517 26543,37522 26546,37527 26551,37525 26555,37529 26558,37524 26563,37524 26562,37527 26562,37522 26562,37522 26559,37526 26561,37522 26559,37523 26561,37523 26556,37524 26558,40524 26560,40524 26563,40521 26567,40525 26566,40527 26568,40532 26572,40534 26569,40533 26565,40531 26565,40535 26569,40535 26570,40539 26572,40544 26575,40543 26575,40544 26579,40548 26584,40549 26581,40553 26585,40556 26590,40552 22590,40557 22594,40556 22595,40561 22592,40561 22593,40565 22593,40568 22593,40573 22588,40570 22590,40570 22591,40570 22588,40573 22590,40573 22593,40568 22593,40567 22597,40567 22599,40571 22599,40574 22600,40574 22604,42574 22607,42577 22607,42577 22612,42579 22616,38579 22619,38580 22617,38580 22614,38575 22619,38579 22619,38579 18619,38582 18614,38582 18617,38586 18622,38590 18625,38590 18622,38594 18621,38596 18616,38597 18614,38597 18618,38600 21618,38601 21618,38605 21620,38607 25620,38611 25620,38608 25617,38608 25621,38608 25625,38611 25623,38615 25623,38615 25620,38616 25622,38619 25624,38620 25625,38620 26625,38623 26627,38623 26627,311 22358,311 22359,-1689 22360,2311 27360,2312 27360,2312 27360,2317 27362,2317 27362,2319 27359,2319 27364,2318 27359,2321 27364,2326 27367,2325 27371,2326 27373,2326 27373,2325 27377,2329 27377,2327 27377,2330 27379,2333 27379,2331 27379,2331 27381,2336 27381,6336 27382,6336 27383,40527 26568,40531 26572,40533 26574,40538 26576,40533 26580,40538 26585,40539 26588,40536 26583,40540 26587,40539 26588,40535 26593,40540 26594,40544 26597,40548 26602,40548 26601,40549 26602,40547 26602,40548 26603,40553 26606,40548 26606,40548 26603,40551 26608,40556 26612,40559 26616,40554 26619,40556 26619,40556 26623,42556 26623,42556 26624,42560 26624,42562 26626,42563 26630,42564 26630,42564 26634,42559 26635,42562 26635,42565 26637,42562 26638,42564 26642,42564 26641,42568 26641,42572 26641,42572 29641,42574 29642,39574 29641,39574 34641,39576 34643,39581 34638,39578 34638,39574 34642,39574 34645,39572 35645,34572 35648,34577 35651,39577 35655,43577 35659,43580 35655,43575 35658,43578 35658,43581 35662,43577 39662,43572 39658,43572 39661,43572 39664,43572 39666,43576 39670,43577 39667,43580 39671,43576 39673,43573 39673,43574 39677,43569 39679,43567 39679,43568 39683,43563 39686,43566 39690,43566 39692,43568 39694,43568 39695,41568 39691,41570 39692,41571 39692,41571 39693,41571 39698,41571 39698,41574 39698,41569 39698,41570 39699,41570 39704,41572 39709,41573 39712,41578 39713,41579 39717,41584 39719,41585 39720,-1850 5268,-1845 5268,-1847 5266,-1842 5268,-1840 5263,-1845 5264,-1843 5264,-1839 8264,-1839 8267,-1839 8272,-1838 8276,-1834 8273,-1834 8273,-1833 8274,-1837 8279,-1836 8283,-1834 8286,-1836 8282,-1834 8279,-1835 8279,-1834 8280,-1836 8283,-1841 8288,-1846 8289,-1843 8286,-1838 8286,-1841 8285,-1838 8285,-1834 8288,-1829 8291,-1825 8286,-1825 8289,-1825 8287,-1824 8291,-1822 8294,-1821 8298,-1818 8300,-1818 8296,-1814 8296,-1811 8295,-1808 8292,1192 8296,1192 8297,1195 11297,1192 11301,1195 11305,1197 11300,1193 11300,1193 11296,1193 11293,1194 11294,1199 11292,1204 11292,1205 11294,1210 11292,1208 11288,1204 11290,1205 11289,1207 8289,1202 8284,1204 8282,1204 8281,1206 8281,1208 8281,1212 8283,1212 13283,1213 13287,1213 13290,1216 13293,1214 13289,1217 13286,1212 13291,1208 13288,1208 13292,1209 13297,1208 13296,1204 13298,1205 13303,1209 13308,1204 13308,1209 13304,1210 13304,1214 13309,1214 13314,1215 13314,1219 13314,1219 13319,1224 13320,1229 13321,1232 13325,1233 13329,1231 13329,1234 13334,-2766 13336,-2769 13337,-2765 13340,-2762 13345,-2760 13342,2240 13342,2238 13342,2242 13342,2246 13345,2246 13346,2244 13348,2239 13348,2240 13351,2240 13352,2245 13357,2248 13357,2243 13362,2247 13362,2248 13362,2252 13363,2256 13363,2256 13363,2260 13367,2255 13372,2251 13369,2251 13369,2252 13372,2249 13376,2254 13378,2255 13382,2259 13379,2262 13379,2267 13381,2262 13381,2262 13383,2265 13383,2269 13385,2270 13386,2271 13389,2267 13391,2271 13386,2275 13391,2273 13392,2275 13387,2277 13390,2274 13390,2275 13394,2280 13395,2280 11395,2281 14395,2279 14400,2277 14403,2273 14406,2274 16406,2274 16410,2279 16410,2284 16411,2280 16409,2280 16409,2282 16409,2282 16411,2282 16412,2280 16413,3280 16418,3284 16418,3285 16423,3289 16423,3292 16427,3294 16429,3296 16431,3297 16436,3298 16435,3303 16435,3305 16434,3305 16436,3305 16436,3309 16437,3309 16438,3308 16439,3308 16439,3306 16444,3302 16441,-1698 16437,-1703 16438,-1699 16438,-1697 16438,-1698 16439,-1695 16436,-1690 16441,-1687 16446,-1683 16450,-1682 16451,-1684 16453,-1682 16457,-1682 16457,-1686 16460,-1681 16459,-1680 16456,-1677 16460,-1681 16461,-1679 16464,-1674 16465,-1673 16469,-1669 16471,-1669 16476,-1665 16474,-1665 16478,-1664 16478,-1664 16479,-1661 16474,-1656 16471,-1655 11471,-1660 11473,-1663 11475,-1666 11480,3334 15480,3338 15476,3342 15471,3345 15471,3345 15470,3350 15469,3347 15474,3351 15476,3352 15473,3353 15476,3350 15477,3350 15479,3351 15482,3352 15484,3351 15487,3353 15487,3358 15487,3353 15486,1217 13286,1222 13291,1222 13291,1225 13286,1229 13286,1231 13281,1235 13280,1236 13281,1241 13282,1245 13285,1247 13285,1247 13287,1250 13287,1247 13290,1247 13295,1247 13298,1252 13301,1249 13304,1252 13304,3252 13304,3247 13304,3249 13308,3254 13308,3257 13308,3261 17308,3261 17309,3261 17306,3259 17305,3262 17310,3263 17308,3262 17311,3259 17314,3259 17314,3257 17309,3254 17309,3253 17309,3255 17310,3253 17312,3255 17312,3255 17312,3256 17307,3257 17307,3256 17311,3256 17313,3255 17317,3251 17317,3248 17321,3253 17325,3256 17326,3258 17324,3258 17327,3263 17322,7263 17325,7265 17328,7263 17330,7265 17333,7270 17333,7273 17333,7278 17336,4278 21336,4278 21340,4279 21340,4281 21340,4286 24340,4290 24343,9290 24347,9294 24349,9296 24347,9298 25347,9301 25348,9301 25348,9304 25353,9303 25357,9303 25352,11303 25355,11304 25358,11307 25358,11312 25358,11312 25361,11310 25365,11313 25365,11314 25369,11319 25371,11321 25371,11325 25366,11329 25365,11330 25366,11329 25370,11330 25365,11334 25367,11338 25366,11343 25363,11348 25359,11345 25356,11348 25357,11349 25358,11349 25358,11352 25360,11356 30360,11360 30365,11360 30365,11362 30365,11367 30367,11368 30369,15368 30370,15373 30371,15376 30373,14376 30378,14377 30383,14381 30378,14386 30380,14388 30382,14391 30385,14393 31385,16393 31389,16396 31394,16396 31397,16392 31400,16395 31405,16398 31409,16398 31413,16397 31415,16396 31417,16401 31418,16401 31422,16402 31419,16407 31420,16411 31419,16406 31423,18406 31427,18411 31432,18415 28432,18417 28437,18418 28441,18414 28438,18417 28435,18416 28439,18420 28442,18423 28447,18427 28444,21427 28445,21428 28450,22428 28455,22432 28457,22436 28458,22441 28458,22445 28463,22448 28468,22451 28465,22456 28468,22453 28468,22458 28471,22463 28473,22460 28475,22459 28472,22463 28476,22464 28472,22468 28468,22468 28471,25468 28466,25471 28468,25473 28464,25473 28464,25475 29464,25476 29466,25479 29461,25476 29462,25476 29464,25478 29464,25483 29461,25484 29460,25486 29458,25486 29462,25490 29460,25495 26460,25498 26463,25495 26468,25495 26472,25495 26472,25499 26474,25504 26476,25504 26478,25509 26476,25513 26479,25514 26481,25519 26477,25519 26480,25518 26481,25519 26484,25524 26483,25527 26484,25522 26484,25526 26487,25528 26492,25533 26496,25535 26498,25535 26498,25539 26503,25542 26504,25543 26505,25547 26510,25552 26510,25551 26508,25550 26512,25553 26510,25557 26510,25554 26511,25552 26508,25556 26505,25556 26506,25560 26506,25560 26507,25560 26506,25565 26501,25567 26504,25569 26504,25568 26508,25571 26508,25571 26511,25576 26511,25581 26516,25581 26519,25582 26521,25585 26522,25588 26527,25588 26526,25584 26530,25587 26534,25589 26529,25593 26533,25598 26538,25599 26540,25599 26540,25599 26540,25604 26543,25603 26543,25603 26538,25606 26538,25609 26540,25611 26542,25612 26547,25612 26547,25612 26548,25617 25548,25612 25548,25613 25547,25616 25545,25616 25549,25618 25551,25620 25555,25620 25551,25622 25550,25625 25551,25622 25555,25619 25557,25617 25556,25622 28556,25625 28551,25630 28546,25634 28548,25639 28553,25643 28553,25638 25553,25634 25553,25634 25557,25639 25557,25643 25558,25644 25553,25646 25556,25647 25560,25650 25562,25650 30562,25650 30562,25650 30564,25650 30566,25652 30570,25656 30571,25661 31571,25662 31575,25663 31579,25662 31579,25665 31581,25666 31584,25671 31582,25674 31581,25674 31584,25676 31584,25673 31587,25678 31586,25679 31581,30679 31584,30675 31589,30680 31590,35680 31590,35675 31589,35677 31591,35680 31590,35681 31587,35684 31588,35685 31589,35689 31592,35689 31593,35692 31597,35696 31597,35700 34597,35699 34599,35703 34604,35703 34606,35702 34601,35705 34603,35705 34606,35708 34603,35713 34604,35717 34603,35719 34608,35715 34608,35711 34608,35713 34609,35714 34605,35714 34610,35714 34614,35718 34616,35719 34617,35722 34618,35722 34621,35725 34625,35725 34626,35725 34629,35725 34631,35725 34635,35730 34636,35727 34638,35731 34640,35735 34642,35739 34645,35741 34645,35742 34649,35738 34649,35738 34645,35741 34647,38741 34650,38741 37650,38742 37646,38746 37651,38749 37652,38753 37653,38753 37657,38757 37656,38756 37660,38761 37660,38765 37660,38760 37660,38759 37660,38760 41660,38760 41660,38762 41665,38757 41667,43757 41669,43752 41674,43752 41677,43757 41672,43758 41677,45758 41680,45758 41679,45762 41683,45765 41683,45769 41683,45770 41684,45768 46684,45773 46688,45776 46692,45774 46694,45775 46697,45778 46695,45776 46698,45774 46702,45779 46702,45784 46704,45787 46706,45791 46711,45786 46707,45790 46711,45793 46715,45796 46719,45799 46724,45797 46728,45802 46726,45797 46729,45801 46733,45802 46733,45803 46732,45804 46732,45805 46732,45808 46735,45810 46740,45810 46744,2326 27373,2322 27377,2323 27379,2325 27383,2325 27382,2322 27382,2323 27382,5323 23382,5325 23385,5329 23386,5330 23390,5335 23392,5330 23392,5330 23395,5329 23395,5333 23399,5333 23402,5338 23405,5339 23405,5334 23406,5329 23401,5332 23403,5330 23407,5333 23409,5328 20409,5324 20411,5324 20414,5329 20416,5328 20421,5325 20421,5329 20424,5330 20424,5335 21424,5331 21427,5333 21431,5334 21433,5329 21434,5330 21437,5333 21440,5338 21437,5338 21440,5334 21441,5333 21438,5329 26438,5332 26435,5335 26439,5337 26440,5338 26444,5342 26439,5342 26442,5345 26440,5349 26438,5352 26442,5349 26445,5348 30445,5350 30447,5350 30444,5354 30444,5359 30443,5363 30445,5367 30446,5367 30448,5367 30453,5371 30455,5371 30453,5373 30458,5375 30461,5380 30463,5384 30463,5383 30459,5384 30459,5383 30459,5385 30460,5390 30459,5392 30464,5394 30464,5389 30465,5393 30469,5391 30469,5391 30469,5395 30474,5396 30470,5399 30470,5401 30467,5401 30468,5404 30470,5400 30465,5401 30462,5403 30467,5404 30467,5409 30469,5412 30473,5412 30477,5407 30481,8407 30486,8408 30489,8410 30490,8410 30489,8413 30490,8414 30493,8414 30496,8419 30501,8420 30502,8415 30507,13415 30509,13411 30506,13414 30507,13412 30511,13412 30515,13417 30518,13419 30523,13418 30527,13422 30529,13418 30531,13413 35531,13409 35531,13413 35532,13417 35537,13419 35533,13423 35529,13424 35529,13423 35524,13428 35525,13433 35526,13438 35530,13443 35531,13448 35531,13452 35532,13455 35536,13457 35536,13452 35536,13455 35539,13452 35535,13457 35540,13457 35544,18457 35546,18460 35547,22460 35546,22465 35550,22466 35554,22468 35552,22473 35555,22471 35559,22470 35564,22472 35564,22470 35569,22474 35569,22474 35571,22477 35573,22482 35576,22487 35580,22488 35583,22489 35585,22493 35585,22496 35585,25496 35586,25493 35582,25494 35585,25498 35585,25496 35585,25498 35587,25503 35591,25503 35593,25499 35590,25499 35591,25495 35591,26495 35595,29495 35591,29495 35593,29498 35597,29498 35601,29500 35606,29501 30606,29502 30603,29505 30603,29510 30606,29511 30606,29514 30607,29516 30610,29518 30608,3259 17305,3263 17304,3267 17303,3271 17308,3269 17312,3269 17313,3274 17315,3277 17315,3282 17311,3285 17313,3283 17309,3278 17310,3275 17315,3275 17317,3276 17322,3280 17324,3280 17324,3276 17325,3277 17325,3276 17328,3278 17324,3273 17329,3277 17331,3280 17326,3281 17328,3276 17324,3277 17324,3277 17322,3277 17321,3277 17321,3281 17323,3282 17327,3282 17332,3287 17335,3288 17335,3288 17338,3290 17337,3294 17340,3294 17341,3299 17341,3299 12341,3299 12342,3304 12339,3301 14339,3305 14340,3307 14341,3311 14343,3313 14343,3314 16343,3310 16341,3310 16346,3312 16348,3311 16349,4311 16346,4316 16348,4321 16344,4324 16348,4322 16349,4323 16346,4323 16346,4326 16350,4322 16354,4323 16356,4325 16361,4325 16358,4322 16362,4325 20362,4325 20366,4322 20367,4326 20372,4326 20374,4331 20373,4333 20373,4338 20376,4339 20379,4341 20382,4338 20384,4339 20386,4340 20383,4340 20383,4335 20388,4336 20390,4341 20390,4346 20391,4348 20391,4349 20393,37497 26499,37494 26496,37496 26500,37496 26501,37499 26506,37497 26502,37498 26502,37500 29502,37500 29507,37505 29508,37506 33508,37508 33513,37513 33518,37517 33522,37516 33520,37521 33521,37521 33525,37516 33530,37519 33528,37520 33528,37524 33530,37527 33530,37525 33527,37528 33530,37533 33533,37534 38533,37536 38536,22358 13355,25358 13360,25361 13358,25362 13362,25362 13362,25365 13365,25363 13367,25359 13369,25357 13374,25360 13374,2247 13362,2252 13366,2254 13363,2257 13363,2261 13358,2264 13354,2264 13356,2269 13361,2272 13363,2274 13363,2275 13363,2273 13362,2274 13365,2278 13365,2280 13370,2284 13366,2284 13365,2289 13368,2290 13366,2293 13368,2298 13373,2298 13372,2295 13375,271 22347,273 22350,4273 22347,4269 22348,4270 22350,4271 22355,4272 22360,4276 22363,4281 22365,4284 24365,4279 24365,4282 24365,4285 24365,4287 24364,4289 24362,4294 24360,4295 24362,4298 24365,4301 24369,1301 24370,1301 24371,1305 24375,1305 24376,1307 24377,1312 24380,1314 24382,1318 24380,1316 24382,1316 24387,1318 24387,1318 29387,1321 29387,1316 29383,1320 29386,1321 29389,1326 29389,1327 29389,2327 29394,2327 29394,2332 29393,-666 24367,-663 24368,-661 24368,-656 24371,-653 24372,-649 24372,-647 24374,-643 24370,-638 24375,-635 24380,-638 24382,-638 24384,-638 24384,-636 24388,-637 24390,-632 24386,-630 24386,-629 24386,371 24389,376 24394,374 24392,377 24397,3377 24400,6377 24405,6378 24408,6373 24406,6370 24406,6375 24403,6370 24403,6375 24403,6379 24406,6374 24409,6378 24411,6380 24412,6378 24415,6378 24419,6383 24423,6385 24425,6387 24428,6390 24433,6386 24430,6386 24435,6387 24436,6388 24440,6387 24444,6383 29444,6383 29447,6386 29451,6382 29446,6387 29447,6390 29452,6393 29452,6397 29455,6400 29459,6400 29463,6397 29467,6393 29467,6395 29470,6397 29473,6399 29468,6394 29467,6397 29470,6396 29473,6396 29470,6393 29465,6389 29469,6390 29470,6389 29465,6389 29468,6392 29470,6388 33470,6390 33466,6391 33466,6392 33467,6394 33467,322 22372,322 22374,323 22377,327 22378,331 22382,330 22383,332 22386,333 22383,331 22383,330 22387,332 22391,332 22396,337 22397,339 22394,340 22399,340 22398,340 22396,343 22396,343 22396,341 22400,342 22404,343 22402,348 22403,345 22407,347 22411,342 22411,345 22413,340 22417,345 22417,348 22422,348 22426,351 22427,352 22432,352 22436,4352 22438,4353 22442,4354 22444,4354 22447,4357 22449,4360 22450,4364 22450,4367 22451,4369 22453,4366 22455,4369 22453,4373 22458,4377 22459,4380 22459,4380 22464,4385 22467,4385 22467,4390 22469,4385 22469,4385 22472,25571 26508,25574 26507,25578 26512,25581 26512,25581 26512,25583 26508,25583 26513,25587 26516,25589 26515,25590 26515,25591 26517,25589 26520,25587 26522,23587 26526,23585 26531,23589 26534,23592 26538,24592 26543,24588 26545,24593 26547,24598 26543,24598 26548,24602 26545,24598 26540,24600 26545,24600 26548,24600 31548,24605 31549,24608 31551,24613 31552,24615 36552,24616 36557,24619 36557,24622 36560,24622 36564,24627 35564,24627 35569,24632 35569,25632 35570,25635 35569,25636 35573,25636 35573,25638 35576,25641 35580,25641 35583,25641 35588,25642 40588,20642 40593,20645 40593,20650 40595,20651 40591,20651 40594,20648 40591,20648 40591,20652 40596,20652 40596,20656 40597,20656 40600,20656 40601,20659 40598,20662 40597,20662 40597,20663 40600,20668 40601,20665 40606,1215 13314,1214 13319,1212 13317,1209 13312,1210 13312,1211 13317,6211 13320,6214 13320,6216 13320,6211 13323,6214 13318,6214 13323,6214 13324,6216 13319,6219 13323,6218 13321,6219 13321,6218 13326,6221 13329,6225 13331,6230 13335,6231 13339,6231 13343,6235 13338,6234 13342,6234 13344,6236 13345,25524 26483,25521 26484,25524 26489,25527 26487,25529 26484,25530 26482,25534 27482,25539 27486,25537 27488,25541 27483,25544 27486,25547 27490,25550 27491,25550 27491,25554 27486,25559 27486,25563 27489,25561 27489,25563 27493,25561 27491,25563 27493,25563 27495,25564 27497,25563 27497,25563 27497,25558 27498,25563 27499,25565 27503,25567 27503,25569 27503,25567 27504,25565 27505,25565 27505,25565 27505,25566 27505,25570 27501,25570 27497,25574 27498,25570 32498,25570 32501,25573 32501,25576 32497,25576 32498,25577 32501,25579 32503,25583 32504,25588 32507,25592 32512,25596 32507,25599 32507,25594 32503,25597 32506,25597 32510,25594 32509,25594 32510,25596 32513,25592 32513,25594 32515,25594 32520,25598 32520,25602 32517,25603 32518,27603 32520,27607 32523,27608 31523,27613 31527,27615 31527,30615 31530,30617 31530,30618 31532,30619 31536,30623 31537,30623 31538,30625 31538,30626 31541,30627 31541,30624 31540,30623 31540,30624 31545,34624 31546,34619 31543,34623 31545,34624 31549,34624 31548,34626 31550,34626 31555,34626 31551,34628 31555,34633 31555,34636 31559,34634 31564,34636 31564,34639 31562,34639 31560,36639 31555,36636 27555,41636 27557,41640 27554,41644 27558,41647 27559,41648 27555,41653 27555,41658 27555,41658 27552,41658 27552,41660 27550,41656 27554,41661 27558,41664 27561,41667 27566,41662 27562,41663 27563,41663 27565,41662 27569,41661 27569,41664 27571,41664 27567,41659 30567,41660 30565,41660 30561,41665 30566,41664 30561,41664 30561,41664 30562,41664 30563,41660 30558,1312 24380,4312 25380,4315 25384,4315 25385,4319 25383,4322 25388,6322 25387,6322 25387,6326 25392,6321 25397,6324 25397,6324 25401,6319 25404,9319 25405,9314 25400,9312 25402,9310 25403,9313 25403,9313 25403,9316 25400,9319 25401,4319 25396,8319 25398,8315 25400,8315 25396,8315 25397,8311 25398,8307 25394,8309 25394,8311 25397,8315 25402,8310 25403,11310 25365,11311 25365,11316 25370,11320 25375,11325 25375,11325 25380,11325 25382,11326 25378,14326 25380,14328 25382,14331 25383,14334 25385,14336 25386,19336 25386,19336 25389,19332 25390,19332 25391,19335 25388,19338 25391,19342 25393,19340 25393,19345 25396,19345 25394,19347 25394,19349 25393,19351 25397,19350 25398,19348 25399,19349 25403,19352 25399,19350 25402,19354 25400,19353 25405,23353 25402,23354 25402,23356 25405,23358 25409,23360 25413,23363 25414,23367 25412,23365 25411,23367 25414,23363 25413,23367 25416,23367 25416,23370 25418,24370 25414,24370 25419,24373 27419,24378 27419,24380 27416,24380 27412,24380 27410,24380 27406,24376 27406,24374 27410,24370 27414,24370 27415,24371 27420,24375 27415,24378 27411,24375 27415,24378 27418,24382 27421,24383 27426,24383 27425,24385 27430,24390 27431,24394 27432,24395 27436,24399 30436,24400 30439,24404 30443,24403 30439,24406 30438,24410 30442,24406 30446,24408 30445,24403 30445,24408 30442,24412 30446,24416 30446,24416 30449,19416 30449,19416 30447,19418 30452,19420 30453,19423 30458,15423 30462,15423 30464,15425 30466,16425 30467,16424 30471,16421 30474,16426 30474,16428 30476,16428 30476,16424 30474,16424 33474,16425 33474,16427 33477,16425 33479,16426 33477,16422 33480,16425 33482,16430 33479,16430 33478,16429 33482,16424 33482,16427 33484,16430 33488,16431 33488,16434 33488,16435 33491,16432 33487,16436 37487,16434 37490,16438 37485,16443 37482,16446 37480,16447 37480,16447 37482,16451 37478,16454 37479,16458 37479,16454 37479,16454 37482,16459 37486,16460 37491,16463 37495,16464 37492,16465 37493,16466 37494,16468 37497,16468 37501,16468 37501,16473 37503,16473 37503,16473 37498,16476 37494,21476 33494,21473 33493,21476 33489,21478 33491,21478 33496,21478 33492,21480 33496,21483 33501,21484 33504,21483 33500,21484 33505,21484 33505,21488 35505,21491 35505,21494 35506,21496 35510,21492 35506,21492 35509,21489 35514,21490 35517,21487 35519,23487 35523,23485 35528,23487 35533,23483 35534,23487 35535,23488 35537,23493 35539,23495 35542,23495 35546,23495 35550,23491 35549,23488 35552,23492 35555,23495 35560,23500 35559,23496 35557,4322 16354,4317 16358,4318 16358,4320 16363,4315 16363,4315 16362,4316 20362,4320 20365,4323 20363,4326 20366,4329 20367,4332 20370,4337 20374,4338 20375,4333 20375,4338 20375,4341 20377,4342 20377,4342 20378,4343 20381,4346 20386,4346 20386,4346 20386,4346 20386,4349 20390,4352 20395,4354 20396,4355 20400,4358 20400,4360 20401,4360 20404,4363 20405,4368 20406,4372 20411,4371 20416,4367 20417,4364 20422,4367 20420,4372 20425,4373 20422,4374 20418,4377 20418,4381 20422,4382 20423,4384 20418,4389 20421,4385 20423,4390 20423,4390 20425,4392 20429,4396 20434,41574 39698,41578 39702,41576 39704,45576 39704,45575 39709,45577 39713,45581 39715,45581 39718,45583 39721,45578 39726,47578 39722,47581 39719,47586 39722,47586 39726,47589 39730,47592 39733,47597 39733,47593 39733,47596 39735,47597 39735,47595 39735,47591 39739,47593 39744,47593 39747,4074 20263,4077 20268,4079 20268,4078 20271,4078 22271,4083 22276,4087 22272,4088 22275,4086 22279,4082 22280,4084 22282,4086 22277,4082 22277,4087 22281,4090 22281,4092 22281,4092 22286,4094 22287,4097 22290,4097 22291,4095 22286,4095 22288,4095 22293,4095 22288,4092 22285,4089 22286,4090 22286,4095 22281,4100 22286,4103 22285,4104 22288,4104 22289,4107 22294,4112 22292,4117 22290,4120 22295,120 22300,121 22303,122 22300,122 22300,121 26300,125 26303,129 26303,127 26305,127 26306,132 26306,132 26307,136 26307,141 26309,140 26311,143 26313,140 26314,145 26318,149 26318,153 26321,153 29321,158 29326,158 29329,162 29324,162 34324,165 34329,168 34328,167 34332,169 34333,173 34334,173 34336,177 34338,178 34340,178 34344,182 34348,177 34348,182 34348,184 34353,184 34358,181 34360,183 34365,187 34365,192 34365,197 34367,199 34366,203 34368,205 34368,202 34363,204 34360,1204 34360,1205 34364,1205 30364,1205 30359,1206 30361,1207 30364,1210 30366,1210 30366,1214 30367,1218 30372,1219 30375,1214 30379,1214 30384,1217 30382,1222 30383,1223 30382,1225 30380,1228 30379,1231 30383,1232 30383,1235 30384,1237 30388,1242 30386,1244 30389,2244 30392,2241 30395,2245 30397,2245 30399,2244 30394,2242 30395,2246 32395,2246 32395,2249 32398,2251 32393,5251 32390,5251 32395,5255 32399,5255 32397,5257 32397,5257 32401,5261 32406,5261 32411,5266 32412,5271 32416,5273 32419,5276 32420,5281 32422,5279 32425,6279 33425,6284 33429,6284 33430,6282 33431,6282 33428,6286 33425,6288 32425,6288 32421,6286 32424,6288 32424,11288 32427,11292 32425,11292 32429,11290 32434,11286 32437,11286 32437,11283 32442,11278 32442,11279 32443,11283 32445,11284 32445,11283 32448,13283 32447,13287 32442,16287 32446,16282 32445,16283 32445,16284 32448,16285 32448,16284 32446,16286 32443,16290 32446,16291 32446,16292 32450,16291 32450,16291 32450,16291 32445,16287 32447,16288 32452,16287 32457,16291 36457,16289 36462,16293 36462,16294 36462,16297 36462,16301 36464,16306 36469,16310 36467,16310 36463,16313 36459,16312 36460,16313 36465,16313 36469,16308 36470,16309 36468,16314 36470,16319 41470,16322 41471,16325 44471,16330 44471,16330 44471,16330 44473,16330 44474,16335 44479,16332 44477,8414 30496,8415 30497,8419 30497,8414 30501,8416 30500,8418 30495,8421 35495,8423 35494,8427 35497,8429 35499,8432 35499,8436 35503,8438 35503,8443 35505,8440 35508,8443 35509,8440 35509,8440 35511,8441 35515,8445 35511,8448 35512,8443 35517,8443 35519,8442 35524,8444 35526,8441 35527,8436 35527,8433 35523,8429 35527,8430 35530,8431 35532,8429 35533,8433 35535,8437 32535,8435 32536,8439 32536,8436 32539,9436 32542,9434 32537,9429 32534,9429 32534,9433 32537,9433 32542,9429 32543,9434 32538,9436 32538,9436 34538,7436 34538,7438 34543,7439 34543,7439 34543,7439 34548,7438 34549,7438 34552,7438 34553,7438 34556,11438 34561,11434 34559,11436 34555,7436 34553,7436 34549,120 1235,124 1239,125 1236,125 1238,129 1235,128 1235,125 1236,123 1239,128 2239,132 2242,131 2242,135 2242,140 2242,145 2247,146 2252,144 2253,146 2248,144 2245,146 2244,150 2249,155 2245,159 2242,160 2243,160 2245,155 2244,156 2245,3156 2246,3159 2248,3159 2250,3164 2254,3165 2257,3166 2255,3169 2257,3171 2262,3169 2263,3174 2268,3177 2273,3174 2276,3178 2275,3173 2279,3177 2276,3180 2279,3182 2284,3185 2289,5185 2286,5185 2288,5181 2286,5185 2288,5184 2293,5187 2293,5187 2297,5190 2299,5187 2299,5185 2300,5181 6300,5182 6297,5187 6300,5189 6298,5191 6296,5193 6296,5193 6296,5195 6297,5195 6300,5197 6297,5195 6300,5190 6302,5191 6306,5192 6308,5195 6312,24395 27436,24391 27437,24393 27433,24398 27436,24398 27437,16286 32443,21286 32443,21286 32444,21282 32448,21283 32446,21283 32448,21285 32451,21281 32456,21282 32458,21282 32463,21282 32468,21284 32470,21289 32471,21287 32471,21287 32469,21287 32474,21284 32477,21288 32482,21291 32482,21291 32486,21296 32485,21299 32486,21301 32487,21303 32484,21301 32482,21305 32487,21310 32491,21312 32495,21313 32491,21315 32495,21312 32495,21314 32498,21316 32501,21311 32506,21311 32508,21312 32513,21317 32516,21319 32516,21324 32516,21327 32521,21328 32526,21332 32527,21328 36527,21331 41527,21336 41527,21334 41531,21337 41533,21335 41535,21339 41540,21340 41540,21343 41536,25343 41539,25340 41542,25337 41542,25337 41545,25335 41542,25335 41543,25335 46543,25339 46548,30339 46551,30340 46556,30343 46557,30342 46553,30337 46556,30341 46561,30337 46565,30336 46563,30338 46564,24373 27419,24373 27421,24375 27424,24377 27425,24377 27430,24374 27435,24379 27437,24384 27432,24385 27434,24382 27437,24381 27442,24381 31442,24381 33442,20381 33439,20383 34439,20382 34440,20378 34444,20381 34446,20381 34442,20384 34443,20388 34446,20392 34447,20393 34442,20393 34447,20396 29447,20395 29443,20399 29443,20400 29439,20399 29436,20404 29439,20409 29440,20410 29440,20410 29444,20408 29445,20413 29448,20413 29451,20412 29455,20413 29458,20418 29461,20413 29463,20415 29464,20416 29464,20416 29463,20416 29463,20418 29464,20414 29465,20418 29463,20413 29460,20413 26460,20418 26458,20421 26459,20421 26461,20421 26460,43578 35658,43578 35654,43578 35658,43578 35660,43583 35661,43583 35659,43583 35662,43579 35663,43583 35661,43587 35666,25625 25551,25629 25551,25630 25554,25630 25559,25632 25560,25627 25561,25623 25557,25623 25559,25624 25561,26624 25566,26627 25566,29627 25571,29626 25574,29625 25575,29622 25579,29625 25583,29630 25588,29632 25589,29635 25591,29635 25594,29637 25598,29642 25596,29643 25597,29644 25597,29649 25598,29654 25602,29656 25602,29661 25603,29661 25601,29664 26601,29666 26604,29665 26604,29668 26607,29672 26607,29669 26611,29671 26616,29674 26613,29679 26616,29680 26616,29681 26615,29682 26619,29679 26617,29684 26622,29686 26624,29689 26624,29690 26628,29691 26630,29693 26625,29694 26620,29698 26617,29703 29617,29707 29616,29706 29620,29709 29623,34709 29626,34710 29628,34710 29627,2282 16411,2283 16412,2283 16412,2287 16417,2292 16421,2297 16421,2298 16426,2303 16426,2304 16429,2309 11429,2313 11432,2308 14432,2308 14431,2311 14433,2310 14437,2308 14438,2309 14440,2311 14440,2309 14443,2312 14443,2314 14447,2314 14452,2314 14450,2309 14451,2309 14451,2309 14456,2313 14461,2313 14461,2309 19461,2309 19461,2311 19462,2315 19465,2318 19465,2321 19462,2317 19464,2321 19467,2322 19467,2322 19469,2322 19469,2320 19464,2321 19462,2322 19461,2327 19466,2327 19461,2322 19461,2322 19463,2317 19467,2318 19471,2102 -1848,2107 -1848,2111 -1846,2114 1154,2114 1156,2115 1157,2114 6157,2116 6162,2121 6165,2124 6170,2121 6175,2124 6179,2124 6183,2128 6178,2126 6179,2125 6178,2126 6181,2122 10181,2127 10186,2128 10189,2130 10188,2130 10191,2127 11191,2127 11195,2131 11196,2132 11192,2131 11197,2135 11201,2135 11203,2139 11199,2142 11203,2143 11204,2147 11208,2142 11210,2142 11211,2147 11212,2150 11217,2150 11219,2151 11219,2152 11222,2152 11222,2148 11224,2150 11220,2150 11223,2146 11218,2143 11219,2140 11221,2143 11218,2140 11219,2140 11223,2145 11225,2147 11226,2152 11226,2155 11224,2157 11229,2157 11229,2153 11233,2153 11238,2149 11239,7149 10239,7154 10241,7157 10241,7162 10243,7164 10248,7164 10251,7169 10253,7171 10253,7172 10257,7177 10260,7182 10256,7187 10260,7191 8260,7195 8256,7200 8258,7204 8258,7203 8261,7203 8262,7205 8266,7209 8270,7209 8273,7214 8273,7214 8276,7210 8276,7211 8276,7213 8279,7218 8278,7222 8283,7223 8279,7220 10279,7221 10283,7223 10284,7228 10286,7230 10290,7231 10290,7231 10293,7232 10294,7232 10297,7234 10299,7229 10295,7226 10294,7221 10293,7223 10295,7228 10299,7229 10303,7232 10307,7232 10311,7233 10316,7234 9316,7239 9318,7244 9321,7241 9326,7241 9328,7238 9331,7235 9330,7237 9335,7236 9335,7236 9337,7236 9338,7231 14338,7230 14333,7232 14338,7237 18338,4082 22280,4081 22280,6081 22283,6076 22285,6076 22289,6078 22286,6080 22287,6084 22292,6084 22293,6085 22293,6086 22291,6091 22294,6092 22293,9092 22290,9095 22294,9096 22295,9096 22297,9091 22292,9096 22295,9098 22290,9094 18290,9097 18290,9096 18294,9099 18292,9098 18297,9103 18299,9103 18302,9103 18305,9100 18301,9102 18302,9106 18305,9102 18310,9101 18306,9103 18308,9103 18312,9107 18310,9107 18315,9107 18320,9111 18322,9111 18326,9113 18329,9111 18329,9116 18329,9121 18329,9121 18332,9123 18331,9124 18332,9125 18328,9127 18325,9125 18328,9128 18329,9133 18329,9136 18333,9141 18337,9142 18342,9143 18340,9148 18344,9152 18341,9150 18346,9149 18341,9149 18341,9154 18343,9158 18345,9161 18346,9161 18347,9163 18352,9164 18352,9162 18349,9165 18352,9165 18351,9165 18352,9165 18356,9163 18352,9167 18353,9167 18349,9168 18351,9168 18347,9173 18347,9175 18347,9179 18348,9182 18349,9187 18352,9186 18357,9189 18360,9192 18360,9196 18362,13196 18367,13196 18369,13196 18371,13199 18374,13194 18374,13197 18375,13200 18377,13205 18380,13210 18384,13209 18379,13209 18374,13213 18375,13216 20375,13212 20375,13215 20375,13211 20375,13211 20372,13208 20373,13204 20373,13204 20369,13205 20369,13207 20366,13212 20367,13216 20367,13221 20372,13222 20377,13225 20381,13226 20386,13230 20383,9230 20388,9228 20384,9228 20386,9223 20389,9223 20392,4223 20397,4223 20396,4225 20399,4222 20404,4220 20408,4220 20411,4223 20416,4227 20421,4230 20418,4234 20421,4232 20422,4236 20423,4238 20423,4239 20423,4235 20427,4231 20427,4230 20426,4228 20428,4232 20427,4232 20431,4236 20433,4241 20431,4241 22431,4236 22436,4239 22437,4239 22439,4236 22443,4232 22439,4236 22444,4236 22446,4239 22447,4239 22452,4241 22454,4245 22457,4245 22460,4250 22462,4251 22465,4253 22465,4249 22465,4251 22460,4251 22464,4255 22469,4257 22473,4256 22478,4259 22479,4260 22480,4257 22485,6257 22489,6260 22490,6260 22493,6262 22496,6262 22500,6267 22495,6271 22495,6276 22491,6276 22489,6281 22487,6286 22490,6289 22490,6294 22490,6294 22489,6292 22485,6292 22489,6288 22489,6288 22494,6288 22496,6286 22497,6288 22501,6292 22500,5292 22503,5292 22503,5296 22508,5295 22510,5300 22510,5305 22513,5302 22514,5306 22510,5309 22513,5313 27513,5313 27513,5317 27513,5322 22513,5326 22517,6326 22516,6323 22518,6323 22523,6320 22523,6321 22526,6323 22531,6323 22531,6324 22532,6324 22532,6325 22529,6321 22531,6323 22534,6328 22534,6329 22530,6324 22527,10324 22522,10319 22524,10315 22520,10314 22525,10311 22525,10307 22526,10304 22531,10306 22527,10306 22528,10309 22530,10312 27530,10312 27534,10312 27534,10307 27536,10307 27532,11307 27531,11307 27533,11308 27535,11303 27531,11298 27532,11294 27534,11294 27534,11299 27538,11297 27542,11302 27547,11306 27547,11311 27549,11313 30549,11317 30551,11313 30546,11316 30541,11316 30540,11319 30545,11318 30546,11323 30550,11326 30554,11326 34554,11330 34558,11331 34558,11333 34558,11332 34561,11328 34561,11331 34562,11336 34562,11336 34567,11340 34570,11342 34569,11345 34568,11344 34569,11345 34571,11349 34574,15349 34574,15354 34569,15359 34566,15362 34571,15363 34576,15367 34577,15368 34577,15371 34581,15374 34576,15379 34574,15383 34579,15384 34584,15387 34583,17387 34578,17392 34578,17391 34578,17396 34573,17397 34578,17397 34580,17397 39580,17402 39584,17397 39587,17402 39587,17406 39582,17403 39587,17407 39589,17409 39592,17406 39592,17409 39595,17409 39599,17412 39603,17416 39608,17417 39608,17417 39608,17421 39607,17422 39609,17424 39608,17427 39604,17425 39605,17426 39609,17423 39611,17422 39610,17425 39613,17428 39618,17428 39619,17429 39616,17432 39616,13432 39615,13432 39617,13432 39617,13432 44617,13434 44621,13434 44623,13439 44627,13442 44632,13442 44635,13440 44631,13442 44631,13445 44635,13447 44639,13445 44637,13445 44638,13450 44639,13454 44644,13457 44644,13459 44642,15459 44639,15457 44644,15461 44644,15462 44642,15459 44645,15459 44647,15463 44650,15458 44651,15459 44653,15461 44657,15463 44661,15463 44661,15463 44663,15467 44666,15472 44668,15474 44664,15470 44668,15471 44670,15473 44674,15475 44675,-3806 12298,-3804 12301,-3805 13301,-3804 13296,-3808 13292,-3809 13295,-3806 13300,-3804 13297,-3801 13301,-3801 13302,-3796 18302,-3801 18306,-3799 18311,-3802 18311,-3799 18312,-3801 18314,-3796 18319,-3795 18322,-3791 18321,-3786 18320,-3786 18321,-3784 18321,-3782 18321,-3781 18324,-3782 18325,-3783 18320,-3788 18324,-1788 18324,-1788 18329,-1784 18333,-1784 18334,-1781 18329,-1777 18334,-6777 18337,-6774 18339,-6776 18341,-6781 18341,-6779 18341,-6779 18343,-6779 18339,-6777 18343,-6782 18338,-6779 18341,-6778 18341,-6776 18336,-6776 18333,-6776 18333,-6780 18338,-6784 18338,-6787 18335,-6786 18336,-6781 22336,-6781 22335,-6778 22331,-6777 22326,-6777 22331,-6777 22335,-6772 22335,-6774 22340,-6769 22341,-6767 22337,-6767 22335,-6767 22335,-6767 22333,-6767 22336,-6762 22331,-6759 22331,-6764 22332,-6765 22334,-6767 22339,-6762 22334,-6760 22334,-6760 22334,-6758 22337,-6754 22341,-6754 22342,-6750 22339,-4750 22343,-4747 22343,-4752 22343,-4751 22344,-4749 22345,-4745 22348,-4740 22353,-4736 22358,-4738 22363,-4740 22358,21336 41527,21334 41527,21330 41526,21330 41526,21333 41529,21328 41529,21329 41530,21326 41532,21328 41532,21324 41537,21328 41532,21330 41535,21334 41532,21336 40532,21334 40536,21339 40534,21341 40534,21344 40534,21346 40532,21350 40532,21353 40535,21357 40539,21359 40542,21360 40546,21355 40546,21360 40547,21359 40550,21356 40551,21356 40550,21357 40550,21361 40554,21358 45554,21362 45556,21366 45553,21370 45557,21374 45556,21377 45553,22377 45549,22382 45549,22382 45552,22386 45557,22387 45557,22388 45553,22392 45557,24392 45561,22392 45558,22397 45561,22399 45558,22398 45561,22400 45564,22400 45569,22404 45573,22406 45577,22406 45581,22404 45581,22407 45582,22409 45579,22409 45575,22409 45579,22407 45579,22402 45582,22402 45582,22404 45587,22406 45587,22406 45589,22411 45589,22413 45590,22417 45591,22417 45592,22422 45587,22425 45583,22428 50583,22428 50585,22428 50585,22430 50588,22435 50590,22435 50585,22435 50590,22439 50595,22440 50590,22445 50587,22442 50584,22442 50586,22443 54586,22443 54590,22446 54595,22448 54597,22448 59597,22444 59593,22449 59596,22449 59599,22452 59600,22457 59600,22458 59605,22457 59602,22462 59603,22463 59604,22461 59605,22458 59602,22457 59601,22457 59601,22455 59605,25455 59606,25457 59611,25462 59613,25464 59614,25467 59617,25472 59612,25476 59613,25478 59610,25482 59615,25482 59616,25486 59612,25483 59614,25487 59619,25492 59623,25497 59625,146 2252,150 2249,150 2249,152 2254,157 2249,158 2253,157 2252,161 2255,159 3255,161 3258,161 3255,163 3255,168 3259,168 3259,172 3263,167 3267,172 3271,172 3272,172 3274,175 3278,179 3282,181 3283,184 3280,185 3282,187 3282,191 3284,192 3286,191 6286,193 6289,198 6285,195 6290,194 6289,195 6289,199 6293,200 6288,198 6290,202 6291,207 6296,212 6301,215 6301,216 6301,211 6304,212 6304,216 6309,216 6304,214 6308,213 6308,211 6305,212 6309,217 6314,220 6317,224 6322,222 6327,220 6323,41573 39712,41572 39709,41576 40709,41580 40714,41576 40717,36576 40717,36577 40719,36582 40716,36585 40721,36590 43721,36585 43721,36582 43724,36585 43729,36590 43731,36590 43730,15289 11307,15285 11312,15286 11315,15289 11315,15294 11315,15295 11316,15296 13316,38742 37646,38743 37650,38745 37655,38744 37658,38739 37659,38737 37662,38742 37662,38745 37657,38748 37662,38748 37662,38752 37667,38753 37667,38748 37669,38748 37668,38752 37673,38754 37674,38756 37676,38758 37674,38760 37679,38760 37675,38758 37675,38763 37675,38767 37674,38772 40674,38767 40679,38772 40683,38774 44683,38778 44686,38780 44690,38780 44690,38779 44695,38782 44700,38780 44695,38775 44696,38775 44696,38775 44696,38779 44699,38783 44696,38784 44696,38786 44692,38786 44692,38786 44696,38791 44698,38793 44699,38795 44703,38800 44708,38803 44708,38807 44709,38802 44706,38806 44708,38809 44709,36809 44709,36814 44704,36813 44705,36814 44705,36816 44709,36811 44712,36812 48712,36811 48717,36815 48721,36816 51721,36818 51717,36822 51720,40822 51715,40827 51712,40830 51716,40829 51719,40832 51723,40835 51724,40840 51721,40841 51721,40836 51725,40841 51730,40846 51734,40848 51738,40849 51740,40851 51743,40854 51745,40855 51746,40857 51750,40857 51746,40861 51748,40866 51751,40862 51750,40866 51750,40869 51752,40865 51752,40863 51755,40858 51757,40855 51753,40855 51758,40852 51758,40853 51760,40857 51761,40855 51757,40852 51760,40853 51761,40855 51762,40858 51757,40859 51756,40863 51757,40863 51759,40860 51764,40859 51764,40854 51768,40850 51765,40852 51767,40852 51767,40848 51772,40852 51776,40854 51778,40852 51778,43852 51778,43854 52778,43856 52781,43859 52781,43859 52776,37512 26536,37517 26531,37520 26535,37520 26540,37522 26544,37527 26544,37532 26549,37537 26544,37540 26549,37545 26544,37549 26547,37549 26550,37548 26551,37549 26553,37546 26553,37546 26553,37549 26556,37549 26559,37552 26559,37556 26564,37560 26559,37561 26561,37565 26565,41565 26565,41569 26568,41571 26573,41571 26573,41576 29573,41571 29573,41573 29576,41573 29578,46573 29578,46569 29582,45569 29583,45572 29583,45568 29583,45573 29581,45575 29578,45571 29581,45572 29584,45572 29585,45576 29585,45578 29588,45581 29591,45582 29593,45582 29598,45584 29597,45589 29600,45585 29605,45589 33605,45593 36605,45594 36607,45599 36609,45600 36604,45604 36604,45604 36608,45604 36607,45608 36610,50608 36613,50611 36609,50614 36609,50619 36605,50624 36605,50625 36606,50625 36605,50629 36606,50624 36608,50625 36610,50626 36610,50629 36608,50627 36610,50628 36614,50632 36618,46632 34618,46632 35618,46636 35622,46636 35617,46637 35620,46639 35619,46643 35620,46645 35625,46643 35630,46648 35635,46648 35640,46649 35643,46651 35647,46655 35650,46652 35655,46657 35656,46658 35657,46662 35660,46659 35663,46662 35664,46665 35663,46667 35667,46667 35663,46670 35666,46672 35671,46674 35671,47674 35668,47676 35672,47677 35673,47677 35678,47677 35677,47677 35677,47677 35682,47672 35683,47671 35683,49671 35685,49674 35689,49677 35692,49675 35692,54675 35697,54678 35699,54674 35699,54670 35701,54670 35700,54675 35703,54676 34703,54676 34703,54679 34706,54683 34708,54688 34706,54688 34707,54685 34702,54687 34702,54692 34707,54687 36707,54687 36706,54682 36707,54685 38707,54680 38710,54680 38714,54677 38714,54679 38719,54682 38720,54687 38716,54688 38717,54692 38722,54697 38726,54699 38727,54700 38724,54702 38720,52702 38719,52702 38719,52702 38721,52702 38725,52704 38726,52706 38728,52707 38729,52711 38728,52711 35728,52713 35733,52712 35737,52712 35739,52713 35742,52713 35745,52708 35745,52710 39745,52713 39749,52716 39748,52721 39749,52720 39753,52716 39756,52716 40756,47716 40757,47717 40761,47722 40761,47722 40761,47722 40766,47726 40769,47728 40772,47733 40777,47731 40773,50731 40777,51731 40779,51733 40782,51734 40786,51737 40784,51741 41784,51739 41783,51739 41785,51739 41785,51736 41789,51731 41789,52731 41790,52735 41791,52738 41790,52742 41789,52746 41785,52747 41785,52745 41785,52750 41782,52753 41786,52753 41787,52758 41792,52754 42792,52749 42793,52752 42794,52756 42791,52757 42790,52762 42793,52766 42797,52766 42797,52769 42802,52774 42806,52774 42805,52771 42807,52774 42807,52770 42808,52771 42811,52767 42811,52766 42812,52767 42817,52771 42817,52771 42817,52775 42815,52779 42811,52779 42812,52780 42815,52776 42818,52774 42818,52777 42822,52780 42823,52781 42827,52776 42829,52780 42832,54780 42835,54780 42840,2135 11201,2140 11203,2137 11204,2140 11209,2142 11213,2147 11211,2145 11213,2145 11213,2150 11218,2150 11221,2153 11225,2157 13225,2162 13228,2167 13231,2171 13232,2167 13229,2168 13233,2171 13237,2173 13239,2168 13234,2168 13235,2173 13235,2175 13234,2177 13235,2177 13234,2179 13229,2179 13226,2180 13226,2177 13226,2177 13231,2180 13231,2181 10231,2176 10233,2177 10232,2180 10235,2185 10237,2182 10240,6182 10240,6184 10244,6182 10242,6183 10243,6185 10246,6190 10244,6194 10244,6194 10247,6192 10247,6192 10252,6195 10256,6194 10260,6195 9260,6195 9260,6195 9264,6199 9269,6204 9272,6199 9268,6201 9268,6203 9265,6208 9268,6204 9270,6204 9275,6201 9279,6201 9281,6201 9286,6206 9281,6206 9277,6202 9281,6200 9285,6202 9288,6198 9290,7198 9293,7200 9297,7201 9297,7205 9298,7209 9298,7209 9299,8209 9302,8214 10302,8218 10306,8222 10308,8226 10313,8231 10313,8235 10318,8237 10318,8237 10323,8233 10326,8233 10327,8237 10325,8238 10328,8238 10330,8234 10330,11234 10332,11236 10333,11241 10337,14241 10338,14240 10338,14237 10339,14238 10337,14237 10339,14242 10339,14246 10339,14250 10339,14250 10339,14251 10337,14254 10337,14256 10334,14256 10332,14252 10336,14255 10340,14259 10342,14262 10347,11148 3159,11153 3163,11154 3162,11154 3165,11158 3167,11161 3172,11162 3175,11162 3176,11166 3179,11166 3181,11171 3185,11176 3180,11178 3179,11176 3181,11179 3183,11174 3182,52776 42818,52778 42822,52777 42822,52782 42817,52783 42822,52784 42823,52789 42826,52789 42823,56789 42828,56786 42829,56786 42832,56789 42836,56789 42835,56785 42838,56786 42843,51786 42844,51788 42846,51790 42847,51794 42842,51796 42842,51801 42846,53801 42849,53806 42849,53809 42852,53812 42850,53817 42846,53817 42848,53818 42853,53822 42856,53823 42854,53826 42858,53825 42860,53826 42860,53826 42864,53830 42868,53835 42873,53839 42873,53841 42872,53841 42876,53841 42879,53841 42884,53836 42888,53836 42889,53836 44889,53833 44889,53835 44893,53838 44897,53842 44897,53844 44900,53844 44904,53845 44905,53850 44903,53853 44904,53858 44906,53856 44907,53861 44909,53856 44913,53858 44916,53863 44916,53868 44918,53867 43918,53869 43921,53869 43919,53867 43919,53862 43918,53860 43923,53864 43928,53869 43930,53874 43933,53874 43932,53874 43932,53875 43930,53877 43928,53878 43924,53883 43927,55883 43929,55883 43925,55879 43929,55881 43929,55884 43928,55881 43928,55882 43929,55883 45929,55883 45933,55883 45936,55884 45941,55884 45941,55886 45946,55882 45948,55883 45952,55888 45956,55890 45957,55894 45953,55892 45954,55897 45950,55893 45954,55896 45956,55892 45955,55897 45959,55899 45961,55899 45961,55894 45962,55898 45957,55893 49957,55896 47957,55894 47956,55898 47960,55901 47964,55901 47967,55901 47970,55896 47973,55898 47969,55894 47974,55895 47975,55891 47976,55896 47979,55899 47984,55902 47983,55897 47987,55899 47989,55904 47992,55904 47993,55905 47997,55902 48001,55902 48003,55907 48000,55910 47998,55915 47999,55911 47994,55906 47998,55910 48003,55914 48000,55918 48000,55914 48000,55919 48000,55921 48003,55921 48007,55924 48007,55919 48010,55922 48005,55927 48009,55928 48008,55928 48008,55930 48012,55925 48012,55925 48016,54925 48014,54922 48018,54922 44018,54926 44013,54929 44012,54932 44016,55932 44017,55935 44017,55936 44020,55937 44022,55936 44020,55939 44015,55944 44018,55945 44022,55947 44023,55950 44024,55953 44020,55956 44023,53867 43919,53871 43921,52871 43921,53871 43923,53876 43923,53881 43923,53880 43927,53882 43931,53886 43936,53884 43937,53879 43934,53879 43937,53877 43939,53878 43938,53879 43942,53880 43947,53881 43948,53884 45948,53884 45949,53882 45953,53883 45954,53878 45956,53880 45953,53885 45958,53885 45958,53886 45957,53886 48957,53886 48962,53891 48962,53892 48964,53897 48965,49897 48962,49902 48965,49906 48967,49902 48967,49904 48971,49901 48967,49904 48970,54904 48971,54904 48971,54904 48975,54909 48979,54907 48975,54910 48975,54906 48971,54909 48973,54911 48975,54915 48978,54920 48978,54923 48981,54918 48984,54921 48984,56921 48984,56926 48986,56924 48981,56929 48980,56932 48979,56932 48977,56936 48979,56937 48981,56937 48982,61937 48984,61937 48980,61934 51980,61935 51981,61935 51984,61935 51984,61931 51986,5329 23395,5331 23395,5333 23390,5337 23392,5340 23395,5345 27395,5345 27397,5350 27398,5355 27399,5356 27402,6356 27405,6360 27407,6361 27406,6364 27402,6366 26402,6371 26402,6371 26402,6372 26405,6370 26405,6375 26406,6380 26411,6385 26413,6387 26414,6388 26419,6390 26419,6391 26424,6393 30424,6390 30429,6390 30432,6390 30430,6394 30434,6394 30437,6394 30441,6396 30442,6398 30439,6399 30436,6404 30435,6405 30435,6400 30435,6405 30440,6404 30443,6405 30447,6409 30447,6411 30447,6412 30448,6417 30446,6421 30450,6418 30448,6417 30444,6418 30449,6420 30451,6425 30456,6426 30456,6425 30458,6426 30458,6426 34458,6427 34459,6432 39459,6434 39462,6434 39467,6439 39470,6443 39467,6444 39468,6449 39473,6451 39476,6452 39481,6452 39479,6452 39476,8452 39476,8456 39478,8460 39480,10460 39482,10455 39482,10456 39484,10460 39484,10463 39484,10468 39486,10473 39482,10475 39484,10475 39486,10476 39488,10477 39492,10475 39494,10480 39499,10476 39501,10479 39506,10480 39510,10475 39508,10480 39513,10481 39516,10481 39516,10485 39521,10487 39522,10490 39523,10490 39520,10493 39520,10496 44520,10491 44519,10491 44524,10492 44520,10497 44525,10499 44525,10502 44527,10500 44531,10502 44535,10506 44535,10511 44532,13511 44536,13513 44533,13510 44535,13507 44540,13511 44543,13515 44548,13517 44549,13522 44550,13525 42550,13520 42551,13522 42553,13525 42552,13529 42557,13529 42558,13524 42559,13525 42559,13525 42562,13520 42564,13523 42567,15523 42569,15523 42572,15524 42577,15529 42577,15530 42582,15532 42584,15532 42588,15531 42587,15531 42592,15530 42587,15530 42583,15533 42583,15536 47583,15532 47583,15535 47587,15534 47590,15536 47594,11536 47590,11533 47590,11529 47590,11533 47592,11533 47592,11533 47593,11537 47598,11538 47603,11538 47603,11538 47605,11541 47609,11544 47613,14544 47614,14539 47610,14537 47610,14537 47614,14535 50614,14537 50619,14539 50619,14540 50623,14538 50623,14537 50619,25599 26540,25599 26541,25599 26544,25594 26542,25599 26543,25596 26544,25597 26543,25598 26543,25593 26544,25588 26542,25593 26545,25595 26544,25596 26544,25599 26541,25594 26544,25592 26549,25593 26548,25597 26549,25596 26550,25594 26551,25590 26550,25594 26554,25597 26550,25598 26552,25593 26555,25598 22555,25599 22557,25604 22559,25605 22558,25606 22562,25605 22559,25605 22564,30605 22569,30610 22571,30610 22575,30609 22575,30609 22576,30609 22581,30605 22581,30610 22583,30610 22584,30613 22579,30613 22581,30616 22577,30619 22577,30621 22580,30621 22585,30626 22590,30628 22593,30629 22598,30626 22603,30628 22606,30629 22607,30629 22604,30627 22606,30632 22608,30633 22608,30636 22612,30641 17612,30642 17614,30647 17614,30651 17615,30654 17610,30655 17607,30658 17611,30653 17610,30654 17606,30654 17607,30659 17606,30660 17611,30658 17616,30659 17616,30664 17619,30665 17621,30665 17620,30667 17621,30671 17624,30673 17624,30673 17624,30678 17627,30675 17632,30675 17635,30678 17640,30681 17643,30686 17639,30691 17641,30696 19641,30699 19640,30700 19640,30696 19645,30698 19643,30699 19645,30702 19646,30703 19649,30699 19651,30704 19648,30706 19652,30709 19653,30709 19655,30709 19655,30712 19657,30708 19658,30705 19660,30700 19662,30701 19663,30706 19664,30711 19663,30707 19667,30704 19670,30708 19672,30709 19673,30711 19673,30711 19674,30713 19678,30718 19682,30723 20682,30721 20686,30725 20691,30726 20693,30729 20695,30728 20690,30730 20692,30733 20694,30736 20692,30736 20691,30740 20694,30741 20695,30741 20697,30746 20700,30747 20702,30750 20701,30751 20698,30753 24698,30749 24701,30748 24703,30746 24704,30747 29704,30747 29705,30749 29707,30752 29712,30757 29712,30760 34712,30760 34716,30763 34716,30759 34713,30759 34717,30763 34717,30758 34717,30757 34721,30760 34726,30758 34726,30763 34727,30763 34727,30764 34727,30759 34729,30759 34732,30762 34734,30757 34735,30761 34736,30759 34736,30762 34738,30757 34733,30760 34735,30762 34737,30760 34736,30765 34733,32765 34737,32768 34737,32765 34740,32765 34742,32768 34747,32772 34751,32772 34752,32777 34749,32782 34751,32783 33751,32783 33746,36783 33749,36783 33754,36786 33756,36787 33755,36787 33758,36791 33754,36796 33754,36801 33756,36801 33758,36801 33762,36802 33765,36802 33765,36806 33770,33806 33772,33806 33777,33809 33777,33814 33780,33814 33785,33818 33782,33821 33784,33826 33781,33822 33781,33824 33783,33822 33784,33826 33787,33823 33792,33827 33795,33828 33798,33829 33799,33833 33801,33833 33801,33836 33805,33839 33809,33842 33805,33847 33810,33845 32810,33847 32808,33849 32812,33851 32815,33849 32818,33849 32822,33847 32822,33847 32826,33850 32831,33854 32836,33857 32833,33856 32828,33859 32829,33860 32832,33857 32834,33857 32830,33855 32830,33857 32830,33855 32834,33859 32829,33859 32833,33862 32836,33864 32837,33864 32839,33866 32837,33869 32835,33872 32840,33874 37840,33879 37845,33881 37850,33881 37855,33886 37856,33891 37860,33896 37860,33893 37863,33894 38863,33896 38859,28896 38864,28899 39864,33899 39869,33896 39871,33898 39875,33902 39873,33902 39875,33907 39879,33912 39884,33908 39887,33908 39888,33905 39890,33909 39895,33911 39896,33908 39900,33912 39901,33915 39902,33915 39902,33915 39902,33910 39907,33910 39904,33914 39903,33912 39906,33916 39909,33920 39909,33922 39912,33923 39916,33928 39916,33931 39918,33932 39919,33935 39915,33936 39912,33934 39909,35934 39914,35931 39915,35935 39917,35939 39920,35939 39915,35940 39911,35944 39916,35944 39911,35944 39908,35945 39904,35945 39908,35945 39912,35950 39915,35955 39917,38955 39916,38960 39921,38962 39920,38962 39920,38967 39922,38967 39924,38970 39928,38975 39928,38973 39928,38977 39931,38980 39934,38984 39936,38982 39939,38983 39942,38985 39943,38987 39945,38992 41945,38988 41950,38989 41954,38992 41958,38992 41962,38992 41965,38993 41970,38997 41970,38997 41970,38994 41974,38994 41979,38997 41979,38999 41982,38994 41980,38998 41985,38998 41984,5334 23406,5330 23406,5325 23403,9325 23404,12325 23408,12325 23408,12322 23406,13322 23411,13325 23416,13326 23412,13322 23414,13327 23419,13328 23422,13329 23425,13333 23422,13337 23424,23491 35549,23490 35544,23494 35546,23499 35548,23495 35549,21495 35553,21490 35556,21492 35558,21492 35556,21494 35559,21494 35564,21494 35566,21499 35566,21502 35562,21502 35567,17502 35568,17506 35573,17507 35574,17511 35578,17512 35583,17513 35588,18513 35591,18514 35592,18515 35594,18513 35596,16513 35601,16513 37601,16513 37602,16511 37604,16513 37609,16514 37611,16518 37616,16522 34616,16524 34613,16528 34615,16528 34620,16533 34624,16535 34627,16538 34628,16539 34630,16539 34631,16542 34628,16542 34633,16544 34638,16547 38638,16547 38640,16543 38645,16543 38640,16540 38640,16543 38640,16542 38641,16546 38646,16541 38649,16541 38645,18541 38648,18544 38648,18544 38653,18544 38656,18549 38651,18547 38651,18550 38656,18547 38658,23547 38663,23544 38664,23548 38668,23548 38670,28548 38672,28549 38669,28549 38673,28545 38669,28549 38670,28554 38670,28557 38674,28560 38669,28562 38674,28562 38669,28561 38669,28564 38671,28569 38671,38779 44699,38780 44695,38778 44698,38783 44700,38785 44700,38781 44701,38782 44696,38786 44691,38789 44692,38794 44692,38799 44688,38799 44693,38803 44697,38808 44697,38806 44697,38806 44700,38803 44702,38803 44706,38802 44707,38807 48707,38808 48707,38806 48707,38810 48712,38810 48709,38810 48711,38810 48711,38806 48707,38802 48710,38803 48706,38805 48711,38810 48711,38805 48709,38809 48710,38809 48710,38814 48707,38815 48703,38816 48703,38816 48704,38820 48704,38822 48709,38820 48710,38818 48714,38822 48716,38822 48719,38827 48722,38828 48727,38832 48725,38830 48730,38831 48726,38832 48724,38829 48728,8431 35532,8431 35537,4431 35532,4434 35537,4438 35537,4439 35533,4443 35535,4442 35530,4445 35527,4449 35527,4453 35530,4458 35530,4459 39530,4460 39531,4461 39531,4464 39531,4468 39531,4470 39534,4465 39534,4465 39532,4469 39532,4471 39537,4466 39538,4470 39539,4473 39540,4476 39540,4480 39543,4485 39548,4483 39546,4484 39547,4484 39549,4484 39551,4486 39553,4486 39554,4487 39551,4483 39553,4486 39554,4490 39556,4493 39557,4498 39561,4494 39562,-4749 22345,-4752 22345,-4748 22348,-4744 22351,-4740 22356,-4741 22358,-4739 22361,-4734 22359,-4730 25359,-4730 25360,-4725 25360,-4727 25360,-4727 25361,-6727 25360,-6729 25365,-6730 25365,-6727 25365,-6731 25364,-6730 27364,-6727 27366,-6723 27367,-3723 27363,-3719 27368,-3720 27371,-3718 27366,-3717 27369,-3716 27369,-3714 27372,-3711 27370,-3712 27371,-3712 27370,-3710 27375,-3708 27377,-3707 27382,-3706 27385,-3706 27389,-3705 32389,-3704 32392,-3704 32392,-3699 32391,-3699 32395,-3694 32399,-3694 32400,-3695 32404,-3695 32408,-3693 32410,-3693 32410,-3697 32410,-3692 32413,-3691 32418,-3686 32420,-3683 32425,-3681 32420,-3678 32424,-3673 32424,-3676 32427,-3673 32426,-3671 32426,-3676 33426,-3678 33428,-3676 33428,-3679 33428,-3679 33433,-3677 33434,-3676 33438,-3681 33440,1319 33444,1321 33441,1325 33444,1329 33439,1326 33444,1326 33439,1327 33439,1327 33440,1332 33444,1333 33449,1338 33453,1338 33450,1343 33450,1347 33454,1346 33457,1346 33455,1342 33459,1341 33462,1346 33462,1347 33463,1343 33463,1344 33462,1348 33457,1347 33460,1352 33464,1356 33468,1361 33469,1363 33468,1365 33469,1368 33472,1369 33475,-2631 33478,-2633 33483,-2629 33486,-2632 34486,-2628 36486,-2625 36488,-2621 36488,-2624 36488,-2622 36492,-2624 36491,-2629 36491,-2627 36496,-2623 36499,-2628 36502,-2631 36506,-2626 36506,-2622 36506,-2622 36509,-2619 36514,-2624 36512,-2621 36510,-2619 36510,-2619 36508,-2617 36512,-2615 36512,-2615 36513,-2615 36511,-2615 36506,-2612 36507,-2609 36511,-2606 37511,-2606 37508,-2610 37505,-2607 37508,-2602 37512,-2599 37512,-2595 37510,-2597 37511,-2592 37515,-2597 37514,-2592 37519,-2592 37524,-2592 37526,-2594 37521,-2594 37516,-2591 36516,-2588 36517,-2589 36513,-2586 36514,-2584 36514,-2583 36516,-2579 36514,-2578 36518,-2578 35518,-2575 35519,-2577 35519,-2578 35524,-2578 35529,-2578 35532,-2578 35534,-2580 35537,-2584 35541,-2586 35542,-2587 35544,-2585 35540,-2585 35544,-2584 35543,-2580 35548,-2576 35550,-2571 35553,-2567 35555,-2565 35560,-2560 35560,-2557 35564,-2553 35564,-5553 36564,-5548 36564,-5544 36565,-5547 36565,-5545 36570,-5542 36565,-5543 36566,-5543 36568,-5543 36570,-5540 36575,-5537 36577,-5535 36581,-5532 36580,-5528 36575,-5526 38575,-5526 38576,-5526 38571,-5522 38571,-5518 38576,-5514 42576,-5510 42581,-5512 42583,-5512 42582,-5507 42582,-5510 42585,-2510 42589,-2511 42592,-2508 42594,-2506 42597,-2503 42598,-2503 42603,-2498 42608,-2501 42611,-2500 42616,-2502 42613,-2502 42616,-4502 42616,-4502 42620,-4502 42622,-4506 42619,-4509 42621,-4511 42624,-4515 42625,-4510 42625,-4507 42628,-4502 42624,-4501 42629,-4505 45629,-4503 45630,-4499 45631,-4496 45630,-4497 45628,-4495 45630,-4494 46630,-4491 46634,-4487 46629,-4483 46631,21336 40532,21341 40533,21346 40534,21346 40536,21345 40536,21346 40536,21345 40536,21344 40538,21347 40543,21348 40543,21351 40540,21351 40542,21348 40545,21351 40546,21352 40546,21353 40546,21358 40546,21359 40545,21359 40550,21357 40555,21362 40560,21364 40555,21363 40555,21364 40560,25364 40564,25365 40566,25368 40566,25371 45566,25372 45567,25372 45562,25376 45564,25381 42564,25385 42560,25389 42564,25389 42568,25393 42572,25390 42572,28390 42569,28389 42570,28385 42574,28386 42576,28389 42577,31389 42578,31385 42582,31387 42582,31390 42578,31391 42579,31392 42576,29392 42580,29396 42582,29398 43582,29402 43584,29406 43585,29407 43587,29411 43592,29413 43594,29414 43595,25414 43600,25412 43595,25415 43599,25420 43602,25418 43604,25423 43599,25426 43599,25429 43602,25434 42602,25429 42604,25432 42600,25435 42605,25436 47605,25440 50605,25441 50610,25439 50614,25444 50617,25447 50621,25444 50624,25444 50626,25445 50627,25450 50632,25450 50628,25451 50630,25451 50632,25454 50633,25458 50637,25462 50641,25463 50640,25463 51640,25467 51644,25469 51649,25473 51650,25474 51653,25475 51654,26475 51658,26475 51662,26474 51665,26476 51665,26481 51661,26483 55661,26485 55664,30485 55667,30485 55670,30489 55671,30489 55668,30491 55670,30492 55670,30493 55675,30497 55675,30501 55671,30503 55676,30500 55677,30498 55672,30494 55675,30499 55676,30500 55676,30505 55681,30501 55684,30496 55685,30500 55685,30502 55687,30506 55692,30507 55693,30506 55692,30511 55693,30516 55694,30514 55699,30514 55701,30512 55701,34512 55705,34516 55708,34520 55704,34518 56704,34519 56704,34520 56706,34517 56706,34515 56701,34519 59701,34522 59706,34522 59708,34522 59713,34526 59715,34528 59717,34533 59712,34538 59715,34538 59717,34541 59717,34546 59720,34548 59721,34552 63721,34547 63726,34549 63728,34554 63726,34556 63726,34557 63721,34556 63725,34561 63730,34558 63730,37558 63725,37561 63729,37565 63724,37569 63720,37573 63718,37578 63722,37577 63718,37579 63720,37579 63722,37580 63719,37580 63720,37579 63724,37574 63725,37574 63727,37576 63725,37581 63729,37583 63732,37586 63732,37590 63737,37592 63734,37597 63731,37600 63730,37596 63731,37596 63733,37600 63733,37601 63735,37596 63735,37591 63732,37596 63733,37601 63738,37602 63733,37599 63738,37594 63740,37598 63744,37603 63745,37605 63747,37607 63752,37607 63756,37603 63757,37603 63761,37604 63761,37608 63758,37609 63762,37604 63764,37604 63764,41604 63765,41600 63761,41599 63761,41600 63766,41596 63766,41599 63766,41601 63770,41604 63768,41608 63768,41611 63772,41614 63767,41609 63763,41612 63765,41615 63760,38615 63764,38615 63768,38618 63768,35618 63769,35618 63774,35617 63775,35618 63776,35613 63775,35615 63780,35612 63782,35613 63779,35614 63775,35618 63774,35619 63776,35624 63778,35624 63780,35629 63785,35629 63780,35626 63781,35624 63782,35629 63784,35634 63787,35638 63782,35634 63783,35634 63778,35633 63777,35638 63782,35641 63786,35644 63791,35648 63793,35647 63793,35649 63797,35653 63801,35654 63804,35654 63804,35656 63804,35655 63806,35658 63810,35658 63805,35662 63805,35657 67805,35658 67808,35660 67811,35664 67808,35660 67803,35658 67803,35661 67803,35663 67808,35666 67810,35670 67814,35669 67813,35669 67816,37669 67820,37664 67820,2275 13363,2278 16363,2274 16363,2275 16362,2279 16362,2282 16362,2287 16366,2284 16366,4284 16366,4286 16371,4290 16375,4294 18375,4295 18377,9295 18381,9296 18381,9299 18382,9303 18379,9305 19379,9308 19375,8308 19380,8312 19380,38746 37651,38749 37652,38754 37653,38757 37656,38753 37661,38753 37661,38758 37663,38763 37664,38763 42664,38768 42666,38765 42668,38770 42664,38767 42659,38768 42659,38773 42654,38771 42659,38775 42661,41775 42663,41778 42665,41781 42669,41782 42667,41779 42669,41784 42672,41781 42672,41783 42672,41780 42672,41783 42675,41784 42675,41788 42676,41792 42677,41792 42675,41793 42680,41793 42676,41796 42681,41801 42685,41804 42684,41806 42685,41804 42690,41802 42692,41805 42696,41800 42697,41802 42698,41804 42700,41809 42704,41813 42705,36813 42708,36813 42704,36810 42703,36811 42705,40811 42706,40815 46706,40816 46708,40820 46708,40818 46712,40822 46717,40825 46720,40829 46724,40827 46727,40831 46727,40833 46731,40829 46733,40830 46733,36830 46738,36830 46741,36834 46744,36831 46749,36826 46748,36822 46748,36824 46751,36819 46755,36823 46758,36823 46762,36824 46766,36822 46769,36826 46772,36831 46774,36828 42774,36833 42776,36833 42777,36838 42782)'))); @@ -42,13 +42,13 @@ SPATIAL KEY (g3), SPATIAL KEY (g4), SPATIAL KEY (g5), SPATIAL KEY (g6) -) ENGINE=InnoDB; +) ENGINE=InnoDB STATS_PERSISTENT=0; DROP TABLE t1,t2; CREATE TABLE t1 ( p INT NOT NULL AUTO_INCREMENT, g LINESTRING NOT NULL, PRIMARY KEY(p) -) ENGINE=InnoDB; +) ENGINE=InnoDB STATS_PERSISTENT=0; ALTER TABLE t1 ADD SPATIAL INDEX spatial_idx (g); INSERT INTO t1(g) VALUES(ST_linefromtext('linestring(-5 -576,0 -576,0 -571,0 -571,5 -568,6 -564,6 -565,6 -563)')); INSERT INTO t1(g) VALUES(ST_linefromtext(concat('linestring','(18 106,19 106,24 111,27 108,32 104,37 107,42 107,44 112,44 116,40 118,43 114,46 114,42 118,44 123,45 123,49 123,53 119,50 123,50 124,54 126,58 125,59 126,64 127,65 127,69 131,74 132,75 135,78 139,2078 141,2075 143,2077 143,2079 143,2084 143,2085 147,2090 -1853,2086 -1852,2086 -1856,2089 -1852,2093 -1850,2090 -1851,2090 -1852,2091 -1851,2092 -1850,2097 -1847,2102 -1848,2100 -1852,2100 -1852,7100 -1851,7103 -1850,7104 -1847,7109 -1842,65 127,67 131,66 131,61 132,61 133,62 137,65 1137,2065 1135,2061 1135,2064 1135,5064 1135,5066 1135,5070 1136,5070 1141,5071 1138,5074 1141,5075 1141,5074 1137,5076 1137,5071 1139,5066 1142,5065 2142,5068 2147,5073 2151,5069 2156,5071 2157,5072 2162,5074 2165,5069 2169,5072 2169,5076 2173,5074 2169,5078 2169,5076 2170,76 2175,74 2179,75 2184,80 2188,83 2190,87 2189,84 2193,87 2189,86 2190,87 2195,87 2200,87 1200,85 1202,86 1199,87 1200,87 1201,91 1206,92 1204,94 1204,98 1206,102 1208,105 1211,102 1216,105 1220,109 1224,110 1224,114 1225,117 1224,118 1229,117 1232,122 1237,123 1236,120 1235,124 1237,121 1236,122 1240,126 1244,127 1246,126 1249,125 5249,123 5251,127 5251,131 5251,135 5256,138 5257,135 5257,139 5257,138 5258,141 5260,146 5260,146 5260,143 10260,147 10265,151 10270,156 10266,157 10269,162 10273,166 12273,168 12274,163 12270,168 12275,170 12277,170 12277,-3830 12277,-3825 12277,-3824 12278,-3825 12276,-3825 12278,-3822 12277,-3825 12275,-3829 12278,-3828 12275,-3824 12280,-3827 12280,-3826 12282,-3822 12283,-3822 12286,-3820 12288,-3818 12289,-3816 12294,-3817 12297,-3819 12300,-3816 12297,-3813 12295,-3811 12299,-3811 12297,-3806 12298,-3806 12298,-3804 12301,-3801 12306,-3803 17306,-3803 17306,-3798 17306,-3803 17310,-3801 17314,-3798 17317,-3797 17317,-797 17321,-797 17323,-796 17325,-793 17326,-792 17322,-789 17327,-784 17331,-780 17335,-776 17339,-774 17339,-771 17342,-770 17345,-765 17348,-765 17349,-763 17353,-760 17350,-760 22350,-756 22346,-752 22349,-748 22352,-752 22348,-748 22347,-746 22345,-745 27345,-743 27346,257 27350,260 27349,261 27352,266 27348,266 22348,269 22347,271 22347,272 22347,273 22348,273 22352,278 22348,279 22344,282 22345,282 22342,283 22347,283 22347,288 22349,292 22347,292 22348,293 22348,298 22348,303 22351,306 22352,309 22352,308 22354,310 22356,311 22361,311 22358,311 22360,311 22360,315 22356,320 22358,325 22363,326 22366,321 22371,318 22373,318 22375,314 22375,316 22375,321 22376,321 22376,322 22372,32 104,36 109,40 114,40 113,40 117,44 119,49 123,49 126,49 129,53 133,50 137,50 139,49 137,48 138,43 138,42 139,46 142,46 138,41 139,45 141,4045 5141,4045 5146,4042 5147,4043 10147,4041 10150,4042 10152,4045 10152,4041 10156,4041 10152,4041 10152,4046 10153,4049 10156,4046 10155,4051 10157,4055 10159,4055 10160,4056 10161,4055 10166,4054 10169,4054 10172,4054 15172,4051 15176,4047 15177,4049 15174,4047 15176,4047 15176,4046 15177,4046 15180,4043 15184,4043 15187,4038 15190,4040 15194,4040 15199,4045 15196,4047 15197,4050 15200,4050 15204,4050 15208,4047 15212,4047 15215,4049 15216,4046 15218,4042 15223,4042 15228,4042 15232,4047 15235,4050 15236,4050 15239,4051 15243,4053 15243,4050 17243,4052 17243,4052 18243,4057 18247,4061 18249,4064 18249,4067 20249,4067 20250,4067 20255,4066 20259,4066 20259,4067 20255,4069 20256,4071 20258,4072 20254,4067 20257,4067 20260,4069 20265,4065 20267,4069 20266,4070 20267,4071 20264,4074 20259,4070 20264,4073 20260,4074 20263,4077 20268,4082 20271,4084 20273,4084 20277,4081 18277,4085 18279,4086 18276,4087 18273,4087 18275,4092 18277,4093 18279,4093 18280,4095 18280,4091 18283,4092 18281,4094 18283,4090 18287,4094 18287,138 5257,138 5255,138 5258,-1862 5254,-1860 5256,-1856 5258,-1851 5255,-1850 5260,-1847 5260,-1847 5263,-1847 5258,-1850 5257,-1850 5259,-1851 5257,-1855 5258,-1853 5261,-1849 5261,-1849 5258,-1849 5259,-1845 5264,-1847 5264,-1850 5268,-1852 5266,-1853 5270,-1856 5265,-1852 5262,-1847 5263,-1842 5263,-1842 5260,-1842 5265,-1841 5265,-1844 5265,-1842 5270,-1837 5274,-1838 5279,-1843 5275,-1842 5280,-1838 5281,-1838 5285,-1833 5285,-1828 5288,-1824 5289,-1828 5291,-1831 5291,-1826 5291,-1830 5293,-1826 5296,-1822 5301,-1826 5302,-1826 5302,-1826 5302,-1825 5297,-1820 5299,-1816 5303,-1816 5299,-3811 12299,-3809 12302,-3806 12302,-3806 12302,-3803 12304,-3798 12304,-3797 12304,-3793 12306,-3788 12306,-3783 12309,-3816 12294,-3811 12299,-3809 12297,7100 -1851,7098 -1854,7102 -1854,7107 -1856,7107 -1858,7110 -1854,7110 -1851,7113 -1851,7115 -1851,7120 -1851,7123 -1847,7124 -1852,7125 -1852,7127 -1852,7131 -1852,7129 1148,7129 1145,7133 1150,7137 1148,7138 1147,7143 1149,7147 1154,8147 1155,8152 3155,8147 3157,8143 3158,8144 3160,8144 3164,11144 3167,11146 3167,11148 3163,11152 3161,11148 3159,11149 3163,11150 3161,11151 3166,11154 3171,11154 3170,8144 3160,8144 3163,8144 3166,8145 3166,8146 3171,8146 3174,8144 3174,8144 3174,8145 3176,8141 3180,3141 3182,7141 3183,7141 7183,7136 7185,7136 7185,7133 7187,7136 7187,7131 7190,7136 7194,7137 7197,7141 7196,7139 7199,12139 7200,12143 7200,12143 7199,12144 7203,12145 7200,12141 7200,12136 7195,12136 7191,12137 7191,12137 7196,12139 7197,12140 7197,12137 7201,12140 7204,12140 7209,12143 7209,12145 7210,12147 7214,12148 9214,12152 9218,12149 9218,12149 9221,12149 9220,12150 9222,12153 10222,12153 10226,12156 10227,12159 10223,12160 10220,12161 10225,12161 10227,12163 10224,12163 10223,12158 10224,12158 10227,12158 10231,12155 12231,12157 12226,7136 7185,7139 7189,7139 7189,7139 7188,7137 7191,7139 7191,7140 7189,7143 7191,7144 7189,7144 7190,7149 7193,7152 7194,7154 7198,7153 7203,7148 7207,12148 7209,12146 7209,12145 7213,12140 7217,12139 7219,12141 7219,12138 7218,12143 7218,13143 7220,13140 7224,13142 7228,13137 7231,13142 7235,13146 7239,13149 7243,13148 7247,13150 7248,13155 7249,13155 7253,13155 7253,13155 7258,13157 7260,13162 7255,13159 7255,13163 7258,13164 7258,13164 7263,13167 7264,13167 8264,13165 8265,13169 8265,13171 13265,13175 13261,13176 13259,13176 13259,13180 13262,13181 13262,13183 13262,13188 13265,13191 13267,13191 13265,13194 13267,13191 13269,13192 13264,13196 13269,13198 13272,13200 13272,13202 13270,13207 11270,13211 11270,13211 11273,13213 11274,13217 11275,13222 11276,13222 11272,13226 11274,13231 11277,13233 11282,13236 11284,13238 11284,13236 11286,13236 11288,13236 11283,13236 11284,13238 11289,13241 11292,13244 11292,13245 11289,13241 11294,13244 11298,13249 11301,320 22358,324 24358,328 24358,327 24363,326 24359,327 24361,329 24365,334 24367,-666 24367,-670 24368,49 123,46 127,46 129,49 131,49 136,47 135,45 138,3045 135,3042 138,3044 139,3044 144,3049 144,3053 142,3055 137,3058 136,3053 139,3048 142,7048 138,7048 3138,7048 3139,7048 3140,7050 3145,7053 1145,7050 1146,7053 5146,7048 5150,7047 5146,10047 5147,10043 5147,10047 5147,10050 5152,10052 5155,10054 5156,10056 5157,10056 5159,10058 5162,10062 5164,10062 5169,10066 9169,10068 9168,10063 9164,10063 9169,10061 9171,14061 9172,14061 9174,282 22342,287 22347,288 22347,288 22343,285 22339,280 22338,278 22341,279 25341,284 25343,13241 11294,13246 11296,13243 11296,13244 11291,13245 11291,13244 11291,13246 11295,13251 11300,13253 11305,13253 11306,13258 11305,13255 11306,13256 11309,13256 11311,13261 11307,13265 11303,13267 11305,13270 11301,13275 11298,13271 11300,15271 11302,15276 11306,15279 11303,15284 11305,15286 11305,15289 11307,15290 11302,15292 11305,15296 11309,15297 11313,15298 11316,15300 11317,15304 11320,15306 11324,15306 11320,15307 11320,15312 11320,15313 11319,15317 11317,15315 11321,15317 11323,15317 11328,15319 11333,15322 11336,15322 11337,15322 11337,15324 11341,15324 11345,15325 14345,15328 13345,17328 13346,17333 13349,17337 13354,17338 13358,17342 13358,17346 13353,17348 13353,17345 13353,17348 13354,17347 13354,17347 13354,17347 13355,22347 13358,22349 13355,22351 13355,22356 13354,22358 13354,22361 13355,22362 13355,22358 13355,22359 13359,22364 13364,22369 13369,22372 13373,22376 13371,22377 13371,22377 13369,22381 13374,22386 13379,22387 13376,22387 13380,22392 13378,22390 13374,22392 13378,22391 13378,22391 13375,22392 13378,22390 13380,22393 13382,22398 13387,22398 10387,22402 10391,22399 10392,22400 10392,22400 10394,22404 10391,22403 15391,22405 15392,22407 15392,22412 15387,22412 15390,22412 15394,22408 15396,26408 15398,26407 20398,26411 20402,26415 20406,26417 20411,26420 20407,26422 20407,31422 16407,31421 16405,31421 16410,31423 16410,31426 16414,31426 16410,31430 16415,31430 16418,31435 16419,31437 16420,31438 16422,31438 16425,31438 16425,31441 16427,31439 16431,31441 16436,36441 16436,36443 18436,36442 18437,36440 18440,36440 18436,36440 18440,36442 18445,36443 18446,36447 18451,37447 23451,37452 23456,37456 23455,37458 23459,37456 23461,37458 23463,37460 23466,37464 23469,37460 23474,37462 23476,37461 26476,37466 26479,37470 26483,37471 26488,37474 26489,37474 26485,37474 26483,37474 26488,37470 26492,37474 26497,37474 26499,37478 26495,37483 26499,37483 26501,37488 26496,37491 26499,37495 26495,37500 26496,37500 26497,37500 26501,37497 26499,37497 26499,37495 26504,37498 26504,37494 26509,37497 26514,37495 26515,37498 26514,37503 26514,37508 26512,37510 26516,37511 26519,37509 26523,37506 26528,37507 26532,37512 26536,37513 26538,37510 26542,37512 26544,37517 26543,37522 26546,37527 26551,37525 26555,37529 26558,37524 26563,37524 26562,37527 26562,37522 26562,37522 26559,37526 26561,37522 26559,37523 26561,37523 26556,37524 26558,40524 26560,40524 26563,40521 26567,40525 26566,40527 26568,40532 26572,40534 26569,40533 26565,40531 26565,40535 26569,40535 26570,40539 26572,40544 26575,40543 26575,40544 26579,40548 26584,40549 26581,40553 26585,40556 26590,40552 22590,40557 22594,40556 22595,40561 22592,40561 22593,40565 22593,40568 22593,40573 22588,40570 22590,40570 22591,40570 22588,40573 22590,40573 22593,40568 22593,40567 22597,40567 22599,40571 22599,40574 22600,40574 22604,42574 22607,42577 22607,42577 22612,42579 22616,38579 22619,38580 22617,38580 22614,38575 22619,38579 22619,38579 18619,38582 18614,38582 18617,38586 18622,38590 18625,38590 18622,38594 18621,38596 18616,38597 18614,38597 18618,38600 21618,38601 21618,38605 21620,38607 25620,38611 25620,38608 25617,38608 25621,38608 25625,38611 25623,38615 25623,38615 25620,38616 25622,38619 25624,38620 25625,38620 26625,38623 26627,38623 26627,311 22358,311 22359,-1689 22360,2311 27360,2312 27360,2312 27360,2317 27362,2317 27362,2319 27359,2319 27364,2318 27359,2321 27364,2326 27367,2325 27371,2326 27373,2326 27373,2325 27377,2329 27377,2327 27377,2330 27379,2333 27379,2331 27379,2331 27381,2336 27381,6336 27382,6336 27383,40527 26568,40531 26572,40533 26574,40538 26576,40533 26580,40538 26585,40539 26588,40536 26583,40540 26587,40539 26588,40535 26593,40540 26594,40544 26597,40548 26602,40548 26601,40549 26602,40547 26602,40548 26603,40553 26606,40548 26606,40548 26603,40551 26608,40556 26612,40559 26616,40554 26619,40556 26619,40556 26623,42556 26623,42556 26624,42560 26624,42562 26626,42563 26630,42564 26630,42564 26634,42559 26635,42562 26635,42565 26637,42562 26638,42564 26642,42564 26641,42568 26641,42572 26641,42572 29641,42574 29642,39574 29641,39574 34641,39576 34643,39581 34638,39578 34638,39574 34642,39574 34645,39572 35645,34572 35648,34577 35651,39577 35655,43577 35659,43580 35655,43575 35658,43578 35658,43581 35662,43577 39662,43572 39658,43572 39661,43572 39664,43572 39666,43576 39670,43577 39667,43580 39671,43576 39673,43573 39673,43574 39677,43569 39679,43567 39679,43568 39683,43563 39686,43566 39690,43566 39692,43568 39694,43568 39695,41568 39691,41570 39692,41571 39692,41571 39693,41571 39698,41571 39698,41574 39698,41569 39698,41570 39699,41570 39704,41572 39709,41573 39712,41578 39713,41579 39717,41584 39719,41585 39720,-1850 5268,-1845 5268,-1847 5266,-1842 5268,-1840 5263,-1845 5264,-1843 5264,-1839 8264,-1839 8267,-1839 8272,-1838 8276,-1834 8273,-1834 8273,-1833 8274,-1837 8279,-1836 8283,-1834 8286,-1836 8282,-1834 8279,-1835 8279,-1834 8280,-1836 8283,-1841 8288,-1846 8289,-1843 8286,-1838 8286,-1841 8285,-1838 8285,-1834 8288,-1829 8291,-1825 8286,-1825 8289,-1825 8287,-1824 8291,-1822 8294,-1821 8298,-1818 8300,-1818 8296,-1814 8296,-1811 8295,-1808 8292,1192 8296,1192 8297,1195 11297,1192 11301,1195 11305,1197 11300,1193 11300,1193 11296,1193 11293,1194 11294,1199 11292,1204 11292,1205 11294,1210 11292,1208 11288,1204 11290,1205 11289,1207 8289,1202 8284,1204 8282,1204 8281,1206 8281,1208 8281,1212 8283,1212 13283,1213 13287,1213 13290,1216 13293,1214 13289,1217 13286,1212 13291,1208 13288,1208 13292,1209 13297,1208 13296,1204 13298,1205 13303,1209 13308,1204 13308,1209 13304,1210 13304,1214 13309,1214 13314,1215 13314,1219 13314,1219 13319,1224 13320,1229 13321,1232 13325,1233 13329,1231 13329,1234 13334,-2766 13336,-2769 13337,-2765 13340,-2762 13345,-2760 13342,2240 13342,2238 13342,2242 13342,2246 13345,2246 13346,2244 13348,2239 13348,2240 13351,2240 13352,2245 13357,2248 13357,2243 13362,2247 13362,2248 13362,2252 13363,2256 13363,2256 13363,2260 13367,2255 13372,2251 13369,2251 13369,2252 13372,2249 13376,2254 13378,2255 13382,2259 13379,2262 13379,2267 13381,2262 13381,2262 13383,2265 13383,2269 13385,2270 13386,2271 13389,2267 13391,2271 13386,2275 13391,2273 13392,2275 13387,2277 13390,2274 13390,2275 13394,2280 13395,2280 11395,2281 14395,2279 14400,2277 14403,2273 14406,2274 16406,2274 16410,2279 16410,2284 16411,2280 16409,2280 16409,2282 16409,2282 16411,2282 16412,2280 16413,3280 16418,3284 16418,3285 16423,3289 16423,3292 16427,3294 16429,3296 16431,3297 16436,3298 16435,3303 16435,3305 16434,3305 16436,3305 16436,3309 16437,3309 16438,3308 16439,3308 16439,3306 16444,3302 16441,-1698 16437,-1703 16438,-1699 16438,-1697 16438,-1698 16439,-1695 16436,-1690 16441,-1687 16446,-1683 16450,-1682 16451,-1684 16453,-1682 16457,-1682 16457,-1686 16460,-1681 16459,-1680 16456,-1677 16460,-1681 16461,-1679 16464,-1674 16465,-1673 16469,-1669 16471,-1669 16476,-1665 16474,-1665 16478,-1664 16478,-1664 16479,-1661 16474,-1656 16471,-1655 11471,-1660 11473,-1663 11475,-1666 11480,3334 15480,3338 15476,3342 15471,3345 15471,3345 15470,3350 15469,3347 15474,3351 15476,3352 15473,3353 15476,3350 15477,3350 15479,3351 15482,3352 15484,3351 15487,3353 15487,3358 15487,3353 15486,1217 13286,1222 13291,1222 13291,1225 13286,1229 13286,1231 13281,1235 13280,1236 13281,1241 13282,1245 13285,1247 13285,1247 13287,1250 13287,1247 13290,1247 13295,1247 13298,1252 13301,1249 13304,1252 13304,3252 13304,3247 13304,3249 13308,3254 13308,3257 13308,3261 17308,3261 17309,3261 17306,3259 17305,3262 17310,3263 17308,3262 17311,3259 17314,3259 17314,3257 17309,3254 17309,3253 17309,3255 17310,3253 17312,3255 17312,3255 17312,3256 17307,3257 17307,3256 17311,3256 17313,3255 17317,3251 17317,3248 17321,3253 17325,3256 17326,3258 17324,3258 17327,3263 17322,7263 17325,7265 17328,7263 17330,7265 17333,7270 17333,7273 17333,7278 17336,4278 21336,4278 21340,4279 21340,4281 21340,4286 24340,4290 24343,9290 24347,9294 24349,9296 24347,9298 25347,9301 25348,9301 25348,9304 25353,9303 25357,9303 25352,11303 25355,11304 25358,11307 25358,11312 25358,11312 25361,11310 25365,11313 25365,11314 25369,11319 25371,11321 25371,11325 25366,11329 25365,11330 25366,11329 25370,11330 25365,11334 25367,11338 25366,11343 25363,11348 25359,11345 25356,11348 25357,11349 25358,11349 25358,11352 25360,11356 30360,11360 30365,11360 30365,11362 30365,11367 30367,11368 30369,15368 30370,15373 30371,15376 30373,14376 30378,14377 30383,14381 30378,14386 30380,14388 30382,14391 30385,14393 31385,16393 31389,16396 31394,16396 31397,16392 31400,16395 31405,16398 31409,16398 31413,16397 31415,16396 31417,16401 31418,16401 31422,16402 31419,16407 31420,16411 31419,16406 31423,18406 31427,18411 31432,18415 28432,18417 28437,18418 28441,18414 28438,18417 28435,18416 28439,18420 28442,18423 28447,18427 28444,21427 28445,21428 28450,22428 28455,22432 28457,22436 28458,22441 28458,22445 28463,22448 28468,22451 28465,22456 28468,22453 28468,22458 28471,22463 28473,22460 28475,22459 28472,22463 28476,22464 28472,22468 28468,22468 28471,25468 28466,25471 28468,25473 28464,25473 28464,25475 29464,25476 29466,25479 29461,25476 29462,25476 29464,25478 29464,25483 29461,25484 29460,25486 29458,25486 29462,25490 29460,25495 26460,25498 26463,25495 26468,25495 26472,25495 26472,25499 26474,25504 26476,25504 26478,25509 26476,25513 26479,25514 26481,25519 26477,25519 26480,25518 26481,25519 26484,25524 26483,25527 26484,25522 26484,25526 26487,25528 26492,25533 26496,25535 26498,25535 26498,25539 26503,25542 26504,25543 26505,25547 26510,25552 26510,25551 26508,25550 26512,25553 26510,25557 26510,25554 26511,25552 26508,25556 26505,25556 26506,25560 26506,25560 26507,25560 26506,25565 26501,25567 26504,25569 26504,25568 26508,25571 26508,25571 26511,25576 26511,25581 26516,25581 26519,25582 26521,25585 26522,25588 26527,25588 26526,25584 26530,25587 26534,25589 26529,25593 26533,25598 26538,25599 26540,25599 26540,25599 26540,25604 26543,25603 26543,25603 26538,25606 26538,25609 26540,25611 26542,25612 26547,25612 26547,25612 26548,25617 25548,25612 25548,25613 25547,25616 25545,25616 25549,25618 25551,25620 25555,25620 25551,25622 25550,25625 25551,25622 25555,25619 25557,25617 25556,25622 28556,25625 28551,25630 28546,25634 28548,25639 28553,25643 28553,25638 25553,25634 25553,25634 25557,25639 25557,25643 25558,25644 25553,25646 25556,25647 25560,25650 25562,25650 30562,25650 30562,25650 30564,25650 30566,25652 30570,25656 30571,25661 31571,25662 31575,25663 31579,25662 31579,25665 31581,25666 31584,25671 31582,25674 31581,25674 31584,25676 31584,25673 31587,25678 31586,25679 31581,30679 31584,30675 31589,30680 31590,35680 31590,35675 31589,35677 31591,35680 31590,35681 31587,35684 31588,35685 31589,35689 31592,35689 31593,35692 31597,35696 31597,35700 34597,35699 34599,35703 34604,35703 34606,35702 34601,35705 34603,35705 34606,35708 34603,35713 34604,35717 34603,35719 34608,35715 34608,35711 34608,35713 34609,35714 34605,35714 34610,35714 34614,35718 34616,35719 34617,35722 34618,35722 34621,35725 34625,35725 34626,35725 34629,35725 34631,35725 34635,35730 34636,35727 34638,35731 34640,35735 34642,35739 34645,35741 34645,35742 34649,35738 34649,35738 34645,35741 34647,38741 34650,38741 37650,38742 37646,38746 37651,38749 37652,38753 37653,38753 37657,38757 37656,38756 37660,38761 37660,38765 37660,38760 37660,38759 37660,38760 41660,38760 41660,38762 41665,38757 41667,43757 41669,43752 41674,43752 41677,43757 41672,43758 41677,45758 41680,45758 41679,45762 41683,45765 41683,45769 41683,45770 41684,45768 46684,45773 46688,45776 46692,45774 46694,45775 46697,45778 46695,45776 46698,45774 46702,45779 46702,45784 46704,45787 46706,45791 46711,45786 46707,45790 46711,45793 46715,45796 46719,45799 46724,45797 46728,45802 46726,45797 46729,45801 46733,45802 46733,45803 46732,45804 46732,45805 46732,45808 46735,45810 46740,45810 46744,2326 27373,2322 27377,2323 27379,2325 27383,2325 27382,2322 27382,2323 27382,5323 23382,5325 23385,5329 23386,5330 23390,5335 23392,5330 23392,5330 23395,5329 23395,5333 23399,5333 23402,5338 23405,5339 23405,5334 23406,5329 23401,5332 23403,5330 23407,5333 23409,5328 20409,5324 20411,5324 20414,5329 20416,5328 20421,5325 20421,5329 20424,5330 20424,5335 21424,5331 21427,5333 21431,5334 21433,5329 21434,5330 21437,5333 21440,5338 21437,5338 21440,5334 21441,5333 21438,5329 26438,5332 26435,5335 26439,5337 26440,5338 26444,5342 26439,5342 26442,5345 26440,5349 26438,5352 26442,5349 26445,5348 30445,5350 30447,5350 30444,5354 30444,5359 30443,5363 30445,5367 30446,5367 30448,5367 30453,5371 30455,5371 30453,5373 30458,5375 30461,5380 30463,5384 30463,5383 30459,5384 30459,5383 30459,5385 30460,5390 30459,5392 30464,5394 30464,5389 30465,5393 30469,5391 30469,5391 30469,5395 30474,5396 30470,5399 30470,5401 30467,5401 30468,5404 30470,5400 30465,5401 30462,5403 30467,5404 30467,5409 30469,5412 30473,5412 30477,5407 30481,8407 30486,8408 30489,8410 30490,8410 30489,8413 30490,8414 30493,8414 30496,8419 30501,8420 30502,8415 30507,13415 30509,13411 30506,13414 30507,13412 30511,13412 30515,13417 30518,13419 30523,13418 30527,13422 30529,13418 30531,13413 35531,13409 35531,13413 35532,13417 35537,13419 35533,13423 35529,13424 35529,13423 35524,13428 35525,13433 35526,13438 35530,13443 35531,13448 35531,13452 35532,13455 35536,13457 35536,13452 35536,13455 35539,13452 35535,13457 35540,13457 35544,18457 35546,18460 35547,22460 35546,22465 35550,22466 35554,22468 35552,22473 35555,22471 35559,22470 35564,22472 35564,22470 35569,22474 35569,22474 35571,22477 35573,22482 35576,22487 35580,22488 35583,22489 35585,22493 35585,22496 35585,25496 35586,25493 35582,25494 35585,25498 35585,25496 35585,25498 35587,25503 35591,25503 35593,25499 35590,25499 35591,25495 35591,26495 35595,29495 35591,29495 35593,29498 35597,29498 35601,29500 35606,29501 30606,29502 30603,29505 30603,29510 30606,29511 30606,29514 30607,29516 30610,29518 30608,3259 17305,3263 17304,3267 17303,3271 17308,3269 17312,3269 17313,3274 17315,3277 17315,3282 17311,3285 17313,3283 17309,3278 17310,3275 17315,3275 17317,3276 17322,3280 17324,3280 17324,3276 17325,3277 17325,3276 17328,3278 17324,3273 17329,3277 17331,3280 17326,3281 17328,3276 17324,3277 17324,3277 17322,3277 17321,3277 17321,3281 17323,3282 17327,3282 17332,3287 17335,3288 17335,3288 17338,3290 17337,3294 17340,3294 17341,3299 17341,3299 12341,3299 12342,3304 12339,3301 14339,3305 14340,3307 14341,3311 14343,3313 14343,3314 16343,3310 16341,3310 16346,3312 16348,3311 16349,4311 16346,4316 16348,4321 16344,4324 16348,4322 16349,4323 16346,4323 16346,4326 16350,4322 16354,4323 16356,4325 16361,4325 16358,4322 16362,4325 20362,4325 20366,4322 20367,4326 20372,4326 20374,4331 20373,4333 20373,4338 20376,4339 20379,4341 20382,4338 20384,4339 20386,4340 20383,4340 20383,4335 20388,4336 20390,4341 20390,4346 20391,4348 20391,4349 20393,37497 26499,37494 26496,37496 26500,37496 26501,37499 26506,37497 26502,37498 26502,37500 29502,37500 29507,37505 29508,37506 33508,37508 33513,37513 33518,37517 33522,37516 33520,37521 33521,37521 33525,37516 33530,37519 33528,37520 33528,37524 33530,37527 33530,37525 33527,37528 33530,37533 33533,37534 38533,37536 38536,22358 13355,25358 13360,25361 13358,25362 13362,25362 13362,25365 13365,25363 13367,25359 13369,25357 13374,25360 13374,2247 13362,2252 13366,2254 13363,2257 13363,2261 13358,2264 13354,2264 13356,2269 13361,2272 13363,2274 13363,2275 13363,2273 13362,2274 13365,2278 13365,2280 13370,2284 13366,2284 13365,2289 13368,2290 13366,2293 13368,2298 13373,2298 13372,2295 13375,271 22347,273 22350,4273 22347,4269 22348,4270 22350,4271 22355,4272 22360,4276 22363,4281 22365,4284 24365,4279 24365,4282 24365,4285 24365,4287 24364,4289 24362,4294 24360,4295 24362,4298 24365,4301 24369,1301 24370,1301 24371,1305 24375,1305 24376,1307 24377,1312 24380,1314 24382,1318 24380,1316 24382,1316 24387,1318 24387,1318 29387,1321 29387,1316 29383,1320 29386,1321 29389,1326 29389,1327 29389,2327 29394,2327 29394,2332 29393,-666 24367,-663 24368,-661 24368,-656 24371,-653 24372,-649 24372,-647 24374,-643 24370,-638 24375,-635 24380,-638 24382,-638 24384,-638 24384,-636 24388,-637 24390,-632 24386,-630 24386,-629 24386,371 24389,376 24394,374 24392,377 24397,3377 24400,6377 24405,6378 24408,6373 24406,6370 24406,6375 24403,6370 24403,6375 24403,6379 24406,6374 24409,6378 24411,6380 24412,6378 24415,6378 24419,6383 24423,6385 24425,6387 24428,6390 24433,6386 24430,6386 24435,6387 24436,6388 24440,6387 24444,6383 29444,6383 29447,6386 29451,6382 29446,6387 29447,6390 29452,6393 29452,6397 29455,6400 29459,6400 29463,6397 29467,6393 29467,6395 29470,6397 29473,6399 29468,6394 29467,6397 29470,6396 29473,6396 29470,6393 29465,6389 29469,6390 29470,6389 29465,6389 29468,6392 29470,6388 33470,6390 33466,6391 33466,6392 33467,6394 33467,322 22372,322 22374,323 22377,327 22378,331 22382,330 22383,332 22386,333 22383,331 22383,330 22387,332 22391,332 22396,337 22397,339 22394,340 22399,340 22398,340 22396,343 22396,343 22396,341 22400,342 22404,343 22402,348 22403,345 22407,347 22411,342 22411,345 22413,340 22417,345 22417,348 22422,348 22426,351 22427,352 22432,352 22436,4352 22438,4353 22442,4354 22444,4354 22447,4357 22449,4360 22450,4364 22450,4367 22451,4369 22453,4366 22455,4369 22453,4373 22458,4377 22459,4380 22459,4380 22464,4385 22467,4385 22467,4390 22469,4385 22469,4385 22472,25571 26508,25574 26507,25578 26512,25581 26512,25581 26512,25583 26508,25583 26513,25587 26516,25589 26515,25590 26515,25591 26517,25589 26520,25587 26522,23587 26526,23585 26531,23589 26534,23592 26538,24592 26543,24588 26545,24593 26547,24598 26543,24598 26548,24602 26545,24598 26540,24600 26545,24600 26548,24600 31548,24605 31549,24608 31551,24613 31552,24615 36552,24616 36557,24619 36557,24622 36560,24622 36564,24627 35564,24627 35569,24632 35569,25632 35570,25635 35569,25636 35573,25636 35573,25638 35576,25641 35580,25641 35583,25641 35588,25642 40588,20642 40593,20645 40593,20650 40595,20651 40591,20651 40594,20648 40591,20648 40591,20652 40596,20652 40596,20656 40597,20656 40600,20656 40601,20659 40598,20662 40597,20662 40597,20663 40600,20668 40601,20665 40606,1215 13314,1214 13319,1212 13317,1209 13312,1210 13312,1211 13317,6211 13320,6214 13320,6216 13320,6211 13323,6214 13318,6214 13323,6214 13324,6216 13319,6219 13323,6218 13321,6219 13321,6218 13326,6221 13329,6225 13331,6230 13335,6231 13339,6231 13343,6235 13338,6234 13342,6234 13344,6236 13345,25524 26483,25521 26484,25524 26489,25527 26487,25529 26484,25530 26482,25534 27482,25539 27486,25537 27488,25541 27483,25544 27486,25547 27490,25550 27491,25550 27491,25554 27486,25559 27486,25563 27489,25561 27489,25563 27493,25561 27491,25563 27493,25563 27495,25564 27497,25563 27497,25563 27497,25558 27498,25563 27499,25565 27503,25567 27503,25569 27503,25567 27504,25565 27505,25565 27505,25565 27505,25566 27505,25570 27501,25570 27497,25574 27498,25570 32498,25570 32501,25573 32501,25576 32497,25576 32498,25577 32501,25579 32503,25583 32504,25588 32507,25592 32512,25596 32507,25599 32507,25594 32503,25597 32506,25597 32510,25594 32509,25594 32510,25596 32513,25592 32513,25594 32515,25594 32520,25598 32520,25602 32517,25603 32518,27603 32520,27607 32523,27608 31523,27613 31527,27615 31527,30615 31530,30617 31530,30618 31532,30619 31536,30623 31537,30623 31538,30625 31538,30626 31541,30627 31541,30624 31540,30623 31540,30624 31545,34624 31546,34619 31543,34623 31545,34624 31549,34624 31548,34626 31550,34626 31555,34626 31551,34628 31555,34633 31555,34636 31559,34634 31564,34636 31564,34639 31562,34639 31560,36639 31555,36636 27555,41636 27557,41640 27554,41644 27558,41647 27559,41648 27555,41653 27555,41658 27555,41658 27552,41658 27552,41660 27550,41656 27554,41661 27558,41664 27561,41667 27566,41662 27562,41663 27563,41663 27565,41662 27569,41661 27569,41664 27571,41664 27567,41659 30567,41660 30565,41660 30561,41665 30566,41664 30561,41664 30561,41664 30562,41664 30563,41660 30558,1312 24380,4312 25380,4315 25384,4315 25385,4319 25383,4322 25388,6322 25387,6322 25387,6326 25392,6321 25397,6324 25397,6324 25401,6319 25404,9319 25405,9314 25400,9312 25402,9310 25403,9313 25403,9313 25403,9316 25400,9319 25401,4319 25396,8319 25398,8315 25400,8315 25396,8315 25397,8311 25398,8307 25394,8309 25394,8311 25397,8315 25402,8310 25403,11310 25365,11311 25365,11316 25370,11320 25375,11325 25375,11325 25380,11325 25382,11326 25378,14326 25380,14328 25382,14331 25383,14334 25385,14336 25386,19336 25386,19336 25389,19332 25390,19332 25391,19335 25388,19338 25391,19342 25393,19340 25393,19345 25396,19345 25394,19347 25394,19349 25393,19351 25397,19350 25398,19348 25399,19349 25403,19352 25399,19350 25402,19354 25400,19353 25405,23353 25402,23354 25402,23356 25405,23358 25409,23360 25413,23363 25414,23367 25412,23365 25411,23367 25414,23363 25413,23367 25416,23367 25416,23370 25418,24370 25414,24370 25419,24373 27419,24378 27419,24380 27416,24380 27412,24380 27410,24380 27406,24376 27406,24374 27410,24370 27414,24370 27415,24371 27420,24375 27415,24378 27411,24375 27415,24378 27418,24382 27421,24383 27426,24383 27425,24385 27430,24390 27431,24394 27432,24395 27436,24399 30436,24400 30439,24404 30443,24403 30439,24406 30438,24410 30442,24406 30446,24408 30445,24403 30445,24408 30442,24412 30446,24416 30446,24416 30449,19416 30449,19416 30447,19418 30452,19420 30453,19423 30458,15423 30462,15423 30464,15425 30466,16425 30467,16424 30471,16421 30474,16426 30474,16428 30476,16428 30476,16424 30474,16424 33474,16425 33474,16427 33477,16425 33479,16426 33477,16422 33480,16425 33482,16430 33479,16430 33478,16429 33482,16424 33482,16427 33484,16430 33488,16431 33488,16434 33488,16435 33491,16432 33487,16436 37487,16434 37490,16438 37485,16443 37482,16446 37480,16447 37480,16447 37482,16451 37478,16454 37479,16458 37479,16454 37479,16454 37482,16459 37486,16460 37491,16463 37495,16464 37492,16465 37493,16466 37494,16468 37497,16468 37501,16468 37501,16473 37503,16473 37503,16473 37498,16476 37494,21476 33494,21473 33493,21476 33489,21478 33491,21478 33496,21478 33492,21480 33496,21483 33501,21484 33504,21483 33500,21484 33505,21484 33505,21488 35505,21491 35505,21494 35506,21496 35510,21492 35506,21492 35509,21489 35514,21490 35517,21487 35519,23487 35523,23485 35528,23487 35533,23483 35534,23487 35535,23488 35537,23493 35539,23495 35542,23495 35546,23495 35550,23491 35549,23488 35552,23492 35555,23495 35560,23500 35559,23496 35557,4322 16354,4317 16358,4318 16358,4320 16363,4315 16363,4315 16362,4316 20362,4320 20365,4323 20363,4326 20366,4329 20367,4332 20370,4337 20374,4338 20375,4333 20375,4338 20375,4341 20377,4342 20377,4342 20378,4343 20381,4346 20386,4346 20386,4346 20386,4346 20386,4349 20390,4352 20395,4354 20396,4355 20400,4358 20400,4360 20401,4360 20404,4363 20405,4368 20406,4372 20411,4371 20416,4367 20417,4364 20422,4367 20420,4372 20425,4373 20422,4374 20418,4377 20418,4381 20422,4382 20423,4384 20418,4389 20421,4385 20423,4390 20423,4390 20425,4392 20429,4396 20434,41574 39698,41578 39702,41576 39704,45576 39704,45575 39709,45577 39713,45581 39715,45581 39718,45583 39721,45578 39726,47578 39722,47581 39719,47586 39722,47586 39726,47589 39730,47592 39733,47597 39733,47593 39733,47596 39735,47597 39735,47595 39735,47591 39739,47593 39744,47593 39747,4074 20263,4077 20268,4079 20268,4078 20271,4078 22271,4083 22276,4087 22272,4088 22275,4086 22279,4082 22280,4084 22282,4086 22277,4082 22277,4087 22281,4090 22281,4092 22281,4092 22286,4094 22287,4097 22290,4097 22291,4095 22286,4095 22288,4095 22293,4095 22288,4092 22285,4089 22286,4090 22286,4095 22281,4100 22286,4103 22285,4104 22288,4104 22289,4107 22294,4112 22292,4117 22290,4120 22295,120 22300,121 22303,122 22300,122 22300,121 26300,125 26303,129 26303,127 26305,127 26306,132 26306,132 26307,136 26307,141 26309,140 26311,143 26313,140 26314,145 26318,149 26318,153 26321,153 29321,158 29326,158 29329,162 29324,162 34324,165 34329,168 34328,167 34332,169 34333,173 34334,173 34336,177 34338,178 34340,178 34344,182 34348,177 34348,182 34348,184 34353,184 34358,181 34360,183 34365,187 34365,192 34365,197 34367,199 34366,203 34368,205 34368,202 34363,204 34360,1204 34360,1205 34364,1205 30364,1205 30359,1206 30361,1207 30364,1210 30366,1210 30366,1214 30367,1218 30372,1219 30375,1214 30379,1214 30384,1217 30382,1222 30383,1223 30382,1225 30380,1228 30379,1231 30383,1232 30383,1235 30384,1237 30388,1242 30386,1244 30389,2244 30392,2241 30395,2245 30397,2245 30399,2244 30394,2242 30395,2246 32395,2246 32395,2249 32398,2251 32393,5251 32390,5251 32395,5255 32399,5255 32397,5257 32397,5257 32401,5261 32406,5261 32411,5266 32412,5271 32416,5273 32419,5276 32420,5281 32422,5279 32425,6279 33425,6284 33429,6284 33430,6282 33431,6282 33428,6286 33425,6288 32425,6288 32421,6286 32424,6288 32424,11288 32427,11292 32425,11292 32429,11290 32434,11286 32437,11286 32437,11283 32442,11278 32442,11279 32443,11283 32445,11284 32445,11283 32448,13283 32447,13287 32442,16287 32446,16282 32445,16283 32445,16284 32448,16285 32448,16284 32446,16286 32443,16290 32446,16291 32446,16292 32450,16291 32450,16291 32450,16291 32445,16287 32447,16288 32452,16287 32457,16291 36457,16289 36462,16293 36462,16294 36462,16297 36462,16301 36464,16306 36469,16310 36467,16310 36463,16313 36459,16312 36460,16313 36465,16313 36469,16308 36470,16309 36468,16314 36470,16319 41470,16322 41471,16325 44471,16330 44471,16330 44471,16330 44473,16330 44474,16335 44479,16332 44477,8414 30496,8415 30497,8419 30497,8414 30501,8416 30500,8418 30495,8421 35495,8423 35494,8427 35497,8429 35499,8432 35499,8436 35503,8438 35503,8443 35505,8440 35508,8443 35509,8440 35509,8440 35511,8441 35515,8445 35511,8448 35512,8443 35517,8443 35519,8442 35524,8444 35526,8441 35527,8436 35527,8433 35523,8429 35527,8430 35530,8431 35532,8429 35533,8433 35535,8437 32535,8435 32536,8439 32536,8436 32539,9436 32542,9434 32537,9429 32534,9429 32534,9433 32537,9433 32542,9429 32543,9434 32538,9436 32538,9436 34538,7436 34538,7438 34543,7439 34543,7439 34543,7439 34548,7438 34549,7438 34552,7438 34553,7438 34556,11438 34561,11434 34559,11436 34555,7436 34553,7436 34549,120 1235,124 1239,125 1236,125 1238,129 1235,128 1235,125 1236,123 1239,128 2239,132 2242,131 2242,135 2242,140 2242,145 2247,146 2252,144 2253,146 2248,144 2245,146 2244,150 2249,155 2245,159 2242,160 2243,160 2245,155 2244,156 2245,3156 2246,3159 2248,3159 2250,3164 2254,3165 2257,3166 2255,3169 2257,3171 2262,3169 2263,3174 2268,3177 2273,3174 2276,3178 2275,3173 2279,3177 2276,3180 2279,3182 2284,3185 2289,5185 2286,5185 2288,5181 2286,5185 2288,5184 2293,5187 2293,5187 2297,5190 2299,5187 2299,5185 2300,5181 6300,5182 6297,5187 6300,5189 6298,5191 6296,5193 6296,5193 6296,5195 6297,5195 6300,5197 6297,5195 6300,5190 6302,5191 6306,5192 6308,5195 6312,24395 27436,24391 27437,24393 27433,24398 27436,24398 27437,16286 32443,21286 32443,21286 32444,21282 32448,21283 32446,21283 32448,21285 32451,21281 32456,21282 32458,21282 32463,21282 32468,21284 32470,21289 32471,21287 32471,21287 32469,21287 32474,21284 32477,21288 32482,21291 32482,21291 32486,21296 32485,21299 32486,21301 32487,21303 32484,21301 32482,21305 32487,21310 32491,21312 32495,21313 32491,21315 32495,21312 32495,21314 32498,21316 32501,21311 32506,21311 32508,21312 32513,21317 32516,21319 32516,21324 32516,21327 32521,21328 32526,21332 32527,21328 36527,21331 41527,21336 41527,21334 41531,21337 41533,21335 41535,21339 41540,21340 41540,21343 41536,25343 41539,25340 41542,25337 41542,25337 41545,25335 41542,25335 41543,25335 46543,25339 46548,30339 46551,30340 46556,30343 46557,30342 46553,30337 46556,30341 46561,30337 46565,30336 46563,30338 46564,24373 27419,24373 27421,24375 27424,24377 27425,24377 27430,24374 27435,24379 27437,24384 27432,24385 27434,24382 27437,24381 27442,24381 31442,24381 33442,20381 33439,20383 34439,20382 34440,20378 34444,20381 34446,20381 34442,20384 34443,20388 34446,20392 34447,20393 34442,20393 34447,20396 29447,20395 29443,20399 29443,20400 29439,20399 29436,20404 29439,20409 29440,20410 29440,20410 29444,20408 29445,20413 29448,20413 29451,20412 29455,20413 29458,20418 29461,20413 29463,20415 29464,20416 29464,20416 29463,20416 29463,20418 29464,20414 29465,20418 29463,20413 29460,20413 26460,20418 26458,20421 26459,20421 26461,20421 26460,43578 35658,43578 35654,43578 35658,43578 35660,43583 35661,43583 35659,43583 35662,43579 35663,43583 35661,43587 35666,25625 25551,25629 25551,25630 25554,25630 25559,25632 25560,25627 25561,25623 25557,25623 25559,25624 25561,26624 25566,26627 25566,29627 25571,29626 25574,29625 25575,29622 25579,29625 25583,29630 25588,29632 25589,29635 25591,29635 25594,29637 25598,29642 25596,29643 25597,29644 25597,29649 25598,29654 25602,29656 25602,29661 25603,29661 25601,29664 26601,29666 26604,29665 26604,29668 26607,29672 26607,29669 26611,29671 26616,29674 26613,29679 26616,29680 26616,29681 26615,29682 26619,29679 26617,29684 26622,29686 26624,29689 26624,29690 26628,29691 26630,29693 26625,29694 26620,29698 26617,29703 29617,29707 29616,29706 29620,29709 29623,34709 29626,34710 29628,34710 29627,2282 16411,2283 16412,2283 16412,2287 16417,2292 16421,2297 16421,2298 16426,2303 16426,2304 16429,2309 11429,2313 11432,2308 14432,2308 14431,2311 14433,2310 14437,2308 14438,2309 14440,2311 14440,2309 14443,2312 14443,2314 14447,2314 14452,2314 14450,2309 14451,2309 14451,2309 14456,2313 14461,2313 14461,2309 19461,2309 19461,2311 19462,2315 19465,2318 19465,2321 19462,2317 19464,2321 19467,2322 19467,2322 19469,2322 19469,2320 19464,2321 19462,2322 19461,2327 19466,2327 19461,2322 19461,2322 19463,2317 19467,2318 19471,2102 -1848,2107 -1848,2111 -1846,2114 1154,2114 1156,2115 1157,2114 6157,2116 6162,2121 6165,2124 6170,2121 6175,2124 6179,2124 6183,2128 6178,2126 6179,2125 6178,2126 6181,2122 10181,2127 10186,2128 10189,2130 10188,2130 10191,2127 11191,2127 11195,2131 11196,2132 11192,2131 11197,2135 11201,2135 11203,2139 11199,2142 11203,2143 11204,2147 11208,2142 11210,2142 11211,2147 11212,2150 11217,2150 11219,2151 11219,2152 11222,2152 11222,2148 11224,2150 11220,2150 11223,2146 11218,2143 11219,2140 11221,2143 11218,2140 11219,2140 11223,2145 11225,2147 11226,2152 11226,2155 11224,2157 11229,2157 11229,2153 11233,2153 11238,2149 11239,7149 10239,7154 10241,7157 10241,7162 10243,7164 10248,7164 10251,7169 10253,7171 10253,7172 10257,7177 10260,7182 10256,7187 10260,7191 8260,7195 8256,7200 8258,7204 8258,7203 8261,7203 8262,7205 8266,7209 8270,7209 8273,7214 8273,7214 8276,7210 8276,7211 8276,7213 8279,7218 8278,7222 8283,7223 8279,7220 10279,7221 10283,7223 10284,7228 10286,7230 10290,7231 10290,7231 10293,7232 10294,7232 10297,7234 10299,7229 10295,7226 10294,7221 10293,7223 10295,7228 10299,7229 10303,7232 10307,7232 10311,7233 10316,7234 9316,7239 9318,7244 9321,7241 9326,7241 9328,7238 9331,7235 9330,7237 9335,7236 9335,7236 9337,7236 9338,7231 14338,7230 14333,7232 14338,7237 18338,4082 22280,4081 22280,6081 22283,6076 22285,6076 22289,6078 22286,6080 22287,6084 22292,6084 22293,6085 22293,6086 22291,6091 22294,6092 22293,9092 22290,9095 22294,9096 22295,9096 22297,9091 22292,9096 22295,9098 22290,9094 18290,9097 18290,9096 18294,9099 18292,9098 18297,9103 18299,9103 18302,9103 18305,9100 18301,9102 18302,9106 18305,9102 18310,9101 18306,9103 18308,9103 18312,9107 18310,9107 18315,9107 18320,9111 18322,9111 18326,9113 18329,9111 18329,9116 18329,9121 18329,9121 18332,9123 18331,9124 18332,9125 18328,9127 18325,9125 18328,9128 18329,9133 18329,9136 18333,9141 18337,9142 18342,9143 18340,9148 18344,9152 18341,9150 18346,9149 18341,9149 18341,9154 18343,9158 18345,9161 18346,9161 18347,9163 18352,9164 18352,9162 18349,9165 18352,9165 18351,9165 18352,9165 18356,9163 18352,9167 18353,9167 18349,9168 18351,9168 18347,9173 18347,9175 18347,9179 18348,9182 18349,9187 18352,9186 18357,9189 18360,9192 18360,9196 18362,13196 18367,13196 18369,13196 18371,13199 18374,13194 18374,13197 18375,13200 18377,13205 18380,13210 18384,13209 18379,13209 18374,13213 18375,13216 20375,13212 20375,13215 20375,13211 20375,13211 20372,13208 20373,13204 20373,13204 20369,13205 20369,13207 20366,13212 20367,13216 20367,13221 20372,13222 20377,13225 20381,13226 20386,13230 20383,9230 20388,9228 20384,9228 20386,9223 20389,9223 20392,4223 20397,4223 20396,4225 20399,4222 20404,4220 20408,4220 20411,4223 20416,4227 20421,4230 20418,4234 20421,4232 20422,4236 20423,4238 20423,4239 20423,4235 20427,4231 20427,4230 20426,4228 20428,4232 20427,4232 20431,4236 20433,4241 20431,4241 22431,4236 22436,4239 22437,4239 22439,4236 22443,4232 22439,4236 22444,4236 22446,4239 22447,4239 22452,4241 22454,4245 22457,4245 22460,4250 22462,4251 22465,4253 22465,4249 22465,4251 22460,4251 22464,4255 22469,4257 22473,4256 22478,4259 22479,4260 22480,4257 22485,6257 22489,6260 22490,6260 22493,6262 22496,6262 22500,6267 22495,6271 22495,6276 22491,6276 22489,6281 22487,6286 22490,6289 22490,6294 22490,6294 22489,6292 22485,6292 22489,6288 22489,6288 22494,6288 22496,6286 22497,6288 22501,6292 22500,5292 22503,5292 22503,5296 22508,5295 22510,5300 22510,5305 22513,5302 22514,5306 22510,5309 22513,5313 27513,5313 27513,5317 27513,5322 22513,5326 22517,6326 22516,6323 22518,6323 22523,6320 22523,6321 22526,6323 22531,6323 22531,6324 22532,6324 22532,6325 22529,6321 22531,6323 22534,6328 22534,6329 22530,6324 22527,10324 22522,10319 22524,10315 22520,10314 22525,10311 22525,10307 22526,10304 22531,10306 22527,10306 22528,10309 22530,10312 27530,10312 27534,10312 27534,10307 27536,10307 27532,11307 27531,11307 27533,11308 27535,11303 27531,11298 27532,11294 27534,11294 27534,11299 27538,11297 27542,11302 27547,11306 27547,11311 27549,11313 30549,11317 30551,11313 30546,11316 30541,11316 30540,11319 30545,11318 30546,11323 30550,11326 30554,11326 34554,11330 34558,11331 34558,11333 34558,11332 34561,11328 34561,11331 34562,11336 34562,11336 34567,11340 34570,11342 34569,11345 34568,11344 34569,11345 34571,11349 34574,15349 34574,15354 34569,15359 34566,15362 34571,15363 34576,15367 34577,15368 34577,15371 34581,15374 34576,15379 34574,15383 34579,15384 34584,15387 34583,17387 34578,17392 34578,17391 34578,17396 34573,17397 34578,17397 34580,17397 39580,17402 39584,17397 39587,17402 39587,17406 39582,17403 39587,17407 39589,17409 39592,17406 39592,17409 39595,17409 39599,17412 39603,17416 39608,17417 39608,17417 39608,17421 39607,17422 39609,17424 39608,17427 39604,17425 39605,17426 39609,17423 39611,17422 39610,17425 39613,17428 39618,17428 39619,17429 39616,17432 39616,13432 39615,13432 39617,13432 39617,13432 44617,13434 44621,13434 44623,13439 44627,13442 44632,13442 44635,13440 44631,13442 44631,13445 44635,13447 44639,13445 44637,13445 44638,13450 44639,13454 44644,13457 44644,13459 44642,15459 44639,15457 44644,15461 44644,15462 44642,15459 44645,15459 44647,15463 44650,15458 44651,15459 44653,15461 44657,15463 44661,15463 44661,15463 44663,15467 44666,15472 44668,15474 44664,15470 44668,15471 44670,15473 44674,15475 44675,-3806 12298,-3804 12301,-3805 13301,-3804 13296,-3808 13292,-3809 13295,-3806 13300,-3804 13297,-3801 13301,-3801 13302,-3796 18302,-3801 18306,-3799 18311,-3802 18311,-3799 18312,-3801 18314,-3796 18319,-3795 18322,-3791 18321,-3786 18320,-3786 18321,-3784 18321,-3782 18321,-3781 18324,-3782 18325,-3783 18320,-3788 18324,-1788 18324,-1788 18329,-1784 18333,-1784 18334,-1781 18329,-1777 18334,-6777 18337,-6774 18339,-6776 18341,-6781 18341,-6779 18341,-6779 18343,-6779 18339,-6777 18343,-6782 18338,-6779 18341,-6778 18341,-6776 18336,-6776 18333,-6776 18333,-6780 18338,-6784 18338,-6787 18335,-6786 18336,-6781 22336,-6781 22335,-6778 22331,-6777 22326,-6777 22331,-6777 22335,-6772 22335,-6774 22340,-6769 22341,-6767 22337,-6767 22335,-6767 22335,-6767 22333,-6767 22336,-6762 22331,-6759 22331,-6764 22332,-6765 22334,-6767 22339,-6762 22334,-6760 22334,-6760 22334,-6758 22337,-6754 22341,-6754 22342,-6750 22339,-4750 22343,-4747 22343,-4752 22343,-4751 22344,-4749 22345,-4745 22348,-4740 22353,-4736 22358,-4738 22363,-4740 22358,21336 41527,21334 41527,21330 41526,21330 41526,21333 41529,21328 41529,21329 41530,21326 41532,21328 41532,21324 41537,21328 41532,21330 41535,21334 41532,21336 40532,21334 40536,21339 40534,21341 40534,21344 40534,21346 40532,21350 40532,21353 40535,21357 40539,21359 40542,21360 40546,21355 40546,21360 40547,21359 40550,21356 40551,21356 40550,21357 40550,21361 40554,21358 45554,21362 45556,21366 45553,21370 45557,21374 45556,21377 45553,22377 45549,22382 45549,22382 45552,22386 45557,22387 45557,22388 45553,22392 45557,24392 45561,22392 45558,22397 45561,22399 45558,22398 45561,22400 45564,22400 45569,22404 45573,22406 45577,22406 45581,22404 45581,22407 45582,22409 45579,22409 45575,22409 45579,22407 45579,22402 45582,22402 45582,22404 45587,22406 45587,22406 45589,22411 45589,22413 45590,22417 45591,22417 45592,22422 45587,22425 45583,22428 50583,22428 50585,22428 50585,22430 50588,22435 50590,22435 50585,22435 50590,22439 50595,22440 50590,22445 50587,22442 50584,22442 50586,22443 54586,22443 54590,22446 54595,22448 54597,22448 59597,22444 59593,22449 59596,22449 59599,22452 59600,22457 59600,22458 59605,22457 59602,22462 59603,22463 59604,22461 59605,22458 59602,22457 59601,22457 59601,22455 59605,25455 59606,25457 59611,25462 59613,25464 59614,25467 59617,25472 59612,25476 59613,25478 59610,25482 59615,25482 59616,25486 59612,25483 59614,25487 59619,25492 59623,25497 59625,146 2252,150 2249,150 2249,152 2254,157 2249,158 2253,157 2252,161 2255,159 3255,161 3258,161 3255,163 3255,168 3259,168 3259,172 3263,167 3267,172 3271,172 3272,172 3274,175 3278,179 3282,181 3283,184 3280,185 3282,187 3282,191 3284,192 3286,191 6286,193 6289,198 6285,195 6290,194 6289,195 6289,199 6293,200 6288,198 6290,202 6291,207 6296,212 6301,215 6301,216 6301,211 6304,212 6304,216 6309,216 6304,214 6308,213 6308,211 6305,212 6309,217 6314,220 6317,224 6322,222 6327,220 6323,41573 39712,41572 39709,41576 40709,41580 40714,41576 40717,36576 40717,36577 40719,36582 40716,36585 40721,36590 43721,36585 43721,36582 43724,36585 43729,36590 43731,36590 43730,15289 11307,15285 11312,15286 11315,15289 11315,15294 11315,15295 11316,15296 13316,38742 37646,38743 37650,38745 37655,38744 37658,38739 37659,38737 37662,38742 37662,38745 37657,38748 37662,38748 37662,38752 37667,38753 37667,38748 37669,38748 37668,38752 37673,38754 37674,38756 37676,38758 37674,38760 37679,38760 37675,38758 37675,38763 37675,38767 37674,38772 40674,38767 40679,38772 40683,38774 44683,38778 44686,38780 44690,38780 44690,38779 44695,38782 44700,38780 44695,38775 44696,38775 44696,38775 44696,38779 44699,38783 44696,38784 44696,38786 44692,38786 44692,38786 44696,38791 44698,38793 44699,38795 44703,38800 44708,38803 44708,38807 44709,38802 44706,38806 44708,38809 44709,36809 44709,36814 44704,36813 44705,36814 44705,36816 44709,36811 44712,36812 48712,36811 48717,36815 48721,36816 51721,36818 51717,36822 51720,40822 51715,40827 51712,40830 51716,40829 51719,40832 51723,40835 51724,40840 51721,40841 51721,40836 51725,40841 51730,40846 51734,40848 51738,40849 51740,40851 51743,40854 51745,40855 51746,40857 51750,40857 51746,40861 51748,40866 51751,40862 51750,40866 51750,40869 51752,40865 51752,40863 51755,40858 51757,40855 51753,40855 51758,40852 51758,40853 51760,40857 51761,40855 51757,40852 51760,40853 51761,40855 51762,40858 51757,40859 51756,40863 51757,40863 51759,40860 51764,40859 51764,40854 51768,40850 51765,40852 51767,40852 51767,40848 51772,40852 51776,40854 51778,40852 51778,43852 51778,43854 52778,43856 52781,43859 52781,43859 52776,37512 26536,37517 26531,37520 26535,37520 26540,37522 26544,37527 26544,37532 26549,37537 26544,37540 26549,37545 26544,37549 26547,37549 26550,37548 26551,37549 26553,37546 26553,37546 26553,37549 26556,37549 26559,37552 26559,37556 26564,37560 26559,37561 26561,37565 26565,41565 26565,41569 26568,41571 26573,41571 26573,41576 29573,41571 29573,41573 29576,41573 29578,46573 29578,46569 29582,45569 29583,45572 29583,45568 29583,45573 29581,45575 29578,45571 29581,45572 29584,45572 29585,45576 29585,45578 29588,45581 29591,45582 29593,45582 29598,45584 29597,45589 29600,45585 29605,45589 33605,45593 36605,45594 36607,45599 36609,45600 36604,45604 36604,45604 36608,45604 36607,45608 36610,50608 36613,50611 36609,50614 36609,50619 36605,50624 36605,50625 36606,50625 36605,50629 36606,50624 36608,50625 36610,50626 36610,50629 36608,50627 36610,50628 36614,50632 36618,46632 34618,46632 35618,46636 35622,46636 35617,46637 35620,46639 35619,46643 35620,46645 35625,46643 35630,46648 35635,46648 35640,46649 35643,46651 35647,46655 35650,46652 35655,46657 35656,46658 35657,46662 35660,46659 35663,46662 35664,46665 35663,46667 35667,46667 35663,46670 35666,46672 35671,46674 35671,47674 35668,47676 35672,47677 35673,47677 35678,47677 35677,47677 35677,47677 35682,47672 35683,47671 35683,49671 35685,49674 35689,49677 35692,49675 35692,54675 35697,54678 35699,54674 35699,54670 35701,54670 35700,54675 35703,54676 34703,54676 34703,54679 34706,54683 34708,54688 34706,54688 34707,54685 34702,54687 34702,54692 34707,54687 36707,54687 36706,54682 36707,54685 38707,54680 38710,54680 38714,54677 38714,54679 38719,54682 38720,54687 38716,54688 38717,54692 38722,54697 38726,54699 38727,54700 38724,54702 38720,52702 38719,52702 38719,52702 38721,52702 38725,52704 38726,52706 38728,52707 38729,52711 38728,52711 35728,52713 35733,52712 35737,52712 35739,52713 35742,52713 35745,52708 35745,52710 39745,52713 39749,52716 39748,52721 39749,52720 39753,52716 39756,52716 40756,47716 40757,47717 40761,47722 40761,47722 40761,47722 40766,47726 40769,47728 40772,47733 40777,47731 40773,50731 40777,51731 40779,51733 40782,51734 40786,51737 40784,51741 41784,51739 41783,51739 41785,51739 41785,51736 41789,51731 41789,52731 41790,52735 41791,52738 41790,52742 41789,52746 41785,52747 41785,52745 41785,52750 41782,52753 41786,52753 41787,52758 41792,52754 42792,52749 42793,52752 42794,52756 42791,52757 42790,52762 42793,52766 42797,52766 42797,52769 42802,52774 42806,52774 42805,52771 42807,52774 42807,52770 42808,52771 42811,52767 42811,52766 42812,52767 42817,52771 42817,52771 42817,52775 42815,52779 42811,52779 42812,52780 42815,52776 42818,52774 42818,52777 42822,52780 42823,52781 42827,52776 42829,52780 42832,54780 42835,54780 42840,2135 11201,2140 11203,2137 11204,2140 11209,2142 11213,2147 11211,2145 11213,2145 11213,2150 11218,2150 11221,2153 11225,2157 13225,2162 13228,2167 13231,2171 13232,2167 13229,2168 13233,2171 13237,2173 13239,2168 13234,2168 13235,2173 13235,2175 13234,2177 13235,2177 13234,2179 13229,2179 13226,2180 13226,2177 13226,2177 13231,2180 13231,2181 10231,2176 10233,2177 10232,2180 10235,2185 10237,2182 10240,6182 10240,6184 10244,6182 10242,6183 10243,6185 10246,6190 10244,6194 10244,6194 10247,6192 10247,6192 10252,6195 10256,6194 10260,6195 9260,6195 9260,6195 9264,6199 9269,6204 9272,6199 9268,6201 9268,6203 9265,6208 9268,6204 9270,6204 9275,6201 9279,6201 9281,6201 9286,6206 9281,6206 9277,6202 9281,6200 9285,6202 9288,6198 9290,7198 9293,7200 9297,7201 9297,7205 9298,7209 9298,7209 9299,8209 9302,8214 10302,8218 10306,8222 10308,8226 10313,8231 10313,8235 10318,8237 10318,8237 10323,8233 10326,8233 10327,8237 10325,8238 10328,8238 10330,8234 10330,11234 10332,11236 10333,11241 10337,14241 10338,14240 10338,14237 10339,14238 10337,14237 10339,14242 10339,14246 10339,14250 10339,14250 10339,14251 10337,14254 10337,14256 10334,14256 10332,14252 10336,14255 10340,14259 10342,14262 10347,11148 3159,11153 3163,11154 3162,11154 3165,11158 3167,11161 3172,11162 3175,11162 3176,11166 3179,11166 3181,11171 3185,11176 3180,11178 3179,11176 3181,11179 3183,11174 3182,52776 42818,52778 42822,52777 42822,52782 42817,52783 42822,52784 42823,52789 42826,52789 42823,56789 42828,56786 42829,56786 42832,56789 42836,56789 42835,56785 42838,56786 42843,51786 42844,51788 42846,51790 42847,51794 42842,51796 42842,51801 42846,53801 42849,53806 42849,53809 42852,53812 42850,53817 42846,53817 42848,53818 42853,53822 42856,53823 42854,53826 42858,53825 42860,53826 42860,53826 42864,53830 42868,53835 42873,53839 42873,53841 42872,53841 42876,53841 42879,53841 42884,53836 42888,53836 42889,53836 44889,53833 44889,53835 44893,53838 44897,53842 44897,53844 44900,53844 44904,53845 44905,53850 44903,53853 44904,53858 44906,53856 44907,53861 44909,53856 44913,53858 44916,53863 44916,53868 44918,53867 43918,53869 43921,53869 43919,53867 43919,53862 43918,53860 43923,53864 43928,53869 43930,53874 43933,53874 43932,53874 43932,53875 43930,53877 43928,53878 43924,53883 43927,55883 43929,55883 43925,55879 43929,55881 43929,55884 43928,55881 43928,55882 43929,55883 45929,55883 45933,55883 45936,55884 45941,55884 45941,55886 45946,55882 45948,55883 45952,55888 45956,55890 45957,55894 45953,55892 45954,55897 45950,55893 45954,55896 45956,55892 45955,55897 45959,55899 45961,55899 45961,55894 45962,55898 45957,55893 49957,55896 47957,55894 47956,55898 47960,55901 47964,55901 47967,55901 47970,55896 47973,55898 47969,55894 47974,55895 47975,55891 47976,55896 47979,55899 47984,55902 47983,55897 47987,55899 47989,55904 47992,55904 47993,55905 47997,55902 48001,55902 48003,55907 48000,55910 47998,55915 47999,55911 47994,55906 47998,55910 48003,55914 48000,55918 48000,55914 48000,55919 48000,55921 48003,55921 48007,55924 48007,55919 48010,55922 48005,55927 48009,55928 48008,55928 48008,55930 48012,55925 48012,55925 48016,54925 48014,54922 48018,54922 44018,54926 44013,54929 44012,54932 44016,55932 44017,55935 44017,55936 44020,55937 44022,55936 44020,55939 44015,55944 44018,55945 44022,55947 44023,55950 44024,55953 44020,55956 44023,53867 43919,53871 43921,52871 43921,53871 43923,53876 43923,53881 43923,53880 43927,53882 43931,53886 43936,53884 43937,53879 43934,53879 43937,53877 43939,53878 43938,53879 43942,53880 43947,53881 43948,53884 45948,53884 45949,53882 45953,53883 45954,53878 45956,53880 45953,53885 45958,53885 45958,53886 45957,53886 48957,53886 48962,53891 48962,53892 48964,53897 48965,49897 48962,49902 48965,49906 48967,49902 48967,49904 48971,49901 48967,49904 48970,54904 48971,54904 48971,54904 48975,54909 48979,54907 48975,54910 48975,54906 48971,54909 48973,54911 48975,54915 48978,54920 48978,54923 48981,54918 48984,54921 48984,56921 48984,56926 48986,56924 48981,56929 48980,56932 48979,56932 48977,56936 48979,56937 48981,56937 48982,61937 48984,61937 48980,61934 51980,61935 51981,61935 51984,61935 51984,61931 51986,5329 23395,5331 23395,5333 23390,5337 23392,5340 23395,5345 27395,5345 27397,5350 27398,5355 27399,5356 27402,6356 27405,6360 27407,6361 27406,6364 27402,6366 26402,6371 26402,6371 26402,6372 26405,6370 26405,6375 26406,6380 26411,6385 26413,6387 26414,6388 26419,6390 26419,6391 26424,6393 30424,6390 30429,6390 30432,6390 30430,6394 30434,6394 30437,6394 30441,6396 30442,6398 30439,6399 30436,6404 30435,6405 30435,6400 30435,6405 30440,6404 30443,6405 30447,6409 30447,6411 30447,6412 30448,6417 30446,6421 30450,6418 30448,6417 30444,6418 30449,6420 30451,6425 30456,6426 30456,6425 30458,6426 30458,6426 34458,6427 34459,6432 39459,6434 39462,6434 39467,6439 39470,6443 39467,6444 39468,6449 39473,6451 39476,6452 39481,6452 39479,6452 39476,8452 39476,8456 39478,8460 39480,10460 39482,10455 39482,10456 39484,10460 39484,10463 39484,10468 39486,10473 39482,10475 39484,10475 39486,10476 39488,10477 39492,10475 39494,10480 39499,10476 39501,10479 39506,10480 39510,10475 39508,10480 39513,10481 39516,10481 39516,10485 39521,10487 39522,10490 39523,10490 39520,10493 39520,10496 44520,10491 44519,10491 44524,10492 44520,10497 44525,10499 44525,10502 44527,10500 44531,10502 44535,10506 44535,10511 44532,13511 44536,13513 44533,13510 44535,13507 44540,13511 44543,13515 44548,13517 44549,13522 44550,13525 42550,13520 42551,13522 42553,13525 42552,13529 42557,13529 42558,13524 42559,13525 42559,13525 42562,13520 42564,13523 42567,15523 42569,15523 42572,15524 42577,15529 42577,15530 42582,15532 42584,15532 42588,15531 42587,15531 42592,15530 42587,15530 42583,15533 42583,15536 47583,15532 47583,15535 47587,15534 47590,15536 47594,11536 47590,11533 47590,11529 47590,11533 47592,11533 47592,11533 47593,11537 47598,11538 47603,11538 47603,11538 47605,11541 47609,11544 47613,14544 47614,14539 47610,14537 47610,14537 47614,14535 50614,14537 50619,14539 50619,14540 50623,14538 50623,14537 50619,25599 26540,25599 26541,25599 26544,25594 26542,25599 26543,25596 26544,25597 26543,25598 26543,25593 26544,25588 26542,25593 26545,25595 26544,25596 26544,25599 26541,25594 26544,25592 26549,25593 26548,25597 26549,25596 26550,25594 26551,25590 26550,25594 26554,25597 26550,25598 26552,25593 26555,25598 22555,25599 22557,25604 22559,25605 22558,25606 22562,25605 22559,25605 22564,30605 22569,30610 22571,30610 22575,30609 22575,30609 22576,30609 22581,30605 22581,30610 22583,30610 22584,30613 22579,30613 22581,30616 22577,30619 22577,30621 22580,30621 22585,30626 22590,30628 22593,30629 22598,30626 22603,30628 22606,30629 22607,30629 22604,30627 22606,30632 22608,30633 22608,30636 22612,30641 17612,30642 17614,30647 17614,30651 17615,30654 17610,30655 17607,30658 17611,30653 17610,30654 17606,30654 17607,30659 17606,30660 17611,30658 17616,30659 17616,30664 17619,30665 17621,30665 17620,30667 17621,30671 17624,30673 17624,30673 17624,30678 17627,30675 17632,30675 17635,30678 17640,30681 17643,30686 17639,30691 17641,30696 19641,30699 19640,30700 19640,30696 19645,30698 19643,30699 19645,30702 19646,30703 19649,30699 19651,30704 19648,30706 19652,30709 19653,30709 19655,30709 19655,30712 19657,30708 19658,30705 19660,30700 19662,30701 19663,30706 19664,30711 19663,30707 19667,30704 19670,30708 19672,30709 19673,30711 19673,30711 19674,30713 19678,30718 19682,30723 20682,30721 20686,30725 20691,30726 20693,30729 20695,30728 20690,30730 20692,30733 20694,30736 20692,30736 20691,30740 20694,30741 20695,30741 20697,30746 20700,30747 20702,30750 20701,30751 20698,30753 24698,30749 24701,30748 24703,30746 24704,30747 29704,30747 29705,30749 29707,30752 29712,30757 29712,30760 34712,30760 34716,30763 34716,30759 34713,30759 34717,30763 34717,30758 34717,30757 34721,30760 34726,30758 34726,30763 34727,30763 34727,30764 34727,30759 34729,30759 34732,30762 34734,30757 34735,30761 34736,30759 34736,30762 34738,30757 34733,30760 34735,30762 34737,30760 34736,30765 34733,32765 34737,32768 34737,32765 34740,32765 34742,32768 34747,32772 34751,32772 34752,32777 34749,32782 34751,32783 33751,32783 33746,36783 33749,36783 33754,36786 33756,36787 33755,36787 33758,36791 33754,36796 33754,36801 33756,36801 33758,36801 33762,36802 33765,36802 33765,36806 33770,33806 33772,33806 33777,33809 33777,33814 33780,33814 33785,33818 33782,33821 33784,33826 33781,33822 33781,33824 33783,33822 33784,33826 33787,33823 33792,33827 33795,33828 33798,33829 33799,33833 33801,33833 33801,33836 33805,33839 33809,33842 33805,33847 33810,33845 32810,33847 32808,33849 32812,33851 32815,33849 32818,33849 32822,33847 32822,33847 32826,33850 32831,33854 32836,33857 32833,33856 32828,33859 32829,33860 32832,33857 32834,33857 32830,33855 32830,33857 32830,33855 32834,33859 32829,33859 32833,33862 32836,33864 32837,33864 32839,33866 32837,33869 32835,33872 32840,33874 37840,33879 37845,33881 37850,33881 37855,33886 37856,33891 37860,33896 37860,33893 37863,33894 38863,33896 38859,28896 38864,28899 39864,33899 39869,33896 39871,33898 39875,33902 39873,33902 39875,33907 39879,33912 39884,33908 39887,33908 39888,33905 39890,33909 39895,33911 39896,33908 39900,33912 39901,33915 39902,33915 39902,33915 39902,33910 39907,33910 39904,33914 39903,33912 39906,33916 39909,33920 39909,33922 39912,33923 39916,33928 39916,33931 39918,33932 39919,33935 39915,33936 39912,33934 39909,35934 39914,35931 39915,35935 39917,35939 39920,35939 39915,35940 39911,35944 39916,35944 39911,35944 39908,35945 39904,35945 39908,35945 39912,35950 39915,35955 39917,38955 39916,38960 39921,38962 39920,38962 39920,38967 39922,38967 39924,38970 39928,38975 39928,38973 39928,38977 39931,38980 39934,38984 39936,38982 39939,38983 39942,38985 39943,38987 39945,38992 41945,38988 41950,38989 41954,38992 41958,38992 41962,38992 41965,38993 41970,38997 41970,38997 41970,38994 41974,38994 41979,38997 41979,38999 41982,38994 41980,38998 41985,38998 41984,5334 23406,5330 23406,5325 23403,9325 23404,12325 23408,12325 23408,12322 23406,13322 23411,13325 23416,13326 23412,13322 23414,13327 23419,13328 23422,13329 23425,13333 23422,13337 23424,23491 35549,23490 35544,23494 35546,23499 35548,23495 35549,21495 35553,21490 35556,21492 35558,21492 35556,21494 35559,21494 35564,21494 35566,21499 35566,21502 35562,21502 35567,17502 35568,17506 35573,17507 35574,17511 35578,17512 35583,17513 35588,18513 35591,18514 35592,18515 35594,18513 35596,16513 35601,16513 37601,16513 37602,16511 37604,16513 37609,16514 37611,16518 37616,16522 34616,16524 34613,16528 34615,16528 34620,16533 34624,16535 34627,16538 34628,16539 34630,16539 34631,16542 34628,16542 34633,16544 34638,16547 38638,16547 38640,16543 38645,16543 38640,16540 38640,16543 38640,16542 38641,16546 38646,16541 38649,16541 38645,18541 38648,18544 38648,18544 38653,18544 38656,18549 38651,18547 38651,18550 38656,18547 38658,23547 38663,23544 38664,23548 38668,23548 38670,28548 38672,28549 38669,28549 38673,28545 38669,28549 38670,28554 38670,28557 38674,28560 38669,28562 38674,28562 38669,28561 38669,28564 38671,28569 38671,38779 44699,38780 44695,38778 44698,38783 44700,38785 44700,38781 44701,38782 44696,38786 44691,38789 44692,38794 44692,38799 44688,38799 44693,38803 44697,38808 44697,38806 44697,38806 44700,38803 44702,38803 44706,38802 44707,38807 48707,38808 48707,38806 48707,38810 48712,38810 48709,38810 48711,38810 48711,38806 48707,38802 48710,38803 48706,38805 48711,38810 48711,38805 48709,38809 48710,38809 48710,38814 48707,38815 48703,38816 48703,38816 48704,38820 48704,38822 48709,38820 48710,38818 48714,38822 48716,38822 48719,38827 48722,38828 48727,38832 48725,38830 48730,38831 48726,38832 48724,38829 48728,8431 35532,8431 35537,4431 35532,4434 35537,4438 35537,4439 35533,4443 35535,4442 35530,4445 35527,4449 35527,4453 35530,4458 35530,4459 39530,4460 39531,4461 39531,4464 39531,4468 39531,4470 39534,4465 39534,4465 39532,4469 39532,4471 39537,4466 39538,4470 39539,4473 39540,4476 39540,4480 39543,4485 39548,4483 39546,4484 39547,4484 39549,4484 39551,4486 39553,4486 39554,4487 39551,4483 39553,4486 39554,4490 39556,4493 39557,4498 39561,4494 39562,-4749 22345,-4752 22345,-4748 22348,-4744 22351,-4740 22356,-4741 22358,-4739 22361,-4734 22359,-4730 25359,-4730 25360,-4725 25360,-4727 25360,-4727 25361,-6727 25360,-6729 25365,-6730 25365,-6727 25365,-6731 25364,-6730 27364,-6727 27366,-6723 27367,-3723 27363,-3719 27368,-3720 27371,-3718 27366,-3717 27369,-3716 27369,-3714 27372,-3711 27370,-3712 27371,-3712 27370,-3710 27375,-3708 27377,-3707 27382,-3706 27385,-3706 27389,-3705 32389,-3704 32392,-3704 32392,-3699 32391,-3699 32395,-3694 32399,-3694 32400,-3695 32404,-3695 32408,-3693 32410,-3693 32410,-3697 32410,-3692 32413,-3691 32418,-3686 32420,-3683 32425,-3681 32420,-3678 32424,-3673 32424,-3676 32427,-3673 32426,-3671 32426,-3676 33426,-3678 33428,-3676 33428,-3679 33428,-3679 33433,-3677 33434,-3676 33438,-3681 33440,1319 33444,1321 33441,1325 33444,1329 33439,1326 33444,1326 33439,1327 33439,1327 33440,1332 33444,1333 33449,1338 33453,1338 33450,1343 33450,1347 33454,1346 33457,1346 33455,1342 33459,1341 33462,1346 33462,1347 33463,1343 33463,1344 33462,1348 33457,1347 33460,1352 33464,1356 33468,1361 33469,1363 33468,1365 33469,1368 33472,1369 33475,-2631 33478,-2633 33483,-2629 33486,-2632 34486,-2628 36486,-2625 36488,-2621 36488,-2624 36488,-2622 36492,-2624 36491,-2629 36491,-2627 36496,-2623 36499,-2628 36502,-2631 36506,-2626 36506,-2622 36506,-2622 36509,-2619 36514,-2624 36512,-2621 36510,-2619 36510,-2619 36508,-2617 36512,-2615 36512,-2615 36513,-2615 36511,-2615 36506,-2612 36507,-2609 36511,-2606 37511,-2606 37508,-2610 37505,-2607 37508,-2602 37512,-2599 37512,-2595 37510,-2597 37511,-2592 37515,-2597 37514,-2592 37519,-2592 37524,-2592 37526,-2594 37521,-2594 37516,-2591 36516,-2588 36517,-2589 36513,-2586 36514,-2584 36514,-2583 36516,-2579 36514,-2578 36518,-2578 35518,-2575 35519,-2577 35519,-2578 35524,-2578 35529,-2578 35532,-2578 35534,-2580 35537,-2584 35541,-2586 35542,-2587 35544,-2585 35540,-2585 35544,-2584 35543,-2580 35548,-2576 35550,-2571 35553,-2567 35555,-2565 35560,-2560 35560,-2557 35564,-2553 35564,-5553 36564,-5548 36564,-5544 36565,-5547 36565,-5545 36570,-5542 36565,-5543 36566,-5543 36568,-5543 36570,-5540 36575,-5537 36577,-5535 36581,-5532 36580,-5528 36575,-5526 38575,-5526 38576,-5526 38571,-5522 38571,-5518 38576,-5514 42576,-5510 42581,-5512 42583,-5512 42582,-5507 42582,-5510 42585,-2510 42589,-2511 42592,-2508 42594,-2506 42597,-2503 42598,-2503 42603,-2498 42608,-2501 42611,-2500 42616,-2502 42613,-2502 42616,-4502 42616,-4502 42620,-4502 42622,-4506 42619,-4509 42621,-4511 42624,-4515 42625,-4510 42625,-4507 42628,-4502 42624,-4501 42629,-4505 45629,-4503 45630,-4499 45631,-4496 45630,-4497 45628,-4495 45630,-4494 46630,-4491 46634,-4487 46629,-4483 46631,21336 40532,21341 40533,21346 40534,21346 40536,21345 40536,21346 40536,21345 40536,21344 40538,21347 40543,21348 40543,21351 40540,21351 40542,21348 40545,21351 40546,21352 40546,21353 40546,21358 40546,21359 40545,21359 40550,21357 40555,21362 40560,21364 40555,21363 40555,21364 40560,25364 40564,25365 40566,25368 40566,25371 45566,25372 45567,25372 45562,25376 45564,25381 42564,25385 42560,25389 42564,25389 42568,25393 42572,25390 42572,28390 42569,28389 42570,28385 42574,28386 42576,28389 42577,31389 42578,31385 42582,31387 42582,31390 42578,31391 42579,31392 42576,29392 42580,29396 42582,29398 43582,29402 43584,29406 43585,29407 43587,29411 43592,29413 43594,29414 43595,25414 43600,25412 43595,25415 43599,25420 43602,25418 43604,25423 43599,25426 43599,25429 43602,25434 42602,25429 42604,25432 42600,25435 42605,25436 47605,25440 50605,25441 50610,25439 50614,25444 50617,25447 50621,25444 50624,25444 50626,25445 50627,25450 50632,25450 50628,25451 50630,25451 50632,25454 50633,25458 50637,25462 50641,25463 50640,25463 51640,25467 51644,25469 51649,25473 51650,25474 51653,25475 51654,26475 51658,26475 51662,26474 51665,26476 51665,26481 51661,26483 55661,26485 55664,30485 55667,30485 55670,30489 55671,30489 55668,30491 55670,30492 55670,30493 55675,30497 55675,30501 55671,30503 55676,30500 55677,30498 55672,30494 55675,30499 55676,30500 55676,30505 55681,30501 55684,30496 55685,30500 55685,30502 55687,30506 55692,30507 55693,30506 55692,30511 55693,30516 55694,30514 55699,30514 55701,30512 55701,34512 55705,34516 55708,34520 55704,34518 56704,34519 56704,34520 56706,34517 56706,34515 56701,34519 59701,34522 59706,34522 59708,34522 59713,34526 59715,34528 59717,34533 59712,34538 59715,34538 59717,34541 59717,34546 59720,34548 59721,34552 63721,34547 63726,34549 63728,34554 63726,34556 63726,34557 63721,34556 63725,34561 63730,34558 63730,37558 63725,37561 63729,37565 63724,37569 63720,37573 63718,37578 63722,37577 63718,37579 63720,37579 63722,37580 63719,37580 63720,37579 63724,37574 63725,37574 63727,37576 63725,37581 63729,37583 63732,37586 63732,37590 63737,37592 63734,37597 63731,37600 63730,37596 63731,37596 63733,37600 63733,37601 63735,37596 63735,37591 63732,37596 63733,37601 63738,37602 63733,37599 63738,37594 63740,37598 63744,37603 63745,37605 63747,37607 63752,37607 63756,37603 63757,37603 63761,37604 63761,37608 63758,37609 63762,37604 63764,37604 63764,41604 63765,41600 63761,41599 63761,41600 63766,41596 63766,41599 63766,41601 63770,41604 63768,41608 63768,41611 63772,41614 63767,41609 63763,41612 63765,41615 63760,38615 63764,38615 63768,38618 63768,35618 63769,35618 63774,35617 63775,35618 63776,35613 63775,35615 63780,35612 63782,35613 63779,35614 63775,35618 63774,35619 63776,35624 63778,35624 63780,35629 63785,35629 63780,35626 63781,35624 63782,35629 63784,35634 63787,35638 63782,35634 63783,35634 63778,35633 63777,35638 63782,35641 63786,35644 63791,35648 63793,35647 63793,35649 63797,35653 63801,35654 63804,35654 63804,35656 63804,35655 63806,35658 63810,35658 63805,35662 63805,35657 67805,35658 67808,35660 67811,35664 67808,35660 67803,35658 67803,35661 67803,35663 67808,35666 67810,35670 67814,35669 67813,35669 67816,37669 67820,37664 67820,2275 13363,2278 16363,2274 16363,2275 16362,2279 16362,2282 16362,2287 16366,2284 16366,4284 16366,4286 16371,4290 16375,4294 18375,4295 18377,9295 18381,9296 18381,9299 18382,9303 18379,9305 19379,9308 19375,8308 19380,8312 19380,38746 37651,38749 37652,38754 37653,38757 37656,38753 37661,38753 37661,38758 37663,38763 37664,38763 42664,38768 42666,38765 42668,38770 42664,38767 42659,38768 42659,38773 42654,38771 42659,38775 42661,41775 42663,41778 42665,41781 42669,41782 42667,41779 42669,41784 42672,41781 42672,41783 42672,41780 42672,41783 42675,41784 42675,41788 42676,41792 42677,41792 42675,41793 42680,41793 42676,41796 42681,41801 42685,41804 42684,41806 42685,41804 42690,41802 42692,41805 42696,41800 42697,41802 42698,41804 42700,41809 42704,41813 42705,36813 42708,36813 42704,36810 42703,36811 42705,40811 42706,40815 46706,40816 46708,40820 46708,40818 46712,40822 46717,40825 46720,40829 46724,40827 46727,40831 46727,40833 46731,40829 46733,40830 46733,36830 46738,36830 46741,36834 46744,36831 46749,36826 46748,36822 46748,36824 46751,36819 46755,36823 46758,36823 46762,36824 46766,36822 46769,36826 46772,36831 46774,36828 42774,36833 42776,36833 42777,36838 42782)'))); @@ -86,13 +86,13 @@ SPATIAL KEY (g3), SPATIAL KEY (g4), SPATIAL KEY (g5), SPATIAL KEY (g6) -) ENGINE=InnoDB; +) ENGINE=InnoDB STATS_PERSISTENT=0; DROP TABLE t1,t2; CREATE TABLE t1 ( p INT NOT NULL AUTO_INCREMENT, g LINESTRING NOT NULL, PRIMARY KEY(p) -) ENGINE=InnoDB; +) ENGINE=InnoDB STATS_PERSISTENT=0; ALTER TABLE t1 ADD SPATIAL INDEX spatial_idx (g); ALTER TABLE t1 ADD INDEX prefix_idx (g(767)); INSERT INTO t1(g) VALUES(ST_linefromtext('linestring(-5 -576,0 -576,0 -571,0 -571,5 -568,6 -564,6 -565,6 -563)')); @@ -131,6 +131,6 @@ SPATIAL KEY (g3), SPATIAL KEY (g4), SPATIAL KEY (g5), SPATIAL KEY (g6) -) ENGINE=InnoDB; +) ENGINE=InnoDB STATS_PERSISTENT=0; DROP TABLE t1,t2; disconnect control_purge; 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 81755124a20..a11f1783e2d 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_add_index.test +++ b/mysql-test/suite/innodb_gis/t/rtree_add_index.test @@ -1,6 +1,6 @@ --source include/have_innodb.inc -CREATE TABLE t1 (g MULTIPOINT NOT NULL) ENGINE=InnoDB; +CREATE TABLE t1 (g MULTIPOINT NOT NULL) ENGINE=InnoDB STATS_PERSISTENT=0; INSERT INTO t1 VALUES (''); connect purge_control,localhost,root; diff --git a/mysql-test/suite/innodb_gis/t/rtree_compress.test b/mysql-test/suite/innodb_gis/t/rtree_compress.test index e667ec8e9f0..56690b88d92 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_compress.test +++ b/mysql-test/suite/innodb_gis/t/rtree_compress.test @@ -10,9 +10,11 @@ # Valgrind takes too much time on PB2 even in the --big-test runs. --source include/not_valgrind.inc -create table t1 (c1 int, c2 geometry not null, spatial index (c2))engine=innodb ROW_FORMAT=COMPRESSED; +create table t1 (c1 int, c2 geometry not null, spatial index (c2))engine=innodb ROW_FORMAT=COMPRESSED STATS_PERSISTENT=0; # Insert enough values to let R-tree split. +lock tables t1 write; +start transaction; insert into t1 values(1, Point(1,1)); insert into t1 values(2, Point(2,2)); insert into t1 values(3, Point(3,3)); @@ -33,6 +35,8 @@ insert into t1 select * from t1; insert into t1 select * from t1; insert into t1 select * from t1; insert into t1 select * from t1; +commit; +unlock tables; start transaction; insert into t1 select * from t1; select count(*) from t1; diff --git a/mysql-test/suite/innodb_gis/t/rtree_purge.test b/mysql-test/suite/innodb_gis/t/rtree_purge.test index cab86aa668f..194c8a23b01 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_purge.test +++ b/mysql-test/suite/innodb_gis/t/rtree_purge.test @@ -8,7 +8,7 @@ create table t ( b point not null,d point not null, spatial key (d),spatial key (b) -) engine=innodb; +) engine=innodb stats_persistent=0; --disable_query_log set @p=point(1,1); diff --git a/mysql-test/suite/innodb_gis/t/rtree_undo.test b/mysql-test/suite/innodb_gis/t/rtree_undo.test index 962ff780fa0..9126b96d3b0 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_undo.test +++ b/mysql-test/suite/innodb_gis/t/rtree_undo.test @@ -17,7 +17,7 @@ CREATE TABLE t1 ( p INT NOT NULL AUTO_INCREMENT, g LINESTRING NOT NULL, PRIMARY KEY(p) -) ENGINE=InnoDB; +) ENGINE=InnoDB STATS_PERSISTENT=0; if ($index == 3) { eval ALTER TABLE t1 ADD INDEX prefix_idx (g($prefix_size)); @@ -88,7 +88,7 @@ CREATE TABLE t2 ( SPATIAL KEY (g4), SPATIAL KEY (g5), SPATIAL KEY (g6) -) ENGINE=InnoDB; +) ENGINE=InnoDB STATS_PERSISTENT=0; DROP TABLE t1,t2; diff --git a/mysql-test/suite/innodb_zip/r/blob.result b/mysql-test/suite/innodb_zip/r/blob.result index df3a49ed777..5671e81aafe 100644 --- a/mysql-test/suite/innodb_zip/r/blob.result +++ b/mysql-test/suite/innodb_zip/r/blob.result @@ -3,7 +3,7 @@ # failed in mtr_t::write(), btr_free_externally_stored_field() # CREATE TABLE t1 (c TEXT, f2 INT PRIMARY KEY, f3 INT UNIQUE) -ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; +ENGINE=InnoDB STATS_PERSISTENT=0 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; SET @level= @@GLOBAL.innodb_compression_level; SET GLOBAL innodb_compression_level=0; connect prevent_purge,localhost,root; diff --git a/mysql-test/suite/innodb_zip/t/blob.test b/mysql-test/suite/innodb_zip/t/blob.test index 4f9117f73ef..461b451fdec 100644 --- a/mysql-test/suite/innodb_zip/t/blob.test +++ b/mysql-test/suite/innodb_zip/t/blob.test @@ -6,7 +6,7 @@ --echo # CREATE TABLE t1 (c TEXT, f2 INT PRIMARY KEY, f3 INT UNIQUE) -ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; +ENGINE=InnoDB STATS_PERSISTENT=0 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; SET @level= @@GLOBAL.innodb_compression_level; SET GLOBAL innodb_compression_level=0; diff --git a/mysql-test/suite/mariabackup/unencrypted_page_compressed.result b/mysql-test/suite/mariabackup/unencrypted_page_compressed.result index d995d1be364..dfcf19b6c2b 100644 --- a/mysql-test/suite/mariabackup/unencrypted_page_compressed.result +++ b/mysql-test/suite/mariabackup/unencrypted_page_compressed.result @@ -1,5 +1,6 @@ call mtr.add_suppression("InnoDB: Table `test`.`t1` has an unreadable root page"); -CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b TEXT, c char(200)) ENGINE=InnoDB page_compressed=yes; +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b TEXT, c char(200)) +ENGINE=InnoDB PAGE_COMPRESSED=YES STATS_PERSISTENT=0; insert into t1(b, c) values("mariadb", "mariabackup"); InnoDB 0 transactions not purged # Corrupt the table diff --git a/mysql-test/suite/mariabackup/unencrypted_page_compressed.test b/mysql-test/suite/mariabackup/unencrypted_page_compressed.test index 247a210a0e7..700c4dd2034 100644 --- a/mysql-test/suite/mariabackup/unencrypted_page_compressed.test +++ b/mysql-test/suite/mariabackup/unencrypted_page_compressed.test @@ -1,5 +1,6 @@ call mtr.add_suppression("InnoDB: Table `test`.`t1` has an unreadable root page"); -CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b TEXT, c char(200)) ENGINE=InnoDB page_compressed=yes; +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b TEXT, c char(200)) +ENGINE=InnoDB PAGE_COMPRESSED=YES STATS_PERSISTENT=0; insert into t1(b, c) values("mariadb", "mariabackup"); --source ../innodb/include/wait_all_purged.inc diff --git a/mysql-test/suite/parts/r/partition_alter_innodb.result b/mysql-test/suite/parts/r/partition_alter_innodb.result index f040f266ce0..03e7d078d51 100644 --- a/mysql-test/suite/parts/r/partition_alter_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter_innodb.result @@ -71,7 +71,8 @@ DROP TABLE t1; # # MDEV-28079 Shutdown hangs after altering innodb partition fts table # -CREATE TABLE t1(f1 INT, f2 CHAR(100))ENGINE=InnoDB PARTITION BY HASH(f1) PARTITIONS 2; +CREATE TABLE t1(f1 INT, f2 CHAR(100))ENGINE=InnoDB STATS_PERSISTENT=0 +PARTITION BY HASH(f1) PARTITIONS 2; ALTER TABLE t1 ADD FULLTEXT(f2); InnoDB 0 transactions not purged DROP TABLE t1; diff --git a/mysql-test/suite/parts/r/partition_purge.result b/mysql-test/suite/parts/r/partition_purge.result index 072b141cd8d..a58e095db04 100644 --- a/mysql-test/suite/parts/r/partition_purge.result +++ b/mysql-test/suite/parts/r/partition_purge.result @@ -1,4 +1,4 @@ -CREATE TABLE t1(f1 INT, f2 INT, INDEX(f1))ENGINE=InnoDB +CREATE TABLE t1(f1 INT, f2 INT, INDEX(f1))ENGINE=InnoDB STATS_PERSISTENT=0 PARTITION BY LIST(f1) ( PARTITION p1 VALUES in (1, 2, 3), PARTITION p2 VALUES in (4, 5, 6)); diff --git a/mysql-test/suite/parts/t/partition_alter_innodb.test b/mysql-test/suite/parts/t/partition_alter_innodb.test index 844b2084531..dcc448631dc 100644 --- a/mysql-test/suite/parts/t/partition_alter_innodb.test +++ b/mysql-test/suite/parts/t/partition_alter_innodb.test @@ -12,7 +12,8 @@ SET GLOBAL innodb_read_only_compressed=@save_innodb_read_only_compressed; --echo # --echo # MDEV-28079 Shutdown hangs after altering innodb partition fts table --echo # -CREATE TABLE t1(f1 INT, f2 CHAR(100))ENGINE=InnoDB PARTITION BY HASH(f1) PARTITIONS 2; +CREATE TABLE t1(f1 INT, f2 CHAR(100))ENGINE=InnoDB STATS_PERSISTENT=0 +PARTITION BY HASH(f1) PARTITIONS 2; ALTER TABLE t1 ADD FULLTEXT(f2); --source ../innodb/include/wait_all_purged.inc DROP TABLE t1; diff --git a/mysql-test/suite/parts/t/partition_purge.test b/mysql-test/suite/parts/t/partition_purge.test index 2df81b0eb77..054ecf479aa 100644 --- a/mysql-test/suite/parts/t/partition_purge.test +++ b/mysql-test/suite/parts/t/partition_purge.test @@ -3,7 +3,7 @@ --source include/have_debug.inc --source include/have_debug_sync.inc -CREATE TABLE t1(f1 INT, f2 INT, INDEX(f1))ENGINE=InnoDB +CREATE TABLE t1(f1 INT, f2 INT, INDEX(f1))ENGINE=InnoDB STATS_PERSISTENT=0 PARTITION BY LIST(f1) ( PARTITION p1 VALUES in (1, 2, 3), PARTITION p2 VALUES in (4, 5, 6)); diff --git a/mysql-test/suite/versioning/r/delete_history.result b/mysql-test/suite/versioning/r/delete_history.result index 16af01a5f0b..965e97e3de3 100644 --- a/mysql-test/suite/versioning/r/delete_history.result +++ b/mysql-test/suite/versioning/r/delete_history.result @@ -193,7 +193,7 @@ drop table t1; # MDEV-25004 Missing row in FTS_DOC_ID_INDEX during DELETE HISTORY # create table t1 (a integer, c0 varchar(255), fulltext key (c0)) -with system versioning engine innodb; +with system versioning engine innodb stats_persistent=0; set system_versioning_alter_history= keep; alter table t1 drop system versioning; alter table t1 add system versioning; @@ -203,7 +203,7 @@ InnoDB 0 transactions not purged delete history from t1; drop table t1; create table t1 (id int primary key, ftx varchar(255)) -with system versioning engine innodb; +with system versioning engine innodb stats_persistent=0; insert into t1 values (1, 'c'); delete from t1; alter table t1 add fulltext key(ftx); diff --git a/mysql-test/suite/versioning/t/delete_history.test b/mysql-test/suite/versioning/t/delete_history.test index d3f7e1172f1..758afb7c570 100644 --- a/mysql-test/suite/versioning/t/delete_history.test +++ b/mysql-test/suite/versioning/t/delete_history.test @@ -195,7 +195,7 @@ drop table t1; --echo # MDEV-25004 Missing row in FTS_DOC_ID_INDEX during DELETE HISTORY --echo # create table t1 (a integer, c0 varchar(255), fulltext key (c0)) -with system versioning engine innodb; +with system versioning engine innodb stats_persistent=0; set system_versioning_alter_history= keep; alter table t1 drop system versioning; alter table t1 add system versioning; @@ -206,7 +206,7 @@ delete history from t1; drop table t1; create table t1 (id int primary key, ftx varchar(255)) -with system versioning engine innodb; +with system versioning engine innodb stats_persistent=0; insert into t1 values (1, 'c'); delete from t1; alter table t1 add fulltext key(ftx); From 7443ad1c8a8437a761e1a2d3ba53f7c0ba0dd3bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 21 Nov 2023 14:38:35 +0200 Subject: [PATCH 302/477] MDEV-32374 log_sys.lsn_lock is a performance hog The log_sys.lsn_lock that was introduced in commit a635c40648519fd6c3729c9657872a16a0a20821 had better be located in the same cache line with log_sys.latch so that log_t::append_prepare() needs to modify only two first cache lines where log_sys is stored. log_t::lsn_lock: On Linux, change the type from pthread_mutex_t to something that may be as small as 32 bits, to pack more data members in the same cache line. On Microsoft Windows, CRITICAL_SECTION works better. log_t::check_flush_or_checkpoint_: Renamed to need_checkpoint. There is no need to pause all writer threads in log_free_check() when we only need to write log_sys.buf to ib_logfile0. That will be done in mtr_t::commit(). log_t::append_prepare_wait(): Make the member function non-static to simplify the call interface, and add a parameter for the LSN. log_t::append_prepare(): Invoke append_prepare_wait() at most once. Only set_check_for_checkpoint() if a log checkpoint needs to be written. If the log buffer needs to be written, we will take care of it ourselves later in our caller. This will reduce interference with log_free_check() in other threads. mtr_t::commit(): Call log_write_up_to() if needed. log_t::get_write_target(): Return a log_write_up_to() target to mtr_t::commit(). buf_flush_ahead(): If we are in furious flushing, call log_sys.set_check_for_checkpoint() so that all writers will wait in log_free_check() until the checkpoint is done. Otherwise, the test innodb.insert_into_empty could occasionally report an error "Crash recovery is broken". log_check_margins(): Replaced by log_free_check(). log_flush_margin(): Removed. This is part of mtr_t::commit() and other operations that write log. log_t::create(), log_t::attach(): Guarantee that buf_free < max_buf_free will always hold on PMEM, to satisfy an assumption of log_t::get_write_target(). log_write_up_to(): Assert lsn!=0. Such calls are not incorrect, but it is cheaper to test that single unlikely condition in mtr_t::commit() rather than test several conditions in log_write_up_to(). innodb_drop_database(), unlock_and_close_files(): Check the LSN before calling log_write_up_to(). ha_innobase::commit_inplace_alter_table(): Remove redundant calls to log_write_up_to() after calling unlock_and_close_files(). Reviewed by: Vladislav Vaintroub Stress tested by: Matthias Leich Performance tested by: Steve Shaw --- storage/innobase/btr/btr0bulk.cc | 4 +- storage/innobase/buf/buf0flu.cc | 2 + storage/innobase/fil/fil0fil.cc | 2 +- storage/innobase/handler/ha_innodb.cc | 3 +- storage/innobase/handler/handler0alter.cc | 5 +- storage/innobase/include/fil0fil.h | 2 +- storage/innobase/include/log0log.h | 74 +++++++++++----------- storage/innobase/include/mtr0mtr.h | 2 +- storage/innobase/include/srw_lock.h | 4 +- storage/innobase/log/log0log.cc | 55 ++++++---------- storage/innobase/mtr/mtr0mtr.cc | 77 +++++++++++++---------- storage/innobase/row/row0merge.cc | 4 +- storage/innobase/sync/srw_lock.cc | 6 +- 13 files changed, 118 insertions(+), 122 deletions(-) diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 013cd13102c..d6164d548ea 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -969,10 +969,10 @@ BtrBulk::pageCommit( /** Log free check */ inline void BtrBulk::logFreeCheck() { - if (log_sys.check_flush_or_checkpoint()) { + if (log_sys.check_for_checkpoint()) { release(); - log_check_margins(); + log_free_check(); latch(); } diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index b6357989341..d38c8e9f89f 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -2124,6 +2124,8 @@ ATTRIBUTE_COLD void buf_flush_ahead(lsn_t lsn, bool furious) limit= lsn; buf_pool.page_cleaner_set_idle(false); pthread_cond_signal(&buf_pool.do_flush_list); + if (furious) + log_sys.set_check_for_checkpoint(); } mysql_mutex_unlock(&buf_pool.flush_list_mutex); } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index a4e50e93890..596ad73c05d 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -3078,7 +3078,7 @@ ATTRIBUTE_NOINLINE ATTRIBUTE_COLD void mtr_t::name_write() and write out FILE_MODIFY if needed, and write FILE_CHECKPOINT. @param lsn checkpoint LSN @return current LSN */ -lsn_t fil_names_clear(lsn_t lsn) +ATTRIBUTE_COLD lsn_t fil_names_clear(lsn_t lsn) { mtr_t mtr; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 5e92e75f4ef..c87aaea1f8b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1575,7 +1575,8 @@ static void innodb_drop_database(handlerton*, char *path) ibuf_delete_for_discarded_space(id); /* Any changes must be persisted before we return. */ - log_write_up_to(mtr.commit_lsn(), true); + if (mtr.commit_lsn()) + log_write_up_to(mtr.commit_lsn(), true); } my_free(namebuf); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 40370ac5df7..2753c114881 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -4338,7 +4338,8 @@ static void unlock_and_close_files(const std::vector &deleted, row_mysql_unlock_data_dictionary(trx); for (pfs_os_file_t d : deleted) os_file_close(d); - log_write_up_to(trx->commit_lsn, true); + if (trx->commit_lsn) + log_write_up_to(trx->commit_lsn, true); } /** Commit a DDL transaction and unlink any deleted files. */ @@ -11666,7 +11667,6 @@ foreign_fail: } unlock_and_close_files(deleted, trx); - log_write_up_to(trx->commit_lsn, true); DBUG_EXECUTE_IF("innodb_alter_commit_crash_after_commit", DBUG_SUICIDE();); trx->free(); @@ -11723,7 +11723,6 @@ foreign_fail: } unlock_and_close_files(deleted, trx); - log_write_up_to(trx->commit_lsn, true); DBUG_EXECUTE_IF("innodb_alter_commit_crash_after_commit", DBUG_SUICIDE();); trx->free(); diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 6f58e3c11ca..2f11f688562 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1802,7 +1802,7 @@ bool fil_comp_algo_loaded(ulint comp_algo); and write out FILE_MODIFY if needed, and write FILE_CHECKPOINT. @param lsn checkpoint LSN @return current LSN */ -lsn_t fil_names_clear(lsn_t lsn); +ATTRIBUTE_COLD lsn_t fil_names_clear(lsn_t lsn); #ifdef UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH void test_make_filepath(); diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index f873eabf346..58213856c79 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -79,13 +79,6 @@ ATTRIBUTE_COLD void log_make_checkpoint(); /** Make a checkpoint at the latest lsn on shutdown. */ ATTRIBUTE_COLD void logs_empty_and_mark_files_at_shutdown(); -/** -Checks that there is enough free space in the log to start a new query step. -Flushes the log buffer or makes a new checkpoint if necessary. NOTE: this -function may only be called if the calling thread owns no synchronization -objects! */ -ATTRIBUTE_COLD void log_check_margins(); - /******************************************************//** Prints info of the log. */ void @@ -179,24 +172,36 @@ private: std::atomic flushed_to_disk_lsn; /** log sequence number when log resizing was initiated, or 0 */ std::atomic resize_lsn; - /** set when there may be need to flush the log buffer, or - preflush buffer pool pages, or initiate a log checkpoint. + /** set when there may be need to initiate a log checkpoint. This must hold if lsn - last_checkpoint_lsn > max_checkpoint_age. */ - std::atomic check_flush_or_checkpoint_; - + std::atomic need_checkpoint; #if defined(__aarch64__) -/* On ARM, we do more spinning */ -typedef srw_spin_lock log_rwlock_t; -#define LSN_LOCK_ATTR MY_MUTEX_INIT_FAST + /* On ARM, we do more spinning */ + typedef srw_spin_lock log_rwlock; + typedef pthread_mutex_wrapper log_lsn_lock; +#elif defined _WIN32 + typedef srw_lock log_rwlock; + typedef pthread_mutex_wrapper log_lsn_lock; #else -typedef srw_lock log_rwlock_t; -#define LSN_LOCK_ATTR nullptr + typedef srw_lock log_rwlock; + typedef srw_mutex log_lsn_lock; #endif public: - /** rw-lock protecting buf */ - alignas(CPU_LEVEL1_DCACHE_LINESIZE) log_rwlock_t latch; + /** rw-lock protecting writes to buf; normal mtr_t::commit() + outside any log checkpoint is covered by a shared latch */ + alignas(CPU_LEVEL1_DCACHE_LINESIZE) log_rwlock latch; +private: + /** mutex protecting buf_free et al, together with latch */ + log_lsn_lock lsn_lock; +public: + /** first free offset within buf use; protected by lsn_lock */ + Atomic_relaxed buf_free; + /** number of write requests (to buf); protected by lsn_lock */ + size_t write_to_buf; + /** number of append_prepare_wait(); protected by lsn_lock */ + size_t waits; private: /** Last written LSN */ lsn_t write_lsn; @@ -227,20 +232,12 @@ private: /** Buffer for writing to resize_log; @see flush_buf */ byte *resize_flush_buf; - /** spin lock protecting lsn, buf_free in append_prepare() */ - alignas(CPU_LEVEL1_DCACHE_LINESIZE) pthread_mutex_t lsn_lock; - void init_lsn_lock() { pthread_mutex_init(&lsn_lock, LSN_LOCK_ATTR); } - void lock_lsn() { pthread_mutex_lock(&lsn_lock); } - void unlock_lsn() { pthread_mutex_unlock(&lsn_lock); } - void destroy_lsn_lock() { pthread_mutex_destroy(&lsn_lock); } + void init_lsn_lock() {lsn_lock.init(); } + void lock_lsn() { lsn_lock.wr_lock(); } + void unlock_lsn() {lsn_lock.wr_unlock(); } + void destroy_lsn_lock() { lsn_lock.destroy(); } public: - /** first free offset within buf use; protected by lsn_lock */ - Atomic_relaxed buf_free; - /** number of write requests (to buf); protected by exclusive lsn_lock */ - ulint write_to_buf; - /** number of waits in append_prepare(); protected by lsn_lock */ - ulint waits; /** recommended maximum size of buf, after which the buffer is flushed */ size_t max_buf_free; @@ -308,6 +305,9 @@ public: bool is_opened() const noexcept { return log.is_opened(); } + /** @return target write LSN to react on buf_free >= max_buf_free */ + inline lsn_t get_write_target() const; + /** @return LSN at which log resizing was started and is still in progress @retval 0 if no log resizing is in progress */ lsn_t resize_in_progress() const noexcept @@ -419,13 +419,14 @@ public: inline void persist(lsn_t lsn) noexcept; #endif - bool check_flush_or_checkpoint() const + bool check_for_checkpoint() const { - return UNIV_UNLIKELY - (check_flush_or_checkpoint_.load(std::memory_order_relaxed)); + return UNIV_UNLIKELY(need_checkpoint.load(std::memory_order_relaxed)); + } + void set_check_for_checkpoint(bool need= true) + { + need_checkpoint.store(need, std::memory_order_relaxed); } - void set_check_flush_or_checkpoint(bool flag= true) - { check_flush_or_checkpoint_.store(flag, std::memory_order_relaxed); } /** Make previous write_buf() durable and update flushed_to_disk_lsn. */ bool flush(lsn_t lsn) noexcept; @@ -446,8 +447,9 @@ public: private: /** Wait in append_prepare() for buffer to become available + @param lsn log sequence number to write up to @param ex whether log_sys.latch is exclusively locked */ - ATTRIBUTE_COLD static void append_prepare_wait(bool ex) noexcept; + ATTRIBUTE_COLD void append_prepare_wait(lsn_t lsn, bool ex) noexcept; public: /** Reserve space in the log buffer for appending data. @tparam pmem log_sys.is_pmem() diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 841cfab1655..4ec8b8cf28c 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -105,7 +105,7 @@ struct mtr_t { This is to be used at log_checkpoint(). @param checkpoint_lsn the log sequence number of a checkpoint, or 0 @return current LSN */ - lsn_t commit_files(lsn_t checkpoint_lsn= 0); + ATTRIBUTE_COLD lsn_t commit_files(lsn_t checkpoint_lsn= 0); /** @return mini-transaction savepoint (current size of m_memo) */ ulint get_savepoint() const diff --git a/storage/innobase/include/srw_lock.h b/storage/innobase/include/srw_lock.h index 1dca0cc1054..01067322a0a 100644 --- a/storage/innobase/include/srw_lock.h +++ b/storage/innobase/include/srw_lock.h @@ -34,7 +34,6 @@ this program; if not, write to the Free Software Foundation, Inc., # define SUX_LOCK_GENERIC /* Use dummy implementation for debugging purposes */ #endif -#ifdef SUX_LOCK_GENERIC /** An exclusive-only variant of srw_lock */ template class pthread_mutex_wrapper final @@ -70,7 +69,6 @@ template<> inline void pthread_mutex_wrapper::wr_lock() { if (!wr_lock_try()) wr_wait(); } # endif -#endif /** Futex-based mutex */ template @@ -541,7 +539,7 @@ public: /** @return whether any lock may be held by any thread */ bool is_locked_or_waiting() const noexcept { return lock.is_locked_or_waiting(); } - /** @return whether an exclusive lock may be held by any thread */ + /** @return whether a shared or exclusive lock may be held by any thread */ bool is_locked() const noexcept { return lock.is_locked(); } /** @return whether an exclusive lock may be held by any thread */ bool is_write_locked() const noexcept { return lock.is_write_locked(); } diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index c0acc4e1884..9f39b303964 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -100,6 +100,7 @@ bool log_t::create() /* LSN 0 and 1 are reserved; @see buf_page_t::oldest_modification_ */ lsn.store(FIRST_LSN, std::memory_order_relaxed); flushed_to_disk_lsn.store(FIRST_LSN, std::memory_order_relaxed); + need_checkpoint.store(true, std::memory_order_relaxed); write_lsn= FIRST_LSN; #ifndef HAVE_PMEM @@ -124,18 +125,17 @@ bool log_t::create() TRASH_ALLOC(flush_buf, buf_size); checkpoint_buf= static_cast(aligned_malloc(4096, 4096)); memset_aligned<4096>(checkpoint_buf, 0, 4096); + max_buf_free= buf_size / LOG_BUF_FLUSH_RATIO - LOG_BUF_FLUSH_MARGIN; #else ut_ad(!checkpoint_buf); ut_ad(!buf); ut_ad(!flush_buf); + max_buf_free= 1; #endif latch.SRW_LOCK_INIT(log_latch_key); init_lsn_lock(); - max_buf_free= buf_size / LOG_BUF_FLUSH_RATIO - LOG_BUF_FLUSH_MARGIN; - set_check_flush_or_checkpoint(); - last_checkpoint_lsn= FIRST_LSN; log_capacity= 0; max_modified_age_async= 0; @@ -236,6 +236,7 @@ void log_t::attach_low(log_file_t file, os_offset_t size) log.close(); mprotect(ptr, size_t(size), PROT_READ); buf= static_cast(ptr); + max_buf_free= size; # if defined __linux__ || defined _WIN32 set_block_size(CPU_LEVEL1_DCACHE_LINESIZE); # endif @@ -264,6 +265,7 @@ void log_t::attach_low(log_file_t file, os_offset_t size) TRASH_ALLOC(buf, buf_size); TRASH_ALLOC(flush_buf, buf_size); + max_buf_free= buf_size / LOG_BUF_FLUSH_RATIO - LOG_BUF_FLUSH_MARGIN; #endif #if defined __linux__ || defined _WIN32 @@ -813,8 +815,8 @@ template inline lsn_t log_t::write_buf() noexcept #ifndef SUX_LOCK_GENERIC ut_ad(latch.is_write_locked()); #endif - ut_ad(!srv_read_only_mode); ut_ad(!is_pmem()); + ut_ad(!srv_read_only_mode); const lsn_t lsn{get_lsn(std::memory_order_relaxed)}; @@ -849,7 +851,7 @@ template inline lsn_t log_t::write_buf() noexcept ... /* TODO: Update the LSN and adjust other code. */ #else /* The rest of the block will be written as garbage. - (We want to avoid memset() while holding mutex.) + (We want to avoid memset() while holding exclusive log_sys.latch) This block will be overwritten later, once records beyond the current LSN are generated. */ # ifdef HAVE_valgrind @@ -886,6 +888,7 @@ template inline lsn_t log_t::write_buf() noexcept write_lsn= lsn; } + set_check_for_checkpoint(false); return lsn; } @@ -927,8 +930,9 @@ wait and check if an already running write is covering the request. void log_write_up_to(lsn_t lsn, bool durable, const completion_callback *callback) { - ut_ad(!srv_read_only_mode); + ut_ad(!srv_read_only_mode || (log_sys.buf_free < log_sys.max_buf_free)); ut_ad(lsn != LSN_MAX); + ut_ad(lsn != 0); if (UNIV_UNLIKELY(recv_no_ibuf_operations)) { @@ -1016,16 +1020,6 @@ ATTRIBUTE_COLD void log_write_and_flush() #endif } -/******************************************************************** - -Tries to establish a big enough margin of free space in the log buffer, such -that a new log entry can be catenated without an immediate need for a flush. */ -ATTRIBUTE_COLD static void log_flush_margin() -{ - if (log_sys.buf_free > log_sys.max_buf_free) - log_buffer_flush_to_disk(false); -} - /****************************************************************//** Tries to establish a big enough margin of free space in the log, such that a new log entry can be catenated without an immediate need for a @@ -1033,12 +1027,12 @@ checkpoint. NOTE: this function may only be called if the calling thread owns no synchronization objects! */ ATTRIBUTE_COLD static void log_checkpoint_margin() { - while (log_sys.check_flush_or_checkpoint()) + while (log_sys.check_for_checkpoint()) { log_sys.latch.rd_lock(SRW_LOCK_CALL); ut_ad(!recv_no_log_write); - if (!log_sys.check_flush_or_checkpoint()) + if (!log_sys.check_for_checkpoint()) { func_exit: log_sys.latch.rd_unlock(); @@ -1054,7 +1048,7 @@ func_exit: #ifndef DBUG_OFF skip_checkpoint: #endif - log_sys.set_check_flush_or_checkpoint(false); + log_sys.set_check_for_checkpoint(false); goto func_exit; } @@ -1068,30 +1062,17 @@ func_exit: } } -/** -Checks that there is enough free space in the log to start a new query step. -Flushes the log buffer or makes a new checkpoint if necessary. NOTE: this -function may only be called if the calling thread owns no synchronization -objects! */ -ATTRIBUTE_COLD void log_check_margins() -{ - do - { - log_flush_margin(); - log_checkpoint_margin(); - ut_ad(!recv_no_log_write); - } - while (log_sys.check_flush_or_checkpoint()); -} - /** Wait for a log checkpoint if needed. NOTE that this function may only be called while not holding any synchronization objects except dict_sys.latch. */ void log_free_check() { ut_ad(!lock_sys.is_writer()); - if (log_sys.check_flush_or_checkpoint()) - log_check_margins(); + if (log_sys.check_for_checkpoint()) + { + ut_ad(!recv_no_log_write); + log_checkpoint_margin(); + } } extern void buf_resize_shutdown(); diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index df7c5fb000e..e14e3d8c797 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -308,6 +308,22 @@ void mtr_t::release() m_memo.clear(); } +inline lsn_t log_t::get_write_target() const +{ +#ifndef SUX_LOCK_GENERIC + ut_ad(latch.is_locked()); +#endif + if (UNIV_LIKELY(buf_free < max_buf_free)) + return 0; + ut_ad(!is_pmem()); + /* The LSN corresponding to the end of buf is + write_lsn - (first_lsn & 4095) + buf_free, + but we use simpler arithmetics to return a smaller write target in + order to minimize waiting in log_write_up_to(). */ + ut_ad(max_buf_free >= 4096 * 4); + return write_lsn + max_buf_free / 2; +} + /** Commit a mini-transaction. */ void mtr_t::commit() { @@ -331,6 +347,7 @@ void mtr_t::commit() std::pair lsns{do_write()}; process_freed_pages(); size_t modified= 0; + const lsn_t write_lsn= log_sys.get_write_target(); if (m_made_dirty) { @@ -448,6 +465,9 @@ void mtr_t::commit() if (UNIV_UNLIKELY(lsns.second != PAGE_FLUSH_NO)) buf_flush_ahead(m_commit_lsn, lsns.second == PAGE_FLUSH_SYNC); + + if (UNIV_UNLIKELY(write_lsn != 0)) + log_write_up_to(write_lsn, false); } else { @@ -677,7 +697,7 @@ The caller must hold exclusive log_sys.latch. This is to be used at log_checkpoint(). @param checkpoint_lsn the log sequence number of a checkpoint, or 0 @return current LSN */ -lsn_t mtr_t::commit_files(lsn_t checkpoint_lsn) +ATTRIBUTE_COLD lsn_t mtr_t::commit_files(lsn_t checkpoint_lsn) { #ifndef SUX_LOCK_GENERIC ut_ad(log_sys.latch.is_write_locked()); @@ -837,26 +857,26 @@ ATTRIBUTE_COLD static void log_overwrite_warning(lsn_t lsn) } /** Wait in append_prepare() for buffer to become available +@param lsn log sequence number to write up to @param ex whether log_sys.latch is exclusively locked */ -ATTRIBUTE_COLD void log_t::append_prepare_wait(bool ex) noexcept +ATTRIBUTE_COLD void log_t::append_prepare_wait(lsn_t lsn, bool ex) noexcept { - log_sys.waits++; - log_sys.unlock_lsn(); + waits++; + unlock_lsn(); if (ex) - log_sys.latch.wr_unlock(); + latch.wr_unlock(); else - log_sys.latch.rd_unlock(); + latch.rd_unlock(); - DEBUG_SYNC_C("log_buf_size_exceeded"); - log_buffer_flush_to_disk(log_sys.is_pmem()); + log_write_up_to(lsn, is_pmem()); if (ex) - log_sys.latch.wr_lock(SRW_LOCK_CALL); + latch.wr_lock(SRW_LOCK_CALL); else - log_sys.latch.rd_lock(SRW_LOCK_CALL); + latch.rd_lock(SRW_LOCK_CALL); - log_sys.lock_lsn(); + lock_lsn(); } /** Reserve space in the log buffer for appending data. @@ -875,34 +895,30 @@ std::pair log_t::append_prepare(size_t size, bool ex) noexcept # endif #endif ut_ad(pmem == is_pmem()); - const lsn_t checkpoint_margin{last_checkpoint_lsn + log_capacity - size}; - const size_t avail{(pmem ? size_t(capacity()) : buf_size) - size}; lock_lsn(); write_to_buf++; - for (ut_d(int count= 50); - UNIV_UNLIKELY((pmem - ? size_t(get_lsn() - - get_flushed_lsn(std::memory_order_relaxed)) - : size_t{buf_free}) > avail); ) + const lsn_t l{lsn.load(std::memory_order_relaxed)}, end_lsn{l + size}; + size_t b{buf_free}; + + if (UNIV_UNLIKELY(pmem + ? (end_lsn - + get_flushed_lsn(std::memory_order_relaxed)) > capacity() + : b + size >= buf_size)) { - append_prepare_wait(ex); - ut_ad(count--); + append_prepare_wait(l, ex); + b= buf_free; } - const lsn_t l{lsn.load(std::memory_order_relaxed)}; - lsn.store(l + size, std::memory_order_relaxed); - const size_t b{buf_free}; - size_t new_buf_free{b}; - new_buf_free+= size; + lsn.store(end_lsn, std::memory_order_relaxed); + size_t new_buf_free= b + size; if (pmem && new_buf_free >= file_size) new_buf_free-= size_t(capacity()); buf_free= new_buf_free; unlock_lsn(); - if (UNIV_UNLIKELY(l > checkpoint_margin) || - (!pmem && b >= max_buf_free)) - set_check_flush_or_checkpoint(); + if (UNIV_UNLIKELY(end_lsn >= last_checkpoint_lsn + log_capacity)) + set_check_for_checkpoint(); return {l, &buf[b]}; } @@ -927,7 +943,7 @@ static mtr_t::page_flush_ahead log_close(lsn_t lsn) noexcept else if (UNIV_LIKELY(checkpoint_age <= log_sys.max_checkpoint_age)) return mtr_t::PAGE_FLUSH_ASYNC; - log_sys.set_check_flush_or_checkpoint(); + log_sys.set_check_for_checkpoint(); return mtr_t::PAGE_FLUSH_SYNC; } @@ -1147,9 +1163,6 @@ inline void log_t::resize_write(lsn_t lsn, const byte *end, size_t len, } } -/** Write the mini-transaction log to the redo log buffer. -@param len number of bytes to write -@return {start_lsn,flush_ahead} */ std::pair mtr_t::finish_write(size_t len) { diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 5df93fe6e50..a1ae7ea643e 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -120,7 +120,7 @@ public: ut_ad(mtr_started == scan_mtr->is_active()); DBUG_EXECUTE_IF("row_merge_instrument_log_check_flush", - log_sys.set_check_flush_or_checkpoint();); + log_sys.set_check_for_checkpoint();); for (idx_tuple_vec::iterator it = m_dtuple_vec.begin(); it != m_dtuple_vec.end(); @@ -128,7 +128,7 @@ public: dtuple = *it; ut_ad(dtuple); - if (log_sys.check_flush_or_checkpoint()) { + if (log_sys.check_for_checkpoint()) { if (mtr_started) { if (!btr_pcur_move_to_prev_on_page(pcur)) { error = DB_CORRUPTION; diff --git a/storage/innobase/sync/srw_lock.cc b/storage/innobase/sync/srw_lock.cc index e41451d8003..5afb79f24ff 100644 --- a/storage/innobase/sync/srw_lock.cc +++ b/storage/innobase/sync/srw_lock.cc @@ -143,8 +143,7 @@ static inline void srw_pause(unsigned delay) HMT_medium(); } -#ifdef SUX_LOCK_GENERIC -# ifndef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +#ifndef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP template<> void pthread_mutex_wrapper::wr_wait() { const unsigned delay= srw_pause_delay(); @@ -158,8 +157,9 @@ template<> void pthread_mutex_wrapper::wr_wait() pthread_mutex_lock(&lock); } -# endif +#endif +#ifdef SUX_LOCK_GENERIC template void ssux_lock_impl::init(); template void ssux_lock_impl::init(); template void ssux_lock_impl::destroy(); From ee033f1ff3ad8de74f9c8f17512ae40ea647fa13 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Tue, 21 Nov 2023 08:53:44 -0500 Subject: [PATCH 303/477] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ebc1b9a5332..82752fb8de8 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=11 MYSQL_VERSION_MINOR=2 -MYSQL_VERSION_PATCH=2 +MYSQL_VERSION_PATCH=3 SERVER_MATURITY=gamma From 78c9a12c8fc25a6032e6c04b83171aafeebc53de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 22 Nov 2023 16:54:41 +0200 Subject: [PATCH 304/477] MDEV-32861 InnoDB hangs when running out of I/O slots When the constant OS_AIO_N_PENDING_IOS_PER_THREAD is changed from 256 to 1 and the server is run with the minimum parameters innodb_read_io_threads=1 and innodb_write_io_threads=2, two hangs were observed. tpool::cache::put(T*): Ensure that get() in io_slots::acquire() will be woken up when the cache previously was empty. buf_pool_t::io_buf_t::reserve(): Schedule a possibly partial doublewrite batch so that os_aio_wait_until_no_pending_writes() has a chance of returning. Add a Boolean parameter and pass wait_for_reads=false inside buf_page_decrypt_after_read(), because those calls will be executed inside a read completion callback, and therefore os_aio_wait_until_no_pending_reads() would block indefinitely. --- storage/innobase/buf/buf0buf.cc | 11 +++++++---- storage/innobase/buf/buf0flu.cc | 2 +- storage/innobase/include/buf0buf.h | 5 +++-- tpool/tpool_structs.h | 3 ++- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index f762cf65a01..c0dece69cf8 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -414,7 +414,7 @@ static bool buf_page_decrypt_after_read(buf_page_t *bpage, if (node.space->purpose == FIL_TYPE_TEMPORARY && innodb_encrypt_temporary_tables) { - slot = buf_pool.io_buf_reserve(); + slot = buf_pool.io_buf_reserve(false); ut_a(slot); slot->allocate(); @@ -444,7 +444,7 @@ decompress: return false; } - slot = buf_pool.io_buf_reserve(); + slot = buf_pool.io_buf_reserve(false); slot->allocate(); decompress_with_slot: @@ -471,7 +471,7 @@ decrypt_failed: return false; } - slot = buf_pool.io_buf_reserve(); + slot = buf_pool.io_buf_reserve(false); slot->allocate(); ut_d(fil_page_type_validate(node.space, dst_frame)); @@ -1513,14 +1513,17 @@ void buf_pool_t::io_buf_t::close() n_slots= 0; } -buf_tmp_buffer_t *buf_pool_t::io_buf_t::reserve() +buf_tmp_buffer_t *buf_pool_t::io_buf_t::reserve(bool wait_for_reads) { for (;;) { for (buf_tmp_buffer_t *s= slots, *e= slots + n_slots; s != e; s++) if (s->acquire()) return s; + buf_dblwr.flush_buffered_writes(); os_aio_wait_until_no_pending_writes(); + if (!wait_for_reads) + continue; for (buf_tmp_buffer_t *s= slots, *e= slots + n_slots; s != e; s++) if (s->acquire()) return s; diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 77008312727..186fb89ddce 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -702,7 +702,7 @@ static byte *buf_page_encrypt(fil_space_t* space, buf_page_t* bpage, byte* s, ut_ad(!bpage->zip_size() || !page_compressed); /* Find free slot from temporary memory array */ - buf_tmp_buffer_t *slot= buf_pool.io_buf_reserve(); + buf_tmp_buffer_t *slot= buf_pool.io_buf_reserve(true); ut_a(slot); slot->allocate(); slot->out_buf= NULL; diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index def7641db1d..0e1a4c27f35 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -2030,7 +2030,8 @@ public: a delete-buffering operation is pending. Protected by mutex. */ buf_page_t watch[innodb_purge_threads_MAX + 1]; /** Reserve a buffer. */ - buf_tmp_buffer_t *io_buf_reserve() { return io_buf.reserve(); } + buf_tmp_buffer_t *io_buf_reserve(bool wait_for_reads) + { return io_buf.reserve(wait_for_reads); } /** @return whether any I/O is pending */ bool any_io_pending() @@ -2083,7 +2084,7 @@ private: void close(); /** Reserve a buffer */ - buf_tmp_buffer_t *reserve(); + buf_tmp_buffer_t *reserve(bool wait_for_reads); } io_buf; /** whether resize() is in the critical path */ diff --git a/tpool/tpool_structs.h b/tpool/tpool_structs.h index b49204f2d75..96c250ebd59 100644 --- a/tpool/tpool_structs.h +++ b/tpool/tpool_structs.h @@ -138,12 +138,13 @@ public: { std::unique_lock lk(m_mtx); assert(!is_full()); + const bool was_empty= is_empty(); // put element to the logical end of the array m_cache[--m_pos] = ele; /* Notify waiters when the cache becomes not empty, or when it becomes full */ - if (m_pos == 1 || (m_waiters && is_full())) + if (was_empty || (is_full() && m_waiters)) m_cv.notify_all(); } From 32c6849736211e27964953436aca86e91ac924fd Mon Sep 17 00:00:00 2001 From: Rex Date: Sat, 18 Nov 2023 05:23:50 +1200 Subject: [PATCH 305/477] MDEV-32829 Crash when executing PS for query with eliminated subquery using view Statements affected by this bug have all the following 1) select statements with a sub-query 2) that sub-query includes a group-by clause 3) that group-by clause contains an expression 4) that expression has a reference to view When a view is used in a group by expression, and that group by can be eliminated in a sub-query simplification as part of and outer condition that could be in, exists, > or <, then the table structure left behind will have a unit that contains a null select_lex pointer. If this happens as part of a prepared statement, or execute in a stored procedure for the second time, then, when the statement is executed, the table list entry for that, now eliminated, view is "opened" and "reinit"ialized. This table entry's unit no longer has a select_lex pointer. Prior to MDEV-31995 this was of little consequence, but now following this null pointer will cause a crash. Reviewed by Igor Babaev (igor@mariadb.com) --- mysql-test/main/derived_view.result | 45 +++++++++++++++++++++++++++++ mysql-test/main/derived_view.test | 36 +++++++++++++++++++++++ sql/sql_derived.cc | 5 +--- 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/mysql-test/main/derived_view.result b/mysql-test/main/derived_view.result index ab32e477816..ca96b741bdd 100644 --- a/mysql-test/main/derived_view.result +++ b/mysql-test/main/derived_view.result @@ -4172,4 +4172,49 @@ a deallocate prepare stmt; drop view v; drop table t1,t2,t3; +# +# MDEV-32829 Crash when executing PS for query with eliminated subquery +# using view +# +create view v1 as select 1 as a; +prepare stmt from +'SELECT EXISTS (SELECT 1 FROM v1 GROUP BY a IN (SELECT a FROM v1))'; +execute stmt; +EXISTS (SELECT 1 FROM v1 GROUP BY a IN (SELECT a FROM v1)) +1 +drop view v1; +create table t1 (a int, b int); +insert into t1 values (1,2),(3,4),(5,6); +create view v1 as select * from t1; +create table t2 select * from t1; +prepare stmt from "select t2.a from t2 where exists +( +select * from t1 where t2.b = t1.b and t1.b != 6 +group by a in (select a from v1 where v1.a = t2.a) +)"; +execute stmt; +a +1 +3 +execute stmt; +a +1 +3 +deallocate prepare stmt; +create procedure aproc() select t2.a from t2 where exists +( +select * from t1 where t2.b = t1.b and t1.b != 6 +group by a in (select a from v1 where v1.a = t2.a) +); +call aproc(); +a +1 +3 +call aproc(); +a +1 +3 +drop table t1, t2; +drop view v1; +drop procedure aproc; # End of 10.4 tests diff --git a/mysql-test/main/derived_view.test b/mysql-test/main/derived_view.test index 1ff06e89aa6..48ed2a0a4b7 100644 --- a/mysql-test/main/derived_view.test +++ b/mysql-test/main/derived_view.test @@ -2759,4 +2759,40 @@ deallocate prepare stmt; drop view v; drop table t1,t2,t3; +--echo # +--echo # MDEV-32829 Crash when executing PS for query with eliminated subquery +--echo # using view +--echo # + +create view v1 as select 1 as a; +prepare stmt from + 'SELECT EXISTS (SELECT 1 FROM v1 GROUP BY a IN (SELECT a FROM v1))'; +execute stmt; +drop view v1; + +create table t1 (a int, b int); +insert into t1 values (1,2),(3,4),(5,6); +create view v1 as select * from t1; +create table t2 select * from t1; + +let $q= +select t2.a from t2 where exists +( + select * from t1 where t2.b = t1.b and t1.b != 6 + group by a in (select a from v1 where v1.a = t2.a) +); + +eval prepare stmt from "$q"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +eval create procedure aproc() $q; +call aproc(); +call aproc(); + +drop table t1, t2; +drop view v1; +drop procedure aproc; + --echo # End of 10.4 tests diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 5ed39430f06..54ef1c3a59f 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1335,13 +1335,10 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) (derived->alias.str ? derived->alias.str : ""), derived->get_unit())); st_select_lex_unit *unit= derived->get_unit(); - st_select_lex *sl= unit->first_select(); // reset item names to that saved after wildcard expansion in JOIN::prepare - do - { + for(st_select_lex *sl= unit->first_select(); sl; sl= sl->next_select()) sl->restore_item_list_names(); - } while ((sl= sl->next_select())); derived->merged_for_insert= FALSE; unit->unclean(); From dd62a285b88958dae9b9f3e49fdd0c55f6eced72 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Mon, 20 Nov 2023 16:22:07 +0100 Subject: [PATCH 306/477] MDEV-31611: mariadb-setpermission - Can't use string as an ARRAY ref while strict refs in use Reviewer: <> --- scripts/mysql_setpermission.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/mysql_setpermission.sh b/scripts/mysql_setpermission.sh index b3c9c27ca88..aa165a5e742 100644 --- a/scripts/mysql_setpermission.sh +++ b/scripts/mysql_setpermission.sh @@ -68,7 +68,7 @@ usage() if ($opt_help); # the help function if ($opt_host =~ s/:(\d+)$//) { - $opt_port = $1; + $opt_port = $1; } if ($opt_host eq '') @@ -98,7 +98,7 @@ my $prefix= 'mysql'; if (eval {DBI->install_driver("MariaDB")}) { $dsn ="DBI:MariaDB:;"; $prefix= 'mariadb'; -} +} else { $dsn = "DBI:mysql:;"; } @@ -226,11 +226,11 @@ sub setpwd { $pass = "PASSWORD(". $dbh->quote($pass) . ")"; } - my $uh= "$user@$host"; + my $uh= $user."@".$host; my $sth = $dbh->prepare("set password for $uh =$pass") || die $dbh->errstr; $sth->execute || die $dbh->errstr; $sth->finish; - print "The password is set for user $user.\n\n"; + print "The password is set for user $uh.\n\n"; } From ff0bade2f8355cf07fff3dcb28b2efd13443b8ea Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Wed, 8 Nov 2023 21:38:14 +0100 Subject: [PATCH 307/477] MDEV-28367: BACKUP LOCKS on table to be accessible to those with database LOCK TABLES privileges - Allow database level access via `LOCK TABLES` to execute statement `BACKUP [un]LOCK ` - `BACKUP UNLOCK` works only with `RELOAD` privilege. In case there is `LOCK TABLES` privilege without `RELOAD` privilege, we check if backup lock is taken before. If it is not we raise an error of missing `RELOAD` privilege. - We had to remove any error/warnings from calling functions because `thd->get_stmt_da()->m_status` will be set to error and will break `my_ok()`. - Added missing test coverage of `RELOAD` privilege to `main.grant.test` Reviewer: --- mysql-test/main/backup_locks.result | 77 +++++++++++++++++++++++++++++ mysql-test/main/backup_locks.test | 73 +++++++++++++++++++++++++++ mysql-test/main/grant.result | 5 ++ mysql-test/main/grant.test | 7 +++ sql/sql_parse.cc | 52 +++++++++++++++++-- 5 files changed, 211 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/backup_locks.result b/mysql-test/main/backup_locks.result index 1505c39f166..fe7b36f11df 100644 --- a/mysql-test/main/backup_locks.result +++ b/mysql-test/main/backup_locks.result @@ -163,5 +163,82 @@ ERROR HY000: Can't execute the query because you have a conflicting read lock BACKUP UNLOCK; DROP TABLE t3; # +# MDEV-28367: BACKUP LOCKS on table to be accessible to those +# with database LOCK TABLES privileges +# +create database db1; +create table db1.t1(t int); +create user user1@localhost; +select user,host from mysql.user where user='user1'; +User Host +user1 localhost +connect(localhost,user1,,db1,MASTER_PORT,MASTER_SOCKET); +connect con1, localhost, user1, ,db1; +ERROR 42000: Access denied for user 'user1'@'localhost' to database 'db1' +grant reload on *.* to user1@localhost; +grant select on db1.* to user1@localhost; +show grants for user1@localhost; +Grants for user1@localhost +GRANT RELOAD ON *.* TO `user1`@`localhost` +GRANT SELECT ON `db1`.* TO `user1`@`localhost` +connect con1, localhost, user1, ,db1; +BACKUP UNLOCK; +BACKUP LOCK db1.t1; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_SHARED_HIGH_PRIO Table metadata lock db1 t1 +BACKUP UNLOCK; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +connection default; +disconnect con1; +grant lock tables on db1.* to user1@localhost; +show grants for user1@localhost; +Grants for user1@localhost +GRANT RELOAD ON *.* TO `user1`@`localhost` +GRANT SELECT, LOCK TABLES ON `db1`.* TO `user1`@`localhost` +connect con1, localhost, user1, ,db1; +BACKUP UNLOCK; +BACKUP LOCK db1.t1; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_SHARED_HIGH_PRIO Table metadata lock db1 t1 +BACKUP UNLOCK; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +connection default; +disconnect con1; +revoke reload on *.* from user1@localhost; +show grants for user1@localhost; +Grants for user1@localhost +GRANT USAGE ON *.* TO `user1`@`localhost` +GRANT SELECT, LOCK TABLES ON `db1`.* TO `user1`@`localhost` +connect con1, localhost, user1, ,db1; +BACKUP UNLOCK; +ERROR 42000: Access denied; you need (at least one of) the RELOAD, LOCK TABLES privilege(s) for this operation +BACKUP LOCK db1.t1; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_SHARED_HIGH_PRIO Table metadata lock db1 t1 +BACKUP UNLOCK; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +connection default; +disconnect con1; +revoke lock tables on db1.* from user1@localhost; +show grants for user1@localhost; +Grants for user1@localhost +GRANT USAGE ON *.* TO `user1`@`localhost` +GRANT SELECT ON `db1`.* TO `user1`@`localhost` +connect con1, localhost, user1, ,db1; +BACKUP LOCK db1.t1; +ERROR 42000: Access denied; you need (at least one of) the RELOAD, LOCK TABLES privilege(s) for this operation +BACKUP UNLOCK; +ERROR 42000: Access denied; you need (at least one of) the RELOAD, LOCK TABLES privilege(s) for this operation +connection default; +disconnect con1; +drop database db1; +drop user user1@localhost; +# # End of MariaDB 10.4 tests # diff --git a/mysql-test/main/backup_locks.test b/mysql-test/main/backup_locks.test index 99d748abd05..cf764e2d60c 100644 --- a/mysql-test/main/backup_locks.test +++ b/mysql-test/main/backup_locks.test @@ -188,6 +188,79 @@ DROP TABLE t3; BACKUP UNLOCK; DROP TABLE t3; +--echo # +--echo # MDEV-28367: BACKUP LOCKS on table to be accessible to those +--echo # with database LOCK TABLES privileges +--echo # + +--source include/have_metadata_lock_info.inc +create database db1; +create table db1.t1(t int); +create user user1@localhost; +select user,host from mysql.user where user='user1'; +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_DBACCESS_DENIED_ERROR +--connect (con1, localhost, user1, ,db1) + +grant reload on *.* to user1@localhost; +# To access DB one need select privileges +grant select on db1.* to user1@localhost; +show grants for user1@localhost; +--connect (con1, localhost, user1, ,db1) + +# This should work we have RELOAD privilege +BACKUP UNLOCK; +BACKUP LOCK db1.t1; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +BACKUP UNLOCK; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; + +# Add LOCK TABLES DB privileges (all privileges for BACKUP LOCK are there) +connection default; +disconnect con1; +grant lock tables on db1.* to user1@localhost; +show grants for user1@localhost; +--connect (con1, localhost, user1, ,db1) +# This should work we have RELOAD & LOCK privilege +BACKUP UNLOCK; +BACKUP LOCK db1.t1; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +BACKUP UNLOCK; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; + +# Remove reload privilege, leave only LOCK TABLES privilege +connection default; +disconnect con1; +revoke reload on *.* from user1@localhost; +show grants for user1@localhost; +--connect (con1, localhost, user1, ,db1) +# There is no reload priv needed for unlock and there is no mdl_backup_lock taken +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +BACKUP UNLOCK; +# BACKUP LOCK should work, since we have LOCK privilege +BACKUP LOCK db1.t1; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +# This works since there was taken mdl_backup_lock before +BACKUP UNLOCK; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; + +# Remove LOCK TABLES privilege +connection default; +disconnect con1; +revoke lock tables on db1.* from user1@localhost; +show grants for user1@localhost; +--connect (con1, localhost, user1, ,db1) +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +BACKUP LOCK db1.t1; +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +BACKUP UNLOCK; + +connection default; +disconnect con1; + +drop database db1; +drop user user1@localhost; + --echo # --echo # End of MariaDB 10.4 tests --echo # diff --git a/mysql-test/main/grant.result b/mysql-test/main/grant.result index 8e69e78b5d2..ae3b7473af2 100644 --- a/mysql-test/main/grant.result +++ b/mysql-test/main/grant.result @@ -1951,6 +1951,11 @@ GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u1@localhost; GRANT FILE ON *.* TO mysqltest_u1@localhost; GRANT CREATE USER ON *.* TO mysqltest_u1@localhost; GRANT PROCESS ON *.* TO mysqltest_u1@localhost; +GRANT RELOAD ON mysqltest_db1.* TO mysqltest_u1@localhost; +ERROR HY000: Incorrect usage of DB GRANT and GLOBAL PRIVILEGES +connect(localhost,mysqltest_u1,,db1,MASTER_PORT,MASTER_SOCKET); +connect con1, localhost, mysqltest_u1, ,db1; +ERROR 42000: Access denied for user 'mysqltest_u1'@'localhost' to database 'db1' GRANT RELOAD ON *.* TO mysqltest_u1@localhost; GRANT REPLICATION CLIENT ON *.* TO mysqltest_u1@localhost; GRANT REPLICATION SLAVE ON *.* TO mysqltest_u1@localhost; diff --git a/mysql-test/main/grant.test b/mysql-test/main/grant.test index 598c223c374..27d4768672a 100644 --- a/mysql-test/main/grant.test +++ b/mysql-test/main/grant.test @@ -1821,6 +1821,13 @@ GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u1@localhost; GRANT FILE ON *.* TO mysqltest_u1@localhost; GRANT CREATE USER ON *.* TO mysqltest_u1@localhost; GRANT PROCESS ON *.* TO mysqltest_u1@localhost; +# Global privileges should be granted to all schemas, not individual DB +--error ER_WRONG_USAGE +GRANT RELOAD ON mysqltest_db1.* TO mysqltest_u1@localhost; +# Select privilege is needed beside RELOAD privilege +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_DBACCESS_DENIED_ERROR +--connect (con1, localhost, mysqltest_u1, ,db1) GRANT RELOAD ON *.* TO mysqltest_u1@localhost; GRANT REPLICATION CLIENT ON *.* TO mysqltest_u1@localhost; GRANT REPLICATION SLAVE ON *.* TO mysqltest_u1@localhost; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1c487ba9d14..7cca219dc81 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5153,9 +5153,55 @@ mysql_execute_command(THD *thd) my_ok(thd); break; case SQLCOM_BACKUP_LOCK: - if (check_global_access(thd, RELOAD_ACL)) - goto error; - /* first table is set for lock. For unlock the list is empty */ + if (check_global_access(thd, RELOAD_ACL, true)) + { +#ifndef NO_EMBEDDED_ACCESS_CHECKS + /* + In case there is no global privilege, check DB privilege for LOCK TABLES. + */ + if (first_table) // BACKUP LOCK + { + if (check_single_table_access(thd, LOCK_TABLES_ACL, first_table, true)) + { + char command[30]; + get_privilege_desc(command, sizeof(command), RELOAD_ACL|LOCK_TABLES_ACL); + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command); + goto error; + } + } + else // BACKUP UNLOCK + { + /* + We test mdl_backup_lock here because, if a user could obtain a lock + it would be silly to error and say `you can't BACKUP UNLOCK` + (because its obvious you did a `BACKUP LOCK`). + As `BACKUP UNLOCK` doesn't have a database reference, + there's no way we can check if the `BACKUP LOCK` privilege is missing. + Testing `thd->db` would involve faking a `TABLE_LIST` structure, + which because of the depth of inspection + in `check_single_table_access` makes the faking likely to cause crashes, + or unintended effects. The outcome of this is, + if a user does an `BACKUP UNLOCK` without a `BACKUP LOCKED` table, + there may be a` ER_SPECIFIC_ACCESS_DENIED` error even though + user has the privilege. + Its a bit different to what happens if the user has RELOAD_ACL, + where the error is silently ignored. + */ + if (!thd->mdl_backup_lock) + { + + char command[30]; + get_privilege_desc(command, sizeof(command), RELOAD_ACL|LOCK_TABLES_ACL); + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command); + goto error; + } + } +#endif + } + /* + There is reload privilege, first table is set for lock. + For unlock the list is empty + */ if (first_table) res= backup_lock(thd, first_table); else From a48c1b89c849a390be9e5b210759369b35777b39 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 23 Nov 2023 13:03:01 +1100 Subject: [PATCH 308/477] MDEV-24670 memory pressure - eventfd rather than pipe Eventfds have a simplier interface and are one file descriptor rather than two. Reuse the patten of the accepting socket connections by testing for abort after a poll returns. This way the same event descriptor can be used for Quit and debugging trigger. Also correct the registration of mem pressure file descriptors. --- storage/innobase/buf/buf0buf.cc | 59 +++++++++++++++------------------ 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 3f1df10ac00..7e584ae07c3 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -744,6 +744,7 @@ bool buf_page_is_corrupted(bool check_lsn, const byte *read_buf, #ifdef __linux__ #include +#include #include /** Memory Pressure @@ -752,14 +753,16 @@ based off https://www.kernel.org/doc/html/latest/accounting/psi.html#pressure-in and https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#memory */ class mem_pressure { - /* triggers + pipe */ + /* triggers + eventfd */ struct pollfd m_fds[3]; nfds_t m_num_fds; - int m_pipe[2]= {-1, -1}; + int m_event_fd= -1; + Atomic_relaxed m_abort= false; std::thread m_thd; - /* mem pressure garbarge collection resticted to interval */ + /* mem pressure garbage collection restricted to interval */ static constexpr ulonglong max_interval_us= 60*1000000; + public: mem_pressure() : m_num_fds(0) {} @@ -796,7 +799,7 @@ public: shutdown(); return false; } - my_register_filename(m_pipe[0], memcgroup.c_str(), FILE_BY_OPEN, 0, MYF(0)); + my_register_filename(m_fds[m_num_fds].fd, memcgroup.c_str(), FILE_BY_OPEN, 0, MYF(0)); ssize_t slen= strlen(*trig); if (write(m_fds[m_num_fds].fd, *trig, slen) < slen) { @@ -810,15 +813,14 @@ public: if (m_num_fds < 1) return false; - if (pipe2(m_pipe, O_CLOEXEC | O_DIRECT)) + if ((m_event_fd= eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK)) == -1) { - sql_print_warning("InnoDB: No memory pressure - can't create pipe"); + sql_print_warning("InnoDB: No memory pressure - can't create eventfd"); shutdown(); return false; } - my_register_filename(m_pipe[0], "mem_pressure_read", FILE_BY_DUP, 0, MYF(0)); - my_register_filename(m_pipe[1], "mem_pressure_write", FILE_BY_DUP, 0, MYF(0)); - m_fds[m_num_fds].fd= m_pipe[0]; + my_register_filename(m_event_fd, "mem_pressure_eventfd", FILE_BY_DUP, 0, MYF(0)); + m_fds[m_num_fds].fd= m_event_fd; m_fds[m_num_fds].events= POLLIN; m_num_fds++; m_thd= std::thread(pressure_routine, this); @@ -827,18 +829,13 @@ public: void shutdown() { + /* m_event_fd is in this list */ while (m_num_fds) { m_num_fds--; my_close(m_fds[m_num_fds].fd, MYF(MY_WME)); m_fds[m_num_fds].fd= -1; } - /* note m_pipe[0] closed in above loop */ - if (m_pipe[1] >= 0) - { - my_close(m_pipe[1], MYF(MY_WME)); - m_pipe[1]= -1; - } } static void pressure_routine(mem_pressure *m); @@ -846,8 +843,8 @@ public: #ifdef UNIV_DEBUG void trigger_collection() { - const char c= 'G'; - if (m_pipe[1] >=0 && write(m_pipe[1], &c, 1) < 1) + uint64_t u= 1; + if (m_event_fd >=0 && write(m_event_fd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) sql_print_information("InnoDB: (Debug) Failed to trigger memory pressure"); else /* assumed failed to meet intialization criteria, so trigger directy */ buf_pool.garbage_collect(); @@ -856,8 +853,9 @@ public: void quit() { - const char c= 'Q'; - if (m_num_fds && write(m_pipe[1], &c, 1) < 1) + uint64_t u= 1; + m_abort= true; + if (write(m_event_fd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) sql_print_warning("InnoDB: Failed to write memory pressure quit message"); } @@ -896,7 +894,7 @@ void mem_pressure::pressure_routine(mem_pressure *m) } ulonglong last= microsecond_interval_timer() - max_interval_us; - while (1) + while (!m->m_abort) { if (poll(&m->m_fds[0], m->m_num_fds, -1) < 0) { @@ -909,6 +907,9 @@ void mem_pressure::pressure_routine(mem_pressure *m) break; } } + if (!m->m_abort) + break; + for (pollfd &p : st_::span(m->m_fds, m->m_num_fds)) { if (p.revents & POLLPRI) @@ -921,23 +922,17 @@ void mem_pressure::pressure_routine(mem_pressure *m) } } +#ifdef UNIV_DEBUG if (p.revents & POLLIN) { - char c= '\0'; - /* signal to quit */ - if (read(p.fd, &c, 1) >=0) - switch (c) { - case 'Q': - goto shutdown; -#ifdef UNIV_DEBUG - case 'G': - buf_pool.garbage_collect(); -#endif - } + uint64_t u; + /* we haven't aborted, so this must be a debug trigger */ + if (read(p.fd, &u, sizeof(u)) >=0) + buf_pool.garbage_collect(); } +#endif } } -shutdown: m->shutdown(); my_thread_end(); From 0ad483942978575b7c0432c2e766bc270b49c3c6 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 22 Nov 2023 12:10:13 +0100 Subject: [PATCH 309/477] Rename variables to make operation comprehansive --- client/mysqltest.cc | 59 ++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 3dcbd3c69e5..f03e837e1fa 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -8991,11 +8991,14 @@ int util_query(MYSQL* org_mysql, const char* query){ void run_query(struct st_connection *cn, struct st_command *command, int flags) { MYSQL *mysql= cn->mysql; - DYNAMIC_STRING *ds; - DYNAMIC_STRING *save_ds= NULL; - DYNAMIC_STRING ds_result; - DYNAMIC_STRING ds_sorted; - DYNAMIC_STRING ds_warnings; + DYNAMIC_STRING *rs_output; /* where to put results */ + DYNAMIC_STRING rs_cmp_result; /* here we put results to compare with + pre-recrded file */ + DYNAMIC_STRING rs_unsorted; /* if we need sorted results, here we store + results before sorting them */ + DYNAMIC_STRING *rs_sorted_save= NULL; /* here we store where to put sorted + result if needed */ + DYNAMIC_STRING rs_warnings; char *query; size_t query_len; my_bool view_created= 0, sp_created= 0; @@ -9008,10 +9011,10 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) if (!(flags & QUERY_SEND_FLAG) && !cn->pending) die("Cannot reap on a connection without pending send"); - - init_dynamic_string(&ds_warnings, NULL, 0, 256); - ds_warn= &ds_warnings; - + + init_dynamic_string(&rs_warnings, NULL, 0, 256); + ds_warn= &rs_warnings; + /* Evaluate query if this is an eval command */ @@ -9041,11 +9044,11 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) */ if (command->require_file) { - init_dynamic_string(&ds_result, "", 1024, 1024); - ds= &ds_result; + init_dynamic_string(&rs_cmp_result, "", 1024, 1024); + rs_output= &rs_cmp_result; } else - ds= &ds_res; + rs_output= &ds_res; // will be shown to colsole /* Log the query into the output buffer @@ -9059,9 +9062,9 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) print_query= command->query; print_len= (int)(command->end - command->query); } - replace_dynstr_append_mem(ds, print_query, print_len); - dynstr_append_mem(ds, delimiter, delimiter_length); - dynstr_append_mem(ds, "\n", 1); + replace_dynstr_append_mem(rs_output, print_query, print_len); + dynstr_append_mem(rs_output, delimiter, delimiter_length); + dynstr_append_mem(rs_output, "\n", 1); } /* We're done with this flag */ @@ -9116,7 +9119,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) Collect warnings from create of the view that should otherwise have been produced when the SELECT was executed */ - append_warnings(&ds_warnings, + append_warnings(&rs_warnings, service_connection_enabled ? cur_con->util_mysql : mysql); @@ -9172,9 +9175,9 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) that can be sorted before it's added to the global result string */ - init_dynamic_string(&ds_sorted, "", 1024, 1024); - save_ds= ds; /* Remember original ds */ - ds= &ds_sorted; + init_dynamic_string(&rs_unsorted, "", 1024, 1024); + rs_sorted_save= rs_output; /* Remember original ds */ + rs_output= &rs_unsorted; } /* @@ -9189,20 +9192,20 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) if (ps_protocol_enabled && complete_query && match_re(&ps_re, query)) - run_query_stmt(cn, command, query, query_len, ds, &ds_warnings); + run_query_stmt(cn, command, query, query_len, rs_output, &rs_warnings); else run_query_normal(cn, command, flags, query, query_len, - ds, &ds_warnings); + rs_output, &rs_warnings); - dynstr_free(&ds_warnings); + dynstr_free(&rs_warnings); ds_warn= 0; if (display_result_sorted) { /* Sort the result set and append it to result */ - dynstr_append_sorted(save_ds, &ds_sorted, 1); - ds= save_ds; - dynstr_free(&ds_sorted); + dynstr_append_sorted(rs_sorted_save, &rs_unsorted, 1); + rs_output= rs_sorted_save; + dynstr_free(&rs_unsorted); } if (sp_created) @@ -9225,11 +9228,11 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) and the output should be checked against an already existing file which has been specified using --require or --result */ - check_require(ds, command->require_file); + check_require(rs_output, command->require_file); } - if (ds == &ds_result) - dynstr_free(&ds_result); + if (rs_output == &rs_cmp_result) + dynstr_free(&rs_cmp_result); DBUG_VOID_RETURN; } From 9e701518e7d0a541ba580b6a6afc9e9bcd522f23 Mon Sep 17 00:00:00 2001 From: Lena Startseva Date: Fri, 15 Sep 2023 17:48:03 +0700 Subject: [PATCH 310/477] MDEV-32177: Add to the ps-protocol a comparison of the result sets of the first and second execution. The results of the first and second execution are compared only if result logging is enabled Comparing two result sets is done as comparing two strings. Added a new method 'read_stmt_results' to get a result set after execution of prepare statement. --- client/mysqltest.cc | 252 +++++++++++++++++++++++++++++++++----------- 1 file changed, 189 insertions(+), 63 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index f03e837e1fa..0483cd4e212 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -80,6 +80,9 @@ static my_bool non_blocking_api_enabled= 0; #define DIE_BUFF_SIZE 256*1024 +#define RESULT_STRING_INIT_MEM 2048 +#define RESULT_STRING_INCREMENT_MEM 2048 + /* Flags controlling send and reap */ #define QUERY_SEND_FLAG 1 #define QUERY_REAP_FLAG 2 @@ -8268,6 +8271,87 @@ void handle_no_error(struct st_command *command) } +/* + Read result set after prepare statement execution + + SYNOPSIS + read_stmt_results + stmt - prepare statemet + mysql - mysql handle + command - current command pointer + ds - output buffer where to store result form query + + RETURN VALUE + 1 - if there is an error in result set +*/ + +int read_stmt_results(MYSQL_STMT* stmt, + DYNAMIC_STRING* ds, + struct st_command *command) +{ + MYSQL_RES *res= NULL; + + /* + We instruct that we want to update the "max_length" field in + mysql_stmt_store_result(), this is our only way to know how much + buffer to allocate for result data + */ + { + my_bool one= 1; + if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one)) + die("mysql_stmt_attr_set(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s", + mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); + } + + /* + If we got here the statement succeeded and was expected to do so, + get data. Note that this can still give errors found during execution! + Store the result of the query if if will return any fields + */ + if (mysql_stmt_field_count(stmt) && mysql_stmt_store_result(stmt)) + { + handle_error(command, mysql_stmt_errno(stmt), + mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); + return 1; + } + + /* If we got here the statement was both executed and read successfully */ + handle_no_error(command); + if (!disable_result_log) + { + /* + Not all statements creates a result set. If there is one we can + now create another normal result set that contains the meta + data. This set can be handled almost like any other non prepared + statement result set. + */ + if ((res= mysql_stmt_result_metadata(stmt)) != NULL) + { + /* Take the column count from meta info */ + MYSQL_FIELD *fields= mysql_fetch_fields(res); + uint num_fields= mysql_num_fields(res); + + if (display_metadata) + append_metadata(ds, fields, num_fields); + + if (!display_result_vertically) + append_table_headings(ds, fields, num_fields); + + append_stmt_result(ds, stmt, fields, num_fields); + + mysql_free_result(res); /* Free normal result set with meta data */ + + } + else + { + /* + This is a query without resultset + */ + } + } + return 0; +} + /* Run query using prepared statement C API @@ -8287,11 +8371,17 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, char *query, size_t query_len, DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings) { - MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */ MYSQL *mysql= cn->mysql; MYSQL_STMT *stmt; DYNAMIC_STRING ds_prepare_warnings; DYNAMIC_STRING ds_execute_warnings; + DYNAMIC_STRING ds_res_1st_execution; + DYNAMIC_STRING ds_res_2_execution_unsorted; + DYNAMIC_STRING *ds_res_2_output; + my_bool ds_res_1st_execution_init = FALSE; + my_bool compare_2nd_execution = TRUE; + int query_match_ps2_re; + DBUG_ENTER("run_query_stmt"); DBUG_PRINT("query", ("'%-.60s'", query)); @@ -8318,6 +8408,12 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, init_dynamic_string(&ds_execute_warnings, NULL, 0, 256); } + /* Check and remove potential trash */ + if(strlen(ds->str) != 0) + { + dynstr_trunc(ds, 0); + } + /* Prepare the query */ @@ -8353,10 +8449,12 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, } #endif + query_match_ps2_re = match_re(&ps2_re, query); + /* Execute the query first time if second execution enable */ - if(ps2_protocol_enabled && match_re(&ps2_re, query)) + if(ps2_protocol_enabled && query_match_ps2_re) { if (do_stmt_execute(cn)) { @@ -8364,6 +8462,17 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); goto end; } + init_dynamic_string(&ds_res_1st_execution, "", + RESULT_STRING_INIT_MEM, RESULT_STRING_INCREMENT_MEM); + ds_res_1st_execution_init = TRUE; + if(read_stmt_results(stmt, &ds_res_1st_execution, command)) + { + /* + There was an error during execution + and there is no result set to compare + */ + compare_2nd_execution = 0; + } } /* @@ -8383,75 +8492,86 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, if (cursor_protocol_enabled && !disable_warnings) append_warnings(&ds_execute_warnings, mysql); - /* - We instruct that we want to update the "max_length" field in - mysql_stmt_store_result(), this is our only way to know how much - buffer to allocate for result data - */ + + DBUG_ASSERT(ds->length == 0); + + if (!disable_result_log && + compare_2nd_execution && + ps2_protocol_enabled && + query_match_ps2_re && + display_result_sorted) { - my_bool one= 1; - if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one)) - die("mysql_stmt_attr_set(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s", - mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); + init_dynamic_string(&ds_res_2_execution_unsorted, "", + RESULT_STRING_INIT_MEM, + RESULT_STRING_INCREMENT_MEM); + ds_res_2_output= &ds_res_2_execution_unsorted; + } + else + ds_res_2_output= ds; + + if(read_stmt_results(stmt, ds_res_2_output, command)) + { + if (ds_res_2_output != ds) + { + dynstr_append_mem(ds, ds_res_2_output->str, ds_res_2_output->length); + dynstr_free(ds_res_2_output); + } + goto end; } - /* - If we got here the statement succeeded and was expected to do so, - get data. Note that this can still give errors found during execution! - Store the result of the query if if will return any fields - */ - if (mysql_stmt_field_count(stmt) && mysql_stmt_store_result(stmt)) - { - handle_error(command, mysql_stmt_errno(stmt), - mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); - goto end; - } - - /* If we got here the statement was both executed and read successfully */ - handle_no_error(command); if (!disable_result_log) { /* - Not all statements creates a result set. If there is one we can - now create another normal result set that contains the meta - data. This set can be handled almost like any other non prepared - statement result set. + The results of the first and second execution are compared + only if result logging is enabled */ - if ((res= mysql_stmt_result_metadata(stmt)) != NULL) + if(compare_2nd_execution && ps2_protocol_enabled && query_match_ps2_re) { - /* Take the column count from meta info */ - MYSQL_FIELD *fields= mysql_fetch_fields(res); - uint num_fields= mysql_num_fields(res); - - if (display_metadata) - append_metadata(ds, fields, num_fields); - - if (!display_result_vertically) - append_table_headings(ds, fields, num_fields); - - append_stmt_result(ds, stmt, fields, num_fields); - - mysql_free_result(res); /* Free normal result set with meta data */ - - /* - Normally, if there is a result set, we do not show warnings from the - prepare phase. This is because some warnings are generated both during - prepare and execute; this would generate different warning output - between normal and ps-protocol test runs. - - The --enable_prepare_warnings command can be used to change this so - that warnings from both the prepare and execute phase are shown. - */ - if (!disable_warnings && !prepare_warnings_enabled) - dynstr_set(&ds_prepare_warnings, NULL); - } - else - { - /* - This is a query without resultset - */ + DYNAMIC_STRING *ds_res_1_execution_compare; + DYNAMIC_STRING ds_res_1_execution_sorted; + if (display_result_sorted) + { + init_dynamic_string(&ds_res_1_execution_sorted, "", + RESULT_STRING_INIT_MEM, + RESULT_STRING_INCREMENT_MEM); + dynstr_append_sorted(&ds_res_1_execution_sorted, + &ds_res_1st_execution, 1); + dynstr_append_sorted(ds, &ds_res_2_execution_unsorted, 1); + ds_res_1_execution_compare= &ds_res_1_execution_sorted; + } + else + { + ds_res_1_execution_compare= &ds_res_1st_execution; + } + if(ds->length != ds_res_1_execution_compare->length || + !(memcmp(ds_res_1_execution_compare->str, ds->str, ds->length) == 0)) + { + die("The result of the 1st execution does not match with \n" + "the result of the 2nd execution of ps-protocol:\n 1st:\n" + "%s\n 2nd:\n %s", + ds_res_1_execution_compare->str, + ds->str); + } + if (display_result_sorted) + { + dynstr_free(&ds_res_1_execution_sorted); + dynstr_free(&ds_res_2_execution_unsorted); + } } + /* + Normally, if there is a result set, we do not show warnings from the + prepare phase. This is because some warnings are generated both during + prepare and execute; this would generate different warning output + between normal and ps-protocol test runs. + The --enable_prepare_warnings command can be used to change this so + that warnings from both the prepare and execute phase are shown. + */ + if ((mysql_stmt_result_metadata(stmt) != NULL) && + !disable_warnings && + !prepare_warnings_enabled) + dynstr_set(&ds_prepare_warnings, NULL); + /* Fetch info before fetching warnings, since it will be reset otherwise. @@ -8462,7 +8582,6 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, if (display_session_track_info) append_session_track_info(ds, mysql); - if (!disable_warnings) { /* Get the warnings from execute */ @@ -8488,6 +8607,13 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, } end: + + if (ds_res_1st_execution_init) + { + dynstr_free(&ds_res_1st_execution); + ds_res_1st_execution_init= FALSE; + } + if (!disable_warnings) { dynstr_free(&ds_prepare_warnings); @@ -9675,7 +9801,7 @@ int main(int argc, char **argv) read_command_buf= (char*)my_malloc(read_command_buflen= 65536, MYF(MY_FAE)); - init_dynamic_string(&ds_res, "", 2048, 2048); + init_dynamic_string(&ds_res, "", RESULT_STRING_INIT_MEM, RESULT_STRING_INCREMENT_MEM); init_alloc_root(&require_file_root, "require_file", 1024, 1024, MYF(0)); parse_args(argc, argv); From ad796aaa943557b26d0905feb897342f89ebdfd3 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 22 Nov 2023 13:58:03 +0100 Subject: [PATCH 311/477] Remove unneeded strlen() calls. --- client/mysqltest.cc | 86 +++++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 0483cd4e212..d3af3c216a9 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1719,7 +1719,7 @@ void log_msg(const char *fmt, ...) va_end(args); dynstr_append_mem(&ds_res, buff, len); - dynstr_append(&ds_res, "\n"); + dynstr_append_mem(&ds_res, STRING_WITH_LEN("\n")); DBUG_VOID_RETURN; } @@ -1854,7 +1854,7 @@ static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...) die("Out of memory"); dynstr_append_os_quoted(&ds_cmdline, tool_path, NullS); - dynstr_append(&ds_cmdline, " "); + dynstr_append_mem(&ds_cmdline, STRING_WITH_LEN(" ")); va_start(args, ds_res); @@ -1865,13 +1865,13 @@ static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...) dynstr_append_os_quoted(&ds_cmdline, arg, NullS); else dynstr_append(&ds_cmdline, arg); - dynstr_append(&ds_cmdline, " "); + dynstr_append_mem(&ds_cmdline, STRING_WITH_LEN(" ")); } va_end(args); #ifdef _WIN32 - dynstr_append(&ds_cmdline, "\""); + dynstr_append_mem(&ds_cmdline, STRING_WITH_LEN("\"")); #endif DBUG_PRINT("info", ("Running: %s", ds_cmdline.str)); @@ -2006,8 +2006,8 @@ void show_diff(DYNAMIC_STRING* ds, Fallback to dump both files to result file and inform about installing "diff" */ - dynstr_append(&ds_tmp, "\n"); - dynstr_append(&ds_tmp, + char message[]= +"\n" "\n" "The two files differ but it was not possible to execute 'diff' in\n" "order to show only the difference. Instead the whole content of the\n" @@ -2017,17 +2017,18 @@ void show_diff(DYNAMIC_STRING* ds, #ifdef _WIN32 "or http://gnuwin32.sourceforge.net/packages/diffutils.htm\n" #endif -"\n"); +"\n"; + dynstr_append_mem(&ds_tmp, message, sizeof(message)); - dynstr_append(&ds_tmp, " --- "); + dynstr_append_mem(&ds_tmp, STRING_WITH_LEN(" --- ")); dynstr_append(&ds_tmp, filename1); - dynstr_append(&ds_tmp, " >>>\n"); + dynstr_append_mem(&ds_tmp, STRING_WITH_LEN(" >>>\n")); cat_file(&ds_tmp, filename1); - dynstr_append(&ds_tmp, "<<<\n --- "); + dynstr_append_mem(&ds_tmp, STRING_WITH_LEN("<<<\n --- ")); dynstr_append(&ds_tmp, filename1); - dynstr_append(&ds_tmp, " >>>\n"); + dynstr_append_mem(&ds_tmp, STRING_WITH_LEN(" >>>\n")); cat_file(&ds_tmp, filename2); - dynstr_append(&ds_tmp, "<<<<\n"); + dynstr_append_mem(&ds_tmp, STRING_WITH_LEN("<<<<\n")); } if (ds) @@ -2806,9 +2807,9 @@ do_result_format_version(struct st_command *command) set_result_format_version(version); - dynstr_append(&ds_res, "result_format: "); + dynstr_append_mem(&ds_res, STRING_WITH_LEN("result_format: ")); dynstr_append_mem(&ds_res, ds_version.str, ds_version.length); - dynstr_append(&ds_res, "\n"); + dynstr_append_mem(&ds_res, STRING_WITH_LEN("\n")); dynstr_free(&ds_version); } @@ -3355,7 +3356,7 @@ void do_exec(struct st_command *command) if (disable_result_log) { /* Collect stderr output as well, for the case app. crashes or returns error.*/ - dynstr_append(&ds_cmd, " 2>&1"); + dynstr_append_mem(&ds_cmd, STRING_WITH_LEN(" 2>&1")); } DBUG_PRINT("info", ("Executing '%s' as '%s'", @@ -3557,9 +3558,9 @@ void do_system(struct st_command *command) else { /* If ! abort_on_error, log message and continue */ - dynstr_append(&ds_res, "system command '"); + dynstr_append_mem(&ds_res, STRING_WITH_LEN("system command '")); replace_dynstr_append(&ds_res, command->first_argument); - dynstr_append(&ds_res, "' failed\n"); + dynstr_append_mem(&ds_res, STRING_WITH_LEN("' failed\n")); } } @@ -4026,7 +4027,7 @@ static int get_list_files(DYNAMIC_STRING *ds, const DYNAMIC_STRING *ds_dirname, wild_compare(file->name, ds_wild->str, 0)) continue; replace_dynstr_append(ds, file->name); - dynstr_append(ds, "\n"); + dynstr_append_mem(ds, STRING_WITH_LEN("\n")); } set_wild_chars(0); my_dirend(dir_info); @@ -7684,9 +7685,10 @@ void append_metadata(DYNAMIC_STRING *ds, uint num_fields) { MYSQL_FIELD *field_end; - dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t" - "Column_alias\tType\tLength\tMax length\tIs_null\t" - "Flags\tDecimals\tCharsetnr\n"); + dynstr_append_mem(ds, STRING_WITH_LEN( + "Catalog\tDatabase\tTable\tTable_alias\tColumn\t" + "Column_alias\tType\tLength\tMax length\tIs_null\t" + "Flags\tDecimals\tCharsetnr\n")); for (field_end= field+num_fields ; field < field_end ; @@ -7738,9 +7740,9 @@ void append_info(DYNAMIC_STRING *ds, ulonglong affected_rows, dynstr_append(ds, buf); if (info) { - dynstr_append(ds, "info: "); + dynstr_append_mem(ds, STRING_WITH_LEN("info: ")); dynstr_append(ds, info); - dynstr_append_mem(ds, "\n", 1); + dynstr_append_mem(ds, STRING_WITH_LEN("\n")); } } @@ -7764,34 +7766,41 @@ static void append_session_track_info(DYNAMIC_STRING *ds, MYSQL *mysql) (enum_session_state_type) type, &data, &data_length)) { - dynstr_append(ds, "-- "); + dynstr_append_mem(ds, STRING_WITH_LEN("-- ")); switch (type) { case SESSION_TRACK_SYSTEM_VARIABLES: - dynstr_append(ds, "Tracker : SESSION_TRACK_SYSTEM_VARIABLES\n"); + dynstr_append_mem(ds, STRING_WITH_LEN( + "Tracker : SESSION_TRACK_SYSTEM_VARIABLES\n")); break; case SESSION_TRACK_SCHEMA: - dynstr_append(ds, "Tracker : SESSION_TRACK_SCHEMA\n"); + dynstr_append_mem(ds, STRING_WITH_LEN( + "Tracker : SESSION_TRACK_SCHEMA\n")); break; case SESSION_TRACK_STATE_CHANGE: - dynstr_append(ds, "Tracker : SESSION_TRACK_STATE_CHANGE\n"); + dynstr_append_mem(ds, STRING_WITH_LEN( + "Tracker : SESSION_TRACK_STATE_CHANGE\n")); break; case SESSION_TRACK_GTIDS: - dynstr_append(ds, "Tracker : SESSION_TRACK_GTIDS\n"); + dynstr_append_mem(ds, STRING_WITH_LEN( + "Tracker : SESSION_TRACK_GTIDS\n")); break; case SESSION_TRACK_TRANSACTION_CHARACTERISTICS: - dynstr_append(ds, "Tracker : SESSION_TRACK_TRANSACTION_CHARACTERISTICS\n"); + dynstr_append_mem(ds, STRING_WITH_LEN( + "Tracker : " + "SESSION_TRACK_TRANSACTION_CHARACTERISTICS\n")); break; case SESSION_TRACK_TRANSACTION_TYPE: - dynstr_append(ds, "Tracker : SESSION_TRACK_TRANSACTION_TYPE\n"); + dynstr_append_mem(ds, STRING_WITH_LEN( + "Tracker : SESSION_TRACK_TRANSACTION_TYPE\n")); break; default: DBUG_ASSERT(0); - dynstr_append(ds, "\n"); + dynstr_append_mem(ds, STRING_WITH_LEN("\n")); } - dynstr_append(ds, "-- "); + dynstr_append_mem(ds, STRING_WITH_LEN("-- ")); dynstr_append_mem(ds, data, data_length); } else @@ -7800,10 +7809,10 @@ static void append_session_track_info(DYNAMIC_STRING *ds, MYSQL *mysql) (enum_session_state_type) type, &data, &data_length)) { - dynstr_append(ds, "\n-- "); + dynstr_append_mem(ds, STRING_WITH_LEN("\n-- ")); dynstr_append_mem(ds, data, data_length); } - dynstr_append(ds, "\n\n"); + dynstr_append_mem(ds, STRING_WITH_LEN("\n\n")); } #endif /* EMBEDDED_LIBRARY */ } @@ -8198,7 +8207,8 @@ void handle_error(struct st_command *command, else if (command->expected_errors.err[0].type == ERR_SQLSTATE || (command->expected_errors.err[0].type == ERR_ERRNO && command->expected_errors.err[0].code.errnum != 0)) - dynstr_append(ds,"Got one of the listed errors\n"); + dynstr_append_mem(ds, STRING_WITH_LEN("Got one of the listed " + "errors\n")); } /* OK */ revert_properties(); @@ -10232,7 +10242,7 @@ int main(int argc, char **argv) if (p && *p == '#' && *(p+1) == '#') { dynstr_append_mem(&ds_res, command->query, command->query_len); - dynstr_append(&ds_res, "\n"); + dynstr_append_mem(&ds_res, STRING_WITH_LEN("\n")); } break; } @@ -10245,7 +10255,7 @@ int main(int argc, char **argv) if (disable_query_log) break; - dynstr_append(&ds_res, "\n"); + dynstr_append_mem(&ds_res, STRING_WITH_LEN("\n")); break; case Q_PING: handle_command_error(command, mysql_ping(cur_con->mysql), -1); @@ -11886,7 +11896,7 @@ void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input, { const char **line= dynamic_element(&lines, i, const char**); dynstr_append(ds, *line); - dynstr_append(ds, "\n"); + dynstr_append_mem(ds, STRING_WITH_LEN("\n")); } delete_dynamic(&lines); From 64f44b22d9a3dab3d4c0b77addbcbdafde57b466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 23 Nov 2023 15:09:26 +0200 Subject: [PATCH 312/477] MDEV-31574: Assertion failure on REPLACE on ROW_FORMAT=COMPRESSED table btr_cur_update_in_place(): Update the DB_TRX_ID,DB_ROLL_PTR also on the compressed copy of the page. In a test case, a server built with cmake -DWITH_INNODB_EXTRA_DEBUG=ON would crash in page_zip_validate() due to the inconsistency. In a normal debug build, a different assertion would fail, depending on when the uncompressed page was restored from the compressed page. In MariaDB Server 10.5, this bug had already been fixed by commit b3d02a1fcf837a8ca0b3aaff20fbfecfe744c477 (MDEV-12353). --- storage/innobase/btr/btr0cur.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 0f6cdf25ca2..38bbf2d1bc1 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -4338,7 +4338,7 @@ btr_cur_update_in_place( } if (!(flags & BTR_KEEP_SYS_FLAG)) { - row_upd_rec_sys_fields(rec, NULL, index, offsets, + row_upd_rec_sys_fields(rec, page_zip, index, offsets, thr_get_trx(thr), roll_ptr); } From 90f8bd1496858a92fdbbe778c3133dda5cf22314 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 23 Nov 2023 14:35:34 +0100 Subject: [PATCH 313/477] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index faa3580edd1..eec275763bb 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=11 MYSQL_VERSION_MINOR=3 -MYSQL_VERSION_PATCH=1 +MYSQL_VERSION_PATCH=2 SERVER_MATURITY=gamma From ed0ab6e1893fe30e30bc08745098d6f323c6aca8 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 24 Nov 2023 14:19:14 +1100 Subject: [PATCH 314/477] MDEV-27575 Add sleeping statement spider/bugfix.mdev_27575 This could help prevent race condition when shutting down the server not long after loading spider. Thus only needed for 10.4-10.6. --- storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result | 6 ++++++ storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test | 2 ++ 2 files changed, 8 insertions(+) diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result index 91af2c8f1e0..f0a720c5b57 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result @@ -5,8 +5,14 @@ for master_1 for child2 for child3 SET GLOBAL default_tmp_storage_engine=spider; +SELECT SLEEP(1); +SLEEP(1) +0 # restart SET GLOBAL default_storage_engine=Spider; +SELECT SLEEP(1); +SLEEP(1) +0 # restart for master_1 for child2 diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test index 79a08489bae..a7a3209ec77 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test @@ -8,9 +8,11 @@ --enable_query_log SET GLOBAL default_tmp_storage_engine=spider; +SELECT SLEEP(1); --source include/restart_mysqld.inc SET GLOBAL default_storage_engine=Spider; +SELECT SLEEP(1); --source include/restart_mysqld.inc --disable_query_log From 1a76d751c56789d0de0d8509c203ecb5e0b36230 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 15 Nov 2023 12:38:43 +1100 Subject: [PATCH 315/477] MDEV-32804 Remove references to spider_rewrite_plugin tables They are not used. The code paths are never reached. --- .../mysql-test/spider/include/init_spider.inc | 21 ----- storage/spider/spd_sys_table.cc | 88 ------------------- storage/spider/spd_sys_table.h | 15 ---- 3 files changed, 124 deletions(-) diff --git a/storage/spider/mysql-test/spider/include/init_spider.inc b/storage/spider/mysql-test/spider/include/init_spider.inc index 69d1fae425e..d2d1c03494c 100644 --- a/storage/spider/mysql-test/spider/include/init_spider.inc +++ b/storage/spider/mysql-test/spider/include/init_spider.inc @@ -139,27 +139,6 @@ let $PLUGIN_VERSION= `SELECT SUBSTRING_INDEX(plugin_version, '.', 1) FROM information_schema.plugins WHERE plugin_name = 'SPIDER'`; -if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) -{ - let $HAS_REWRITE= - `SELECT IF (STRCMP('$SERVER_NAME', 'MariaDB') = 0, - IF ($SERVER_MAJOR_VERSION = 10, - IF ($SERVER_MINOR_VERSION < 4, 0, 1), - IF ($SERVER_MAJOR_VERSION < 10, 0, 1)), - 0)`; - let $HAS_REWRITE= 0; - if ($HAS_REWRITE) - { - let $PLUGIN_NAME= spider_flush_rewrite_cache; - let $PLUGIN_EXIST= - `SELECT COUNT(*) FROM mysql.func WHERE name = '$PLUGIN_NAME'`; - while (!$PLUGIN_EXIST) - { - let $PLUGIN_EXIST= - `SELECT COUNT(*) FROM mysql.func WHERE name = '$PLUGIN_NAME'`; - } - } -} let $PLUGIN_NAME= spider_flush_table_mon_cache; let $PLUGIN_EXIST= `SELECT COUNT(*) FROM mysql.func WHERE name = '$PLUGIN_NAME'`; diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc index c5abf7b0b3b..c84e4250c40 100644 --- a/storage/spider/spd_sys_table.cc +++ b/storage/spider/spd_sys_table.cc @@ -339,24 +339,6 @@ TABLE *spider_open_sys_table( } DBUG_ASSERT(0); break; - case 21: - if (!memcmp(table_name, SPIDER_SYS_RW_TBLS_TABLE_NAME_STR, - SPIDER_SYS_RW_TBLS_TABLE_NAME_LEN)) - { - DBUG_PRINT("info",("spider checking for SYS_RW_TBLS")); - if (table->s->fields != SPIDER_SYS_RW_TBLS_COL_CNT) - { - spider_close_sys_table(thd, table, open_tables_backup, need_lock); - table = NULL; - my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM, - ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0), - SPIDER_SYS_RW_TBLS_TABLE_NAME_STR); - *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM; - goto error_col_num_chk; - } - } - DBUG_ASSERT(0); - break; case 22: if (!memcmp(table_name, SPIDER_SYS_LINK_FAILED_TABLE_NAME_STR, SPIDER_SYS_LINK_FAILED_TABLE_NAME_LEN)) @@ -393,60 +375,6 @@ TABLE *spider_open_sys_table( } break; } - if (!memcmp(table_name, SPIDER_SYS_RWN_TBLS_TABLE_NAME_STR, - SPIDER_SYS_RWN_TBLS_TABLE_NAME_LEN)) - { - DBUG_PRINT("info",("spider checking for SYS_RWN_TBLS")); - if (table->s->fields != SPIDER_SYS_RWN_TBLS_COL_CNT) - { - spider_close_sys_table(thd, table, open_tables_backup, need_lock); - table = NULL; - my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM, - ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0), - SPIDER_SYS_RWN_TBLS_TABLE_NAME_STR); - *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM; - goto error_col_num_chk; - } - break; - } - DBUG_ASSERT(0); - break; - case 27: - if (!memcmp(table_name, SPIDER_SYS_RW_TBL_TBLS_TABLE_NAME_STR, - SPIDER_SYS_RW_TBL_TBLS_TABLE_NAME_LEN)) - { - DBUG_PRINT("info",("spider checking for SYS_RW_TBL_TBLS")); - if (table->s->fields != SPIDER_SYS_RW_TBL_TBLS_COL_CNT) - { - spider_close_sys_table(thd, table, open_tables_backup, need_lock); - table = NULL; - my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM, - ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0), - SPIDER_SYS_RW_TBL_TBLS_TABLE_NAME_STR); - *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM; - goto error_col_num_chk; - } - break; - } - DBUG_ASSERT(0); - break; - case 31: - if (!memcmp(table_name, SPIDER_SYS_RW_TBL_PTTS_TABLE_NAME_STR, - SPIDER_SYS_RW_TBL_PTTS_TABLE_NAME_LEN)) - { - DBUG_PRINT("info",("spider checking for SYS_RW_TBL_PTTS")); - if (table->s->fields != SPIDER_SYS_RW_TBL_PTTS_COL_CNT) - { - spider_close_sys_table(thd, table, open_tables_backup, need_lock); - table = NULL; - my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM, - ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0), - SPIDER_SYS_RW_TBL_PTTS_TABLE_NAME_STR); - *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM; - goto error_col_num_chk; - } - break; - } DBUG_ASSERT(0); break; case 34: @@ -466,22 +394,6 @@ TABLE *spider_open_sys_table( } break; } - if (!memcmp(table_name, SPIDER_SYS_RW_TBL_SPTTS_TABLE_NAME_STR, - SPIDER_SYS_RW_TBL_SPTTS_TABLE_NAME_LEN)) - { - DBUG_PRINT("info",("spider checking for SYS_RW_TBL_SPTTS")); - if (table->s->fields != SPIDER_SYS_RW_TBL_SPTTS_COL_CNT) - { - spider_close_sys_table(thd, table, open_tables_backup, need_lock); - table = NULL; - my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM, - ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0), - SPIDER_SYS_RW_TBL_SPTTS_TABLE_NAME_STR); - *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM; - goto error_col_num_chk; - } - break; - } DBUG_ASSERT(0); break; default: diff --git a/storage/spider/spd_sys_table.h b/storage/spider/spd_sys_table.h index df933ec61b8..90ed5811cd1 100644 --- a/storage/spider/spd_sys_table.h +++ b/storage/spider/spd_sys_table.h @@ -32,16 +32,6 @@ #define SPIDER_SYS_TABLE_STS_TABLE_NAME_LEN 16 #define SPIDER_SYS_TABLE_CRD_TABLE_NAME_STR "spider_table_crd" #define SPIDER_SYS_TABLE_CRD_TABLE_NAME_LEN 16 -#define SPIDER_SYS_RW_TBLS_TABLE_NAME_STR "spider_rewrite_tables" -#define SPIDER_SYS_RW_TBLS_TABLE_NAME_LEN 21 -#define SPIDER_SYS_RW_TBL_TBLS_TABLE_NAME_STR "spider_rewrite_table_tables" -#define SPIDER_SYS_RW_TBL_TBLS_TABLE_NAME_LEN 27 -#define SPIDER_SYS_RW_TBL_PTTS_TABLE_NAME_STR "spider_rewrite_table_partitions" -#define SPIDER_SYS_RW_TBL_PTTS_TABLE_NAME_LEN 31 -#define SPIDER_SYS_RW_TBL_SPTTS_TABLE_NAME_STR "spider_rewrite_table_subpartitions" -#define SPIDER_SYS_RW_TBL_SPTTS_TABLE_NAME_LEN 34 -#define SPIDER_SYS_RWN_TBLS_TABLE_NAME_STR "spider_rewritten_tables" -#define SPIDER_SYS_RWN_TBLS_TABLE_NAME_LEN 23 #define SPIDER_SYS_XA_PREPARED_STR "PREPARED" #define SPIDER_SYS_XA_NOT_YET_STR "NOT YET" @@ -65,11 +55,6 @@ #define SPIDER_SYS_TABLE_STS_PK_COL_CNT 2 #define SPIDER_SYS_TABLE_CRD_COL_CNT 4 #define SPIDER_SYS_TABLE_CRD_PK_COL_CNT 3 -#define SPIDER_SYS_RW_TBLS_COL_CNT 3 -#define SPIDER_SYS_RW_TBL_TBLS_COL_CNT 8 -#define SPIDER_SYS_RW_TBL_PTTS_COL_CNT 7 -#define SPIDER_SYS_RW_TBL_SPTTS_COL_CNT 8 -#define SPIDER_SYS_RWN_TBLS_COL_CNT 4 #define SPIDER_SYS_LINK_MON_TABLE_DB_NAME_SIZE 64 #define SPIDER_SYS_LINK_MON_TABLE_TABLE_NAME_SIZE 64 From bdfd93d30c1bba2a8932477f16f6280ee665d818 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 24 Nov 2023 16:30:54 +1100 Subject: [PATCH 316/477] MDEV-28739 MDEV-29421 Remove spider persistent table stats We remove the call to update spider persistent table stats (sts/crd) in spider_free_share(). This prevents spider from opening and closing further tables during close(), which fixes the following issues: MDEV-28739: ha_spider::close() is called during tdc_start_shutdown(), which is called after query_cache_destroy(). Closing the sts/crd Aria tables will trigger a call to Query_cache::invalidate_table(), which will attempt to use the query cache mutex structure_guard_mutex destroyed previously. MDEV-29421: during ha_spider::close(), spider_free_share() could trigger another spider_free_share() through updating sts/crd table, because open_table() calls tc_add_table(), which could trigger another ha_spider::close()... Since spider sts/crd system tables are only updated here, there's no use for these tables any more, and we remove all uses of these tables too. The removal should not cause any performance issue, as in memory spider table stats are only updated based on a time interval (spider_sts_interval and spider_crd_interval), which defaults to 10 seconds. It should not affect accuracy either, due to the infrequency of server restart. And inaccurate stats are not a problem for optimizer anyway. To be on the safe side, we defer the removal of the spider sts/crd tables themselves to future. --- storage/spider/ha_spider.cc | 6 - .../include/spider_table_sts_deinit.inc | 12 - .../bugfix/include/spider_table_sts_init.inc | 13 - .../spider/bugfix/r/mdev_27575.result | 8 +- .../spider/bugfix/r/mdev_28739.result | 34 ++ .../spider/bugfix/r/mdev_29421.result | 19 + .../spider/bugfix/r/spider_table_sts.result | 38 -- .../spider/bugfix/t/mdev_27575.test | 6 +- .../{spider_table_sts.cnf => mdev_28739.cnf} | 1 + .../spider/bugfix/t/mdev_28739.test | 41 ++ .../spider/bugfix/t/mdev_28739_simple.test | 30 ++ .../spider/bugfix/t/mdev_29421.test | 26 + .../spider/bugfix/t/spider_table_sts.test | 46 -- storage/spider/spd_sys_table.cc | 491 ------------------ storage/spider/spd_sys_table.h | 78 --- storage/spider/spd_table.cc | 104 +--- 16 files changed, 164 insertions(+), 789 deletions(-) delete mode 100644 storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_deinit.inc delete mode 100644 storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_init.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_28739.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_29421.result delete mode 100644 storage/spider/mysql-test/spider/bugfix/r/spider_table_sts.result rename storage/spider/mysql-test/spider/bugfix/t/{spider_table_sts.cnf => mdev_28739.cnf} (71%) create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_28739.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_29421.test delete mode 100644 storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.test diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index f037477ecad..3cfbae34198 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -11965,12 +11965,6 @@ int ha_spider::delete_table( ) need_lock = TRUE; - if ((error_num = spider_sys_delete_table_sts( - current_thd, name, name_len, need_lock))) - goto error; - if ((error_num = spider_sys_delete_table_crd( - current_thd, name, name_len, need_lock))) - goto error; if ( !(table_tables = spider_open_sys_table( current_thd, SPIDER_SYS_TABLES_TABLE_NAME_STR, diff --git a/storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_deinit.inc deleted file mode 100644 index 01645e85f32..00000000000 --- a/storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_deinit.inc +++ /dev/null @@ -1,12 +0,0 @@ ---connection master_1 -alter table mysql.spider_table_sts add column checksum bigint unsigned default null after update_time; -DROP DATABASE IF EXISTS auto_test_local; - ---let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP ---disable_warnings ---disable_query_log ---disable_result_log ---source ../t/test_deinit.inc ---enable_result_log ---enable_query_log ---enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_init.inc b/storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_init.inc deleted file mode 100644 index 1e438812af7..00000000000 --- a/storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_init.inc +++ /dev/null @@ -1,13 +0,0 @@ ---disable_warnings ---disable_query_log ---disable_result_log ---source ../t/test_init.inc ---enable_result_log ---enable_query_log ---enable_warnings ---let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 -let $MASTER_1_COMMENT_2_1= - COMMENT='table "tbl_a", host "127.0.0.1", port "$MASTER_1_MYPORT", user "root"'; ---connection master_1 -alter table mysql.spider_table_sts drop column checksum; -insert into mysql.spider_table_sts values ('auto_test_local', 'tbl_a', 0, 0, 0, 0, 0, '2019-01-01 00:00:00', '2019-01-01 00:00:00', '2019-01-01 00:00:00'); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result index f0a720c5b57..4899f191ada 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result @@ -4,15 +4,11 @@ for master_1 for child2 for child3 +call mtr.add_suppression("\\[ERROR\\] Table 'mysql.spider_table_sts' doesn't exist"); +call mtr.add_suppression("\\[ERROR\\] Server shutdown in progress"); SET GLOBAL default_tmp_storage_engine=spider; -SELECT SLEEP(1); -SLEEP(1) -0 # restart SET GLOBAL default_storage_engine=Spider; -SELECT SLEEP(1); -SLEEP(1) -0 # restart for master_1 for child2 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28739.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28739.result new file mode 100644 index 00000000000..ee497bb3e1e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28739.result @@ -0,0 +1,34 @@ +# +# MDEV-28739 Trying to lock uninitialized mutex or hang upon shutdown after using Spider with query_cache +# +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +connection child2_1; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +CREATE TABLE tbl_a (id INT); +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +set global query_cache_type= on; +set spider_same_server_link = on; +CREATE TABLE tbl_a ( +id INT +) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='table "tbl_a", srv "s_2_1"'; +SELECT * FROM tbl_a; +id +# restart +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29421.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29421.result new file mode 100644 index 00000000000..bcbf050d142 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29421.result @@ -0,0 +1,19 @@ +for master_1 +for child2 +for child3 +set @old_table_open_cache=@@global.table_open_cache; +set global table_open_cache=10; +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE TABLE t (c INT) ENGINE=InnoDB; +CREATE TABLE t_s (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv", TABLE "t"'; +CREATE TABLE t1 (a INT) ENGINE=Spider; +SELECT * FROM t1; +ERROR HY000: Unable to connect to foreign data source: localhost +SELECT * FROM information_schema.tables; +DROP TABLE t, t_s, t1; +drop server srv; +set global table_open_cache=@old_table_open_cache; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/spider_table_sts.result b/storage/spider/mysql-test/spider/bugfix/r/spider_table_sts.result deleted file mode 100644 index f915cc951b1..00000000000 --- a/storage/spider/mysql-test/spider/bugfix/r/spider_table_sts.result +++ /dev/null @@ -1,38 +0,0 @@ -for master_1 -for child2 -for child3 -connection master_1; -alter table mysql.spider_table_sts drop column checksum; -insert into mysql.spider_table_sts values ('auto_test_local', 'tbl_a', 0, 0, 0, 0, 0, '2019-01-01 00:00:00', '2019-01-01 00:00:00', '2019-01-01 00:00:00'); - -this test is for MDEV-19842 - -drop and create databases -connection master_1; -CREATE DATABASE auto_test_local; -USE auto_test_local; - -create table -connection master_1; -CREATE TABLE tbl_a ( -pkey int NOT NULL, -PRIMARY KEY (pkey) -) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 - -select test 1 -connection master_1; -SELECT pkey FROM tbl_a; -ERROR HY000: System table spider_table_sts is different version - -deinit -connection master_1; -DROP DATABASE IF EXISTS auto_test_local; -ERROR HY000: System table spider_table_sts is different version -connection master_1; -alter table mysql.spider_table_sts add column checksum bigint unsigned default null after update_time; -DROP DATABASE IF EXISTS auto_test_local; -for master_1 -for child2 -for child3 - -end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test index a7a3209ec77..6f291c6f690 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test @@ -7,12 +7,14 @@ --enable_result_log --enable_query_log +# These suppressions are a workaround and should not be needed once +# MDEV-29870 is done. +call mtr.add_suppression("\\[ERROR\\] Table 'mysql.spider_table_sts' doesn't exist"); +call mtr.add_suppression("\\[ERROR\\] Server shutdown in progress"); SET GLOBAL default_tmp_storage_engine=spider; -SELECT SLEEP(1); --source include/restart_mysqld.inc SET GLOBAL default_storage_engine=Spider; -SELECT SLEEP(1); --source include/restart_mysqld.inc --disable_query_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.cnf b/storage/spider/mysql-test/spider/bugfix/t/mdev_28739.cnf similarity index 71% rename from storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.cnf rename to storage/spider/mysql-test/spider/bugfix/t/mdev_28739.cnf index b0853e32654..05dfd8a0bce 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.cnf +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28739.cnf @@ -1,2 +1,3 @@ !include include/default_mysqld.cnf !include ../my_1_1.cnf +!include ../my_2_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28739.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28739.test new file mode 100644 index 00000000000..d4ac8e42d86 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28739.test @@ -0,0 +1,41 @@ +--echo # +--echo # MDEV-28739 Trying to lock uninitialized mutex or hang upon shutdown after using Spider with query_cache +--echo # + +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +--connection child2_1 +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +CREATE TABLE tbl_a (id INT); + +--connection master_1 +CREATE DATABASE auto_test_local; +USE auto_test_local; + +set global query_cache_type= on; +set spider_same_server_link = on; + +eval CREATE TABLE tbl_a ( + id INT +) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='table "tbl_a", srv "s_2_1"'; + +SELECT * FROM tbl_a; + +--source include/restart_mysqld.inc + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; + +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_query_log +--enable_result_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test new file mode 100644 index 00000000000..7a011520bb6 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test @@ -0,0 +1,30 @@ +--echo # +--echo # MDEV-28739 Trying to lock uninitialized mutex or hang upon shutdown after using Spider with query_cache +--echo # + +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +# set @@global.debug_dbug="+d,xid_thd_trace,enter,exit,info,error:o,/tmp/trace2.out:i:F:L"; +#set @@global.debug_dbug="d:t:i:o,mysqld.trace"; + +set global query_cache_type= on; +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +SELECT * FROM t1; +#shutdown; +--source include/restart_mysqld.inc +drop table t1, t2; +drop server srv; + +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_query_log +--enable_result_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29421.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29421.test new file mode 100644 index 00000000000..47ad42d3d92 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29421.test @@ -0,0 +1,26 @@ +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log +set @old_table_open_cache=@@global.table_open_cache; +set global table_open_cache=10; +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE TABLE t (c INT) ENGINE=InnoDB; +CREATE TABLE t_s (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv", TABLE "t"'; +CREATE TABLE t1 (a INT) ENGINE=Spider; +--error 1429 +SELECT * FROM t1; +--disable_result_log +SELECT * FROM information_schema.tables; +--enable_result_log +DROP TABLE t, t_s, t1; +drop server srv; +set global table_open_cache=@old_table_open_cache; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.test b/storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.test deleted file mode 100644 index 7213017505b..00000000000 --- a/storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.test +++ /dev/null @@ -1,46 +0,0 @@ ---source ../include/spider_table_sts_init.inc ---echo ---echo this test is for MDEV-19842 ---echo ---echo drop and create databases - ---connection master_1 ---disable_warnings -CREATE DATABASE auto_test_local; -USE auto_test_local; ---enable_warnings - ---echo ---echo create table - ---connection master_1 ---disable_query_log -echo CREATE TABLE tbl_a ( - pkey int NOT NULL, - PRIMARY KEY (pkey) -) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; -eval CREATE TABLE tbl_a ( - pkey int NOT NULL, - PRIMARY KEY (pkey) -) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; ---enable_query_log - ---echo ---echo select test 1 - ---connection master_1 ---error 12609 -SELECT pkey FROM tbl_a; - ---echo ---echo deinit ---disable_warnings - ---connection master_1 ---error 12609 -DROP DATABASE IF EXISTS auto_test_local; - ---enable_warnings ---source ../include/spider_table_sts_deinit.inc ---echo ---echo end of test diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc index c84e4250c40..f33a5373168 100644 --- a/storage/spider/spd_sys_table.cc +++ b/storage/spider/spd_sys_table.cc @@ -286,38 +286,6 @@ TABLE *spider_open_sys_table( } break; } - if (!memcmp(table_name, SPIDER_SYS_TABLE_STS_TABLE_NAME_STR, - SPIDER_SYS_TABLE_STS_TABLE_NAME_LEN)) - { - DBUG_PRINT("info",("spider checking for SYS_TABLE_STS")); - if (table->s->fields != SPIDER_SYS_TABLE_STS_COL_CNT) - { - spider_close_sys_table(thd, table, open_tables_backup, need_lock); - table = NULL; - my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM, - ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0), - SPIDER_SYS_TABLE_STS_TABLE_NAME_STR); - *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM; - goto error_col_num_chk; - } - break; - } - if (!memcmp(table_name, SPIDER_SYS_TABLE_CRD_TABLE_NAME_STR, - SPIDER_SYS_TABLE_CRD_TABLE_NAME_LEN)) - { - DBUG_PRINT("info",("spider checking for SYS_TABLE_CRD")); - if (table->s->fields != SPIDER_SYS_TABLE_CRD_COL_CNT) - { - spider_close_sys_table(thd, table, open_tables_backup, need_lock); - table = NULL; - my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM, - ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0), - SPIDER_SYS_TABLE_CRD_TABLE_NAME_STR); - *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM; - goto error_col_num_chk; - } - break; - } DBUG_ASSERT(0); break; case 20: @@ -1329,45 +1297,6 @@ void spider_store_binlog_pos_gtid( DBUG_VOID_RETURN; } -void spider_store_table_sts_info( - TABLE *table, - ha_statistics *stat -) { - MYSQL_TIME mysql_time; - DBUG_ENTER("spider_store_table_sts_info"); - table->field[2]->store((longlong) stat->data_file_length, TRUE); - table->field[3]->store((longlong) stat->max_data_file_length, TRUE); - table->field[4]->store((longlong) stat->index_file_length, TRUE); - table->field[5]->store((longlong) stat->records, TRUE); - table->field[6]->store((longlong) stat->mean_rec_length, TRUE); - spd_tz_system->gmt_sec_to_TIME(&mysql_time, (my_time_t) stat->check_time); - table->field[7]->store_time(&mysql_time); - spd_tz_system->gmt_sec_to_TIME(&mysql_time, (my_time_t) stat->create_time); - table->field[8]->store_time(&mysql_time); - spd_tz_system->gmt_sec_to_TIME(&mysql_time, (my_time_t) stat->update_time); - table->field[9]->store_time(&mysql_time); - if (stat->checksum_null) - { - table->field[10]->set_null(); - table->field[10]->reset(); - } else { - table->field[10]->set_notnull(); - table->field[10]->store((longlong) stat->checksum, TRUE); - } - DBUG_VOID_RETURN; -} - -void spider_store_table_crd_info( - TABLE *table, - uint *seq, - longlong *cardinality -) { - DBUG_ENTER("spider_store_table_crd_info"); - table->field[2]->store((longlong) *seq, TRUE); - table->field[3]->store((longlong) *cardinality, FALSE); - DBUG_VOID_RETURN; -} - int spider_insert_xa( TABLE *table, XID *xid, @@ -1474,83 +1403,6 @@ int spider_insert_sys_table( DBUG_RETURN(error_num); } -int spider_insert_or_update_table_sts( - TABLE *table, - const char *name, - uint name_length, - ha_statistics *stat -) { - int error_num; - char table_key[MAX_KEY_LENGTH]; - DBUG_ENTER("spider_insert_or_update_table_sts"); - table->use_all_columns(); - spider_store_tables_name(table, name, name_length); - spider_store_table_sts_info( - table, - stat - ); - - if ((error_num = spider_check_sys_table_for_update_all_columns(table, table_key))) - { - if (error_num != HA_ERR_KEY_NOT_FOUND && error_num != HA_ERR_END_OF_FILE) - { - table->file->print_error(error_num, MYF(0)); - DBUG_RETURN(error_num); - } - if ((error_num = spider_write_sys_table_row(table))) - { - DBUG_RETURN(error_num); - } - } else { - if ((error_num = spider_update_sys_table_row(table, FALSE))) - { - table->file->print_error(error_num, MYF(0)); - DBUG_RETURN(error_num); - } - } - - DBUG_RETURN(0); -} - -int spider_insert_or_update_table_crd( - TABLE *table, - const char *name, - uint name_length, - longlong *cardinality, - uint number_of_keys -) { - int error_num; - uint roop_count; - char table_key[MAX_KEY_LENGTH]; - DBUG_ENTER("spider_insert_or_update_table_crd"); - table->use_all_columns(); - spider_store_tables_name(table, name, name_length); - - for (roop_count = 0; roop_count < number_of_keys; ++roop_count) - { - spider_store_table_crd_info(table, &roop_count, &cardinality[roop_count]); - if ((error_num = spider_check_sys_table_for_update_all_columns(table, table_key))) - { - if (error_num != HA_ERR_KEY_NOT_FOUND && error_num != HA_ERR_END_OF_FILE) - { - table->file->print_error(error_num, MYF(0)); - DBUG_RETURN(error_num); - } - if ((error_num = spider_write_sys_table_row(table))) - { - DBUG_RETURN(error_num); - } - } else { - if ((error_num = spider_update_sys_table_row(table, FALSE))) - { - table->file->print_error(error_num, MYF(0)); - DBUG_RETURN(error_num); - } - } - } - DBUG_RETURN(0); -} - int spider_log_tables_link_failed( TABLE *table, char *name, @@ -2518,73 +2370,6 @@ int spider_get_sys_tables_static_link_id( DBUG_RETURN(error_num); } -void spider_get_sys_table_sts_info( - TABLE *table, - ha_statistics *stat -) { - MYSQL_TIME mysql_time; -#ifdef MARIADB_BASE_VERSION - uint not_used_uint; -#else - my_bool not_used_my_bool; -#endif - long not_used_long; - DBUG_ENTER("spider_get_sys_table_sts_info"); - stat->data_file_length = (ulonglong) table->field[2]->val_int(); - stat->max_data_file_length = (ulonglong) table->field[3]->val_int(); - stat->index_file_length = (ulonglong) table->field[4]->val_int(); - stat->records = (ha_rows) table->field[5]->val_int(); - stat->mean_rec_length = (ulong) table->field[6]->val_int(); - table->field[7]->get_date(&mysql_time, SPIDER_date_mode_t(0)); -#ifdef MARIADB_BASE_VERSION - stat->check_time = (time_t) my_system_gmt_sec(&mysql_time, - ¬_used_long, ¬_used_uint); -#else - stat->check_time = (time_t) my_system_gmt_sec(&mysql_time, - ¬_used_long, ¬_used_my_bool); -#endif - table->field[8]->get_date(&mysql_time, SPIDER_date_mode_t(0)); -#ifdef MARIADB_BASE_VERSION - stat->create_time = (time_t) my_system_gmt_sec(&mysql_time, - ¬_used_long, ¬_used_uint); -#else - stat->create_time = (time_t) my_system_gmt_sec(&mysql_time, - ¬_used_long, ¬_used_my_bool); -#endif - table->field[9]->get_date(&mysql_time, SPIDER_date_mode_t(0)); -#ifdef MARIADB_BASE_VERSION - stat->update_time = (time_t) my_system_gmt_sec(&mysql_time, - ¬_used_long, ¬_used_uint); -#else - stat->update_time = (time_t) my_system_gmt_sec(&mysql_time, - ¬_used_long, ¬_used_my_bool); -#endif - if (table->field[10]->is_null()) - { - stat->checksum_null = TRUE; - stat->checksum = 0; - } else { - stat->checksum_null = FALSE; - stat->checksum = (ha_checksum) table->field[10]->val_int(); - } - DBUG_VOID_RETURN; -} - -void spider_get_sys_table_crd_info( - TABLE *table, - longlong *cardinality, - uint number_of_keys -) { - uint seq; - DBUG_ENTER("spider_get_sys_table_crd_info"); - seq = (uint) table->field[2]->val_int(); - if (seq < number_of_keys) - { - cardinality[seq] = (longlong) table->field[3]->val_int(); - } - DBUG_VOID_RETURN; -} - int spider_sys_update_tables_link_status( THD *thd, char *name, @@ -2983,282 +2768,6 @@ int spider_get_link_statuses( DBUG_RETURN(0); } -int spider_sys_insert_or_update_table_sts( - THD *thd, - const char *name, - uint name_length, - ha_statistics *stat, - bool need_lock -) { - int error_num; - TABLE *table_sts = NULL; -#if MYSQL_VERSION_ID < 50500 - Open_tables_state open_tables_backup; -#else - Open_tables_backup open_tables_backup; -#endif - DBUG_ENTER("spider_sys_insert_or_update_table_sts"); - if ( - !(table_sts = spider_open_sys_table( - thd, SPIDER_SYS_TABLE_STS_TABLE_NAME_STR, - SPIDER_SYS_TABLE_STS_TABLE_NAME_LEN, TRUE, - &open_tables_backup, need_lock, &error_num)) - ) { - goto error; - } - if ((error_num = spider_insert_or_update_table_sts( - table_sts, - name, - name_length, - stat - ))) - goto error; - spider_close_sys_table(thd, table_sts, &open_tables_backup, need_lock); - table_sts = NULL; - DBUG_RETURN(0); - -error: - if (table_sts) - spider_close_sys_table(thd, table_sts, &open_tables_backup, need_lock); - DBUG_RETURN(error_num); -} - -int spider_sys_insert_or_update_table_crd( - THD *thd, - const char *name, - uint name_length, - longlong *cardinality, - uint number_of_keys, - bool need_lock -) { - int error_num; - TABLE *table_crd = NULL; -#if MYSQL_VERSION_ID < 50500 - Open_tables_state open_tables_backup; -#else - Open_tables_backup open_tables_backup; -#endif - DBUG_ENTER("spider_sys_insert_or_update_table_crd"); - if ( - !(table_crd = spider_open_sys_table( - thd, SPIDER_SYS_TABLE_CRD_TABLE_NAME_STR, - SPIDER_SYS_TABLE_CRD_TABLE_NAME_LEN, TRUE, - &open_tables_backup, need_lock, &error_num)) - ) { - goto error; - } - if ((error_num = spider_insert_or_update_table_crd( - table_crd, - name, - name_length, - cardinality, - number_of_keys - ))) - goto error; - spider_close_sys_table(thd, table_crd, &open_tables_backup, need_lock); - table_crd = NULL; - DBUG_RETURN(0); - -error: - if (table_crd) - spider_close_sys_table(thd, table_crd, &open_tables_backup, need_lock); - DBUG_RETURN(error_num); -} - -int spider_sys_delete_table_sts( - THD *thd, - const char *name, - uint name_length, - bool need_lock -) { - int error_num; - TABLE *table_sts = NULL; -#if MYSQL_VERSION_ID < 50500 - Open_tables_state open_tables_backup; -#else - Open_tables_backup open_tables_backup; -#endif - DBUG_ENTER("spider_sys_delete_table_sts"); - if ( - !(table_sts = spider_open_sys_table( - thd, SPIDER_SYS_TABLE_STS_TABLE_NAME_STR, - SPIDER_SYS_TABLE_STS_TABLE_NAME_LEN, TRUE, - &open_tables_backup, need_lock, &error_num)) - ) { - goto error; - } - if ((error_num = spider_delete_table_sts( - table_sts, - name, - name_length - ))) - goto error; - spider_close_sys_table(thd, table_sts, &open_tables_backup, need_lock); - table_sts = NULL; - DBUG_RETURN(0); - -error: - if (table_sts) - spider_close_sys_table(thd, table_sts, &open_tables_backup, need_lock); - DBUG_RETURN(error_num); -} - -int spider_sys_delete_table_crd( - THD *thd, - const char *name, - uint name_length, - bool need_lock -) { - int error_num; - TABLE *table_crd = NULL; -#if MYSQL_VERSION_ID < 50500 - Open_tables_state open_tables_backup; -#else - Open_tables_backup open_tables_backup; -#endif - DBUG_ENTER("spider_sys_delete_table_crd"); - if ( - !(table_crd = spider_open_sys_table( - thd, SPIDER_SYS_TABLE_CRD_TABLE_NAME_STR, - SPIDER_SYS_TABLE_CRD_TABLE_NAME_LEN, TRUE, - &open_tables_backup, need_lock, &error_num)) - ) { - goto error; - } - if ((error_num = spider_delete_table_crd( - table_crd, - name, - name_length - ))) - goto error; - spider_close_sys_table(thd, table_crd, &open_tables_backup, need_lock); - table_crd = NULL; - DBUG_RETURN(0); - -error: - if (table_crd) - spider_close_sys_table(thd, table_crd, &open_tables_backup, need_lock); - DBUG_RETURN(error_num); -} - -int spider_sys_get_table_sts( - THD *thd, - const char *name, - uint name_length, - ha_statistics *stat, - bool need_lock -) { - int error_num; - char table_key[MAX_KEY_LENGTH]; - TABLE *table_sts = NULL; -#if MYSQL_VERSION_ID < 50500 - Open_tables_state open_tables_backup; -#else - Open_tables_backup open_tables_backup; -#endif - DBUG_ENTER("spider_sys_get_table_sts"); - if ( - !(table_sts = spider_open_sys_table( - thd, SPIDER_SYS_TABLE_STS_TABLE_NAME_STR, - SPIDER_SYS_TABLE_STS_TABLE_NAME_LEN, TRUE, - &open_tables_backup, need_lock, &error_num)) - ) { - goto error; - } - - table_sts->use_all_columns(); - spider_store_tables_name(table_sts, name, name_length); - if ((error_num = spider_check_sys_table(table_sts, table_key))) - { - if (error_num != HA_ERR_KEY_NOT_FOUND && error_num != HA_ERR_END_OF_FILE) - { - table_sts->file->print_error(error_num, MYF(0)); - } - goto error; - } else { - spider_get_sys_table_sts_info( - table_sts, - stat - ); - } - - spider_close_sys_table(thd, table_sts, &open_tables_backup, need_lock); - table_sts = NULL; - DBUG_RETURN(0); - -error: - if (table_sts) - spider_close_sys_table(thd, table_sts, &open_tables_backup, need_lock); - DBUG_RETURN(error_num); -} - -int spider_sys_get_table_crd( - THD *thd, - const char *name, - uint name_length, - longlong *cardinality, - uint number_of_keys, - bool need_lock -) { - int error_num; - char table_key[MAX_KEY_LENGTH]; - bool index_inited = FALSE; - TABLE *table_crd = NULL; -#if MYSQL_VERSION_ID < 50500 - Open_tables_state open_tables_backup; -#else - Open_tables_backup open_tables_backup; -#endif - DBUG_ENTER("spider_sys_get_table_crd"); - if ( - !(table_crd = spider_open_sys_table( - thd, SPIDER_SYS_TABLE_CRD_TABLE_NAME_STR, - SPIDER_SYS_TABLE_CRD_TABLE_NAME_LEN, TRUE, - &open_tables_backup, need_lock, &error_num)) - ) { - goto error; - } - - table_crd->use_all_columns(); - spider_store_tables_name(table_crd, name, name_length); - if ((error_num = spider_get_sys_table_by_idx(table_crd, table_key, 0, - SPIDER_SYS_TABLE_CRD_PK_COL_CNT - 1))) - { - if (error_num != HA_ERR_KEY_NOT_FOUND && error_num != HA_ERR_END_OF_FILE) - { - table_crd->file->print_error(error_num, MYF(0)); - } - goto error; - } else { - index_inited = TRUE; - do { - spider_get_sys_table_crd_info( - table_crd, - cardinality, - number_of_keys - ); - error_num = spider_sys_index_next_same(table_crd, table_key); - } while (error_num == 0); - } - index_inited = FALSE; - if ((error_num = spider_sys_index_end(table_crd))) - { - table_crd->file->print_error(error_num, MYF(0)); - goto error; - } - - spider_close_sys_table(thd, table_crd, &open_tables_backup, need_lock); - table_crd = NULL; - DBUG_RETURN(0); - -error: - if (index_inited) - spider_sys_index_end(table_crd); - if (table_crd) - spider_close_sys_table(thd, table_crd, &open_tables_backup, need_lock); - DBUG_RETURN(error_num); -} - int spider_sys_replace( TABLE *table, bool *modified_non_trans_table diff --git a/storage/spider/spd_sys_table.h b/storage/spider/spd_sys_table.h index 90ed5811cd1..53ef3b82465 100644 --- a/storage/spider/spd_sys_table.h +++ b/storage/spider/spd_sys_table.h @@ -28,10 +28,6 @@ #define SPIDER_SYS_XA_FAILED_TABLE_NAME_LEN 20 #define SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_STR "spider_table_position_for_recovery" #define SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_LEN 34 -#define SPIDER_SYS_TABLE_STS_TABLE_NAME_STR "spider_table_sts" -#define SPIDER_SYS_TABLE_STS_TABLE_NAME_LEN 16 -#define SPIDER_SYS_TABLE_CRD_TABLE_NAME_STR "spider_table_crd" -#define SPIDER_SYS_TABLE_CRD_TABLE_NAME_LEN 16 #define SPIDER_SYS_XA_PREPARED_STR "PREPARED" #define SPIDER_SYS_XA_NOT_YET_STR "NOT YET" @@ -322,21 +318,6 @@ int spider_insert_sys_table( TABLE *table ); -int spider_insert_or_update_table_sts( - TABLE *table, - const char *name, - uint name_length, - ha_statistics *stat -); - -int spider_insert_or_update_table_crd( - TABLE *table, - const char *name, - uint name_length, - longlong *cardinality, - uint number_of_keys -); - int spider_log_tables_link_failed( TABLE *table, char *name, @@ -480,17 +461,6 @@ int spider_get_sys_tables_static_link_id( MEM_ROOT *mem_root ); -void spider_get_sys_table_sts_info( - TABLE *table, - ha_statistics *stat -); - -void spider_get_sys_table_crd_info( - TABLE *table, - longlong *cardinality, - uint number_of_keys -); - int spider_sys_update_tables_link_status( THD *thd, char *name, @@ -542,54 +512,6 @@ int spider_get_link_statuses( MEM_ROOT *mem_root ); -int spider_sys_insert_or_update_table_sts( - THD *thd, - const char *name, - uint name_length, - ha_statistics *stat, - bool need_lock -); - -int spider_sys_insert_or_update_table_crd( - THD *thd, - const char *name, - uint name_length, - longlong *cardinality, - uint number_of_keys, - bool need_lock -); - -int spider_sys_delete_table_sts( - THD *thd, - const char *name, - uint name_length, - bool need_lock -); - -int spider_sys_delete_table_crd( - THD *thd, - const char *name, - uint name_length, - bool need_lock -); - -int spider_sys_get_table_sts( - THD *thd, - const char *name, - uint name_length, - ha_statistics *stat, - bool need_lock -); - -int spider_sys_get_table_crd( - THD *thd, - const char *name, - uint name_length, - longlong *cardinality, - uint number_of_keys, - bool need_lock -); - int spider_sys_replace( TABLE *table, bool *modified_non_trans_table diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 6f4882789fc..48ccfbfac38 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -5595,8 +5595,6 @@ int spider_free_share( ) { DBUG_ENTER("spider_free_share"); pthread_mutex_lock(&spider_tbl_mutex); - bool do_delete_thd = false; - THD *thd = current_thd; if (!--share->use_count) { #ifndef WITHOUT_SPIDER_BG_SEARCH @@ -5614,47 +5612,6 @@ int spider_free_share( spider_free_spider_object_for_share(&share->crd_spider); } #endif - if ( - share->sts_init && - spider_param_store_last_sts(share->store_last_sts) - ) { - if (!thd) - { - /* Create a thread for Spider system table update */ - thd = spider_create_thd(); - if (!thd) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - do_delete_thd = TRUE; - } - spider_sys_insert_or_update_table_sts( - thd, - share->lgtm_tblhnd_share->table_name, - share->lgtm_tblhnd_share->table_name_length, - &share->stat, - FALSE - ); - } - if ( - share->crd_init && - spider_param_store_last_crd(share->store_last_crd) - ) { - if (!thd) - { - /* Create a thread for Spider system table update */ - thd = spider_create_thd(); - if (!thd) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - do_delete_thd = TRUE; - } - spider_sys_insert_or_update_table_crd( - thd, - share->lgtm_tblhnd_share->table_name, - share->lgtm_tblhnd_share->table_name_length, - share->cardinality, - share->table_share->fields, - FALSE - ); - } spider_free_share_alloc(share); #ifdef HASH_UPDATE_WITH_HASH_VALUE my_hash_delete_with_hash_value(&spider_open_tables, @@ -5669,8 +5626,6 @@ int spider_free_share( free_root(&share->mem_root, MYF(0)); spider_free(spider_current_trx, share, MYF(0)); } - if (do_delete_thd) - spider_destroy_thd(thd); pthread_mutex_unlock(&spider_tbl_mutex); DBUG_RETURN(0); } @@ -7450,7 +7405,6 @@ int spider_get_sts( ) { int get_type __attribute__ ((unused)); int error_num = 0; - bool need_to_get = TRUE; DBUG_ENTER("spider_get_sts"); #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -7488,37 +7442,16 @@ int spider_get_sts( get_type = 0; } #endif - if ( - !share->sts_init && - spider_param_load_sts_at_startup(share->load_sts_at_startup) && - (!share->init || share->init_error) - ) { - error_num = spider_sys_get_table_sts( - current_thd, - share->lgtm_tblhnd_share->table_name, - share->lgtm_tblhnd_share->table_name_length, - &share->stat, - FALSE - ); - if ( - !error_num || - (error_num != HA_ERR_KEY_NOT_FOUND && error_num != HA_ERR_END_OF_FILE) - ) - need_to_get = FALSE; - } - if (need_to_get) - { #ifdef WITH_PARTITION_STORAGE_ENGINE - if (get_type == 0) + if (get_type == 0) spider_copy_sts_to_share(share, share->partition_share); - else { + else { #endif error_num = spider_db_show_table_status(spider, link_idx, sts_mode, flag); #ifdef WITH_PARTITION_STORAGE_ENGINE - } -#endif } +#endif #ifdef WITH_PARTITION_STORAGE_ENGINE if (get_type >= 2) pthread_mutex_unlock(&share->partition_share->sts_mutex); @@ -7598,7 +7531,6 @@ int spider_get_crd( ) { int get_type __attribute__ ((unused)); int error_num = 0; - bool need_to_get = TRUE; DBUG_ENTER("spider_get_crd"); #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -7636,38 +7568,16 @@ int spider_get_crd( get_type = 0; } #endif - if ( - !share->crd_init && - spider_param_load_sts_at_startup(share->load_crd_at_startup) - ) { - error_num = spider_sys_get_table_crd( - current_thd, - share->lgtm_tblhnd_share->table_name, - share->lgtm_tblhnd_share->table_name_length, - share->cardinality, - table->s->fields, - FALSE - ); - if ( - !error_num || - (error_num != HA_ERR_KEY_NOT_FOUND && error_num != HA_ERR_END_OF_FILE) - ) - need_to_get = FALSE; - } - - if (need_to_get) - { #ifdef WITH_PARTITION_STORAGE_ENGINE - if (get_type == 0) + if (get_type == 0) spider_copy_crd_to_share(share, share->partition_share, - table->s->fields); - else { + table->s->fields); + else { #endif error_num = spider_db_show_index(spider, link_idx, table, crd_mode); #ifdef WITH_PARTITION_STORAGE_ENGINE - } -#endif } +#endif #ifdef WITH_PARTITION_STORAGE_ENGINE if (get_type >= 2) pthread_mutex_unlock(&share->partition_share->crd_mutex); From 5064750fbf9bafc9efbb84c431e9c92fa8e039be Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Fri, 24 Nov 2023 16:26:12 +0700 Subject: [PATCH 317/477] MDEV-32466: Potential memory leak on executing of create view statement This patch is actually follow-up for the task MDEV-23902: MariaDB crash on calling function to use correct query arena for a statement. In case invocation of a function is in progress use its call arena, else use current query arena that can be either a statement or a regular query arena. --- mysql-test/main/ps_mem_leaks.result | 22 ++++++++++++++++++++++ mysql-test/main/ps_mem_leaks.test | 28 ++++++++++++++++++++++++++++ sql/sp.cc | 3 ++- sql/sql_base.cc | 2 +- sql/sql_class.h | 11 +++++++++++ sql/sql_lex.cc | 5 +++-- sql/sql_view.cc | 2 +- 7 files changed, 68 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/ps_mem_leaks.result b/mysql-test/main/ps_mem_leaks.result index 6a1155dbafe..90e003f8e5c 100644 --- a/mysql-test/main/ps_mem_leaks.result +++ b/mysql-test/main/ps_mem_leaks.result @@ -57,4 +57,26 @@ EXECUTE stmt; exp 0 DEALLOCATE PREPARE stmt; +# +# MDEV-32466: Potential memory leak on execuing of create view statement +# +CREATE FUNCTION f1 () RETURNS VARCHAR(1) +BEGIN +DECLARE rec1 ROW TYPE OF v1; +SELECT z INTO rec1 FROM v1; +RETURN 1; +END| +CREATE FUNCTION f2 () RETURNS VARCHAR(1) RETURN '!'; +CREATE VIEW v1 AS SELECT f2() z; +PREPARE stmt FROM "SELECT f1()"; +EXECUTE stmt; +f1() +1 +EXECUTE stmt; +f1() +1 +DEALLOCATE PREPARE stmt; +DROP FUNCTION f1; +DROP VIEW v1; +DROP FUNCTION f2; # End of 10.4 tests diff --git a/mysql-test/main/ps_mem_leaks.test b/mysql-test/main/ps_mem_leaks.test index 90de38ad482..a68d62fd293 100644 --- a/mysql-test/main/ps_mem_leaks.test +++ b/mysql-test/main/ps_mem_leaks.test @@ -69,4 +69,32 @@ EXECUTE stmt; DEALLOCATE PREPARE stmt; +--echo # +--echo # MDEV-32466: Potential memory leak on execuing of create view statement +--echo # + +--delimiter | + +CREATE FUNCTION f1 () RETURNS VARCHAR(1) +BEGIN + DECLARE rec1 ROW TYPE OF v1; + SELECT z INTO rec1 FROM v1; + RETURN 1; +END| +--delimiter ; + +CREATE FUNCTION f2 () RETURNS VARCHAR(1) RETURN '!'; +CREATE VIEW v1 AS SELECT f2() z; + +PREPARE stmt FROM "SELECT f1()"; +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; + +# Clean up +DROP FUNCTION f1; +DROP VIEW v1; +DROP FUNCTION f2; + --echo # End of 10.4 tests diff --git a/sql/sp.cc b/sql/sp.cc index 87af91187e7..266dbbe9d71 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -2720,7 +2720,8 @@ void sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *belong_to_view) { for (Sroutine_hash_entry *rt= src->first; rt; rt= rt->next) - (void)sp_add_used_routine(prelocking_ctx, thd->stmt_arena, + + (void)sp_add_used_routine(prelocking_ctx, thd->active_stmt_arena_to_use(), &rt->mdl_request.key, rt->m_handler, belong_to_view); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 91dd8cb12cd..7642f41e46c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7740,7 +7740,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, while ((item= it++)) { if (make_pre_fix) - pre_fix->push_back(item, thd->stmt_arena->mem_root); + pre_fix->push_back(item, thd->active_stmt_arena_to_use()->mem_root); if (item->fix_fields_if_needed_for_scalar(thd, it.ref())) { diff --git a/sql/sql_class.h b/sql/sql_class.h index a903b70fa84..5db5aca92b8 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2790,6 +2790,17 @@ public: */ Query_arena *stmt_arena; + /** + Get either call or statement arena. In case some function is called from + within a query the call arena has to be used for a memory allocation, + else use the statement arena. + */ + Query_arena *active_stmt_arena_to_use() + { + return (state == Query_arena::STMT_SP_QUERY_ARGUMENTS) ? this : + stmt_arena; + } + void *bulk_param; /* diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 2e8bf40003e..a4859bcc1d2 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3115,8 +3115,9 @@ 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()) return false; - Item **array= static_cast(thd->stmt_arena->alloc(sizeof(Item*) * - n_elems)); + + Item **array= static_cast( + thd->active_stmt_arena_to_use()->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_view.cc b/sql/sql_view.cc index 3651bad7067..9f9a9716982 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1655,7 +1655,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, objects of the view. */ if (!(table->view_sctx= (Security_context *) - thd->stmt_arena->calloc(sizeof(Security_context)))) + thd->active_stmt_arena_to_use()->calloc(sizeof(Security_context)))) goto err; security_ctx= table->view_sctx; } From 85f2e4f8e8c82978bd9cc0af9bfd2b549ea04d65 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Fri, 24 Nov 2023 16:28:31 +0700 Subject: [PATCH 318/477] MDEV-32466: Potential memory leak on executing of create view statement This is the follow-up patch that removes explicit use of thd->stmt_arena for memory allocation and replaces it with call of the method THD::active_stmt_arena_to_use() Additionally, this patch adds extra DBUG_ASSERT to check that right query arena is in use. --- sql/item_func.cc | 11 ++++++++++- sql/item_jsonfunc.cc | 2 +- sql/item_subselect.cc | 6 +++++- sql/item_sum.cc | 10 ++++++++-- sql/sp.cc | 9 +++++++-- sql/sql_lex.cc | 12 +++++++++--- sql/sql_show.cc | 4 ++-- sql/sql_trigger.cc | 3 ++- sql/sql_tvc.cc | 5 ++++- sql/table.cc | 2 +- 10 files changed, 49 insertions(+), 15 deletions(-) diff --git a/sql/item_func.cc b/sql/item_func.cc index 31c81eb7463..612fe7a4b9e 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2740,8 +2740,17 @@ bool Item_func_rand::fix_fields(THD *thd,Item **ref) No need to send a Rand log event if seed was given eg: RAND(seed), as it will be replicated in the query as such. */ + DBUG_ASSERT((!rand && + (thd->active_stmt_arena_to_use()-> + is_stmt_prepare_or_first_stmt_execute() || + thd->active_stmt_arena_to_use()-> + is_conventional() || + thd->active_stmt_arena_to_use()->state == + Query_arena::STMT_SP_QUERY_ARGUMENTS + ) + ) || rand); if (!rand && !(rand= (struct my_rnd_struct*) - thd->stmt_arena->alloc(sizeof(*rand)))) + thd->active_stmt_arena_to_use()->alloc(sizeof(*rand)))) return TRUE; } else diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index ffa43f542ed..13eb9955fbd 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -827,7 +827,7 @@ static int alloc_tmp_paths(THD *thd, uint n_paths, { if (*tmp_paths == 0) { - MEM_ROOT *root= thd->stmt_arena->mem_root; + MEM_ROOT *root= thd->active_stmt_arena_to_use()->mem_root; *paths= (json_path_with_flags *) alloc_root(root, sizeof(json_path_with_flags) * n_paths); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 6400bf518ce..c632c9fc94b 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -3200,8 +3200,12 @@ bool Item_exists_subselect::exists2in_processor(void *opt_arg) if (eqs.at(i).outer_exp-> walk(&Item::find_item_processor, TRUE, upper->item)) break; + DBUG_ASSERT(thd->stmt_arena->is_stmt_prepare_or_first_stmt_execute() || + thd->stmt_arena->is_conventional()); + DBUG_ASSERT(thd->stmt_arena->mem_root == thd->mem_root); if (i == (uint)eqs.elements() && - (in_subs->upper_refs.push_back(upper, thd->stmt_arena->mem_root))) + (in_subs->upper_refs.push_back( + upper, thd->mem_root))) goto out; } } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 9a0f08e2a18..048307fdeb2 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -4098,8 +4098,14 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) char *buf; String *new_separator; - if (!(buf= (char*) thd->stmt_arena->alloc(buflen)) || - !(new_separator= new(thd->stmt_arena->mem_root) + DBUG_ASSERT(thd->active_stmt_arena_to_use()-> + is_stmt_prepare_or_first_sp_execute() || + thd->active_stmt_arena_to_use()-> + is_conventional() || + thd->active_stmt_arena_to_use()->state == + Query_arena::STMT_SP_QUERY_ARGUMENTS); + if (!(buf= (char*) thd->active_stmt_arena_to_use()->alloc(buflen)) || + !(new_separator= new(thd->active_stmt_arena_to_use()->mem_root) String(buf, buflen, collation.collation))) return TRUE; diff --git a/sql/sp.cc b/sql/sp.cc index 266dbbe9d71..d25c7353ca4 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -2694,7 +2694,13 @@ sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx, for (uint i=0 ; i < src->records ; i++) { Sroutine_hash_entry *rt= (Sroutine_hash_entry *)my_hash_element(src, i); - (void)sp_add_used_routine(prelocking_ctx, thd->stmt_arena, + DBUG_ASSERT(thd->active_stmt_arena_to_use()-> + is_stmt_prepare_or_first_stmt_execute() || + thd->active_stmt_arena_to_use()-> + is_conventional() || + thd->active_stmt_arena_to_use()->state == + Query_arena::STMT_SP_QUERY_ARGUMENTS); + (void)sp_add_used_routine(prelocking_ctx, thd->active_stmt_arena_to_use(), &rt->mdl_request.key, rt->m_handler, belong_to_view); } @@ -2720,7 +2726,6 @@ void sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *belong_to_view) { for (Sroutine_hash_entry *rt= src->first; rt; rt= rt->next) - (void)sp_add_used_routine(prelocking_ctx, thd->active_stmt_arena_to_use(), &rt->mdl_request.key, rt->m_handler, belong_to_view); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index a4859bcc1d2..127691997b0 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -4137,18 +4137,24 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl) void st_select_lex::fix_prepare_information(THD *thd, Item **conds, Item **having_conds) { + Query_arena *active_arena= thd->active_stmt_arena_to_use(); + DBUG_ENTER("st_select_lex::fix_prepare_information"); - if (!thd->stmt_arena->is_conventional() && + + if (!active_arena->is_conventional() && !(changed_elements & TOUCHED_SEL_COND)) { Query_arena_stmt on_stmt_arena(thd); changed_elements|= TOUCHED_SEL_COND; + DBUG_ASSERT( + active_arena->is_stmt_prepare_or_first_stmt_execute() || + active_arena->state == Query_arena::STMT_SP_QUERY_ARGUMENTS); if (group_list.first) { if (!group_list_ptrs) { - void *mem= thd->stmt_arena->alloc(sizeof(Group_list_ptrs)); - group_list_ptrs= new (mem) Group_list_ptrs(thd->stmt_arena->mem_root); + void *mem= active_arena->alloc(sizeof(Group_list_ptrs)); + group_list_ptrs= new (mem) Group_list_ptrs(active_arena->mem_root); } group_list_ptrs->reserve(group_list.elements); for (ORDER *order= group_list.first; order; order= order->next) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3d74cf333ce..d93dea50972 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -8842,9 +8842,9 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) } List_iterator_fast it(sel->item_list); if (!(transl= - (Field_translator*)(thd->stmt_arena-> + (Field_translator*)(thd->active_stmt_arena_to_use()-> alloc(sel->item_list.elements * - sizeof(Field_translator))))) + sizeof(Field_translator))))) // ??? { DBUG_RETURN(1); } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 1398e8f9a55..08532030505 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -2298,7 +2298,8 @@ add_tables_and_routines_for_triggers(THD *thd, MDL_key key(MDL_key::TRIGGER, trigger->m_db.str, trigger->m_name.str); - if (sp_add_used_routine(prelocking_ctx, thd->stmt_arena, + if (sp_add_used_routine(prelocking_ctx, + thd->active_stmt_arena_to_use(), &key, &sp_handler_trigger, table_list->belong_to_view)) { diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index a351e3fa308..0f940ca5206 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -240,7 +240,10 @@ bool table_value_constr::prepare(THD *thd, SELECT_LEX *sl, if (!holders) { - holders= type_holders= new (thd->stmt_arena->mem_root) Type_holder[cnt]; + DBUG_ASSERT(thd->stmt_arena->is_stmt_prepare_or_first_stmt_execute() || + thd->stmt_arena->is_conventional()); + holders= type_holders= + new (thd->active_stmt_arena_to_use()->mem_root) Type_holder[cnt]; if (!holders || join_type_handlers_for_tvc(thd, li, holders, cnt) || get_type_attributes_for_tvc(thd, li, holders, diff --git a/sql/table.cc b/sql/table.cc index 96a97b0e950..88154986805 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -5548,7 +5548,7 @@ allocate: /* Create view fields translation table */ if (!(transl= - (Field_translator*)(thd->stmt_arena-> + (Field_translator*)(thd-> alloc(select->item_list.elements * sizeof(Field_translator))))) { From 69d294e7557eca760251d418c8fc9db94cf0521f Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Thu, 23 Nov 2023 17:33:42 +0700 Subject: [PATCH 319/477] MDEV-29070 SIGSEGV in my_decimal::operator= and Assertion `0' failed and in Item_type_holder::val_decimal on SELECT The bug is fixed by the patch ported from MySQL. See the comprehensive description below. commit 455c4e8810c76430719b1a08a63ca0f69f44678a Author: Guilhem Bichot Date: Fri Mar 13 17:51:27 2015 +0100 Bug#17668844: CRASH/ASSERT AT ITEM_TYPE_HOLDER::VAL_STR IN ITEM.C We have a predicate of the form: literal_row <=> (a UNION) The subquery is constant, so Item_cache objects are used for its SELECT list. In order, this happens: - Item_subselect::fix_fields() calls select_lex_unit::prepare, where we create Item_type_holder's (appended to unit->types list), create the tmp table (using type info found in unit->types), and call fill_item_list() to put the Item_field's of this table into unit->item_list. - Item_subselect::fix_length_and_dec() calls set_row() which makes Item_cache's of the subquery wrap the Item_type_holder's - When/if a first result row is found for the subquery, Item_cache's are re-pointed to unit->item_list (i.e. Item_field objects which reference the UNION's tmp table columns) (see call to Item_singlerow_subselect::store()). - In our subquery, no result row is found, so the Item_cache's still wrap Item_type_holder's; evaluating '<=>' reads the value of those, but Item_type_holder objects are not expected to be evaluated. Fix: instead of putting unit->types into Item_cache, and later replacing with unit->item_list, put unit->item_list in Item_cache from the start. Approved by Oleksandr Byelkin --- mysql-test/main/subselect.result | 41 ++++++++++++++++- mysql-test/main/subselect.test | 44 +++++++++++++++++++ .../main/subselect_no_exists_to_in.result | 41 ++++++++++++++++- mysql-test/main/subselect_no_mat.result | 41 ++++++++++++++++- mysql-test/main/subselect_no_opts.result | 41 ++++++++++++++++- mysql-test/main/subselect_no_scache.result | 41 ++++++++++++++++- mysql-test/main/subselect_no_semijoin.result | 41 ++++++++++++++++- sql/item_subselect.cc | 4 +- 8 files changed, 286 insertions(+), 8 deletions(-) diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result index 61742b0289c..cb0273542af 100644 --- a/mysql-test/main/subselect.result +++ b/mysql-test/main/subselect.result @@ -1320,7 +1320,7 @@ a SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` int(3) DEFAULT NULL + `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; create table t1 (a int); @@ -7498,5 +7498,44 @@ ERROR HY000: Illegal parameter data types row and boolean for operation '=' SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); ERROR HY000: Illegal parameter data types row and boolean for operation '=' # +# MDEV-29070 SIGSEGV in my_decimal::operator= and Assertion `0' failed +# in Item_type_holder::val_decimal on SELECT +# +CREATE TABLE t1(a INT UNIQUE); +INSERT INTO t1(a) VALUES (1); +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT 1, 1); +a +1 +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT a, a); +a +1 +UPDATE t1 SET a = 0 +WHERE (SELECT a, a WHERE a < 0 INTERSECT +SELECT +1 / +1, a FROM t1 WHERE a > -0+1) IN (SELECT a, a); +SELECT a FROM t1 WHERE (SELECT a, a WHERE a < 0 INTERSECT +SELECT + 1 / + 1, a FROM t1 +WHERE a > -0 + 1) IN (SELECT a, a); +a +CREATE TABLE x (x INT); +INSERT INTO x (x) VALUES (1); +UPDATE x SET x = 1 WHERE x = 1; +INSERT INTO x (x) VALUES (1), (1); +WITH RECURSIVE x (x) AS ( +SELECT 1 INTERSECT +SELECT -(SELECT 1.000000 AS x +UNION +SELECT 1.000000 ORDER BY NOT x < 'x', +-(SELECT 1 + x/1.000000 IN (1, 1) FROM x +WHERE x ORDER BY 1 - x) DESC LIMIT 1 OFFSET 1 +) + 1 FROM x +) +SELECT DISTINCT x, 1, NULL, 1.000000 +FROM x +WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > +(SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) +ORDER BY x ASC, x DESC, x; +ERROR 22007: Truncated incorrect DECIMAL value: 'x' +DROP TABLE t1, x; +# # End of 10.4 tests # diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test index c250b4584fb..1b74651adb6 100644 --- a/mysql-test/main/subselect.test +++ b/mysql-test/main/subselect.test @@ -6346,6 +6346,50 @@ SELECT ROW(1,2) = 1 IN (SELECT 1 UNION SELECT 2); --error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); +--echo # +--echo # MDEV-29070 SIGSEGV in my_decimal::operator= and Assertion `0' failed +--echo # in Item_type_holder::val_decimal on SELECT +--echo # + +CREATE TABLE t1(a INT UNIQUE); +INSERT INTO t1(a) VALUES (1); + +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT 1, 1); + +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT a, a); + +UPDATE t1 SET a = 0 + WHERE (SELECT a, a WHERE a < 0 INTERSECT + SELECT +1 / +1, a FROM t1 WHERE a > -0+1) IN (SELECT a, a); + +SELECT a FROM t1 WHERE (SELECT a, a WHERE a < 0 INTERSECT + SELECT + 1 / + 1, a FROM t1 + WHERE a > -0 + 1) IN (SELECT a, a); + +CREATE TABLE x (x INT); +INSERT INTO x (x) VALUES (1); +UPDATE x SET x = 1 WHERE x = 1; +INSERT INTO x (x) VALUES (1), (1); +let $q= WITH RECURSIVE x (x) AS ( + SELECT 1 INTERSECT + SELECT -(SELECT 1.000000 AS x + UNION + SELECT 1.000000 ORDER BY NOT x < 'x', + -(SELECT 1 + x/1.000000 IN (1, 1) FROM x + WHERE x ORDER BY 1 - x) DESC LIMIT 1 OFFSET 1 + ) + 1 FROM x + ) + SELECT DISTINCT x, 1, NULL, 1.000000 + FROM x + WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > + (SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) + ORDER BY x ASC, x DESC, x; + +--error ER_TRUNCATED_WRONG_VALUE +eval $q; + +DROP TABLE t1, x; + --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result index c3b7f803838..431fdbfb04c 100644 --- a/mysql-test/main/subselect_no_exists_to_in.result +++ b/mysql-test/main/subselect_no_exists_to_in.result @@ -1324,7 +1324,7 @@ a SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` int(3) DEFAULT NULL + `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; create table t1 (a int); @@ -7498,6 +7498,45 @@ ERROR HY000: Illegal parameter data types row and boolean for operation '=' SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); ERROR HY000: Illegal parameter data types row and boolean for operation '=' # +# MDEV-29070 SIGSEGV in my_decimal::operator= and Assertion `0' failed +# in Item_type_holder::val_decimal on SELECT +# +CREATE TABLE t1(a INT UNIQUE); +INSERT INTO t1(a) VALUES (1); +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT 1, 1); +a +1 +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT a, a); +a +1 +UPDATE t1 SET a = 0 +WHERE (SELECT a, a WHERE a < 0 INTERSECT +SELECT +1 / +1, a FROM t1 WHERE a > -0+1) IN (SELECT a, a); +SELECT a FROM t1 WHERE (SELECT a, a WHERE a < 0 INTERSECT +SELECT + 1 / + 1, a FROM t1 +WHERE a > -0 + 1) IN (SELECT a, a); +a +CREATE TABLE x (x INT); +INSERT INTO x (x) VALUES (1); +UPDATE x SET x = 1 WHERE x = 1; +INSERT INTO x (x) VALUES (1), (1); +WITH RECURSIVE x (x) AS ( +SELECT 1 INTERSECT +SELECT -(SELECT 1.000000 AS x +UNION +SELECT 1.000000 ORDER BY NOT x < 'x', +-(SELECT 1 + x/1.000000 IN (1, 1) FROM x +WHERE x ORDER BY 1 - x) DESC LIMIT 1 OFFSET 1 +) + 1 FROM x +) +SELECT DISTINCT x, 1, NULL, 1.000000 +FROM x +WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > +(SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) +ORDER BY x ASC, x DESC, x; +ERROR 22007: Truncated incorrect DECIMAL value: 'x' +DROP TABLE t1, x; +# # End of 10.4 tests # set optimizer_switch=default; diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result index 1b02363588b..7e83755ffdf 100644 --- a/mysql-test/main/subselect_no_mat.result +++ b/mysql-test/main/subselect_no_mat.result @@ -1327,7 +1327,7 @@ a SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` int(3) DEFAULT NULL + `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; create table t1 (a int); @@ -7491,6 +7491,45 @@ ERROR HY000: Illegal parameter data types row and boolean for operation '=' SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); ERROR HY000: Illegal parameter data types row and boolean for operation '=' # +# MDEV-29070 SIGSEGV in my_decimal::operator= and Assertion `0' failed +# in Item_type_holder::val_decimal on SELECT +# +CREATE TABLE t1(a INT UNIQUE); +INSERT INTO t1(a) VALUES (1); +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT 1, 1); +a +1 +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT a, a); +a +1 +UPDATE t1 SET a = 0 +WHERE (SELECT a, a WHERE a < 0 INTERSECT +SELECT +1 / +1, a FROM t1 WHERE a > -0+1) IN (SELECT a, a); +SELECT a FROM t1 WHERE (SELECT a, a WHERE a < 0 INTERSECT +SELECT + 1 / + 1, a FROM t1 +WHERE a > -0 + 1) IN (SELECT a, a); +a +CREATE TABLE x (x INT); +INSERT INTO x (x) VALUES (1); +UPDATE x SET x = 1 WHERE x = 1; +INSERT INTO x (x) VALUES (1), (1); +WITH RECURSIVE x (x) AS ( +SELECT 1 INTERSECT +SELECT -(SELECT 1.000000 AS x +UNION +SELECT 1.000000 ORDER BY NOT x < 'x', +-(SELECT 1 + x/1.000000 IN (1, 1) FROM x +WHERE x ORDER BY 1 - x) DESC LIMIT 1 OFFSET 1 +) + 1 FROM x +) +SELECT DISTINCT x, 1, NULL, 1.000000 +FROM x +WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > +(SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) +ORDER BY x ASC, x DESC, x; +ERROR 22007: Truncated incorrect DECIMAL value: 'x' +DROP TABLE t1, x; +# # End of 10.4 tests # set optimizer_switch=default; diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result index 040b3fbf150..9de07ccbf9e 100644 --- a/mysql-test/main/subselect_no_opts.result +++ b/mysql-test/main/subselect_no_opts.result @@ -1323,7 +1323,7 @@ a SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` int(3) DEFAULT NULL + `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; create table t1 (a int); @@ -7489,6 +7489,45 @@ ERROR HY000: Illegal parameter data types row and boolean for operation '=' SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); ERROR HY000: Illegal parameter data types row and boolean for operation '=' # +# MDEV-29070 SIGSEGV in my_decimal::operator= and Assertion `0' failed +# in Item_type_holder::val_decimal on SELECT +# +CREATE TABLE t1(a INT UNIQUE); +INSERT INTO t1(a) VALUES (1); +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT 1, 1); +a +1 +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT a, a); +a +1 +UPDATE t1 SET a = 0 +WHERE (SELECT a, a WHERE a < 0 INTERSECT +SELECT +1 / +1, a FROM t1 WHERE a > -0+1) IN (SELECT a, a); +SELECT a FROM t1 WHERE (SELECT a, a WHERE a < 0 INTERSECT +SELECT + 1 / + 1, a FROM t1 +WHERE a > -0 + 1) IN (SELECT a, a); +a +CREATE TABLE x (x INT); +INSERT INTO x (x) VALUES (1); +UPDATE x SET x = 1 WHERE x = 1; +INSERT INTO x (x) VALUES (1), (1); +WITH RECURSIVE x (x) AS ( +SELECT 1 INTERSECT +SELECT -(SELECT 1.000000 AS x +UNION +SELECT 1.000000 ORDER BY NOT x < 'x', +-(SELECT 1 + x/1.000000 IN (1, 1) FROM x +WHERE x ORDER BY 1 - x) DESC LIMIT 1 OFFSET 1 +) + 1 FROM x +) +SELECT DISTINCT x, 1, NULL, 1.000000 +FROM x +WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > +(SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) +ORDER BY x ASC, x DESC, x; +ERROR 22007: Truncated incorrect DECIMAL value: 'x' +DROP TABLE t1, x; +# # End of 10.4 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 5d09a9cb52e..74cd5422327 100644 --- a/mysql-test/main/subselect_no_scache.result +++ b/mysql-test/main/subselect_no_scache.result @@ -1326,7 +1326,7 @@ a SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` int(3) DEFAULT NULL + `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; create table t1 (a int); @@ -7504,6 +7504,45 @@ ERROR HY000: Illegal parameter data types row and boolean for operation '=' SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); ERROR HY000: Illegal parameter data types row and boolean for operation '=' # +# MDEV-29070 SIGSEGV in my_decimal::operator= and Assertion `0' failed +# in Item_type_holder::val_decimal on SELECT +# +CREATE TABLE t1(a INT UNIQUE); +INSERT INTO t1(a) VALUES (1); +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT 1, 1); +a +1 +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT a, a); +a +1 +UPDATE t1 SET a = 0 +WHERE (SELECT a, a WHERE a < 0 INTERSECT +SELECT +1 / +1, a FROM t1 WHERE a > -0+1) IN (SELECT a, a); +SELECT a FROM t1 WHERE (SELECT a, a WHERE a < 0 INTERSECT +SELECT + 1 / + 1, a FROM t1 +WHERE a > -0 + 1) IN (SELECT a, a); +a +CREATE TABLE x (x INT); +INSERT INTO x (x) VALUES (1); +UPDATE x SET x = 1 WHERE x = 1; +INSERT INTO x (x) VALUES (1), (1); +WITH RECURSIVE x (x) AS ( +SELECT 1 INTERSECT +SELECT -(SELECT 1.000000 AS x +UNION +SELECT 1.000000 ORDER BY NOT x < 'x', +-(SELECT 1 + x/1.000000 IN (1, 1) FROM x +WHERE x ORDER BY 1 - x) DESC LIMIT 1 OFFSET 1 +) + 1 FROM x +) +SELECT DISTINCT x, 1, NULL, 1.000000 +FROM x +WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > +(SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) +ORDER BY x ASC, x DESC, x; +ERROR 22007: Truncated incorrect DECIMAL value: 'x' +DROP TABLE t1, x; +# # End of 10.4 tests # set optimizer_switch=default; diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result index 50625b2e1b5..b8713a4c06b 100644 --- a/mysql-test/main/subselect_no_semijoin.result +++ b/mysql-test/main/subselect_no_semijoin.result @@ -1323,7 +1323,7 @@ a SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` int(3) DEFAULT NULL + `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; create table t1 (a int); @@ -7489,6 +7489,45 @@ ERROR HY000: Illegal parameter data types row and boolean for operation '=' SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); ERROR HY000: Illegal parameter data types row and boolean for operation '=' # +# MDEV-29070 SIGSEGV in my_decimal::operator= and Assertion `0' failed +# in Item_type_holder::val_decimal on SELECT +# +CREATE TABLE t1(a INT UNIQUE); +INSERT INTO t1(a) VALUES (1); +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT 1, 1); +a +1 +SELECT a FROM t1 WHERE (SELECT a, a UNION SELECT 1, a FROM t1) IN (SELECT a, a); +a +1 +UPDATE t1 SET a = 0 +WHERE (SELECT a, a WHERE a < 0 INTERSECT +SELECT +1 / +1, a FROM t1 WHERE a > -0+1) IN (SELECT a, a); +SELECT a FROM t1 WHERE (SELECT a, a WHERE a < 0 INTERSECT +SELECT + 1 / + 1, a FROM t1 +WHERE a > -0 + 1) IN (SELECT a, a); +a +CREATE TABLE x (x INT); +INSERT INTO x (x) VALUES (1); +UPDATE x SET x = 1 WHERE x = 1; +INSERT INTO x (x) VALUES (1), (1); +WITH RECURSIVE x (x) AS ( +SELECT 1 INTERSECT +SELECT -(SELECT 1.000000 AS x +UNION +SELECT 1.000000 ORDER BY NOT x < 'x', +-(SELECT 1 + x/1.000000 IN (1, 1) FROM x +WHERE x ORDER BY 1 - x) DESC LIMIT 1 OFFSET 1 +) + 1 FROM x +) +SELECT DISTINCT x, 1, NULL, 1.000000 +FROM x +WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > +(SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) +ORDER BY x ASC, x DESC, x; +ERROR 22007: Truncated incorrect DECIMAL value: 'x' +DROP TABLE t1, x; +# # End of 10.4 tests # # diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c632c9fc94b..a8824adbdd8 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -3910,14 +3910,14 @@ bool subselect_union_engine::fix_length_and_dec(Item_cache **row) if (unit->first_select()->item_list.elements == 1) { - if (set_row(unit->types, row)) + if (set_row(unit->item_list, row)) return TRUE; item->collation.set(row[0]->collation); } else { bool maybe_null_saved= maybe_null; - if (set_row(unit->types, row)) + if (set_row(unit->item_list, row)) return TRUE; maybe_null= maybe_null_saved; } From ead61d9bd96b773a3bbacf16c20df7cc34d85c96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 24 Nov 2023 14:23:52 +0200 Subject: [PATCH 320/477] MDEV-32874 Test innodb.innodb-table-online,crypt occasionally fails Let us make the test compatible with ./mtr --repeat and convert variable_value to integer, so that comparisons like 16>9 will work as intended, instead of being compared as '16'<'9'. --- .../suite/innodb/r/innodb-table-online.result | 30 +++++++++-------- .../suite/innodb/t/innodb-table-online.test | 32 +++++++++++-------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-table-online.result b/mysql-test/suite/innodb/r/innodb-table-online.result index 8078daad633..5c8810d94c6 100644 --- a/mysql-test/suite/innodb/r/innodb-table-online.result +++ b/mysql-test/suite/innodb/r/innodb-table-online.result @@ -1,3 +1,5 @@ +SET GLOBAL innodb_monitor_reset_all=all; +SET GLOBAL innodb_monitor_reset_all=default; call mtr.add_suppression("InnoDB: Warning: Small buffer pool size"); call mtr.add_suppression("InnoDB: Error: table 'test/t1'"); call mtr.add_suppression("MySQL is trying to open a table handle but the .ibd file for"); @@ -185,13 +187,13 @@ Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SET @merge_encrypt_0= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_0= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_0= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); connection con1; SHOW CREATE TABLE t1; @@ -253,13 +255,13 @@ ddl_pending_alter_table 1 ddl_sort_file_alter_table 0 ddl_log_file_alter_table 1 SET @merge_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SELECT (@merge_encrypt_1-@merge_encrypt_0)- @@ -280,16 +282,16 @@ ddl_pending_alter_table 0 ddl_sort_file_alter_table 0 ddl_log_file_alter_table 1 SET @merge_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SET @rowlog_decrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_decrypted'); 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; @@ -342,16 +344,16 @@ CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK SET @merge_encrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SET @rowlog_decrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_decrypted'); SELECT (@merge_encrypt_2-@merge_encrypt_1)- diff --git a/mysql-test/suite/innodb/t/innodb-table-online.test b/mysql-test/suite/innodb/t/innodb-table-online.test index a89073db4f7..d3e29a63f91 100644 --- a/mysql-test/suite/innodb/t/innodb-table-online.test +++ b/mysql-test/suite/innodb/t/innodb-table-online.test @@ -3,6 +3,10 @@ --source include/have_debug.inc --source include/have_debug_sync.inc +SET GLOBAL innodb_monitor_reset_all=all; +--disable_warnings +SET GLOBAL innodb_monitor_reset_all=default; +--enable_warnings let $innodb_metrics_select= SELECT name, count FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE subsystem = 'ddl'; @@ -171,13 +175,13 @@ EXPLAIN SELECT COUNT(*) FROM t1 WHERE c2 > 3; ANALYZE TABLE t1; SET @merge_encrypt_0= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_0= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_0= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); connection con1; @@ -222,13 +226,13 @@ while ($c) eval $innodb_metrics_select; SET @merge_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SELECT @@ -250,16 +254,16 @@ reap; eval $innodb_metrics_select; SET @merge_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SET @rowlog_decrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_decrypted'); # Accumulate and apply some modification log. @@ -296,16 +300,16 @@ SELECT COUNT(c22f) FROM t1; CHECK TABLE t1; SET @merge_encrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SET @rowlog_decrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_decrypted'); SELECT From 2f467de4c4851d2f9b0f3bec54f748d92349582a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 24 Nov 2023 14:25:32 +0200 Subject: [PATCH 321/477] MDEV-32873 Test innodb.innodb-index-online occasionally fails Let us wait for the completion of purge before testing the KILL of CREATE INDEX c2d ON t1(c2), so that there will be no table handle acquisition by a purge task before the operation is rolled back. Also, let us make the test compatible with ./mtr --repeat, and convert variable_value from string to integer so that any comparisons will be performed correctly. --- .../suite/innodb/r/innodb-index-online.result | 31 +++++++++-------- .../suite/innodb/t/innodb-index-online.test | 33 +++++++++++-------- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-index-online.result b/mysql-test/suite/innodb/r/innodb-index-online.result index e6b69f8f5cc..5a287e58d8a 100644 --- a/mysql-test/suite/innodb/r/innodb-index-online.result +++ b/mysql-test/suite/innodb/r/innodb-index-online.result @@ -1,3 +1,5 @@ +SET GLOBAL innodb_monitor_reset_all=all; +SET GLOBAL innodb_monitor_reset_all=default; call mtr.add_suppression("InnoDB: Warning: Small buffer pool size"); SET @global_innodb_file_per_table_orig = @@global.innodb_file_per_table; SET GLOBAL innodb_file_per_table = on; @@ -155,6 +157,7 @@ test t1_c2_stats GEN_CLUST_INDEX LAST_UPDATE size 1 NULL Number of pages in the connection con1; KILL QUERY @id; ERROR 70100: Query execution was interrupted +SET GLOBAL innodb_max_purge_lag_wait=0; SET DEBUG_SYNC = 'row_log_apply_before SIGNAL c2d_created WAIT_FOR kill_done'; CREATE INDEX c2d ON t1(c2); connection default; @@ -221,13 +224,13 @@ t1 CREATE TABLE `t1` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci STATS_PERSISTENT=1 connection default; SET @merge_encrypt_0= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_0= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_0= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); connection con1; SET DEBUG_SYNC = 'row_log_apply_before SIGNAL c2e_created WAIT_FOR dml2_done'; @@ -274,13 +277,13 @@ name pos c2 0 c3 1 SET @merge_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SELECT (@merge_encrypt_1-@merge_encrypt_0)- @@ -320,16 +323,16 @@ ddl_pending_alter_table 0 ddl_sort_file_alter_table 0 ddl_log_file_alter_table 1 SET @merge_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SET @rowlog_decrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_decrypted'); connection con1; SET DEBUG_SYNC = 'row_log_apply_before SIGNAL c2f_created WAIT_FOR dml3_done'; @@ -405,16 +408,16 @@ ddl_sort_file_alter_table 0 ddl_log_file_alter_table 2 connection default; SET @merge_encrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SET @rowlog_decrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_decrypted'); SELECT (@merge_encrypt_2-@merge_encrypt_1)- diff --git a/mysql-test/suite/innodb/t/innodb-index-online.test b/mysql-test/suite/innodb/t/innodb-index-online.test index f8eb8957911..96ee3149518 100644 --- a/mysql-test/suite/innodb/t/innodb-index-online.test +++ b/mysql-test/suite/innodb/t/innodb-index-online.test @@ -4,6 +4,10 @@ --source include/have_debug_sync.inc --source include/no_valgrind_without_big.inc +SET GLOBAL innodb_monitor_reset_all=all; +--disable_warnings +SET GLOBAL innodb_monitor_reset_all=default; +--enable_warnings let $innodb_metrics_select= SELECT name, count FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE subsystem = 'ddl'; @@ -158,6 +162,7 @@ let $ID= `SELECT @id := CONNECTION_ID()`; --error ER_QUERY_INTERRUPTED KILL QUERY @id; +SET GLOBAL innodb_max_purge_lag_wait=0; SET DEBUG_SYNC = 'row_log_apply_before SIGNAL c2d_created WAIT_FOR kill_done'; --send CREATE INDEX c2d ON t1(c2); @@ -209,13 +214,13 @@ SHOW CREATE TABLE t1; connection default; SET @merge_encrypt_0= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_0= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_0= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); connection con1; @@ -254,13 +259,13 @@ INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_FIELDS sf ON si.index_id = sf.index_id WHERE si.name = '?c2e'; SET @merge_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SELECT @@ -297,16 +302,16 @@ ALTER TABLE t1 COMMENT 'testing if c2e will be dropped'; eval $innodb_metrics_select; SET @merge_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SET @rowlog_decrypt_1= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_decrypted'); connection con1; @@ -343,16 +348,16 @@ eval $innodb_metrics_select; connection default; SET @merge_encrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted'); SET @merge_decrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_merge_blocks_decrypted'); SET @rowlog_encrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted'); SET @rowlog_decrypt_2= -(SELECT variable_value FROM information_schema.global_status +(SELECT CAST(variable_value AS INTEGER) FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_decrypted'); SELECT From 85c157808bf10c7ef2093848fce734930e878e61 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Fri, 24 Nov 2023 20:39:12 +0700 Subject: [PATCH 322/477] MDEV-32867: ASAN errors in Item_func_json_contains_path::val_int upon PS execution This bug was caused by a patch for the task MDEV-32733. Incorrect memory root was used for allocation of memory pointed by the data memebr Item_func_json_contains_path::p_found. --- mysql-test/main/ps_mem_leaks.result | 9 +++++++++ mysql-test/main/ps_mem_leaks.test | 12 ++++++++++++ sql/item_jsonfunc.cc | 2 +- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/ps_mem_leaks.result b/mysql-test/main/ps_mem_leaks.result index 90e003f8e5c..2ddf47a992c 100644 --- a/mysql-test/main/ps_mem_leaks.result +++ b/mysql-test/main/ps_mem_leaks.result @@ -79,4 +79,13 @@ DEALLOCATE PREPARE stmt; DROP FUNCTION f1; DROP VIEW v1; DROP FUNCTION f2; +# +# MDEV-32867: ASAN errors in Item_func_json_contains_path::val_int upon PS execution +# +CREATE TABLE t1 (f BLOB) ENGINE=MyISAM; +PREPARE stmt FROM "SELECT * FROM t1 WHERE JSON_EXISTS(JSON_ARRAY('[true,1234567890]'), '$**.*') != JSON_CONTAINS_PATH(JSON_INSERT('{}', '$[1]', NULL), 'all', '$[1]')"; +EXECUTE stmt; +f +DEALLOCATE PREPARE stmt; +DROP TABLE t1; # End of 10.4 tests diff --git a/mysql-test/main/ps_mem_leaks.test b/mysql-test/main/ps_mem_leaks.test index a68d62fd293..dacb4ecabba 100644 --- a/mysql-test/main/ps_mem_leaks.test +++ b/mysql-test/main/ps_mem_leaks.test @@ -97,4 +97,16 @@ DROP FUNCTION f1; DROP VIEW v1; DROP FUNCTION f2; +--echo # +--echo # MDEV-32867: ASAN errors in Item_func_json_contains_path::val_int upon PS execution +--echo # +CREATE TABLE t1 (f BLOB) ENGINE=MyISAM; + +PREPARE stmt FROM "SELECT * FROM t1 WHERE JSON_EXISTS(JSON_ARRAY('[true,1234567890]'), '$**.*') != JSON_CONTAINS_PATH(JSON_INSERT('{}', '$[1]', NULL), 'all', '$[1]')"; +EXECUTE stmt; + +# Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + --echo # End of 10.4 tests diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 13eb9955fbd..6b96f46e082 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -1437,7 +1437,7 @@ bool Item_func_json_contains_path::fix_fields(THD *thd, Item **ref) if (!tmp_paths) { if (alloc_tmp_paths(thd, arg_count-2, &paths, &tmp_paths) || - (p_found= (bool *) alloc_root(thd->mem_root, + (p_found= (bool *) alloc_root(thd->active_stmt_arena_to_use()->mem_root, (arg_count-2)*sizeof(bool))) == NULL) return true; } From 934db2efb623f25c953415f7c591e66cb92c0425 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 24 Nov 2023 18:48:27 +0100 Subject: [PATCH 323/477] MDEV-32875 SERVER_STATUS_AUTOCOMMIT set after connecting, if autocommit=0 After successful connection, server always sets SERVER_STATUS_AUTOCOMMIT in server_status in the OK packet. This is wrong, if global variable autocommit=0. Fixed THD::init(), added mysql_client_test test. Thanks to Diego Dupin for the providing the patch. Signed-off-by: Vladislav Vaintroub --- sql/sql_class.cc | 4 +++- tests/mysql_client_test.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index bee793b7d0f..184aa731f3a 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1227,7 +1227,9 @@ void THD::init() user_time.val= start_time= start_time_sec_part= 0; - server_status= SERVER_STATUS_AUTOCOMMIT; + server_status= 0; + if (variables.option_bits & OPTION_AUTOCOMMIT) + server_status|= SERVER_STATUS_AUTOCOMMIT; if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; if (variables.sql_mode & MODE_ANSI_QUOTES) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index a5178837f97..da04b078e76 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -21770,6 +21770,44 @@ static void test_mdev_30159() myquery(rc); } +/* + Check that server_status returned after connecting to server + is consistent with the value of autocommit variable. +*/ +static void test_connect_autocommit() +{ + int rc; + my_bool autocommit[]= {0, 1}; + int i; + rc= mysql_query(mysql, "SET @save_autocommit=@@global.autocommit"); + myquery(rc); + for (i= 0; i < 2; i++) + { + MYSQL *con; + char query[100]; + int autocommit_val; + + con= mysql_client_init(NULL); + DIE_UNLESS(con); + autocommit_val = autocommit[i]; + snprintf(query, sizeof(query), "SET global autocommit=%d", autocommit_val); + rc= mysql_query(mysql, query); + myquery(rc); + + if (!(mysql_real_connect(con, opt_host, opt_user, opt_password, current_db, + opt_port, opt_unix_socket, 0))) + { + fprintf(stderr, "Failed to connect to database: Error: %s\n", + mysql_error(con)); + exit(1); + } + DIE_UNLESS(!!(con->server_status & SERVER_STATUS_AUTOCOMMIT) == autocommit_val); + mysql_close(con); + } + rc= mysql_query(mysql, "SET global autocommit=@save_autocommit"); + myquery(rc); +} + static struct my_tests_st my_tests[]= { { "test_mdev_20516", test_mdev_20516 }, { "test_mdev24827", test_mdev24827 }, @@ -22074,6 +22112,7 @@ static struct my_tests_st my_tests[]= { { "test_mdev18408", test_mdev18408 }, { "test_mdev20261", test_mdev20261 }, { "test_mdev_30159", test_mdev_30159 }, + { "test_connect_autocommit", test_connect_autocommit}, { 0, 0 } }; From d8e448ba1b8834bcf3e358ab7b0a369eeff993ba Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 25 Nov 2023 10:33:06 +0100 Subject: [PATCH 324/477] MDEV-32168 fix failing tests followup for a7d186a17d3 --- mysql-test/suite/engines/funcs/r/rpl_row_until.result | 4 +++- mysql-test/suite/engines/funcs/r/rpl_slave_status.result | 1 - mysql-test/suite/engines/funcs/t/rpl_server_id1.test | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/engines/funcs/r/rpl_row_until.result b/mysql-test/suite/engines/funcs/r/rpl_row_until.result index 82268ce72eb..d5085a4feaf 100644 --- a/mysql-test/suite/engines/funcs/r/rpl_row_until.result +++ b/mysql-test/suite/engines/funcs/r/rpl_row_until.result @@ -51,7 +51,9 @@ ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UN START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', MASTER_LOG_POS=MASTER_LOG_POS; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=MASTER_LOG_POS; -include/stop_slave.inc +include/wait_for_slave_io_to_start.inc +include/wait_for_slave_sql_to_stop.inc +include/stop_slave_io.inc RESET SLAVE; include/start_slave.inc include/rpl_reset.inc diff --git a/mysql-test/suite/engines/funcs/r/rpl_slave_status.result b/mysql-test/suite/engines/funcs/r/rpl_slave_status.result index 1c81cec2577..ef122b9ca92 100644 --- a/mysql-test/suite/engines/funcs/r/rpl_slave_status.result +++ b/mysql-test/suite/engines/funcs/r/rpl_slave_status.result @@ -36,7 +36,6 @@ connection slave; include/stop_slave.inc START SLAVE; include/wait_for_slave_sql_to_start.inc -include/wait_for_slave_io_to_stop.inc ==== Verify that Slave IO thread stopped with error ==== include/wait_for_slave_io_error.inc [errno=1045] ==== Cleanup (Note that slave IO thread is not running) ==== diff --git a/mysql-test/suite/engines/funcs/t/rpl_server_id1.test b/mysql-test/suite/engines/funcs/t/rpl_server_id1.test index 1412db46d3a..d0ac3b67108 100644 --- a/mysql-test/suite/engines/funcs/t/rpl_server_id1.test +++ b/mysql-test/suite/engines/funcs/t/rpl_server_id1.test @@ -25,6 +25,7 @@ insert into t1 values (1); --let $status_items= Last_IO_Errno, Last_IO_Error --source include/show_slave_status.inc +--let $rpl_only_running_threads= 1 --source include/stop_slave.inc reset slave; reset master; From 7317aadeeadf84bd973871d7a5efe04d3397b8c1 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 21 Nov 2023 00:12:02 +0100 Subject: [PATCH 325/477] perfschema.threads_mysql sporadic failures wait a bit more thoroughly for event scheduler to be fully started --- .../perfschema/include/pfs_running_event_scheduler.inc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/perfschema/include/pfs_running_event_scheduler.inc b/mysql-test/suite/perfschema/include/pfs_running_event_scheduler.inc index 219a41051fb..313c0ed8ca9 100644 --- a/mysql-test/suite/perfschema/include/pfs_running_event_scheduler.inc +++ b/mysql-test/suite/perfschema/include/pfs_running_event_scheduler.inc @@ -1,10 +1,10 @@ -# threads are removed from: +# threads are added to: # - information_schema.processlist # - performance_schema.threads # at different times, so we may have to wait a little more -# for the event_scheduler to shutdown +# for the event_scheduler to start # let $wait_condition= SELECT COUNT(*) = 1 FROM performance_schema.threads - WHERE name like 'thread/sql/event%'; + WHERE name LIKE 'thread/sql/event%' AND processlist_command IS NOT NULL; --source include/wait_condition.inc From d1ca8fbb76c8537ce6c025ca1f226a7baeed7cfb Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 22 Nov 2023 22:29:11 +0100 Subject: [PATCH 326/477] Backport MEM_ROOT::flags from 10.7 --- include/my_alloc.h | 3 ++- mysys/my_alloc.c | 27 ++++++++++++--------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/include/my_alloc.h b/include/my_alloc.h index 6399ce67667..6161f5cdb2a 100644 --- a/include/my_alloc.h +++ b/include/my_alloc.h @@ -49,7 +49,8 @@ typedef struct st_mem_root first free block in queue test counter (if it exceed MAX_BLOCK_USAGE_BEFORE_DROP block will be dropped in 'used' list) */ - unsigned int first_block_usage; + unsigned short first_block_usage; + unsigned short flags; #ifdef PROTECT_STATEMENT_MEMROOT int read_only; diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 4a5e48c9e80..493fb92aa52 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -23,9 +23,11 @@ #undef EXTRA_DEBUG #define EXTRA_DEBUG +#define ROOT_FLAG_THREAD_SPECIFIC 1 + /* data packed in MEM_ROOT -> min_malloc */ -#define MALLOC_FLAG(A) ((A & 1) ? MY_THREAD_SPECIFIC : 0) +#define MALLOC_FLAG(root) (((root)->flags & ROOT_FLAG_THREAD_SPECIFIC) ? MY_THREAD_SPECIFIC : 0) #define TRASH_MEM(X) TRASH_FREE(((char*)(X) + ((X)->size-(X)->left)), (X)->left) @@ -50,9 +52,6 @@ Although error can happen during execution of this function if pre_alloc_size is non-0 it won't be reported. Instead it will be reported as error in first alloc_root() on this memory root. - - We don't want to change the structure size for MEM_ROOT. - Because of this, we store in MY_THREAD_SPECIFIC as bit 1 in block_size */ void init_alloc_root(MEM_ROOT *mem_root, const char *name, size_t block_size, @@ -65,9 +64,10 @@ void init_alloc_root(MEM_ROOT *mem_root, const char *name, size_t block_size, mem_root->free= mem_root->used= mem_root->pre_alloc= 0; mem_root->min_malloc= 32; - mem_root->block_size= (block_size - ALLOC_ROOT_MIN_BLOCK_SIZE) & ~1; - if (MY_TEST(my_flags & MY_THREAD_SPECIFIC)) - mem_root->block_size|= 1; + mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE; + mem_root->flags= 0; + if (my_flags & MY_THREAD_SPECIFIC) + mem_root->flags|= ROOT_FLAG_THREAD_SPECIFIC; mem_root->error_handler= 0; mem_root->block_num= 4; /* We shift this with >>2 */ @@ -119,8 +119,7 @@ void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, DBUG_ENTER("reset_root_defaults"); DBUG_ASSERT(alloc_root_inited(mem_root)); - mem_root->block_size= (((block_size - ALLOC_ROOT_MIN_BLOCK_SIZE) & ~1) | - (mem_root->block_size & 1)); + mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE; #if !(defined(HAVE_valgrind) && defined(EXTRA_DEBUG)) if (pre_alloc_size) { @@ -153,8 +152,7 @@ void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, } /* Allocate new prealloc block and add it to the end of free list */ if ((mem= (USED_MEM *) my_malloc(size, - MYF(MALLOC_FLAG(mem_root-> - block_size))))) + MYF(MALLOC_FLAG(mem_root))))) { mem->size= size; mem_root->total_alloc+= size; @@ -197,7 +195,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) length+=ALIGN_SIZE(sizeof(USED_MEM)); if (!(next = (USED_MEM*) my_malloc(length, MYF(MY_WME | ME_FATAL | - MALLOC_FLAG(mem_root->block_size))))) + MALLOC_FLAG(mem_root))))) { if (mem_root->error_handler) (*mem_root->error_handler)(); @@ -251,14 +249,13 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) } if (! next) { /* Time to alloc new block */ - block_size= (mem_root->block_size & ~1) * (mem_root->block_num >> 2); + block_size= mem_root->block_size * (mem_root->block_num >> 2); get_size= length+ALIGN_SIZE(sizeof(USED_MEM)); get_size= MY_MAX(get_size, block_size); if (!(next = (USED_MEM*) my_malloc(get_size, MYF(MY_WME | ME_FATAL | - MALLOC_FLAG(mem_root-> - block_size))))) + MALLOC_FLAG(mem_root))))) { if (mem_root->error_handler) (*mem_root->error_handler)(); From 69d78cd3f858748c0ee5ccd6ae1e77cfc063d57b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 23 Nov 2023 09:56:56 +0100 Subject: [PATCH 327/477] move MEM_ROOT::read_only into flags --- include/my_alloc.h | 6 ++---- mysys/my_alloc.c | 9 ++------- sql/sp_head.cc | 6 +++--- sql/sql_prepare.cc | 8 ++++---- 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/include/my_alloc.h b/include/my_alloc.h index 6161f5cdb2a..8d7ebe013db 100644 --- a/include/my_alloc.h +++ b/include/my_alloc.h @@ -23,6 +23,8 @@ #define ALLOC_MAX_BLOCK_TO_DROP 4096 #define ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP 10 +#define ROOT_FLAG_READ_ONLY 4 + #ifdef __cplusplus extern "C" { #endif @@ -52,10 +54,6 @@ typedef struct st_mem_root unsigned short first_block_usage; unsigned short flags; -#ifdef PROTECT_STATEMENT_MEMROOT - int read_only; -#endif - void (*error_handler)(void); const char *name; } MEM_ROOT; diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 493fb92aa52..beda4d50480 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -24,6 +24,7 @@ #define EXTRA_DEBUG #define ROOT_FLAG_THREAD_SPECIFIC 1 +#define ROOT_FLAG_READ_ONLY 4 /* data packed in MEM_ROOT -> min_malloc */ @@ -74,9 +75,6 @@ void init_alloc_root(MEM_ROOT *mem_root, const char *name, size_t block_size, mem_root->first_block_usage= 0; mem_root->total_alloc= 0; mem_root->name= name; -#ifdef PROTECT_STATEMENT_MEMROOT - mem_root->read_only= 0; -#endif #if !(defined(HAVE_valgrind) && defined(EXTRA_DEBUG)) if (pre_alloc_size) @@ -218,10 +216,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) DBUG_ENTER("alloc_root"); DBUG_PRINT("enter",("root: %p name: %s", mem_root, mem_root->name)); DBUG_ASSERT(alloc_root_inited(mem_root)); - -#ifdef PROTECT_STATEMENT_MEMROOT - DBUG_ASSERT(mem_root->read_only == 0); -#endif + DBUG_ASSERT((mem_root->flags & ROOT_FLAG_READ_ONLY) == 0); DBUG_EXECUTE_IF("simulate_out_of_memory", { diff --git a/sql/sp_head.cc b/sql/sp_head.cc index b1a697ada2a..312d779b05a 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1477,7 +1477,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) { // Don't count a call ended with an error as normal run executed_counter= 0; - main_mem_root.read_only= 0; + main_mem_root.flags &= ~ROOT_FLAG_READ_ONLY; reset_instrs_executed_counter(); } #endif @@ -1597,10 +1597,10 @@ sp_head::execute(THD *thd, bool merge_da_on_success) #ifdef PROTECT_STATEMENT_MEMROOT if (!err_status) { - if (!main_mem_root.read_only && + if (!(main_mem_root.flags & ROOT_FLAG_READ_ONLY) && has_all_instrs_executed()) { - main_mem_root.read_only= 1; + main_mem_root.flags |= ROOT_FLAG_READ_ONLY; } ++executed_counter; DBUG_PRINT("info", ("execute counter: %lu", executed_counter)); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 5a2c39b160d..47de393e795 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -176,7 +176,7 @@ public: /* The following data member is wholly for debugging purpose. It can be used for possible crash analysis to determine how many times - the stored routine was executed before the mem_root marked read_only + the stored routine was executed before the mem_root marked ROOT_FLAG_READ_ONLY was requested for a memory chunk. Additionally, a value of this data member is output to the log with DBUG_PRINT. */ @@ -4489,7 +4489,7 @@ reexecute: #ifdef PROTECT_STATEMENT_MEMROOT // There was reprepare so the counter of runs should be reset executed_counter= 0; - mem_root->read_only= 0; + mem_root->flags &= ~ROOT_FLAG_READ_ONLY; #endif goto reexecute; } @@ -4498,7 +4498,7 @@ reexecute: #ifdef PROTECT_STATEMENT_MEMROOT if (!error) { - mem_root->read_only= 1; + mem_root->flags |= ROOT_FLAG_READ_ONLY; ++executed_counter; DBUG_PRINT("info", ("execute counter: %lu", executed_counter)); @@ -4507,7 +4507,7 @@ reexecute: { // Error on call shouldn't be counted as a normal run executed_counter= 0; - mem_root->read_only= 0; + mem_root->flags &= ~ROOT_FLAG_READ_ONLY; } #endif From 361a11decb364664b517858891bfacc67fd20c99 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 24 Nov 2023 19:58:11 +0100 Subject: [PATCH 328/477] backport MEM_ROOT::total_alloc removal from 10.5 to fix sizeof(MEM_ROOT) --- include/my_alloc.h | 1 - mysys/my_alloc.c | 7 ------- 2 files changed, 8 deletions(-) diff --git a/include/my_alloc.h b/include/my_alloc.h index 8d7ebe013db..bddc5e9c0d0 100644 --- a/include/my_alloc.h +++ b/include/my_alloc.h @@ -45,7 +45,6 @@ typedef struct st_mem_root /* if block have less memory it will be put in 'used' list */ size_t min_malloc; size_t block_size; /* initial block size */ - size_t total_alloc; unsigned int block_num; /* allocated blocks counter */ /* first free block in queue test counter (if it exceed diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index beda4d50480..983c4440243 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -73,7 +73,6 @@ void init_alloc_root(MEM_ROOT *mem_root, const char *name, size_t block_size, mem_root->error_handler= 0; mem_root->block_num= 4; /* We shift this with >>2 */ mem_root->first_block_usage= 0; - mem_root->total_alloc= 0; mem_root->name= name; #if !(defined(HAVE_valgrind) && defined(EXTRA_DEBUG)) @@ -84,7 +83,6 @@ void init_alloc_root(MEM_ROOT *mem_root, const char *name, size_t block_size, MYF(my_flags)))) { mem_root->free->size= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM)); - mem_root->total_alloc= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM)); mem_root->free->left= pre_alloc_size; mem_root->free->next= 0; TRASH_MEM(mem_root->free); @@ -142,7 +140,6 @@ void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, { /* remove block from the list and free it */ *prev= mem->next; - mem_root->total_alloc-= mem->size; my_free(mem); } else @@ -153,7 +150,6 @@ void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, MYF(MALLOC_FLAG(mem_root))))) { mem->size= size; - mem_root->total_alloc+= size; mem->left= pre_alloc_size; mem->next= *prev; *prev= mem_root->pre_alloc= mem; @@ -257,7 +253,6 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) DBUG_RETURN((void*) 0); /* purecov: inspected */ } mem_root->block_num++; - mem_root->total_alloc+= get_size; next->next= *prev; next->size= get_size; next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM)); @@ -416,7 +411,6 @@ void free_root(MEM_ROOT *root, myf MyFlags) old=next; next= next->next ; if (old != root->pre_alloc) { - root->total_alloc-= old->size; my_free(old); } } @@ -425,7 +419,6 @@ void free_root(MEM_ROOT *root, myf MyFlags) old=next; next= next->next; if (old != root->pre_alloc) { - root->total_alloc-= old->size; my_free(old); } } From c432c9ef19bf6ff40ab9551bcae202d7e1319878 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 23 Nov 2023 10:00:37 +0100 Subject: [PATCH 329/477] MDEV-32862 MYSQL struct in C/C and server differs move MYSQL::fields down, replacing MYSQL::unused5 this way only MYSQL::fields and MYSQL::field_alloc will still have different offset in C/C and the server, but all other MYSQL members will get back in sync. luckily, plugins shouldn't need MYSQL::fields or MYSQL::field_alloc added a check to ensure both MYSQL structures are always of the same size. --- include/mysql.h | 4 ++-- tests/mysql_client_fw.c | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index 89807c07fce..dd928fe0bf1 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -274,7 +274,6 @@ typedef struct st_mysql char *host,*user,*passwd,*unix_socket,*server_version,*host_info; char *info, *db; const struct charset_info_st *charset; - MYSQL_FIELD *fields; MEM_ROOT field_alloc; my_ulonglong affected_rows; my_ulonglong insert_id; /* id if insert on table with NEXTNR */ @@ -296,7 +295,8 @@ typedef struct st_mysql /* session-wide random string */ char scramble[SCRAMBLE_LENGTH+1]; my_bool auto_local_infile; - void *unused2, *unused3, *unused4, *unused5; + void *unused2, *unused3, *unused4; + MYSQL_FIELD *fields; LIST *stmts; /* list of all statements */ const struct st_mysql_methods *methods; diff --git a/tests/mysql_client_fw.c b/tests/mysql_client_fw.c index 75425aa98e4..f6e9bfc2713 100644 --- a/tests/mysql_client_fw.c +++ b/tests/mysql_client_fw.c @@ -1426,6 +1426,14 @@ int main(int argc, char **argv) tests_to_run[i]= NULL; } +#ifdef _WIN32 + /* must be the same in C/C and embedded, 1208 on 64bit, 968 on 32bit */ + compile_time_assert(sizeof(MYSQL) == 60*sizeof(void*)+728); +#else + /* must be the same in C/C and embedded, 1272 on 64bit, 964 on 32bit */ + compile_time_assert(sizeof(MYSQL) == 77*sizeof(void*)+656); +#endif + if (mysql_server_init(embedded_server_arg_count, embedded_server_args, (char**) embedded_server_groups)) From 5bb31bc88273ae00464afc489827dc536136955f Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 24 Nov 2023 12:05:52 +0530 Subject: [PATCH 330/477] MDEV-22230 : Unexpected ER_ERROR_ON_RENAME upon DROP non-existing FOREIGN KEY mysql_prepare_alter_table(): Alter table should check whether foreign key exists when it expected to exists and report the error in early stage dict_foreign_parse_drop_constraints(): Don't throw error if the foreign key constraints doesn't exist when if exists is given in the statement. --- mysql-test/main/alter_table.result | 3 +- mysql-test/main/alter_table.test | 1 + mysql-test/main/type_ranges.result | 4 +- mysql-test/main/type_ranges.test | 2 +- .../suite/innodb/r/fk_drop_alter.result | 44 +++++++++++++++++++ mysql-test/suite/innodb/t/fk_drop_alter.test | 35 +++++++++++++++ sql/sql_table.cc | 24 ++++++++++ storage/innobase/dict/dict0dict.cc | 19 +++++--- 8 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 mysql-test/suite/innodb/r/fk_drop_alter.result create mode 100644 mysql-test/suite/innodb/t/fk_drop_alter.test diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result index e778bf6603e..2d8c7d15851 100644 --- a/mysql-test/main/alter_table.result +++ b/mysql-test/main/alter_table.result @@ -1998,8 +1998,7 @@ ALTER TABLE ti1 DROP FOREIGN KEY fi1; affected rows: 0 info: Records: 0 Duplicates: 0 Warnings: 0 ALTER TABLE tm1 DROP FOREIGN KEY fm1; -affected rows: 2 -info: Records: 2 Duplicates: 0 Warnings: 0 +ERROR 42000: Can't DROP FOREIGN KEY `fm1`; check that it exists ALTER TABLE ti1 RENAME TO ti3; affected rows: 0 ALTER TABLE tm1 RENAME TO tm3; diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test index e83bc65c83e..98884e2a514 100644 --- a/mysql-test/main/alter_table.test +++ b/mysql-test/main/alter_table.test @@ -1700,6 +1700,7 @@ ALTER TABLE ti1 DROP PRIMARY KEY; ALTER TABLE tm1 DROP PRIMARY KEY; ALTER TABLE ti1 DROP FOREIGN KEY fi1; +--error ER_CANT_DROP_FIELD_OR_KEY ALTER TABLE tm1 DROP FOREIGN KEY fm1; ALTER TABLE ti1 RENAME TO ti3; diff --git a/mysql-test/main/type_ranges.result b/mysql-test/main/type_ranges.result index 784a394d8b5..cd7ea8dc07d 100644 --- a/mysql-test/main/type_ranges.result +++ b/mysql-test/main/type_ranges.result @@ -144,8 +144,10 @@ alter short drop default, DROP INDEX utiny, DROP INDEX ushort, DROP PRIMARY KEY, -DROP FOREIGN KEY any_name, +DROP FOREIGN KEY IF EXISTS any_name, ADD INDEX (auto); +Warnings: +Note 1091 Can't DROP FOREIGN KEY `any_name`; check that it exists LOCK TABLES t1 WRITE; ALTER TABLE t1 RENAME as t2, diff --git a/mysql-test/main/type_ranges.test b/mysql-test/main/type_ranges.test index 7bf29321d06..a69e3ac5796 100644 --- a/mysql-test/main/type_ranges.test +++ b/mysql-test/main/type_ranges.test @@ -76,7 +76,7 @@ alter short drop default, DROP INDEX utiny, DROP INDEX ushort, DROP PRIMARY KEY, -DROP FOREIGN KEY any_name, +DROP FOREIGN KEY IF EXISTS any_name, ADD INDEX (auto); LOCK TABLES t1 WRITE; diff --git a/mysql-test/suite/innodb/r/fk_drop_alter.result b/mysql-test/suite/innodb/r/fk_drop_alter.result new file mode 100644 index 00000000000..414f44f2c48 --- /dev/null +++ b/mysql-test/suite/innodb/r/fk_drop_alter.result @@ -0,0 +1,44 @@ +# +# MDEV-22230 : Unexpected ER_ERROR_ON_RENAME upon DROP +# non-existing FOREIGN KEY +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +ALTER TABLE t1 DROP FOREIGN KEY x, ALGORITHM=COPY; +ERROR 42000: Can't DROP FOREIGN KEY `x`; check that it exists +ALTER TABLE t1 DROP FOREIGN KEY x, ALGORITHM=INPLACE; +ERROR 42000: Can't DROP FOREIGN KEY `x`; check that it exists +DROP TABLE t1; +CREATE TABLE t1 (a INT, KEY(a)) ENGINE=InnoDB; +CREATE TABLE t2 (a INT, FOREIGN KEY fk_id (a) REFERENCES t1(a))ENGINE=InnoDB; +CREATE TABLE t3 (a INT, FOREIGN KEY fk_1 (a) REFERENCES t1(a))ENGINE=InnoDB; +ALTER TABLE t3 DROP FOREIGN KEY IF EXISTS fk_id; +Warnings: +Note 1091 Can't DROP FOREIGN KEY `fk_id`; check that it exists +DROP TABLE t3, t2; +ALTER TABLE t1 MODIFY COLUMN a VARCHAR(2), DROP FOREIGN KEY IF EXISTS x; +Warnings: +Note 1091 Can't DROP FOREIGN KEY `x`; check that it exists +DROP TABLE t1; +CREATE DATABASE best; +CREATE TABLE best.t1(f1 INT, KEY(f1))ENGINE=InnoDB; +CREATE TABLE best.t2(f1 INT, FOREIGN KEY foo(f1) REFERENCES t1(f1))ENGINE=InnoDB; +CREATE TABLE t1(f1 INT, KEY(f1))ENGINE=InnoDB; +CREATE TABLE t2(f1 INT, FOREIGN KEY foo(f1) REFERENCES t1(f1))ENGINE=InnoDB; +ALTER TABLE t2 DROP FOREIGN KEY foo; +ALTER TABLE t2 DROP FOREIGN KEY foo; +ERROR 42000: Can't DROP FOREIGN KEY `foo`; check that it exists +ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS foo; +Warnings: +Note 1091 Can't DROP FOREIGN KEY `foo`; check that it exists +SHOW CREATE TABLE best.t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) DEFAULT NULL, + KEY `foo` (`f1`), + CONSTRAINT `foo` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN; +ID FOR_NAME REF_NAME N_COLS TYPE +best/foo best/t2 best/t1 1 0 +DROP TABLE best.t2, best.t1, t2, t1; +DROP DATABASE best; diff --git a/mysql-test/suite/innodb/t/fk_drop_alter.test b/mysql-test/suite/innodb/t/fk_drop_alter.test new file mode 100644 index 00000000000..c79eb873d62 --- /dev/null +++ b/mysql-test/suite/innodb/t/fk_drop_alter.test @@ -0,0 +1,35 @@ +--source include/have_innodb.inc +--echo # +--echo # MDEV-22230 : Unexpected ER_ERROR_ON_RENAME upon DROP +--echo # non-existing FOREIGN KEY +--echo # +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +--error ER_CANT_DROP_FIELD_OR_KEY +ALTER TABLE t1 DROP FOREIGN KEY x, ALGORITHM=COPY; +--error ER_CANT_DROP_FIELD_OR_KEY +ALTER TABLE t1 DROP FOREIGN KEY x, ALGORITHM=INPLACE; +# Cleanup +DROP TABLE t1; + +CREATE TABLE t1 (a INT, KEY(a)) ENGINE=InnoDB; +CREATE TABLE t2 (a INT, FOREIGN KEY fk_id (a) REFERENCES t1(a))ENGINE=InnoDB; +CREATE TABLE t3 (a INT, FOREIGN KEY fk_1 (a) REFERENCES t1(a))ENGINE=InnoDB; +ALTER TABLE t3 DROP FOREIGN KEY IF EXISTS fk_id; +DROP TABLE t3, t2; +ALTER TABLE t1 MODIFY COLUMN a VARCHAR(2), DROP FOREIGN KEY IF EXISTS x; +DROP TABLE t1; + +CREATE DATABASE best; +CREATE TABLE best.t1(f1 INT, KEY(f1))ENGINE=InnoDB; +CREATE TABLE best.t2(f1 INT, FOREIGN KEY foo(f1) REFERENCES t1(f1))ENGINE=InnoDB; + +CREATE TABLE t1(f1 INT, KEY(f1))ENGINE=InnoDB; +CREATE TABLE t2(f1 INT, FOREIGN KEY foo(f1) REFERENCES t1(f1))ENGINE=InnoDB; +ALTER TABLE t2 DROP FOREIGN KEY foo; +--error ER_CANT_DROP_FIELD_OR_KEY +ALTER TABLE t2 DROP FOREIGN KEY foo; +ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS foo; +SHOW CREATE TABLE best.t2; +SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN; +DROP TABLE best.t2, best.t1, t2, t1; +DROP DATABASE best; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 4514421b7d2..897027cc73d 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -9056,6 +9056,30 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, goto err; case Alter_drop::FOREIGN_KEY: // Leave the DROP FOREIGN KEY names in the alter_info->drop_list. + /* If this is DROP FOREIGN KEY without IF EXIST, + we can now check does it exists and if not report a error. */ + if (!drop->drop_if_exists) + { + List fk_child_key_list; + table->file->get_foreign_key_list(thd, &fk_child_key_list); + if (fk_child_key_list.is_empty()) + { + fk_not_found: + my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop->type_name(), + drop->name); + goto err; + } + List_iterator fk_key_it(fk_child_key_list); + while (FOREIGN_KEY_INFO *f_key= fk_key_it++) + { + if (my_strcasecmp(system_charset_info, f_key->foreign_id->str, + drop->name) == 0) + goto fk_found; + } + goto fk_not_found; + fk_found: + break; + } break; } } diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 6fe40c75555..1245799b7d3 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -4592,6 +4592,7 @@ dict_foreign_parse_drop_constraints( const char* ptr1; const char* id; CHARSET_INFO* cs; + bool if_exists = false; ut_a(trx->mysql_thd); @@ -4645,6 +4646,7 @@ loop: ptr1 = dict_accept(cs, ptr1, "EXISTS", &success); if (success) { ptr = ptr1; + if_exists = true; } } @@ -4655,14 +4657,14 @@ loop: goto syntax_error; } - ut_a(*n < 1000); - (*constraints_to_drop)[*n] = id; - (*n)++; - if (std::find_if(table->foreign_set.begin(), - table->foreign_set.end(), - dict_foreign_matches_id(id)) - == table->foreign_set.end()) { + table->foreign_set.end(), + dict_foreign_matches_id(id)) + == table->foreign_set.end()) { + + if (if_exists) { + goto loop; + } if (!srv_read_only_mode) { FILE* ef = dict_foreign_err_file; @@ -4684,6 +4686,9 @@ loop: return(DB_CANNOT_DROP_CONSTRAINT); } + ut_a(*n < 1000); + (*constraints_to_drop)[*n] = id; + (*n)++; goto loop; syntax_error: From 18acf97dfdd089a16fe78e606f9871bac92ccfb5 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Wed, 22 Nov 2023 22:41:28 +0100 Subject: [PATCH 331/477] MDEV-32168: slave_error_param condition is never checked from the wait_for_slave_param.inc - Record unrecorded tests from `rpl` suite to `engines/funcs` suite (done by d8e448ba1b8834bcf3e358ab7b0a369eeff993ba): 1) Record test `rpl_row_until` from commit d95fa7e33279c6c6849eb053d85f1faa1c77e269 2) Record test `rpl_slave_status` from commit a7d186a17d35b2651f3ebee8aa3e49b68ded4d64 - Stop only running threads for `engines/funcs.rpl_server_id1.test` that is not the same as `rpl.rpl_server_id1.test` - Reviewer: --- mysql-test/suite/engines/funcs/r/rpl_server_id1.result | 2 +- mysql-test/suite/engines/funcs/t/rpl_server_id1.test | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/engines/funcs/r/rpl_server_id1.result b/mysql-test/suite/engines/funcs/r/rpl_server_id1.result index 001d1151843..6f64faba5fa 100644 --- a/mysql-test/suite/engines/funcs/r/rpl_server_id1.result +++ b/mysql-test/suite/engines/funcs/r/rpl_server_id1.result @@ -15,7 +15,7 @@ insert into t1 values (1); include/wait_for_slave_param.inc [Last_IO_Errno] Last_IO_Errno = '1593' Last_IO_Error = 'Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; these ids must be different for replication to work (or the --replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it).' -include/stop_slave.inc +include/stop_slave_sql.inc reset slave; reset master; drop table t1; diff --git a/mysql-test/suite/engines/funcs/t/rpl_server_id1.test b/mysql-test/suite/engines/funcs/t/rpl_server_id1.test index d0ac3b67108..8f0248ebbde 100644 --- a/mysql-test/suite/engines/funcs/t/rpl_server_id1.test +++ b/mysql-test/suite/engines/funcs/t/rpl_server_id1.test @@ -25,8 +25,7 @@ insert into t1 values (1); --let $status_items= Last_IO_Errno, Last_IO_Error --source include/show_slave_status.inc ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_sql.inc reset slave; reset master; drop table t1; From 20b0ec9aae38faaa4d249f67315cc5394eaea22e Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 27 Nov 2023 09:56:21 +0400 Subject: [PATCH 332/477] MDEV-32879 Server crash in my_decimal::operator= or unexpected ER_DUP_ENTRY upon comparison with INET6 and similar types This is the 10.6 version of the patch. Item_bool_rowready_func2, Item_func_between, Item_func_in did not check if a not-NULL argument of an arbitrary data type can produce a NULL value on conversion to INET6. This caused a crash on DBUG_ASSERT() in conversion failures, because the function returned SQL NULL for something that has Item::maybe_null() equal to false. Adding setting NULL-ability in such cases. Details: - Removing the code in Item_func::setup_args_and_comparator() performing character set aggregation with optional narrowing. This aggregation is done inside Arg_comparator::set_cmp_func_string(). So this code was redundant - Removing Item_func::setup_args_and_comparator() as it git simplified to just to two lines: convert_const_compared_to_int_field(thd); return cmp->set_cmp_func(thd, this, &args[0], &args[1], true); Using these lines directly in: - Item_bool_rowready_func2::fix_length_and_dec() - Item_func_nullif::fix_length_and_dec() - Adding a new virtual method: - Type_handler::Item_bool_rowready_func2_fix_length_and_dec(). - Adding tests detecting if the data type conversion can return SQL NULL into the following methods of Type_handler_fbt: - Item_bool_rowready_func2_fix_length_and_dec - Item_func_between_fix_length_and_dec - Item_func_in_fix_comparator_compatible_types --- .../mysql-test/type_inet/type_inet6.result | 75 +++++++++++++++++++ .../mysql-test/type_inet/type_inet6.test | 26 +++++++ sql/item_cmpfunc.cc | 67 ++++++----------- sql/item_cmpfunc.h | 28 ++++++- sql/item_func.h | 9 --- sql/item_sum.cc | 7 +- sql/sql_type.cc | 8 ++ sql/sql_type.h | 3 + sql/sql_type_fixedbin.h | 32 ++++++++ 9 files changed, 196 insertions(+), 59 deletions(-) diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.result b/plugin/type_inet/mysql-test/type_inet/type_inet6.result index 9c601697e4f..38af2c16076 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.result @@ -2283,3 +2283,78 @@ a Warnings: Warning 1292 Incorrect inet6 value: '' DROP TABLE t1; +# +# MDEV-32879 Server crash in my_decimal::operator= or unexpected ER_DUP_ENTRY upon comparison with INET6 and similar types +# +CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL); +INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01'); +SELECT c + (b = a) AS f, GROUP_CONCAT(c) FROM t1 GROUP BY f; +f GROUP_CONCAT(c) +NULL 2000-01-01 00:00:00.000000,1900-01-01 00:00:00.000000 +Warnings: +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL); +INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01'); +SELECT c + (b = a) AS f, COUNT(c) FROM t1 GROUP BY f; +f COUNT(c) +NULL 2 +Warnings: +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL); +INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01'); +SELECT c + (b = a) AS f FROM t1 ORDER BY f; +f +NULL +NULL +Warnings: +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL); +INSERT INTO t1 VALUES ('','::'),('','::'); +SELECT 1.00 + (b = a) AS f FROM t1 ORDER BY f; +f +NULL +NULL +Warnings: +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +SELECT 1.00 + (b BETWEEN a AND '') AS f FROM t1 ORDER BY f; +f +NULL +NULL +Warnings: +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +SELECT 1.00 + (b IN (a,'')) AS f FROM t1 ORDER BY f; +f +NULL +NULL +Warnings: +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +DROP TABLE t1; diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.test b/plugin/type_inet/mysql-test/type_inet/type_inet6.test index 771d8fbc347..32638573825 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6.test +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.test @@ -1675,3 +1675,29 @@ CREATE OR REPLACE TABLE t1 (a INET6); INSERT INTO t1 VALUES ('::'); SELECT * FROM t1 WHERE a IN ('','::1'); DROP TABLE t1; + +--echo # +--echo # MDEV-32879 Server crash in my_decimal::operator= or unexpected ER_DUP_ENTRY upon comparison with INET6 and similar types +--echo # + +CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL); +INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01'); +SELECT c + (b = a) AS f, GROUP_CONCAT(c) FROM t1 GROUP BY f; +DROP TABLE t1; + +CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL); +INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01'); +SELECT c + (b = a) AS f, COUNT(c) FROM t1 GROUP BY f; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL); +INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01'); +SELECT c + (b = a) AS f FROM t1 ORDER BY f; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL); +INSERT INTO t1 VALUES ('','::'),('','::'); +SELECT 1.00 + (b = a) AS f FROM t1 ORDER BY f; +SELECT 1.00 + (b BETWEEN a AND '') AS f FROM t1 ORDER BY f; +SELECT 1.00 + (b IN (a,'')) AS f FROM t1 ORDER BY f; +DROP TABLE t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d63db33edb3..48215c60768 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -457,40 +457,6 @@ void Item_bool_func::raise_note_if_key_become_unused(THD *thd, const Item_args & } -bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp) -{ - DBUG_ASSERT(arg_count >= 2); // Item_func_nullif has arg_count == 3 - - if (args[0]->cmp_type() == STRING_RESULT && - args[1]->cmp_type() == STRING_RESULT) - { - 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; - } - // Convert constants when compared to int/year field - DBUG_ASSERT(functype() != LIKE_FUNC); - convert_const_compared_to_int_field(thd); - - return cmp->set_cmp_func(thd, this, &args[0], &args[1], true); -} - - /* Comparison operators remove arguments' dependency on PAD_CHAR_TO_FULL_LENGTH in case of PAD SPACE comparison collations: trailing spaces do not affect @@ -520,8 +486,15 @@ bool Item_bool_rowready_func2::fix_length_and_dec() if (!args[0] || !args[1]) return FALSE; Item_args old_args(args[0], args[1]); - if (setup_args_and_comparator(thd, &cmp)) + convert_const_compared_to_int_field(thd); + Type_handler_hybrid_field_type tmp; + if (tmp.aggregate_for_comparison(func_name_cstring(), args, 2, false) || + tmp.type_handler()->Item_bool_rowready_func2_fix_length_and_dec(thd, + this)) + { + DBUG_ASSERT(thd->is_error()); return true; + } raise_note_if_key_become_unused(thd, old_args); return false; } @@ -541,21 +514,14 @@ bool Item_bool_rowready_func2::fix_length_and_dec() */ int Arg_comparator::set_cmp_func(THD *thd, Item_func_or_sum *owner_arg, + const Type_handler *compare_handler, Item **a1, Item **a2) { owner= owner_arg; set_null= set_null && owner_arg; a= a1; b= a2; - Item *tmp_args[2]= {*a1, *a2}; - Type_handler_hybrid_field_type tmp; - if (tmp.aggregate_for_comparison(owner_arg->func_name_cstring(), tmp_args, 2, - false)) - { - DBUG_ASSERT(thd->is_error()); - return 1; - } - m_compare_handler= tmp.type_handler(); + m_compare_handler= compare_handler; return m_compare_handler->set_comparator_func(thd, this); } @@ -606,6 +572,14 @@ 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. Allow reinterpted superset as subset. + 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= false; if (owner->type() == Item::FUNC_ITEM) @@ -2816,8 +2790,9 @@ Item_func_nullif::fix_length_and_dec() fix_char_length(args[2]->max_char_length()); set_maybe_null(); m_arg0= args[0]; - if (setup_args_and_comparator(thd, &cmp)) - return TRUE; + convert_const_compared_to_int_field(thd); + if (cmp.set_cmp_func(thd, this, &args[0], &args[1], true/*set_null*/)) + return true; /* A special code for EXECUTE..PREPARE. diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index ae0efdd6ae1..2e8a28cdd17 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -57,6 +57,7 @@ class Arg_comparator: public Sql_alloc // when one of arguments is NULL. int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg, + const Type_handler *compare_handler, Item **a1, Item **a2); int compare_not_null_values(longlong val1, longlong val2) @@ -95,11 +96,24 @@ public: bool set_cmp_func_decimal(THD *thd); inline int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg, - Item **a1, Item **a2, bool set_null_arg) + const Type_handler *compare_handler, + Item **a1, Item **a2, bool set_null_arg) { set_null= set_null_arg; - return set_cmp_func(thd, owner_arg, a1, a2); + return set_cmp_func(thd, owner_arg, compare_handler, a1, a2); } + int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg, + Item **a1, Item **a2, bool set_null_arg) + { + Item *tmp_args[2]= { *a1, *a2 }; + Type_handler_hybrid_field_type tmp; + if (tmp.aggregate_for_comparison(owner_arg->func_name_cstring(), + tmp_args, 2, false)) + return 1; + return set_cmp_func(thd, owner_arg, tmp.type_handler(), + a1, a2, set_null_arg); + } + inline int compare() { return (this->*func)(); } int compare_string(); // compare args[0] & args[1] @@ -562,9 +576,17 @@ public: return this; } bool fix_length_and_dec() override; + bool fix_length_and_dec_generic(THD *thd, + const Type_handler *compare_handler) + { + DBUG_ASSERT(args == tmp_arg); + return cmp.set_cmp_func(thd, this, compare_handler, + tmp_arg, tmp_arg + 1, true/*set_null*/); + } int set_cmp_func(THD *thd) { - return cmp.set_cmp_func(thd, this, tmp_arg, tmp_arg + 1, true); + DBUG_ASSERT(args == tmp_arg); + return cmp.set_cmp_func(thd, this, tmp_arg, tmp_arg + 1, true/*set_null*/); } CHARSET_INFO *compare_collation() const override { return cmp.compare_collation(); } diff --git a/sql/item_func.h b/sql/item_func.h index a1712745a89..1390fab014f 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -388,15 +388,6 @@ public: } } void convert_const_compared_to_int_field(THD *thd); - /** - Prepare arguments and setup a comparator. - Used in Item_func_xxx with two arguments and a comparator, - e.g. Item_bool_func2 and Item_func_nullif. - args[0] or args[1] can be modified: - - converted to character set and collation of the operation - - or replaced to an Item_int_with_ref - */ - bool setup_args_and_comparator(THD *thd, Arg_comparator *cmp); Item_func *get_item_func() override { return this; } bool is_simplified_cond_processor(void *arg) override { return const_item() && !val_int(); } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index a26adb17e28..b3e600824de 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1288,9 +1288,14 @@ void Item_sum_min_max::setup_hybrid(THD *thd, Item *item, Item *value_arg) /* Don't cache value, as it will change */ if (!item->const_item()) arg_cache->set_used_tables(RAND_TABLE_BIT); + DBUG_ASSERT(item->type_handler_for_comparison() == + value->type_handler_for_comparison()); + DBUG_ASSERT(item->type_handler_for_comparison() == + arg_cache->type_handler_for_comparison()); cmp= new (thd->mem_root) Arg_comparator(); if (cmp) - cmp->set_cmp_func(thd, this, (Item**)&arg_cache, (Item**)&value, FALSE); + cmp->set_cmp_func(thd, this, item->type_handler_for_comparison(), + (Item**)&arg_cache, (Item**)&value, FALSE); DBUG_VOID_RETURN; } diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 2c12f1b7139..fec7f0edb9f 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -5679,6 +5679,14 @@ Type_handler_string_result::Item_func_hybrid_field_type_get_date( /***************************************************************************/ +bool Type_handler::Item_bool_rowready_func2_fix_length_and_dec(THD *thd, + Item_bool_rowready_func2 *func) const +{ + return func->fix_length_and_dec_generic(thd, this); +} + +/***************************************************************************/ + bool Type_handler_numeric:: Item_func_between_fix_length_and_dec(Item_func_between *func) const { diff --git a/sql/sql_type.h b/sql/sql_type.h index fc270915e5b..11ca46517fc 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -55,6 +55,7 @@ class Item_hybrid_func; class Item_func_min_max; class Item_func_hybrid_field_type; class Item_bool_func2; +class Item_bool_rowready_func2; class Item_func_between; class Item_func_in; class Item_func_round; @@ -4271,6 +4272,8 @@ public: } virtual bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, Item *a, Item *b) const= 0; + virtual bool Item_bool_rowready_func2_fix_length_and_dec(THD *thd, + Item_bool_rowready_func2 *func) const; virtual bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *, diff --git a/sql/sql_type_fixedbin.h b/sql/sql_type_fixedbin.h index 9bd23a949fa..1ebf559eabb 100644 --- a/sql/sql_type_fixedbin.h +++ b/sql/sql_type_fixedbin.h @@ -136,6 +136,21 @@ public: return Fbt_null(item, false).is_null(); } + /* + Check at fix_fields() time if any of the items can return a nullable + value on conversion to Fbt. + */ + static bool fix_fields_maybe_null_on_conversion_to_fbt(Item **items, + uint count) + { + for (uint i= 0; i < count; i++) + { + if (Fbt::fix_fields_maybe_null_on_conversion_to_fbt(items[i])) + return true; + } + return false; + } + public: Fbt(Item *item, bool *error, bool warn= true) @@ -1532,6 +1547,16 @@ public: Fbt_null na(a), nb(b); return !na.is_null() && !nb.is_null() && !na.cmp(nb); } + bool Item_bool_rowready_func2_fix_length_and_dec(THD *thd, + Item_bool_rowready_func2 *func) const override + { + if (Type_handler::Item_bool_rowready_func2_fix_length_and_dec(thd, func)) + return true; + if (!func->maybe_null() && + Fbt::fix_fields_maybe_null_on_conversion_to_fbt(func->arguments(), 2)) + func->set_maybe_null(); + return false; + } bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name, Type_handler_hybrid_field_type *h, Type_all_attributes *attr, @@ -1713,6 +1738,9 @@ public: bool Item_func_between_fix_length_and_dec(Item_func_between *func) const override { + if (!func->maybe_null() && + Fbt::fix_fields_maybe_null_on_conversion_to_fbt(func->arguments(), 3)) + func->set_maybe_null(); return false; } longlong Item_func_between_val_int(Item_func_between *func) const override @@ -1735,6 +1763,10 @@ public: Item_func_in *func) const override { + if (!func->maybe_null() && + Fbt::fix_fields_maybe_null_on_conversion_to_fbt(func->arguments(), + func->argument_count())) + func->set_maybe_null(); if (func->compatible_types_scalar_bisection_possible()) { return func->value_list_convert_const_to_int(thd) || From 9e424b6290e204437683e3413a0f4ff317e9abe4 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 23 Nov 2023 16:49:26 +0200 Subject: [PATCH 333/477] MENT-1707 Crash at reload_acl_and_cache The stack function trace for this bug is: libc my_free free_root acl_reload The crash happens because acl_memroot gets corrupted. The issue was that during FLUSH PRIVILEGES we discard the old privileges and create new ones. We have protection in place that no one can accesses the privileges during this time. However one short piece of code called during login of a new user, or change password, was not properly protected, which could in some very rare circumstances case a memory overwrite of a MEMROOT object if at the same time another thread calls FLUSH PRIVILEGES. This it issue is fixed by adding protection around set_user_salt(). I also added asserts to other code that is using the acl_memroot to ensure that it is properly proteced everywhere. --- sql/sql_acl.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 34011bf1a76..82f8101e929 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -934,6 +934,7 @@ class User_table_tabular: public User_table int get_auth(THD *thd, MEM_ROOT *root, ACL_USER *u) const { + mysql_mutex_assert_owner(&acl_cache->lock); u->alloc_auth(root, 1); if (have_password()) { @@ -2144,6 +2145,9 @@ static bool validate_password(THD *thd, const LEX_CSTRING &user, static int set_user_salt(ACL_USER::AUTH *auth, plugin_ref plugin) { st_mysql_auth *info= (st_mysql_auth *) plugin_decl(plugin)->info; + + mysql_mutex_assert_owner(&acl_cache->lock); + if (info->interface_version >= 0x0202 && info->preprocess_hash && auth->auth_string.length) { @@ -2178,6 +2182,8 @@ static int set_user_auth(THD *thd, const LEX_CSTRING &user, plugin_ref plugin= get_auth_plugin(thd, auth->plugin, &unlock_plugin); int res= 1; + mysql_mutex_assert_owner(&acl_cache->lock); + if (!plugin) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, @@ -2254,10 +2260,13 @@ static bool set_user_salt_if_needed(ACL_USER *user_copy, int curr_auth, if (auth_copy->salt.str) return 0; // already done - if (set_user_salt(auth_copy, plugin)) - return 1; - mysql_mutex_lock(&acl_cache->lock); + if (set_user_salt(auth_copy, plugin)) + { + mysql_mutex_unlock(&acl_cache->lock); + return 1; + } + ACL_USER *user= find_user_exact(user_copy->host.hostname, user_copy->user.str); // make sure the user wasn't altered or dropped meanwhile if (user) @@ -3280,6 +3289,7 @@ ACL_USER::ACL_USER(THD *thd, const LEX_USER &combo, const Account_options &options, const ulong privileges) { + mysql_mutex_assert_owner(&acl_cache->lock); user= safe_lexcstrdup_root(&acl_memroot, combo.user); update_hostname(&host, safe_strdup_root(&acl_memroot, combo.host.str)); hostname_length= combo.host.length; @@ -3296,6 +3306,8 @@ static int acl_user_update(THD *thd, ACL_USER *acl_user, uint nauth, const ulong privileges) { ACL_USER_PARAM::AUTH *work_copy= NULL; + mysql_mutex_assert_owner(&acl_cache->lock); + if (nauth) { if (!(work_copy= (ACL_USER_PARAM::AUTH*) @@ -4971,6 +4983,7 @@ update_role_mapping(LEX_CSTRING *user, LEX_CSTRING *host, LEX_CSTRING *role, return 0; } + mysql_mutex_assert_owner(&acl_cache->lock); /* allocate a new entry that will go in the hash */ ROLE_GRANT_PAIR *hash_entry= new (&acl_memroot) ROLE_GRANT_PAIR; if (hash_entry->init(&acl_memroot, user->str, host->str, @@ -5035,6 +5048,7 @@ replace_proxies_priv_table(THD *thd, TABLE *table, const LEX_USER *user, DBUG_ENTER("replace_proxies_priv_table"); + mysql_mutex_assert_owner(&acl_cache->lock); if (!table) { my_error(ER_NO_SUCH_TABLE, MYF(0), MYSQL_SCHEMA_NAME.str, From dc1165419a2e08506b2a6c2f8bc944b20ae57dd4 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 23 Nov 2023 16:59:21 +0200 Subject: [PATCH 334/477] Do not use MEM_ROOT in set_killed_no_mutex() The reason for this change are the following: - If we call set_killed() from one thread to kill another thread with a message, there may be concurrent usage of the MEM_ROOT which is not supported (this could cause memory corruption). We do not currently have code that does this, but the API allows this and it is better to be fix the issue before it happens. - The per thread memory tracking does not work if one thread uses another threads MEM_ROOT. - set_killed() can be called if a MEM_ROOT allocation fails. In this case it is not good to try to allocate more memory from potentially the same MEM_ROOT. Fix is to use my_malloc() instead of mem_root for killed messages. --- sql/sql_class.cc | 11 ++++++++++- sql/sql_class.h | 3 ++- sql/wsrep_thd.cc | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 184aa731f3a..b4893581e1a 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1649,6 +1649,7 @@ void THD::reset_for_reuse() wsrep_cs().reset_error(); wsrep_aborter= 0; wsrep_abort_by_kill= NOT_KILLED; + my_free(wsrep_abort_by_kill_err); wsrep_abort_by_kill_err= 0; #ifndef DBUG_OFF wsrep_killed_state= 0; @@ -1689,6 +1690,8 @@ THD::~THD() #ifdef WITH_WSREP mysql_cond_destroy(&COND_wsrep_thd); + my_free(wsrep_abort_by_kill_err); + wsrep_abort_by_kill_err= 0; #endif mdl_context.destroy(); @@ -1708,6 +1711,7 @@ THD::~THD() main_lex.free_set_stmt_mem_root(); free_root(&main_mem_root, MYF(0)); my_free(m_token_array); + my_free(killed_err); main_da.free_memory(); if (tdc_hash_pins) lf_hash_put_pins(tdc_hash_pins); @@ -2131,7 +2135,11 @@ void THD::reset_killed() mysql_mutex_assert_not_owner(&LOCK_thd_kill); mysql_mutex_lock(&LOCK_thd_kill); killed= NOT_KILLED; - killed_err= 0; + if (unlikely(killed_err)) + { + my_free(killed_err); + killed_err= 0; + } mysql_mutex_unlock(&LOCK_thd_kill); } #ifdef WITH_WSREP @@ -2142,6 +2150,7 @@ void THD::reset_killed() mysql_mutex_assert_not_owner(&LOCK_thd_kill); mysql_mutex_lock(&LOCK_thd_kill); wsrep_abort_by_kill= NOT_KILLED; + my_free(wsrep_abort_by_kill_err); wsrep_abort_by_kill_err= 0; mysql_mutex_unlock(&LOCK_thd_kill); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 5db5aca92b8..fa124d899dd 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4182,7 +4182,8 @@ public: The worst things that can happen is that we get a suboptimal error message. */ - killed_err= (err_info*) alloc_root(&main_mem_root, sizeof(*killed_err)); + if (!killed_err) + killed_err= (err_info*) my_malloc(sizeof(*killed_err), MYF(MY_WME)); if (likely(killed_err)) { killed_err->no= killed_errno_arg; diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 950c1528141..4a6f0736c76 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -485,6 +485,7 @@ void wsrep_backup_kill_for_commit(THD *thd) thd->wsrep_trx().state() != wsrep::transaction::s_must_replay) { thd->wsrep_abort_by_kill= thd->killed; + my_free(thd->wsrep_abort_by_kill_err); thd->wsrep_abort_by_kill_err= thd->killed_err; thd->killed= NOT_KILLED; thd->killed_err= 0; @@ -497,6 +498,7 @@ void wsrep_restore_kill_after_commit(THD *thd) DBUG_ASSERT(WSREP(thd)); mysql_mutex_assert_owner(&thd->LOCK_thd_kill); thd->killed= thd->wsrep_abort_by_kill; + my_free(thd->killed_err); thd->killed_err= thd->wsrep_abort_by_kill_err; thd->wsrep_abort_by_kill= NOT_KILLED; thd->wsrep_abort_by_kill_err= 0; From 8e96119159a946b1b56c1f8ea78f924e06c2cb88 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 24 Nov 2023 18:50:15 +0200 Subject: [PATCH 335/477] Backport my_addr_resolve from 10.6 to get latest bug fixes in. This will enable safemalloc to resolve symbols when compiled with __PIE__ --- mysys/my_addr_resolve.c | 82 ++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c index 52fcaaf67bb..376e73686e2 100644 --- a/mysys/my_addr_resolve.c +++ b/mysys/my_addr_resolve.c @@ -170,7 +170,7 @@ static pid_t pid; static char addr2line_binary[1024]; static char output[1024]; static struct pollfd poll_fds; -static Dl_info info; +static void *addr_offset; int start_addr2line_fork(const char *binary_path) { @@ -211,7 +211,9 @@ int start_addr2line_fork(const char *binary_path) return 0; } -int my_addr_resolve(void *ptr, my_addr_loc *loc) +static int first_error= 0; + +static int addr_resolve(void *ptr, my_addr_loc *loc) { char input[32]; size_t len; @@ -225,31 +227,16 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) int filename_start = -1; int line_number_start = -1; - void *offset; - poll_fds.fd = out[0]; poll_fds.events = POLLIN | POLLRDBAND; - if (!dladdr(ptr, &info)) - return 1; - - if (strcmp(addr2line_binary, info.dli_fname)) - { - /* We use dli_fname in case the path is longer than the length of our static - string. We don't want to allocate anything dynamicaly here as we are in - a "crashed" state. */ - if (start_addr2line_fork(info.dli_fname)) - { - addr2line_binary[0] = '\0'; - return 2; - } - /* Save result for future comparisons. */ - strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); - } - offset = info.dli_fbase; - len= my_snprintf(input, sizeof(input), "%08x\n", (ulonglong)(ptr - offset)); + len= my_snprintf(input, sizeof(input), "%p\n", ptr); if (write(in[1], input, len) <= 0) + { + if (!first_error++) + fputs("Printing to addr2line failed\n", stderr); return 3; + } /* 5000 ms should be plenty of time for addr2line to issue a response. */ @@ -308,6 +295,57 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) return 0; } + +int my_addr_resolve(void *ptr, my_addr_loc *loc) +{ + Dl_info info; + + if (!dladdr(ptr, &info)) + return 1; + + if (strcmp(addr2line_binary, info.dli_fname)) + { + /* + We use dli_fname in case the path is longer than the length of + our static string. We don't want to allocate anything + dynamically here as we are in a "crashed" state. + */ + if (start_addr2line_fork(info.dli_fname)) + { + if (!first_error++) + fputs("Can't start addr2line\n", stderr); + addr2line_binary[0] = '\0'; + return 2; + } + /* Save result for future comparisons. */ + strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); + +#ifdef _AIX + /* + info.dli_fbase is a char on AIX and casting it doesn't fool gcc. + leave backtracing broken on AIX until a real solution can be found. + */ + addr_offset= NULL; +#else + /* + Check if we should use info.dli_fbase as an offset or not + for the base program. This is depending on if the compilation is + done with PIE or not. + */ + addr_offset= info.dli_fbase; +#endif +#ifndef __PIE__ + if (strcmp(info.dli_fname, my_progname) == 0 && + addr_resolve((void*) my_addr_resolve, loc) == 0 && + strcmp(loc->func, "my_addr_resolve") == 0) + addr_offset= 0; +#endif + } + + return addr_resolve((void*) (ptr - addr_offset), loc); +} + + const char *my_addr_resolve_init() { return 0; From 08e6431c8c9c2b6174b9a46ec5f3f36c496f9a9d Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 24 Nov 2023 19:59:32 +0200 Subject: [PATCH 336/477] Fixed memory leak introduces by a fix for MDEV-29932 The leaks are all 40 bytes and happens in this call stack when running mtr vcol.vcol_syntax: alloc_root() ... Virtual_column_info::fix_and_check_exp() ... Delayed_insert::get_local_table() The problem was that one copied a MEM_ROOT from THD to a TABLE without taking into account that new blocks would be allocated through the TABLE memroot (and would thus be leaked). In general, one should NEVER copy MEM_ROOT from one object to another without clearing the copied memroot! Fixed by, at end of get_local_table(), copy all new allocated objects to client_thd->mem_root. Other things: - Removed references to MEM_ROOT::total_alloc that was wrongly left after a previous commit --- include/my_sys.h | 1 + mysys/my_alloc.c | 23 ++++++++++++++++++++++- sql/sql_insert.cc | 7 ++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index 3c44b6a0a80..82acdaa1a2a 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -892,6 +892,7 @@ extern void init_alloc_root(MEM_ROOT *mem_root, const char *name, extern void *alloc_root(MEM_ROOT *mem_root, size_t Size); extern void *multi_alloc_root(MEM_ROOT *mem_root, ...); extern void free_root(MEM_ROOT *root, myf MyFLAGS); +extern void move_root(MEM_ROOT *to, MEM_ROOT *from); extern void set_prealloc_root(MEM_ROOT *root, char *ptr); extern void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, size_t prealloc_size); diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 983c4440243..d7151e5e867 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -199,7 +199,6 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) next->left= 0; next->size= length; mem_root->used= next; - mem_root->total_alloc+= length; DBUG_PRINT("exit",("ptr: %p", (((char*) next)+ ALIGN_SIZE(sizeof(USED_MEM))))); DBUG_RETURN((uchar*) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM)))); @@ -460,6 +459,28 @@ void set_prealloc_root(MEM_ROOT *root, char *ptr) } } +/* + Move allocated objects from one root to another. + + Notes: + We do not increase 'to->block_num' here as the variable isused to + increase block sizes in case of many allocations. This is special + case where this is not needed to take into account +*/ + +void move_root(MEM_ROOT *to, MEM_ROOT *from) +{ + USED_MEM *block, *next; + for (block= from->used; block ; block= next) + { + next= block->next; + block->next= to->used; + to->used= block; + } + from->used= 0; +} + + char *strdup_root(MEM_ROOT *root, const char *str) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 99592d79f16..933ce306861 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2635,7 +2635,9 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) copy= new (copy_tmp) TABLE; *copy= *table; copy->vcol_refix_list.empty(); - copy->mem_root= *client_thd->mem_root; + init_alloc_root(©->mem_root, client_thd->mem_root->name, + client_thd->mem_root->block_size, + 0, MY_THREAD_SPECIFIC); /* We don't need to change the file handler here */ /* Assign the pointers for the field pointers array and the record. */ @@ -2729,11 +2731,14 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) bzero((char*) bitmap, share->column_bitmap_size * bitmaps_used); copy->read_set= ©->def_read_set; copy->write_set= ©->def_write_set; + move_root(client_thd->mem_root, ©->mem_root); + free_root(©->mem_root, 0); DBUG_RETURN(copy); /* Got fatal error */ error: + free_root(©->mem_root, 0); tables_in_use--; mysql_cond_signal(&cond); // Inform thread about abort DBUG_RETURN(0); From 06f7ed4dcde86e4b269c0cda85d6b5c04aa6574d Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 24 Nov 2023 20:54:43 +0200 Subject: [PATCH 337/477] MDEV-28566 Assertion `!expr->is_fixed()' failed in bool virtual_column_info::fix_session_expr(THD*) The problem was that table->vcol_cleanup_expr() was not called in case of error in open_table(). --- mysql-test/suite/gcol/r/gcol_bugfixes.result | 38 ++++++++++++++++++++ mysql-test/suite/gcol/t/gcol_bugfixes.test | 35 ++++++++++++++++++ sql/sql_base.cc | 2 ++ 3 files changed, 75 insertions(+) diff --git a/mysql-test/suite/gcol/r/gcol_bugfixes.result b/mysql-test/suite/gcol/r/gcol_bugfixes.result index 56ea46a8052..48d4235a2fb 100644 --- a/mysql-test/suite/gcol/r/gcol_bugfixes.result +++ b/mysql-test/suite/gcol/r/gcol_bugfixes.result @@ -745,3 +745,41 @@ SELECT id, ts, vc INTO OUTFILE 'load_t1' FROM t1; LOAD DATA INFILE 'load_t1' REPLACE INTO TABLE t1 (id, ts, vc); INSERT IGNORE INTO t1 (id) VALUES (2); DROP TABLE t1; +# +# MDEV-28566 Assertion `!expr->is_fixed()' failed in bool +# Virtual_column_info::fix_session_expr(THD*) +# +CREATE TABLE t1 (c1 CHAR(1)); +FLUSH TABLES WITH READ LOCK; +UPDATE t1 SET c1=1; +ERROR HY000: Can't execute the query because you have a conflicting read lock +unlock tables; +SELECT * FROM t1; +c1 +DROP TABLE t1; +CREATE TABLE t1 (c1 CHAR AS (CONCAT (0,DAYNAME (0)))); +FLUSH TABLES WITH READ LOCK; +UPDATE t1 SET c1=1; +ERROR HY000: Can't execute the query because you have a conflicting read lock +unlock tables; +UPDATE t1 SET c1=1; +SELECT * FROM t1; +c1 +DROP TABLE t1; +CREATE TABLE t1 (a int primary key, c1 CHAR AS (CONCAT (0,DAYNAME (0)))); +insert into t1 (a) values (1); +FLUSH TABLES WITH READ LOCK; +UPDATE t1 SET c1=1; +ERROR HY000: Can't execute the query because you have a conflicting read lock +UPDATE t1 SET a=2; +ERROR HY000: Can't execute the query because you have a conflicting read lock +unlock tables; +UPDATE t1 SET a=2; +UPDATE t1 SET c1=1; +ERROR HY000: The value specified for generated column 'c1' in table 't1' has been ignored +SELECT * FROM t1; +a c1 +2 NULL +Warnings: +Warning 1292 Incorrect datetime value: '0' +DROP TABLE t1; diff --git a/mysql-test/suite/gcol/t/gcol_bugfixes.test b/mysql-test/suite/gcol/t/gcol_bugfixes.test index 4c1b00a878a..1edc9779d41 100644 --- a/mysql-test/suite/gcol/t/gcol_bugfixes.test +++ b/mysql-test/suite/gcol/t/gcol_bugfixes.test @@ -724,3 +724,38 @@ DROP TABLE t1; --remove_file $datadir/test/load_t1 +--echo # +--echo # MDEV-28566 Assertion `!expr->is_fixed()' failed in bool +--echo # Virtual_column_info::fix_session_expr(THD*) +--echo # + +CREATE TABLE t1 (c1 CHAR(1)); +FLUSH TABLES WITH READ LOCK; +--error ER_CANT_UPDATE_WITH_READLOCK +UPDATE t1 SET c1=1; +unlock tables; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 CHAR AS (CONCAT (0,DAYNAME (0)))); +FLUSH TABLES WITH READ LOCK; +--error ER_CANT_UPDATE_WITH_READLOCK +UPDATE t1 SET c1=1; +unlock tables; +UPDATE t1 SET c1=1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a int primary key, c1 CHAR AS (CONCAT (0,DAYNAME (0)))); +insert into t1 (a) values (1); +FLUSH TABLES WITH READ LOCK; +--error ER_CANT_UPDATE_WITH_READLOCK +UPDATE t1 SET c1=1; +--error ER_CANT_UPDATE_WITH_READLOCK +UPDATE t1 SET a=2; +unlock tables; +UPDATE t1 SET a=2; +--error ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN +UPDATE t1 SET c1=1; +SELECT * FROM t1; +DROP TABLE t1; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7642f41e46c..627dc6ff5f6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2191,6 +2191,7 @@ retry_share: if (thd->has_read_only_protection()) { MYSQL_UNBIND_TABLE(table->file); + table->vcol_cleanup_expr(thd); tc_release_table(table); DBUG_RETURN(TRUE); } @@ -2210,6 +2211,7 @@ retry_share: if (result) { MYSQL_UNBIND_TABLE(table->file); + table->vcol_cleanup_expr(thd); tc_release_table(table); DBUG_RETURN(TRUE); } From 83214c34064bc396ef0baac252a4eb861bf74e5a Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 26 Nov 2023 10:10:37 +0200 Subject: [PATCH 338/477] Improve reporting from sf_report_leaked_memory() Other things: - Added DBUG_EXECUTE_IF("print_allocated_thread_memory") at end of query to easier find not freed memory allocated by THD - Removed free_root() from plugin_init() that did nothing. --- mysys/safemalloc.c | 12 ++++++++---- sql/sql_parse.cc | 2 ++ sql/sql_plugin.cc | 1 - 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index 034b6f2536b..3d4988e29a4 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -66,7 +66,7 @@ struct st_irem uint32 marker; /* Underrun marker value */ }; -static int sf_malloc_count= 0; /* Number of allocated chunks */ +static uint sf_malloc_count= 0; /* Number of allocated chunks */ static void *sf_min_adress= (void*) (intptr)~0ULL, *sf_max_adress= 0; @@ -344,7 +344,7 @@ int sf_sanity() { struct st_irem *irem; int flag= 0; - int count= 0; + uint count= 0; pthread_mutex_lock(&sf_mutex); count= sf_malloc_count; @@ -369,6 +369,7 @@ void sf_report_leaked_memory(my_thread_id id) { size_t total= 0; struct st_irem *irem; + uint first= 0, chunks= 0; sf_sanity(); @@ -380,15 +381,18 @@ void sf_report_leaked_memory(my_thread_id id) { my_thread_id tid = irem->thread_id && irem->flags & MY_THREAD_SPECIFIC ? irem->thread_id : 0; + if (!first++) + fprintf(stderr, "Memory report from safemalloc\n"); fprintf(stderr, "Warning: %4lu bytes lost at %p, allocated by T@%llu at ", (ulong) irem->datasize, (char*) (irem + 1), tid); print_stack(irem->frame); total+= irem->datasize; + chunks++; } } if (total) - fprintf(stderr, "Memory lost: %lu bytes in %d chunks\n", - (ulong) total, sf_malloc_count); + fprintf(stderr, "Memory lost: %lu bytes in %u chunks of %u total chunks\n", + (ulong) total, chunks, sf_malloc_count); return; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7cca219dc81..d6ad9dc270b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2480,6 +2480,8 @@ dispatch_end: */ thd->lex->m_sql_cmd= NULL; free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); + DBUG_EXECUTE_IF("print_allocated_thread_memory", + SAFEMALLOC_REPORT_MEMORY(sf_malloc_dbug_id());); #if defined(ENABLED_PROFILING) thd->profiling.finish_current_query(); diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 25ce43fd315..19c5f86c765 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1646,7 +1646,6 @@ int plugin_init(int *argc, char **argv, int flags) } } - free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE)); tmp.state= PLUGIN_IS_UNINITIALIZED; if (register_builtin(plugin, &tmp, &plugin_ptr)) goto err_unlock; From 2057820532312e2b6be5bad5abde361532f5d4c6 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 21 Nov 2023 15:25:35 +1100 Subject: [PATCH 339/477] MDEV-32849 Spider: check if any table is actually locked when unlocking This avoids the scenario in MDEV-32849, when the unlock happens after the connection has been freed, say in rollback. This is done in 10.5+ after the commit a26700cca579926cddf9a48c45f13b32785746bb. It may or may not prevent potential other scenarios where spider has locked something, then for some reason the statement needs to be rolled back and spider frees the connection, and then spider proceeds to use the freed connection. But at least we fix the regression introduced by MDEV-30014 to 10.4 and bring 10.4 closer in parity with 10.5+. --- storage/spider/ha_spider.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 3cfbae34198..793fa45c12f 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -1265,6 +1265,13 @@ int ha_spider::external_lock( #ifdef HA_CAN_BULK_ACCESS external_lock_cnt++; #endif + if (lock_type == F_UNLCK) + { + if (!trx->locked_connections) + { + DBUG_RETURN(0); /* No remote table actually locked by Spider */ + } + } if (store_error_num) DBUG_RETURN(store_error_num); #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) From f436b4a523df603ca3f245e7b523e30bbe06f12b Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 27 Nov 2023 09:56:21 +0400 Subject: [PATCH 340/477] MDEV-32879 Server crash in my_decimal::operator= or unexpected ER_DUP_ENTRY upon comparison with INET6 and similar types During the 10.5->10.6 merge please use the 10.6 code on conflicts. This is the 10.5 version of the patch (a backport of the 10.6 version). Unlike 10.6 version, it makes changes in plugin/type_inet/sql_type_inet.* rather than in sql/sql_type_fixedbin.h Item_bool_rowready_func2, Item_func_between, Item_func_in did not check if a not-NULL argument of an arbitrary data type can produce a NULL value on conversion to INET6. This caused a crash on DBUG_ASSERT() in conversion failures, because the function returned SQL NULL for something that has Item::maybe_null() equal to false. Adding setting NULL-ability in such cases. Details: - Removing the code in Item_func::setup_args_and_comparator() performing character set aggregation with optional narrowing. This aggregation is done inside Arg_comparator::set_cmp_func_string(). So this code was redundant - Removing Item_func::setup_args_and_comparator() as it git simplified to just to two lines: convert_const_compared_to_int_field(thd); return cmp->set_cmp_func(thd, this, &args[0], &args[1], true); Using these lines directly in: - Item_bool_rowready_func2::fix_length_and_dec() - Item_func_nullif::fix_length_and_dec() - Adding a new virtual method: - Type_handler::Item_bool_rowready_func2_fix_length_and_dec(). - Adding tests detecting if the data type conversion can return SQL NULL into the following methods of Type_handler_inet6: - Item_bool_rowready_func2_fix_length_and_dec - Item_func_between_fix_length_and_dec - Item_func_in_fix_comparator_compatible_types --- .../mysql-test/type_inet/type_inet6.result | 75 +++++++++++++++++++ .../mysql-test/type_inet/type_inet6.test | 26 +++++++ plugin/type_inet/sql_type_inet.h | 33 ++++++++ sql/item.cc | 26 ++++++- sql/item.h | 11 ++- sql/item_cmpfunc.cc | 65 ++++++++-------- sql/item_cmpfunc.h | 35 +++++++-- sql/item_func.h | 10 --- sql/item_sum.cc | 9 ++- sql/sql_select.cc | 10 +-- sql/sql_type.cc | 8 ++ sql/sql_type.h | 11 ++- 12 files changed, 255 insertions(+), 64 deletions(-) diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.result b/plugin/type_inet/mysql-test/type_inet/type_inet6.result index 9c43725c733..7484a10962c 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.result @@ -2255,3 +2255,78 @@ a Warnings: Warning 1292 Incorrect inet6 value: '' DROP TABLE t1; +# +# MDEV-32879 Server crash in my_decimal::operator= or unexpected ER_DUP_ENTRY upon comparison with INET6 and similar types +# +CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL); +INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01'); +SELECT c + (b = a) AS f, GROUP_CONCAT(c) FROM t1 GROUP BY f; +f GROUP_CONCAT(c) +NULL 2000-01-01 00:00:00.000000,1900-01-01 00:00:00.000000 +Warnings: +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL); +INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01'); +SELECT c + (b = a) AS f, COUNT(c) FROM t1 GROUP BY f; +f COUNT(c) +NULL 2 +Warnings: +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL); +INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01'); +SELECT c + (b = a) AS f FROM t1 ORDER BY f; +f +NULL +NULL +Warnings: +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL); +INSERT INTO t1 VALUES ('','::'),('','::'); +SELECT 1.00 + (b = a) AS f FROM t1 ORDER BY f; +f +NULL +NULL +Warnings: +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +SELECT 1.00 + (b BETWEEN a AND '') AS f FROM t1 ORDER BY f; +f +NULL +NULL +Warnings: +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +SELECT 1.00 + (b IN (a,'')) AS f FROM t1 ORDER BY f; +f +NULL +NULL +Warnings: +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +Warning 1292 Incorrect inet6 value: '' +DROP TABLE t1; diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.test b/plugin/type_inet/mysql-test/type_inet/type_inet6.test index b0dffb098f2..abe9071962f 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6.test +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.test @@ -1660,3 +1660,29 @@ CREATE OR REPLACE TABLE t1 (a INET6); INSERT INTO t1 VALUES ('::'); SELECT * FROM t1 WHERE a IN ('','::1'); DROP TABLE t1; + +--echo # +--echo # MDEV-32879 Server crash in my_decimal::operator= or unexpected ER_DUP_ENTRY upon comparison with INET6 and similar types +--echo # + +CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL); +INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01'); +SELECT c + (b = a) AS f, GROUP_CONCAT(c) FROM t1 GROUP BY f; +DROP TABLE t1; + +CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL); +INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01'); +SELECT c + (b = a) AS f, COUNT(c) FROM t1 GROUP BY f; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL); +INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01'); +SELECT c + (b = a) AS f FROM t1 ORDER BY f; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL); +INSERT INTO t1 VALUES ('','::'),('','::'); +SELECT 1.00 + (b = a) AS f FROM t1 ORDER BY f; +SELECT 1.00 + (b BETWEEN a AND '') AS f FROM t1 ORDER BY f; +SELECT 1.00 + (b IN (a,'')) AS f FROM t1 ORDER BY f; +DROP TABLE t1; diff --git a/plugin/type_inet/sql_type_inet.h b/plugin/type_inet/sql_type_inet.h index 80d8544e6c9..a83dddb4c26 100644 --- a/plugin/type_inet/sql_type_inet.h +++ b/plugin/type_inet/sql_type_inet.h @@ -188,6 +188,21 @@ public: */ static bool fix_fields_maybe_null_on_conversion_to_inet6(Item *item); + /* + Check at fix_fields() time if any of the items can return a nullable + value on conversion to Fbt. + */ + static bool fix_fields_maybe_null_on_conversion_to_inet6(Item **items, + uint count) + { + for (uint i= 0; i < count; i++) + { + if (fix_fields_maybe_null_on_conversion_to_inet6(items[i])) + return true; + } + return false; + } + public: Inet6(Item *item, bool *error, bool warn= true) @@ -714,6 +729,16 @@ public: Inet6_null nb(b); return !na.is_null() && !nb.is_null() && !na.cmp(nb); } + bool Item_bool_rowready_func2_fix_length_and_dec(THD *thd, + Item_bool_rowready_func2 *func) const override + { + if (Type_handler::Item_bool_rowready_func2_fix_length_and_dec(thd, func)) + return true; + if (!func->maybe_null && + Inet6::fix_fields_maybe_null_on_conversion_to_inet6(func->arguments(), 2)) + func->maybe_null= true; + return false; + } bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *h, @@ -902,6 +927,10 @@ public: bool Item_func_between_fix_length_and_dec(Item_func_between *func) const override { + if (!func->maybe_null && + Inet6::fix_fields_maybe_null_on_conversion_to_inet6(func->arguments(), 3)) + func->maybe_null= true; + return false; } longlong Item_func_between_val_int(Item_func_between *func) const override @@ -918,6 +947,10 @@ public: Item_func_in *func) const override { + if (!func->maybe_null && + Inet6::fix_fields_maybe_null_on_conversion_to_inet6(func->arguments(), + func->argument_count())) + func->maybe_null= true; if (func->compatible_types_scalar_bisection_possible()) { return func->value_list_convert_const_to_int(thd) || diff --git a/sql/item.cc b/sql/item.cc index 1853f7b560f..44965a1feb9 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2497,7 +2497,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->name,c1.derivation_name(), @@ -2579,10 +2580,17 @@ bool Type_std_attributes::agg_item_collations(DTCollation &c, const char *fname, } +/* + @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 char *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()) @@ -2620,7 +2628,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, 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); + else + my_coll_agg_error(single_err->coll, args[0]->collation, fname); + } + else + my_coll_agg_error(args, nargs, fname, item_sep); return TRUE; } diff --git a/sql/item.h b/sql/item.h index e7125cccd14..16679776053 100644 --- a/sql/item.h +++ b/sql/item.h @@ -5237,10 +5237,17 @@ public: func_name()); return true; } + /* + 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(), - 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(), - b, 1, MY_COLL_CMP_CONV, 1)) + 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 4a2de58e748..324aceafd41 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -413,26 +413,6 @@ void Item_func::convert_const_compared_to_int_field(THD *thd) } -bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp) -{ - DBUG_ASSERT(arg_count >= 2); // Item_func_nullif has arg_count == 3 - - if (args[0]->cmp_type() == STRING_RESULT && - args[1]->cmp_type() == STRING_RESULT) - { - DTCollation tmp; - if (agg_arg_charsets_for_comparison(tmp, args, 2)) - return true; - cmp->m_compare_collation= tmp.collation; - } - // Convert constants when compared to int/year field - DBUG_ASSERT(functype() != LIKE_FUNC); - convert_const_compared_to_int_field(thd); - - return cmp->set_cmp_func(this, &args[0], &args[1], true); -} - - /* Comparison operators remove arguments' dependency on PAD_CHAR_TO_FULL_LENGTH in case of PAD SPACE comparison collations: trailing spaces do not affect @@ -452,6 +432,7 @@ Item_bool_rowready_func2::value_depends_on_sql_mode() const bool Item_bool_rowready_func2::fix_length_and_dec() { + THD *thd= current_thd; max_length= 1; // Function returns 0 or 1 /* @@ -460,7 +441,16 @@ bool Item_bool_rowready_func2::fix_length_and_dec() */ if (!args[0] || !args[1]) return FALSE; - return setup_args_and_comparator(current_thd, &cmp); + convert_const_compared_to_int_field(thd); + Type_handler_hybrid_field_type tmp; + if (tmp.aggregate_for_comparison(func_name(), args, 2, false) || + tmp.type_handler()->Item_bool_rowready_func2_fix_length_and_dec(thd, + this)) + { + DBUG_ASSERT(thd->is_error()); + return true; + } + return false; } @@ -477,27 +467,22 @@ bool Item_bool_rowready_func2::fix_length_and_dec() items, holding the cached converted value of the original (constant) item. */ -int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg, +int Arg_comparator::set_cmp_func(THD *thd, Item_func_or_sum *owner_arg, + const Type_handler *compare_handler, Item **a1, Item **a2) { owner= owner_arg; set_null= set_null && owner_arg; a= a1; b= a2; - Item *tmp_args[2]= {*a1, *a2}; - Type_handler_hybrid_field_type tmp; - if (tmp.aggregate_for_comparison(owner_arg->func_name(), tmp_args, 2, false)) - { - DBUG_ASSERT(current_thd->is_error()); - return 1; - } - m_compare_handler= tmp.type_handler(); + m_compare_handler= compare_handler; return m_compare_handler->set_comparator_func(this); } bool Arg_comparator::set_cmp_func_for_row_arguments() { + THD *thd= current_thd; uint n= (*a)->cols(); if (n != (*b)->cols()) { @@ -514,8 +499,8 @@ bool Arg_comparator::set_cmp_func_for_row_arguments() my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols()); return true; } - if (comparators[i].set_cmp_func(owner, (*a)->addr(i), - (*b)->addr(i), set_null)) + if (comparators[i].set_cmp_func(thd, owner, (*a)->addr(i), + (*b)->addr(i), set_null)) return true; } return false; @@ -541,7 +526,16 @@ bool Arg_comparator::set_cmp_func_string() { /* 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. + 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. */ if (owner->agg_arg_charsets_for_comparison(&m_compare_collation, a, b)) return true; @@ -2748,8 +2742,9 @@ Item_func_nullif::fix_length_and_dec() fix_char_length(args[2]->max_char_length()); maybe_null=1; m_arg0= args[0]; - if (setup_args_and_comparator(thd, &cmp)) - return TRUE; + convert_const_compared_to_int_field(thd); + if (cmp.set_cmp_func(thd, this, &args[0], &args[1], true/*set_null*/)) + return true; /* A special code for EXECUTE..PREPARE. diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 7cbc1236a03..3929b4c7d30 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -56,7 +56,9 @@ class Arg_comparator: public Sql_alloc Item *a_cache, *b_cache; // Cached values of a and b items // when one of arguments is NULL. - int set_cmp_func(Item_func_or_sum *owner_arg, Item **a1, Item **a2); + int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg, + const Type_handler *compare_handler, + Item **a1, Item **a2); int compare_not_null_values(longlong val1, longlong val2) { @@ -93,12 +95,25 @@ public: bool set_cmp_func_real(); bool set_cmp_func_decimal(); - inline int set_cmp_func(Item_func_or_sum *owner_arg, - Item **a1, Item **a2, bool set_null_arg) + inline int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg, + const Type_handler *compare_handler, + Item **a1, Item **a2, bool set_null_arg) { set_null= set_null_arg; - return set_cmp_func(owner_arg, a1, a2); + return set_cmp_func(thd, owner_arg, compare_handler, a1, a2); } + int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg, + Item **a1, Item **a2, bool set_null_arg) + { + Item *tmp_args[2]= { *a1, *a2 }; + Type_handler_hybrid_field_type tmp; + if (tmp.aggregate_for_comparison(owner_arg->func_name(), + tmp_args, 2, false)) + return 1; + return set_cmp_func(thd, owner_arg, tmp.type_handler(), + a1, a2, set_null_arg); + } + inline int compare() { return (this->*func)(); } int compare_string(); // compare args[0] & args[1] @@ -533,9 +548,17 @@ public: return this; } bool fix_length_and_dec(); - int set_cmp_func() + bool fix_length_and_dec_generic(THD *thd, + const Type_handler *compare_handler) { - return cmp.set_cmp_func(this, tmp_arg, tmp_arg + 1, true); + DBUG_ASSERT(args == tmp_arg); + return cmp.set_cmp_func(thd, this, compare_handler, + tmp_arg, tmp_arg + 1, true/*set_null*/); + } + int set_cmp_func(THD *thd) + { + DBUG_ASSERT(args == tmp_arg); + return cmp.set_cmp_func(thd, this, tmp_arg, tmp_arg + 1, true/*set_null*/); } CHARSET_INFO *compare_collation() const { return cmp.compare_collation(); } const Type_handler *compare_type_handler() const diff --git a/sql/item_func.h b/sql/item_func.h index bd04af926b0..ef020fa9054 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -395,16 +395,6 @@ public: } } void convert_const_compared_to_int_field(THD *thd); - /** - Prepare arguments and setup a comparator. - Used in Item_func_xxx with two arguments and a comparator, - e.g. Item_bool_func2 and Item_func_nullif. - args[0] or args[1] can be modified: - - converted to character set and collation of the operation - - or replaced to an Item_int_with_ref - */ - bool setup_args_and_comparator(THD *thd, Arg_comparator *cmp); - bool with_sum_func() const { return m_with_sum_func; } With_sum_func_cache* get_with_sum_func_cache() { return this; } Item_func *get_item_func() { return this; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 46942c0c785..584fd21ca4a 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1277,9 +1277,14 @@ void Item_sum_min_max::setup_hybrid(THD *thd, Item *item, Item *value_arg) /* Don't cache value, as it will change */ if (!item->const_item()) arg_cache->set_used_tables(RAND_TABLE_BIT); - cmp= new Arg_comparator(); + DBUG_ASSERT(item->type_handler_for_comparison() == + value->type_handler_for_comparison()); + DBUG_ASSERT(item->type_handler_for_comparison() == + arg_cache->type_handler_for_comparison()); + cmp= new (thd->mem_root) Arg_comparator(); if (cmp) - cmp->set_cmp_func(this, (Item**)&arg_cache, (Item**)&value, FALSE); + cmp->set_cmp_func(thd, this, item->type_handler_for_comparison(), + (Item**)&arg_cache, (Item**)&value, FALSE); DBUG_VOID_RETURN; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 62766cdb9cf..21132651b07 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15405,7 +15405,7 @@ static bool check_row_equality(THD *thd, const Arg_comparator *comparators, { Item_func_eq *eq_item; if (!(eq_item= new (thd->mem_root) Item_func_eq(thd, left_item, right_item)) || - eq_item->set_cmp_func()) + eq_item->set_cmp_func(thd)) return FALSE; eq_item->quick_fix_field(); eq_list->push_back(eq_item, thd->mem_root); @@ -16155,7 +16155,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels, Don't produce equality if const is equal to item_const. */ Item_func_eq *func= new (thd->mem_root) Item_func_eq(thd, item_const, upper_const); - func->set_cmp_func(); + func->set_cmp_func(thd); func->quick_fix_field(); if (func->val_int()) item= 0; @@ -16203,7 +16203,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels, field_item->remove_item_direct_ref(), head_item->remove_item_direct_ref()); - if (!eq_item || eq_item->set_cmp_func()) + if (!eq_item || eq_item->set_cmp_func(thd)) return 0; eq_item->quick_fix_field(); } @@ -16621,7 +16621,7 @@ change_cond_ref_to_const(THD *thd, I_List *save_list, So make sure to use set_cmp_func() only for non-LIKE operators. */ if (functype != Item_func::LIKE_FUNC) - ((Item_bool_rowready_func2*) func)->set_cmp_func(); + ((Item_bool_rowready_func2*) func)->set_cmp_func(thd); } } else if (can_change_cond_ref_to_const(func, left_item, right_item, @@ -16646,7 +16646,7 @@ change_cond_ref_to_const(THD *thd, I_List *save_list, save_list->push_back(tmp2); } if (functype != Item_func::LIKE_FUNC) - ((Item_bool_rowready_func2*) func)->set_cmp_func(); + ((Item_bool_rowready_func2*) func)->set_cmp_func(thd); } } } diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 6bdc96ac401..e7058f6b4ed 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -5675,6 +5675,14 @@ Type_handler_string_result::Item_func_hybrid_field_type_get_date( /***************************************************************************/ +bool Type_handler::Item_bool_rowready_func2_fix_length_and_dec(THD *thd, + Item_bool_rowready_func2 *func) const +{ + return func->fix_length_and_dec_generic(thd, this); +} + +/***************************************************************************/ + bool Type_handler_numeric:: Item_func_between_fix_length_and_dec(Item_func_between *func) const { diff --git a/sql/sql_type.h b/sql/sql_type.h index aa89c8850af..ee3eb454ead 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -55,6 +55,7 @@ class Item_hybrid_func; class Item_func_min_max; class Item_func_hybrid_field_type; class Item_bool_func2; +class Item_bool_rowready_func2; class Item_func_between; class Item_func_in; class Item_func_round; @@ -3233,9 +3234,15 @@ public: bool agg_item_collations(DTCollation &c, const char *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 char *fname, 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. @@ -4232,6 +4239,8 @@ public: } virtual bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, Item *a, Item *b) const= 0; + virtual bool Item_bool_rowready_func2_fix_length_and_dec(THD *thd, + Item_bool_rowready_func2 *func) const; virtual bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, From 60c01206dfddc817b7404cffcf006a568efe6ffb Mon Sep 17 00:00:00 2001 From: Faustin Lammler Date: Mon, 27 Nov 2023 14:31:45 +0100 Subject: [PATCH 341/477] The MariaDB mailing list system has been moved See: https://mariadb.org/mailing-lists/ --- cmake/mysql_version.cmake | 2 +- debian/control | 2 +- debian/copyright | 3 +-- mysql-test/README | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cmake/mysql_version.cmake b/cmake/mysql_version.cmake index 85273136a32..cb12bf14b86 100644 --- a/cmake/mysql_version.cmake +++ b/cmake/mysql_version.cmake @@ -85,7 +85,7 @@ IF(NOT CPACK_PACKAGE_FILE_NAME) ENDIF() SET_IF_UNSET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-${VERSION}") -SET_IF_UNSET(CPACK_PACKAGE_CONTACT "MariaDB Developers ") +SET_IF_UNSET(CPACK_PACKAGE_CONTACT "MariaDB Developers ") SET_IF_UNSET(CPACK_PACKAGE_VENDOR "MariaDB Foundation") SET_IF_UNSET(CPACK_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION_SUMMARY} diff --git a/debian/control b/debian/control index f927ba0c5ea..30decad3cc5 100644 --- a/debian/control +++ b/debian/control @@ -1,7 +1,7 @@ Source: mariadb-10.4 Section: database Priority: optional -Maintainer: MariaDB Developers +Maintainer: MariaDB Developers Build-Depends: bison, chrpath, cmake (>= 2.7), diff --git a/debian/copyright b/debian/copyright index 836fe89f4c3..ec76dc5e3d8 100644 --- a/debian/copyright +++ b/debian/copyright @@ -6,8 +6,7 @@ Schwarz and ist maintained since 1999-04-20 by Christian Hammers . The MariaDB packages were initially made by http://ourdelta.org/, and -are now managed by the MariaDB development team, -maria-developers@lists.launchpad.net +are now managed by the MariaDB development team, developers@lists.mariadb.org MariaDB can be downloaded from https://downloads.mariadb.org/ diff --git a/mysql-test/README b/mysql-test/README index f1c38f11716..793e5e1983d 100644 --- a/mysql-test/README +++ b/mysql-test/README @@ -86,8 +86,8 @@ If the result is incorrect, you have found a bug. In this case, you should edit the test result to the correct results so that we can verify that the bug is corrected in future releases. -If you want to submit your test case you can send it -to maria-developers@lists.launchpad.net or attach it to a bug report on +If you want to submit your test case you can send it +to developers@lists.mariadb.org or attach it to a bug report on http://mariadb.org/jira/. If the test case is really big or if it contains 'not public' data, From 81aba2c21fc17882076ec3da716fafaa60edb16b Mon Sep 17 00:00:00 2001 From: Faustin Lammler Date: Mon, 27 Nov 2023 14:33:42 +0100 Subject: [PATCH 342/477] Fix typo --- debian/control | 2 +- debian/copyright | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/control b/debian/control index 30decad3cc5..4005715959e 100644 --- a/debian/control +++ b/debian/control @@ -547,7 +547,7 @@ Description: Backup tool for MariaDB server Based on Xtrabackup, but improved to work with MariaDB server. This backup tool is guaranteed to be compatible with MariaDB server. . - Plese refer to the MariaDB Knowledge Base on more information on + Please refer to the MariaDB Knowledge Base on more information on how to use this tool. Package: mariadb-plugin-connect diff --git a/debian/copyright b/debian/copyright index ec76dc5e3d8..a35a25dcdbe 100644 --- a/debian/copyright +++ b/debian/copyright @@ -2,7 +2,7 @@ == MariaDB == The Debian package of MySQL was first debianzed on 1997-04-12 by Christian -Schwarz and ist maintained since 1999-04-20 by +Schwarz and is maintained since 1999-04-20 by Christian Hammers . The MariaDB packages were initially made by http://ourdelta.org/, and From d9ae5820c582b556aef41c1b18e1a3d81cf836f4 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 27 Nov 2023 19:28:38 +0530 Subject: [PATCH 343/477] MDEV-32890 LeakSanitizer errors in mem_heap_create_block_func upon query from I_S.INNODB_SYS_TABLES with LIMIT ROWS EXAMINED - innodb_sys_tables query fails to free the object which contains sys_tables information in case of error. --- mysql-test/suite/innodb/r/innodb_stats_fetch.result | 2 ++ mysql-test/suite/innodb/t/innodb_stats_fetch.test | 2 ++ storage/innobase/handler/i_s.cc | 3 +++ 3 files changed, 7 insertions(+) diff --git a/mysql-test/suite/innodb/r/innodb_stats_fetch.result b/mysql-test/suite/innodb/r/innodb_stats_fetch.result index bcb3c48d4d9..df6bc4b0cf7 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_fetch.result +++ b/mysql-test/suite/innodb/r/innodb_stats_fetch.result @@ -153,6 +153,7 @@ set @@use_stat_tables = @save_use_stat_tables; # # MDEV-28613 LeakSanitizer caused by I_S query using LIMIT ROWS EXAMINED # +CREATE TABLE t1(f1 VARCHAR(255), FULLTEXT(f1))ENGINE=InnoDB; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES LIMIT ROWS EXAMINED 5; Warnings: Level Warning @@ -172,3 +173,4 @@ SELECT SPACE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES LIMIT ROWS EXAMINED SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_VIRTUAL LIMIT ROWS EXAMINED 5; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN LIMIT ROWS EXAMINED 5; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS LIMIT ROWS EXAMINED 5; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb_stats_fetch.test b/mysql-test/suite/innodb/t/innodb_stats_fetch.test index 52946510304..99fc115af1d 100644 --- a/mysql-test/suite/innodb/t/innodb_stats_fetch.test +++ b/mysql-test/suite/innodb/t/innodb_stats_fetch.test @@ -85,6 +85,7 @@ set @@use_stat_tables = @save_use_stat_tables; --echo # --echo # MDEV-28613 LeakSanitizer caused by I_S query using LIMIT ROWS EXAMINED --echo # +CREATE TABLE t1(f1 VARCHAR(255), FULLTEXT(f1))ENGINE=InnoDB; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES LIMIT ROWS EXAMINED 5; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES LIMIT ROWS EXAMINED 5; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS LIMIT ROWS EXAMINED 5; @@ -94,3 +95,4 @@ SELECT SPACE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES LIMIT ROWS EXAMINED SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_VIRTUAL LIMIT ROWS EXAMINED 5; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN LIMIT ROWS EXAMINED 5; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS LIMIT ROWS EXAMINED 5; +DROP TABLE t1; diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 75f93000a34..14dee835591 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -5070,6 +5070,9 @@ i_s_sys_tables_fill_table( thd, table_rec, tables->table); if (err) { err = i_s_sys_error_handling(err, thd); + if (table_rec) { + dict_mem_table_free(table_rec); + } goto func_exit; } } else { From 7081feeac9b7442380b2cb134c215b3d74f9a96c Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 28 Nov 2023 13:52:22 +0530 Subject: [PATCH 344/477] MDEV-29913 Assertion `thd->stmt_arena != thd->progress.arena' failed in thd_progress_init upon bulk load - Commit fc31e3114b2538d152194d17ff0f0439db565634(MDEV-8179) doesn't report the progress of inplace alter completely. It just does only in row_merge_sort(). Removing the progress report function completely --- storage/innobase/row/row0merge.cc | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index a85a6d8becb..8c6d4341a50 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -3324,17 +3324,6 @@ row_merge_sort( of file marker). Thus, it must be at least one block. */ ut_ad(file->offset > 0); - /* These thd_progress* calls will crash on sol10-64 when innodb_plugin - is used. MDEV-9356: innodb.innodb_bug53290 fails (crashes) on - sol10-64 in buildbot. - */ -#ifndef __sun__ - /* Progress report only for "normal" indexes. */ - if (!(dup->index->type & DICT_FTS)) { - thd_progress_init(trx->mysql_thd, 1); - } -#endif /* __sun__ */ - if (global_system_variables.log_warnings > 2) { sql_print_information("InnoDB: Online DDL : merge-sorting" " has estimated " ULINTPF " runs", @@ -3343,15 +3332,6 @@ row_merge_sort( /* Merge the runs until we have one big run */ do { - /* Report progress of merge sort to MySQL for - show processlist progress field */ - /* Progress report only for "normal" indexes. */ -#ifndef __sun__ - if (!(dup->index->type & DICT_FTS)) { - thd_progress_report(trx->mysql_thd, file->offset - num_runs, file->offset); - } -#endif /* __sun__ */ - error = row_merge(trx, dup, file, block, tmpfd, &num_runs, run_offset, stage, crypt_block, space); @@ -3374,13 +3354,6 @@ row_merge_sort( ut_free(run_offset); - /* Progress report only for "normal" indexes. */ -#ifndef __sun__ - if (!(dup->index->type & DICT_FTS)) { - thd_progress_end(trx->mysql_thd); - } -#endif /* __sun__ */ - DBUG_RETURN(error); } From 2d6c2f22a4f9844db45d66e063fbf9314889eb1b Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 28 Nov 2023 16:29:04 +0530 Subject: [PATCH 345/477] MDEV-32452 InnoDB system tablespace is not shrunk on slow shutdown - During slow shutdown, shrink the system tablespace which was done in commit f9003c73a15d892423845a2df96c8bd73bbe96ca (MDEV-14795) --- .../innodb/r/sys_truncate_shutdown.result | 23 +++++++++ .../r/sys_truncate_shutdown_debug.result | 41 +++++++++++++++ .../suite/innodb/t/sys_truncate_shutdown.opt | 3 ++ .../suite/innodb/t/sys_truncate_shutdown.test | 20 ++++++++ .../innodb/t/sys_truncate_shutdown_debug.opt | 3 ++ .../innodb/t/sys_truncate_shutdown_debug.test | 51 +++++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 5 ++ 7 files changed, 146 insertions(+) create mode 100644 mysql-test/suite/innodb/r/sys_truncate_shutdown.result create mode 100644 mysql-test/suite/innodb/r/sys_truncate_shutdown_debug.result create mode 100644 mysql-test/suite/innodb/t/sys_truncate_shutdown.opt create mode 100644 mysql-test/suite/innodb/t/sys_truncate_shutdown.test create mode 100644 mysql-test/suite/innodb/t/sys_truncate_shutdown_debug.opt create mode 100644 mysql-test/suite/innodb/t/sys_truncate_shutdown_debug.test diff --git a/mysql-test/suite/innodb/r/sys_truncate_shutdown.result b/mysql-test/suite/innodb/r/sys_truncate_shutdown.result new file mode 100644 index 00000000000..ee567a76fb1 --- /dev/null +++ b/mysql-test/suite/innodb/r/sys_truncate_shutdown.result @@ -0,0 +1,23 @@ +SET GLOBAL innodb_fast_shutdown=0; +# restart +SET GLOBAL INNODB_FILE_PER_TABLE= 0; +Warnings: +Warning 1287 '@@innodb_file_per_table' is deprecated and will be removed in a future release +SET UNIQUE_CHECKS=0, FOREIGN_KEY_CHECKS=0; +CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, +f3 INT NOT NULL, INDEX(f1), +INDEX(f2), INDEX(f3))ENGINE=InnoDB; +BEGIN; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +COMMIT; +DROP TABLE t1; +SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 0; +NAME FILE_SIZE +innodb_system 70254592 +SET GLOBAL innodb_fast_shutdown=0; +# restart +SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 0; +NAME FILE_SIZE +innodb_system 3145728 diff --git a/mysql-test/suite/innodb/r/sys_truncate_shutdown_debug.result b/mysql-test/suite/innodb/r/sys_truncate_shutdown_debug.result new file mode 100644 index 00000000000..0aad5af9cb6 --- /dev/null +++ b/mysql-test/suite/innodb/r/sys_truncate_shutdown_debug.result @@ -0,0 +1,41 @@ +call mtr.add_suppression("InnoDB: Cannot shrink the system tablespace"); +call mtr.add_suppression("InnoDB: Plugin initialization aborted"); +call mtr.add_suppression("Plugin 'InnoDB' init function returned error"); +call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); +SET GLOBAL innodb_fast_shutdown=0; +# restart +SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=2; +SET GLOBAL INNODB_FILE_PER_TABLE= 0; +Warnings: +Warning 1287 '@@innodb_file_per_table' is deprecated and will be removed in a future release +SET UNIQUE_CHECKS=0, FOREIGN_KEY_CHECKS=0; +CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, +f3 INT NOT NULL, INDEX(f1), +INDEX(f2), INDEX(f3))ENGINE=InnoDB; +BEGIN; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +COMMIT; +DROP TABLE t1; +SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 0; +NAME FILE_SIZE +innodb_system 540016640 +SET GLOBAL INNODB_FAST_SHUTDOWN=0; +SET GLOBAL DEBUG_DBUG="+d,shrink_buffer_pool_full"; +# restart +FOUND 1 /\[Warning\] InnoDB: Cannot shrink the system tablespace/ in mysqld.1.err +SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 0; +NAME FILE_SIZE +innodb_system 540016640 +SET GLOBAL INNODB_FAST_SHUTDOWN=0; +SET GLOBAL DEBUG_DBUG="+d,mtr_log_max_size"; +# restart +FOUND 1 /\[ERROR\] InnoDB: Cannot shrink the system tablespace/ in mysqld.1.err +SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 0; +NAME FILE_SIZE +innodb_system 540016640 +SET GLOBAL INNODB_FAST_SHUTDOWN=0; +# restart: --debug_dbug=+d,crash_after_sys_truncate +SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 0; +NAME FILE_SIZE +innodb_system 3145728 diff --git a/mysql-test/suite/innodb/t/sys_truncate_shutdown.opt b/mysql-test/suite/innodb/t/sys_truncate_shutdown.opt new file mode 100644 index 00000000000..001feac38fb --- /dev/null +++ b/mysql-test/suite/innodb/t/sys_truncate_shutdown.opt @@ -0,0 +1,3 @@ +--innodb_data_file_path=ibdata1:1M:autoextend +--innodb_sys_tablespaces +--innodb_page_size=4k diff --git a/mysql-test/suite/innodb/t/sys_truncate_shutdown.test b/mysql-test/suite/innodb/t/sys_truncate_shutdown.test new file mode 100644 index 00000000000..0f61049ba5e --- /dev/null +++ b/mysql-test/suite/innodb/t/sys_truncate_shutdown.test @@ -0,0 +1,20 @@ +--source include/have_innodb.inc +--source include/have_sequence.inc +SET GLOBAL innodb_fast_shutdown=0; +--source include/restart_mysqld.inc +SET GLOBAL INNODB_FILE_PER_TABLE= 0; +SET UNIQUE_CHECKS=0, FOREIGN_KEY_CHECKS=0; +CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, + f3 INT NOT NULL, INDEX(f1), + INDEX(f2), INDEX(f3))ENGINE=InnoDB; +BEGIN; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +COMMIT; +DROP TABLE t1; +SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 0; + +SET GLOBAL innodb_fast_shutdown=0; +--source include/restart_mysqld.inc +SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 0; diff --git a/mysql-test/suite/innodb/t/sys_truncate_shutdown_debug.opt b/mysql-test/suite/innodb/t/sys_truncate_shutdown_debug.opt new file mode 100644 index 00000000000..001feac38fb --- /dev/null +++ b/mysql-test/suite/innodb/t/sys_truncate_shutdown_debug.opt @@ -0,0 +1,3 @@ +--innodb_data_file_path=ibdata1:1M:autoextend +--innodb_sys_tablespaces +--innodb_page_size=4k diff --git a/mysql-test/suite/innodb/t/sys_truncate_shutdown_debug.test b/mysql-test/suite/innodb/t/sys_truncate_shutdown_debug.test new file mode 100644 index 00000000000..8e8c91e7b47 --- /dev/null +++ b/mysql-test/suite/innodb/t/sys_truncate_shutdown_debug.test @@ -0,0 +1,51 @@ +--source include/have_innodb.inc +--source include/have_sequence.inc +--source include/not_embedded.inc +--source include/have_debug.inc + +call mtr.add_suppression("InnoDB: Cannot shrink the system tablespace"); +call mtr.add_suppression("InnoDB: Plugin initialization aborted"); +call mtr.add_suppression("Plugin 'InnoDB' init function returned error"); +call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); + +SET GLOBAL innodb_fast_shutdown=0; +--source include/restart_mysqld.inc +SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=2; +SET GLOBAL INNODB_FILE_PER_TABLE= 0; +SET UNIQUE_CHECKS=0, FOREIGN_KEY_CHECKS=0; +CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL, + f3 INT NOT NULL, INDEX(f1), + INDEX(f2), INDEX(f3))ENGINE=InnoDB; +BEGIN; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +INSERT INTO t1 SELECT seq, seq, seq FROM seq_1_to_16384; +COMMIT; +DROP TABLE t1; +SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 0; + +SET GLOBAL INNODB_FAST_SHUTDOWN=0; +SET GLOBAL DEBUG_DBUG="+d,shrink_buffer_pool_full"; +--source include/restart_mysqld.inc + +--let SEARCH_PATTERN= \\[Warning\\] InnoDB: Cannot shrink the system tablespace +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; +--source include/search_pattern_in_file.inc + +SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 0; + +SET GLOBAL INNODB_FAST_SHUTDOWN=0; +SET GLOBAL DEBUG_DBUG="+d,mtr_log_max_size"; +--source include/restart_mysqld.inc + +--let SEARCH_PATTERN= \\[ERROR\\] InnoDB: Cannot shrink the system tablespace +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; +--source include/search_pattern_in_file.inc + +SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 0; + +SET GLOBAL INNODB_FAST_SHUTDOWN=0; +# Crash after shrinking the system tablespace +let $restart_parameters=--debug_dbug="+d,crash_after_sys_truncate"; +--source include/restart_mysqld.inc + +SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 0; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 4e5a46c1a00..d937c654de5 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4236,6 +4236,11 @@ innobase_end(handlerton*, ha_panic_function) } } + /* Do system tablespace truncation during slow shutdown */ + if (!srv_fast_shutdown + && srv_operation == SRV_OPERATION_NORMAL) { + fsp_system_tablespace_truncate(); + } innodb_shutdown(); mysql_mutex_destroy(&log_requests.mutex); From acdb8b6779adf2d47f6f2de27da0b2d9b19aad8e Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 28 Nov 2023 12:05:22 +0200 Subject: [PATCH 346/477] Fixed crash in Delayed_insert::get_local_table() This was a bug in my previous commit, found by buildbot --- sql/sql_insert.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 933ce306861..3b634df8547 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2586,7 +2586,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) } THD_STAGE_INFO(client_thd, stage_got_handler_lock); if (client_thd->killed) - goto error; + goto error2; if (thd.killed) { /* @@ -2611,7 +2611,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) my_message(thd.get_stmt_da()->sql_errno(), thd.get_stmt_da()->message(), MYF(0)); } - goto error; + goto error2; } } share= table->s; @@ -2629,7 +2629,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) share->reclength + share->column_bitmap_size*4); if (!copy_tmp) - goto error; + goto error2; /* Copy the TABLE object. */ copy= new (copy_tmp) TABLE; @@ -2739,6 +2739,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) /* Got fatal error */ error: free_root(©->mem_root, 0); +error2: tables_in_use--; mysql_cond_signal(&cond); // Inform thread about abort DBUG_RETURN(0); From 1ffa8c5072935abf481ec9e264d3fcda5acd5c59 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 28 Nov 2023 15:09:04 +0200 Subject: [PATCH 347/477] Fixed build failure on aarch64-macos debug_sync.h was wrongly combined with replication --- sql/slave.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index 0e1cd97414e..84b245fa1be 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -46,7 +46,7 @@ #include #include #include - +#include "debug_sync.h" // debug_sync_set_action #include "sql_base.h" // close_thread_tables #include "tztime.h" // struct Time_zone #include "log_event.h" // Rotate_log_event, @@ -60,7 +60,6 @@ #ifdef HAVE_REPLICATION #include "rpl_tblmap.h" -#include "debug_sync.h" #include "rpl_parallel.h" #include "sql_show.h" #include "semisync_slave.h" From 569da6a7bab034fc9768af88d8dbc2a8e2944764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 28 Nov 2023 15:50:41 +0200 Subject: [PATCH 348/477] MDEV-32899 InnoDB is holding shared dict_sys.latch while waiting for FOREIGN KEY child table lock on DDL lock_table_children(): A new function to lock all child tables of a table. We will only hold dict_sys.latch while traversing dict_table_t::referenced_set. To prevent a race condition with std::set::erase() we will copy the pointers to the child tables to a local vector. Once we have acquired references to all child tables, we can safely release dict_sys.latch, wait for the locks, and finally release the references. This fixes up commit 2ca112346438611ab7800b70bea6af1fd1169308 (MDEV-26217) and commit c3c53926c467c95386ae98d61ada87294bd61478 (MDEV-26554). --- storage/innobase/handler/ha_innodb.cc | 29 +++------------------- storage/innobase/handler/handler0alter.cc | 11 +-------- storage/innobase/include/lock0lock.h | 7 ++++++ storage/innobase/lock/lock0lock.cc | 30 +++++++++++++++++++++++ 4 files changed, 41 insertions(+), 36 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index d5cc2311a2b..ea4f85229b4 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13561,14 +13561,7 @@ int ha_innobase::delete_table(const char *name) /* FOREIGN KEY constraints cannot exist on partitioned tables. */; #endif else - { - dict_sys.freeze(SRW_LOCK_CALL); - for (const dict_foreign_t* f : table->referenced_set) - if (dict_table_t* child= f->foreign_table) - if ((err= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS) - break; - dict_sys.unfreeze(); - } + err= lock_table_children(table, trx); } dict_table_t *table_stats= nullptr, *index_stats= nullptr; @@ -13966,14 +13959,7 @@ int ha_innobase::truncate() dict_table_t *table_stats = nullptr, *index_stats = nullptr; MDL_ticket *mdl_table = nullptr, *mdl_index = nullptr; - dberr_t error= DB_SUCCESS; - - dict_sys.freeze(SRW_LOCK_CALL); - for (const dict_foreign_t *f : ib_table->referenced_set) - if (dict_table_t *child= f->foreign_table) - if ((error= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS) - break; - dict_sys.unfreeze(); + dberr_t error= lock_table_children(ib_table, trx); if (error == DB_SUCCESS) error= lock_table_for_trx(ib_table, trx, LOCK_X); @@ -14164,16 +14150,7 @@ ha_innobase::rename_table( /* There is no need to lock any FOREIGN KEY child tables. */ } else if (dict_table_t *table = dict_table_open_on_name( norm_from, false, DICT_ERR_IGNORE_FK_NOKEY)) { - dict_sys.freeze(SRW_LOCK_CALL); - for (const dict_foreign_t* f : table->referenced_set) { - if (dict_table_t* child = f->foreign_table) { - error = lock_table_for_trx(child, trx, LOCK_X); - if (error != DB_SUCCESS) { - break; - } - } - } - dict_sys.unfreeze(); + error = lock_table_children(table, trx); if (error == DB_SUCCESS) { error = lock_table_for_trx(table, trx, LOCK_X); } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 092aa54737d..9ce277362e4 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -11200,16 +11200,7 @@ ha_innobase::commit_inplace_alter_table( fts_optimize_remove_table(ctx->old_table); } - dict_sys.freeze(SRW_LOCK_CALL); - for (auto f : ctx->old_table->referenced_set) { - if (dict_table_t* child = f->foreign_table) { - error = lock_table_for_trx(child, trx, LOCK_X); - if (error != DB_SUCCESS) { - break; - } - } - } - dict_sys.unfreeze(); + error = lock_table_children(ctx->old_table, trx); if (ctx->new_table->fts) { ut_ad(!ctx->new_table->fts->add_wq); diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 59ee7f551b4..65537859924 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -438,6 +438,13 @@ dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode, bool no_wait= false) MY_ATTRIBUTE((nonnull, warn_unused_result)); +/** Lock the child tables of a table. +@param table parent table +@param trx transaction +@return error code */ +dberr_t lock_table_children(dict_table_t *table, trx_t *trx) + MY_ATTRIBUTE((nonnull, warn_unused_result)); + /** Exclusively lock the data dictionary tables. @param trx dictionary transaction @return error code diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index df51ceb16d8..15098415782 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -3976,6 +3976,36 @@ run_again: return err; } +/** Lock the child tables of a table. +@param table parent table +@param trx transaction +@return error code */ +dberr_t lock_table_children(dict_table_t *table, trx_t *trx) +{ + dict_sys.freeze(SRW_LOCK_CALL); + std::vector children; + + for (auto f : table->referenced_set) + if (dict_table_t *child= f->foreign_table) + { + child->acquire(); + children.emplace_back(child); + } + dict_sys.unfreeze(); + + dberr_t err= DB_SUCCESS; + + for (auto child : children) + if ((err= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS) + break; + + for (auto child : children) + child->release(); + + return err; +} + + /** Exclusively lock the data dictionary tables. @param trx dictionary transaction @return error code From 387b92df97e70680641ad0bcaed83b44373f13c5 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 28 Nov 2023 15:31:02 +0200 Subject: [PATCH 349/477] Remove deprication from mariadbd --debug --debug is supported by allmost all our other binaries and we should keep it also in the server to keep option names similar. --- mysql-test/suite/innodb/r/innodb-blob.result | 6 ------ mysql-test/suite/innodb/r/innodb-index-debug.result | 2 -- mysql-test/suite/innodb/r/innodb-table-online.result | 6 ------ mysql-test/suite/innodb/r/page_reorganize.result | 2 -- .../suite/innodb_fts/r/ft_result_cache_limit.result | 2 -- mysql-test/suite/innodb_gis/r/check_rtree.result | 2 -- mysql-test/suite/innodb_gis/r/rollback.result | 2 -- mysql-test/suite/innodb_gis/r/rtree_compress.result | 2 -- mysql-test/suite/innodb_gis/r/rtree_create_inplace.result | 2 -- mysql-test/suite/rpl/r/rpl_semisync_ali_issues.result | 8 -------- mysql-test/suite/sys_vars/r/debug_basic.result | 2 -- mysql-test/suite/sys_vars/r/sysvars_debug.result | 2 +- sql/sys_vars.cc | 5 ++--- 13 files changed, 3 insertions(+), 40 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-blob.result b/mysql-test/suite/innodb/r/innodb-blob.result index fdfbfe3e683..bbb071ccb3e 100644 --- a/mysql-test/suite/innodb/r/innodb-blob.result +++ b/mysql-test/suite/innodb/r/innodb-blob.result @@ -20,8 +20,6 @@ a RIGHT(b,20) 2 bbbbbbbbbbbbbbbbbbbb connection default; SET DEBUG='+d,row_ins_extern_checkpoint'; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead SET DEBUG_SYNC='before_row_ins_extern_latch SIGNAL rec_not_blob WAIT_FOR crash'; ROLLBACK; BEGIN; @@ -88,8 +86,6 @@ BEGIN; INSERT INTO t2 VALUES (347); connection default; SET DEBUG='+d,row_upd_extern_checkpoint'; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR crash'; UPDATE t3 SET c=REPEAT('i',3000) WHERE a=2; connection con2; @@ -126,8 +122,6 @@ BEGIN; INSERT INTO t2 VALUES (33101); connection default; SET DEBUG='+d,row_upd_extern_checkpoint'; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead SET DEBUG_SYNC='after_row_upd_extern SIGNAL have_latch WAIT_FOR crash'; UPDATE t3 SET c=REPEAT('j',3000) WHERE a=2; connection con2; diff --git a/mysql-test/suite/innodb/r/innodb-index-debug.result b/mysql-test/suite/innodb/r/innodb-index-debug.result index bcd41392adb..8db3757dc95 100644 --- a/mysql-test/suite/innodb/r/innodb-index-debug.result +++ b/mysql-test/suite/innodb/r/innodb-index-debug.result @@ -88,8 +88,6 @@ ALTER TABLE t1 FORCE, ADD COLUMN k4 int; connection default; SET DEBUG_SYNC= 'now WAIT_FOR opened'; SET debug = '+d,row_log_tmpfile_fail'; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead INSERT INTO t1 select NULL,'aaa','bbb' from t480; INSERT INTO t1 select NULL,'aaaa','bbbb' from t480; SET DEBUG_SYNC= 'now SIGNAL flushed'; diff --git a/mysql-test/suite/innodb/r/innodb-table-online.result b/mysql-test/suite/innodb/r/innodb-table-online.result index 8078daad633..8f71ea83b9c 100644 --- a/mysql-test/suite/innodb/r/innodb-table-online.result +++ b/mysql-test/suite/innodb/r/innodb-table-online.result @@ -40,16 +40,10 @@ SET DEBUG_DBUG = '+d,innodb_OOM_prepare_inplace_alter'; ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM=INPLACE, LOCK=NONE; ERROR HY000: Out of memory. SET SESSION DEBUG = @saved_debug_dbug; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead SET SESSION DEBUG = '+d,innodb_OOM_inplace_alter'; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM=INPLACE, LOCK=NONE; ERROR HY000: Out of memory. SET SESSION DEBUG = @saved_debug_dbug; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM=INPLACE, LOCK=NONE; connection default; SHOW CREATE TABLE t1; diff --git a/mysql-test/suite/innodb/r/page_reorganize.result b/mysql-test/suite/innodb/r/page_reorganize.result index 20e1600bd0d..fe85926e2b8 100644 --- a/mysql-test/suite/innodb/r/page_reorganize.result +++ b/mysql-test/suite/innodb/r/page_reorganize.result @@ -16,8 +16,6 @@ SET @save_dbug = @@debug_dbug; SET DEBUG_DBUG = '+d,do_page_reorganize,do_lock_reverse_page_reorganize'; insert into t1(f2) values (repeat('+', 100)); SET DEBUG = @save_dbug; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead commit; connection con1; f1 diff --git a/mysql-test/suite/innodb_fts/r/ft_result_cache_limit.result b/mysql-test/suite/innodb_fts/r/ft_result_cache_limit.result index 2dbdd5a04bc..74d60410d58 100644 --- a/mysql-test/suite/innodb_fts/r/ft_result_cache_limit.result +++ b/mysql-test/suite/innodb_fts/r/ft_result_cache_limit.result @@ -20,8 +20,6 @@ END// CALL populate_t1; SET autocommit=1; SET SESSION debug="+d,fts_instrument_result_cache_limit"; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead ALTER TABLE t1 ADD FULLTEXT INDEX `text_content_idx` (`text_content`); SELECT FTS_DOC_ID, text_content FROM t1 diff --git a/mysql-test/suite/innodb_gis/r/check_rtree.result b/mysql-test/suite/innodb_gis/r/check_rtree.result index fe60a628fde..0d7b25b6b72 100644 --- a/mysql-test/suite/innodb_gis/r/check_rtree.result +++ b/mysql-test/suite/innodb_gis/r/check_rtree.result @@ -1,7 +1,5 @@ create table t1 (i int, g geometry not null, spatial index (g))engine=innodb; SET SESSION debug="+d,rtree_test_check_count"; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead insert into t1 values (1, POINT(1,1)); insert into t1 values (1, POINT(1.5,1.5)); insert into t1 values (1, POINT(3,3)); diff --git a/mysql-test/suite/innodb_gis/r/rollback.result b/mysql-test/suite/innodb_gis/r/rollback.result index 8688690b66a..9e0db79667e 100644 --- a/mysql-test/suite/innodb_gis/r/rollback.result +++ b/mysql-test/suite/innodb_gis/r/rollback.result @@ -408,8 +408,6 @@ update t1 set a=point(5,5), b=point(5,5), c=5 where i < 3; ERROR 23000: Duplicate entry '5' for key 'c' rollback; set session debug="+d,row_mysql_crash_if_error"; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead update t1 set a=point(5,5), b=point(5,5), c=5 where i < 3; ERROR HY000: Lost connection to MySQL server during query insert into t1 values(5, point(5,5), point(5,5), 5); diff --git a/mysql-test/suite/innodb_gis/r/rtree_compress.result b/mysql-test/suite/innodb_gis/r/rtree_compress.result index a88f8b9fa9b..360cf8ab5ef 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_compress.result +++ b/mysql-test/suite/innodb_gis/r/rtree_compress.result @@ -42,8 +42,6 @@ count(*) 0 SET @saved_dbug = @@SESSION.debug_dbug; SET DEBUG='+d,page_copy_rec_list_start_compress_fail'; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead delete from t1; select count(*) from t1 where MBRWithin(t1.c2, @g1); count(*) diff --git a/mysql-test/suite/innodb_gis/r/rtree_create_inplace.result b/mysql-test/suite/innodb_gis/r/rtree_create_inplace.result index a8898f5c98f..5279eea8aa8 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_create_inplace.result +++ b/mysql-test/suite/innodb_gis/r/rtree_create_inplace.result @@ -31,7 +31,5 @@ COUNT(*) 0 ALTER TABLE t1 DROP INDEX idx, ADD SPATIAL INDEX idx3(c2); SET SESSION debug="+d,row_merge_instrument_log_check_flush"; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead ALTER TABLE t1 DROP INDEX idx3, ADD SPATIAL INDEX idx4(c2), ADD SPATIAL INDEX idx5(c3); DROP TABLE t1; diff --git a/mysql-test/suite/rpl/r/rpl_semisync_ali_issues.result b/mysql-test/suite/rpl/r/rpl_semisync_ali_issues.result index 9607e8a7998..94ec9ceae86 100644 --- a/mysql-test/suite/rpl/r/rpl_semisync_ali_issues.result +++ b/mysql-test/suite/rpl/r/rpl_semisync_ali_issues.result @@ -266,16 +266,12 @@ Variable_name Value Rpl_semi_sync_master_clients 1 # Test failure of select error . SET GLOBAL debug = 'd,rpl_semisync_simulate_select_error'; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead INSERT INTO t1 VALUES(3); connection slave; connection con1; # Test failure of pthread_create SET GLOBAL rpl_semi_sync_master_enabled = 0; SET GLOBAL debug = 'd,rpl_semisync_simulate_create_thread_failure'; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead SET GLOBAL rpl_semi_sync_master_enabled= ON; # Test failure of pthread_join SET GLOBAL rpl_semi_sync_master_enabled= OFF; @@ -283,8 +279,6 @@ SET GLOBAL rpl_semi_sync_master_enabled= OFF; # Failure on registering semisync slave # SET GLOBAL debug= 'd,rpl_semisync_simulate_add_slave_failure'; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead SET GLOBAL rpl_semi_sync_master_enabled= ON; connection slave; STOP SLAVE IO_THREAD; @@ -293,8 +287,6 @@ START SLAVE IO_THREAD; include/wait_for_slave_io_to_start.inc connection con1; SET GLOBAL debug=''; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead connection slave; START SLAVE IO_THREAD; include/wait_for_slave_io_to_start.inc diff --git a/mysql-test/suite/sys_vars/r/debug_basic.result b/mysql-test/suite/sys_vars/r/debug_basic.result index a97ad65b40f..5a77446d036 100644 --- a/mysql-test/suite/sys_vars/r/debug_basic.result +++ b/mysql-test/suite/sys_vars/r/debug_basic.result @@ -1,6 +1,4 @@ set session debug="L"; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead select @@global.debug="1"; @@global.debug="1" 0 diff --git a/mysql-test/suite/sys_vars/r/sysvars_debug.result b/mysql-test/suite/sys_vars/r/sysvars_debug.result index 0d77b0211a1..c7357790e6b 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_debug.result +++ b/mysql-test/suite/sys_vars/r/sysvars_debug.result @@ -38,7 +38,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE VARIABLE_SCOPE SESSION VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Built-in DBUG debugger +VARIABLE_COMMENT Built-in DBUG debugger. Alias for --debug NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 081c489de53..cd5e87bc54c 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1002,11 +1002,10 @@ static Sys_var_charptr_fscs Sys_datadir( static Sys_var_dbug Sys_dbug( "debug", "Built-in DBUG debugger", sys_var::SESSION, CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, - ON_CHECK(check_has_super), ON_UPDATE(0), - DEPRECATED("'@@debug_dbug'")); // since 5.5.37 + ON_CHECK(check_has_super)); static Sys_var_dbug Sys_debug_dbug( - "debug_dbug", "Built-in DBUG debugger", sys_var::SESSION, + "debug_dbug", "Built-in DBUG debugger. Alias for --debug", sys_var::SESSION, CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_has_super)); #endif From bc6b6cf6a70b3ac99ead8971c25b2fd9702b0b49 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 28 Nov 2023 17:56:24 +0200 Subject: [PATCH 350/477] Add back --debug option to mariadbd This option was never supposed to be depricated. Almost all MariaDB binaries also supports the --debug option. --- mysql-test/suite/sys_vars/r/sysvars_debug.result | 15 +++++++++++++++ sql/mysqld.cc | 1 - sql/sys_vars.cc | 5 +++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_debug.result b/mysql-test/suite/sys_vars/r/sysvars_debug.result index e929d9000df..fc04ac83210 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_debug.result +++ b/mysql-test/suite/sys_vars/r/sysvars_debug.result @@ -1,6 +1,21 @@ select * from information_schema.system_variables where variable_name like 'debug%' order by variable_name; +VARIABLE_NAME DEBUG +SESSION_VALUE +GLOBAL_VALUE +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE +VARIABLE_SCOPE SESSION +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Built-in DBUG debugger +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL +GLOBAL_VALUE_PATH NULL VARIABLE_NAME DEBUG_BINLOG_FSYNC_SLEEP SESSION_VALUE NULL GLOBAL_VALUE 314 diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 23e327c6802..cdeb4bbcf4c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5366,7 +5366,6 @@ static int init_server_components() MARIADB_REMOVED_OPTION("innodb-change-buffering"), /* removed in 11.3 */ - MARIADB_REMOVED_OPTION("debug"), MARIADB_REMOVED_OPTION("date-format"), MARIADB_REMOVED_OPTION("datetime-format"), MARIADB_REMOVED_OPTION("time-format"), diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 57db827c67b..7ab0f2cd342 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1052,6 +1052,11 @@ static Sys_var_charptr_fscs Sys_datadir( CMD_LINE(REQUIRED_ARG, 'h'), DEFAULT(mysql_real_data_home)); #ifndef DBUG_OFF +static Sys_var_dbug Sys_dbug( + "debug", "Built-in DBUG debugger", sys_var::SESSION, + CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(check_has_super)); + static Sys_var_dbug Sys_debug_dbug( "debug_dbug", "Built-in DBUG debugger", sys_var::SESSION, CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, From ea4bcb9d98189f4c0fc5da28c9ce3e17ac67e875 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Mon, 20 Nov 2023 21:59:55 +0100 Subject: [PATCH 351/477] MDEV-32168: slave_error_param condition is never checked from the wait_for_slave_param.inc Fix some random test failures following MDEV-32168 push. Don't blindly set $rpl_only_running_threads in many places. Instead explicit stop only the IO or SQL thread, as appropriate. Setting it interfered with rpl_end.inc in some cases. Rather than clearing it afterwards, better to not set it at all when it is not needed, removing ambiguity in the test about the state of the replication threads. Don't fail the test if include/stop_slave_io.inc finds an error in the IO thread after stop. Such errors can be simply because slave stop happened in the middle of the IO thread's initial communication with the master. Signed-off-by: Kristian Nielsen --- mysql-test/include/wait_for_slave_io_to_stop.inc | 16 +++++++++++----- ...ed_master_switch_to_unencrypted_coords.result | 2 +- ...pted_master_switch_to_unencrypted_coords.test | 3 +-- ...pted_master_switch_to_unencrypted_gtid.result | 2 +- ...rypted_master_switch_to_unencrypted_gtid.test | 3 +-- .../rpl_mixed_binlog_max_cache_size.result | 2 +- .../rpl_parallel_ignored_errors.result | 2 +- .../suite/multi_source/gtid_slave_pos.result | 2 +- .../suite/multi_source/gtid_slave_pos.test | 3 +-- .../rpl/include/mdev-31448_conservative.inc | 3 ++- .../suite/rpl/include/mdev-31448_optimistic.inc | 3 ++- .../rpl/include/rpl_binlog_max_cache_size.test | 3 +-- .../suite/rpl/include/rpl_start_stop_slave.test | 3 +-- .../mdev-31448_kill_ooo_finish_optimistic.result | 3 ++- mysql-test/suite/rpl/r/rpl_connection.result | 2 +- .../rpl/r/rpl_domain_id_filter_io_crash.result | 8 ++++---- mysql-test/suite/rpl/r/rpl_gtid_errorlog.result | 5 +++-- mysql-test/suite/rpl/r/rpl_gtid_startpos.result | 2 +- .../suite/rpl/r/rpl_heartbeat_basic.result | 2 +- mysql-test/suite/rpl/r/rpl_mdev_17614.result | 6 ++---- .../rpl/r/rpl_mixed_binlog_max_cache_size.result | 2 +- .../rpl/r/rpl_parallel_ignored_errors.result | 2 +- .../rpl/r/rpl_row_binlog_max_cache_size.result | 2 +- mysql-test/suite/rpl/r/rpl_row_corruption.result | 2 +- .../rpl/r/rpl_stm_binlog_max_cache_size.result | 2 +- .../suite/rpl/r/rpl_stm_start_stop_slave.result | 2 +- .../suite/rpl/r/semisync_future-7591.result | 2 +- .../t/mdev-31448_kill_ooo_finish_optimistic.test | 8 +++++--- mysql-test/suite/rpl/t/rpl_connection.test | 3 +-- .../rpl/t/rpl_domain_id_filter_io_crash.test | 9 ++++----- mysql-test/suite/rpl/t/rpl_gtid_errorlog.test | 6 +++--- mysql-test/suite/rpl/t/rpl_gtid_startpos.test | 3 +-- mysql-test/suite/rpl/t/rpl_heartbeat_basic.test | 3 +-- mysql-test/suite/rpl/t/rpl_mdev_17614.test | 8 ++------ .../suite/rpl/t/rpl_parallel_ignored_errors.test | 3 +-- mysql-test/suite/rpl/t/rpl_row_corruption.test | 3 +-- mysql-test/suite/rpl/t/semisync_future-7591.test | 3 +-- 37 files changed, 66 insertions(+), 72 deletions(-) diff --git a/mysql-test/include/wait_for_slave_io_to_stop.inc b/mysql-test/include/wait_for_slave_io_to_stop.inc index 0ad18ffefa2..760e032eeb1 100644 --- a/mysql-test/include/wait_for_slave_io_to_stop.inc +++ b/mysql-test/include/wait_for_slave_io_to_stop.inc @@ -28,6 +28,9 @@ # there is an error in the IO thread. # (If an error is _always_ expected, a better alternative might be to # use wait_for_slave_io_error.inc instead of this file). +# Note: This is currently always enabled, since a simple STOP SLAVE +# IO_THREAD can cause an error if it interrupts the slave's initial +# communication with the master (MDEV-32892). # # $rpl_debug # See include/rpl_init.inc @@ -39,12 +42,15 @@ --let $slave_param= Slave_IO_Running --let $slave_param_value= No -if (!$rpl_allow_error) -{ - --let $slave_error_param= Last_IO_Errno -} +--let $_io_stop_save_allow_error= $slave_error_param +# Disabled, as IO errors are left behind when a normal STOP SLAVE interrupts +# the initial communication between the IO thread and the master (MDEV-32892). +#if (!$rpl_allow_error) +#{ +# --let $slave_error_param= Last_IO_Errno +#} --source include/wait_for_slave_param.inc ---let $slave_error_param= +--let $slave_error_param= $_io_stop_save_allow_error --let $include_filename= wait_for_slave_io_to_stop.inc diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.result b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.result index 33c1f1413b4..25212024623 100644 --- a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.result +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.result @@ -63,7 +63,7 @@ include/wait_for_slave_io_error.inc [errno=1236] SHOW TABLES; Tables_in_test table1_no_encryption -include/stop_slave.inc +include/stop_slave_sql.inc reset slave; ########## # Cleanup diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test index c9dbc5c0e96..b74632690ca 100644 --- a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_coords.test @@ -137,8 +137,7 @@ SHOW TABLES; --disable_connect_log # IO thread is stopped, stop SQL thread only ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_sql.inc --enable_connect_log reset slave; diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.result b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.result index 16ea30557e7..c6835ff90f4 100644 --- a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.result +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.result @@ -62,7 +62,7 @@ include/wait_for_slave_io_error.inc [errno=1236] # ..success SHOW TABLES; Tables_in_test -include/stop_slave.inc +include/stop_slave_sql.inc reset slave; ########## # Cleanup diff --git a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.test b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.test index b96d11c998a..9991fb9b1b9 100644 --- a/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.test +++ b/mysql-test/suite/binlog_encryption/encrypted_master_switch_to_unencrypted_gtid.test @@ -133,8 +133,7 @@ SHOW TABLES; --disable_connect_log # IO thread is stopped, wait for SQL thread to be stopped ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_sql.inc --enable_connect_log reset slave; diff --git a/mysql-test/suite/binlog_encryption/rpl_mixed_binlog_max_cache_size.result b/mysql-test/suite/binlog_encryption/rpl_mixed_binlog_max_cache_size.result index 944ad9331ad..7ce98cbcc10 100644 --- a/mysql-test/suite/binlog_encryption/rpl_mixed_binlog_max_cache_size.result +++ b/mysql-test/suite/binlog_encryption/rpl_mixed_binlog_max_cache_size.result @@ -192,7 +192,7 @@ SET GLOBAL max_binlog_cache_size= ORIGINAL_VALUE; SET GLOBAL binlog_cache_size= ORIGINAL_VALUE; SET GLOBAL max_binlog_stmt_cache_size= ORIGINAL_VALUE; SET GLOBAL binlog_stmt_cache_size= ORIGINAL_VALUE; -include/stop_slave.inc +include/stop_slave_io.inc include/start_slave.inc connection master; connection slave; diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.result b/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.result index f1e8c78d1d1..39ea2f202ea 100644 --- a/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.result +++ b/mysql-test/suite/binlog_encryption/rpl_parallel_ignored_errors.result @@ -36,7 +36,7 @@ connection con_temp2; COMMIT; connection server_2; include/wait_for_slave_sql_error.inc [errno=1062] -include/stop_slave.inc +include/stop_slave_io.inc include/assert.inc [table t1 should have zero rows where a>32] SELECT * FROM t1 WHERE a>32; a diff --git a/mysql-test/suite/multi_source/gtid_slave_pos.result b/mysql-test/suite/multi_source/gtid_slave_pos.result index 6daed494c55..44eb482327d 100644 --- a/mysql-test/suite/multi_source/gtid_slave_pos.result +++ b/mysql-test/suite/multi_source/gtid_slave_pos.result @@ -99,7 +99,7 @@ include/wait_for_slave_to_stop.inc set default_master_connection = 'slave2'; include/wait_for_slave_sql_error.inc [errno=1942] STOP SLAVE; -include/stop_slave.inc +include/wait_for_slave_io_to_stop.inc set default_master_connection = 'slave1'; START SLAVE; include/wait_for_slave_to_start.inc diff --git a/mysql-test/suite/multi_source/gtid_slave_pos.test b/mysql-test/suite/multi_source/gtid_slave_pos.test index 8c8decc476e..cc418d76870 100644 --- a/mysql-test/suite/multi_source/gtid_slave_pos.test +++ b/mysql-test/suite/multi_source/gtid_slave_pos.test @@ -121,8 +121,7 @@ set default_master_connection = 'slave2'; --let $slave_sql_errno= 1942 --source include/wait_for_slave_sql_error.inc STOP SLAVE; ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/wait_for_slave_io_to_stop.inc set default_master_connection = 'slave1'; START SLAVE; --source include/wait_for_slave_to_start.inc diff --git a/mysql-test/suite/rpl/include/mdev-31448_conservative.inc b/mysql-test/suite/rpl/include/mdev-31448_conservative.inc index 53c0444886e..9ab585b0980 100644 --- a/mysql-test/suite/rpl/include/mdev-31448_conservative.inc +++ b/mysql-test/suite/rpl/include/mdev-31448_conservative.inc @@ -36,7 +36,8 @@ insert into t1 values (3); --connection slave --source include/start_slave.inc ---let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE 'Update_rows_log_event::find_row(-1)' and command LIKE 'Slave_worker'; +# Wildcard for `state` as it depends on whether WSREP is compiled in or not. +--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE 'Update_rows_log_event::find_row(%)' and command LIKE 'Slave_worker'; --source include/wait_condition.inc --let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE 'Waiting for prior transaction to commit%' and command LIKE 'Slave_worker'; --source include/wait_condition.inc diff --git a/mysql-test/suite/rpl/include/mdev-31448_optimistic.inc b/mysql-test/suite/rpl/include/mdev-31448_optimistic.inc index 23ddcbd5e6f..ab7de09480e 100644 --- a/mysql-test/suite/rpl/include/mdev-31448_optimistic.inc +++ b/mysql-test/suite/rpl/include/mdev-31448_optimistic.inc @@ -55,7 +55,8 @@ drop table t2; --source include/start_slave.inc --echo # wait for T1 ---let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE 'Update_rows_log_event::find_row(-1)' and command LIKE 'Slave_worker'; +# Wildcard for `state` as it depends on whether WSREP is compiled in or not. +--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE 'Update_rows_log_event::find_row(%)' and command LIKE 'Slave_worker'; --source include/wait_condition.inc --echo # wait for T2 diff --git a/mysql-test/suite/rpl/include/rpl_binlog_max_cache_size.test b/mysql-test/suite/rpl/include/rpl_binlog_max_cache_size.test index 9d0a5685926..59bc4d056ab 100644 --- a/mysql-test/suite/rpl/include/rpl_binlog_max_cache_size.test +++ b/mysql-test/suite/rpl/include/rpl_binlog_max_cache_size.test @@ -433,8 +433,7 @@ source include/show_binlog_events.inc; --eval SET GLOBAL binlog_stmt_cache_size= $old_binlog_stmt_cache_size # SQL slave is stopped, stop only IO thread ---let $rpl_only_running_threads= 1 -source include/stop_slave.inc; +source include/stop_slave_io.inc; source include/start_slave.inc; connection master; diff --git a/mysql-test/suite/rpl/include/rpl_start_stop_slave.test b/mysql-test/suite/rpl/include/rpl_start_stop_slave.test index 793ec159082..72f481e00fb 100644 --- a/mysql-test/suite/rpl/include/rpl_start_stop_slave.test +++ b/mysql-test/suite/rpl/include/rpl_start_stop_slave.test @@ -207,8 +207,7 @@ START SLAVE; --let $status_items= Last_IO_Errno, Last_IO_Error --source include/show_slave_status.inc ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_sql.inc RESET SLAVE; --connection master diff --git a/mysql-test/suite/rpl/r/mdev-31448_kill_ooo_finish_optimistic.result b/mysql-test/suite/rpl/r/mdev-31448_kill_ooo_finish_optimistic.result index 2753e66fe48..a837fe8fa9c 100644 --- a/mysql-test/suite/rpl/r/mdev-31448_kill_ooo_finish_optimistic.result +++ b/mysql-test/suite/rpl/r/mdev-31448_kill_ooo_finish_optimistic.result @@ -42,7 +42,8 @@ include/save_master_gtid.inc connection slave; # # Cleanup -include/stop_slave.inc +include/wait_for_slave_sql_to_stop.inc +include/stop_slave_io.inc set @@global.slave_parallel_threads= 0; set @@global.slave_parallel_mode= conservative; set @@global.innodb_lock_wait_timeout= 50; diff --git a/mysql-test/suite/rpl/r/rpl_connection.result b/mysql-test/suite/rpl/r/rpl_connection.result index b5ce7f4ed71..9fb17b5f174 100644 --- a/mysql-test/suite/rpl/r/rpl_connection.result +++ b/mysql-test/suite/rpl/r/rpl_connection.result @@ -6,7 +6,7 @@ include/stop_slave.inc CHANGE MASTER TO MASTER_USER= '', MASTER_PASSWORD= ''; START SLAVE; include/wait_for_slave_io_error.inc [errno=1045, 1593] -include/stop_slave.inc +include/stop_slave_sql.inc CHANGE MASTER TO MASTER_USER= 'root', MASTER_PASSWORD= ''; START SLAVE; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_domain_id_filter_io_crash.result b/mysql-test/suite/rpl/r/rpl_domain_id_filter_io_crash.result index feef82a57fc..5250c4bb36a 100644 --- a/mysql-test/suite/rpl/r/rpl_domain_id_filter_io_crash.result +++ b/mysql-test/suite/rpl/r/rpl_domain_id_filter_io_crash.result @@ -135,7 +135,7 @@ i 2 3 SET @@global.debug_dbug=@saved_dbug; -include/stop_slave.inc +include/stop_slave_sql.inc DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; @@ -204,7 +204,7 @@ i 10 11 SET @@global.debug_dbug=@saved_dbug; -include/stop_slave.inc +include/stop_slave_sql.inc DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : 1 CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; @@ -287,7 +287,7 @@ i 16 17 SET @@global.debug_dbug=@saved_dbug; -include/stop_slave.inc +include/stop_slave_sql.inc DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : 1 CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; @@ -384,7 +384,7 @@ i 22 23 SET @@global.debug_dbug=@saved_dbug; -include/stop_slave.inc +include/stop_slave_sql.inc DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; diff --git a/mysql-test/suite/rpl/r/rpl_gtid_errorlog.result b/mysql-test/suite/rpl/r/rpl_gtid_errorlog.result index 593f83a7946..229ac02b1d1 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_errorlog.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_errorlog.result @@ -23,7 +23,8 @@ INSERT INTO t1 VALUES (2); SET sql_log_bin=1; START SLAVE; include/wait_for_slave_sql_error.inc [errno=1062] -include/stop_slave.inc +include/wait_for_slave_io_to_start.inc +include/stop_slave_io.inc SET GLOBAL gtid_slave_pos= "0-1-100"; include/start_slave.inc SELECT * FROM t1 ORDER BY a; @@ -39,7 +40,7 @@ REPLACE INTO t1 VALUES (5); SET debug_dbug= @dbug_save; connection slave; include/wait_for_slave_sql_error.inc [errno=1590] -include/stop_slave.inc +include/stop_slave_io.inc SET sql_slave_skip_counter=1; include/start_slave.inc SELECT * FROM t1 ORDER BY a; diff --git a/mysql-test/suite/rpl/r/rpl_gtid_startpos.result b/mysql-test/suite/rpl/r/rpl_gtid_startpos.result index 3c363004170..2ee51245c90 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_startpos.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_startpos.result @@ -36,7 +36,7 @@ CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT, MASTER_USE_GTID=CURRENT_POS; START SLAVE; include/wait_for_slave_io_error.inc [errno=1236] -include/stop_slave.inc +include/stop_slave_sql.inc CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT, MASTER_LOG_FILE="master-bin.000003", MASTER_LOG_POS=4; include/start_slave.inc diff --git a/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result b/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result index 1db69ea4b83..683b5fb569a 100644 --- a/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result +++ b/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result @@ -226,7 +226,7 @@ connection slave; call mtr.add_suppression("Slave SQL.*Duplicate entry .1. for key .PRIMARY.. on query.* error.* 1062"); call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); Heartbeat events are received while sql thread stopped (1 means 'yes'): 1 -include/stop_slave.inc +include/stop_slave_io.inc DROP TABLE t1; *** Master send to slave *** diff --git a/mysql-test/suite/rpl/r/rpl_mdev_17614.result b/mysql-test/suite/rpl/r/rpl_mdev_17614.result index 66aec55fe67..125f90c0485 100644 --- a/mysql-test/suite/rpl/r/rpl_mdev_17614.result +++ b/mysql-test/suite/rpl/r/rpl_mdev_17614.result @@ -29,8 +29,7 @@ SELECT * FROM t1; a b c 1 1 1 2 2 3 -stop slave; -include/stop_slave.inc +include/stop_slave_io.inc reset slave; connection master; reset master; @@ -189,8 +188,7 @@ SELECT * FROM t1; a b c 1 1 1 2 2 3 -stop slave; -include/stop_slave.inc +include/stop_slave_io.inc reset slave; connection master; reset master; diff --git a/mysql-test/suite/rpl/r/rpl_mixed_binlog_max_cache_size.result b/mysql-test/suite/rpl/r/rpl_mixed_binlog_max_cache_size.result index 944ad9331ad..7ce98cbcc10 100644 --- a/mysql-test/suite/rpl/r/rpl_mixed_binlog_max_cache_size.result +++ b/mysql-test/suite/rpl/r/rpl_mixed_binlog_max_cache_size.result @@ -192,7 +192,7 @@ SET GLOBAL max_binlog_cache_size= ORIGINAL_VALUE; SET GLOBAL binlog_cache_size= ORIGINAL_VALUE; SET GLOBAL max_binlog_stmt_cache_size= ORIGINAL_VALUE; SET GLOBAL binlog_stmt_cache_size= ORIGINAL_VALUE; -include/stop_slave.inc +include/stop_slave_io.inc include/start_slave.inc connection master; connection slave; diff --git a/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.result b/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.result index f1e8c78d1d1..39ea2f202ea 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_ignored_errors.result @@ -36,7 +36,7 @@ connection con_temp2; COMMIT; connection server_2; include/wait_for_slave_sql_error.inc [errno=1062] -include/stop_slave.inc +include/stop_slave_io.inc include/assert.inc [table t1 should have zero rows where a>32] SELECT * FROM t1 WHERE a>32; a diff --git a/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result b/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result index a8e569aad61..e10008352a9 100644 --- a/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result +++ b/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result @@ -191,7 +191,7 @@ SET GLOBAL max_binlog_cache_size= ORIGINAL_VALUE; SET GLOBAL binlog_cache_size= ORIGINAL_VALUE; SET GLOBAL max_binlog_stmt_cache_size= ORIGINAL_VALUE; SET GLOBAL binlog_stmt_cache_size= ORIGINAL_VALUE; -include/stop_slave.inc +include/stop_slave_io.inc include/start_slave.inc connection master; connection slave; diff --git a/mysql-test/suite/rpl/r/rpl_row_corruption.result b/mysql-test/suite/rpl/r/rpl_row_corruption.result index 24535460418..1950617af83 100644 --- a/mysql-test/suite/rpl/r/rpl_row_corruption.result +++ b/mysql-test/suite/rpl/r/rpl_row_corruption.result @@ -14,7 +14,7 @@ connection master; UPDATE t1_11753004, t2_11753004 SET t1_11753004.c1=3, t2_11753004.c1=4 WHERE t1_11753004.c1=1 OR t2_11753004.c1=2; connection slave; include/wait_for_slave_sql_error.inc [errno=1593 ] -include/stop_slave.inc +include/stop_slave_io.inc SET @@global.debug_dbug=@saved_debug; include/start_slave.inc connection master; diff --git a/mysql-test/suite/rpl/r/rpl_stm_binlog_max_cache_size.result b/mysql-test/suite/rpl/r/rpl_stm_binlog_max_cache_size.result index 944ad9331ad..7ce98cbcc10 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_binlog_max_cache_size.result +++ b/mysql-test/suite/rpl/r/rpl_stm_binlog_max_cache_size.result @@ -192,7 +192,7 @@ SET GLOBAL max_binlog_cache_size= ORIGINAL_VALUE; SET GLOBAL binlog_cache_size= ORIGINAL_VALUE; SET GLOBAL max_binlog_stmt_cache_size= ORIGINAL_VALUE; SET GLOBAL binlog_stmt_cache_size= ORIGINAL_VALUE; -include/stop_slave.inc +include/stop_slave_io.inc include/start_slave.inc connection master; connection slave; diff --git a/mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result b/mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result index 992e6c2181b..391ef95104f 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result +++ b/mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result @@ -109,7 +109,7 @@ START SLAVE; include/wait_for_slave_param.inc [Last_IO_Errno] Last_IO_Errno = '1236' Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from impossible position; the first event 'master-bin.000001' at XXX, the last event read from 'master-bin.000001' at XXX, the last byte read from 'master-bin.000001' at XXX.'' -include/stop_slave.inc +include/stop_slave_sql.inc RESET SLAVE; connection master; RESET MASTER; diff --git a/mysql-test/suite/rpl/r/semisync_future-7591.result b/mysql-test/suite/rpl/r/semisync_future-7591.result index 9dc0ee51e53..fe355f34cfa 100644 --- a/mysql-test/suite/rpl/r/semisync_future-7591.result +++ b/mysql-test/suite/rpl/r/semisync_future-7591.result @@ -13,7 +13,7 @@ connection master; insert into t1 values (1); reset master; connection slave; -include/stop_slave.inc +include/stop_slave_sql.inc reset slave; include/start_slave.inc set global rpl_semi_sync_slave_enabled = OFF; diff --git a/mysql-test/suite/rpl/t/mdev-31448_kill_ooo_finish_optimistic.test b/mysql-test/suite/rpl/t/mdev-31448_kill_ooo_finish_optimistic.test index ab2f846f33c..12f079dc99d 100644 --- a/mysql-test/suite/rpl/t/mdev-31448_kill_ooo_finish_optimistic.test +++ b/mysql-test/suite/rpl/t/mdev-31448_kill_ooo_finish_optimistic.test @@ -54,7 +54,8 @@ drop table t2; --source include/start_slave.inc --echo # wait for T1 ---let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE 'Update_rows_log_event::find_row(-1)' and command LIKE 'Slave_worker'; +# Wildcard for `state` as it depends on whether WSREP is compiled in or not. +--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE 'Update_rows_log_event::find_row(%)' and command LIKE 'Slave_worker'; --source include/wait_condition.inc --echo # wait for T2 @@ -81,8 +82,9 @@ DROP TABLE t1; --connection slave --echo # --echo # Cleanup ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--let $rpl_allow_error= 1 +--source include/wait_for_slave_sql_to_stop.inc +--source include/stop_slave_io.inc eval set @@global.slave_parallel_threads= $save_slave_parallel_threads; eval set @@global.slave_parallel_mode= $save_slave_parallel_mode; eval set @@global.innodb_lock_wait_timeout= $save_innodb_lock_wait_timeout; diff --git a/mysql-test/suite/rpl/t/rpl_connection.test b/mysql-test/suite/rpl/t/rpl_connection.test index 8eee639cd34..24ada7c85c6 100644 --- a/mysql-test/suite/rpl/t/rpl_connection.test +++ b/mysql-test/suite/rpl/t/rpl_connection.test @@ -16,8 +16,7 @@ CHANGE MASTER TO MASTER_USER= '', MASTER_PASSWORD= ''; START SLAVE; --let $slave_io_errno= 1045, 1593 --source include/wait_for_slave_io_error.inc ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_sql.inc CHANGE MASTER TO MASTER_USER= 'root', MASTER_PASSWORD= ''; START SLAVE; diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test index 22331c39f1d..95fac6c2edb 100644 --- a/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test @@ -149,8 +149,7 @@ connection slave; SELECT * FROM t1; SET @@global.debug_dbug=@saved_dbug; ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_sql.inc let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); --echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before @@ -218,7 +217,7 @@ SELECT * FROM t1; SET @@global.debug_dbug=@saved_dbug; ---source include/stop_slave.inc +--source include/stop_slave_sql.inc let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); --echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before @@ -286,7 +285,7 @@ SELECT * FROM t1; SET @@global.debug_dbug=@saved_dbug; ---source include/stop_slave.inc +--source include/stop_slave_sql.inc let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); --echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before @@ -354,7 +353,7 @@ SELECT * FROM t1; SET @@global.debug_dbug=@saved_dbug; ---source include/stop_slave.inc +--source include/stop_slave_sql.inc let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); --echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before diff --git a/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test b/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test index c8c63cf5e6e..0ee54cd1183 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test @@ -31,8 +31,8 @@ SET sql_log_bin=1; START SLAVE; --let $slave_sql_errno=1062 --source include/wait_for_slave_sql_error.inc ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/wait_for_slave_io_to_start.inc +--source include/stop_slave_io.inc # Skip the problem event from the master. SET GLOBAL gtid_slave_pos= "0-1-100"; --source include/start_slave.inc @@ -51,7 +51,7 @@ SET debug_dbug= @dbug_save; --connection slave --let $slave_sql_errno=1590 --source include/wait_for_slave_sql_error.inc ---source include/stop_slave.inc +--source include/stop_slave_io.inc SET sql_slave_skip_counter=1; --source include/start_slave.inc --sync_with_master diff --git a/mysql-test/suite/rpl/t/rpl_gtid_startpos.test b/mysql-test/suite/rpl/t/rpl_gtid_startpos.test index 834efdc6a2d..6795c008311 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_startpos.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_startpos.test @@ -50,8 +50,7 @@ eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, START SLAVE; --let $slave_io_errno= 1236 --source include/wait_for_slave_io_error.inc ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_sql.inc --replace_result $MASTER_MYPORT MASTER_PORT eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test index cae7a0e59ed..74e1deec44b 100644 --- a/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test +++ b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test @@ -327,8 +327,7 @@ sleep 4; let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) > 0 AS Result, Result, 1); --echo Heartbeat events are received while sql thread stopped (1 means 'yes'): $result ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_io.inc DROP TABLE t1; --echo diff --git a/mysql-test/suite/rpl/t/rpl_mdev_17614.test b/mysql-test/suite/rpl/t/rpl_mdev_17614.test index da70d3ef451..92fddc79e84 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev_17614.test +++ b/mysql-test/suite/rpl/t/rpl_mdev_17614.test @@ -40,9 +40,7 @@ SELECT * FROM t1; SELECT * FROM t1; # restart replication for the next testcase -stop slave; ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_io.inc reset slave; connection master; reset master; @@ -160,9 +158,7 @@ SELECT * FROM t1; SELECT * FROM t1; # restart replication for the next testcase -stop slave; ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_io.inc reset slave; connection master; reset master; diff --git a/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test b/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test index 6303c5c6ddd..e2b85f13cfa 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test @@ -95,8 +95,7 @@ COMMIT; --connection server_2 --let $slave_sql_errno= 1062 --source include/wait_for_slave_sql_error.inc ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_io.inc --let $assert_cond= COUNT(*) = 0 FROM t1 WHERE a>32 --let $assert_text= table t1 should have zero rows where a>32 --source include/assert.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_corruption.test b/mysql-test/suite/rpl/t/rpl_row_corruption.test index 52828a639ed..6f4f9c882e2 100644 --- a/mysql-test/suite/rpl/t/rpl_row_corruption.test +++ b/mysql-test/suite/rpl/t/rpl_row_corruption.test @@ -39,8 +39,7 @@ SET @@global.debug_dbug="d,inject_tblmap_same_id_maps_diff_table"; # wait for error 1593 (ER_SLAVE_FATAL_ERROR) --let $slave_sql_errno=1593 --source include/wait_for_slave_sql_error.inc ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_io.inc # clean up SET @@global.debug_dbug=@saved_debug; diff --git a/mysql-test/suite/rpl/t/semisync_future-7591.test b/mysql-test/suite/rpl/t/semisync_future-7591.test index dd003486495..53d87182870 100644 --- a/mysql-test/suite/rpl/t/semisync_future-7591.test +++ b/mysql-test/suite/rpl/t/semisync_future-7591.test @@ -19,8 +19,7 @@ insert into t1 values (1); reset master; --connection slave ---let $rpl_only_running_threads= 1 ---source include/stop_slave.inc +--source include/stop_slave_sql.inc reset slave; --source include/start_slave.inc From 705f7ab620c2d4ff8876c34953afd94ce9ab8ccc Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Tue, 28 Nov 2023 16:14:47 +0100 Subject: [PATCH 352/477] MDEV-20169: main.partition_innodb fails in buildbot with wrong result The problem is that background statistics can race with statistics update during INSERT and cause slightly inaccurate `Rows` count in table statistics (this is deliberate to avoid excessive locking overhead). This was seen as occasional .result difference in the test. Mask out the unstable `Rows` column from SHOW TABLE STATUS; the value is not related to what is being tested in this part of the test case. Run ANALYZE TABLE before SHOW EXPLAIN to get stable row count in output. Signed-off-by: Kristian Nielsen --- mysql-test/main/partition_innodb.result | 10 +++++++--- mysql-test/main/partition_innodb.test | 9 ++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/mysql-test/main/partition_innodb.result b/mysql-test/main/partition_innodb.result index 17d0c20ec99..5227cd923c3 100644 --- a/mysql-test/main/partition_innodb.result +++ b/mysql-test/main/partition_innodb.result @@ -203,6 +203,10 @@ INSERT INTO t1 VALUES (100); ERROR HY000: Table has no partition for value 100 insert INTO t1 VALUES (110); ERROR HY000: Table has no partition for value 110 +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 90; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables @@ -406,7 +410,7 @@ t1 InnoDB 10 Dynamic 2 8192 16384 0 0 0 NULL Create_time NULL NULL latin1_swedis insert into t1 values (0), (1), (2), (3); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary -t1 InnoDB 10 Dynamic 4 4096 16384 0 0 0 NULL Create_time Update_time NULL latin1_swedish_ci NULL partitioned 0 N +t1 InnoDB 10 Dynamic Rows Avg_row_length 16384 0 0 0 NULL Create_time Update_time NULL latin1_swedish_ci NULL partitioned 0 N drop table t1; create table t1 (a int auto_increment primary key) engine = innodb @@ -417,11 +421,11 @@ t1 InnoDB 10 Dynamic 2 8192 16384 0 0 0 1 Create_time NULL NULL latin1_swedish_c insert into t1 values (NULL), (NULL), (NULL), (NULL); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary -t1 InnoDB 10 Dynamic 4 4096 16384 0 0 0 5 Create_time Update_time NULL latin1_swedish_ci NULL partitioned 0 N +t1 InnoDB 10 Dynamic Rows Avg_row_length 16384 0 0 0 5 Create_time Update_time NULL latin1_swedish_ci NULL partitioned 0 N insert into t1 values (NULL), (NULL), (NULL), (NULL); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary -t1 InnoDB 10 Dynamic 8 2048 16384 0 0 0 9 Create_time Update_time NULL latin1_swedish_ci NULL partitioned 0 N +t1 InnoDB 10 Dynamic Rows Avg_row_length 16384 0 0 0 9 Create_time Update_time NULL latin1_swedish_ci NULL partitioned 0 N drop table t1; create table t1 (a int) partition by key (a) diff --git a/mysql-test/main/partition_innodb.test b/mysql-test/main/partition_innodb.test index cef10e745e0..7b5722feed6 100644 --- a/mysql-test/main/partition_innodb.test +++ b/mysql-test/main/partition_innodb.test @@ -214,6 +214,7 @@ INSERT INTO t1 VALUES (90); INSERT INTO t1 VALUES (100); --error ER_NO_PARTITION_FOR_GIVEN_VALUE insert INTO t1 VALUES (110); +ANALYZE TABLE t1; EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 90; EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 90; EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 90; @@ -426,7 +427,9 @@ partition by key (a); --replace_column 12 Create_time show table status; insert into t1 values (0), (1), (2), (3); ---replace_column 12 Create_time 13 Update_time +# Mask `Rows`, as it can fluctuate slightly if background statistics are +# running simultaneously with insert (MDEV-20169). +--replace_column 5 Rows 6 Avg_row_length 12 Create_time 13 Update_time show table status; drop table t1; @@ -436,10 +439,10 @@ partition by key (a); --replace_column 12 Create_time show table status; insert into t1 values (NULL), (NULL), (NULL), (NULL); ---replace_column 12 Create_time 13 Update_time +--replace_column 5 Rows 6 Avg_row_length 12 Create_time 13 Update_time show table status; insert into t1 values (NULL), (NULL), (NULL), (NULL); ---replace_column 12 Create_time 13 Update_time +--replace_column 5 Rows 6 Avg_row_length 12 Create_time 13 Update_time show table status; drop table t1; From 1fec50120fb4b08ea76cc79cf65905a0d5027e84 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 29 Nov 2023 12:23:46 +1100 Subject: [PATCH 353/477] mallinfo2: include malloc header even if mallinfo undetected It may be the case that for some reason, -Werror deprecated for instance, that mallinfo isn't detected. In this case the malloc.h headers won't be included which defined the mallinfo2 function and its structure. Re-organise so that either function pulls in the header. --- sql/sql_test.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 5ea132c83d4..1470965eefe 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -27,11 +27,13 @@ #include "my_json_writer.h" #include #include -#if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_H) +#if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2) +#if defined(HAVE_MALLOC_H) #include -#elif defined(HAVE_MALLINFO) && defined(HAVE_SYS_MALLOC_H) +#elif defined(HAVE_SYS_MALLOC_H) #include #endif +#endif #ifdef HAVE_EVENT_SCHEDULER #include "events.h" From ba6bf7ad9e52c1dc31a22a619c17e1bb55b46d5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 29 Nov 2023 10:48:10 +0200 Subject: [PATCH 354/477] MDEV-32899 instrumentation In debug builds, let us declare dict_sys.latch as index_lock instead of srw_lock, so that we will benefit from the full tracking of lock ownership. lock_table_for_trx(): Assert that the current thread is not holding dict_sys.latch. If the dict_sys.unfreeze() call were moved to the end of lock_table_children(), this assertion would fail in the test innodb.innodb and many other tests that use FOREIGN KEY. --- .../perfschema/r/sxlock_func,debug.rdiff | 22 ++++++++ .../suite/perfschema/t/sxlock_func.test | 1 + storage/innobase/dict/dict0dict.cc | 37 +++++++----- storage/innobase/handler/ha_innodb.cc | 8 ++- storage/innobase/include/dict0dict.h | 56 +++++++++---------- storage/innobase/lock/lock0lock.cc | 2 + 6 files changed, 84 insertions(+), 42 deletions(-) create mode 100644 mysql-test/suite/perfschema/r/sxlock_func,debug.rdiff diff --git a/mysql-test/suite/perfschema/r/sxlock_func,debug.rdiff b/mysql-test/suite/perfschema/r/sxlock_func,debug.rdiff new file mode 100644 index 00000000000..0596810e553 --- /dev/null +++ b/mysql-test/suite/perfschema/r/sxlock_func,debug.rdiff @@ -0,0 +1,22 @@ +@@ -7,7 +7,6 @@ + WHERE name LIKE 'wait/synch/rwlock/innodb/%' + AND name!='wait/synch/rwlock/innodb/btr_search_latch' ORDER BY name; + name +-wait/synch/rwlock/innodb/dict_operation_lock + wait/synch/rwlock/innodb/fil_space_latch + wait/synch/rwlock/innodb/lock_latch + wait/synch/rwlock/innodb/trx_i_s_cache_lock +@@ -19,11 +18,13 @@ + select name from performance_schema.setup_instruments + where name like "wait/synch/sxlock/%" order by name; + name ++wait/synch/sxlock/innodb/dict_operation_lock + wait/synch/sxlock/innodb/index_tree_rw_lock + SELECT DISTINCT name FROM performance_schema.rwlock_instances + WHERE name LIKE 'wait/synch/sxlock/innodb/%' + ORDER BY name; + name ++wait/synch/sxlock/innodb/dict_operation_lock + wait/synch/sxlock/innodb/index_tree_rw_lock + create table t1(a int) engine=innodb; + begin; diff --git a/mysql-test/suite/perfschema/t/sxlock_func.test b/mysql-test/suite/perfschema/t/sxlock_func.test index c43adc849d2..24d0e07ca41 100644 --- a/mysql-test/suite/perfschema/t/sxlock_func.test +++ b/mysql-test/suite/perfschema/t/sxlock_func.test @@ -5,6 +5,7 @@ --source include/not_embedded.inc --source include/have_perfschema.inc --source include/have_innodb.inc +--source include/maybe_debug.inc UPDATE performance_schema.setup_instruments SET enabled = 'NO', timed = 'YES'; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 0680e60d81c..25f72a974c3 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -958,11 +958,12 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line)) if (latch_ex_wait_start.compare_exchange_strong (old, now, std::memory_order_relaxed, std::memory_order_relaxed)) { +#ifdef UNIV_DEBUG + latch.x_lock(SRW_LOCK_ARGS(file, line)); +#else latch.wr_lock(SRW_LOCK_ARGS(file, line)); +#endif latch_ex_wait_start.store(0, std::memory_order_relaxed); - ut_ad(!latch_readers); - ut_ad(!latch_ex); - ut_d(latch_ex= pthread_self()); return; } @@ -977,33 +978,39 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line)) if (waited > threshold / 4) ib::warn() << "A long wait (" << waited << " seconds) was observed for dict_sys.latch"; +#ifdef UNIV_DEBUG + latch.x_lock(SRW_LOCK_ARGS(file, line)); +#else latch.wr_lock(SRW_LOCK_ARGS(file, line)); - ut_ad(!latch_readers); - ut_ad(!latch_ex); - ut_d(latch_ex= pthread_self()); +#endif } #ifdef UNIV_PFS_RWLOCK ATTRIBUTE_NOINLINE void dict_sys_t::unlock() { - ut_ad(latch_ex == pthread_self()); - ut_ad(!latch_readers); - ut_d(latch_ex= 0); +# ifdef UNIV_DEBUG + latch.x_unlock(); +# else latch.wr_unlock(); +# endif } ATTRIBUTE_NOINLINE void dict_sys_t::freeze(const char *file, unsigned line) { +# ifdef UNIV_DEBUG + latch.s_lock(file, line); +# else latch.rd_lock(file, line); - ut_ad(!latch_ex); - ut_d(latch_readers++); +# endif } ATTRIBUTE_NOINLINE void dict_sys_t::unfreeze() { - ut_ad(!latch_ex); - ut_ad(latch_readers--); +# ifdef UNIV_DEBUG + latch.s_unlock(); +# else latch.rd_unlock(); +# endif } #endif /* UNIV_PFS_RWLOCK */ @@ -4533,7 +4540,11 @@ void dict_sys_t::close() temp_id_hash.free(); unlock(); +#ifdef UNIV_DEBUG + latch.free(); +#else latch.destroy(); +#endif mysql_mutex_destroy(&dict_foreign_err_mutex); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ea4f85229b4..b38b1218fb6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -598,7 +598,13 @@ static PSI_rwlock_info all_innodb_rwlocks[] = # ifdef BTR_CUR_HASH_ADAPT { &btr_search_latch_key, "btr_search_latch", 0 }, # endif - { &dict_operation_lock_key, "dict_operation_lock", 0 }, + { &dict_operation_lock_key, "dict_operation_lock", +# ifdef UNIV_DEBUG + PSI_RWLOCK_FLAG_SX +# else + 0 +# endif + }, { &fil_space_latch_key, "fil_space_latch", 0 }, { &trx_i_s_cache_lock_key, "trx_i_s_cache_lock", 0 }, { &trx_purge_latch_key, "trx_purge_latch", 0 }, diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 895743be84b..a0ba7d6ff5c 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1316,14 +1316,14 @@ class dict_sys_t /** The my_hrtime_coarse().val of the oldest lock_wait() start, or 0 */ std::atomic latch_ex_wait_start; - /** the rw-latch protecting the data dictionary cache */ - alignas(CPU_LEVEL1_DCACHE_LINESIZE) srw_lock latch; #ifdef UNIV_DEBUG - /** whether latch is being held in exclusive mode (by any thread) */ - Atomic_relaxed latch_ex; - /** number of S-latch holders */ - Atomic_counter latch_readers; + typedef index_lock dict_lock; +#else + typedef srw_lock dict_lock; #endif + + /** the rw-latch protecting the data dictionary cache */ + alignas(CPU_LEVEL1_DCACHE_LINESIZE) dict_lock latch; public: /** Indexes of SYS_TABLE[] */ enum @@ -1491,15 +1491,12 @@ public: } #ifdef UNIV_DEBUG - /** @return whether any thread (not necessarily the current thread) - is holding the latch; that is, this check may return false - positives */ - bool frozen() const { return latch_readers || latch_ex; } - /** @return whether any thread (not necessarily the current thread) - is holding a shared latch */ - bool frozen_not_locked() const { return latch_readers; } + /** @return whether the current thread is holding the latch */ + bool frozen() const { return latch.have_any(); } + /** @return whether the current thread is holding a shared latch */ + bool frozen_not_locked() const { return latch.have_s(); } /** @return whether the current thread holds the exclusive latch */ - bool locked() const { return latch_ex == pthread_self(); } + bool locked() const { return latch.have_x(); } #endif private: /** Acquire the exclusive latch */ @@ -1514,13 +1511,11 @@ public: /** Exclusively lock the dictionary cache. */ void lock(SRW_LOCK_ARGS(const char *file, unsigned line)) { - if (latch.wr_lock_try()) - { - ut_ad(!latch_readers); - ut_ad(!latch_ex); - ut_d(latch_ex= pthread_self()); - } - else +#ifdef UNIV_DEBUG + if (!latch.x_lock_try()) +#else + if (!latch.wr_lock_try()) +#endif lock_wait(SRW_LOCK_ARGS(file, line)); } @@ -1535,24 +1530,29 @@ public: /** Unlock the data dictionary cache. */ void unlock() { - ut_ad(latch_ex == pthread_self()); - ut_ad(!latch_readers); - ut_d(latch_ex= 0); +# ifdef UNIV_DEBUG + latch.x_unlock(); +# else latch.wr_unlock(); +# endif } /** Acquire a shared lock on the dictionary cache. */ void freeze() { +# ifdef UNIV_DEBUG + latch.s_lock(); +# else latch.rd_lock(); - ut_ad(!latch_ex); - ut_d(latch_readers++); +# endif } /** Release a shared lock on the dictionary cache. */ void unfreeze() { - ut_ad(!latch_ex); - ut_ad(latch_readers--); +# ifdef UNIV_DEBUG + latch.s_unlock(); +# else latch.rd_unlock(); +# endif } #endif diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 15098415782..c9072998e66 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -3940,6 +3940,8 @@ static void lock_table_dequeue(lock_t *in_lock, bool owns_wait_mutex) dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode, bool no_wait) { + ut_ad(!dict_sys.frozen()); + mem_heap_t *heap= mem_heap_create(512); sel_node_t *node= sel_node_create(heap); que_thr_t *thr= pars_complete_graph_for_exec(node, trx, heap, nullptr); From 47fc64c19f5525161a840405f4ac98963fdaafc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 29 Nov 2023 10:52:25 +0200 Subject: [PATCH 355/477] MDEV-32833 InnoDB wrong error message trx_t::commit_in_memory(): Empty the detailed_error string, so that FOREIGN KEY error messages from an earlier transaction will not be wrongly reused in ha_innobase::get_error_message(). Reviewed by: Thirunarayanan Balathandayuthapani --- mysql-test/suite/innodb/r/foreign-keys.result | 7 +++++++ mysql-test/suite/innodb/r/innodb.result | 2 +- mysql-test/suite/innodb/t/foreign-keys.test | 4 ++++ storage/innobase/include/trx0trx.h | 1 + storage/innobase/trx/trx0trx.cc | 1 + 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/r/foreign-keys.result b/mysql-test/suite/innodb/r/foreign-keys.result index 503825dbeee..f7f87bd7898 100644 --- a/mysql-test/suite/innodb/r/foreign-keys.result +++ b/mysql-test/suite/innodb/r/foreign-keys.result @@ -236,3 +236,10 @@ INSERT INTO t2 VALUES('G', 3); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`)) DROP TABLE t2, t1; SET FOREIGN_KEY_CHECKS=DEFAULT; +CREATE TABLE t1(a SERIAL) ENGINE=InnoDB ROW_FORMAT=COMPRESSED PAGE_COMPRESSED=1; +ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") +SHOW WARNINGS; +Level Code Message +Warning 140 InnoDB: PAGE_COMPRESSED table can't have ROW_TYPE=COMPRESSED +Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") +Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index 5e0f231d419..1401b539c06 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -2481,7 +2481,7 @@ INSERT INTO t2 VALUES(1); DELETE FROM t1 WHERE id = 1; ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`)) DROP TABLE t1; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`)) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails SET FOREIGN_KEY_CHECKS=0; DROP TABLE t1; SET FOREIGN_KEY_CHECKS=1; diff --git a/mysql-test/suite/innodb/t/foreign-keys.test b/mysql-test/suite/innodb/t/foreign-keys.test index b93f82c93ef..aeff7009402 100644 --- a/mysql-test/suite/innodb/t/foreign-keys.test +++ b/mysql-test/suite/innodb/t/foreign-keys.test @@ -268,3 +268,7 @@ SET FOREIGN_KEY_CHECKS=1; INSERT INTO t2 VALUES('G', 3); DROP TABLE t2, t1; SET FOREIGN_KEY_CHECKS=DEFAULT; + +--error ER_CANT_CREATE_TABLE +CREATE TABLE t1(a SERIAL) ENGINE=InnoDB ROW_FORMAT=COMPRESSED PAGE_COMPRESSED=1; +SHOW WARNINGS; diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index b84f458374e..5574980f3ec 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -1054,6 +1054,7 @@ public: { ut_ad(state == TRX_STATE_NOT_STARTED); ut_ad(!id); + ut_ad(!*detailed_error); ut_ad(!has_logged()); ut_ad(!is_referenced()); ut_ad(!is_wsrep()); diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 00d8506c5e7..0d37fac9bd0 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1471,6 +1471,7 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr) DBUG_LOG("trx", "Commit in memory: " << this); state= TRX_STATE_NOT_STARTED; + *detailed_error= '\0'; assert_freed(); trx_init(this); From e996f77cd8716320dc132bd63a252a4b5bb1366e Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 29 Nov 2023 17:43:40 +0530 Subject: [PATCH 356/477] MDEV-32897 main suite test case prints extra row for metadata_lock_info query MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added the parameter stats_persistent=0 for InnoDB engine. - Before printing metadata_lock_info query, make sure that InnoDB does complete purging. Reviewed by: Marko Mäkelä --- mysql-test/main/backup_interaction.result | 8 ++++++-- mysql-test/main/backup_interaction.test | 9 +++++++-- mysql-test/main/backup_lock.result | 11 +++++++++-- mysql-test/main/backup_lock.test | 12 +++++++++--- mysql-test/main/backup_locks.result | 7 ++++++- mysql-test/main/backup_locks.test | 10 ++++++---- mysql-test/main/backup_stages.result | 4 ++++ mysql-test/main/backup_stages.test | 4 ++++ mysql-test/main/create_or_replace.result | 4 ++++ mysql-test/main/create_or_replace.test | 4 ++++ mysql-test/main/mdl.result | 8 +++++++- mysql-test/main/mdl.test | 9 +++++++-- mysql-test/main/mdl_sync.result | 6 +++++- mysql-test/main/mdl_sync.test | 6 +++++- 14 files changed, 83 insertions(+), 19 deletions(-) diff --git a/mysql-test/main/backup_interaction.result b/mysql-test/main/backup_interaction.result index 3c3071b8e70..55a05b7f6dd 100644 --- a/mysql-test/main/backup_interaction.result +++ b/mysql-test/main/backup_interaction.result @@ -1,3 +1,5 @@ +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; # # Check backup and FTWRL # @@ -95,7 +97,7 @@ drop table t1; # # BACKUP STAGE performs implicit commits # -create table t1(a int) engine=InnoDB; +create table t1(a int) stats_persistent=0, engine=InnoDB; begin; insert into t1 values(1); select lock_mode from information_schema.metadata_lock_info; @@ -197,8 +199,9 @@ drop table t1; # CHECK: RO transaction under BACKUP STAGE is a potential deadlock # OTOH we most probably allow them under FTWRL as well # -CREATE TABLE t1 (col1 INT) ENGINE = InnoDB; +CREATE TABLE t1 (col1 INT)stats_persistent=0, ENGINE = InnoDB; insert into t1 values (1); +InnoDB 0 transactions not purged backup stage start; backup stage block_commit; begin; @@ -526,3 +529,4 @@ FLUSH TABLE t1 WITH READ LOCK; ERROR HY000: Can't execute the command as you have a BACKUP STAGE active BACKUP STAGE END; DROP TABLE t1; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/main/backup_interaction.test b/mysql-test/main/backup_interaction.test index 05e359d1c71..7eecbaf1c14 100644 --- a/mysql-test/main/backup_interaction.test +++ b/mysql-test/main/backup_interaction.test @@ -5,6 +5,9 @@ --source include/have_innodb.inc --source include/have_metadata_lock_info.inc +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; + --echo # --echo # Check backup and FTWRL --echo # @@ -120,7 +123,7 @@ drop table t1; --echo # BACKUP STAGE performs implicit commits --echo # --disable_view_protocol -create table t1(a int) engine=InnoDB; +create table t1(a int) stats_persistent=0, engine=InnoDB; begin; insert into t1 values(1); select lock_mode from information_schema.metadata_lock_info; @@ -221,8 +224,9 @@ drop table t1; --echo # OTOH we most probably allow them under FTWRL as well --echo # --disable_view_protocol -CREATE TABLE t1 (col1 INT) ENGINE = InnoDB; +CREATE TABLE t1 (col1 INT)stats_persistent=0, ENGINE = InnoDB; insert into t1 values (1); +--source ../suite/innodb/include/wait_all_purged.inc backup stage start; backup stage block_commit; begin; @@ -521,3 +525,4 @@ FLUSH TABLE t1 FOR EXPORT; FLUSH TABLE t1 WITH READ LOCK; BACKUP STAGE END; DROP TABLE t1; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/main/backup_lock.result b/mysql-test/main/backup_lock.result index 95b2f520d90..a122abd1464 100644 --- a/mysql-test/main/backup_lock.result +++ b/mysql-test/main/backup_lock.result @@ -1,6 +1,9 @@ # # Testing which locks we get from all stages # +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; +InnoDB 0 transactions not purged BACKUP STAGE START; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME @@ -29,7 +32,8 @@ connection default; # # testing if BACKUP STAGE FLUSH causes deadlocks with ALTER TABLE # -create table t1 (a int) engine=innodb; +create table t1 (a int) stats_persistent= 0, engine=innodb; +InnoDB 0 transactions not purged start transaction; insert into t1 values (1); connection con1; @@ -95,7 +99,8 @@ drop table t1; # # testing if BACKUP STAGE FLUSH causes deadlocks with DROP TABLE # -create table t1 (a int) engine=innodb; +create table t1 (a int)stats_persistent=0, engine=innodb; +InnoDB 0 transactions not purged start transaction; insert into t1 values (1); connection con1; @@ -122,6 +127,7 @@ connection default; # Check if backup stage block_dll + concurrent drop table blocks select # create table t1 (a int) engine=innodb; +InnoDB 0 transactions not purged backup stage start; backup stage block_ddl; connection con1; @@ -217,3 +223,4 @@ DROP TABLE t_permanent_myisam, t_permanent_innodb; DROP TABLE t_con1_innodb, t_con1_myisam; disconnect con1; set global lock_wait_timeout=default; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/main/backup_lock.test b/mysql-test/main/backup_lock.test index 1f3e4a8704d..bbb4976c233 100644 --- a/mysql-test/main/backup_lock.test +++ b/mysql-test/main/backup_lock.test @@ -12,6 +12,9 @@ --echo # Testing which locks we get from all stages --echo # +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; +--source ../suite/innodb/include/wait_all_purged.inc BACKUP STAGE START; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; BACKUP STAGE FLUSH; @@ -36,8 +39,8 @@ connection default; --echo # testing if BACKUP STAGE FLUSH causes deadlocks with ALTER TABLE --echo # -create table t1 (a int) engine=innodb; - +create table t1 (a int) stats_persistent= 0, engine=innodb; +--source ../suite/innodb/include/wait_all_purged.inc start transaction; # Acquires MDL lock insert into t1 values (1); @@ -123,7 +126,8 @@ drop table t1; --echo # testing if BACKUP STAGE FLUSH causes deadlocks with DROP TABLE --echo # -create table t1 (a int) engine=innodb; +create table t1 (a int)stats_persistent=0, engine=innodb; +--source ../suite/innodb/include/wait_all_purged.inc start transaction; # Acquires MDL lock insert into t1 values (1); @@ -159,6 +163,7 @@ connection default; --echo # create table t1 (a int) engine=innodb; +--source ../suite/innodb/include/wait_all_purged.inc backup stage start; backup stage block_ddl; connection con1; @@ -284,3 +289,4 @@ DROP TABLE t_permanent_myisam, t_permanent_innodb; DROP TABLE t_con1_innodb, t_con1_myisam; --disconnect con1 set global lock_wait_timeout=default; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/main/backup_locks.result b/mysql-test/main/backup_locks.result index fe7b36f11df..9222442e01c 100644 --- a/mysql-test/main/backup_locks.result +++ b/mysql-test/main/backup_locks.result @@ -1,6 +1,9 @@ # # Test lock taken # +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; +InnoDB 0 transactions not purged BACKUP LOCK test.t1; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME @@ -23,7 +26,7 @@ BACKUP UNLOCK; # connect con1,localhost,root,,; connection default; -create table t1 (a int) engine=innodb; +create table t1 (a int) stats_persistent=0,engine=innodb; insert into t1 values (1); backup lock t1; select * from t1; @@ -32,6 +35,7 @@ a connection con1; drop table t1; connection default; +InnoDB 0 transactions not purged SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME MDL_SHARED_HIGH_PRIO Table metadata lock test t1 @@ -93,6 +97,7 @@ BACKUP LOCK t1; ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction UNLOCK TABLES; INSERT INTO t1 VALUES(0); +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; # restart DROP TABLE t1; DROP TABLE t2; diff --git a/mysql-test/main/backup_locks.test b/mysql-test/main/backup_locks.test index cf764e2d60c..441fd1bd35b 100644 --- a/mysql-test/main/backup_locks.test +++ b/mysql-test/main/backup_locks.test @@ -10,7 +10,9 @@ --echo # --echo # Test lock taken --echo # - +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; +--source ../suite/innodb/include/wait_all_purged.inc BACKUP LOCK test.t1; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; BACKUP UNLOCK; @@ -29,7 +31,7 @@ BACKUP UNLOCK; connect (con1,localhost,root,,); connection default; -create table t1 (a int) engine=innodb; +create table t1 (a int) stats_persistent=0,engine=innodb; insert into t1 values (1); backup lock t1; select * from t1; @@ -40,6 +42,7 @@ let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock"; --source include/wait_condition.inc +--source ../suite/innodb/include/wait_all_purged.inc SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; --error ER_LOCK_DEADLOCK select * from t1; @@ -107,6 +110,7 @@ LOCK TABLES t2 AS a2 WRITE; BACKUP LOCK t1; UNLOCK TABLES; INSERT INTO t1 VALUES(0); +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; --source include/restart_mysqld.inc DROP TABLE t1; DROP TABLE t2; @@ -187,7 +191,6 @@ LOCK TABLES t3 AS a2 WRITE, t3 AS a1 READ LOCAL; DROP TABLE t3; BACKUP UNLOCK; DROP TABLE t3; - --echo # --echo # MDEV-28367: BACKUP LOCKS on table to be accessible to those --echo # with database LOCK TABLES privileges @@ -260,7 +263,6 @@ disconnect con1; drop database db1; drop user user1@localhost; - --echo # --echo # End of MariaDB 10.4 tests --echo # diff --git a/mysql-test/main/backup_stages.result b/mysql-test/main/backup_stages.result index 4704a4b6bd1..5504c68a989 100644 --- a/mysql-test/main/backup_stages.result +++ b/mysql-test/main/backup_stages.result @@ -1,3 +1,5 @@ +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; #----------------------------------------------------------------------- # Multi-threaded tests #----------------------------------------------------------------------- @@ -17,6 +19,7 @@ FROM information_schema.processlist WHERE id = @con1_id; ID USER COMMAND STATE INFO STAGE MAX_STAGE INFO_BINARY root Query Waiting for backup lock BACKUP STAGE START 0 0 BACKUP STAGE START BACKUP STAGE END; +InnoDB 0 transactions not purged SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME MDL_BACKUP_START Backup lock @@ -333,3 +336,4 @@ disconnect con11; disconnect con12; disconnect backup; connection default; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/main/backup_stages.test b/mysql-test/main/backup_stages.test index e8cc5f7a7b9..11e191e194a 100644 --- a/mysql-test/main/backup_stages.test +++ b/mysql-test/main/backup_stages.test @@ -11,6 +11,8 @@ # Save the initial number of concurrent sessions. --source include/count_sessions.inc +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; let $old_lock_wait_timeout = `SELECT @@global.lock_wait_timeout`; --echo #----------------------------------------------------------------------- @@ -50,6 +52,7 @@ FROM information_schema.processlist WHERE id = @con1_id; # con1 uses @@global.lock_wait_timeout BACKUP STAGE END; +--source ../suite/innodb/include/wait_all_purged.inc SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; --connection con1 @@ -383,3 +386,4 @@ SET GLOBAL lock_wait_timeout = $old_lock_wait_timeout; --connection default --source include/wait_until_count_sessions.inc +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/main/create_or_replace.result b/mysql-test/main/create_or_replace.result index 701b8a8c6d3..45e6231132c 100644 --- a/mysql-test/main/create_or_replace.result +++ b/mysql-test/main/create_or_replace.result @@ -1,4 +1,6 @@ drop table if exists t1,t2,t3; +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TABLE t2 (a int); INSERT INTO t2 VALUES(1),(2),(3); # @@ -260,6 +262,7 @@ Note 1051 Unknown table 'mysqltest2.t2' create table test.t1 (i int) engine=myisam; create table mysqltest2.t2 like test.t1; lock table test.t1 write, mysqltest2.t2 write; +InnoDB 0 transactions not purged select * from information_schema.metadata_lock_info; THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME # MDL_BACKUP_DDL NULL Backup lock @@ -576,6 +579,7 @@ CREATE TABLE tm (a INT) ENGINE=MERGE UNION(t); CREATE OR REPLACE TABLE t LIKE tm; ERROR HY000: Table 'tm' is specified twice, both as a target for 'CREATE' and as a separate source for data DROP TABLE IF EXISTS tm, t; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; # # End of 10.3 tests # diff --git a/mysql-test/main/create_or_replace.test b/mysql-test/main/create_or_replace.test index b4bfcab50db..974ce2b51b9 100644 --- a/mysql-test/main/create_or_replace.test +++ b/mysql-test/main/create_or_replace.test @@ -8,6 +8,8 @@ drop table if exists t1,t2,t3; --enable_warnings +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; # # Create help table # @@ -216,6 +218,7 @@ drop table if exists test.t1,mysqltest2.t2; create table test.t1 (i int) engine=myisam; create table mysqltest2.t2 like test.t1; lock table test.t1 write, mysqltest2.t2 write; +--source ../suite/innodb/include/wait_all_purged.inc --replace_column 1 # --sorted_result select * from information_schema.metadata_lock_info; @@ -523,6 +526,7 @@ CREATE OR REPLACE TABLE t LIKE tm; # Cleanup DROP TABLE IF EXISTS tm, t; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; --echo # --echo # End of 10.3 tests --echo # diff --git a/mysql-test/main/mdl.result b/mysql-test/main/mdl.result index c6fa2c2dbde..3108121e00c 100644 --- a/mysql-test/main/mdl.result +++ b/mysql-test/main/mdl.result @@ -5,8 +5,11 @@ # mdl_ticket->m_type == MDL_SHARED_READ' # failed in MDL_context::upgrade_shared_lock # +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TABLE t1(a INT) ENGINE=InnoDB; CREATE TABLE t3(a INT) ENGINE=myisam; +InnoDB 0 transactions not purged LOCK TABLES t1 WRITE CONCURRENT, t1 AS t2 READ; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME @@ -56,7 +59,7 @@ DROP TABLE t1,t3; # # Check MDL locks taken for different kind of tables by open # -CREATE TABLE t1(a INT) ENGINE=InnoDB; +CREATE TABLE t1(a INT) stats_persistent=0, ENGINE=InnoDB; CREATE TABLE t3(a INT) ENGINE=myisam; connect locker,localhost,root,,; connection default; @@ -64,6 +67,7 @@ FLUSH TABLES WITH READ LOCK; connection locker; insert into t1 values (1); connection default; +InnoDB 0 transactions not purged connection default; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME @@ -77,6 +81,7 @@ FLUSH TABLES WITH READ LOCK; connection locker; insert into t3 values (2); connection default; +InnoDB 0 transactions not purged connection default; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME @@ -129,6 +134,7 @@ disconnect foo; connection default; set autocommit=default; drop table t2; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; # # End of 10.4 tests # diff --git a/mysql-test/main/mdl.test b/mysql-test/main/mdl.test index d55d2c81f9b..00a089e1266 100644 --- a/mysql-test/main/mdl.test +++ b/mysql-test/main/mdl.test @@ -8,9 +8,12 @@ --echo # mdl_ticket->m_type == MDL_SHARED_READ' --echo # failed in MDL_context::upgrade_shared_lock --echo # +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; --disable_service_connection CREATE TABLE t1(a INT) ENGINE=InnoDB; CREATE TABLE t3(a INT) ENGINE=myisam; +--source ../suite/innodb/include/wait_all_purged.inc LOCK TABLES t1 WRITE CONCURRENT, t1 AS t2 READ; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; UNLOCK TABLES; @@ -38,7 +41,7 @@ DROP TABLE t1,t3; --echo # Check MDL locks taken for different kind of tables by open --echo # -CREATE TABLE t1(a INT) ENGINE=InnoDB; +CREATE TABLE t1(a INT) stats_persistent=0, ENGINE=InnoDB; CREATE TABLE t3(a INT) ENGINE=myisam; connect (locker,localhost,root,,); connection default; @@ -52,6 +55,7 @@ let $wait_condition= select count(*) > 0 from information_schema.processlist where state = "Waiting for backup lock"; --source include/wait_condition.inc +--source ../suite/innodb/include/wait_all_purged.inc connection default; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; unlock tables; @@ -69,6 +73,7 @@ let $wait_condition= select count(*) > 0 from information_schema.processlist where state = "Waiting for backup lock"; --source include/wait_condition.inc +--source ../suite/innodb/include/wait_all_purged.inc connection default; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; unlock tables; @@ -121,7 +126,7 @@ connection default; set autocommit=default; drop table t2; --enable_view_protocol - +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/mdl_sync.result b/mysql-test/main/mdl_sync.result index 5203fdddb2d..23b3ba6b6d6 100644 --- a/mysql-test/main/mdl_sync.result +++ b/mysql-test/main/mdl_sync.result @@ -1,4 +1,6 @@ SET DEBUG_SYNC= 'RESET'; +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; connect con1,localhost,root,,test,,; connect con2,localhost,root,,test,,; connect con3,localhost,root,,test,,; @@ -2514,6 +2516,7 @@ connection con2; SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; # Check that FLUSH must wait to get the GRL # and let DROP PROCEDURE continue +InnoDB 0 transactions not purged SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME MDL_BACKUP_DDL Backup lock @@ -2538,7 +2541,7 @@ SET DEBUG_SYNC= 'RESET'; # UPDATE should wait for FTWRL with non transactional table second # create table t1 (a int) engine=myisam; -create table t2 (a int) engine=innodb; +create table t2 (a int) stats_persistent=0, engine=innodb; insert into t1 values (1); insert into t2 values (1); SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait execute 2'; @@ -3124,3 +3127,4 @@ connection default; SET debug_sync='RESET'; DROP TABLE t1; disconnect con1; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/main/mdl_sync.test b/mysql-test/main/mdl_sync.test index 2a1e488ab44..e7ea8c05d54 100644 --- a/mysql-test/main/mdl_sync.test +++ b/mysql-test/main/mdl_sync.test @@ -16,6 +16,8 @@ SET DEBUG_SYNC= 'RESET'; --enable_warnings +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; # # Test the case of when a exclusive lock request waits for a # shared lock being upgraded to a exclusive lock. @@ -3249,6 +3251,7 @@ connection con2; SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; --echo # Check that FLUSH must wait to get the GRL --echo # and let DROP PROCEDURE continue +--source ../suite/innodb/include/wait_all_purged.inc SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL grlwait'; --send FLUSH TABLES WITH READ LOCK @@ -3274,7 +3277,7 @@ SET DEBUG_SYNC= 'RESET'; --echo # create table t1 (a int) engine=myisam; -create table t2 (a int) engine=innodb; +create table t2 (a int) stats_persistent=0, engine=innodb; insert into t1 values (1); insert into t2 values (1); @@ -4175,3 +4178,4 @@ disconnect con1; # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. --source include/wait_until_count_sessions.inc +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; From 968061fd9c7a1c501badb5bc82a9b7c3c44b6f6f Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Mon, 27 Nov 2023 21:03:21 +0300 Subject: [PATCH 357/477] MDEV-28682 gcol.gcol_purge contaminates further execution of innodb.gap_locks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ha_innobase::extra() invokes check_trx_exists() unconditionally even for not supported operations. check_trx_exists() creates and registers trx_t object if THD does not contain pointer to it. If ha_innobase::extra() does not support some operation, it just invokes check_trx_exists() and quites. If check_trx_exists() creates and registers new trx_t object for such operation, it will never be freed and deregistered. For example, if ha_innobase::extra() is invoked from purge thread with operation = HA_EXTRA_IS_ATTACHED_CHILDREN, like it goes in gcol.gcol_purge test, trx_t object will be registered, but not deregisreted, and this causes innodb.gap_lock failure, as "SHOW ENGINE INNODB STATUS" shows information about unexpected transaction at the end of trx_sys.trx_list. The fix is not to invoke check_trx_exists() for unsupported operations in ha_innobase::extra(). Reviewed by: Marko Mäkelä --- storage/innobase/handler/ha_innodb.cc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 58626c4667c..d955b63c817 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -15412,29 +15412,33 @@ ha_innobase::extra( enum ha_extra_function operation) /*!< in: HA_EXTRA_FLUSH or some other flag */ { - check_trx_exists(ha_thd()); - /* Warning: since it is not sure that MySQL calls external_lock before calling this function, the trx field in m_prebuilt can be obsolete! */ + trx_t *trx; switch (operation) { case HA_EXTRA_FLUSH: + (void)check_trx_exists(ha_thd()); if (m_prebuilt->blob_heap) { row_mysql_prebuilt_free_blob_heap(m_prebuilt); } break; case HA_EXTRA_RESET_STATE: + trx = check_trx_exists(ha_thd()); reset_template(); - thd_to_trx(ha_thd())->duplicates = 0; + trx->duplicates = 0; break; case HA_EXTRA_NO_KEYREAD: + (void)check_trx_exists(ha_thd()); m_prebuilt->read_just_key = 0; break; case HA_EXTRA_KEYREAD: + (void)check_trx_exists(ha_thd()); m_prebuilt->read_just_key = 1; break; case HA_EXTRA_KEYREAD_PRESERVE_FIELDS: + (void)check_trx_exists(ha_thd()); m_prebuilt->keep_other_fields_on_keyread = 1; break; @@ -15445,18 +15449,23 @@ ha_innobase::extra( either, because the calling threads may change. CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */ case HA_EXTRA_INSERT_WITH_UPDATE: - thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE; + trx = check_trx_exists(ha_thd()); + trx->duplicates |= TRX_DUP_IGNORE; break; case HA_EXTRA_NO_IGNORE_DUP_KEY: - thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_IGNORE; + trx = check_trx_exists(ha_thd()); + trx->duplicates &= ~TRX_DUP_IGNORE; break; case HA_EXTRA_WRITE_CAN_REPLACE: - thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE; + trx = check_trx_exists(ha_thd()); + trx->duplicates |= TRX_DUP_REPLACE; break; case HA_EXTRA_WRITE_CANNOT_REPLACE: - thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE; + trx = check_trx_exists(ha_thd()); + trx->duplicates &= ~TRX_DUP_REPLACE; break; case HA_EXTRA_BEGIN_ALTER_COPY: + (void)check_trx_exists(ha_thd()); m_prebuilt->table->skip_alter_undo = 1; if (m_prebuilt->table->is_temporary() || !m_prebuilt->table->versioned_by_id()) { @@ -15470,6 +15479,7 @@ ha_innobase::extra( .first->second.set_versioned(0); break; case HA_EXTRA_END_ALTER_COPY: + (void)check_trx_exists(ha_thd()); m_prebuilt->table->skip_alter_undo = 0; break; default:/* Do nothing */ From cd79f102110a3543bc78ef4bec4dbeadaf1f1a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 29 Nov 2023 18:57:57 +0200 Subject: [PATCH 358/477] MDEV-31441 BLOB corruption on UPDATE of PRIMARY KEY with FOREIGN KEY row_upd_clust_rec_by_insert(): If we are resuming from a lock wait, reset the 'disowned' flag of the BLOB pointers in 'entry' that we copied from 'rec' on which we had invoked btr_cur_disown_inherited_fields() before the lock wait started. In this way, the inserted record with the updated PRIMARY KEY value will have the BLOB ownership associated with itself, like it is supposed to be. Note: If the lock wait had been aborted, then rollback would have invoked btr_cur_unmark_extern_fields() and no corruption would be possible. Reviewed by: Vladislav Lesin Tested by: Matthias Leich --- mysql-test/suite/innodb/r/foreign_key.result | 27 ++++++++++++++-- mysql-test/suite/innodb/t/foreign_key.test | 34 ++++++++++++++++++-- storage/innobase/row/row0upd.cc | 25 +++++++++++++- 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index f87aeb56b77..769af9cc220 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -727,7 +727,9 @@ pk a b 13 0 1 14 0 1 15 1 0 -disconnect con1; +connection con1; +COMMIT; +connection default; InnoDB 0 transactions not purged CHECK TABLE t1; Table Op Msg_type Msg_text @@ -906,5 +908,26 @@ 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 +# MDEV-31441 BLOB corruption on UPDATE of PRIMARY KEY with FOREIGN KEY # +CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT) ENGINE=InnoDB; +CREATE TABLE t2 (pk INT PRIMARY KEY, FOREIGN KEY (pk) REFERENCES t1(pk)) +ENGINE=InnoDB; +SET @blob = REPEAT('A', @@innodb_page_size / 2); +INSERT INTO t1 SET pk=1, t=@blob; +INSERT INTO t2 SET pk=1; +connection con1; +BEGIN; +DELETE FROM t2; +connection default; +UPDATE t1 SET pk=12; +connection con1; +COMMIT; +disconnect con1; +connection default; +UPDATE t1 SET pk=1; +SELECT pk,t=@blob FROM t1; +pk t=@blob +1 1 +DROP TABLE t2, t1; +# 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 032bab2408d..9de72eb4681 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -732,7 +732,9 @@ SELECT a FROM t1 FORCE INDEX(a); # the "goto rollback_to_savept" in row_mysql_handle_errors() is reverted. SELECT * FROM t1; # Allow purge to continue by closing the read view. -disconnect con1; +connection con1; +COMMIT; +connection default; # Wait for purge. With the fix reverted, the server would crash here. --source include/wait_all_purged.inc @@ -954,7 +956,35 @@ ALTER TABLE t1 MODIFY id INT unsigned AUTO_INCREMENT; DROP TABLE t1,t2; --echo # ---echo # End of 10.4 tests +--echo # MDEV-31441 BLOB corruption on UPDATE of PRIMARY KEY with FOREIGN KEY --echo # +CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT) ENGINE=InnoDB; +CREATE TABLE t2 (pk INT PRIMARY KEY, FOREIGN KEY (pk) REFERENCES t1(pk)) +ENGINE=InnoDB; + +SET @blob = REPEAT('A', @@innodb_page_size / 2); +INSERT INTO t1 SET pk=1, t=@blob; +INSERT INTO t2 SET pk=1; +--connection con1 +BEGIN; +DELETE FROM t2; +--connection default +# The following will be blocked by a FOREIGN KEY check on pk=1 in t2. +--send +UPDATE t1 SET pk=12; +--connection con1 +let $wait_condition= +SELECT count(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE state='Updating'; +--source include/wait_condition.inc +COMMIT; +--disconnect con1 +--connection default +--reap +UPDATE t1 SET pk=1; +SELECT pk,t=@blob FROM t1; +DROP TABLE t2, t1; + +--echo # End of 10.4 tests + --source include/wait_until_count_sessions.inc diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 0700792e441..58c93e4db0f 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2698,6 +2698,25 @@ row_upd_clust_rec_by_insert_inherit_func( return(inherit); } +/** Mark 'disowned' BLOBs as 'owned' and 'inherited' again, +after resuming from a lock wait. +@param entry clustered index entry */ +static ATTRIBUTE_COLD void row_upd_reown_inherited_fields(dtuple_t *entry) +{ + for (ulint i= 0; i < entry->n_fields; i++) + { + const dfield_t *dfield= dtuple_get_nth_field(entry, i); + if (dfield_is_ext(dfield)) + { + byte *blob_len= static_cast(dfield->data) + + dfield->len - (BTR_EXTERN_FIELD_REF_SIZE - BTR_EXTERN_LEN); + ut_ad(*blob_len & BTR_EXTERN_OWNER_FLAG); + *blob_len= byte(*blob_len & ~BTR_EXTERN_OWNER_FLAG) | + BTR_EXTERN_INHERITED_FLAG; + } + } +} + /***********************************************************//** Marks the clustered index record deleted and inserts the updated version of the record to the index. This function should be used when the ordering @@ -2776,12 +2795,16 @@ row_upd_clust_rec_by_insert( /* If the clustered index record is already delete marked, then we are here after a DB_LOCK_WAIT. Skip delete marking clustered index and disowning - its blobs. */ + its blobs. Mark the BLOBs in the index entry + (which we copied from the already "disowned" rec) + as "owned", like it was on the previous call of + row_upd_clust_rec_by_insert(). */ ut_ad(row_get_rec_trx_id(rec, index, offsets) == trx->id); ut_ad(!trx_undo_roll_ptr_is_insert( row_get_rec_roll_ptr(rec, index, offsets))); + row_upd_reown_inherited_fields(entry); goto check_fk; } From 2fe3e033e69f9a8274047092e985ad636c316564 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 30 Nov 2023 14:14:10 +1100 Subject: [PATCH 359/477] main.subselect* often fails on CI with ER_SUBQUERY_NO_1_ROW Using mysql.slow_log was a test table would generate more than one row if there was more than one row in the table. Replace this table with a empty table with PK. Reviewer: Rex Johnston --- mysql-test/main/subselect.result | 13 ++++++++----- mysql-test/main/subselect.test | 13 ++++++++----- mysql-test/main/subselect_no_exists_to_in.result | 13 ++++++++----- mysql-test/main/subselect_no_mat.result | 13 ++++++++----- mysql-test/main/subselect_no_opts.result | 13 ++++++++----- mysql-test/main/subselect_no_scache.result | 13 ++++++++----- mysql-test/main/subselect_no_semijoin.result | 13 ++++++++----- 7 files changed, 56 insertions(+), 35 deletions(-) diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result index cb0273542af..c33350d5bc1 100644 --- a/mysql-test/main/subselect.result +++ b/mysql-test/main/subselect.result @@ -7163,24 +7163,26 @@ drop table t1; # # MDEV-7565: Server crash with Signal 6 (part 2) # -truncate table mysql.slow_log; +create table t1 (id int not null primary key); Select -(Select Sum(`TestCase`.Revenue) From mysql.slow_log E -Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) +(Select Sum(`TestCase`.Revenue) From t1 E +Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` Group By TestCase.Revenue, TestCase.TemplateID; ControlRev NULL +drop table t1; # # MDEV-7445:Server crash with Signal 6 # +create table t1 (id int not null primary key); CREATE PROCEDURE procedure2() BEGIN Select -(Select Sum(`TestCase`.Revenue) From mysql.slow_log E -Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) +(Select Sum(`TestCase`.Revenue) From t1 E +Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` @@ -7193,6 +7195,7 @@ call procedure2(); ControlRev NULL drop procedure procedure2; +drop table t1; # # MDEV-7846:Server crashes in Item_subselect::fix #_fields or fails with Thread stack overrun diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test index 1b74651adb6..cd9e80e080b 100644 --- a/mysql-test/main/subselect.test +++ b/mysql-test/main/subselect.test @@ -5995,25 +5995,27 @@ drop table t1; --echo # MDEV-7565: Server crash with Signal 6 (part 2) --echo # -truncate table mysql.slow_log; +create table t1 (id int not null primary key); Select - (Select Sum(`TestCase`.Revenue) From mysql.slow_log E - Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) + (Select Sum(`TestCase`.Revenue) From t1 E + Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` Group By TestCase.Revenue, TestCase.TemplateID; +drop table t1; --echo # --echo # MDEV-7445:Server crash with Signal 6 --echo # +create table t1 (id int not null primary key); --delimiter | CREATE PROCEDURE procedure2() BEGIN Select - (Select Sum(`TestCase`.Revenue) From mysql.slow_log E - Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) + (Select Sum(`TestCase`.Revenue) From t1 E + Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` @@ -6025,6 +6027,7 @@ call procedure2(); call procedure2(); drop procedure procedure2; +drop table t1; --echo # diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result index 431fdbfb04c..c36e02fb6a0 100644 --- a/mysql-test/main/subselect_no_exists_to_in.result +++ b/mysql-test/main/subselect_no_exists_to_in.result @@ -7163,24 +7163,26 @@ drop table t1; # # MDEV-7565: Server crash with Signal 6 (part 2) # -truncate table mysql.slow_log; +create table t1 (id int not null primary key); Select -(Select Sum(`TestCase`.Revenue) From mysql.slow_log E -Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) +(Select Sum(`TestCase`.Revenue) From t1 E +Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` Group By TestCase.Revenue, TestCase.TemplateID; ControlRev NULL +drop table t1; # # MDEV-7445:Server crash with Signal 6 # +create table t1 (id int not null primary key); CREATE PROCEDURE procedure2() BEGIN Select -(Select Sum(`TestCase`.Revenue) From mysql.slow_log E -Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) +(Select Sum(`TestCase`.Revenue) From t1 E +Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` @@ -7193,6 +7195,7 @@ call procedure2(); ControlRev NULL drop procedure procedure2; +drop table t1; # # MDEV-7846:Server crashes in Item_subselect::fix #_fields or fails with Thread stack overrun diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result index 7e83755ffdf..778b097de75 100644 --- a/mysql-test/main/subselect_no_mat.result +++ b/mysql-test/main/subselect_no_mat.result @@ -7156,24 +7156,26 @@ drop table t1; # # MDEV-7565: Server crash with Signal 6 (part 2) # -truncate table mysql.slow_log; +create table t1 (id int not null primary key); Select -(Select Sum(`TestCase`.Revenue) From mysql.slow_log E -Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) +(Select Sum(`TestCase`.Revenue) From t1 E +Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` Group By TestCase.Revenue, TestCase.TemplateID; ControlRev NULL +drop table t1; # # MDEV-7445:Server crash with Signal 6 # +create table t1 (id int not null primary key); CREATE PROCEDURE procedure2() BEGIN Select -(Select Sum(`TestCase`.Revenue) From mysql.slow_log E -Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) +(Select Sum(`TestCase`.Revenue) From t1 E +Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` @@ -7186,6 +7188,7 @@ call procedure2(); ControlRev NULL drop procedure procedure2; +drop table t1; # # MDEV-7846:Server crashes in Item_subselect::fix #_fields or fails with Thread stack overrun diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result index 9de07ccbf9e..fe43e93fa0e 100644 --- a/mysql-test/main/subselect_no_opts.result +++ b/mysql-test/main/subselect_no_opts.result @@ -7154,24 +7154,26 @@ drop table t1; # # MDEV-7565: Server crash with Signal 6 (part 2) # -truncate table mysql.slow_log; +create table t1 (id int not null primary key); Select -(Select Sum(`TestCase`.Revenue) From mysql.slow_log E -Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) +(Select Sum(`TestCase`.Revenue) From t1 E +Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` Group By TestCase.Revenue, TestCase.TemplateID; ControlRev NULL +drop table t1; # # MDEV-7445:Server crash with Signal 6 # +create table t1 (id int not null primary key); CREATE PROCEDURE procedure2() BEGIN Select -(Select Sum(`TestCase`.Revenue) From mysql.slow_log E -Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) +(Select Sum(`TestCase`.Revenue) From t1 E +Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` @@ -7184,6 +7186,7 @@ call procedure2(); ControlRev NULL drop procedure procedure2; +drop table t1; # # MDEV-7846:Server crashes in Item_subselect::fix #_fields or fails with Thread stack overrun diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result index 74cd5422327..968627607bd 100644 --- a/mysql-test/main/subselect_no_scache.result +++ b/mysql-test/main/subselect_no_scache.result @@ -7169,24 +7169,26 @@ drop table t1; # # MDEV-7565: Server crash with Signal 6 (part 2) # -truncate table mysql.slow_log; +create table t1 (id int not null primary key); Select -(Select Sum(`TestCase`.Revenue) From mysql.slow_log E -Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) +(Select Sum(`TestCase`.Revenue) From t1 E +Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` Group By TestCase.Revenue, TestCase.TemplateID; ControlRev NULL +drop table t1; # # MDEV-7445:Server crash with Signal 6 # +create table t1 (id int not null primary key); CREATE PROCEDURE procedure2() BEGIN Select -(Select Sum(`TestCase`.Revenue) From mysql.slow_log E -Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) +(Select Sum(`TestCase`.Revenue) From t1 E +Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` @@ -7199,6 +7201,7 @@ call procedure2(); ControlRev NULL drop procedure procedure2; +drop table t1; # # MDEV-7846:Server crashes in Item_subselect::fix #_fields or fails with Thread stack overrun diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result index b8713a4c06b..3e4b5072623 100644 --- a/mysql-test/main/subselect_no_semijoin.result +++ b/mysql-test/main/subselect_no_semijoin.result @@ -7154,24 +7154,26 @@ drop table t1; # # MDEV-7565: Server crash with Signal 6 (part 2) # -truncate table mysql.slow_log; +create table t1 (id int not null primary key); Select -(Select Sum(`TestCase`.Revenue) From mysql.slow_log E -Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) +(Select Sum(`TestCase`.Revenue) From t1 E +Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` Group By TestCase.Revenue, TestCase.TemplateID; ControlRev NULL +drop table t1; # # MDEV-7445:Server crash with Signal 6 # +create table t1 (id int not null primary key); CREATE PROCEDURE procedure2() BEGIN Select -(Select Sum(`TestCase`.Revenue) From mysql.slow_log E -Where TestCase.TemplateID not in (Select 1 from mysql.slow_log where 2=2) +(Select Sum(`TestCase`.Revenue) From t1 E +Where TestCase.TemplateID not in (Select 1 from t1 where 2=2) ) As `ControlRev` From (Select 3 as Revenue, 4 as TemplateID) As `TestCase` @@ -7184,6 +7186,7 @@ call procedure2(); ControlRev NULL drop procedure procedure2; +drop table t1; # # MDEV-7846:Server crashes in Item_subselect::fix #_fields or fails with Thread stack overrun From 89a5a8d234832ef9ed5ee814e4db42c636fcde1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 30 Nov 2023 09:43:36 +0200 Subject: [PATCH 360/477] =?UTF-8?q?MDEV-32269=20InnoDB=20after=20ALTER=20T?= =?UTF-8?q?ABLE=E2=80=A6IMPORT=20TABLESPACE=20may=20not=20be=20crash=20saf?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mtr_t::commit(): If IMPORT TABLESPACE is first-time-dirtying blocks, acquire both log_sys.mutex and log_sys.flush_order_mutex to assign a valid m_commit_lsn so that the block will be inserted into the correct position of buf_pool.flush_list. This fixes occasional debug assertion failures when running the regression test suite. Reviewed by: Vladislav Lesin --- storage/innobase/mtr/mtr0mtr.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index b138dd13073..dd9036f9e08 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -453,10 +453,16 @@ void mtr_t::commit() { ut_ad(m_log_mode == MTR_LOG_NO_REDO); ut_ad(m_log.size() == 0); - m_commit_lsn= log_sys.get_lsn(); - lsns= { m_commit_lsn, PAGE_FLUSH_NO }; if (UNIV_UNLIKELY(m_made_dirty)) /* This should be IMPORT TABLESPACE */ + { + mysql_mutex_lock(&log_sys.mutex); + m_commit_lsn= log_sys.get_lsn(); mysql_mutex_lock(&log_sys.flush_order_mutex); + mysql_mutex_unlock(&log_sys.mutex); + } + else + m_commit_lsn= log_sys.get_lsn(); + lsns= { m_commit_lsn, PAGE_FLUSH_NO }; } if (m_freed_pages) From 0ee9b119bf336a89b5667d43ce4edc8997394870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 30 Nov 2023 09:46:25 +0200 Subject: [PATCH 361/477] MDEV-31817 SIGSEGV after btr_page_get_father_block() returns nullptr on corrupted data btr_attach_half_pages(), btr_lift_page_up(), btr_compress(): Return DB_CORRUPTION if btr_page_get_father_block() returns nullptr Reviewed by: Thirunarayanan Balathandayuthapani --- storage/innobase/btr/btr0btr.cc | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index ee2f8d00857..1e4e15a5433 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -873,7 +873,8 @@ static rec_offs *btr_page_get_parent(rec_offs *offsets, mem_heap_t *heap, /************************************************************//** Returns the upper level node pointer to a page. It is assumed that mtr holds an x-latch on the tree. -@return rec_get_offsets() of the node pointer record */ +@return rec_get_offsets() of the node pointer record +@retval nullptr on corruption */ static rec_offs* btr_page_get_father_block( @@ -2541,6 +2542,11 @@ btr_attach_half_pages( offsets = btr_page_get_father_block(nullptr, heap, mtr, &cursor); + if (UNIV_UNLIKELY(!offsets)) { + mem_heap_free(heap); + return DB_CORRUPTION; + } + /* Replace the address of the old child node (= page) with the address of the new lower half */ @@ -3476,6 +3482,14 @@ btr_lift_page_up( offsets = btr_page_get_father_block(offsets, heap, mtr, &cursor); } + + if (UNIV_UNLIKELY(!offsets)) { +parent_corrupted: + mem_heap_free(heap); + *err = DB_CORRUPTION; + return nullptr; + } + father_block = btr_cur_get_block(&cursor); father_page_zip = buf_block_get_page_zip(father_block); @@ -3500,6 +3514,10 @@ btr_lift_page_up( &cursor); } + if (UNIV_UNLIKELY(!offsets)) { + goto parent_corrupted; + } + blocks[n_blocks++] = b = btr_cur_get_block(&cursor); } @@ -3715,6 +3733,11 @@ btr_compress( NULL, heap, mtr, &father_cursor); } + if (UNIV_UNLIKELY(!offsets)) { + err = DB_CORRUPTION; + goto func_exit; + } + if (adjust) { nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor)); if (UNIV_UNLIKELY(!nth_rec || nth_rec == ULINT_UNDEFINED)) { From bb511def1d316ffbdd815f2fc99d0a5813671814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 30 Nov 2023 10:35:53 +0200 Subject: [PATCH 362/477] MDEV-32371 Deadlock between buf_page_get_zip() and buf_pool_t::corrupted_evict() buf_page_get_zip(): Do not wait for the page latch while holding hash_lock. If the latch is not available, ensure that any concurrent buf_pool_t::corrupted_evict() will be able to acquire the hash_lock, and then retry the lookup. If the page was corrupted, we will finally "goto must_read_page", retry the read once more, and then report an error. Reviewed by: Thirunarayanan Balathandayuthapani --- storage/innobase/buf/buf0buf.cc | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 12a27f92d07..77b27d9b1ba 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2235,14 +2235,21 @@ lookup: if (discard_attempted || !bpage->frame) { - /* Even when we are holding a hash_lock, it should be - acceptable to wait for a page S-latch here, because - buf_page_t::read_complete() will not wait for buf_pool.mutex, - and because S-latch would not conflict with a U-latch - that would be protecting buf_page_t::write_complete(). */ - bpage->lock.s_lock(); + const bool got_s_latch= bpage->lock.s_lock_try(); hash_lock.unlock_shared(); - break; + if (UNIV_LIKELY(got_s_latch)) + break; + /* We may fail to acquire bpage->lock because + buf_page_t::read_complete() may be invoking + buf_pool_t::corrupted_evict() on this block, which it would + hold an exclusive latch on. + + Let us aqcuire and release buf_pool.mutex to ensure that any + buf_pool_t::corrupted_evict() will proceed before we reacquire + the hash_lock that it could be waiting for. */ + mysql_mutex_lock(&buf_pool.mutex); + mysql_mutex_unlock(&buf_pool.mutex); + goto lookup; } hash_lock.unlock_shared(); From 9d07b0520c65d8088a522e3d8b1292ad723dba15 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 6 Oct 2023 22:36:32 +0200 Subject: [PATCH 363/477] MDEV-31608 - Connector/NET fails to connect since 10.10 Connector/NET does not expect collation IDs returned by "show collations" to be NULL, runs into an exception. The fix is to determine connector/net using its connection attributes, then make sure "show collations" does not output NULL IDs. The patch introduces new old_mode NO_NULL_COLLATION_IDs, that is automatically set, once MySQL Connector/NET connection is determined. A test was added, that uses MySql.Data from powershell - only works if MySql.Data is installed into GAC (i.e with C/NET MSI package) --- mysql-test/main/mysql_connector_net.ps1 | 58 +++++++++++++++++++ mysql-test/main/mysql_connector_net.result | 2 + mysql-test/main/mysql_connector_net.test | 11 ++++ mysql-test/main/mysqld--help,win.rdiff | 20 ++++--- mysql-test/main/mysqld--help.result | 3 +- mysql-test/main/old-mode.result | 10 ++++ mysql-test/main/old-mode.test | 8 +++ .../suite/sys_vars/r/old_mode_basic.result | 4 +- .../sys_vars/r/sysvars_server_embedded.result | 2 +- .../r/sysvars_server_notembedded.result | 2 +- .../suite/sys_vars/t/old_mode_basic.test | 2 +- sql/sql_acl.cc | 41 +++++++++++-- sql/sql_class.h | 1 + sql/sql_show.cc | 3 +- sql/sys_vars.cc | 1 + 15 files changed, 148 insertions(+), 20 deletions(-) create mode 100644 mysql-test/main/mysql_connector_net.ps1 create mode 100644 mysql-test/main/mysql_connector_net.result create mode 100644 mysql-test/main/mysql_connector_net.test diff --git a/mysql-test/main/mysql_connector_net.ps1 b/mysql-test/main/mysql_connector_net.ps1 new file mode 100644 index 00000000000..159acf9361c --- /dev/null +++ b/mysql-test/main/mysql_connector_net.ps1 @@ -0,0 +1,58 @@ +$assembly = [system.reflection.Assembly]::LoadWithPartialName("MySql.Data") +if ($assembly -eq $null) +{ + "Can't load assembly MySql.Data" + exit 100 +} + +try +{ + $connectionString =[string]::Format("server=127.0.0.1;uid=root;port={0};Connection Reset=true;",$Env:MASTER_MYPORT) + $connection = [MySql.Data.MySqlClient.MySqlConnection]@{ConnectionString=$connectionString} + $connection.Open() + + # Test ExecuteReader() + $command = New-Object MySql.Data.MySqlClient.MySqlCommand + $command.Connection = $connection + $command.CommandText = "SELECT @@old_mode" + $reader = $command.ExecuteReader() + $reader.GetName(0) + while ($reader.Read()) + { + $reader.GetValue(0) + } + + # Test connection reset + $connection.Close() + $connection.Open() + # Test ExecuteNonQuery() + $command.CommandText="do 1"; + $affected_rows = $command.ExecuteNonQuery() + if ($affected_rows -ne 0) + { + "Expected affected rows 0, actual $affected_rows" + exit 1 + } + # Test Prepared Statement + $command.CommandText = "SELECT @var"; + [void]$command.Parameters.AddWithValue("@var", 1); + $command.Prepare(); + $out = $command.ExecuteScalar(); + if ($out -ne 1) + { + "Expected output 1, actual $out" + exit 1 + } + $connection.Close() +} +catch +{ + # Dump exception + $_ + $inner = $PSItem.Exception.InnerException + if ($inner -ne $null) + { + $PSItem.Exception.InnerException.Message + $PSItem.Exception.InnerException.StackTrace + } +} diff --git a/mysql-test/main/mysql_connector_net.result b/mysql-test/main/mysql_connector_net.result new file mode 100644 index 00000000000..f2fa39df3e7 --- /dev/null +++ b/mysql-test/main/mysql_connector_net.result @@ -0,0 +1,2 @@ +@@old_mode +UTF8_IS_UTF8MB3,NO_NULL_COLLATION_IDS diff --git a/mysql-test/main/mysql_connector_net.test b/mysql-test/main/mysql_connector_net.test new file mode 100644 index 00000000000..c1dce65adc8 --- /dev/null +++ b/mysql-test/main/mysql_connector_net.test @@ -0,0 +1,11 @@ +--source include/windows.inc +let $sys_errno=0; + +# Error 100 is returned by the powershell script +# if MySql.Data is not installed +--error 0,100 +--exec powershell -NoLogo -NoProfile -File main\mysql_connector_net.ps1 +if ($sys_errno != 0) +{ + --skip Connector/NET is not installed +} diff --git a/mysql-test/main/mysqld--help,win.rdiff b/mysql-test/main/mysqld--help,win.rdiff index 3e9541d7d2f..a42c0c6f81f 100644 --- a/mysql-test/main/mysqld--help,win.rdiff +++ b/mysql-test/main/mysqld--help,win.rdiff @@ -1,4 +1,6 @@ -@@ -180,6 +180,7 @@ +--- main/mysqld--help.result 2023-11-30 02:21:51.951132200 +0100 ++++ main/mysqld--help,win.reject 2023-11-30 02:35:44.404612300 +0100 +@@ -191,6 +191,7 @@ --console Write error output on screen; don't remove the console window on windows. --core-file Write core on crashes @@ -6,7 +8,7 @@ -h, --datadir=name Path to the database root directory --date-format=name The DATE format (ignored) --datetime-format=name -@@ -650,6 +651,7 @@ +@@ -696,6 +697,7 @@ Use MySQL-5.6 (instead of MariaDB-5.3) format for TIME, DATETIME, TIMESTAMP columns. (Defaults to on; use --skip-mysql56-temporal-format to disable.) @@ -14,7 +16,7 @@ --net-buffer-length=# Buffer length for TCP/IP and socket communication --net-read-timeout=# -@@ -1327,6 +1328,10 @@ +@@ -1351,6 +1353,10 @@ Alias for log_slow_query_file. Log slow queries to given log file. Defaults logging to 'hostname'-slow.log. Must be enabled to activate other slow log options @@ -25,7 +27,7 @@ --socket=name Socket file to use for connection --sort-buffer-size=# Each thread that needs to do a sort allocates a buffer of -@@ -1351,6 +1356,7 @@ +@@ -1376,6 +1382,7 @@ deleting or updating every row in a table. --stack-trace Print a symbolic stack trace on failure (Defaults to on; use --skip-stack-trace to disable.) @@ -33,7 +35,7 @@ --standard-compliant-cte Allow only CTEs compliant to SQL standard (Defaults to on; use --skip-standard-compliant-cte to disable.) -@@ -1426,6 +1432,11 @@ +@@ -1454,6 +1461,11 @@ --thread-pool-max-threads=# Maximum allowed number of worker threads in the thread pool @@ -45,7 +47,7 @@ --thread-pool-oversubscribe=# How many additional active worker threads in a group are allowed. -@@ -1464,8 +1475,8 @@ +@@ -1493,8 +1505,8 @@ automatically convert it to an on-disk MyISAM or Aria table. -t, --tmpdir=name Path for temporary files. Several paths may be specified, @@ -56,7 +58,7 @@ --transaction-alloc-block-size=# Allocation block size for transactions to be stored in binary log -@@ -1685,6 +1696,7 @@ +@@ -1716,6 +1728,7 @@ myisam-stats-method NULLS_UNEQUAL myisam-use-mmap FALSE mysql56-temporal-format TRUE @@ -64,7 +66,7 @@ net-buffer-length 16384 net-read-timeout 30 net-retry-count 10 -@@ -1841,6 +1853,7 @@ +@@ -1874,6 +1887,7 @@ slave-type-conversions slow-launch-time 2 slow-query-log FALSE @@ -72,7 +74,7 @@ sort-buffer-size 2097152 sql-mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION sql-safe-updates FALSE -@@ -1867,6 +1880,8 @@ +@@ -1901,6 +1915,8 @@ thread-pool-exact-stats FALSE thread-pool-idle-timeout 60 thread-pool-max-threads 65536 diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index d271f1a308d..867d5cd3c57 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -721,7 +721,8 @@ The following specify which files/extra groups are read (specified before remain MySQL versions. Any combination of: NO_DUP_KEY_WARNINGS_WITH_IGNORE, NO_PROGRESS_INFO, ZERO_DATE_TIME_CAST, UTF8_IS_UTF8MB3, - IGNORE_INDEX_ONLY_FOR_JOIN, COMPAT_5_1_CHECKSUM + IGNORE_INDEX_ONLY_FOR_JOIN, COMPAT_5_1_CHECKSUM, + NO_NULL_COLLATION_IDS Use 'ALL' to set all combinations. --old-passwords Use old password encryption method (needed for 4.0 and older clients) diff --git a/mysql-test/main/old-mode.result b/mysql-test/main/old-mode.result index daa2a4dc915..cb87c45ada8 100644 --- a/mysql-test/main/old-mode.result +++ b/mysql-test/main/old-mode.result @@ -257,3 +257,13 @@ Warning 1264 Out of range value for column 'a' at row 2 DROP TABLE t1; SET @@time_zone=DEFAULT; SET TIMESTAMP=DEFAULT; +# +# MDEV-31608 - Connector/NET fails to connect since 10.10 +# +select count(*) > 0 from information_schema.collations where id IS NULL; +count(*) > 0 +1 +SET old_mode=no_null_collation_ids; +select count(*) > 0 from information_schema.collations where id IS NULL; +count(*) > 0 +0 diff --git a/mysql-test/main/old-mode.test b/mysql-test/main/old-mode.test index e4928329b47..177e00edce8 100644 --- a/mysql-test/main/old-mode.test +++ b/mysql-test/main/old-mode.test @@ -169,3 +169,11 @@ DROP TABLE t1; SET @@time_zone=DEFAULT; SET TIMESTAMP=DEFAULT; + +--echo # +--echo # MDEV-31608 - Connector/NET fails to connect since 10.10 +--echo # +select count(*) > 0 from information_schema.collations where id IS NULL; +SET old_mode=no_null_collation_ids; +select count(*) > 0 from information_schema.collations where id IS NULL; + diff --git a/mysql-test/suite/sys_vars/r/old_mode_basic.result b/mysql-test/suite/sys_vars/r/old_mode_basic.result index 252316dc1cb..776d45a1fe3 100644 --- a/mysql-test/suite/sys_vars/r/old_mode_basic.result +++ b/mysql-test/suite/sys_vars/r/old_mode_basic.result @@ -114,8 +114,8 @@ SET @@global.old_mode = 4; SELECT @@global.old_mode; @@global.old_mode ZERO_DATE_TIME_CAST -SET @@global.old_mode = 64; -ERROR 42000: Variable 'old_mode' can't be set to the value of '64' +SET @@global.old_mode = 128; +ERROR 42000: Variable 'old_mode' can't be set to the value of '128' SELECT @@global.old_mode; @@global.old_mode ZERO_DATE_TIME_CAST 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 48eb32e9698..ac8752ac82e 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -2299,7 +2299,7 @@ VARIABLE_COMMENT Used to emulate old behavior from earlier MariaDB or MySQL vers NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM +ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM,NO_NULL_COLLATION_IDS READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OLD_PASSWORDS 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 6cb556308a8..1f600a8a718 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -2469,7 +2469,7 @@ VARIABLE_COMMENT Used to emulate old behavior from earlier MariaDB or MySQL vers NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM +ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM,NO_NULL_COLLATION_IDS READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OLD_PASSWORDS diff --git a/mysql-test/suite/sys_vars/t/old_mode_basic.test b/mysql-test/suite/sys_vars/t/old_mode_basic.test index 631d638767f..cb18796729e 100644 --- a/mysql-test/suite/sys_vars/t/old_mode_basic.test +++ b/mysql-test/suite/sys_vars/t/old_mode_basic.test @@ -172,7 +172,7 @@ SET @@global.old_mode = 4; SELECT @@global.old_mode; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.old_mode = 64; +SET @@global.old_mode = 128; SELECT @@global.old_mode; # use of decimal values diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 6b6e1c30da1..ebd2949a64e 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -13576,8 +13576,37 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio) DBUG_RETURN(0); } + +/** + Determine if the client is MySQL Connector/NET. + + Checks whether the given connection attributes blob corresponds to + MySQL Connector/NET by examining the "_client_name" attribute, which is + expected to be the first attribute in the blob. + + @param connection_attrs - The connection attributes blob. + @param length - The length of the blob. + + @return true if the client is MySQL Connector/NET, false otherwise. +*/ +static inline bool is_connector_net_client(const char *connection_attrs, + size_t length) +{ + constexpr LEX_CSTRING prefix= + {STRING_WITH_LEN("\x0c_client_name\x13mysql-connector-net")}; + + if (length < prefix.length) + return false; + + /* Optimization to avoid following memcmp in common cases.*/ + if (connection_attrs[prefix.length - 1] != prefix.str[prefix.length - 1]) + return false; + + return !memcmp(connection_attrs, prefix.str, prefix.length); +} + static bool -read_client_connect_attrs(char **ptr, char *end, CHARSET_INFO *from_cs) +read_client_connect_attrs(char **ptr, char *end, THD* thd) { ulonglong length; char *ptr_save= *ptr; @@ -13600,10 +13629,14 @@ read_client_connect_attrs(char **ptr, char *end, CHARSET_INFO *from_cs) if (length > 65535) return true; - if (PSI_CALL_set_thread_connect_attrs(*ptr, (uint)length, from_cs) && + if (PSI_CALL_set_thread_connect_attrs(*ptr, (uint)length, thd->charset()) && current_thd->variables.log_warnings) sql_print_warning("Connection attributes of length %llu were truncated", length); + + /* Connector/Net crashes, when "show collations" returns NULL IDs*/ + if (is_connector_net_client(*ptr, length)) + thd->variables.old_behavior |= OLD_MODE_NO_NULL_COLLATION_IDS; return false; } @@ -13737,7 +13770,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) } if ((thd->client_capabilities & CLIENT_CONNECT_ATTRS) && - read_client_connect_attrs(&next_field, end, thd->charset())) + read_client_connect_attrs(&next_field, end, thd)) { my_message(ER_UNKNOWN_COM_ERROR, ER_THD(thd, ER_UNKNOWN_COM_ERROR), MYF(0)); @@ -13987,7 +14020,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, if ((thd->client_capabilities & CLIENT_CONNECT_ATTRS) && read_client_connect_attrs(&next_field, ((char *)net->read_pos) + pkt_len, - mpvio->auth_info.thd->charset())) + mpvio->auth_info.thd)) return packet_error; /* diff --git a/sql/sql_class.h b/sql/sql_class.h index beb33d8394e..b53de8d55c0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -201,6 +201,7 @@ enum enum_binlog_row_image { #define OLD_MODE_UTF8_IS_UTF8MB3 (1 << 3) #define OLD_MODE_IGNORE_INDEX_ONLY_FOR_JOIN (1 << 4) #define OLD_MODE_COMPAT_5_1_CHECKSUM (1 << 5) +#define OLD_MODE_NO_NULL_COLLATION_IDS (1 << 6) extern char internal_table_name[2]; extern char empty_c_string[1]; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 32b29468c32..c21043aaba2 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -6398,7 +6398,8 @@ int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond) tmp_cl->get_collation_name(MY_COLLATION_NAME_MODE_CONTEXT); LEX_CSTRING full_collation_name= tmp_cl->get_collation_name(MY_COLLATION_NAME_MODE_FULL); - bool is_context= cmp(context_collation_name, full_collation_name); + bool is_context= cmp(context_collation_name, full_collation_name) && + !(thd->variables.old_behavior & OLD_MODE_NO_NULL_COLLATION_IDS); /* Some collations are applicable to multiple character sets. Display them only once, with the short name (without the diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 0319298a9d7..23f1ca3a259 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3886,6 +3886,7 @@ static const char *old_mode_names[]= "UTF8_IS_UTF8MB3", "IGNORE_INDEX_ONLY_FOR_JOIN", "COMPAT_5_1_CHECKSUM", + "NO_NULL_COLLATION_IDS", 0 }; From 5f89045221717533994da01fc270d4851ccdc06c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 30 Nov 2023 13:56:26 +0100 Subject: [PATCH 364/477] MDEV-22230 fix failing test followup for 5bb31bc88273 --- storage/tokudb/mysql-test/tokudb/r/type_ranges.result | 2 +- storage/tokudb/mysql-test/tokudb/t/type_ranges.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/tokudb/mysql-test/tokudb/r/type_ranges.result b/storage/tokudb/mysql-test/tokudb/r/type_ranges.result index 38252e870df..cbe1eb6eebe 100644 --- a/storage/tokudb/mysql-test/tokudb/r/type_ranges.result +++ b/storage/tokudb/mysql-test/tokudb/r/type_ranges.result @@ -145,7 +145,7 @@ alter short drop default, DROP INDEX utiny, DROP INDEX ushort, DROP PRIMARY KEY, -DROP FOREIGN KEY any_name, +DROP KEY any_name, ADD INDEX (auto); LOCK TABLES t1 WRITE; ALTER TABLE t1 diff --git a/storage/tokudb/mysql-test/tokudb/t/type_ranges.test b/storage/tokudb/mysql-test/tokudb/t/type_ranges.test index 06a78900d57..99064fc1d38 100644 --- a/storage/tokudb/mysql-test/tokudb/t/type_ranges.test +++ b/storage/tokudb/mysql-test/tokudb/t/type_ranges.test @@ -79,7 +79,7 @@ alter short drop default, DROP INDEX utiny, DROP INDEX ushort, DROP PRIMARY KEY, -DROP FOREIGN KEY any_name, +DROP KEY any_name, ADD INDEX (auto); LOCK TABLES t1 WRITE; From 18166e45014c121f4cb04b9aeb26b77f621b0776 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 24 Nov 2023 11:23:30 +0200 Subject: [PATCH 365/477] mysqladmin -vv processlist now shows more information What is shown in this case is the result from the following query: select * from information_schema.processlist where id != connection_id() This allows easy monitoring of for example MAX_MEMORY_USED --- client/mysqladmin.cc | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index c14b99890b5..45205eb7b97 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -28,7 +28,7 @@ #include #include -#define ADMIN_VERSION "9.1" +#define ADMIN_VERSION "10.0" #define MAX_MYSQL_VAR 512 #define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */ #define MAX_TRUNC_LENGTH 3 @@ -40,12 +40,12 @@ char ex_var_names[MAX_MYSQL_VAR+100][FN_REFLEN]; ulonglong last_values[MAX_MYSQL_VAR+100]; static int interval=0; static my_bool option_force=0,interrupted=0,new_line=0, - opt_compress= 0, opt_local= 0, opt_relative= 0, opt_verbose= 0, + opt_compress= 0, opt_local= 0, opt_relative= 0, opt_vertical= 0, tty_password= 0, opt_nobeep, - opt_shutdown_wait_for_slaves= 0; + opt_shutdown_wait_for_slaves= 0, opt_not_used; static my_bool debug_info_flag= 0, debug_check_flag= 0; static uint tcp_port = 0, option_wait = 0, option_silent=0, nr_iterations; -static uint opt_count_iterations= 0, my_end_arg; +static uint opt_count_iterations= 0, my_end_arg, opt_verbose= 0; static ulong opt_connect_timeout, opt_shutdown_timeout; static char * unix_port=0; static char *opt_plugin_dir= 0, *opt_default_auth= 0; @@ -204,8 +204,10 @@ static struct my_option my_long_options[] = {"user", 'u', "User for login if not current user.", &user, &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"verbose", 'v', "Write more information.", &opt_verbose, - &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"verbose", 'v', "Write more information." + "Using it will print more information for 'processlist." + "Using it 2 times will print even more information for 'processlist'.", + &opt_not_used, &opt_not_used, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"vertical", 'E', @@ -298,6 +300,11 @@ get_one_option(const struct my_option *opt, const char *argument, case 'I': /* Info */ usage(); exit(0); + case 'v': /* --verbose */ + opt_verbose++; + if (argument == disabled_my_option) + opt_verbose= 0; + break; case OPT_CHARSETS_DIR: #if MYSQL_VERSION_ID > 32300 charsets_dir = argument; @@ -827,10 +834,17 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) { MYSQL_RES *result; MYSQL_ROW row; + const char *query; - if (mysql_query(mysql, (opt_verbose ? "show full processlist" : - "show processlist")) || - !(result = mysql_store_result(mysql))) + if (!opt_verbose) + query= "show processlist"; + else if (opt_verbose == 1) + query= "show full processlist"; + else + query= "select * from information_schema.processlist where id != connection_id()"; + + if (mysql_query(mysql, query) || + !(result = mysql_store_result(mysql))) { my_printf_error(0, "process list failed; error: '%s'", error_flags, mysql_error(mysql)); From 4bd94afbd3cecdcca9edb87834b41de5494fbbea Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 26 Nov 2023 11:53:12 +0200 Subject: [PATCH 366/477] MDEV-32884 Make s3_debug dynamic --- mysql-test/suite/s3/debug.result | 32 ++++++++++++++++++++++++++++++ mysql-test/suite/s3/debug.test | 34 ++++++++++++++++++++++++++++++++ storage/maria/aria_s3_copy.cc | 2 +- storage/maria/ha_s3.cc | 29 ++++++++++++++++++++++++--- storage/maria/libmarias3 | 2 +- 5 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 mysql-test/suite/s3/debug.result create mode 100644 mysql-test/suite/s3/debug.test diff --git a/mysql-test/suite/s3/debug.result b/mysql-test/suite/s3/debug.result new file mode 100644 index 00000000000..69d7a0ac9ea --- /dev/null +++ b/mysql-test/suite/s3/debug.result @@ -0,0 +1,32 @@ +drop table if exists t1; +# +# MDEV-32884 Make s3_debug dynamic +# +create or replace table t1 (a int, b int, c varchar(1000), key (a), key(c)) engine=aria; +insert into t1 select seq, seq+10, repeat(char(65+ mod(seq, 20)),mod(seq,1000)) from seq_1_to_100; +alter table t1 engine=s3; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `c` varchar(1000) DEFAULT NULL, + KEY `a` (`a`), + KEY `c` (`c`) +) ENGINE=S3 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci PAGE_CHECKSUM=1 +select count(*) from t1; +count(*) +100 +flush table t1; +NOT FOUND /storage-engine/s3_test_/ in mysqld.1.err +set @@global.s3_debug=1; +select count(*) from t1; +count(*) +100 +set @@global.s3_debug=0; +FOUND 6 /storage-engine/s3_test_/ in mysqld.1.err +select count(*) from t1; +count(*) +100 +drop table t1; +FOUND 6 /storage-engine/s3_test_/ in mysqld.1.err diff --git a/mysql-test/suite/s3/debug.test b/mysql-test/suite/s3/debug.test new file mode 100644 index 00000000000..d891678c85f --- /dev/null +++ b/mysql-test/suite/s3/debug.test @@ -0,0 +1,34 @@ +--source include/have_s3.inc +--source include/have_sequence.inc + +# +# Create unique database for running the tests +# +--source create_database.inc +--disable_warnings +drop table if exists t1; +--enable_warnings + +--echo # +--echo # MDEV-32884 Make s3_debug dynamic +--echo # + +create or replace table t1 (a int, b int, c varchar(1000), key (a), key(c)) engine=aria; +insert into t1 select seq, seq+10, repeat(char(65+ mod(seq, 20)),mod(seq,1000)) from seq_1_to_100; +alter table t1 engine=s3; +show create table t1; +select count(*) from t1; +flush table t1; + +--let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err +--let SEARCH_PATTERN=storage-engine/s3_test_ +--source include/search_pattern_in_file.inc +set @@global.s3_debug=1; +select count(*) from t1; +set @@global.s3_debug=0; +--source include/search_pattern_in_file.inc +select count(*) from t1; +drop table t1; +--source include/search_pattern_in_file.inc + +--source drop_database.inc diff --git a/storage/maria/aria_s3_copy.cc b/storage/maria/aria_s3_copy.cc index 77c41ba4572..b35c40ef2a6 100644 --- a/storage/maria/aria_s3_copy.cc +++ b/storage/maria/aria_s3_copy.cc @@ -195,7 +195,7 @@ static void get_options(int *argc, char ***argv) my_exit(-1); } if (opt_s3_debug) - ms3_debug(); + ms3_debug(1); } /* get_options */ diff --git a/storage/maria/ha_s3.cc b/storage/maria/ha_s3.cc index 8c105522c11..0f5cecf5c38 100644 --- a/storage/maria/ha_s3.cc +++ b/storage/maria/ha_s3.cc @@ -121,6 +121,29 @@ static void update_secret_key(MYSQL_THD thd, } } +static void update_s3_debug(MYSQL_THD thd, + struct st_mysql_sys_var *var + __attribute__((unused)), + void *var_ptr __attribute__((unused)), + const void *save) +{ + char new_state= *(char *) save; + if (s3_debug != new_state) + { + s3_debug= new_state; + if (s3_hton) // If library is initalized + { + ms3_debug(new_state); + if (!new_state) + { + /* Ensure that all logging is written to log */ + fflush(stderr); + } + } + } +} + + /* Define system variables for S3 */ static MYSQL_SYSVAR_ULONG(block_size, s3_block_size, @@ -129,9 +152,9 @@ static MYSQL_SYSVAR_ULONG(block_size, s3_block_size, 4*1024*1024, 65536, 16*1024*1024, 8192); static MYSQL_SYSVAR_BOOL(debug, s3_debug, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + PLUGIN_VAR_RQCMDARG, "Generates trace file from libmarias3 on stderr for debugging", - 0, 0, 0); + 0, update_s3_debug, 0); static MYSQL_SYSVAR_BOOL(slave_ignore_updates, s3_slave_ignore_updates, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, @@ -1048,7 +1071,7 @@ static int ha_s3_init(void *p) s3_pagecache.big_block_free= s3_free; s3_init_library(); if (s3_debug) - ms3_debug(); + ms3_debug(1); struct s3_func s3f_real = { diff --git a/storage/maria/libmarias3 b/storage/maria/libmarias3 index 3846890513d..a81724ab07b 160000 --- a/storage/maria/libmarias3 +++ b/storage/maria/libmarias3 @@ -1 +1 @@ -Subproject commit 3846890513df0653b8919bc45a7600f9b55cab31 +Subproject commit a81724ab07bd28e16bf431419c24b6362d5894fc From c6a9fd79047b1ce5b0938a609978e63d9aa04b3a Mon Sep 17 00:00:00 2001 From: Rex Date: Thu, 30 Nov 2023 11:47:44 +1200 Subject: [PATCH 367/477] MDEV-32212 DELETE with ORDER BY and semijoin optimization causing crash Statements affected by this bug are delete statements that have all these conditions 1) single table delete syntax 2) and in (sub-query) predicate 3) semi-join optimization enabled 4) an order by clause. Semijoin optimization on an innocent looking query, such as DELETE FROM t1 WHERE c1 IN (select c2 from t2) ORDER BY c1; turns it from a single table delete to a multi-table delete. During multi_delete::initialize_tables for the top level join object, a table is initialized missing a keep_current_rowid flag, needed to position a handler for removal of the correct row after the filesort structure has been built. Fix provided by Monty (monty@mariadb.com) Pushed into 10.5 at Monty's request. Applicable to 10.6, 10.11, 11.0. OK'd by Monty in slack:#askmonty 2023-12-01 --- sql/filesort.h | 7 +++++-- sql/sql_delete.cc | 7 +++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/sql/filesort.h b/sql/filesort.h index 9f71da02c96..7f54de266e6 100644 --- a/sql/filesort.h +++ b/sql/filesort.h @@ -54,8 +54,11 @@ public: /* TRUE means sort operation must produce table rowids. - FALSE means that it halso has an option of producing {sort_key, - addon_fields} pairs. + FALSE means that it also has an option of producing {sort_key, addon_fields} + pairs. + + Usually initialized with value of join_tab->keep_current_rowid to allow for + a call to table->file->position() using these table rowids. */ bool sort_positions; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 81c3141c252..ab0d5d35927 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1234,6 +1234,13 @@ multi_delete::initialize_tables(JOIN *join) { TABLE_LIST *tbl= walk->correspondent_table->find_table_for_update(); tables_to_delete_from|= tbl->table->map; + + /* + Ensure that filesort re-reads the row from the engine before + delete is called. + */ + join->map2table[tbl->table->tablenr]->keep_current_rowid= true; + if (delete_while_scanning && unique_table(thd, tbl, join->tables_list, 0)) { From 5a5ba7f1bd81d7ae1a2a93bf4d3809165352cf97 Mon Sep 17 00:00:00 2001 From: Rex Date: Mon, 6 Nov 2023 15:04:30 +1200 Subject: [PATCH 368/477] MDEV-32212 DELETE with ORDER BY and semijoin optimization causing crash Statements affected by this bug are delete statements that have all these conditions 1) single table delete syntax 2) and in (sub-query) predicate 3) semi-join optimization enabled 4) an order by clause. Semijoin optimization on an innocent looking query, such as DELETE FROM t1 WHERE c1 IN (select c2 from t2) ORDER BY c1; turns it from a single table delete to a multi-table delete. During multi_delete::initialize_tables for the top level join object, a table is initialized missing a keep_current_rowid flag, needed to position a handler for removal of the correct row after the filesort structure has been built. Fix provided by Monty (monty@mariadb.com) OK'd in slack:#askmonty 2023-12-01 applicable to 11.1 on --- mysql-test/main/delete.result | 45 +++++++++++++++++++++++++++++++++++ mysql-test/main/delete.test | 27 +++++++++++++++++++++ sql/filesort.h | 7 ++++-- sql/sql_delete.cc | 7 ++++++ 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/delete.result b/mysql-test/main/delete.result index c4bf335091a..21a3bedcaed 100644 --- a/mysql-test/main/delete.result +++ b/mysql-test/main/delete.result @@ -610,4 +610,49 @@ c1 c2 c3 2 1 4 2 2 5 drop table t1; +# +# MDEV-32212 DELETE with ORDER BY and semijoin optimization causing crash +# +CREATE TABLE t1 (c1 INT) ENGINE=InnoDB; +CREATE TABLE t2 (c2 INT) ENGINE=InnoDB; +INSERT INTO t1 values (1),(2),(3),(4),(5),(6); +INSERT INTO t2 values (2); +DELETE FROM t1 WHERE c1 IN (select c2 from t2); +select * from t1; +c1 +1 +3 +4 +5 +6 +truncate t1; +truncate t2; +INSERT INTO t1 values (1),(2),(3),(4),(5),(6); +INSERT INTO t2 values (2); +check sj optimization with order-by +analyze DELETE FROM t1 WHERE c1 IN (select c2 from t2) ORDER BY c1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 6 6.00 100.00 100.00 Using filesort +1 PRIMARY t2 ALL NULL NULL NULL NULL 1 1.00 100.00 16.67 Using where; FirstMatch(t1) +select * from t1; +c1 +1 +3 +4 +5 +6 +truncate t2; +INSERT INTO t2 values (3); +disallows sj optimization +analyze DELETE FROM t1 WHERE c1 IN (select c2 from t2) ORDER BY c1 limit 1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 5 1.00 100.00 100.00 Using where; Using filesort +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 1 1.00 100.00 20.00 Using where +select * from t1; +c1 +1 +4 +5 +6 +DROP TABLE t1, t2; End of 11.1 tests diff --git a/mysql-test/main/delete.test b/mysql-test/main/delete.test index 583d8223168..54d0ed7f014 100644 --- a/mysql-test/main/delete.test +++ b/mysql-test/main/delete.test @@ -667,4 +667,31 @@ select *from t1; drop table t1; +--echo # +--echo # MDEV-32212 DELETE with ORDER BY and semijoin optimization causing crash +--echo # +--source include/have_innodb.inc + +CREATE TABLE t1 (c1 INT) ENGINE=InnoDB; +CREATE TABLE t2 (c2 INT) ENGINE=InnoDB; +INSERT INTO t1 values (1),(2),(3),(4),(5),(6); +INSERT INTO t2 values (2); + +DELETE FROM t1 WHERE c1 IN (select c2 from t2); +select * from t1; +truncate t1; +truncate t2; +INSERT INTO t1 values (1),(2),(3),(4),(5),(6); +INSERT INTO t2 values (2); +--echo check sj optimization with order-by +analyze DELETE FROM t1 WHERE c1 IN (select c2 from t2) ORDER BY c1; +select * from t1; +truncate t2; +INSERT INTO t2 values (3); +--echo disallows sj optimization +analyze DELETE FROM t1 WHERE c1 IN (select c2 from t2) ORDER BY c1 limit 1; +select * from t1; + +DROP TABLE t1, t2; + --echo End of 11.1 tests diff --git a/sql/filesort.h b/sql/filesort.h index ebb521e2adc..8c7931e75e9 100644 --- a/sql/filesort.h +++ b/sql/filesort.h @@ -56,8 +56,11 @@ public: bool using_pq; /* TRUE means sort operation must produce table rowids. - FALSE means that it halso has an option of producing {sort_key, - addon_fields} pairs. + FALSE means that it also has an option of producing {sort_key, addon_fields} + pairs. + + Usually initialized with value of join_tab->keep_current_rowid to allow for + a call to table->file->position() using these table rowids. */ bool sort_positions; /* diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d0d0d47641e..781980bb8de 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1054,6 +1054,13 @@ multi_delete::initialize_tables(JOIN *join) { TABLE_LIST *tbl= walk->correspondent_table->find_table_for_update(); tables_to_delete_from|= tbl->table->map; + + /* + Ensure that filesort re-reads the row from the engine before + delete is called. + */ + join->map2table[tbl->table->tablenr]->keep_current_rowid= true; + if (delete_while_scanning && unique_table(thd, tbl, join->tables_list, 0)) { From 99cab7ee57945e13f958cd918724d438e05c2053 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 29 Nov 2023 14:36:03 +1100 Subject: [PATCH 369/477] MDEV-32903 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 b65305918e3..b7a76746a7f 100644 --- a/sql/ddl_log.cc +++ b/sql/ddl_log.cc @@ -179,6 +179,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. @@ -729,6 +731,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; @@ -2803,24 +2806,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; @@ -2833,6 +2823,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 9e76d94ef0f3f1a8d222a23c7922f806d00777b5 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sat, 18 Nov 2023 21:05:28 +0400 Subject: [PATCH 370/477] MDEV-19177: Geometry support by the partition feature. Remove the limitation, add tests. --- mysql-test/main/partition_geometries.result | 125 ++++++++++++++++++ mysql-test/main/partition_geometries.test | 93 +++++++++++++ mysql-test/suite/innodb_gis/r/geometry.result | 2 +- mysql-test/suite/innodb_gis/t/geometry.test | 2 +- sql/ha_partition.cc | 3 +- 5 files changed, 221 insertions(+), 4 deletions(-) create mode 100644 mysql-test/main/partition_geometries.result create mode 100644 mysql-test/main/partition_geometries.test diff --git a/mysql-test/main/partition_geometries.result b/mysql-test/main/partition_geometries.result new file mode 100644 index 00000000000..ec63b92b3da --- /dev/null +++ b/mysql-test/main/partition_geometries.result @@ -0,0 +1,125 @@ +# +# MDEV-19177: Geometry support for partition feature +# Test partition/geometry type cross-compatibility for the 4 storage engines that support +# geometries (Aria, MyISAM, InnoDB, Archive) +# Geometries to test - point, multipolygon, geometry collection +# Note: Archive does not support additional indices. +# +SET @point = Point(3,3); +SET @poly = MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))); +SET @collection = GeometryCollection(Point(1,1), Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))); +# +# Aria engine +# +CREATE TABLE t1 ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`geom` geometry NOT NULL, +PRIMARY KEY (id), +SPATIAL INDEX(geom) +) Engine=Aria PARTITION BY HASH (id) +PARTITIONS 10; +INSERT INTO t1 VALUES (NULL, @point), (NULL, @poly), (NULL, @collection); +SELECT ST_AsGeoJSON(geom) FROM t1; +ST_AsGeoJSON(geom) +{"type": "Point", "coordinates": [3, 3]} +{"type": "MultiPolygon", "coordinates": [[[[0, 3], [3, 3], [3, 0], [0, 3]]]]} +{"type": "GeometryCollection", "geometries": [{"type": "Point", "coordinates": [1, 1]}, {"type": "Polygon", "coordinates": [[[0, 3], [3, 3], [3, 0], [0, 3]]]}]} +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `geom` geometry NOT NULL, + PRIMARY KEY (`id`), + SPATIAL KEY `geom` (`geom`) +) ENGINE=Aria AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci + PARTITION BY HASH (`id`) +PARTITIONS 10 +DROP TABLE t1; +# +# MyISAM engine +# +CREATE TABLE t1 ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`geom` geometry NOT NULL, +PRIMARY KEY (id), +SPATIAL INDEX(geom) +) Engine=myisam PARTITION BY HASH (id) +PARTITIONS 10; +INSERT INTO t1 VALUES (NULL, @point), (NULL, @poly), (NULL, @collection); +SELECT ST_AsGeoJSON(geom) FROM t1; +ST_AsGeoJSON(geom) +{"type": "Point", "coordinates": [3, 3]} +{"type": "MultiPolygon", "coordinates": [[[[0, 3], [3, 3], [3, 0], [0, 3]]]]} +{"type": "GeometryCollection", "geometries": [{"type": "Point", "coordinates": [1, 1]}, {"type": "Polygon", "coordinates": [[[0, 3], [3, 3], [3, 0], [0, 3]]]}]} +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `geom` geometry NOT NULL, + PRIMARY KEY (`id`), + SPATIAL KEY `geom` (`geom`) +) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci + PARTITION BY HASH (`id`) +PARTITIONS 10 +DROP TABLE t1; +# +# InnoDB engine +# +CREATE TABLE t1 ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`geom` geometry NOT NULL, +PRIMARY KEY (id), +SPATIAL INDEX(geom) +) Engine=innodb PARTITION BY HASH (id) +PARTITIONS 10; +INSERT INTO t1 VALUES (NULL, @point), (NULL, @poly), (NULL, @collection); +SELECT ST_AsGeoJSON(geom) FROM t1; +ST_AsGeoJSON(geom) +{"type": "Point", "coordinates": [3, 3]} +{"type": "MultiPolygon", "coordinates": [[[[0, 3], [3, 3], [3, 0], [0, 3]]]]} +{"type": "GeometryCollection", "geometries": [{"type": "Point", "coordinates": [1, 1]}, {"type": "Polygon", "coordinates": [[[0, 3], [3, 3], [3, 0], [0, 3]]]}]} +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `geom` geometry NOT NULL, + PRIMARY KEY (`id`), + SPATIAL KEY `geom` (`geom`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci + PARTITION BY HASH (`id`) +PARTITIONS 10 +DROP TABLE t1; +# +# Archive engine +# +INSTALL SONAME 'ha_archive'; +CREATE TABLE t1 ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`geom` geometry, +SPATIAL INDEX(geom) +) Engine=archive PARTITION BY HASH (id) +PARTITIONS 10; +ERROR HY000: The storage engine partition doesn't support SPATIAL indexes +CREATE TABLE t1 ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`geom` geometry, +PRIMARY KEY (id) +) Engine=archive PARTITION BY HASH (id) +PARTITIONS 10; +INSERT INTO t1 VALUES (NULL, @point), (NULL, @poly), (NULL, @collection); +SELECT ST_AsGeoJSON(geom) FROM t1; +ST_AsGeoJSON(geom) +{"type": "Point", "coordinates": [3, 3]} +{"type": "MultiPolygon", "coordinates": [[[[0, 3], [3, 3], [3, 0], [0, 3]]]]} +{"type": "GeometryCollection", "geometries": [{"type": "Point", "coordinates": [1, 1]}, {"type": "Polygon", "coordinates": [[[0, 3], [3, 3], [3, 0], [0, 3]]]}]} +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `geom` geometry DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=ARCHIVE AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci + PARTITION BY HASH (`id`) +PARTITIONS 10 +DROP TABLE t1; +UNINSTALL SONAME 'ha_archive'; diff --git a/mysql-test/main/partition_geometries.test b/mysql-test/main/partition_geometries.test new file mode 100644 index 00000000000..34e72463058 --- /dev/null +++ b/mysql-test/main/partition_geometries.test @@ -0,0 +1,93 @@ +-- source include/have_geometry.inc + +if (!$HA_ARCHIVE_SO) { + skip Needs Archive plugin; +} + +--echo # +--echo # MDEV-19177: Geometry support for partition feature +--echo # Test partition/geometry type cross-compatibility for the 4 storage engines that support +--echo # geometries (Aria, MyISAM, InnoDB, Archive) +--echo # Geometries to test - point, multipolygon, geometry collection +--echo # Note: Archive does not support additional indices. +--echo # +SET @point = Point(3,3); +SET @poly = MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))); +SET @collection = GeometryCollection(Point(1,1), Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))); + +--source include/have_partition.inc + +--echo # +--echo # Aria engine +--echo # +CREATE TABLE t1 ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `geom` geometry NOT NULL, + PRIMARY KEY (id), + SPATIAL INDEX(geom) +) Engine=Aria PARTITION BY HASH (id) +PARTITIONS 10; + +INSERT INTO t1 VALUES (NULL, @point), (NULL, @poly), (NULL, @collection); +SELECT ST_AsGeoJSON(geom) FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--echo # +--echo # MyISAM engine +--echo # +CREATE TABLE t1 ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `geom` geometry NOT NULL, + PRIMARY KEY (id), + SPATIAL INDEX(geom) +) Engine=myisam PARTITION BY HASH (id) +PARTITIONS 10; + +INSERT INTO t1 VALUES (NULL, @point), (NULL, @poly), (NULL, @collection); +SELECT ST_AsGeoJSON(geom) FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--echo # +--echo # InnoDB engine +--echo # +--source include/have_innodb.inc +CREATE TABLE t1 ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `geom` geometry NOT NULL, + PRIMARY KEY (id), + SPATIAL INDEX(geom) +) Engine=innodb PARTITION BY HASH (id) +PARTITIONS 10; + +INSERT INTO t1 VALUES (NULL, @point), (NULL, @poly), (NULL, @collection); +SELECT ST_AsGeoJSON(geom) FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--echo # +--echo # Archive engine +--echo # + +INSTALL SONAME 'ha_archive'; +--error ER_TABLE_CANT_HANDLE_SPKEYS +CREATE TABLE t1 ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `geom` geometry, + SPATIAL INDEX(geom) +) Engine=archive PARTITION BY HASH (id) +PARTITIONS 10; +CREATE TABLE t1 ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `geom` geometry, + PRIMARY KEY (id) +) Engine=archive PARTITION BY HASH (id) +PARTITIONS 10; + +INSERT INTO t1 VALUES (NULL, @point), (NULL, @poly), (NULL, @collection); +SELECT ST_AsGeoJSON(geom) FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; +UNINSTALL SONAME 'ha_archive'; + diff --git a/mysql-test/suite/innodb_gis/r/geometry.result b/mysql-test/suite/innodb_gis/r/geometry.result index c38e9e28d85..d4d4abe0c93 100644 --- a/mysql-test/suite/innodb_gis/r/geometry.result +++ b/mysql-test/suite/innodb_gis/r/geometry.result @@ -1093,7 +1093,7 @@ PARTITION pNorth VALUES IN (10,20,30) , PARTITION pEast VALUES IN (40,50,60) , PARTITION pWest VALUES IN (70,80,100) ); -ERROR 42000: The storage engine for the table doesn't support GEOMETRY +ERROR HY000: A BLOB field is not allowed in partition function #check start transaction commit & Rollback START TRANSACTION; DELETE FROM tab3; diff --git a/mysql-test/suite/innodb_gis/t/geometry.test b/mysql-test/suite/innodb_gis/t/geometry.test index 4e8f0f729b5..fe19deb3b7a 100644 --- a/mysql-test/suite/innodb_gis/t/geometry.test +++ b/mysql-test/suite/innodb_gis/t/geometry.test @@ -648,7 +648,7 @@ CREATE TABLE child (id GEOMETRY, parent_id GEOMETRY, ) ENGINE=INNODB; --echo #check partition table support ---error 1178 +--error ER_BLOB_FIELD_IN_PART_FUNC_ERROR CREATE TABLE emp2( id GEOMETRY NOT NULL, store_name VARCHAR(30), diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index f8d8868913b..3b04e5c0c2d 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -75,8 +75,7 @@ HA_REC_NOT_IN_SEQ | \ HA_CAN_REPAIR | \ HA_REUSES_FILE_NAMES) -#define PARTITION_DISABLED_TABLE_FLAGS (HA_CAN_GEOMETRY | \ - HA_DUPLICATE_POS | \ +#define PARTITION_DISABLED_TABLE_FLAGS (HA_DUPLICATE_POS | \ HA_CAN_INSERT_DELAYED | \ HA_READ_BEFORE_WRITE_REMOVAL |\ HA_CAN_TABLES_WITHOUT_ROLLBACK) From af2e91d9f23f21edd5f2b510aa0efe196662e1b3 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 30 Nov 2023 09:59:23 +0100 Subject: [PATCH 371/477] fix for the test (real fixes will be in 10.4) --- mysql-test/main/subselect.result | 2 +- mysql-test/main/subselect.test | 2 +- mysql-test/main/subselect_no_exists_to_in.result | 2 +- mysql-test/main/subselect_no_mat.result | 2 +- mysql-test/main/subselect_no_opts.result | 2 +- mysql-test/main/subselect_no_scache.result | 2 +- mysql-test/main/subselect_no_semijoin.result | 2 +- sql/item_func.cc | 2 +- sql/sql_cte.cc | 2 ++ 9 files changed, 10 insertions(+), 8 deletions(-) diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result index 5bf10e9310f..6f110d1d603 100644 --- a/mysql-test/main/subselect.result +++ b/mysql-test/main/subselect.result @@ -7535,7 +7535,7 @@ FROM x WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > (SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) ORDER BY x ASC, x DESC, x; -ERROR 22007: Truncated incorrect DECIMAL value: 'x' +ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'x' DROP TABLE t1, x; # # End of 10.4 tests diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test index 9d992ec9021..5fafaad8754 100644 --- a/mysql-test/main/subselect.test +++ b/mysql-test/main/subselect.test @@ -6386,7 +6386,7 @@ let $q= WITH RECURSIVE x (x) AS ( (SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) ORDER BY x ASC, x DESC, x; ---error ER_TRUNCATED_WRONG_VALUE +--error ER_NOT_STANDARD_COMPLIANT_RECURSIVE eval $q; DROP TABLE t1, x; diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result index 6d95e6bfbe6..860cc252073 100644 --- a/mysql-test/main/subselect_no_exists_to_in.result +++ b/mysql-test/main/subselect_no_exists_to_in.result @@ -7535,7 +7535,7 @@ FROM x WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > (SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) ORDER BY x ASC, x DESC, x; -ERROR 22007: Truncated incorrect DECIMAL value: 'x' +ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'x' DROP TABLE t1, x; # # End of 10.4 tests diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result index 7e3238dfc9e..c4b306c6f06 100644 --- a/mysql-test/main/subselect_no_mat.result +++ b/mysql-test/main/subselect_no_mat.result @@ -7528,7 +7528,7 @@ FROM x WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > (SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) ORDER BY x ASC, x DESC, x; -ERROR 22007: Truncated incorrect DECIMAL value: 'x' +ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'x' DROP TABLE t1, x; # # End of 10.4 tests diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result index 629115d5142..d286d7ed015 100644 --- a/mysql-test/main/subselect_no_opts.result +++ b/mysql-test/main/subselect_no_opts.result @@ -7526,7 +7526,7 @@ FROM x WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > (SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) ORDER BY x ASC, x DESC, x; -ERROR 22007: Truncated incorrect DECIMAL value: 'x' +ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'x' DROP TABLE t1, x; # # End of 10.4 tests diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result index 182eb5d74e7..3975ccc5193 100644 --- a/mysql-test/main/subselect_no_scache.result +++ b/mysql-test/main/subselect_no_scache.result @@ -7541,7 +7541,7 @@ FROM x WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > (SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) ORDER BY x ASC, x DESC, x; -ERROR 22007: Truncated incorrect DECIMAL value: 'x' +ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'x' DROP TABLE t1, x; # # End of 10.4 tests diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result index 89b3fbb981b..fab8ad0e2cc 100644 --- a/mysql-test/main/subselect_no_semijoin.result +++ b/mysql-test/main/subselect_no_semijoin.result @@ -7526,7 +7526,7 @@ FROM x WHERE (SELECT (SELECT x WHERE x IN (SELECT x FROM x))) > (SELECT (SELECT x ORDER BY x = x OR (x = 1 AND x = 1) DESC)) ORDER BY x ASC, x DESC, x; -ERROR 22007: Truncated incorrect DECIMAL value: 'x' +ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'x' DROP TABLE t1, x; # # End of 10.4 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index c9b249a4554..5202d395580 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1824,7 +1824,7 @@ void Item_func_neg::fix_length_and_dec_int() Use val() to get value as arg_type doesn't mean that item is Item_int or Item_float due to existence of Item_param. */ - if (args[0]->const_item()) + if (args[0]->const_item() && !args[0]->is_expensive()) { longlong val= args[0]->val_int(); if ((ulonglong) val >= (ulonglong) LONGLONG_MIN && diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 6250d71e4fc..3310ba55229 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -643,6 +643,8 @@ void With_element::check_dependencies_in_unit(st_select_lex_unit *unit, { check_dependencies_in_select(sl, &unit_ctxt_elem, in_subq, dep_map); } + if ((sl= unit->fake_select_lex)) + check_dependencies_in_select(sl, &unit_ctxt_elem, in_subq, dep_map); } From d8e6bb00888b1f82c031938f4c8ac5d97f6874c3 Mon Sep 17 00:00:00 2001 From: Gulshan Kumar Prasad Date: Sat, 18 Nov 2023 19:08:10 +0530 Subject: [PATCH 372/477] MDEV-32611: Test suite is missing dump option delete-master-logs. Extending the rpl_mysqldump_slave.test to incorporate the delete-master-logs option, and this options is alias of get binlogs: show master status -> flush logs -> purge binary logs to sequence and this test is derived using the same pattern. also we measure the pre and post log state on the master following the mysqldump process. Introducing assertions to validate the correct state. --- mysql-test/main/rpl_mysqldump_slave.result | 9 +++++ mysql-test/main/rpl_mysqldump_slave.test | 40 ++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/mysql-test/main/rpl_mysqldump_slave.result b/mysql-test/main/rpl_mysqldump_slave.result index 903b671178f..c5458ec374c 100644 --- a/mysql-test/main/rpl_mysqldump_slave.result +++ b/mysql-test/main/rpl_mysqldump_slave.result @@ -65,4 +65,13 @@ SET GLOBAL gtid_slave_pos='0-2-1003'; -- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START; CHANGE MASTER TO MASTER_USE_GTID=slave_pos; SET GLOBAL gtid_slave_pos='0-2-1003'; +connection master; +CREATE TABLE t ( +id int +); +insert into t values (1); +insert into t values (2); +drop table t; +-- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000002', MASTER_LOG_POS=BINLOG_START; +-- SET GLOBAL gtid_slave_pos='0-1-1005'; include/rpl_end.inc diff --git a/mysql-test/main/rpl_mysqldump_slave.test b/mysql-test/main/rpl_mysqldump_slave.test index 345bdb82535..315b4def2a4 100644 --- a/mysql-test/main/rpl_mysqldump_slave.test +++ b/mysql-test/main/rpl_mysqldump_slave.test @@ -83,6 +83,46 @@ DROP TABLE t2; --replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ --exec $MYSQL_DUMP_SLAVE --compact --master-data --single-transaction --gtid test +# +# MDEV-32611 Added test for mysqldump --delete-master-logs option. +# This options is alias of +# get binlogs: show master status -> flush logs -> purge binary logs to +# sequence and this test is derived using the same pattern. +# +connection master; + +CREATE TABLE t ( + id int +); + +insert into t values (1); +insert into t values (2); + +drop table t; + +--let $predump_binlog_filename= query_get_value(SHOW MASTER STATUS, File, 1) + +# Execute mysqldump with delete-master-logs option +--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ +--exec $MYSQL_DUMP --compact --no-create-info --no-data --delete-master-logs test + +--let $postdump_binlog_filename= query_get_value(SHOW MASTER STATUS, File, 1) + +--let $postdump_first_binary_log_filename= query_get_value(SHOW BINARY LOGS, Log_name, 1) + +if ($predump_binlog_filename == $postdump_binlog_filename) +{ + --echo # predump_binlog_filename: $predump_binlog_filename + --echo # postdump_binlog_filename: $postdump_binlog_filename + --die Master state didn't change after mariadb-dump with --delete-master-logs. +} + +if ($postdump_first_binary_log_filename != $postdump_binlog_filename) +{ + --echo # postdump_first_binary_log_filename: $postdump_first_binary_log_filename + --echo # postdump_binlog_filename: $postdump_binlog_filename + --die Master binlog wasn't deleted after mariadb-dump with --delete-master-logs. +} --source include/rpl_end.inc From 31ffa7441c26364987276cbc9721e645a3219c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 4 Dec 2023 09:38:29 +0200 Subject: [PATCH 373/477] Fix GCC -Wunused-variable --- storage/innobase/mtr/mtr0mtr.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index e14e3d8c797..e5206ca1d92 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -425,7 +425,8 @@ void mtr_t::commit() break; default: buf_page_t *bpage= static_cast(slot.object); - const auto s= bpage->unfix(); + ut_d(const auto s=) + bpage->unfix(); if (slot.type & MTR_MEMO_MODIFY) { ut_ad(slot.type == MTR_MEMO_PAGE_X_MODIFY || From 850d61736deba354377634cf344256ee850b93b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 4 Dec 2023 09:45:53 +0200 Subject: [PATCH 374/477] MDEV-32042 Simplify buf_page_get_gen() buf_page_get_low(): Rename to buf_page_get_gen(), and assume that no crash recovery is needed. recv_sys_t::recover(): Replaces the old buf_page_get_gen(). Read a page while crash recovery is in progress. trx_rseg_get_n_undo_tablespaces(), ibuf_upgrade_needed(): Invoke recv_sys.recover() instead of buf_page_get_gen(). dict_boot(): Invoke recv_sys.recover() instead of buf_page_get_gen(). Do not load the system tables. srv_start(): Load the system tables and the undo logs after all redo log has been applied in recv_sys.apply(true) and we can safely invoke the regular buf_page_get_gen(). --- storage/innobase/btr/btr0btr.cc | 6 +-- storage/innobase/buf/buf0buf.cc | 64 ++------------------------ storage/innobase/buf/buf0lru.cc | 2 +- storage/innobase/dict/dict0boot.cc | 18 +------- storage/innobase/ibuf/ibuf0ibuf.cc | 6 +-- storage/innobase/include/buf0buf.h | 26 +---------- storage/innobase/include/log0recv.h | 21 +++------ storage/innobase/log/log0recv.cc | 71 ++++++++++++++++++++++------- storage/innobase/row/row0import.cc | 2 +- storage/innobase/srv/srv0start.cc | 55 +++++++++++++++------- 10 files changed, 115 insertions(+), 156 deletions(-) diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 45fc98b5c48..44e761a961a 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -1114,9 +1114,9 @@ void btr_drop_temporary_table(const dict_table_t &table) for (const dict_index_t *index= table.indexes.start; index; index= dict_table_get_next_index(index)) { - if (buf_block_t *block= buf_page_get_low({SRV_TMP_SPACE_ID, index->page}, 0, - RW_X_LATCH, nullptr, BUF_GET, &mtr, - nullptr)) + if (buf_block_t *block= buf_page_get_gen({SRV_TMP_SPACE_ID, index->page}, + 0, RW_X_LATCH, nullptr, BUF_GET, + &mtr, nullptr)) { btr_free_but_not_root(block, MTR_LOG_NO_REDO); mtr.set_log_mode(MTR_LOG_NO_REDO); diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index bf5bd162081..a4bccf64348 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2585,7 +2585,7 @@ or BUF_PEEK_IF_IN_POOL @return pointer to the block or NULL */ TRANSACTIONAL_TARGET buf_block_t* -buf_page_get_low( +buf_page_get_gen( const page_id_t page_id, ulint zip_size, ulint rw_latch, @@ -2778,7 +2778,7 @@ free_unfixed_block: wait_for_unzip: /* The page is being read or written, or another thread is executing buf_zip_decompress() - in buf_page_get_low() on it. */ + in buf_page_get_gen() on it. */ block->page.unfix(); std::this_thread::sleep_for( std::chrono::microseconds(100)); @@ -2801,10 +2801,7 @@ wait_for_unfix: ut_ad(&block->page == buf_pool.page_hash.get(page_id, chain)); /* Wait for any other threads to release their buffer-fix - on the compressed-only block descriptor. - FIXME: Never fix() before acquiring the lock. - Only in buf_page_get_gen(), buf_page_get_low(), buf_page_free() - we are violating that principle. */ + on the compressed-only block descriptor. */ state = block->page.state(); switch (state) { @@ -2830,7 +2827,7 @@ wait_for_unfix: goto wait_for_unfix; } - /* Ensure that another buf_page_get_low() will wait for + /* Ensure that another buf_page_get_gen() will wait for new_block->page.lock.x_unlock(). */ block->page.set_state(buf_page_t::READ_FIX); @@ -2954,59 +2951,6 @@ page_id_mismatch: return block; } -/** Get access to a database page. Buffered redo log may be applied. -@param[in] page_id page id -@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 -@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH -@param[in] guess guessed block or NULL -@param[in] mode BUF_GET, BUF_GET_IF_IN_POOL, -or BUF_PEEK_IF_IN_POOL -@param[in,out] mtr mini-transaction, or NULL -@param[out] err DB_SUCCESS or error code -@return pointer to the block or NULL */ -buf_block_t* -buf_page_get_gen( - const page_id_t page_id, - ulint zip_size, - ulint rw_latch, - buf_block_t* guess, - ulint mode, - mtr_t* mtr, - dberr_t* err) -{ - buf_block_t *block= recv_sys.recover(page_id); - if (UNIV_LIKELY(!block)) - return buf_page_get_low(page_id, zip_size, rw_latch, - guess, mode, mtr, err); - else if (UNIV_UNLIKELY(block == reinterpret_cast(-1))) - { - corrupted: - if (err) - *err= DB_CORRUPTION; - return nullptr; - } - if (err) - *err= DB_SUCCESS; - /* Recovery is a special case; we fix() before acquiring lock. */ - auto s= block->page.fix(); - ut_ad(s >= buf_page_t::FREED); - /* The block may be write-fixed at this point because we are not - holding a lock, but it must not be read-fixed. */ - ut_ad(s < buf_page_t::READ_FIX || s >= buf_page_t::WRITE_FIX); - if (s < buf_page_t::UNFIXED) - { - ut_ad(mode == BUF_GET_POSSIBLY_FREED || mode == BUF_PEEK_IF_IN_POOL); - mysql_mutex_lock(&buf_pool.mutex); - block->page.unfix(); - buf_LRU_free_page(&block->page, true); - mysql_mutex_unlock(&buf_pool.mutex); - goto corrupted; - } - - mtr->page_lock(block, rw_latch); - return block; -} - /********************************************************************//** This is the general function used to get optimistic access to a database page. diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 3e556c7df37..6f5a7b1a7ee 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -815,7 +815,7 @@ bool buf_LRU_free_page(buf_page_t *bpage, bool zip) /* We must hold an exclusive hash_lock to prevent bpage->can_relocate() from changing due to a concurrent - execution of buf_page_get_low(). */ + execution of buf_page_get_gen(). */ buf_pool_t::hash_chain& chain= buf_pool.page_hash.cell_get(id.fold()); page_hash_latch& hash_lock = buf_pool.page_hash.lock_get(chain); /* We cannot use transactional_lock_guard here, diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc index 316d0f01322..2a59cc78355 100644 --- a/storage/innobase/dict/dict0boot.cc +++ b/storage/innobase/dict/dict0boot.cc @@ -218,8 +218,7 @@ dberr_t dict_boot() dict_sys.create(); dberr_t err; - const buf_block_t *d = buf_page_get_gen(hdr_page_id, 0, RW_S_LATCH, - nullptr, BUF_GET, &mtr, &err); + const buf_block_t *d = recv_sys.recover(hdr_page_id, &mtr ,&err); if (!d) { mtr.commit(); return err; @@ -393,19 +392,6 @@ dberr_t dict_boot() UT_BITS_IN_BYTES(unsigned(table->indexes.start->n_nullable))); mtr.commit(); - - if (err == DB_SUCCESS) { - /* Load definitions of other indexes on system tables */ - - dict_load_sys_table(dict_sys.sys_tables); - dict_load_sys_table(dict_sys.sys_columns); - dict_load_sys_table(dict_sys.sys_indexes); - dict_load_sys_table(dict_sys.sys_fields); - dict_sys.unlock(); - dict_sys.load_sys_tables(); - } else { - dict_sys.unlock(); - } - + dict_sys.unlock(); return err; } diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index ce5e0541ecf..4fff8bed133 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -1012,8 +1012,7 @@ dberr_t ibuf_upgrade_needed() mtr.start(); mtr.x_lock_space(fil_system.sys_space); dberr_t err; - const buf_block_t *header_page= - buf_page_get_gen(ibuf_header, 0, RW_S_LATCH, nullptr, BUF_GET, &mtr, &err); + const buf_block_t *header_page= recv_sys.recover(ibuf_header, &mtr, &err); if (!header_page) { @@ -1026,8 +1025,7 @@ dberr_t ibuf_upgrade_needed() return err; } - const buf_block_t *root= buf_page_get_gen(ibuf_root, 0, RW_S_LATCH, nullptr, - BUF_GET, &mtr, &err); + const buf_block_t *root= recv_sys.recover(ibuf_root, &mtr, &err); if (!root) goto err_exit; diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 1aae6d9867a..f4796d004ae 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -201,34 +201,12 @@ buf_page_get_gen( buf_block_t* guess, ulint mode, mtr_t* mtr, - dberr_t* err = NULL) - MY_ATTRIBUTE((nonnull(6))); - -/** This is the low level function used to get access to a database page. -@param[in] page_id page id -@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 -@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH -@param[in] guess guessed block or NULL -@param[in] mode BUF_GET, BUF_GET_IF_IN_POOL, -or BUF_PEEK_IF_IN_POOL -@param[in,out] mtr mini-transaction, or NULL if a - block with page_id is to be evicted -@param[out] err DB_SUCCESS or error code -@return pointer to the block or NULL */ -buf_block_t* -buf_page_get_low( - const page_id_t page_id, - ulint zip_size, - ulint rw_latch, - buf_block_t* guess, - ulint mode, - mtr_t* mtr, - dberr_t* err); + dberr_t* err = nullptr); /** Initialize a page in the buffer pool. The page is usually not read from a file even if it cannot be found in the buffer buf_pool. This is one of the functions which perform to a block a state transition NOT_USED => LRU -(the other is buf_page_get_low()). +(the other is buf_page_get_gen()). @param[in,out] space space object @param[in] offset offset of the tablespace @param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index e67246dd906..d4e8242b513 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -280,12 +280,6 @@ private: @retval -1 if the page cannot be recovered due to corruption */ inline buf_block_t *recover_low(const map::iterator &p, mtr_t &mtr, buf_block_t *b, lsn_t init_lsn); - /** Attempt to initialize a page based on redo log records. - @param page_id page identifier - @return the recovered block - @retval nullptr if the page cannot be initialized based on log records - @retval -1 if the page cannot be recovered due to corruption */ - ATTRIBUTE_COLD buf_block_t *recover_low(const page_id_t page_id); /** All found log files (multiple ones are possible if we are upgrading from before MariaDB Server 10.5.1) */ @@ -430,15 +424,14 @@ public: /** @return whether log file corruption was found */ bool is_corrupt_log() const { return UNIV_UNLIKELY(found_corrupt_log); } - /** Attempt to initialize a page based on redo log records. + /** Read a page or recover it based on redo log records. @param page_id page identifier - @return the recovered block - @retval nullptr if the page cannot be initialized based on log records - @retval -1 if the page cannot be recovered due to corruption */ - buf_block_t *recover(const page_id_t page_id) - { - return UNIV_UNLIKELY(recovery_on) ? recover_low(page_id) : nullptr; - } + @param mtr mini-transaction + @param err error code + @return the requested block + @retval nullptr if the page cannot be accessed due to corruption */ + ATTRIBUTE_COLD + buf_block_t *recover(const page_id_t page_id, mtr_t *mtr, dberr_t *err); /** Try to recover a tablespace that was not readable earlier @param p iterator diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index bf450211bfb..fcda96b501a 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3649,33 +3649,70 @@ inline buf_block_t *recv_sys_t::recover_low(const map::iterator &p, mtr_t &mtr, return block ? block : reinterpret_cast(-1); } -/** Attempt to initialize a page based on redo log records. +/** Read a page or recover it based on redo log records. @param page_id page identifier -@return recovered block -@retval nullptr if the page cannot be initialized based on log records */ -ATTRIBUTE_COLD buf_block_t *recv_sys_t::recover_low(const page_id_t page_id) +@param mtr mini-transaction +@param err error code +@return the requested block +@retval nullptr if the page cannot be accessed due to corruption */ +ATTRIBUTE_COLD +buf_block_t * +recv_sys_t::recover(const page_id_t page_id, mtr_t *mtr, dberr_t *err) { + if (!recovery_on) + must_read: + return buf_page_get_gen(page_id, 0, RW_S_LATCH, nullptr, BUF_GET, mtr, + err); + mysql_mutex_lock(&mutex); map::iterator p= pages.find(page_id); - if (p != pages.end() && !p->second.being_processed && p->second.skip_read) + if (p == pages.end() || p->second.being_processed || !p->second.skip_read) { - p->second.being_processed= 1; - const lsn_t init_lsn{mlog_init.last(page_id)}; mysql_mutex_unlock(&mutex); - buf_block_t *free_block= buf_LRU_get_free_block(have_no_mutex); - mtr_t mtr; - buf_block_t *block= recover_low(p, mtr, free_block, init_lsn); - p->second.being_processed= -1; - ut_ad(!block || block == reinterpret_cast(-1) || - block == free_block); - if (UNIV_UNLIKELY(!block)) - buf_pool.free_block(free_block); - return block; + goto must_read; } + p->second.being_processed= 1; + const lsn_t init_lsn{mlog_init.last(page_id)}; mysql_mutex_unlock(&mutex); - return nullptr; + buf_block_t *free_block= buf_LRU_get_free_block(have_no_mutex); + buf_block_t *block; + { + mtr_t local_mtr; + block= recover_low(p, local_mtr, free_block, init_lsn); + } + p->second.being_processed= -1; + if (UNIV_UNLIKELY(!block)) + { + buf_pool.free_block(free_block); + goto must_read; + } + else if (block == reinterpret_cast(-1)) + { + corrupted: + if (err) + *err= DB_CORRUPTION; + return nullptr; + } + + ut_ad(block == free_block); + auto s= block->page.fix(); + ut_ad(s >= buf_page_t::FREED); + /* The block may be write-fixed at this point because we are not + holding a latch, but it must not be read-fixed. */ + ut_ad(s < buf_page_t::READ_FIX || s >= buf_page_t::WRITE_FIX); + if (s < buf_page_t::UNFIXED) + { + mysql_mutex_lock(&buf_pool.mutex); + block->page.unfix(); + buf_LRU_free_page(&block->page, true); + mysql_mutex_unlock(&buf_pool.mutex); + goto corrupted; + } + + mtr->page_lock(block, RW_S_LATCH); + return block; } inline fil_space_t *fil_system_t::find(const char *path) const diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 3ff46bf76fe..809b9110a6a 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -2074,7 +2074,7 @@ dberr_t PageConverter::operator()(buf_block_t* block) UNIV_NOTHROW /* If we already had an old page with matching number in the buffer pool, evict it now, because we no longer evict the pages on DISCARD TABLESPACE. */ - buf_page_get_low(block->page.id(), get_zip_size(), RW_NO_LATCH, + buf_page_get_gen(block->page.id(), get_zip_size(), RW_NO_LATCH, nullptr, BUF_PEEK_IF_IN_POOL, nullptr, nullptr); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index f9f4da5b61b..4a2cd5078dd 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -596,7 +596,8 @@ static uint32_t trx_rseg_get_n_undo_tablespaces() mtr_t mtr; mtr.start(); - if (const buf_block_t *sys_header= trx_sysf_get(&mtr, false)) + if (const buf_block_t *sys_header= + recv_sys.recover({TRX_SYS_SPACE, TRX_SYS_PAGE_NO}, &mtr, nullptr)) for (ulint rseg_id= 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) if (trx_sysf_rseg_get_page_no(sys_header, rseg_id) != FIL_NULL) if (uint32_t space= trx_sysf_rseg_get_space(sys_header, rseg_id)) @@ -1552,20 +1553,6 @@ dberr_t srv_start(bool create_new_db) srv_undo_tablespaces_active = trx_rseg_get_n_undo_tablespaces(); - - if (srv_operation != SRV_OPERATION_RESTORE) { - dict_sys.load_sys_tables(); - } - - if (UNIV_UNLIKELY(must_upgrade_ibuf)) { - dict_load_tablespaces(nullptr, true); - err = ibuf_upgrade(); - if (err != DB_SUCCESS) { - break; - } - } - - err = trx_lists_init_at_db_start(); break; default: ut_ad("wrong mariabackup mode" == 0); @@ -1596,9 +1583,45 @@ dberr_t srv_start(bool create_new_db) return(srv_init_abort(DB_CORRUPTION)); } + if (srv_operation != SRV_OPERATION_RESTORE + || recv_needed_recovery) { + } + DBUG_PRINT("ib_log", ("apply completed")); - if (recv_needed_recovery) { + if (srv_operation != SRV_OPERATION_RESTORE) { + dict_sys.lock(SRW_LOCK_CALL); + dict_load_sys_table(dict_sys.sys_tables); + dict_sys.unlock(); + + if (UNIV_UNLIKELY(must_upgrade_ibuf)) { + dict_load_tablespaces(nullptr, true); + err = ibuf_upgrade(); + if (err != DB_SUCCESS) { + return srv_init_abort(err); + } + } + + dict_sys.lock(SRW_LOCK_CALL); + dict_load_sys_table(dict_sys.sys_columns); + dict_load_sys_table(dict_sys.sys_indexes); + dict_load_sys_table(dict_sys.sys_fields); + dict_sys.unlock(); + dict_sys.load_sys_tables(); + + err = trx_lists_init_at_db_start(); + if (err != DB_SUCCESS) { + return srv_init_abort(err); + } + + if (recv_needed_recovery) { + trx_sys_print_mysql_binlog_offset(); + } + } else if (recv_needed_recovery) { + err = trx_lists_init_at_db_start(); + if (err != DB_SUCCESS) { + return srv_init_abort(err); + } trx_sys_print_mysql_binlog_offset(); } } From be1c4bd1bd2ab7f1506e0711043e5a0e2b8761bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 4 Dec 2023 11:17:46 +0200 Subject: [PATCH 375/477] Fix occasional failure of innodb.innodb-alter-tempfile --- mysql-test/suite/innodb/r/innodb-alter-tempfile.result | 2 -- mysql-test/suite/innodb/t/innodb-alter-tempfile.test | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-alter-tempfile.result b/mysql-test/suite/innodb/r/innodb-alter-tempfile.result index 4475abab066..00a210b85d5 100644 --- a/mysql-test/suite/innodb/r/innodb-alter-tempfile.result +++ b/mysql-test/suite/innodb/r/innodb-alter-tempfile.result @@ -44,8 +44,6 @@ set DEBUG_SYNC="now WAIT_FOR default_signal"; # restart disconnect con1; SHOW KEYS FROM t1; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Ignored -t1 1 f1 1 f1 A # NULL NULL BTREE NO DROP TABLE t1; # # MDEV-25503 InnoDB hangs on startup during recovery diff --git a/mysql-test/suite/innodb/t/innodb-alter-tempfile.test b/mysql-test/suite/innodb/t/innodb-alter-tempfile.test index 0ae116f58f0..2534f03dbec 100644 --- a/mysql-test/suite/innodb/t/innodb-alter-tempfile.test +++ b/mysql-test/suite/innodb/t/innodb-alter-tempfile.test @@ -65,8 +65,11 @@ set DEBUG_SYNC="now WAIT_FOR default_signal"; --let $shutdown_timeout=0 --source include/restart_mysqld.inc disconnect con1; ---replace_column 7 # +# This may occasionally display records for a corrupted index(f2). +# The original bug was about a crash during the execution of SHOW KEYS. +--disable_result_log SHOW KEYS FROM t1; +--enable_result_log DROP TABLE t1; remove_files_wildcard $datadir/test #sql-*.frm; From 1ac03fd9142905e6585b97214cb14690f478c6a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 4 Dec 2023 11:21:58 +0200 Subject: [PATCH 376/477] Fix occasional failure of encryption.corrupted_during_recovery --- mysql-test/suite/encryption/r/corrupted_during_recovery.result | 2 +- mysql-test/suite/encryption/t/corrupted_during_recovery.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/encryption/r/corrupted_during_recovery.result b/mysql-test/suite/encryption/r/corrupted_during_recovery.result index 356dce64f8d..7329999dd27 100644 --- a/mysql-test/suite/encryption/r/corrupted_during_recovery.result +++ b/mysql-test/suite/encryption/r/corrupted_during_recovery.result @@ -9,7 +9,7 @@ INSERT INTO t2 VALUES(2); SELECT * FROM t1; ERROR 42000: Unknown storage engine 'InnoDB' SELECT * FROM t1; -ERROR 42S02: Table 'test.t1' doesn't exist in engine +Got one of the listed errors SELECT * FROM t2; a 2 diff --git a/mysql-test/suite/encryption/t/corrupted_during_recovery.test b/mysql-test/suite/encryption/t/corrupted_during_recovery.test index bccac2bb182..d4048997a13 100644 --- a/mysql-test/suite/encryption/t/corrupted_during_recovery.test +++ b/mysql-test/suite/encryption/t/corrupted_during_recovery.test @@ -60,7 +60,7 @@ call mtr.add_suppression("InnoDB: Table `test`\\.`t1` is corrupted. Please drop let $restart_parameters=--innodb_force_recovery=1 --skip-innodb-buffer-pool-load-at-startup; --source include/restart_mysqld.inc ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_NO_SUCH_TABLE_IN_ENGINE,ER_TABLE_CORRUPT SELECT * FROM t1; SELECT * FROM t2; CHECK TABLE t2; From 2700d20b7c2c803142cc54aeb45188c6d4de3f5f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 4 Dec 2023 10:30:39 +0100 Subject: [PATCH 377/477] MDEV-32725 innodb.import_update_stats accesses uninitialized ib_table->stat_n_rows disable a failing test --- mysql-test/suite/innodb/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/innodb/disabled.def b/mysql-test/suite/innodb/disabled.def index 35c941f8af7..db2f066c41b 100644 --- a/mysql-test/suite/innodb/disabled.def +++ b/mysql-test/suite/innodb/disabled.def @@ -11,3 +11,4 @@ ############################################################################## create-index-debug : MDEV-13680 InnoDB may crash when btr_page_alloc() fails +import_update_stats: MDEV-32725 fails in MSAN, uninit access From 768a736174d6caf09df43e84b0c1b9ec52f1a301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 4 Dec 2023 11:47:19 +0200 Subject: [PATCH 378/477] MDEV-32899 instrumentation fixup dict_sys_t::lock(), dict_sys_t::freeze(): Assert that the current thread is not holding dict_sys.latch in any mode. The SUX lock is reentrant, but the simpler RW lock that we use in non-debug builds is not. --- storage/innobase/include/dict0dict.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index a0ba7d6ff5c..e4fc58007cf 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1512,6 +1512,7 @@ public: void lock(SRW_LOCK_ARGS(const char *file, unsigned line)) { #ifdef UNIV_DEBUG + ut_ad(!latch.have_any()); if (!latch.x_lock_try()) #else if (!latch.wr_lock_try()) @@ -1540,6 +1541,7 @@ public: void freeze() { # ifdef UNIV_DEBUG + ut_ad(!latch.have_any()); latch.s_lock(); # else latch.rd_lock(); From 9a8b1f2ac41657d11bec5efed7ca45acb22130a1 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 4 Dec 2023 12:15:30 +0100 Subject: [PATCH 379/477] MDEV-32926 mysql_install_db_win fails on buildbot - Do not suppress mysql_install_db.exe output in case of error - Add --verbose-bootstrap to get errors coming from mysqld --boostrap --- mysql-test/main/mysql_install_db_win.test | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/mysql_install_db_win.test b/mysql-test/main/mysql_install_db_win.test index 3f0256e860e..5c90779c1a3 100644 --- a/mysql-test/main/mysql_install_db_win.test +++ b/mysql-test/main/mysql_install_db_win.test @@ -22,7 +22,9 @@ rmdir $ddir; # MDEV-23052 # 1. mysql_install_db works on existing, empty directory mkdir $ddir; -exec $MYSQL_INSTALL_DB_EXE --datadir=$ddir --password=foo -R > /dev/null; +disable_result_log; +exec $MYSQL_INSTALL_DB_EXE --datadir=$ddir --password=foo -R --verbose-bootstrap; +enable_result_log; rmdir $ddir; # 2. mysql_install_db rejects existing, non-empty directory, and does not From b97f4c340ead53c42ec674da19b420e57bf40ddc Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Mon, 4 Dec 2023 20:34:45 +0300 Subject: [PATCH 380/477] Followup for fix for MDEV-20169: enable main.partition_innodb --- mysql-test/main/disabled.def | 1 - mysql-test/main/partition_innodb.result | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/disabled.def b/mysql-test/main/disabled.def index 02104f6a680..8ba5b271c2b 100644 --- a/mysql-test/main/disabled.def +++ b/mysql-test/main/disabled.def @@ -17,4 +17,3 @@ mysql_embedded : Bug#12561297 2011-05-14 Anitha Dependent on PB2 chang file_contents : MDEV-6526 these files are not installed anymore max_statement_time : cannot possibly work, depends on timing partition_open_files_limit : open_files_limit check broken by MDEV-18360 -partition_innodb : Waiting for fix MDEV-20169 diff --git a/mysql-test/main/partition_innodb.result b/mysql-test/main/partition_innodb.result index 669b62f0269..072786931ae 100644 --- a/mysql-test/main/partition_innodb.result +++ b/mysql-test/main/partition_innodb.result @@ -84,6 +84,8 @@ DROP TABLE t1; SET @old_innodb_thread_concurrency := @@innodb_thread_concurrency; SET @old_innodb_thread_sleep_delay := @@innodb_thread_sleep_delay; SET GLOBAL innodb_thread_concurrency = 1; +Warnings: +Warning 138 The parameter innodb_thread_concurrency is deprecated and has no effect. CREATE TABLE t1 (user_num BIGINT, hours SMALLINT, @@ -117,7 +119,11 @@ connection con1; disconnect con1; connection default; SET GLOBAL innodb_thread_concurrency = @old_innodb_thread_concurrency; +Warnings: +Warning 138 The parameter innodb_thread_concurrency is deprecated and has no effect. SET GLOBAL innodb_thread_sleep_delay = @old_innodb_thread_sleep_delay; +Warnings: +Warning 138 The parameter innodb_thread_sleep_delay is deprecated and has no effect. DROP TABLE t1; # # Bug#50418: DROP PARTITION does not interact with transactions From ddd5449c5794b5afc2a53550af74fc630a363723 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 5 Dec 2023 14:33:16 +1100 Subject: [PATCH 381/477] [fixup] post-merge spider fixup MDEV-32524: a couple missed magic numbers MDEV-26247: a couple missed goto statements that could lead to memory leak --- storage/spider/spd_db_conn.cc | 2 +- storage/spider/spd_db_mysql.cc | 2 +- storage/spider/spd_group_by_handler.cc | 6 ++---- storage/spider/spd_include.h | 2 ++ 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index ff9dadde7d0..48d28198e1f 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -4786,7 +4786,7 @@ int spider_db_store_result_for_reuse_cursor( THD *thd = current_thd; char buf[MAX_FIELD_WIDTH]; spider_string tmp_str(buf, MAX_FIELD_WIDTH, &my_charset_bin); - tmp_str.init_calc_mem(120); + tmp_str.init_calc_mem(SPD_MID_DB_STORE_RESULT_FOR_REUSE_CURSOR_1); DBUG_PRINT("info",("spider store result to temporary table")); DBUG_ASSERT(!current->result_tmp_tbl); diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 8d448c77133..8b8641dda04 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -3364,7 +3364,7 @@ int spider_db_mbase::set_loop_check( spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); DBUG_ENTER("spider_db_mbase::set_loop_check"); DBUG_PRINT("info",("spider this=%p", this)); - sql_str.init_calc_mem(270); + sql_str.init_calc_mem(SPD_MID_DB_MBASE_SET_LOOP_CHECK_1); while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( &conn->loop_check_queue, 0))) { diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index f1d303ad343..19e9e294b6e 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -1719,8 +1719,7 @@ group_by_handler *spider_create_group_by_handler( if (spider->dml_init()) { DBUG_PRINT("info",("spider can not init for dml")); - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } for ( roop_count = spider_conn_link_idx_next(share->link_statuses, @@ -1792,8 +1791,7 @@ group_by_handler *spider_create_group_by_handler( if (spider->dml_init()) { DBUG_PRINT("info",("spider can not init for dml")); - delete fields; - DBUG_RETURN(NULL); + goto skip_free_fields; } for ( roop_count = spider_conn_link_idx_next(share->link_statuses, diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 4cebb9b667a..6c11bef3f84 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -377,6 +377,7 @@ enum spider_malloc_id { SPD_MID_DB_MBASE_RESULT_FETCH_ROW_FROM_TMP_TABLE_3, SPD_MID_DB_MBASE_ROW_APPEND_ESCAPED_TO_STR_1, SPD_MID_DB_MBASE_ROW_CLONE_1, + SPD_MID_DB_MBASE_SET_LOOP_CHECK_1, SPD_MID_DB_MBASE_SET_SQL_MODE_1, SPD_MID_DB_MBASE_SET_TIME_ZONE_1, SPD_MID_DB_MBASE_SET_WAIT_TIMEOUT_1, @@ -412,6 +413,7 @@ enum spider_malloc_id { SPD_MID_DB_STORE_RESULT_3, SPD_MID_DB_STORE_RESULT_4, SPD_MID_DB_STORE_RESULT_5, + SPD_MID_DB_STORE_RESULT_FOR_REUSE_CURSOR_1, SPD_MID_DB_UDF_COPY_TABLES_1, SPD_MID_DB_UDF_PING_TABLE_1, SPD_MID_DB_UDF_PING_TABLE_2, From 9d15c3e35a30ad4801f00632c194fe2850cd79f1 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 15 Nov 2023 14:27:56 +1100 Subject: [PATCH 382/477] MDEV-29020 Reduce default spider bg sts/crd thread counts --- storage/spider/spd_param.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/spider/spd_param.cc b/storage/spider/spd_param.cc index b77acef57fe..5eaf9518048 100644 --- a/storage/spider/spd_param.cc +++ b/storage/spider/spd_param.cc @@ -2701,7 +2701,7 @@ static MYSQL_SYSVAR_UINT( "Static thread count of table sts", NULL, NULL, - 10, + 1, 1, 4294967295U, 0 @@ -2720,7 +2720,7 @@ static MYSQL_SYSVAR_UINT( "Static thread count of table crd", NULL, NULL, - 10, + 1, 1, 4294967295U, 0 From f074223ae730cfa12511090f2257d9779e867181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 5 Dec 2023 12:31:29 +0200 Subject: [PATCH 383/477] MDEV-32068 Some calls to buf_read_ahead_linear() seem to be useless The linear read-ahead (enabled by nonzero innodb_read_ahead_threshold) works best if index leaf pages or undo log pages have been allocated on adjacent page numbers. The read-ahead is assumed not to be helpful in other types of page accesses, such as non-leaf index pages. buf_page_get_low(): Do not invoke buf_page_t::set_accessed(), buf_page_make_young_if_needed(), or buf_read_ahead_linear(). We will invoke them in those callers of buf_page_get_gen() or buf_page_get() where it makes sense: the access is not one-time-on-startup and the page and not going to be freed soon. btr_copy_blob_prefix(), btr_pcur_move_to_next_page(), trx_undo_get_prev_rec_from_prev_page(), trx_undo_get_first_rec(), btr_cur_t::search_leaf(), btr_cur_t::open_leaf(): Invoke buf_read_ahead_linear(). We will not invoke linear read-ahead in functions that would essentially allocate or free pages, because pages that are freshly allocated are expected to be initialized by buf_page_create() and not read from the data file. Likewise, freeing pages should not involve accessing any sibling pages, except for freeing singly-linked lists of BLOB pages. We will not invoke read-ahead in btr_cur_t::pessimistic_search_leaf() or in a pessimistic operation of btr_cur_t::open_leaf(), because it is assumed that pessimistic operations should be preceded by optimistic operations, which should already have invoked read-ahead. buf_page_make_young_if_needed(): Invoke also buf_page_t::set_accessed() and return the result. btr_cur_nonleaf_make_young(): Like buf_page_make_young_if_needed(), but do not invoke buf_page_t::set_accessed(). Reviewed by: Vladislav Lesin Tested by: Matthias Leich --- storage/innobase/btr/btr0btr.cc | 11 ++++++- storage/innobase/btr/btr0cur.cc | 51 +++++++++++++++++++----------- storage/innobase/btr/btr0pcur.cc | 17 +++++++--- storage/innobase/btr/btr0sea.cc | 1 - storage/innobase/buf/buf0buf.cc | 14 -------- storage/innobase/buf/buf0lru.cc | 8 +++++ storage/innobase/dict/dict0boot.cc | 5 ++- storage/innobase/gis/gis0sea.cc | 6 ++++ storage/innobase/ibuf/ibuf0ibuf.cc | 14 ++++++-- storage/innobase/include/btr0btr.h | 4 ++- storage/innobase/include/buf0buf.h | 11 ------- storage/innobase/include/buf0lru.h | 10 ++++++ storage/innobase/row/row0merge.cc | 2 ++ storage/innobase/row/row0purge.cc | 1 - storage/innobase/row/row0sel.cc | 1 + storage/innobase/row/row0undo.cc | 2 ++ storage/innobase/trx/trx0rec.cc | 3 +- storage/innobase/trx/trx0rseg.cc | 9 ++++-- storage/innobase/trx/trx0trx.cc | 1 + storage/innobase/trx/trx0undo.cc | 41 ++++++++++++++++++------ 20 files changed, 146 insertions(+), 66 deletions(-) diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 1e4e15a5433..5e106fbc2cd 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -216,10 +216,11 @@ ATTRIBUTE_COLD void btr_decryption_failed(const dict_index_t &index) @param[in] merge whether change buffer merge should be attempted @param[in,out] mtr mini-transaction @param[out] err error code +@param[out] first set if this is a first-time access to the page @return block */ buf_block_t *btr_block_get(const dict_index_t &index, uint32_t page, rw_lock_type_t mode, bool merge, - mtr_t *mtr, dberr_t *err) + mtr_t *mtr, dberr_t *err, bool *first) { ut_ad(mode != RW_NO_LATCH); dberr_t local_err; @@ -242,6 +243,8 @@ buf_block_t *btr_block_get(const dict_index_t &index, *err= DB_PAGE_CORRUPTED; block= nullptr; } + else if (!buf_page_make_young_if_needed(&block->page) && first) + *first= true; } else if (*err == DB_DECRYPTION_FAILED) btr_decryption_failed(index); @@ -302,6 +305,8 @@ btr_root_block_get( *err= DB_CORRUPTION; block= nullptr; } + else + buf_page_make_young_if_needed(&block->page); } else if (*err == DB_DECRYPTION_FAILED) btr_decryption_failed(*index); @@ -553,8 +558,11 @@ btr_page_alloc_for_ibuf( root->page.frame)), 0, RW_X_LATCH, nullptr, BUF_GET, mtr, err); if (new_block) + { + buf_page_make_young_if_needed(&new_block->page); *err= flst_remove(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, new_block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr); + } ut_d(if (*err == DB_SUCCESS) flst_validate(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr)); return new_block; @@ -1352,6 +1360,7 @@ btr_write_autoinc(dict_index_t* index, ib_uint64_t autoinc, bool reset) if (buf_block_t *root= buf_page_get(page_id_t(space->id, index->page), space->zip_size(), RW_SX_LATCH, &mtr)) { + buf_page_make_young_if_needed(&root->page); mtr.set_named_space(space); page_set_autoinc(root, autoinc, &mtr, reset); } diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index b05c9db787b..dc8e9159e6e 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -1263,7 +1263,7 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode, page_cur.block= block; ut_ad(block == mtr->at_savepoint(block_savepoint)); - ut_ad(rw_latch != RW_NO_LATCH); + const bool not_first_access{buf_page_make_young_if_needed(&block->page)}; #ifdef UNIV_ZIP_DEBUG if (const page_zip_des_t *page_zip= buf_block_get_page_zip(block)) ut_a(page_zip_validate(page_zip, block->page.frame, index())); @@ -1542,6 +1542,9 @@ release_tree: case BTR_SEARCH_PREV: /* btr_pcur_move_to_prev() */ ut_ad(rw_latch == RW_S_LATCH || rw_latch == RW_X_LATCH); + if (!not_first_access) + buf_read_ahead_linear(page_id, zip_size, false); + if (page_has_prev(block->page.frame) && page_rec_is_first(page_cur.rec, block->page.frame)) { @@ -1581,6 +1584,8 @@ release_tree: buf_mode= btr_op == BTR_DELETE_OP ? BUF_GET_IF_IN_POOL_OR_WATCH : BUF_GET_IF_IN_POOL; + else if (!not_first_access) + buf_read_ahead_linear(page_id, zip_size, false); break; case BTR_MODIFY_TREE: ut_ad(rw_latch == RW_X_LATCH); @@ -1614,6 +1619,14 @@ ATTRIBUTE_COLD void mtr_t::index_lock_upgrade() slot.type= MTR_MEMO_X_LOCK; } +/** Mark a non-leaf page "least recently used", but avoid invoking +buf_page_t::set_accessed(), because we do not want linear read-ahead */ +static void btr_cur_nonleaf_make_young(buf_page_t *bpage) +{ + if (UNIV_UNLIKELY(buf_page_peek_if_too_old(bpage))) + buf_page_make_young(bpage); +} + ATTRIBUTE_COLD dberr_t btr_cur_t::pessimistic_search_leaf(const dtuple_t *tuple, page_cur_mode_t mode, mtr_t *mtr) @@ -1716,6 +1729,8 @@ dberr_t btr_cur_t::pessimistic_search_leaf(const dtuple_t *tuple, if (height != btr_page_get_level(block->page.frame)) goto corrupted; + btr_cur_nonleaf_make_young(&block->page); + #ifdef UNIV_ZIP_DEBUG const page_zip_des_t *page_zip= buf_block_get_page_zip(block); ut_a(!page_zip || page_zip_validate(page_zip, block->page.frame, index())); @@ -1802,6 +1817,8 @@ search_loop: btr_decryption_failed(*index); goto func_exit; } + else + btr_cur_nonleaf_make_young(&block->page); #ifdef UNIV_ZIP_DEBUG if (const page_zip_des_t *page_zip= buf_block_get_page_zip(block)) @@ -1937,18 +1954,15 @@ index_locked: ut_ad(n_blocks < BTR_MAX_LEVELS); ut_ad(savepoint + n_blocks == mtr->get_savepoint()); + bool first_access= false; buf_block_t* block= btr_block_get(*index, page, height ? upper_rw_latch : root_leaf_rw_latch, - !height, mtr, &err); + !height, mtr, &err, &first_access); ut_ad(!block == (err != DB_SUCCESS)); if (!block) - { - if (err == DB_DECRYPTION_FAILED) - btr_decryption_failed(*index); break; - } if (first) page_cur_set_before_first(block, &page_cur); @@ -2032,10 +2046,16 @@ index_locked: offsets= rec_get_offsets(page_cur.rec, index, offsets, 0, ULINT_UNDEFINED, &heap); + page= btr_node_ptr_get_child_page_no(page_cur.rec, offsets); ut_ad(latch_mode != BTR_MODIFY_TREE || upper_rw_latch == RW_X_LATCH); - if (latch_mode != BTR_MODIFY_TREE); + if (latch_mode != BTR_MODIFY_TREE) + { + if (!height && first && first_access) + buf_read_ahead_linear(page_id_t(block->page.id().space(), page), + block->page.zip_size(), false); + } else if (btr_cur_need_opposite_intention(block->page, index->is_clust(), lock_intention, node_ptr_max_size, compress_limit, @@ -2073,7 +2093,6 @@ index_locked: } /* Go to the child node */ - page= btr_node_ptr_get_child_page_no(page_cur.rec, offsets); n_blocks++; } @@ -3840,22 +3859,14 @@ btr_cur_pess_upd_restore_supremum( const page_id_t block_id{block->page.id()}; const page_id_t prev_id(block_id.space(), prev_page_no); - dberr_t err; buf_block_t* prev_block - = buf_page_get_gen(prev_id, 0, RW_NO_LATCH, nullptr, - BUF_PEEK_IF_IN_POOL, mtr, &err); - /* Since we already held an x-latch on prev_block, it must - be available and not be corrupted unless the buffer pool got - corrupted somehow. */ + = mtr->get_already_latched(prev_id, MTR_MEMO_PAGE_X_FIX); if (UNIV_UNLIKELY(!prev_block)) { - return err; + return DB_CORRUPTION; } ut_ad(!memcmp_aligned<4>(prev_block->page.frame + FIL_PAGE_NEXT, block->page.frame + FIL_PAGE_OFFSET, 4)); - /* We must already have an x-latch on prev_block! */ - ut_ad(mtr->memo_contains_flagged(prev_block, MTR_MEMO_PAGE_X_FIX)); - lock_rec_reset_and_inherit_gap_locks(*prev_block, block_id, PAGE_HEAP_NO_SUPREMUM, page_rec_get_heap_no(rec)); @@ -6664,6 +6675,10 @@ btr_copy_blob_prefix( mtr.commit(); return copied_len; } + if (!buf_page_make_young_if_needed(&block->page)) { + buf_read_ahead_linear(id, 0, false); + } + page = buf_block_get_frame(block); blob_header = page + offset; diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 01f8b2671b0..0be12523ae1 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -25,9 +25,10 @@ Created 2/23/1996 Heikki Tuuri *******************************************************/ #include "btr0pcur.h" -#include "ut0byte.h" +#include "buf0rea.h" #include "rem0cmp.h" #include "trx0trx.h" +#include "ibuf0ibuf.h" /**************************************************************//** Resets a persistent cursor object, freeing ::old_rec_buf if it is @@ -261,13 +262,15 @@ static bool btr_pcur_optimistic_latch_leaves(buf_block_t *block, buf_page_get_gen(page_id_t(id.space(), left_page_no), zip_size, mode, nullptr, BUF_GET_POSSIBLY_FREED, mtr); - if (left_block && - btr_page_get_next(left_block->page.frame) != id.page_no()) + if (!left_block); + else if (btr_page_get_next(left_block->page.frame) != id.page_no()) { release_left_block: mtr->release_last_page(); return false; } + else + buf_page_make_young_if_needed(&left_block->page); } if (buf_page_optimistic_get(mode, block, pcur->modify_clock, mtr)) @@ -539,10 +542,11 @@ btr_pcur_move_to_next_page( } dberr_t err; + bool first_access = false; buf_block_t* next_block = btr_block_get( *cursor->index(), next_page_no, rw_lock_type_t(cursor->latch_mode & (RW_X_LATCH | RW_S_LATCH)), - page_is_leaf(page), mtr, &err); + page_is_leaf(page), mtr, &err, &first_access); if (UNIV_UNLIKELY(!next_block)) { return err; @@ -561,6 +565,11 @@ btr_pcur_move_to_next_page( const auto s = mtr->get_savepoint(); mtr->rollback_to_savepoint(s - 2, s - 1); + if (first_access) { + buf_read_ahead_linear(next_block->page.id(), + next_block->zip_size(), + ibuf_inside(mtr)); + } return DB_SUCCESS; } diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 6905e631e5d..5d99e24273b 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -1141,7 +1141,6 @@ block_and_ahi_release_and_fail: } block->page.fix(); - block->page.set_accessed(); buf_page_make_young_if_needed(&block->page); static_assert(ulint{MTR_MEMO_PAGE_S_FIX} == ulint{BTR_SEARCH_LEAF}, ""); diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 77b27d9b1ba..a6004a09084 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2268,7 +2268,6 @@ lookup: ut_ad(s < buf_page_t::READ_FIX || s >= buf_page_t::WRITE_FIX); } - bpage->set_accessed(); buf_page_make_young_if_needed(bpage); #ifdef UNIV_DEBUG @@ -2895,18 +2894,6 @@ get_latch_valid: ut_ad(page_id_t(page_get_space_id(block->page.frame), page_get_page_no(block->page.frame)) == page_id); - - if (mode == BUF_GET_POSSIBLY_FREED - || mode == BUF_PEEK_IF_IN_POOL) { - return block; - } - - const bool not_first_access{block->page.set_accessed()}; - buf_page_make_young_if_needed(&block->page); - if (!not_first_access) { - buf_read_ahead_linear(page_id, block->zip_size(), - ibuf_inside(mtr)); - } } return block; @@ -3079,7 +3066,6 @@ bool buf_page_optimistic_get(ulint rw_latch, buf_block_t *block, block->page.fix(); ut_ad(!block->page.is_read_fixed()); - block->page.set_accessed(); buf_page_make_young_if_needed(&block->page); mtr->memo_push(block, mtr_memo_type_t(rw_latch)); } diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 6c86114a8d0..b80b99a9b12 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -789,6 +789,14 @@ void buf_page_make_young(buf_page_t *bpage) mysql_mutex_unlock(&buf_pool.mutex); } +bool buf_page_make_young_if_needed(buf_page_t *bpage) +{ + const bool not_first{bpage->set_accessed()}; + if (UNIV_UNLIKELY(buf_page_peek_if_too_old(bpage))) + buf_page_make_young(bpage); + return not_first; +} + /** Try to free a block. If bpage is a descriptor of a compressed-only ROW_FORMAT=COMPRESSED page, the buf_page_t object will be freed as well. The caller must hold buf_pool.mutex. diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc index e57121041d5..7b7fab82fd5 100644 --- a/storage/innobase/dict/dict0boot.cc +++ b/storage/innobase/dict/dict0boot.cc @@ -42,7 +42,10 @@ static constexpr page_id_t hdr_page_id{DICT_HDR_SPACE, DICT_HDR_PAGE_NO}; static buf_block_t *dict_hdr_get(mtr_t *mtr) { /* We assume that the DICT_HDR page is always readable and available. */ - return buf_page_get_gen(hdr_page_id, 0, RW_X_LATCH, nullptr, BUF_GET, mtr); + buf_block_t *b= + buf_page_get_gen(hdr_page_id, 0, RW_X_LATCH, nullptr, BUF_GET, mtr); + buf_page_make_young_if_needed(&b->page); + return b; } /**********************************************************************//** diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index 8ca8681bce9..0df9a7ded9a 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -304,6 +304,8 @@ rtr_pcur_getnext_from_path( break; } + buf_page_make_young_if_needed(&block->page); + page = buf_block_get_frame(block); page_ssn = page_get_ssn_id(page); @@ -683,6 +685,8 @@ dberr_t rtr_search_to_nth_level(ulint level, const dtuple_t *tuple, return err; } + buf_page_make_young_if_needed(&block->page); + const page_t *page= buf_block_get_frame(block); #ifdef UNIV_ZIP_DEBUG if (rw_latch != RW_NO_LATCH) { @@ -1703,6 +1707,8 @@ corrupted: goto func_exit; } + buf_page_make_young_if_needed(&page_cursor->block->page); + /* Get the page SSN */ page = buf_block_get_frame(page_cursor->block); page_ssn = page_get_ssn_id(page); diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 8226ebbfd54..a8b180401ba 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -309,8 +309,13 @@ ibuf_header_page_get( buf_block_t* block = buf_page_get( page_id_t(IBUF_SPACE_ID, FSP_IBUF_HEADER_PAGE_NO), 0, RW_X_LATCH, mtr); + if (UNIV_UNLIKELY(!block)) { + return nullptr; + } - return block ? block->page.frame : nullptr; + buf_page_make_young_if_needed(&block->page); + + return block->page.frame; } /** Acquire the change buffer root page. @@ -326,7 +331,12 @@ static buf_block_t *ibuf_tree_root_get(mtr_t *mtr, dberr_t *err= nullptr) buf_block_t *block= buf_page_get_gen(page_id_t{IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO}, 0, RW_SX_LATCH, nullptr, BUF_GET, mtr, err); - ut_ad(!block || ibuf.empty == page_is_empty(block->page.frame)); + if (block) + { + ut_ad(ibuf.empty == page_is_empty(block->page.frame)); + buf_page_make_young_if_needed(&block->page); + } + return block; } diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index 5a0401fad85..b42c543c095 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -89,10 +89,12 @@ ATTRIBUTE_COLD void btr_decryption_failed(const dict_index_t &index); @param[in] merge whether change buffer merge should be attempted @param[in,out] mtr mini-transaction @param[out] err error code +@param[out] first set if this is a first-time access to the page @return block */ buf_block_t *btr_block_get(const dict_index_t &index, uint32_t page, rw_lock_type_t mode, bool merge, - mtr_t *mtr, dberr_t *err= nullptr); + mtr_t *mtr, dberr_t *err= nullptr, + bool *first= nullptr); /**************************************************************//** Gets the index id field of a page. diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index dd1c07c1ee0..5626af17bb7 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -262,8 +262,6 @@ buf_block_t* buf_page_create_deferred(uint32_t space_id, ulint zip_size, mtr_t *mtr, buf_block_t *free_block); -/** Move a block to the start of the LRU list. */ -void buf_page_make_young(buf_page_t *bpage); /** Mark the page status as FREED for the given tablespace and page number. @param[in,out] space tablespace @param[in] page page number @@ -285,15 +283,6 @@ there is danger of dropping from the buffer pool. @return true if bpage should be made younger */ inline bool buf_page_peek_if_too_old(const buf_page_t *bpage); -/** Move a page to the start of the buffer pool LRU list if it is too old. -@param[in,out] bpage buffer pool page */ -inline void buf_page_make_young_if_needed(buf_page_t *bpage) -{ - if (UNIV_UNLIKELY(buf_page_peek_if_too_old(bpage))) { - buf_page_make_young(bpage); - } -} - /********************************************************************//** Increments the modify clock of a frame by 1. The caller must (1) own the buf_pool.mutex and block bufferfix count has to be zero, (2) or own an x-lock diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h index aec08e77f54..28410276217 100644 --- a/storage/innobase/include/buf0lru.h +++ b/storage/innobase/include/buf0lru.h @@ -108,6 +108,16 @@ buf_LRU_add_block( blocks in the LRU list, else put to the start; if the LRU list is very short, added to the start regardless of this parameter */ + +/** Move a block to the start of the buf_pool.LRU list. +@param bpage buffer pool page */ +void buf_page_make_young(buf_page_t *bpage); +/** Flag a page accessed in buf_pool and move it to the start of buf_pool.LRU +if it is too old. +@param bpage buffer pool page +@return whether this is not the first access */ +bool buf_page_make_young_if_needed(buf_page_t *bpage); + /******************************************************************//** Adds a block to the LRU list of decompressed zip pages. */ void diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 1ceaf4d649f..7642326f8b7 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -2051,6 +2051,8 @@ end_of_index: goto err_exit; } + buf_page_make_young_if_needed(&block->page); + page_cur_set_before_first(block, cur); if (!page_cur_move_to_next(cur) || page_cur_is_after_last(cur)) { diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index c380c4901b9..4533b7166b7 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -822,7 +822,6 @@ skip_secondaries: buf_page_get(page_id_t(rseg.space->id, page_no), 0, RW_X_LATCH, &mtr)) { - block->page.set_accessed(); buf_page_make_young_if_needed(&block->page); byte* data_field = block->page.frame diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 5c9e5e6354d..94c6673e731 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -1223,6 +1223,7 @@ re_scan: if (!cur_block) { goto func_end; } + buf_page_make_young_if_needed(&cur_block->page); } else { mtr->start(); goto func_end; diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc index 8a1041c8576..f14673c173f 100644 --- a/storage/innobase/row/row0undo.cc +++ b/storage/innobase/row/row0undo.cc @@ -318,6 +318,8 @@ static buf_block_t* row_undo_rec_get(undo_node_t* node) return nullptr; } + buf_page_make_young_if_needed(&undo_page->page); + uint16_t offset = undo->top_offset; buf_block_t* prev_page = undo_page; diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 511bad1fb47..e05c018c734 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -2062,9 +2062,10 @@ trx_undo_get_undo_rec_low( mtr.start(); trx_undo_rec_t *undo_rec= nullptr; - if (const buf_block_t* undo_page= + if (buf_block_t* undo_page= buf_page_get(page_id_t(rseg->space->id, page_no), 0, RW_S_LATCH, &mtr)) { + buf_page_make_young_if_needed(&undo_page->page); undo_rec= undo_page->page.frame + offset; const size_t end= mach_read_from_2(undo_rec); if (UNIV_UNLIKELY(end <= offset || diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 0d7b96e9280..136294ae48b 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -295,8 +295,13 @@ buf_block_t *trx_rseg_t::get(mtr_t *mtr, dberr_t *err) const if (err) *err= DB_TABLESPACE_NOT_FOUND; return nullptr; } - return buf_page_get_gen(page_id(), 0, RW_X_LATCH, nullptr, - BUF_GET, mtr, err); + + buf_block_t *block= buf_page_get_gen(page_id(), 0, RW_X_LATCH, nullptr, + BUF_GET, mtr, err); + if (UNIV_LIKELY(block != nullptr)) + buf_page_make_young_if_needed(&block->page); + + return block; } /** Upgrade a rollback segment header page to MariaDB 10.3 format. diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 1bd24870a0c..c99dd2110d4 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -582,6 +582,7 @@ static dberr_t trx_resurrect_table_locks(trx_t *trx, const trx_undo_t &undo) undo.top_page_no), 0, RW_S_LATCH, nullptr, BUF_GET, &mtr, &err)) { + buf_page_make_young_if_needed(&block->page); buf_block_t *undo_block= block; const trx_undo_rec_t *undo_rec= block->page.frame + undo.top_offset; diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index 63da2982fec..def47686da2 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -25,8 +25,8 @@ Created 3/26/1996 Heikki Tuuri *******************************************************/ #include "trx0undo.h" +#include "buf0rea.h" #include "fsp0fsp.h" -#include "mach0data.h" #include "mtr0log.h" #include "srv0mon.h" #include "srv0srv.h" @@ -178,8 +178,12 @@ trx_undo_get_prev_rec_from_prev_page(buf_block_t *&block, uint16_t rec, block= buf_page_get(page_id_t(block->page.id().space(), prev_page_no), 0, shared ? RW_S_LATCH : RW_X_LATCH, mtr); + if (UNIV_UNLIKELY(!block)) + return nullptr; - return block ? trx_undo_page_get_last_rec(block, page_no, offset) : nullptr; + if (!buf_page_make_young_if_needed(&block->page)) + buf_read_ahead_linear(block->page.id(), 0, false); + return trx_undo_page_get_last_rec(block, page_no, offset); } /** Get the previous undo log record. @@ -268,12 +272,16 @@ 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) { - block= buf_page_get_gen(page_id_t{space.id, page_no}, 0, mode, - nullptr, BUF_GET, mtr, err); + buf_block_t *b= buf_page_get_gen(page_id_t{space.id, page_no}, 0, mode, + nullptr, BUF_GET, mtr, err); + block= b; if (!block) return nullptr; - if (trx_undo_rec_t *rec= trx_undo_page_get_first_rec(block, page_no, offset)) + if (!buf_page_make_young_if_needed(&b->page)) + buf_read_ahead_linear(b->page.id(), 0, false); + + if (trx_undo_rec_t *rec= trx_undo_page_get_first_rec(b, page_no, offset)) return rec; return trx_undo_get_next_rec_from_next_page(block, page_no, offset, mode, @@ -663,6 +671,8 @@ buf_block_t *trx_undo_add_page(trx_undo_t *undo, mtr_t *mtr, dberr_t *err) 0, RW_X_LATCH, nullptr, BUF_GET, mtr, err); if (!header_block) goto func_exit; + buf_page_make_young_if_needed(&header_block->page); + *err= fsp_reserve_free_extents(&n_reserved, rseg->space, 1, FSP_UNDO, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) @@ -732,6 +742,8 @@ trx_undo_free_page( return FIL_NULL; } + buf_page_make_young_if_needed(&header_block->page); + *err = flst_remove(header_block, TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST, undo_block, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr); @@ -1271,6 +1283,8 @@ trx_undo_reuse_cached(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** pundo, return NULL; } + buf_page_make_young_if_needed(&block->page); + UT_LIST_REMOVE(rseg->undo_cached, undo); *pundo = undo; @@ -1305,19 +1319,24 @@ trx_undo_assign(trx_t* trx, dberr_t* err, mtr_t* mtr) ut_ad(mtr->get_log_mode() == MTR_LOG_ALL); trx_undo_t* undo = trx->rsegs.m_redo.undo; + buf_block_t* block; if (undo) { - return buf_page_get_gen( + block = buf_page_get_gen( page_id_t(undo->rseg->space->id, undo->last_page_no), 0, RW_X_LATCH, undo->guess_block, BUF_GET, mtr, err); + if (UNIV_LIKELY(block != nullptr)) { + buf_page_make_young_if_needed(&block->page); + } + return block; } *err = DB_SUCCESS; trx_rseg_t* rseg = trx->rsegs.m_redo.rseg; rseg->latch.wr_lock(SRW_LOCK_CALL); - buf_block_t* block = trx_undo_reuse_cached( + block = trx_undo_reuse_cached( trx, rseg, &trx->rsegs.m_redo.undo, mtr, err); if (!block) { @@ -1358,12 +1377,17 @@ trx_undo_assign_low(trx_t *trx, trx_rseg_t *rseg, trx_undo_t **undo, : &trx->rsegs.m_redo.undo)); ut_ad(mtr->get_log_mode() == (is_temp ? MTR_LOG_NO_REDO : MTR_LOG_ALL)); + buf_block_t* block; if (*undo) { - return buf_page_get_gen( + block = buf_page_get_gen( page_id_t(rseg->space->id, (*undo)->last_page_no), 0, RW_X_LATCH, (*undo)->guess_block, BUF_GET, mtr, err); + if (UNIV_LIKELY(block != nullptr)) { + buf_page_make_young_if_needed(&block->page); + } + return block; } DBUG_EXECUTE_IF( @@ -1373,7 +1397,6 @@ trx_undo_assign_low(trx_t *trx, trx_rseg_t *rseg, trx_undo_t **undo, *err = DB_SUCCESS; rseg->latch.wr_lock(SRW_LOCK_CALL); - buf_block_t* block; if (is_temp) { ut_ad(!UT_LIST_GET_LEN(rseg->undo_cached)); } else { From dc7138cbed7150f473dd5f74be71003f24c1083e Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Thu, 30 Nov 2023 08:45:11 +0100 Subject: [PATCH 384/477] galera: temporarily disabling problematic tests --- mysql-test/suite/galera/disabled.def | 4 ++++ mysql-test/suite/galera_3nodes/disabled.def | 3 +++ 2 files changed, 7 insertions(+) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index c5412874929..9fcc1f18fd4 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -22,3 +22,7 @@ galera_as_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsr galera_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() galera_bf_lock_wait : MDEV-32781 galera_bf_lock_wait test failed galera_sst_mysqldump_with_key : MDEV-32782 galera_sst_mysqldump_with_key test failed +mdev-31285 : MDEV-25089 Assertion `error.len > 0' failed in galera::ReplicatorSMM::handle_apply_error() +galera_var_ignore_apply_errors : MENT-1997 galera_var_ignore_apply_errors test freezes +MW-402 : temporarily disabled at the request of Codership +MDEV-22232 : temporarily disabled at the request of Codership diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index 2cec93fd3b7..730f98667e6 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -13,3 +13,6 @@ galera_2_cluster : MDEV-32631 galera_2_cluster: before_rollback(): Assertion `0' failed galera_gtid_2_cluster : MDEV-32633 galera_gtid_2_cluster: Assertion `thd->wsrep_next_trx_id() != (0x7fffffffffffffffLL * 2ULL + 1)' galera_ssl_reload : MDEV-32778 galera_ssl_reload failed with warning message +galera_ipv6_mariabackup : temporarily disabled at the request of Codership +galera_pc_bootstrap : temporarily disabled at the request of Codership +galera_ipv6_mariabackup_section : temporarily disabled at the request of Codership From 6d9c9d92cc518fe429bd4aa866ad0655bb56c11e Mon Sep 17 00:00:00 2001 From: Denis Protivensky Date: Mon, 27 Nov 2023 11:45:34 +0300 Subject: [PATCH 385/477] MDEV-32938: DDL must check if not aborted before entering TOI Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/MDEV-32938.result | 21 ++++++++ mysql-test/suite/galera/t/MDEV-32938.test | 57 +++++++++++++++++++++ sql/sql_alter.cc | 19 +++---- sql/wsrep_mysqld.cc | 31 ++++++++++- 4 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 mysql-test/suite/galera/r/MDEV-32938.result create mode 100644 mysql-test/suite/galera/t/MDEV-32938.test diff --git a/mysql-test/suite/galera/r/MDEV-32938.result b/mysql-test/suite/galera/r/MDEV-32938.result new file mode 100644 index 00000000000..5e310eb7843 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-32938.result @@ -0,0 +1,21 @@ +connection node_2; +connection node_1; +connect con1,127.0.0.1,root,,test,$NODE_MYPORT_1; +call mtr.add_suppression("WSREP: ALTER TABLE isolation failure"); +CREATE TABLE t1(c1 INT PRIMARY KEY, c2 INT) ENGINE=InnoDB; +SET DEBUG_SYNC = 'wsrep_append_fk_toi_keys_before_close_tables SIGNAL may_alter WAIT_FOR bf_abort'; +ALTER TABLE t1 DROP COLUMN c2; +connection node_1; +SET DEBUG_SYNC = 'now WAIT_FOR may_alter'; +ALTER TABLE t1 ADD COLUMN c3 INT; +connection con1; +ERROR 70100: Query execution was interrupted +INSERT INTO t1 (c1, c2, c3) VALUES (1, 0, 0); +connection node_2; +INSERT INTO t1 (c1, c2, c3) VALUES (2, 0, 0); +connection node_1; +SET DEBUG_SYNC = 'RESET'; +DROP TABLE t1; +disconnect con1; +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera/t/MDEV-32938.test b/mysql-test/suite/galera/t/MDEV-32938.test new file mode 100644 index 00000000000..cb41f21a58a --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-32938.test @@ -0,0 +1,57 @@ +# +# MDEV-32938: ALTER command is replicated and successfully applied while being BF-aborted locally. +# +# Why it happend: +# - ALTER went to prepare FK-referenced tables as TOI keys +# - to do this, it would open the main table with SHARED_HIGH_PRIO MDL lock which disregarded any +# other locks (including X-lock) waiting in the queue in case someone was already holding a +# compatible lock type (like any DML operation) +# - if there was other TOI operation on the same table, it would go through BF-abort cycle to grab +# the lock for itself +# - since the initial ALTER had not reached TOI yet, it would loose to real TOI operation and got +# BF-aborted with its THD marked as killed +# - then, ALTER would enter TOI and get replicated with no checks that it has already been aborted +# - after entering TOI mode, it would later find it'd been killed, and complete with an error +# - at the same time, the command would successfully apply on every other node except the initiator. +# +# Fixed by checking killed state on THD before entering TOI. +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +--connect con1,127.0.0.1,root,,test,$NODE_MYPORT_1 + +call mtr.add_suppression("WSREP: ALTER TABLE isolation failure"); + +CREATE TABLE t1(c1 INT PRIMARY KEY, c2 INT) ENGINE=InnoDB; + +# Run ALTER DROP COLUMN and hang before closing tables on adding FK keys and before entering TOI. +# Wait until it gets BF-aborted. +SET DEBUG_SYNC = 'wsrep_append_fk_toi_keys_before_close_tables SIGNAL may_alter WAIT_FOR bf_abort'; +--send + ALTER TABLE t1 DROP COLUMN c2; + +--connection node_1 +# Run ALTER ADD COLUMN and BF-abort the previous ALTER DROP COLUMN. +SET DEBUG_SYNC = 'now WAIT_FOR may_alter'; +ALTER TABLE t1 ADD COLUMN c3 INT; + +--connection con1 +# ALTER DROP COLUMN gets BF aborted. +--error ER_QUERY_INTERRUPTED +--reap + +INSERT INTO t1 (c1, c2, c3) VALUES (1, 0, 0); + +--connection node_2 +# ALTER DROP COLUMN must not be replicated. +INSERT INTO t1 (c1, c2, c3) VALUES (2, 0, 0); + +# Cleanup. +--connection node_1 +SET DEBUG_SYNC = 'RESET'; +DROP TABLE t1; +--disconnect con1 +--source include/galera_end.inc diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index f83f629a715..b619f9ed741 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -490,17 +490,18 @@ bool Sql_cmd_alter_table::execute(THD *thd) } 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) + if (!wsrep_append_fk_parent_table(thd, first_table, &keys)) { - WSREP_WARN("ALTER TABLE isolation failure"); - DBUG_RETURN(TRUE); - } + 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"); + DEBUG_SYNC(thd, "wsrep_alter_table_after_toi"); + } } #endif diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 688b0061389..7c8bb683aab 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1288,7 +1288,7 @@ static void wsrep_keys_free(wsrep_key_arr_t* key_arr) * @param tables list of tables * @param keys prepared keys - * @return true if parent table append was successfull, otherwise false. + * @return 0 if parent table append was successful, non-zero otherwise. */ bool wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* keys) @@ -1337,6 +1337,8 @@ wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* key } exit: + DEBUG_SYNC(thd, "wsrep_append_fk_toi_keys_before_close_tables"); + /* close the table and release MDL locks */ close_thread_tables(thd); thd->mdl_context.rollback_to_savepoint(mdl_savepoint); @@ -1347,6 +1349,24 @@ exit: table->mdl_request.ticket= NULL; } + /* + MDEV-32938: Check if DDL operation has been killed before. + + It may be that during collecting foreign keys this operation gets BF-aborted + by another already-running TOI operation because it got MDL locks on the same + table for checking foreign keys. + After `close_thread_tables()` has been called it's safe to assume that no-one + can BF-abort this operation as it's not holding any MDL locks any more. + */ + if (!fail) + { + mysql_mutex_lock(&thd->LOCK_thd_kill); + if (thd->killed) + { + fail= true; + } + mysql_mutex_unlock(&thd->LOCK_thd_kill); + } return fail; } @@ -2294,6 +2314,15 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, const TABLE_LIST* table_list, Alter_info* alter_info, wsrep::key_array* fk_tables) { + mysql_mutex_lock(&thd->LOCK_thd_kill); + const killed_state killed = thd->killed; + mysql_mutex_unlock(&thd->LOCK_thd_kill); + if (killed) + { + DBUG_ASSERT(FALSE); + return -1; + } + /* No isolation for applier or replaying threads. */ From 5c4c1844bf8b60dcee9fdeacd4a39705d40a4515 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Mon, 20 Nov 2023 13:42:38 +0100 Subject: [PATCH 386/477] MDEV-32781 galera_bf_lock_wait test failed This test happens to fail if it runs after test galera_inject_bf_long_wait. And the reason is that galera_bf_lock_wait greps for message "BF lock wait long" in the error log, and expects that grep matches no lines. Whereas galera_inject_bf_long_wait intentionally causes the message to appear in the log. The fix consists in using assert_grep.inc with option assert_only_after, such that galera_bf_lock_wait is limited to grep only those lines that appeared in the log after it started to execute. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/disabled.def | 1 - .../suite/galera/r/galera_bf_lock_wait.result | 20 +++++++++++++++++++ .../suite/galera/t/galera_bf_lock_wait.test | 14 ++++++++++--- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 9fcc1f18fd4..4db06714bc1 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -20,7 +20,6 @@ versioning_trx_id : MDEV-18590 : galera.versioning_trx_id: Test failure: mysqlte galera_concurrent_ctas : MDEV-32779 galera_concurrent_ctas: assertion in the galera::ReplicatorSMM::finish_cert() galera_as_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() galera_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() -galera_bf_lock_wait : MDEV-32781 galera_bf_lock_wait test failed galera_sst_mysqldump_with_key : MDEV-32782 galera_sst_mysqldump_with_key test failed mdev-31285 : MDEV-25089 Assertion `error.len > 0' failed in galera::ReplicatorSMM::handle_apply_error() galera_var_ignore_apply_errors : MENT-1997 galera_var_ignore_apply_errors test freezes diff --git a/mysql-test/suite/galera/r/galera_bf_lock_wait.result b/mysql-test/suite/galera/r/galera_bf_lock_wait.result index 757fbf50cad..9e5cb2d9266 100644 --- a/mysql-test/suite/galera/r/galera_bf_lock_wait.result +++ b/mysql-test/suite/galera/r/galera_bf_lock_wait.result @@ -33,6 +33,26 @@ SET SESSION wsrep_sync_wait=0; call p1(1000); connection node_1; checking error log for 'BF lock wait long' message for 10 times every 10 seconds ... +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] +include/assert_grep.inc [BF lock wait long] connection node_1_p1; connection node_1_p2; connection node_2_p1; diff --git a/mysql-test/suite/galera/t/galera_bf_lock_wait.test b/mysql-test/suite/galera/t/galera_bf_lock_wait.test index 0562b4361ff..8ef2fee78ed 100644 --- a/mysql-test/suite/galera/t/galera_bf_lock_wait.test +++ b/mysql-test/suite/galera/t/galera_bf_lock_wait.test @@ -52,6 +52,12 @@ let $counter=10; let $sleep_period=10; echo checking error log for 'BF lock wait long' message for $counter times every $sleep_period seconds ...; + +--let assert_text= BF lock wait long +--let assert_select= BF lock wait long +--let assert_count= 0 +--let assert_only_after= CURRENT_TEST: galera.galera_bf_lock_wait + while($counter > 0) { --disable_query_log @@ -60,9 +66,11 @@ while($counter > 0) --enable_query_log --enable_result_log -# use error 0,1 instead if want test to continue - --error 1 - exec grep 'BF lock wait long' $MYSQLTEST_VARDIR/log/mysqld.*.err; +--let assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--source include/assert_grep.inc + +--let assert_file= $MYSQLTEST_VARDIR/log/mysqld.2.err +--source include/assert_grep.inc dec $counter; } From bd23b3dc0673bc9556a2bd7207c242d489dc92a7 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Mon, 4 Dec 2023 15:55:53 +0300 Subject: [PATCH 387/477] MDEV-32901: innodb.mdev-14846 fails in 11.0 InnoDB could return off-by-1 estimates for the involved tables. This would cause off-by-many difference in join output cardinality for the top-level SELECT, and so different query plan for the subquery. The fix: Introduce mysql-test/include/innodb_stable_estimates.{inc,opt} which disables InnoDB's background statistics collection, and use it. --- mysql-test/include/innodb_stable_estimates.inc | 12 ++++++++++++ mysql-test/include/innodb_stable_estimates.opt | 1 + mysql-test/suite/innodb/t/mdev-14846.test | 2 ++ 3 files changed, 15 insertions(+) create mode 100644 mysql-test/include/innodb_stable_estimates.inc create mode 100644 mysql-test/include/innodb_stable_estimates.opt diff --git a/mysql-test/include/innodb_stable_estimates.inc b/mysql-test/include/innodb_stable_estimates.inc new file mode 100644 index 00000000000..dc3bc4de9ee --- /dev/null +++ b/mysql-test/include/innodb_stable_estimates.inc @@ -0,0 +1,12 @@ +# +# Include this file in your .test file if your testcase uses InnoDB tables +# requiring stable query plans, which likely requires that InnoDB produces +# stable estimates for #records in tables. +# +# How it works: +# Unstable InnoDB estimates are caused by InnoDB's background statistics +# collection. When you include this file, MTR will use server options from +# include/innodb_stable_estimates.opt, which disables background statistics +# collection. +# (and no, InnoDB team objects to using this configuration for all MTR tests) +# diff --git a/mysql-test/include/innodb_stable_estimates.opt b/mysql-test/include/innodb_stable_estimates.opt new file mode 100644 index 00000000000..896950f4ae5 --- /dev/null +++ b/mysql-test/include/innodb_stable_estimates.opt @@ -0,0 +1 @@ +--innodb_stats_auto_recalc=0 diff --git a/mysql-test/suite/innodb/t/mdev-14846.test b/mysql-test/suite/innodb/t/mdev-14846.test index adcefecd52f..0952470506d 100644 --- a/mysql-test/suite/innodb/t/mdev-14846.test +++ b/mysql-test/suite/innodb/t/mdev-14846.test @@ -2,6 +2,8 @@ --source include/count_sessions.inc --source include/have_debug_sync.inc +--source include/innodb_stable_estimates.inc + CREATE TABLE t1 ( pk INT, f1 VARCHAR(10) NOT NULL, From dc9ac9266ccedcfc8ce269dbf1b710aec536f560 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Mon, 4 Dec 2023 07:38:44 -0700 Subject: [PATCH 388/477] MDEV-32933: Skip statement and mix mode for binlog.flashback The binlog.flashback test tries to run using the stmt and mix binlog_format combinations (because it includes have_log_bin.inc), yet are meaningless tests because the server starts with the --flashback option, forcing binlog_format=row. This patch optimizes test time by removing the stmt and mix format combinations from running. Reviewed By: ============ Andrei Elkin --- mysql-test/suite/binlog/t/flashback.test | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/binlog/t/flashback.test b/mysql-test/suite/binlog/t/flashback.test index 50190da6dbe..0c499139a9f 100644 --- a/mysql-test/suite/binlog/t/flashback.test +++ b/mysql-test/suite/binlog/t/flashback.test @@ -1,4 +1,4 @@ ---source include/have_log_bin.inc +--source include/have_binlog_format_row.inc --source include/have_innodb.inc --echo # @@ -101,7 +101,7 @@ let $MYSQLD_DATADIR= `select @@datadir`; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_1.sql --exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql ---exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql;" +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql;" SELECT * FROM t1; @@ -126,7 +126,7 @@ let $MYSQLD_DATADIR= `select @@datadir`; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_2.sql --exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql ---exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql;" +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql;" SELECT * FROM t1; @@ -160,7 +160,7 @@ let $MYSQLD_DATADIR= `select @@datadir`; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_3.sql --exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql ---exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql;" +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql;" SELECT * FROM t1; @@ -202,7 +202,7 @@ let $MYSQLD_DATADIR= `select @@datadir`; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_4.sql --exec $MYSQL_BINLOG -B $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_4.sql ---exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_4.sql;" +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_4.sql;" SELECT * FROM t1; SELECT * FROM t2; @@ -247,7 +247,7 @@ let $MYSQLD_DATADIR= `select @@datadir`; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_5.sql --exec $MYSQL_BINLOG -B $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_5.sql ---exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_5.sql;" +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_5.sql;" SELECT * FROM t1; @@ -323,7 +323,7 @@ let $MYSQLD_DATADIR= `select @@datadir`; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --exec $MYSQL_BINLOG --database=world --table=city -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_6.sql --exec $MYSQL_BINLOG --database=world --table=city -B $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_6.sql ---exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_6.sql;" +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_6.sql;" SELECT * FROM world.city; @@ -355,7 +355,7 @@ FLUSH LOGS; --source include/assert.inc --exec $MYSQL_BINLOG -vv -B --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002> $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_7.sql ---exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_7.sql;" +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_7.sql;" --echo # 6- Rows must be present upon restoring from flashback --let $assert_cond= COUNT(*) = 6 FROM t1 From d5fc34db4c722309bc30d5f6fe7c24397b104a7d Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 6 Dec 2023 14:29:17 +0530 Subject: [PATCH 389/477] MDEV-29092 FOREIGN_KEY_CHECKS does not prevent non-copy alter from creating invalid FK structure Problem: ======== - InnoDB should have two keys on the same column for the self referencing foreign key relation. Solution: ========= - Allow self referential foreign key relation to work with one key. --- .../innodb/r/innodb-index-online-fk.result | 31 +++++++++++++++++++ .../suite/innodb/r/innodb-truncate.result | 7 ++--- .../suite/innodb/r/innodb_bug12902967.result | 6 ---- .../innodb/t/innodb-index-online-fk.test | 16 ++++++++++ .../suite/innodb/t/innodb-truncate.test | 8 ++--- .../suite/innodb/t/innodb_bug12902967.test | 25 --------------- storage/innobase/dict/dict0dict.cc | 3 +- 7 files changed, 54 insertions(+), 42 deletions(-) delete mode 100644 mysql-test/suite/innodb/r/innodb_bug12902967.result delete mode 100644 mysql-test/suite/innodb/t/innodb_bug12902967.test diff --git a/mysql-test/suite/innodb/r/innodb-index-online-fk.result b/mysql-test/suite/innodb/r/innodb-index-online-fk.result index afe55543e55..35ef7ae9ef9 100644 --- a/mysql-test/suite/innodb/r/innodb-index-online-fk.result +++ b/mysql-test/suite/innodb/r/innodb-index-online-fk.result @@ -654,3 +654,34 @@ t2 CREATE TABLE `t2` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t2; drop table t1; +# +# MDEV-29092 FOREIGN_KEY_CHECKS does not prevent non-copy +# alter from creating invalid FK structures +# +CREATE TABLE t1(f1 INT, KEY(f1), +FOREIGN KEY(f1) references t1(f1))ENGINE=InnoDB; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + KEY `f1` (`f1`), + CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t1; +CREATE TABLE t1(f1 INT, KEY(f1), +FOREIGN KEY(f1) REFERENCES t1(f1))ENGINE=InnoDB; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + KEY `f1` (`f1`), + CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +ALTER TABLE t1 DROP KEY f1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb-truncate.result b/mysql-test/suite/innodb/r/innodb-truncate.result index 8610a892cc6..fb027967390 100644 --- a/mysql-test/suite/innodb/r/innodb-truncate.result +++ b/mysql-test/suite/innodb/r/innodb-truncate.result @@ -86,8 +86,7 @@ CREATE TABLE t2 (f2 INT, FOREIGN KEY(f2) REFERENCES t1 (f2)) ENGINE=InnoDB; CREATE TABLE t3 (a INT) ENGINE=InnoDB; ERROR HY000: Can't create table `test`.`t3` (errno: 150 "Foreign key constraint is incorrectly formed") ALTER TABLE t1 RENAME TO t3; -ERROR HY000: Error on rename of './test/t1' to './test/t3' (errno: 150 "Foreign key constraint is incorrectly formed") -ALTER TABLE t1 FORCE; -TRUNCATE TABLE t1; +ALTER TABLE t3 FORCE; +TRUNCATE TABLE t3; ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `test`.`t3` (`f2`)) -DROP TABLE t2, t1; +DROP TABLE t2, t3; diff --git a/mysql-test/suite/innodb/r/innodb_bug12902967.result b/mysql-test/suite/innodb/r/innodb_bug12902967.result deleted file mode 100644 index 6478cdb6c1f..00000000000 --- a/mysql-test/suite/innodb/r/innodb_bug12902967.result +++ /dev/null @@ -1,6 +0,0 @@ -call mtr.add_suppression("In ALTER TABLE .* has or is referenced in foreign key constraints which are not compatible with the new table definition."); -# restart -create table t1 (f1 integer primary key) engine innodb; -alter table t1 add constraint c1 foreign key (f1) references t1(f1); -ERROR HY000: Error on rename of '#sql-temporary' to './test/t1' (errno: 150 "Foreign key constraint is incorrectly formed") -drop table t1; diff --git a/mysql-test/suite/innodb/t/innodb-index-online-fk.test b/mysql-test/suite/innodb/t/innodb-index-online-fk.test index 12a6eea49c2..00333db0d8f 100644 --- a/mysql-test/suite/innodb/t/innodb-index-online-fk.test +++ b/mysql-test/suite/innodb/t/innodb-index-online-fk.test @@ -511,3 +511,19 @@ alter table t2 drop key t,algorithm=inplace; show create table t2; drop table t2; drop table t1; + +--echo # +--echo # MDEV-29092 FOREIGN_KEY_CHECKS does not prevent non-copy +--echo # alter from creating invalid FK structures +--echo # +CREATE TABLE t1(f1 INT, KEY(f1), + FOREIGN KEY(f1) references t1(f1))ENGINE=InnoDB; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT, KEY(f1), + FOREIGN KEY(f1) REFERENCES t1(f1))ENGINE=InnoDB; +SHOW CREATE TABLE t1; +ALTER TABLE t1 DROP KEY f1; +SHOW CREATE TABLE t1; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb-truncate.test b/mysql-test/suite/innodb/t/innodb-truncate.test index 71c0fcfea8b..87387c313df 100644 --- a/mysql-test/suite/innodb/t/innodb-truncate.test +++ b/mysql-test/suite/innodb/t/innodb-truncate.test @@ -85,10 +85,8 @@ SET FOREIGN_KEY_CHECKS= ON; CREATE TABLE t2 (f2 INT, FOREIGN KEY(f2) REFERENCES t1 (f2)) ENGINE=InnoDB; --error ER_CANT_CREATE_TABLE CREATE TABLE t3 (a INT) ENGINE=InnoDB; ---replace_result $datadir ./ ---error ER_ERROR_ON_RENAME ALTER TABLE t1 RENAME TO t3; -ALTER TABLE t1 FORCE; +ALTER TABLE t3 FORCE; --error ER_TRUNCATE_ILLEGAL_FK -TRUNCATE TABLE t1; -DROP TABLE t2, t1; +TRUNCATE TABLE t3; +DROP TABLE t2, t3; diff --git a/mysql-test/suite/innodb/t/innodb_bug12902967.test b/mysql-test/suite/innodb/t/innodb_bug12902967.test deleted file mode 100644 index 1b5df7fa165..00000000000 --- a/mysql-test/suite/innodb/t/innodb_bug12902967.test +++ /dev/null @@ -1,25 +0,0 @@ -# Bug 12902967: Creating self referencing fk on same index unhandled, -# confusing error -# -# Creating a self referencing foreign key on the same -# column/index is an unhandled exception, it should throw a sensible -# error but instead implies that your data dictionary may now be out -# of sync: - ---source include/have_innodb.inc ---source include/not_embedded.inc - -call mtr.add_suppression("In ALTER TABLE .* has or is referenced in foreign key constraints which are not compatible with the new table definition."); - -let error_log= $MYSQLTEST_VARDIR/log/mysqld.1.err; ---source include/restart_mysqld.inc - -create table t1 (f1 integer primary key) engine innodb; - -# The below statement should produce error message in error log. -# This error message should mention problem with foreign keys -# rather than with data dictionary. ---replace_regex /'\.\/test\/#sql-[0-9a-f_]*'/'#sql-temporary'/ ---error ER_ERROR_ON_RENAME -alter table t1 add constraint c1 foreign key (f1) references t1(f1); -drop table t1; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 1245799b7d3..d0f8ac21dd8 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -2697,8 +2697,7 @@ dict_foreign_find_index( for (dict_index_t* index = dict_table_get_first_index(table); index; index = dict_table_get_next_index(index)) { - if (types_idx != index - && !index->to_be_dropped + if (!index->to_be_dropped && !dict_index_is_online_ddl(index) && dict_foreign_qualify_index( table, col_names, columns, n_cols, From a8bd6a9813d497d15ee42eefcc02682872484b3b Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Fri, 10 Nov 2023 20:03:06 +0700 Subject: [PATCH 390/477] MDEV-15656 Assertion `is_last_prefix <= 0' failed in QUICK_GROUP_MIN_MAX_SELECT::get_next When QUICK_GROUP_MIN_MAX_SELECT is initialized or being reset it stores the prefix of the last group of the index chosen for retrieving data (last_value). Later, when looping through records at get_next() method, the server checks whether the retrieved group is the last, and if so, it finishes processing. At the same time, it looks like there is no need for that additional check since method next_prefix() returns HA_ERR_KEY_NOT_FOUND or HA_ERR_END_OF_FILE when there are no more satisfying records. If we do not perform the check, we do not need to retrieve and store last_value either. This commit removes using of last_value from QUICK_GROUP_MIN_MAX_SELECT. Reviewer: Sergei Petrunia --- mysql-test/main/group_min_max_innodb.result | 107 ++++++++++++++++++ mysql-test/main/group_min_max_innodb.test | 47 ++++++++ .../innodb_ext_key,covering,innodb,on.rdiff | 20 ++++ ...innodb_ext_key,innodb,on,unoptimized.rdiff | 20 ++++ sql/opt_range.cc | 45 ++------ sql/opt_range.h | 1 - 6 files changed, 202 insertions(+), 38 deletions(-) create mode 100644 mysql-test/main/innodb_ext_key,covering,innodb,on.rdiff create mode 100644 mysql-test/main/innodb_ext_key,innodb,on,unoptimized.rdiff diff --git a/mysql-test/main/group_min_max_innodb.result b/mysql-test/main/group_min_max_innodb.result index a2b06b0481b..d7edad83b80 100644 --- a/mysql-test/main/group_min_max_innodb.result +++ b/mysql-test/main/group_min_max_innodb.result @@ -330,6 +330,113 @@ JOIN t1 ON dt.a=t1.b; a Australia DROP TABLES t1, t2; +# +# MDEV-15656: Assertion `is_last_prefix <= 0' failed in +# QUICK_GROUP_MIN_MAX_SELECT::get_next +# +SET @lru_depth.save= @@innodb_lru_scan_depth; +SET GLOBAL innodb_lru_scan_depth= 1024; +CREATE TABLE t1 ( +pk_part1 INT AUTO_INCREMENT, +a VARCHAR(4), +row_start timestamp(6) default current_timestamp, +PRIMARY KEY (pk_part1, row_start) +) ENGINE=InnoDB; +INSERT INTO t1 (a) VALUES +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'); +connect con1,localhost,root,,test; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +SELECT DISTINCT pk_part1 FROM t1; +connection default; +INSERT INTO t1 (pk_part1) VALUES (NULL); +connection con1; +disconnect con1; +connection default; +DROP TABLE t1; +SET GLOBAL innodb_lru_scan_depth= @lru_depth.save; set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent_sample_pages= @innodb_stats_persistent_sample_pages_save; diff --git a/mysql-test/main/group_min_max_innodb.test b/mysql-test/main/group_min_max_innodb.test index fcecbec41b3..33a3a8888a5 100644 --- a/mysql-test/main/group_min_max_innodb.test +++ b/mysql-test/main/group_min_max_innodb.test @@ -273,6 +273,53 @@ eval $query; DROP TABLES t1, t2; +--echo # +--echo # MDEV-15656: Assertion `is_last_prefix <= 0' failed in +--echo # QUICK_GROUP_MIN_MAX_SELECT::get_next +--echo # +SET @lru_depth.save= @@innodb_lru_scan_depth; +SET GLOBAL innodb_lru_scan_depth= 1024; + +CREATE TABLE t1 ( + pk_part1 INT AUTO_INCREMENT, + a VARCHAR(4), + row_start timestamp(6) default current_timestamp, + PRIMARY KEY (pk_part1, row_start) +) ENGINE=InnoDB; + +INSERT INTO t1 (a) VALUES +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'), +('foo'),('bar'),('foo'),('bar'),('foo'); + +--connect (con1,localhost,root,,test) + +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; + +--let $run= 20 +--disable_result_log +while ($run) +{ + --send + SELECT DISTINCT pk_part1 FROM t1; + --connection default + INSERT INTO t1 (pk_part1) VALUES (NULL); + --connection con1 + --reap + --dec $run +} +--enable_result_log + +--disconnect con1 +--connection default +DROP TABLE t1; +SET GLOBAL innodb_lru_scan_depth= @lru_depth.save; + set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent_sample_pages= @innodb_stats_persistent_sample_pages_save; diff --git a/mysql-test/main/innodb_ext_key,covering,innodb,on.rdiff b/mysql-test/main/innodb_ext_key,covering,innodb,on.rdiff new file mode 100644 index 00000000000..0d8bcc6ce3c --- /dev/null +++ b/mysql-test/main/innodb_ext_key,covering,innodb,on.rdiff @@ -0,0 +1,20 @@ +--- ./main/innodb_ext_key.result ++++ ./main/innodb_ext_key.reject +@@ -244,7 +244,7 @@ + Variable_name Value + Handler_read_first 0 + Handler_read_key 21 +-Handler_read_last 1 ++Handler_read_last 0 + Handler_read_next 0 + Handler_read_prev 0 + Handler_read_retry 0 +@@ -266,7 +266,7 @@ + Variable_name Value + Handler_read_first 0 + Handler_read_key 6 +-Handler_read_last 1 ++Handler_read_last 0 + Handler_read_next 0 + Handler_read_prev 0 + Handler_read_retry 0 diff --git a/mysql-test/main/innodb_ext_key,innodb,on,unoptimized.rdiff b/mysql-test/main/innodb_ext_key,innodb,on,unoptimized.rdiff new file mode 100644 index 00000000000..0d8bcc6ce3c --- /dev/null +++ b/mysql-test/main/innodb_ext_key,innodb,on,unoptimized.rdiff @@ -0,0 +1,20 @@ +--- ./main/innodb_ext_key.result ++++ ./main/innodb_ext_key.reject +@@ -244,7 +244,7 @@ + Variable_name Value + Handler_read_first 0 + Handler_read_key 21 +-Handler_read_last 1 ++Handler_read_last 0 + Handler_read_next 0 + Handler_read_prev 0 + Handler_read_retry 0 +@@ -266,7 +266,7 @@ + Variable_name Value + Handler_read_first 0 + Handler_read_key 6 +-Handler_read_last 1 ++Handler_read_last 0 + Handler_read_next 0 + Handler_read_prev 0 + Handler_read_retry 0 diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 0049be0daf4..b353c1aab41 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -14669,13 +14669,6 @@ int QUICK_GROUP_MIN_MAX_SELECT::init() { if (group_prefix) /* Already initialized. */ return 0; - - /* - We allocate one byte more to serve the case when the last field in - the buffer is compared using uint3korr (e.g. a Field_newdate field) - */ - if (!(last_prefix= (uchar*) alloc_root(&alloc, group_prefix_len+1))) - return 1; /* We may use group_prefix to store keys with all select fields, so allocate enough space for it. @@ -14931,8 +14924,7 @@ void QUICK_GROUP_MIN_MAX_SELECT::update_key_stat() QUICK_GROUP_MIN_MAX_SELECT::reset() DESCRIPTION - Initialize the index chosen for access and find and store the prefix - of the last group. The method is expensive since it performs disk access. + Initialize the index chosen for access. RETURN 0 OK @@ -14954,12 +14946,6 @@ int QUICK_GROUP_MIN_MAX_SELECT::reset(void) } if (quick_prefix_select && quick_prefix_select->reset()) DBUG_RETURN(1); - result= file->ha_index_last(record); - if (result == HA_ERR_END_OF_FILE) - DBUG_RETURN(0); - /* Save the prefix of the last group. */ - key_copy(last_prefix, record, index_info, group_prefix_len); - DBUG_RETURN(0); } @@ -15005,34 +14991,20 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next() #else int result; #endif - int is_last_prefix= 0; - DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::get_next"); /* - Loop until a group is found that satisfies all query conditions or the last - group is reached. + Loop until a group is found that satisfies all query conditions or + there are no satisfying groups left */ do { result= next_prefix(); - /* - Check if this is the last group prefix. Notice that at this point - this->record contains the current prefix in record format. - */ - if (!result) - { - is_last_prefix= key_cmp(index_info->key_part, last_prefix, - group_prefix_len); - DBUG_ASSERT(is_last_prefix <= 0); - } - else - { - if (result == HA_ERR_KEY_NOT_FOUND) - continue; + if (result != 0) break; - } - + /* + At this point this->record contains the current prefix in record format. + */ if (have_min) { min_res= next_min(); @@ -15061,8 +15033,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next() HA_READ_KEY_EXACT); result= have_min ? min_res : have_max ? max_res : result; - } while ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) && - is_last_prefix != 0); + } while (result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE); if (result == HA_ERR_KEY_NOT_FOUND) result= HA_ERR_END_OF_FILE; diff --git a/sql/opt_range.h b/sql/opt_range.h index 3f9d29a4447..a355dbacd9d 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -1527,7 +1527,6 @@ private: uchar *group_prefix; /* Key prefix consisting of the GROUP fields. */ const uint group_prefix_len; /* Length of the group prefix. */ uint group_key_parts; /* A number of keyparts in the group prefix */ - uchar *last_prefix; /* Prefix of the last group for detecting EOF. */ bool have_min; /* Specify whether we are computing */ bool have_max; /* a MIN, a MAX, or both. */ bool have_agg_distinct;/* aggregate_function(DISTINCT ...). */ From ecbdd72953e808c2e99068c0d672272e5627a2ad Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 6 Dec 2023 16:18:53 +0400 Subject: [PATCH 391/477] MDEV-32957 Unusable key notes report wrong predicates for > and >= The function scalar_comparison_op_to_lex_cstring() returned wrong operator names for SCALAR_CMP_GE and SCALAR_CMP_GT. --- mysql-test/include/explain_non_select.inc | 13 ++++ .../main/myisam_explain_non_select_all.result | 75 +++++++++++++++++-- mysql-test/main/type_varchar.result | 22 ++++++ mysql-test/main/type_varchar.test | 19 +++++ sql/sql_type.h | 4 +- 5 files changed, 125 insertions(+), 8 deletions(-) diff --git a/mysql-test/include/explain_non_select.inc b/mysql-test/include/explain_non_select.inc index bd0962d3876..bab76ffb67a 100644 --- a/mysql-test/include/explain_non_select.inc +++ b/mysql-test/include/explain_non_select.inc @@ -306,6 +306,19 @@ INSERT INTO t1 (i) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), --source include/explain_utils.inc DROP TABLE t1; +--echo #30a +--echo # +--echo # MDEV-32957 Unusable key notes report wrong predicates for > and >= +--echo # +CREATE TABLE t1(a INT, i CHAR(2), INDEX(i(1))); +INSERT INTO t1 (i) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), + (20),(21),(22),(23),(24),(25),(26),(27),(28),(29), + (30),(31),(32),(33),(34),(35); +--let $query = DELETE FROM t1 WHERE i >= 10 AND i < 18 ORDER BY i LIMIT 5 +--let $select = SELECT * FROM t1 WHERE i >= 10 AND i < 18 ORDER BY i LIMIT 5 +--source include/explain_utils.inc +DROP TABLE t1; + --echo #31 CREATE TABLE t1 (i INT); INSERT INTO t1 (i) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result index cc42c16d46b..b72df544a3f 100644 --- a/mysql-test/main/myisam_explain_non_select_all.result +++ b/mysql-test/main/myisam_explain_non_select_all.result @@ -1506,7 +1506,7 @@ EXPLAIN DELETE FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where; Using filesort Warnings: -Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` > "10" of type `int` Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` <= "18" of type `int` FLUSH STATUS; FLUSH TABLES; @@ -1514,7 +1514,7 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: -Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` > "10" of type `int` Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` <= "18" of type `int` Note 1003 delete from `test`.`t1` where `test`.`t1`.`i` > 10 and `test`.`t1`.`i` <= 18 order by `test`.`t1`.`i` limit 5 # Status of EXPLAIN EXTENDED query @@ -1526,7 +1526,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL i NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: -Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` > "10" of type `int` Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` <= "18" of type `int` Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`i` AS `i` from `test`.`t1` where `test`.`t1`.`i` > 10 and `test`.`t1`.`i` <= 18 order by `test`.`t1`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution @@ -1550,6 +1550,69 @@ Handler_read_rnd_next 27 Sort_rows 8 Sort_scan 1 +DROP TABLE t1; +#30a +# +# MDEV-32957 Unusable key notes report wrong predicates for > and >= +# +CREATE TABLE t1(a INT, i CHAR(2), INDEX(i(1))); +INSERT INTO t1 (i) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), +(20),(21),(22),(23),(24),(25),(26),(27),(28),(29), +(30),(31),(32),(33),(34),(35); +# +# query: DELETE FROM t1 WHERE i >= 10 AND i < 18 ORDER BY i LIMIT 5 +# select: SELECT * FROM t1 WHERE i >= 10 AND i < 18 ORDER BY i LIMIT 5 +# +Warnings: +Warning 1287 ' INTO FROM...' instead +EXPLAIN DELETE FROM t1 WHERE i >= 10 AND i < 18 ORDER BY i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "18" of type `int` +FLUSH STATUS; +FLUSH TABLES; +EXPLAIN EXTENDED DELETE FROM t1 WHERE i >= 10 AND i < 18 ORDER BY i LIMIT 5; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "18" of type `int` +Note 1003 delete from `test`.`t1` where `test`.`t1`.`i` >= 10 and `test`.`t1`.`i` < 18 order by `test`.`t1`.`i` limit 5 +# Status of EXPLAIN EXTENDED query +Variable_name Value +Handler_read_key 4 +FLUSH STATUS; +FLUSH TABLES; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE i >= 10 AND i < 18 ORDER BY i LIMIT 5; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL i NULL NULL NULL 26 100.00 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "18" of type `int` +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`i` AS `i` from `test`.`t1` where `test`.`t1`.`i` >= 10 and `test`.`t1`.`i` < 18 order by `test`.`t1`.`i` limit 5 +# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution +Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 ' INTO FROM...' instead +# Status of "equivalent" SELECT query execution: +Variable_name Value +Handler_read_key 4 +Handler_read_rnd_next 27 +Sort_priority_queue_sorts 1 +Sort_rows 5 +Sort_scan 1 +# Status of testing query execution: +Variable_name Value +Handler_delete 5 +Handler_read_key 4 +Handler_read_rnd 5 +Handler_read_rnd_next 27 +Sort_rows 8 +Sort_scan 1 + DROP TABLE t1; #31 CREATE TABLE t1 (i INT); @@ -2057,7 +2120,7 @@ EXPLAIN UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort Warnings: -Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` > "10" of type `int` Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` <= "18" of type `int` FLUSH STATUS; FLUSH TABLES; @@ -2065,7 +2128,7 @@ EXPLAIN EXTENDED UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: -Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` > "10" of type `int` Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` <= "18" of type `int` Note 1003 update `test`.`t2` set `test`.`t2`.`a` = 10 where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` limit 5 # Status of EXPLAIN EXTENDED query @@ -2077,7 +2140,7 @@ EXPLAIN EXTENDED SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL i NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: -Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` > "10" of type `int` Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` <= "18" of type `int` Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution diff --git a/mysql-test/main/type_varchar.result b/mysql-test/main/type_varchar.result index 6cce19dec38..cc3ccc00907 100644 --- a/mysql-test/main/type_varchar.result +++ b/mysql-test/main/type_varchar.result @@ -952,3 +952,25 @@ Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten c DROP TABLE t2; DROP TABLE t1; SET note_verbosity=DEFAULT; +# +# MDEV-32957 Unusable key notes report wrong predicates for > and >= +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (a INT, i CHAR(32), KEY(i)); +FOR i IN 1..31 +DO +INSERT INTO t1 VALUES (i, 10+i); +END FOR; +$$ +EXPLAIN SELECT * FROM t1 WHERE i>30 ORDER BY i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL i NULL NULL NULL 31 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` > "30" of type `int` +EXPLAIN SELECT * FROM t1 WHERE i>=30 ORDER BY i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL i NULL NULL NULL 31 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "30" of type `int` +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_varchar.test b/mysql-test/main/type_varchar.test index 46b37554575..620d25f3f7f 100644 --- a/mysql-test/main/type_varchar.test +++ b/mysql-test/main/type_varchar.test @@ -415,3 +415,22 @@ DELIMITER ;$$ --source unusable_keys_joins.inc DROP TABLE t1; SET note_verbosity=DEFAULT; + + +--echo # +--echo # MDEV-32957 Unusable key notes report wrong predicates for > and >= +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (a INT, i CHAR(32), KEY(i)); +DELIMITER $$; +FOR i IN 1..31 +DO + INSERT INTO t1 VALUES (i, 10+i); +END FOR; +$$ +DELIMITER ;$$ +EXPLAIN SELECT * FROM t1 WHERE i>30 ORDER BY i LIMIT 5; +EXPLAIN SELECT * FROM t1 WHERE i>=30 ORDER BY i LIMIT 5; +DROP TABLE t1; +SET note_verbosity=DEFAULT; diff --git a/sql/sql_type.h b/sql/sql_type.h index 11ca46517fc..6c277e5ad9c 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -151,8 +151,8 @@ scalar_comparison_op_to_lex_cstring(scalar_comparison_op op) case SCALAR_CMP_EQUAL: return LEX_CSTRING{STRING_WITH_LEN("<=>")}; case SCALAR_CMP_LT: return LEX_CSTRING{STRING_WITH_LEN("<")}; case SCALAR_CMP_LE: return LEX_CSTRING{STRING_WITH_LEN("<=")}; - case SCALAR_CMP_GE: return LEX_CSTRING{STRING_WITH_LEN(">")}; - case SCALAR_CMP_GT: return LEX_CSTRING{STRING_WITH_LEN(">=")}; + case SCALAR_CMP_GE: return LEX_CSTRING{STRING_WITH_LEN(">=")}; + case SCALAR_CMP_GT: return LEX_CSTRING{STRING_WITH_LEN(">")}; } DBUG_ASSERT(0); return LEX_CSTRING{STRING_WITH_LEN("")}; From 13896f73dfe7fb206b3ed72e40ae9039e37bea19 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Thu, 7 Dec 2023 10:45:52 +1100 Subject: [PATCH 392/477] MDEV-28683 Spider: create conn on demand when direct delete We do this in 10.4 at the same place where in 10.5+ dml_init() is called which does the same thing, among other things. --- storage/spider/ha_spider.cc | 2 ++ .../spider/bugfix/t/mdev_28683.test | 29 +++++++++++++++++++ storage/spider/spd_trx.cc | 3 -- 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_28683.test diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 793fa45c12f..24ee6c5e902 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -10999,6 +10999,8 @@ int ha_spider::direct_delete_rows_init() DBUG_RETURN(bulk_access_link_exec_tgt->spider->direct_delete_rows_init()); } #endif + if (int error_num = spider_check_trx_and_get_conn(thd, this, TRUE)) + DBUG_RETURN(error_num); direct_update_init( thd, FALSE diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28683.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28683.test new file mode 100644 index 00000000000..30821d0f251 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28683.test @@ -0,0 +1,29 @@ +--echo # +--echo # MDEV-28683 Spider: SIGSEGV in spider_db_direct_delete, SIGSEGV in spider_db_connect, ASAN: heap-use-after-free in spider_db_direct_delete +--echo # +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +CREATE TABLE t (c INT) ENGINE=Spider; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +SELECT * FROM t; +--error 12701 +INSERT INTO t (SELECT 1 FROM t); +LOCK TABLES t WRITE CONCURRENT; +--error 12701 +DELETE FROM t; + +UNLOCK TABLES; +DROP TABLE t; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log +--echo # +--echo # end of test mdev_28683 +--echo # diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index b39a398376c..29b5497dd81 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -3720,9 +3720,6 @@ int spider_check_trx_and_get_conn( for (roop_count = 0; roop_count < (int) share->link_count; roop_count++) { if ( -/* - spider->conn_kind[roop_count] != SPIDER_CONN_KIND_MYSQL && -*/ share->hs_dbton_ids[spider->conn_link_idx[roop_count]] == SPIDER_DBTON_SIZE ) { From 66fafdb9227dc39ed0dadec12435880b6b060b8e Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Thu, 7 Dec 2023 01:29:57 +0100 Subject: [PATCH 393/477] MDEV-32344: IST failed with ssl-mode=VERIFY_CA This commit fixes a bug where IST could be rejected in favor of SST when ssl-mode=VERIFY_CA and when mariabackup is used. It also contains a test and small code simplifications that will make it easier to find bugs in the future. --- .../r/galera_ist_mariabackup_verify_ca.result | 21 +++++++ .../r/galera_ist_rsync_verify_ca.result | 21 +++++++ .../t/galera_ist_mariabackup_verify_ca.cnf | 20 ++++++ .../t/galera_ist_mariabackup_verify_ca.test | 61 +++++++++++++++++++ .../galera/t/galera_ist_rsync_verify_ca.cnf | 17 ++++++ .../galera/t/galera_ist_rsync_verify_ca.test | 60 ++++++++++++++++++ scripts/wsrep_sst_mariabackup.sh | 42 +++++++------ scripts/wsrep_sst_rsync.sh | 25 ++++---- 8 files changed, 236 insertions(+), 31 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_ist_mariabackup_verify_ca.result create mode 100644 mysql-test/suite/galera/r/galera_ist_rsync_verify_ca.result create mode 100644 mysql-test/suite/galera/t/galera_ist_mariabackup_verify_ca.cnf create mode 100644 mysql-test/suite/galera/t/galera_ist_mariabackup_verify_ca.test create mode 100644 mysql-test/suite/galera/t/galera_ist_rsync_verify_ca.cnf create mode 100644 mysql-test/suite/galera/t/galera_ist_rsync_verify_ca.test diff --git a/mysql-test/suite/galera/r/galera_ist_mariabackup_verify_ca.result b/mysql-test/suite/galera/r/galera_ist_mariabackup_verify_ca.result new file mode 100644 index 00000000000..955d5af7827 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ist_mariabackup_verify_ca.result @@ -0,0 +1,21 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +CREATE TABLE t1 (f1 INT PRIMARY KEY); +connection node_2; +# Verify that graceful shutdown succeeds... +connection node_1; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +connection node_2; +# Start node_2 again... +SELECT * FROM t1; +f1 +1 +2 +3 +connection node_1; +include/assert_grep.inc [mariabackup IST completed on joiner] +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_ist_rsync_verify_ca.result b/mysql-test/suite/galera/r/galera_ist_rsync_verify_ca.result new file mode 100644 index 00000000000..51dfa7bcd18 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ist_rsync_verify_ca.result @@ -0,0 +1,21 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +CREATE TABLE t1 (f1 INT PRIMARY KEY); +connection node_2; +# Verify that graceful shutdown succeeds... +connection node_1; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +connection node_2; +# Start node_2 again... +SELECT * FROM t1; +f1 +1 +2 +3 +connection node_1; +include/assert_grep.inc [rsync IST completed on joiner] +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_ist_mariabackup_verify_ca.cnf b/mysql-test/suite/galera/t/galera_ist_mariabackup_verify_ca.cnf new file mode 100644 index 00000000000..f2187b83486 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_mariabackup_verify_ca.cnf @@ -0,0 +1,20 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=mariabackup +wsrep_sst_auth=root: + +ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/server-cert.pem +ssl-key=@ENV.MYSQL_TEST_DIR/std_data/server-key.pem +ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' + +[sst] +ssl-mode=VERIFY_CA +transferfmt=@ENV.MTR_GALERA_TFMT +streamfmt=mbstream diff --git a/mysql-test/suite/galera/t/galera_ist_mariabackup_verify_ca.test b/mysql-test/suite/galera/t/galera_ist_mariabackup_verify_ca.test new file mode 100644 index 00000000000..4e2d25b1770 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_mariabackup_verify_ca.test @@ -0,0 +1,61 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_mariabackup.inc + +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + +--let $LOG_FILE=$MYSQL_TMP_DIR/galera_node2.log +--error 0,1 +--remove_file $LOG_FILE + +CREATE TABLE t1 (f1 INT PRIMARY KEY); + +--connection node_2 + +--echo # Verify that graceful shutdown succeeds... +--source include/shutdown_mysqld.inc + +--connection node_1 + +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); + +--connection node_2 +--echo # Start node_2 again... +--let $restart_noprint=2 +--let $start_mysqld_params=--log-error=$LOG_FILE +--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 + +SELECT * FROM t1; + +--let $start_mysqld_params= +--source include/restart_mysqld.inc + +--connection node_1 + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# Confirm that IST took place +--let $assert_text = mariabackup IST completed on joiner +--let $assert_select = mariabackup IST completed on joiner +--let $assert_count = 1 +--let $assert_file = $LOG_FILE +--let $assert_only_after = Prepared IST receiver for +--source include/assert_grep.inc + +DROP TABLE t1; + +--source include/auto_increment_offset_restore.inc + +--remove_file $LOG_FILE diff --git a/mysql-test/suite/galera/t/galera_ist_rsync_verify_ca.cnf b/mysql-test/suite/galera/t/galera_ist_rsync_verify_ca.cnf new file mode 100644 index 00000000000..9125f6708fe --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_rsync_verify_ca.cnf @@ -0,0 +1,17 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=rsync + +ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/server-cert.pem +ssl-key=@ENV.MYSQL_TEST_DIR/std_data/server-key.pem +ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' + +[sst] +ssl-mode=VERIFY_CA diff --git a/mysql-test/suite/galera/t/galera_ist_rsync_verify_ca.test b/mysql-test/suite/galera/t/galera_ist_rsync_verify_ca.test new file mode 100644 index 00000000000..d9f7bb152fc --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_rsync_verify_ca.test @@ -0,0 +1,60 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + +--let $LOG_FILE=$MYSQL_TMP_DIR/galera_node2.log +--error 0,1 +--remove_file $LOG_FILE + +CREATE TABLE t1 (f1 INT PRIMARY KEY); + +--connection node_2 + +--echo # Verify that graceful shutdown succeeds... +--source include/shutdown_mysqld.inc + +--connection node_1 + +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); + +--connection node_2 +--echo # Start node_2 again... +--let $restart_noprint=2 +--let $start_mysqld_params=--log-error=$LOG_FILE +--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 + +SELECT * FROM t1; + +--let $start_mysqld_params= +--source include/restart_mysqld.inc + +--connection node_1 + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# Confirm that IST took place +--let $assert_text = rsync IST completed on joiner +--let $assert_select = rsync IST completed on joiner +--let $assert_count = 1 +--let $assert_file = $LOG_FILE +--let $assert_only_after = Prepared IST receiver for +--source include/assert_grep.inc + +DROP TABLE t1; + +--source include/auto_increment_offset_restore.inc + +--remove_file $LOG_FILE diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 84742defc16..4e21270feb2 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -102,6 +102,7 @@ if [ -z "$BACKUP_BIN" ]; then fi DATA="$WSREP_SST_OPT_DATA" + INFO_FILE='xtrabackup_galera_info' IST_FILE='xtrabackup_ist' MAGIC_FILE="$DATA/$INFO_FILE" @@ -1042,6 +1043,23 @@ setup_commands() INNOBACKUP="$BACKUP_BIN$WSREP_SST_OPT_CONF --backup$disver${iopts:+ }$iopts$tmpopts$INNOEXTRA --galera-info --stream=$sfmt --target-dir='$itmpdir' --datadir='$DATA'$mysqld_args $INNOBACKUP" } +send_magic() +{ + # Store donor's wsrep GTID (state ID) and wsrep_gtid_domain_id + # (separated by a space). + echo "$WSREP_SST_OPT_GTID $WSREP_SST_OPT_GTID_DOMAIN_ID" > "$MAGIC_FILE" + + if [ -n "$WSREP_SST_OPT_REMOTE_PSWD" ]; then + # Let joiner know that we know its secret + echo "$SECRET_TAG $WSREP_SST_OPT_REMOTE_PSWD" >> "$MAGIC_FILE" + fi + + if [ $WSREP_SST_OPT_BYPASS -eq 0 -a $WSREP_SST_OPT_PROGRESS -eq 1 ]; then + # Tell joiner what to expect: + echo "$TOTAL_TAG $payload" >> "$MAGIC_FILE" + fi +} + get_stream get_transfer @@ -1099,20 +1117,7 @@ if [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then fi wsrep_log_info "Streaming GTID file before SST" - - # Store donor's wsrep GTID (state ID) and wsrep_gtid_domain_id - # (separated by a space). - echo "$WSREP_SST_OPT_GTID $WSREP_SST_OPT_GTID_DOMAIN_ID" > "$MAGIC_FILE" - - if [ -n "$WSREP_SST_OPT_REMOTE_PSWD" ]; then - # Let joiner know that we know its secret - echo "$SECRET_TAG $WSREP_SST_OPT_REMOTE_PSWD" >> "$MAGIC_FILE" - fi - - if [ $WSREP_SST_OPT_PROGRESS -eq 1 ]; then - # Tell joiner what to expect: - echo "$TOTAL_TAG $payload" >> "$MAGIC_FILE" - fi + send_magic ttcmd="$tcmd" @@ -1202,9 +1207,8 @@ if [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then wsrep_log_info "Bypassing the SST for IST" echo "continue" # now server can resume updating data - # Store donor's wsrep GTID (state ID) and wsrep_gtid_domain_id - # (separated by a space). - echo "$WSREP_SST_OPT_GTID $WSREP_SST_OPT_GTID_DOMAIN_ID" > "$MAGIC_FILE" + send_magic + echo "1" > "$DATA/$IST_FILE" if [ -n "$scomp" ]; then @@ -1310,7 +1314,7 @@ else # joiner impts="--parallel=$backup_threads${impts:+ }$impts" fi - SST_PID="$WSREP_SST_OPT_DATA/wsrep_sst.pid" + SST_PID="$DATA/wsrep_sst.pid" # give some time for previous SST to complete: check_round=0 @@ -1451,8 +1455,8 @@ else # joiner TDATA="$DATA" DATA="$DATA/.sst" - MAGIC_FILE="$DATA/$INFO_FILE" + wsrep_log_info "Waiting for SST streaming to complete!" monitor_process $jpid diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 3e63596bcbe..ade9bb491e5 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -149,10 +149,12 @@ check_pid_and_port() check_pid "$pid_file" && [ $CHECK_PID -eq $pid ] } -STUNNEL_CONF="$WSREP_SST_OPT_DATA/stunnel.conf" -STUNNEL_PID="$WSREP_SST_OPT_DATA/stunnel.pid" +DATA="$WSREP_SST_OPT_DATA" -MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete" +STUNNEL_CONF="$DATA/stunnel.conf" +STUNNEL_PID="$DATA/stunnel.pid" + +MAGIC_FILE="$DATA/rsync_sst_complete" get_binlog @@ -163,7 +165,6 @@ fi OLD_PWD="$(pwd)" -DATA="$WSREP_SST_OPT_DATA" if [ -n "$DATA" -a "$DATA" != '.' ]; then [ ! -d "$DATA" ] && mkdir -p "$DATA" cd "$DATA" @@ -347,7 +348,7 @@ fi readonly SECRET_TAG='secret' readonly BYPASS_TAG='bypass' -SST_PID="$WSREP_SST_OPT_DATA/wsrep_sst.pid" +SST_PID="$DATA/wsrep_sst.pid" # give some time for previous SST to complete: check_round=0 @@ -379,8 +380,8 @@ done MODULE="${WSREP_SST_OPT_MODULE:-rsync_sst}" -RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid" -RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf" +RSYNC_PID="$DATA/$MODULE.pid" +RSYNC_CONF="$DATA/$MODULE.conf" # give some time for rsync from the previous SST to complete: check_round=0 @@ -422,8 +423,8 @@ EOF if [ $WSREP_SST_OPT_BYPASS -eq 0 ]; then - FLUSHED="$WSREP_SST_OPT_DATA/tables_flushed" - ERROR="$WSREP_SST_OPT_DATA/sst_error" + FLUSHED="$DATA/tables_flushed" + ERROR="$DATA/sst_error" [ -f "$FLUSHED" ] && rm -f "$FLUSHED" [ -f "$ERROR" ] && rm -f "$ERROR" @@ -580,7 +581,7 @@ FILTER="-f '- /lost+found' eval rsync ${STUNNEL:+"--rsh='$STUNNEL'"} \ --owner --group --perms --links --specials \ --ignore-times --inplace --dirs --delete --quiet \ - $WHOLE_FILE_OPT $FILTER "'$WSREP_SST_OPT_DATA/'" \ + $WHOLE_FILE_OPT $FILTER "'$DATA/'" \ "'rsync://$WSREP_SST_OPT_ADDR'" >&2 || RC=$? if [ $RC -ne 0 ]; then @@ -688,7 +689,7 @@ FILTER="-f '- /lost+found' -f '- $ib_log_dir/ib_logfile[0-9]*' \ -f '- $ar_log_dir/aria_log_control' \ -f '- $ar_log_dir/aria_log.*' \ - "$WSREP_SST_OPT_DATA/{}/" \ + "$DATA/{}/" \ "rsync://$WSREP_SST_OPT_ADDR/{}" >&2 || RC=$? cd "$OLD_PWD" @@ -770,7 +771,7 @@ read only = no timeout = 300 $SILENT [$MODULE] - path = $WSREP_SST_OPT_DATA + path = $DATA exclude = .zfs [$MODULE-log_dir] path = $ib_log_dir From f0af56be01591e593c875d63656e287c829c0073 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 14 Nov 2023 16:09:07 +1100 Subject: [PATCH 394/477] MDEV-27095 installing one spider plugin should not trigger others There are several plugins in ha_spider: spider, spider_alloc_mem, spider_wrapper_protocols, spider_rewrite etc. INSTALL PLUGIN foo SONAME ha_spider causes all the other ones to be installed by the init queries where foo is any of the plugins. This introduces unnecessary complexiy. For example it reads mysql.plugins to find all other plugins, causing the hack of moving spider plugin init to a separate thread. To install all spider related plugins, install soname ha_spider should be used instead. This also fixes spurious rows in mysql.plugin when installing say only the spider plugin with `plugin-load-add=SPIDER=ha_spider.so`: select * from mysql.plugin; name dl spider_alloc_mem ha_spider.so # should not be here spider_wrapper_protocols ha_spider.so # should not be here Adapted from part of the reverted commit c160a115b8b6dcd54bb3daf1a751ee9c68b7ee47. --- .../mysql-test/spider/include/init_spider.inc | 4 +- storage/spider/spd_init_query.h | 98 ------------------- 2 files changed, 2 insertions(+), 100 deletions(-) diff --git a/storage/spider/mysql-test/spider/include/init_spider.inc b/storage/spider/mysql-test/spider/include/init_spider.inc index d2d1c03494c..e5fe7862534 100644 --- a/storage/spider/mysql-test/spider/include/init_spider.inc +++ b/storage/spider/mysql-test/spider/include/init_spider.inc @@ -2,7 +2,7 @@ let $VERSION_COMPILE_OS_WIN= `SELECT IF(@@version_compile_os like 'Win%', 1, 0)`; if ($VERSION_COMPILE_OS_WIN) { - INSTALL PLUGIN spider SONAME 'ha_spider.dll'; + INSTALL SONAME 'ha_spider'; if ($CHILD2_1_MYPORT) { eval CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS ( @@ -66,7 +66,7 @@ if ($VERSION_COMPILE_OS_WIN) } if (!$VERSION_COMPILE_OS_WIN) { - INSTALL PLUGIN spider SONAME 'ha_spider.so'; + INSTALL SONAME 'ha_spider'; if ($CHILD2_1_MYSOCK) { eval CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS ( diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h index 4c58f8d80a4..7bb47fc4378 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -612,57 +612,6 @@ static LEX_STRING spider_init_queries[] = { "create procedure mysql.spider_plugin_installer()" "begin" " set @win_plugin := IF(@@version_compile_os like 'Win%', 1, 0);" -/* - Install spider plugin -*/ -/* - " set @have_spider_i_s_plugin := 0;" - " select @have_spider_i_s_plugin := 1 from INFORMATION_SCHEMA.plugins" - " where PLUGIN_NAME = 'SPIDER';" - " set @have_spider_plugin := 0;" - " select @have_spider_plugin := 1 from mysql.plugin" - " where name = 'spider';" - " if @have_spider_i_s_plugin = 0 then" - " if @have_spider_plugin = 1 then" - " / *" - " spider plugin is present in mysql.plugin but not in" - " information_schema.plugins. Remove spider plugin entry" - " in mysql.plugin first." - " * /" - " delete from mysql.plugin where name = 'spider';" - " end if;" - " if @win_plugin = 0 then " - " install plugin spider soname 'ha_spider.so';" - " else" - " install plugin spider soname 'ha_spider.dll';" - " end if;" - " end if;" -*/ -/* - Install spider_alloc_mem plugin -*/ - " set @have_spider_i_s_alloc_mem_plugin := 0;" - " select @have_spider_i_s_alloc_mem_plugin := 1" - " from INFORMATION_SCHEMA.plugins" - " where PLUGIN_NAME = 'SPIDER_ALLOC_MEM';" - " set @have_spider_alloc_mem_plugin := 0;" - " select @have_spider_alloc_mem_plugin := 1 from mysql.plugin" - " where name = 'spider_alloc_mem';" - " if @have_spider_i_s_alloc_mem_plugin = 0 then" - " if @have_spider_alloc_mem_plugin = 1 then" - " /*" - " spider_alloc_mem plugin is present in mysql.plugin but not in" - " information_schema.plugins. Remove spider_alloc_mem plugin entry" - " in mysql.plugin first." - " */" - " delete from mysql.plugin where name = 'spider_alloc_mem';" - " end if;" - " if @win_plugin = 0 then " - " install plugin spider_alloc_mem soname 'ha_spider.so';" - " else" - " install plugin spider_alloc_mem soname 'ha_spider.dll';" - " end if;" - " end if;" " set @have_spider_direct_sql_udf := 0;" " select @have_spider_direct_sql_udf := 1 from mysql.func" " where name = 'spider_direct_sql';" @@ -723,53 +672,6 @@ static LEX_STRING spider_init_queries[] = { " soname 'ha_spider.dll';" " end if;" " end if;" - " if @server_name = 'MariaDB' and" - " (" - " @server_major_version > 10 or" - " (" - " @server_major_version = 10 and" - " @server_minor_version >= 6" - " )" - " )" - " then" -/* - Install spider_rewrite plugin -*/ - " set @have_spider_i_s_rewrite_plugin := 0;" - " select @have_spider_i_s_rewrite_plugin := 1" - " from INFORMATION_SCHEMA.plugins" - " where PLUGIN_NAME = 'SPIDER_REWRITE';" - " set @have_spider_rewrite_plugin := 0;" - " select @have_spider_rewrite_plugin := 1 from mysql.plugin" - " where name = 'spider_rewrite';" - " if @have_spider_i_s_rewrite_plugin = 0 then" - " if @have_spider_rewrite_plugin = 1 then" - " /*" - " spider_rewrite plugin is present in mysql.plugin but not in" - " information_schema.plugins. Remove spider_rewrite plugin entry" - " in mysql.plugin first." - " */" - " delete from mysql.plugin where name = 'spider_rewrite';" - " end if;" - " if @win_plugin = 0 then " - " install plugin spider_rewrite soname 'ha_spider.so';" - " else" - " install plugin spider_rewrite soname 'ha_spider.dll';" - " end if;" - " end if;" - " set @have_spider_flush_rewrite_cache_udf := 0;" - " select @have_spider_flush_rewrite_cache_udf := 1 from mysql.func" - " where name = 'spider_flush_rewrite_cache';" - " if @have_spider_flush_rewrite_cache_udf = 0 then" - " if @win_plugin = 0 then " - " create function spider_flush_rewrite_cache returns int" - " soname 'ha_spider.so';" - " else" - " create function spider_flush_rewrite_cache returns int" - " soname 'ha_spider.dll';" - " end if;" - " end if;" - " end if;" "end;" )}, {C_STRING_WITH_LEN( From afe63ec61446359931a8eaa223eac540d2db65af Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Thu, 20 Apr 2023 13:07:43 +1000 Subject: [PATCH 395/477] MDEV-27095 clean up spd_init_query.h Removing procedures that were created and dropped during init. This also fixes a race condition where mtr test with plugin-load-add=ha_spider.so causes post test check to fail as it expects the procedures to still be there. --- storage/spider/spd_init_query.h | 840 +++++++++++++++----------------- 1 file changed, 398 insertions(+), 442 deletions(-) diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h index 7bb47fc4378..1ed4fcdd8ff 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -185,500 +185,456 @@ static LEX_STRING spider_init_queries[] = { If tables already exist and their definition differ from the latest ones, we fix them here. */ - {C_STRING_WITH_LEN( - "drop procedure if exists mysql.spider_fix_one_table" - )}, - {C_STRING_WITH_LEN( - "drop procedure if exists mysql.spider_fix_system_tables" - )}, - {C_STRING_WITH_LEN( - "create procedure mysql.spider_fix_one_table" - " (tab_name char(255) charset utf8 collate utf8_bin," - " test_col_name char(255) charset utf8 collate utf8_bin," - " _sql text charset utf8 collate utf8_bin)" - "begin" - " set @col_exists := 0;" - " select 1 into @col_exists from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = tab_name" - " AND COLUMN_NAME = test_col_name;" - " if @col_exists = 0 then" - " select @stmt := _sql;" - " prepare sp_stmt1 from @stmt;" - " execute sp_stmt1;" - " end if;" - "end;" - )}, - {C_STRING_WITH_LEN( - "create procedure mysql.spider_fix_system_tables()" - "begin" - " select substring_index(substring_index(version(), '-', 2), '-', -1)" - " into @server_name;" - " select substring_index(version(), '.', 1)" - " into @server_major_version;" - " select substring_index(substring_index(version(), '.', 2), '.', -1)" - " into @server_minor_version;" /* Fix for 0.5 */ - " call mysql.spider_fix_one_table('spider_tables', 'server'," - " 'alter table mysql.spider_tables" - " add server char(64) default null," - " add scheme char(64) default null," - " add host char(64) default null," - " add port char(5) default null," - " add socket char(64) default null," - " add username char(64) default null," - " add password char(64) default null," - " add tgt_db_name char(64) default null," - " add tgt_table_name char(64) default null');" + {C_STRING_WITH_LEN( + "alter table mysql.spider_tables" + " add if not exists server char(64) default null," + " add if not exists scheme char(64) default null," + " add if not exists host char(64) default null," + " add if not exists port char(5) default null," + " add if not exists socket char(64) default null," + " 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;" + )}, /* Fix for version 0.17 */ - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_xa'" - " AND COLUMN_NAME = 'data';" - " if @col_type != 'binary(128)' then" - " alter table mysql.spider_xa" - " modify data binary(128) not null default '';" - " end if;" - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_xa_member'" - " AND COLUMN_NAME = 'data';" - " if @col_type != 'binary(128)' then" - " alter table mysql.spider_xa_member" - " modify data binary(128) not null default '';" - " end if;" + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_xa'" + " AND COLUMN_NAME = 'data';" + )}, + {C_STRING_WITH_LEN( + "if @col_type != 'binary(128)' then" + " alter table mysql.spider_xa" + " modify data binary(128) not null default '';" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_xa_member'" + " AND COLUMN_NAME = 'data';" + )}, + {C_STRING_WITH_LEN( + "if @col_type != 'binary(128)' then" + " alter table mysql.spider_xa_member" + " modify data binary(128) not null default '';" + "end if;" + )}, /* Fix for version 2.7 */ - " call mysql.spider_fix_one_table('spider_tables', 'link_id'," - " 'alter table mysql.spider_tables" - " add column link_id int not null default 0 after table_name," - " drop primary key," - " add primary key (db_name, table_name, link_id)');" + {C_STRING_WITH_LEN( + "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);" + )}, /* Fix for version 2.8 */ - " call mysql.spider_fix_one_table('spider_tables', 'link_status'," - " 'alter table mysql.spider_tables" - " add column link_status tinyint not null default 1');" + {C_STRING_WITH_LEN( + "alter table mysql.spider_tables" + " add column if not exists link_status tinyint not null default 1;" + )}, /* Fix for version 2.10 */ - " call mysql.spider_fix_one_table('spider_xa_member', 'ssl_ca'," - " 'alter table mysql.spider_xa_member" - " add column ssl_ca char(64) default null after password," - " add column ssl_capath char(64) default null after ssl_ca," - " add column ssl_cert char(64) default null after ssl_capath," - " add column ssl_cipher char(64) default null after ssl_cert," - " add column ssl_key char(64) default null after ssl_cipher," - " add column ssl_verify_server_cert tinyint not null default 0" - " after ssl_key," - " add column default_file char(64) default null" - " after ssl_verify_server_cert," - " add column default_group char(64) default null after default_file');" - " call mysql.spider_fix_one_table('spider_tables', 'ssl_ca'," - " 'alter table mysql.spider_tables" - " add column ssl_ca char(64) default null after password," - " add column ssl_capath char(64) default null after ssl_ca," - " add column ssl_cert char(64) default null after ssl_capath," - " add column ssl_cipher char(64) default null after ssl_cert," - " add column ssl_key char(64) default null after ssl_cipher," - " add column ssl_verify_server_cert tinyint not null default 0" - " after ssl_key," - " add column default_file char(64) default null" - " after ssl_verify_server_cert," - " add column default_group char(64) default null after default_file');" - " call mysql.spider_fix_one_table('spider_link_mon_servers', 'ssl_ca'," - " 'alter table mysql.spider_link_mon_servers" - " add column ssl_ca char(64) default null after password," - " add column ssl_capath char(64) default null after ssl_ca," - " add column ssl_cert char(64) default null after ssl_capath," - " add column ssl_cipher char(64) default null after ssl_cert," - " add column ssl_key char(64) default null after ssl_cipher," - " add column ssl_verify_server_cert tinyint not null default 0" - " after ssl_key," - " add column default_file char(64) default null" - " after ssl_verify_server_cert," - " add column default_group char(64) default null after default_file');" + {C_STRING_WITH_LEN( + "alter table mysql.spider_xa_member" + " add column if not exists ssl_ca char(64) default null after password," + " add column if not exists ssl_capath char(64) default null after ssl_ca," + " add column if not exists ssl_cert char(64) default null after ssl_capath," + " add column if not exists ssl_cipher char(64) default null after ssl_cert," + " add column if not exists ssl_key char(64) default null after ssl_cipher," + " add column if not exists ssl_verify_server_cert tinyint not null default 0" + " 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;" + )}, + {C_STRING_WITH_LEN( + "alter table mysql.spider_tables" + " add column if not exists ssl_ca char(64) default null after password," + " add column if not exists ssl_capath char(64) default null after ssl_ca," + " add column if not exists ssl_cert char(64) default null after ssl_capath," + " add column if not exists ssl_cipher char(64) default null after ssl_cert," + " add column if not exists ssl_key char(64) default null after ssl_cipher," + " add column if not exists ssl_verify_server_cert tinyint not null default 0" + " 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;" + )}, + {C_STRING_WITH_LEN( + "alter table mysql.spider_link_mon_servers" + " add column if not exists ssl_ca char(64) default null after password," + " add column if not exists ssl_capath char(64) default null after ssl_ca," + " add column if not exists ssl_cert char(64) default null after ssl_capath," + " add column if not exists ssl_cipher char(64) default null after ssl_cert," + " add column if not exists ssl_key char(64) default null after ssl_cipher," + " add column if not exists ssl_verify_server_cert tinyint not null default 0" + " 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;" + )}, /* Fix for version 2.28 */ - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_link_mon_servers'" - " AND COLUMN_NAME = 'sid';" - " if @col_type != 'int(10) unsigned' then" - " alter table mysql.spider_link_mon_servers" - " modify sid int unsigned not null default 0;" - " end if;" + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_link_mon_servers'" + " AND COLUMN_NAME = 'sid';" + )}, + {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;" + "end if;" + )}, /* Fix for version 3.1 */ - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_xa_member'" - " AND COLUMN_NAME = 'socket';" - " if @col_type = 'char(64)' then" - " alter table mysql.spider_xa_member" - " drop primary key," - " add index idx1 (data, format_id, gtrid_length, host)," - " modify socket text not null," - " modify ssl_ca text," - " modify ssl_capath text," - " modify ssl_cert text," - " modify ssl_key text," - " modify default_file text;" - " end if;" - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_tables'" - " AND COLUMN_NAME = 'socket';" - " if @col_type = 'char(64)' then" - " alter table mysql.spider_tables" - " modify socket text," - " modify ssl_ca text," - " modify ssl_capath text," - " modify ssl_cert text," - " modify ssl_key text," - " modify default_file text;" - " end if;" - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_link_mon_servers'" - " AND COLUMN_NAME = 'socket';" - " if @col_type = 'char(64)' then" - " alter table mysql.spider_link_mon_servers" - " modify socket text," - " modify ssl_ca text," - " modify ssl_capath text," - " modify ssl_cert text," - " modify ssl_key text," - " modify default_file text;" - " end if;" + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_xa_member'" + " AND COLUMN_NAME = 'socket';" + )}, + {C_STRING_WITH_LEN( + "if @col_type = 'char(64)' then" + " alter table mysql.spider_xa_member" + " drop primary key," + " add index idx1 (data, format_id, gtrid_length, host)," + " modify socket text not null," + " modify ssl_ca text," + " modify ssl_capath text," + " modify ssl_cert text," + " modify ssl_key text," + " modify default_file text;" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_tables'" + " AND COLUMN_NAME = 'socket';" + )}, + {C_STRING_WITH_LEN( + "if @col_type = 'char(64)' then" + " alter table mysql.spider_tables" + " modify socket text," + " modify ssl_ca text," + " modify ssl_capath text," + " modify ssl_cert text," + " modify ssl_key text," + " modify default_file text;" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_link_mon_servers'" + " AND COLUMN_NAME = 'socket';" + )}, + {C_STRING_WITH_LEN( + "if @col_type = 'char(64)' then" + " alter table mysql.spider_link_mon_servers" + " modify socket text," + " modify ssl_ca text," + " modify ssl_capath text," + " modify ssl_cert text," + " modify ssl_key text," + " modify default_file text;" + "end if;" + )}, /* Fix for version 3.3.0 */ - " call mysql.spider_fix_one_table('spider_tables'," - " 'monitoring_binlog_pos_at_failing'," - " 'alter table mysql.spider_tables" - " add monitoring_binlog_pos_at_failing tinyint not null default 0" - " after ssl_verify_server_cert');" + {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;" + )}, /* Fix for version 3.3.6 */ - " call mysql.spider_fix_one_table('spider_tables', 'block_status'," - " 'alter table mysql.spider_tables" - " add column block_status tinyint not null default 0" - " after link_status');" - " call mysql.spider_fix_one_table('spider_tables', 'static_link_id'," - " 'alter table mysql.spider_tables" - " add column static_link_id char(64) default null after block_status," - " add unique index uidx1 (db_name, table_name, static_link_id)');" - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_link_mon_servers'" - " AND COLUMN_NAME = 'link_id';" - " if @col_type != 'char(64)' then" - " alter table mysql.spider_link_mon_servers" - " modify link_id char(64) not null default '';" - " end if;" - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_link_failed_log'" - " AND COLUMN_NAME = 'link_id';" - " if @col_type != 'char(64)' then" - " alter table mysql.spider_link_failed_log" - " modify link_id char(64) not null default '';" - " end if;" + {C_STRING_WITH_LEN( + "alter table mysql.spider_tables" + " add column if not exists block_status tinyint not null default 0" + " after link_status;" + )}, + {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);" + )}, + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_link_mon_servers'" + " AND COLUMN_NAME = 'link_id';" + )}, + {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 '';" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_link_failed_log'" + " AND COLUMN_NAME = 'link_id';" + )}, + {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 '';" + "end if;" + )}, /* Fix for version 3.3.10 */ - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_tables'" - " AND COLUMN_NAME = 'table_name';" - " if @col_type != 'char(199)' then" - " alter table mysql.spider_tables" - " modify table_name char(199) not null default '';" - " end if;" - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_link_mon_servers'" - " AND COLUMN_NAME = 'table_name';" - " if @col_type != 'char(199)' then" - " alter table mysql.spider_link_mon_servers" - " modify table_name char(199) not null default '';" - " end if;" - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_link_failed_log'" - " AND COLUMN_NAME = 'table_name';" - " if @col_type != 'char(199)' then" - " alter table mysql.spider_link_failed_log" - " modify table_name char(199) not null default '';" - " end if;" - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_table_position_for_recovery'" - " AND COLUMN_NAME = 'table_name';" - " if @col_type != 'char(199)' then" - " alter table mysql.spider_table_position_for_recovery" - " modify table_name char(199) not null default '';" - " end if;" - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_table_sts'" - " AND COLUMN_NAME = 'table_name';" - " if @col_type != 'char(199)' then" - " alter table mysql.spider_table_sts" - " modify table_name char(199) not null default '';" - " end if;" - " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_table_crd'" - " AND COLUMN_NAME = 'table_name';" - " if @col_type != 'char(199)' then" - " alter table mysql.spider_table_crd" - " modify table_name char(199) not null default '';" - " end if;" + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_tables'" + " AND COLUMN_NAME = 'table_name';" + )}, + {C_STRING_WITH_LEN( + "if @col_type != 'char(199)' then" + " alter table mysql.spider_tables" + " modify table_name char(199) not null default '';" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_link_mon_servers'" + " AND COLUMN_NAME = 'table_name';" + )}, + {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 '';" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_link_failed_log'" + " AND COLUMN_NAME = 'table_name';" + )}, + {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 '';" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_table_position_for_recovery'" + " AND COLUMN_NAME = 'table_name';" + )}, + {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 '';" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_table_sts'" + " AND COLUMN_NAME = 'table_name';" + )}, + {C_STRING_WITH_LEN( + "if @col_type != 'char(199)' then" + " alter table mysql.spider_table_sts" + " modify table_name char(199) not null default '';" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_table_crd'" + " AND COLUMN_NAME = 'table_name';" + )}, + {C_STRING_WITH_LEN( + "if @col_type != 'char(199)' then" + " alter table mysql.spider_table_crd" + " modify table_name char(199) not null default '';" + "end if;" + )}, /* Fix for version 3.3.15 */ - " call mysql.spider_fix_one_table('spider_table_sts', 'checksum'," - " 'alter table mysql.spider_table_sts" - " add column checksum bigint unsigned default null after update_time');" + {C_STRING_WITH_LEN( + "alter table mysql.spider_table_sts" + " add column if not exists checksum bigint unsigned default null after update_time;" + )}, /* Fix for MariaDB 10.4: Crash-Safe system tables */ - " if @server_name = 'MariaDB' and" - " (" - " @server_major_version > 10 or" - " (" - " @server_major_version = 10 and" - " @server_minor_version >= 4" - " )" - " )" - " then" - " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_link_failed_log';" - " if @engine_name != 'Aria' then" - " alter table mysql.spider_link_failed_log" - " engine=Aria transactional=1;" - " end if;" - " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_link_mon_servers';" - " if @engine_name != 'Aria' then" - " alter table mysql.spider_link_mon_servers" - " engine=Aria transactional=1;" - " end if;" - " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_table_crd';" - " if @engine_name != 'Aria' then" - " alter table mysql.spider_table_crd" - " engine=Aria transactional=1;" - " end if;" - " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_table_position_for_recovery';" - " if @engine_name != 'Aria' then" - " alter table mysql.spider_table_position_for_recovery" - " engine=Aria transactional=1;" - " end if;" - " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_table_sts';" - " if @engine_name != 'Aria' then" - " alter table mysql.spider_table_sts" - " engine=Aria transactional=1;" - " end if;" - " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_tables';" - " if @engine_name != 'Aria' then" - " alter table mysql.spider_tables" - " engine=Aria transactional=1;" - " end if;" - " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_xa';" - " if @engine_name != 'Aria' then" - " alter table mysql.spider_xa" - " engine=Aria transactional=1;" - " end if;" - " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_xa_failed_log';" - " if @engine_name != 'Aria' then" - " alter table mysql.spider_xa_failed_log" - " engine=Aria transactional=1;" - " end if;" - " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" - " where TABLE_SCHEMA = 'mysql'" - " AND TABLE_NAME = 'spider_xa_member';" - " if @engine_name != 'Aria' then" - " alter table mysql.spider_xa_member" - " engine=Aria transactional=1;" - " end if;" - " end if;" - " if @server_name = 'MariaDB' and" - " (" - " @server_major_version > 10 or" - " (" - " @server_major_version = 10 and" - " @server_minor_version >= 6" - " )" - " )" - " then" - " /* table for ddl pushdown */" - " create table if not exists mysql.spider_rewrite_tables(" - " table_id bigint unsigned not null auto_increment," - " db_name char(64) not null default ''," - " table_name char(64) not null default ''," - " primary key (table_id)," - " unique uk1(db_name, table_name)" - " ) engine=Aria transactional=1 default charset=utf8 collate=utf8_bin;" - " create table if not exists mysql.spider_rewrite_table_tables(" - " table_id bigint unsigned not null," - " partition_id bigint unsigned not null auto_increment," - " partition_method varchar(18) default ''," - " partition_expression varchar(64) default ''," - " subpartition_method varchar(12) default ''," - " subpartition_expression varchar(64) default ''," - " connection_str text not null default ''," - " comment_str text not null default ''," - " primary key (table_id, partition_id)," - " unique uk1(table_id, partition_method, partition_expression," - " subpartition_method, subpartition_expression)" - " ) engine=Aria transactional=1 default charset=utf8 collate=utf8_bin;" - " create table if not exists mysql.spider_rewrite_table_partitions(" - " table_id bigint unsigned not null," - " partition_id bigint unsigned not null," - " partition_ordinal_position bigint unsigned not null auto_increment," - " partition_name varchar(64) not null default ''," - " partition_description varchar(64) not null default ''," - " connection_str text not null default ''," - " comment_str text not null default ''," - " primary key (table_id, partition_id, partition_ordinal_position)," - " unique key uk1 (table_id, partition_id, partition_name)" - " ) engine=Aria transactional=1 default charset=utf8 collate=utf8_bin;" - " create table if not exists mysql.spider_rewrite_table_subpartitions(" - " table_id bigint unsigned not null," - " partition_id bigint unsigned not null," - " partition_ordinal_position bigint unsigned not null," - " subpartition_ordinal_position bigint unsigned not null" - " auto_increment," - " subpartition_name varchar(64) not null default ''," - " subpartition_description varchar(64) not null default ''," - " connection_str text not null default ''," - " comment_str text not null default ''," - " primary key (table_id, partition_id, partition_ordinal_position," - " subpartition_ordinal_position)," - " unique key uk1 (table_id, partition_id, partition_ordinal_position," - " subpartition_name)" - " ) engine=Aria transactional=1 default charset=utf8 collate=utf8_bin;" - " create table if not exists mysql.spider_rewritten_tables(" - " db_name char(64) not null," - " table_name char(64) not null," - " table_id bigint unsigned not null," - " partition_id bigint unsigned not null," - " primary key (db_name, table_name, table_id, partition_id)" - " ) engine=Aria transactional=1 default charset=utf8 collate=utf8_bin;" - " end if;" - "end;" + {C_STRING_WITH_LEN( + "select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_link_failed_log';" )}, {C_STRING_WITH_LEN( - "call mysql.spider_fix_system_tables" + "if @engine_name != 'Aria' then" + " alter table mysql.spider_link_failed_log" + " engine=Aria transactional=1;" + "end if;" )}, {C_STRING_WITH_LEN( - "drop procedure mysql.spider_fix_one_table" + "select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_link_mon_servers';" )}, {C_STRING_WITH_LEN( - "drop procedure mysql.spider_fix_system_tables" + "if @engine_name != 'Aria' then" + " alter table mysql.spider_link_mon_servers" + " engine=Aria transactional=1;" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_table_crd';" + )}, + {C_STRING_WITH_LEN( + "if @engine_name != 'Aria' then" + " alter table mysql.spider_table_crd" + " engine=Aria transactional=1;" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_table_position_for_recovery';" + )}, + {C_STRING_WITH_LEN( + "if @engine_name != 'Aria' then" + " alter table mysql.spider_table_position_for_recovery" + " engine=Aria transactional=1;" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_table_sts';" + )}, + {C_STRING_WITH_LEN( + "if @engine_name != 'Aria' then" + " alter table mysql.spider_table_sts" + " engine=Aria transactional=1;" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_tables';" + )}, + {C_STRING_WITH_LEN( + "if @engine_name != 'Aria' then" + " alter table mysql.spider_tables" + " engine=Aria transactional=1;" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_xa';" + )}, + {C_STRING_WITH_LEN( + "if @engine_name != 'Aria' then" + " alter table mysql.spider_xa" + " engine=Aria transactional=1;" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_xa_failed_log';" + )}, + {C_STRING_WITH_LEN( + "if @engine_name != 'Aria' then" + " alter table mysql.spider_xa_failed_log" + " engine=Aria transactional=1;" + "end if;" + )}, + {C_STRING_WITH_LEN( + "select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES" + " where TABLE_SCHEMA = 'mysql'" + " AND TABLE_NAME = 'spider_xa_member';" + )}, + {C_STRING_WITH_LEN( + "if @engine_name != 'Aria' then" + " alter table mysql.spider_xa_member" + " engine=Aria transactional=1;" + "end if;" )}, /* - Install a plugin and UDFs + Install UDFs */ {C_STRING_WITH_LEN( - "drop procedure if exists mysql.spider_plugin_installer" + "set @win_plugin := IF(@@version_compile_os like 'Win%', 1, 0);" )}, {C_STRING_WITH_LEN( - "create procedure mysql.spider_plugin_installer()" - "begin" - " set @win_plugin := IF(@@version_compile_os like 'Win%', 1, 0);" - " set @have_spider_direct_sql_udf := 0;" - " select @have_spider_direct_sql_udf := 1 from mysql.func" - " where name = 'spider_direct_sql';" - " if @have_spider_direct_sql_udf = 0 then" - " if @win_plugin = 0 then " - " create function spider_direct_sql returns int" - " soname 'ha_spider.so';" - " else" - " create function spider_direct_sql returns int" - " soname 'ha_spider.dll';" - " end if;" - " end if;" - " set @have_spider_bg_direct_sql_udf := 0;" - " select @have_spider_bg_direct_sql_udf := 1 from mysql.func" - " where name = 'spider_bg_direct_sql';" - " if @have_spider_bg_direct_sql_udf = 0 then" - " if @win_plugin = 0 then " - " create aggregate function spider_bg_direct_sql returns int" - " soname 'ha_spider.so';" - " else" - " create aggregate function spider_bg_direct_sql returns int" - " soname 'ha_spider.dll';" - " end if;" - " end if;" - " set @have_spider_ping_table_udf := 0;" - " select @have_spider_ping_table_udf := 1 from mysql.func" - " where name = 'spider_ping_table';" - " if @have_spider_ping_table_udf = 0 then" - " if @win_plugin = 0 then " - " create function spider_ping_table returns int" - " soname 'ha_spider.so';" - " else" - " create function spider_ping_table returns int" - " soname 'ha_spider.dll';" - " end if;" - " end if;" - " set @have_spider_copy_tables_udf := 0;" - " select @have_spider_copy_tables_udf := 1 from mysql.func" - " where name = 'spider_copy_tables';" - " if @have_spider_copy_tables_udf = 0 then" - " if @win_plugin = 0 then " - " create function spider_copy_tables returns int" - " soname 'ha_spider.so';" - " else" - " create function spider_copy_tables returns int" - " soname 'ha_spider.dll';" - " end if;" - " end if;" - " set @have_spider_flush_table_mon_cache_udf := 0;" - " select @have_spider_flush_table_mon_cache_udf := 1 from mysql.func" - " where name = 'spider_flush_table_mon_cache';" - " if @have_spider_flush_table_mon_cache_udf = 0 then" - " if @win_plugin = 0 then " - " create function spider_flush_table_mon_cache returns int" - " soname 'ha_spider.so';" - " else" - " create function spider_flush_table_mon_cache returns int" - " soname 'ha_spider.dll';" - " end if;" - " end if;" - "end;" + "if @win_plugin = 0 then" + " create function if not exists spider_direct_sql returns int" + " soname 'ha_spider.so';" + "else" + " create function if not exists spider_direct_sql returns int" + " soname 'ha_spider.dll';" + "end if;" )}, {C_STRING_WITH_LEN( - "call mysql.spider_plugin_installer" + "if @win_plugin = 0 then" + " create aggregate function if not exists spider_bg_direct_sql returns int" + " soname 'ha_spider.so';" + "else" + " create aggregate function if not exists spider_bg_direct_sql returns int" + " soname 'ha_spider.dll';" + "end if;" )}, {C_STRING_WITH_LEN( - "drop procedure mysql.spider_plugin_installer" + "if @win_plugin = 0 then" + " create function if not exists spider_ping_table returns int" + " soname 'ha_spider.so';" + "else" + " create function if not exists spider_ping_table returns int" + " soname 'ha_spider.dll';" + "end if;" + )}, + {C_STRING_WITH_LEN( + "if @win_plugin = 0 then" + " create function if not exists spider_copy_tables returns int" + " soname 'ha_spider.so';" + "else" + " create function if not exists spider_copy_tables returns int" + " soname 'ha_spider.dll';" + "end if;" + )}, + {C_STRING_WITH_LEN( + "if @win_plugin = 0 then" + " create function if not exists spider_flush_table_mon_cache returns int" + " soname 'ha_spider.so';" + "else" + " create function if not exists spider_flush_table_mon_cache returns int" + " soname 'ha_spider.dll';" + "end if;" )}, {C_STRING_WITH_LEN("")} }; From d8f5d2bef062853f30e071a46f4cd69fd01c6808 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Thu, 16 Nov 2023 11:00:09 +1100 Subject: [PATCH 396/477] MDEV-22979 MDEV-27233 MDEV-28218 Fixing spider init bugs Fix spider init bugs (MDEV-22979, MDEV-27233, MDEV-28218) while preventing regression on old ones (MDEV-30370, MDEV-29904) Two things are changed: First, Spider initialisation is made fully synchronous, i.e. it no longer happens in a background thread. Adapted from the original fix by nayuta for MDEV-27233. This change itself would cause failure when spider is initialised early, by plugin-load-add, due to dependency on Aria and udf function creation, which are fixed in the second and third parts below. Requires SQL Service, thus porting earlier versions requires MDEV-27595 Second, if spider is initialised before udf_init(), create udf by inserting into `mysql.func`, otherwise do it by `CREATE FUNCTION` as usual. This change may be generalised in MDEV-31401. Also factor out some clean-up queries from deinit_spider.inc for use of spider init tests. A minor caveat is that early spider initialisation will fail if the server is bootstrapped for the first time, due to missing `mysql` database which needs to be created by the bootstrap script. --- .../spider/bugfix/r/mdev_22979.result | 5 + .../spider/bugfix/r/mdev_27233.result | 11 ++ .../spider/bugfix/r/mdev_28218.result | 9 ++ .../bugfix/r/mdev_28218_init_file.result | 5 + .../spider/bugfix/r/mdev_28218_mixed.result | 5 + .../spider/bugfix/r/mdev_30370.result | 4 + .../bugfix/r/plugin_load_add_all.result | 7 + .../bugfix/r/plugin_load_add_spider.result | 7 + .../bugfix/r/udf_mysql_func_early.result | 43 +++++ .../r/udf_mysql_func_early_init_file.result | 1 + .../spider/bugfix/t/mdev_22979.test | 18 +++ .../mysql-test/spider/bugfix/t/mdev_27233.opt | 1 + .../mysql-test/spider/bugfix/t/mdev_27233.sql | 3 + .../spider/bugfix/t/mdev_27233.test | 7 + .../spider/bugfix/t/mdev_28218.test | 10 ++ .../spider/bugfix/t/mdev_28218_init_file.opt | 1 + .../spider/bugfix/t/mdev_28218_init_file.sql | 2 + .../spider/bugfix/t/mdev_28218_init_file.test | 7 + .../spider/bugfix/t/mdev_28218_mixed.opt | 2 + .../spider/bugfix/t/mdev_28218_mixed.sql | 1 + .../spider/bugfix/t/mdev_28218_mixed.test | 8 + .../spider/bugfix/t/mdev_30370.test | 8 +- .../spider/bugfix/t/plugin_load_add_all.opt | 1 + .../spider/bugfix/t/plugin_load_add_all.test | 7 + .../bugfix/t/plugin_load_add_spider.opt | 1 + .../bugfix/t/plugin_load_add_spider.test | 7 + .../spider/bugfix/t/udf_mysql_func_early.cnf | 3 + .../spider/bugfix/t/udf_mysql_func_early.opt | 1 + .../spider/bugfix/t/udf_mysql_func_early.test | 48 ++++++ .../t/udf_mysql_func_early_init_file.cnf | 3 + .../t/udf_mysql_func_early_init_file.opt | 1 + .../t/udf_mysql_func_early_init_file.sql | 1 + .../t/udf_mysql_func_early_init_file.test | 4 + storage/spider/spd_include.h | 1 - storage/spider/spd_init_query.h | 86 +++++----- storage/spider/spd_table.cc | 147 +++++++----------- 36 files changed, 337 insertions(+), 139 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_22979.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_27233.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_28218.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_28218_init_file.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_28218_mixed.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/plugin_load_add_all.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/plugin_load_add_spider.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early.result create mode 120000 storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early_init_file.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_22979.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_27233.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_27233.sql create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_27233.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_28218.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.sql create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.sql create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_all.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_all.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_spider.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_spider.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.sql create mode 100644 storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_22979.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_22979.result new file mode 100644 index 00000000000..b3049af3e67 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_22979.result @@ -0,0 +1,5 @@ +MDEV-22979 "mysqld --bootstrap" / mysql_install_db hangs when Spider is installed +# Kill the server +# restart +Warnings: +Note 1305 SONAME ha_spider.so does not exist diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_27233.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_27233.result new file mode 100644 index 00000000000..17f3316b625 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_27233.result @@ -0,0 +1,11 @@ +# +# MDEV-27233 Server hangs when using --init-file which loads Spider and creates a Spider table +# +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `c` int(11) DEFAULT NULL +) ENGINE=SPIDER DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +Warnings: +Error 1429 Unable to connect to foreign data source: localhost +Error 1429 Unable to connect to foreign data source: localhost diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28218.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28218.result new file mode 100644 index 00000000000..394d3b271b5 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28218.result @@ -0,0 +1,9 @@ +# +# MDEV-28218 Spider: thread hang/deadlock as result of INSTALL PLUGIN and DROP TABLE +# +INSTALL SONAME 'ha_spider.so'; +DROP TABLE IF EXISTS mysql.spider_tables; +show create table mysql.spider_tables; +ERROR 42S02: Table 'mysql.spider_tables' doesn't exist +Warnings: +Note 1051 Unknown table 'mysql.spider_tables' diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28218_init_file.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28218_init_file.result new file mode 100644 index 00000000000..05c396acb99 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28218_init_file.result @@ -0,0 +1,5 @@ +# +# MDEV-28218 Spider: thread hang/deadlock as result of INSTALL PLUGIN and DROP TABLE +# +show create table mysql.spider_tables; +ERROR 42S02: Table 'mysql.spider_tables' doesn't exist diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28218_mixed.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28218_mixed.result new file mode 100644 index 00000000000..05c396acb99 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28218_mixed.result @@ -0,0 +1,5 @@ +# +# MDEV-28218 Spider: thread hang/deadlock as result of INSTALL PLUGIN and DROP TABLE +# +show create table mysql.spider_tables; +ERROR 42S02: Table 'mysql.spider_tables' doesn't exist 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 df0f6949280..1ffbf2e6b01 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_30370.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_30370.result @@ -1,3 +1,7 @@ # # MDEV-30370 mariadbd hangs when running with --wsrep-recover and --plugin-load-add=ha_spider.so # +# Kill the server +# restart +Warnings: +Note 1305 SONAME ha_spider.so does not exist diff --git a/storage/spider/mysql-test/spider/bugfix/r/plugin_load_add_all.result b/storage/spider/mysql-test/spider/bugfix/r/plugin_load_add_all.result new file mode 100644 index 00000000000..04e5ed6da68 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/plugin_load_add_all.result @@ -0,0 +1,7 @@ +# +# plugin-load-add=ha_spider +# +select * from mysql.plugin; +name dl +create table t (c int) Engine=SPIDER; +drop table t; diff --git a/storage/spider/mysql-test/spider/bugfix/r/plugin_load_add_spider.result b/storage/spider/mysql-test/spider/bugfix/r/plugin_load_add_spider.result new file mode 100644 index 00000000000..04e5ed6da68 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/plugin_load_add_spider.result @@ -0,0 +1,7 @@ +# +# plugin-load-add=ha_spider +# +select * from mysql.plugin; +name dl +create table t (c int) Engine=SPIDER; +drop table t; diff --git a/storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early.result b/storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early.result new file mode 100644 index 00000000000..b84f60a67fb --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early.result @@ -0,0 +1,43 @@ +# +# Test that udf created by inserting into mysql_func works as expected +# +CREATE SERVER s_1 FOREIGN DATA WRAPPER mysql OPTIONS ( +HOST 'localhost', +DATABASE 'auto_test_local', +USER 'root', +PASSWORD '', +SOCKET '$MASTER_1_MYSOCK' + ); +CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS ( +HOST 'localhost', +DATABASE 'auto_test_remote', +USER 'root', +PASSWORD '', +SOCKET '$CHILD2_1_MYSOCK' + ); +connect master_1, localhost, root, , , $MASTER_1_MYPORT, $MASTER_1_MYSOCK; +connect child2_1, localhost, root, , , $CHILD2_1_MYPORT, $CHILD2_1_MYSOCK; +connection child2_1; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +CREATE TABLE tbl_a ( +a INT +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +insert into tbl_a values (42); +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +CREATE TABLE tbl_a ( +a INT +) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='table "tbl_a", srv "s_2_1"'; +create temporary table results (a int); +SELECT SPIDER_DIRECT_SQL('select * from tbl_a', 'results', 'srv "s_2_1", database "auto_test_remote"'); +SPIDER_DIRECT_SQL('select * from tbl_a', 'results', 'srv "s_2_1", database "auto_test_remote"') +1 +select * from results; +a +42 +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; diff --git a/storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early_init_file.result b/storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early_init_file.result new file mode 120000 index 00000000000..045ddc4372c --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early_init_file.result @@ -0,0 +1 @@ +udf_mysql_func_early.result \ No newline at end of file diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_22979.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_22979.test new file mode 100644 index 00000000000..7f42bd734c6 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_22979.test @@ -0,0 +1,18 @@ +--echo MDEV-22979 "mysqld --bootstrap" / mysql_install_db hangs when Spider is installed + +# This test is not the most faithful, as it does not have any +# dependency problems on the existence of the `mysql` database. To +# test MDEV-22979 faithfully, a mysql_install_db invocation with +# --plugin-load-add=ha_spider should be run. We cannot run it in mtr +# because we do not have access to --srcdir. + +let $MYSQLD_DATADIR= `select @@datadir`; +let $PLUGIN_DIR=`select @@plugin_dir`; +--source include/kill_mysqld.inc +--write_file $MYSQLTEST_VARDIR/tmp/mdev_22979.sql +drop table if exists foo.bar; +EOF +--exec $MYSQLD_CMD --datadir=$MYSQLD_DATADIR --bootstrap --plugin-dir=$PLUGIN_DIR --plugin-load-add=ha_spider < $MYSQLTEST_VARDIR/tmp/mdev_22979.sql +--source include/start_mysqld.inc +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.opt b/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.opt new file mode 100644 index 00000000000..7bc1c2127a6 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.opt @@ -0,0 +1 @@ +--init-file=$MYSQL_TEST_DIR/../storage/spider/mysql-test/spider/bugfix/t/mdev_27233.sql diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.sql b/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.sql new file mode 100644 index 00000000000..2be9ec1fad6 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.sql @@ -0,0 +1,3 @@ +INSTALL SONAME 'ha_spider.so'; +USE test; +CREATE TABLE t (c INT) ENGINE=SPIDER; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.test new file mode 100644 index 00000000000..88e70f4b689 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27233.test @@ -0,0 +1,7 @@ +--echo # +--echo # MDEV-27233 Server hangs when using --init-file which loads Spider and creates a Spider table +--echo # +# ps protocol eats warnings +--disable_ps_protocol +show create table t; +--enable_ps_protocol diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28218.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218.test new file mode 100644 index 00000000000..91fdf168f53 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218.test @@ -0,0 +1,10 @@ +--echo # +--echo # MDEV-28218 Spider: thread hang/deadlock as result of INSTALL PLUGIN and DROP TABLE +--echo # +INSTALL SONAME 'ha_spider.so'; +DROP TABLE IF EXISTS mysql.spider_tables; +--error ER_NO_SUCH_TABLE +show create table mysql.spider_tables; + +--disable_query_log +--source ../../include/clean_up_spider.inc 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 new file mode 100644 index 00000000000..f7ce5b39b5e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.opt @@ -0,0 +1 @@ +--init-file=$MYSQL_TEST_DIR/../storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.sql diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.sql b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.sql new file mode 100644 index 00000000000..ef3e1e91ce1 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.sql @@ -0,0 +1,2 @@ +INSTALL PLUGIN spider SONAME 'ha_spider.so'; +DROP TABLE IF EXISTS mysql.spider_tables; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.test new file mode 100644 index 00000000000..9152df4f684 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_init_file.test @@ -0,0 +1,7 @@ +--echo # +--echo # MDEV-28218 Spider: thread hang/deadlock as result of INSTALL PLUGIN and DROP TABLE +--echo # +# This is a variant of the testcase in MDEV-28218, where we put the +# queries are in an init file +--error ER_NO_SUCH_TABLE +show create table mysql.spider_tables; 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 new file mode 100644 index 00000000000..37d8664c6da --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.opt @@ -0,0 +1,2 @@ +--plugin-load-add=ha_spider +--init-file=$MYSQL_TEST_DIR/../storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.sql diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.sql b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.sql new file mode 100644 index 00000000000..e408ae0c04a --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS mysql.spider_tables; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.test new file mode 100644 index 00000000000..184a5399312 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28218_mixed.test @@ -0,0 +1,8 @@ +--echo # +--echo # MDEV-28218 Spider: thread hang/deadlock as result of INSTALL PLUGIN and DROP TABLE +--echo # +# this is a variant of the testcase in MDEV-28218, where we load +# spider early with --plugin_load_add, and execute the drop table +# query in an init file +--error ER_NO_SUCH_TABLE +show create table mysql.spider_tables; 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 955e77b4175..721a0996d96 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_30370.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_30370.test @@ -3,4 +3,10 @@ --echo # MDEV-30370 mariadbd hangs when running with --wsrep-recover and --plugin-load-add=ha_spider.so --echo # ---exec $MYSQLD_BOOTSTRAP_CMD --wsrep-recover --plugin-load-add=ha_spider.so +let $MYSQLD_DATADIR= `select @@datadir`; +let $PLUGIN_DIR=`select @@plugin_dir`; +--source include/kill_mysqld.inc +--exec $MYSQLD_CMD --datadir=$MYSQLD_DATADIR --wsrep-recover --plugin-dir=$PLUGIN_DIR --plugin-load-add=ha_spider +--source include/start_mysqld.inc +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_all.opt b/storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_all.opt new file mode 100644 index 00000000000..924ea4e31ef --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_all.opt @@ -0,0 +1 @@ +--plugin-load-add=ha_spider diff --git a/storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_all.test b/storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_all.test new file mode 100644 index 00000000000..396145fba2e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_all.test @@ -0,0 +1,7 @@ +--echo # +--echo # plugin-load-add=ha_spider +--echo # +# A simple test that tests plugin-load-add=ha_spider +select * from mysql.plugin; +create table t (c int) Engine=SPIDER; +drop table t; diff --git a/storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_spider.opt b/storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_spider.opt new file mode 100644 index 00000000000..bf4180ca67a --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_spider.opt @@ -0,0 +1 @@ +--plugin-load-add=SPIDER=ha_spider diff --git a/storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_spider.test b/storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_spider.test new file mode 100644 index 00000000000..49db6c38a28 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/plugin_load_add_spider.test @@ -0,0 +1,7 @@ +--echo # +--echo # plugin-load-add=ha_spider +--echo # +# A simple test that tests plugin-load-add=SPIDER=ha_spider +select * from mysql.plugin; +create table t (c int) Engine=SPIDER; +drop table t; diff --git a/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early.cnf b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early.cnf new file mode 100644 index 00000000000..05dfd8a0bce --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early.cnf @@ -0,0 +1,3 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early.opt b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early.opt new file mode 100644 index 00000000000..52144383000 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early.opt @@ -0,0 +1 @@ +--plugin-load-add=ha_spider \ No newline at end of file diff --git a/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early.test b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early.test new file mode 100644 index 00000000000..4edff9ca784 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early.test @@ -0,0 +1,48 @@ +--echo # +--echo # Test that udf created by inserting into mysql_func works as expected +--echo # + +evalp CREATE SERVER s_1 FOREIGN DATA WRAPPER mysql OPTIONS ( +HOST 'localhost', +DATABASE 'auto_test_local', +USER 'root', +PASSWORD '', +SOCKET '$MASTER_1_MYSOCK' + ); +evalp CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS ( +HOST 'localhost', +DATABASE 'auto_test_remote', +USER 'root', +PASSWORD '', +SOCKET '$CHILD2_1_MYSOCK' + ); + +--connect (master_1, localhost, root, , , $MASTER_1_MYPORT, $MASTER_1_MYSOCK) +--connect (child2_1, localhost, root, , , $CHILD2_1_MYPORT, $CHILD2_1_MYSOCK) + +--connection child2_1 +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +eval CREATE TABLE tbl_a ( + a INT +) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +insert into tbl_a values (42); + +--connection master_1 +CREATE DATABASE auto_test_local; +USE auto_test_local; +eval CREATE TABLE tbl_a ( + a INT +) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='table "tbl_a", srv "s_2_1"'; + +create temporary table results (a int); +--disable_ps_protocol +SELECT SPIDER_DIRECT_SQL('select * from tbl_a', 'results', 'srv "s_2_1", database "auto_test_remote"'); +--enable_ps_protocol +select * from results; + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; diff --git a/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.cnf b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.cnf new file mode 100644 index 00000000000..05dfd8a0bce --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.cnf @@ -0,0 +1,3 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf 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 new file mode 100644 index 00000000000..60bb42d2918 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.opt @@ -0,0 +1 @@ +--init-file=$MYSQL_TEST_DIR/../storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.sql diff --git a/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.sql b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.sql new file mode 100644 index 00000000000..9b767554185 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.sql @@ -0,0 +1 @@ +install soname "ha_spider.so"; diff --git a/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.test b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.test new file mode 100644 index 00000000000..57b4ee15220 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/udf_mysql_func_early_init_file.test @@ -0,0 +1,4 @@ +# Same as udf_mysql_func_early.test, except that we load spider in +# init_file, which is after udf_init() and before +# mysqld_server_started is on. +--source udf_mysql_func_early.test diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index c8b3eb979d7..f3df1ed8378 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -568,7 +568,6 @@ typedef struct st_spider_thread volatile bool killed; volatile bool thd_wait; volatile bool first_free_wait; - volatile bool init_command; volatile int error; pthread_t thread; pthread_cond_t cond; diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h index 1ed4fcdd8ff..32ef27052b0 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -585,56 +585,52 @@ static LEX_STRING spider_init_queries[] = { " engine=Aria transactional=1;" "end if;" )}, -/* - Install UDFs -*/ {C_STRING_WITH_LEN( "set @win_plugin := IF(@@version_compile_os like 'Win%', 1, 0);" )}, + /* Install UDFs. If udf is not initialised, then install by + inserting into mysql.func */ {C_STRING_WITH_LEN( "if @win_plugin = 0 then" - " create function if not exists spider_direct_sql returns int" - " soname 'ha_spider.so';" + " begin not atomic" + " declare exit handler for 1041, 1123" + " insert 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')," + " ('spider_copy_tables', 2, 'ha_spider.so', 'function')," + " ('spider_flush_table_mon_cache', 2, 'ha_spider.so', 'function');" + " create function if not exists spider_direct_sql returns int" + " soname 'ha_spider.so';" + " create aggregate function if not exists spider_bg_direct_sql returns int" + " soname 'ha_spider.so';" + " create function if not exists spider_ping_table returns int" + " soname 'ha_spider.so';" + " create function if not exists spider_copy_tables returns int" + " soname 'ha_spider.so';" + " create function if not exists spider_flush_table_mon_cache returns int" + " soname 'ha_spider.so';" + " end;" "else" - " create function if not exists spider_direct_sql returns int" - " soname 'ha_spider.dll';" + " begin not atomic" + " declare exit handler for 1041, 1123" + " insert 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')," + " ('spider_copy_tables', 2, 'ha_spider.dll', 'function')," + " ('spider_flush_table_mon_cache', 2, 'ha_spider.dll', 'function');" + " create function if not exists spider_direct_sql returns int" + " soname 'ha_spider.dll';" + " create aggregate function if not exists spider_bg_direct_sql returns int" + " soname 'ha_spider.dll';" + " create function if not exists spider_ping_table returns int" + " soname 'ha_spider.dll';" + " create function if not exists spider_copy_tables returns int" + " soname 'ha_spider.dll';" + " create function if not exists spider_flush_table_mon_cache returns int" + " soname 'ha_spider.dll';" + " end;" "end if;" - )}, - {C_STRING_WITH_LEN( - "if @win_plugin = 0 then" - " create aggregate function if not exists spider_bg_direct_sql returns int" - " soname 'ha_spider.so';" - "else" - " create aggregate function if not exists spider_bg_direct_sql returns int" - " soname 'ha_spider.dll';" - "end if;" - )}, - {C_STRING_WITH_LEN( - "if @win_plugin = 0 then" - " create function if not exists spider_ping_table returns int" - " soname 'ha_spider.so';" - "else" - " create function if not exists spider_ping_table returns int" - " soname 'ha_spider.dll';" - "end if;" - )}, - {C_STRING_WITH_LEN( - "if @win_plugin = 0 then" - " create function if not exists spider_copy_tables returns int" - " soname 'ha_spider.so';" - "else" - " create function if not exists spider_copy_tables returns int" - " soname 'ha_spider.dll';" - "end if;" - )}, - {C_STRING_WITH_LEN( - "if @win_plugin = 0 then" - " create function if not exists spider_flush_table_mon_cache returns int" - " soname 'ha_spider.so';" - "else" - " create function if not exists spider_flush_table_mon_cache returns int" - " soname 'ha_spider.dll';" - "end if;" - )}, - {C_STRING_WITH_LEN("")} + )} }; diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 48ccfbfac38..e47b8eff7a2 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -129,9 +129,6 @@ const char **spd_mysqld_unix_port; uint *spd_mysqld_port; bool volatile *spd_abort_loop; Time_zone *spd_tz_system; -static int *spd_mysqld_server_started; -static pthread_mutex_t *spd_LOCK_server_started; -static pthread_cond_t *spd_COND_server_started; extern long spider_conn_mutex_id; handlerton *spider_hton_ptr; SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE]; @@ -6316,30 +6313,6 @@ handler* spider_create_handler( MEM_ROOT *mem_root ) { DBUG_ENTER("spider_create_handler"); -#ifndef WITHOUT_SPIDER_BG_SEARCH - SPIDER_THREAD *thread = &spider_table_sts_threads[0]; - if (unlikely(thread->init_command)) - { - THD *thd = current_thd; - pthread_cond_t *cond = thd->mysys_var->current_cond; - pthread_mutex_t *mutex = thd->mysys_var->current_mutex; - /* wait for finishing init_command */ - pthread_mutex_lock(&thread->mutex); - if (unlikely(thread->init_command)) - { - thd->mysys_var->current_cond = &thread->sync_cond; - thd->mysys_var->current_mutex = &thread->mutex; - pthread_cond_wait(&thread->sync_cond, &thread->mutex); - } - pthread_mutex_unlock(&thread->mutex); - thd->mysys_var->current_cond = cond; - thd->mysys_var->current_mutex = mutex; - if (thd->killed) - { - DBUG_RETURN(NULL); - } - } -#endif DBUG_RETURN(new (mem_root) ha_spider(hton, table)); } @@ -6640,6 +6613,50 @@ int spider_panic( DBUG_RETURN(0); } +/* + Create or fix the system tables. See spd_init_query.h for the details. +*/ +bool spider_init_system_tables() +{ + DBUG_ENTER("spider_init_system_tables"); + + MYSQL *mysql= mysql_init(NULL); + if (!mysql) + { + DBUG_RETURN(TRUE); + } + + if (!mysql_real_connect_local(mysql)) + { + mysql_close(mysql); + DBUG_RETURN(TRUE); + } + + const int size= sizeof(spider_init_queries) / sizeof(spider_init_queries[0]); + for (int i= 0; i < size; i++) + { + const LEX_STRING *query= &spider_init_queries[i]; + if (mysql_real_query(mysql, query->str, query->length)) + { + fprintf(stderr, + "[ERROR] SPIDER plugin initialization failed at '%s' by '%s'\n", + query->str, mysql_error(mysql)); + + mysql_close(mysql); + DBUG_RETURN(TRUE); + } + + if (MYSQL_RES *res= mysql_store_result(mysql)) + { + mysql_free_result(res); + } + } + + mysql_close(mysql); + + DBUG_RETURN(FALSE); +} + int spider_db_init( void *p ) { @@ -6647,6 +6664,11 @@ int spider_db_init( uint dbton_id = 0; handlerton *spider_hton = (handlerton *)p; DBUG_ENTER("spider_db_init"); + + const LEX_CSTRING aria_name={STRING_WITH_LEN("Aria")}; + if (!plugin_is_ready(&aria_name, MYSQL_STORAGE_ENGINE_PLUGIN)) + DBUG_RETURN(HA_ERR_RETRY_INIT); + spider_hton_ptr = spider_hton; spider_hton->state = SHOW_OPTION_YES; @@ -6743,13 +6765,6 @@ int spider_db_init( #else GetProcAddress(current_module, "?my_tz_SYSTEM@@3PAVTime_zone@@A"); #endif - spd_mysqld_server_started = (int *) - GetProcAddress(current_module, "?mysqld_server_started@@3HA"); - spd_LOCK_server_started = (pthread_mutex_t *) - GetProcAddress(current_module, - "?LOCK_server_started@@3Ust_mysql_mutex@@A"); - spd_COND_server_started = (pthread_cond_t *) - GetProcAddress(current_module, "?COND_server_started@@3Ust_mysql_cond@@A"); #else #ifndef SPIDER_HAS_NEXT_THREAD_ID spd_db_att_thread_id = &thread_id; @@ -6772,9 +6787,6 @@ int spider_db_init( spd_mysqld_port = &mysqld_port; spd_abort_loop = &abort_loop; spd_tz_system = my_tz_SYSTEM; - spd_mysqld_server_started = &mysqld_server_started; - spd_LOCK_server_started = &LOCK_server_started; - spd_COND_server_started = &COND_server_started; #endif #ifdef HAVE_PSI_INTERFACE @@ -7050,6 +7062,11 @@ int spider_db_init( spider_udf_table_mon_list_hash[roop_count].array.size_of_element); } + if (spider_init_system_tables()) + { + goto error_system_table_creation; + } + #ifndef WITHOUT_SPIDER_BG_SEARCH if (!(spider_table_sts_threads = (SPIDER_THREAD *) spider_bulk_malloc(NULL, SPD_MID_DB_INIT_12, MYF(MY_WME | MY_ZEROFILL), @@ -7060,7 +7077,6 @@ int spider_db_init( NullS)) ) goto error_alloc_mon_mutxes; - spider_table_sts_threads[0].init_command = TRUE; for (roop_count = 0; roop_count < (int) spider_param_table_sts_thread_count(); @@ -7151,6 +7167,7 @@ error_init_udf_table_mon_list_hash: error_init_udf_table_mon_cond: for (; roop_count >= 0; roop_count--) pthread_cond_destroy(&spider_udf_table_mon_conds[roop_count]); +error_system_table_creation: roop_count = spider_param_udf_table_mon_mutex_count() - 1; error_init_udf_table_mon_mutex: for (; roop_count >= 0; roop_count--) @@ -9557,7 +9574,6 @@ void spider_free_sts_threads( ) { bool thread_killed; DBUG_ENTER("spider_free_sts_threads"); - spider_thread->init_command = FALSE; pthread_mutex_lock(&spider_thread->mutex); thread_killed = spider_thread->killed; spider_thread->killed = TRUE; @@ -9708,59 +9724,6 @@ void *spider_table_bg_sts_action( trx->thd = thd; /* init end */ - if (thread->init_command) - { - uint i = 0; - tmp_disable_binlog(thd); - thd->security_ctx->skip_grants(); - thd->client_capabilities |= CLIENT_MULTI_RESULTS; - if (!(*spd_mysqld_server_started) && !thd->killed && !thread->killed) - { - pthread_mutex_lock(spd_LOCK_server_started); - thd->mysys_var->current_cond = spd_COND_server_started; - thd->mysys_var->current_mutex = spd_LOCK_server_started; - if (!(*spd_mysqld_server_started) && !thd->killed && !thread->killed && - thread->init_command) - { - do - { - struct timespec abstime; - set_timespec_nsec(abstime, 1000); - error_num = pthread_cond_timedwait(spd_COND_server_started, - spd_LOCK_server_started, &abstime); - } while ( - (error_num == ETIMEDOUT || error_num == ETIME) && - !(*spd_mysqld_server_started) && !thd->killed && !thread->killed && - thread->init_command - ); - } - pthread_mutex_unlock(spd_LOCK_server_started); - thd->mysys_var->current_cond = &thread->cond; - thd->mysys_var->current_mutex = &thread->mutex; - } - bool spd_wsrep_on = thd->variables.wsrep_on; - thd->variables.wsrep_on = false; - while (spider_init_queries[i].length && !thd->killed && !thread->killed && - thread->init_command) - { - dispatch_command(COM_QUERY, thd, spider_init_queries[i].str, - (uint) spider_init_queries[i].length, FALSE, FALSE); - if (unlikely(thd->is_error())) - { - fprintf(stderr, "[ERROR] %s\n", spider_stmt_da_message(thd)); - thd->clear_error(); - break; - } - ++i; - } - thd->variables.wsrep_on = spd_wsrep_on; - thd->mysys_var->current_cond = &thread->cond; - thd->mysys_var->current_mutex = &thread->mutex; - thd->client_capabilities -= CLIENT_MULTI_RESULTS; - reenable_binlog(thd); - thread->init_command = FALSE; - pthread_cond_broadcast(&thread->sync_cond); - } if (thd->killed) { thread->killed = TRUE; From 70283aca3444cf61f1e298cb68de6b8e6c25796a Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 20 Oct 2023 10:28:34 +1100 Subject: [PATCH 397/477] 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 30af98725998724ebcb3c33b71cc0e41ba6c0cbd Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Thu, 19 Oct 2023 12:15:39 +1100 Subject: [PATCH 398/477] 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 9259b4b8494ca532d4e7fd1162465ee2b19ac8a4 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 17 Oct 2023 15:02:12 +1100 Subject: [PATCH 399/477] 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 32ef27052b0..df3e8c7979d 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -594,7 +594,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')," @@ -614,7 +614,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 69389c03b16e5957980beb662c4b2f6775a1bba1 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 7 Nov 2023 11:00:49 +0100 Subject: [PATCH 400/477] 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 | 99 ++++++++++++------- 3 files changed, 96 insertions(+), 33 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 df3e8c7979d..0c26a88c8d3 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -198,7 +198,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 @@ -212,7 +213,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( @@ -224,7 +226,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;" )}, /* @@ -234,14 +237,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 @@ -257,7 +262,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" @@ -270,7 +276,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" @@ -283,7 +290,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 @@ -297,7 +305,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;" )}, /* @@ -319,7 +328,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( @@ -336,7 +346,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( @@ -353,7 +364,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;" )}, /* @@ -362,7 +374,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 @@ -370,12 +383,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" @@ -386,7 +401,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( @@ -398,7 +414,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;" )}, /* @@ -413,7 +430,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( @@ -425,7 +443,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( @@ -437,7 +456,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( @@ -449,7 +469,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( @@ -461,7 +482,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( @@ -473,7 +495,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;" )}, /* @@ -481,7 +504,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 @@ -494,7 +518,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( @@ -505,7 +530,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( @@ -516,7 +542,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( @@ -527,7 +554,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( @@ -538,7 +566,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( @@ -549,7 +578,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( @@ -560,7 +590,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( @@ -571,7 +602,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( @@ -582,7 +614,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;" )}, {C_STRING_WITH_LEN( From ba94778d2c438d4c0f93ce031e504f7d78e895e1 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 14 Nov 2023 17:32:56 +1100 Subject: [PATCH 401/477] MDEV-32753 Make spider init queries compatible with oracle sql mode Remove ORACLE from the (session) sql_mode in connections made with sql service to run init queries The connection is new and the global variable value takes effect rather than the session value from the caller of spider_db_init. --- .../spider/bugfix/r/mdev_32753.result | 10 +++++++++ .../bugfix/r/mdev_32753_after_start.result | 13 +++++++++++ .../r/mdev_32753_after_start_session.result | 16 ++++++++++++++ .../mysql-test/spider/bugfix/t/mdev_32753.opt | 2 ++ .../spider/bugfix/t/mdev_32753.test | 12 ++++++++++ .../bugfix/t/mdev_32753_after_start.opt | 1 + .../bugfix/t/mdev_32753_after_start.test | 19 ++++++++++++++++ .../t/mdev_32753_after_start_session.test | 22 +++++++++++++++++++ .../spider/include/clean_up_spider.inc | 2 +- storage/spider/spd_init_query.h | 3 +++ 10 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_32753.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start_session.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_32753.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_32753.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start_session.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_32753.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_32753.result new file mode 100644 index 00000000000..4260d80f0cf --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_32753.result @@ -0,0 +1,10 @@ +# +# MDEV-32753 Spider engine does not load in ORACLE mode +# +select * from mysql.plugin; +name dl +create table t (c int) Engine=SPIDER; +drop table t; +# +# end of test mdev_32753 +# diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start.result new file mode 100644 index 00000000000..9ca01594054 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start.result @@ -0,0 +1,13 @@ +# +# MDEV-32753 Spider engine does not load in ORACLE mode +# +install soname 'ha_spider'; +select * from mysql.plugin; +name dl +SPIDER ha_spider.so +SPIDER_ALLOC_MEM ha_spider.so +create table t (c int) Engine=SPIDER; +drop table t; +# +# end of test mdev_32753_after_start +# diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start_session.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start_session.result new file mode 100644 index 00000000000..5a3643499d2 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_32753_after_start_session.result @@ -0,0 +1,16 @@ +# +# MDEV-32753 Spider engine does not load in ORACLE mode +# +set @old_sql_mode=@@sql_mode; +SET @@sql_mode = CONCAT(@@sql_mode, ',ORACLE'); +install soname 'ha_spider'; +select * from mysql.plugin; +name dl +SPIDER ha_spider.so +SPIDER_ALLOC_MEM ha_spider.so +create table t (c int) Engine=SPIDER; +drop table t; +set sql_mode=@old_sql_mode; +# +# end of test mdev_32753_after_start +# diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32753.opt b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753.opt new file mode 100644 index 00000000000..c3151b0e44a --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753.opt @@ -0,0 +1,2 @@ +--sql-mode=oracle +--plugin-load-add=ha_spider diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32753.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753.test new file mode 100644 index 00000000000..2be7289fd74 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753.test @@ -0,0 +1,12 @@ +--echo # +--echo # MDEV-32753 Spider engine does not load in ORACLE mode +--echo # + +# This test tests spider init during server startup under global +# ORACLE mode +select * from mysql.plugin; +create table t (c int) Engine=SPIDER; +drop table t; +--echo # +--echo # end of test mdev_32753 +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.opt b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.opt new file mode 100644 index 00000000000..a918abb90b9 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.opt @@ -0,0 +1 @@ +--sql-mode=oracle diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.test new file mode 100644 index 00000000000..281d2adce64 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.test @@ -0,0 +1,19 @@ +--echo # +--echo # MDEV-32753 Spider engine does not load in ORACLE mode +--echo # + +# This test tests spider init after startup under global ORACLE mode +install soname 'ha_spider'; +select * from mysql.plugin; +create table t (c int) Engine=SPIDER; +drop table t; + +--disable_query_log +--disable_result_log +--source ../../include/clean_up_spider.inc +--enable_result_log +--enable_query_log + +--echo # +--echo # end of test mdev_32753_after_start +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start_session.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start_session.test new file mode 100644 index 00000000000..bf7bdb4f884 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start_session.test @@ -0,0 +1,22 @@ +--echo # +--echo # MDEV-32753 Spider engine does not load in ORACLE mode +--echo # + +# This test tests spider init after startup under session ORACLE mode +set @old_sql_mode=@@sql_mode; +SET @@sql_mode = CONCAT(@@sql_mode, ',ORACLE'); +install soname 'ha_spider'; +select * from mysql.plugin; +create table t (c int) Engine=SPIDER; +drop table t; +set sql_mode=@old_sql_mode; + +--disable_query_log +--disable_result_log +--source ../../include/clean_up_spider.inc +--enable_result_log +--enable_query_log + +--echo # +--echo # end of test mdev_32753_after_start +--echo # diff --git a/storage/spider/mysql-test/spider/include/clean_up_spider.inc b/storage/spider/mysql-test/spider/include/clean_up_spider.inc index 1f0659dc98a..249606ec774 100644 --- a/storage/spider/mysql-test/spider/include/clean_up_spider.inc +++ b/storage/spider/mysql-test/spider/include/clean_up_spider.inc @@ -3,7 +3,7 @@ DROP FUNCTION spider_copy_tables; DROP FUNCTION spider_ping_table; DROP FUNCTION spider_bg_direct_sql; DROP FUNCTION spider_direct_sql; -UNINSTALL SONAME IF EXISTS "ha_spider"; +UNINSTALL SONAME IF EXISTS 'ha_spider'; DROP TABLE IF EXISTS mysql.spider_xa; DROP TABLE IF EXISTS mysql.spider_xa_member; DROP TABLE IF EXISTS mysql.spider_xa_failed_log; diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h index 0c26a88c8d3..b8d1751a21b 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -20,6 +20,9 @@ */ static LEX_STRING spider_init_queries[] = { + {C_STRING_WITH_LEN( + "SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'ORACLE', '');" + )}, {C_STRING_WITH_LEN( "create table if not exists mysql.spider_xa(" " format_id int not null default 0," From d018b9099001292cfe29c263b05db1edc9a21469 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 6 Dec 2023 20:57:23 +0530 Subject: [PATCH 402/477] MDEV-32920 innodb_buffer_pool_read_requests always 0 srv_export_innodb_status(): Update export_vars.innodb_buffer_pool_read_requests with buf_pool.stat.n_page_gets. This is caused due to incorrect merge commit 44c9008ba65686abf1c82c9166255a8c52d61f74 --- mysql-test/suite/innodb/r/innodb_force_recovery.result | 9 +++++++++ mysql-test/suite/innodb/t/innodb_force_recovery.test | 10 ++++++++++ storage/innobase/srv/srv0srv.cc | 3 +++ 3 files changed, 22 insertions(+) diff --git a/mysql-test/suite/innodb/r/innodb_force_recovery.result b/mysql-test/suite/innodb/r/innodb_force_recovery.result index 05239950678..2f1169f4147 100644 --- a/mysql-test/suite/innodb/r/innodb_force_recovery.result +++ b/mysql-test/suite/innodb/r/innodb_force_recovery.result @@ -4,9 +4,18 @@ insert into t1 values(1, 2); insert into t2 values(1, 2); SET GLOBAL innodb_fast_shutdown = 0; # restart: --innodb-force-recovery=4 +SELECT CAST(variable_value AS INTEGER) INTO @read1 +FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME='innodb_buffer_pool_read_requests'; select * from t1; f1 f2 1 2 +SELECT CAST(variable_value AS INTEGER) INTO @read2 +FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME='innodb_buffer_pool_read_requests'; +SELECT @read1>0, @read2>@read1; +@read1>0 @read2>@read1 +1 1 begin; insert into t1 values(2, 3); rollback; diff --git a/mysql-test/suite/innodb/t/innodb_force_recovery.test b/mysql-test/suite/innodb/t/innodb_force_recovery.test index 2368af76f09..30364c06bb3 100644 --- a/mysql-test/suite/innodb/t/innodb_force_recovery.test +++ b/mysql-test/suite/innodb/t/innodb_force_recovery.test @@ -21,8 +21,18 @@ SET GLOBAL innodb_fast_shutdown = 0; --source include/restart_mysqld.inc let $status=`SHOW ENGINE INNODB STATUS`; +SELECT CAST(variable_value AS INTEGER) INTO @read1 +FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME='innodb_buffer_pool_read_requests'; + select * from t1; +SELECT CAST(variable_value AS INTEGER) INTO @read2 +FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME='innodb_buffer_pool_read_requests'; + +SELECT @read1>0, @read2>@read1; + begin; insert into t1 values(2, 3); rollback; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index bf9755fb6d3..441530b048d 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -901,6 +901,9 @@ srv_export_innodb_status(void) export_vars.innodb_data_written = srv_stats.data_written + (dblwr << srv_page_size_shift); + export_vars.innodb_buffer_pool_read_requests + = buf_pool.stat.n_page_gets; + export_vars.innodb_buffer_pool_bytes_data = buf_pool.stat.LRU_bytes + (UT_LIST_GET_LEN(buf_pool.unzip_LRU) From d5a6ea36f384172205ab7a95de504b1b4cbd3136 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Thu, 7 Dec 2023 18:44:28 +0530 Subject: [PATCH 403/477] MDEV-32242 innodb.doublewrite test case always gets skipped MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Split the doublewrite test into two test (doublewrite, doublewrite_debug) to reduce the execution time of the test - Removed big_test tag for the newly added test case - Made doublewrite test as non-debug test - Added search pattern to make sure that InnoDB uses doublewrite buffer - Replaced all kill_mysqld.inc with shutdown_mysqld.inc and zero shutdown timeout - Removed the case where fsp_flags got corrupted. Because from commit 3da5d047b8d8c193a872c5ae6c3fb213218117bc (MDEV-31851) onwards, doublewrite buffer removes the conversion the fsp flags from buggy 10.1 format Thanks to Marko Mäkelä for providing the non-debug test --- mysql-test/suite/innodb/r/doublewrite.result | 266 +---------- .../suite/innodb/r/doublewrite_debug.result | 92 ++++ mysql-test/suite/innodb/t/doublewrite.test | 423 ++---------------- .../innodb/t/doublewrite_debug.combinations | 7 + .../suite/innodb/t/doublewrite_debug.test | 162 +++++++ storage/innobase/handler/ha_innodb.cc | 14 +- 6 files changed, 326 insertions(+), 638 deletions(-) create mode 100644 mysql-test/suite/innodb/r/doublewrite_debug.result create mode 100644 mysql-test/suite/innodb/t/doublewrite_debug.combinations create mode 100644 mysql-test/suite/innodb/t/doublewrite_debug.test diff --git a/mysql-test/suite/innodb/r/doublewrite.result b/mysql-test/suite/innodb/r/doublewrite.result index 1f26f7d1f5f..7763aa99322 100644 --- a/mysql-test/suite/innodb/r/doublewrite.result +++ b/mysql-test/suite/innodb/r/doublewrite.result @@ -1,22 +1,6 @@ # -# Bug #17335427 INNODB CAN NOT USE THE DOUBLEWRITE BUFFER PROPERLY -# Bug #18144349 INNODB CANNOT USE THE DOUBLEWRITE BUFFER FOR THE FIRST -# PAGE OF SYSTEM TABLESPACE +# MDEV-32242 innodb.doublewrite test case always is skipped # -SET GLOBAL innodb_fast_shutdown = 0; -# restart -show variables like 'innodb_doublewrite'; -Variable_name Value -innodb_doublewrite ON -show variables like 'innodb_fil_make_page_dirty_debug'; -Variable_name Value -innodb_fil_make_page_dirty_debug 0 -show variables like 'innodb_saved_page_number_debug'; -Variable_name Value -innodb_saved_page_number_debug 0 -connect stop_purge,localhost,root,,; -START TRANSACTION WITH CONSISTENT SNAPSHOT; -connection default; create table t1 (f1 int primary key, f2 blob) engine=innodb; start transaction; insert into t1 values(1, repeat('#',12)); @@ -25,29 +9,20 @@ insert into t1 values(3, repeat('/',12)); insert into t1 values(4, repeat('-',12)); insert into t1 values(5, repeat('.',12)); commit work; -# --------------------------------------------------------------- -# Test Begin: Test if recovery works if first page of user -# tablespace is full of zeroes. -select space from information_schema.innodb_sys_tables -where name = 'test/t1' into @space_id; -Warnings: -Warning 1287 ' INTO FROM...' instead -begin; -insert into t1 values (6, repeat('%', 12)); -# Ensure that dirty pages of table t1 are flushed. -set global innodb_buf_flush_list_now = 1; -# Make the first page dirty for table t1 -set global innodb_saved_page_number_debug = 0; -set global innodb_fil_make_page_dirty_debug = @space_id; -# Ensure that dirty pages of table t1 are flushed. -set global innodb_buf_flush_list_now = 1; -# Kill the server -disconnect stop_purge; -# Make the first page (page_no=0) of the user tablespace -# full of zeroes. -# -# MDEV-11623: Use old FSP_SPACE_FLAGS in the doublewrite buffer. +SET GLOBAL innodb_fast_shutdown = 0; # restart +connect dml,localhost,root,,; +XA START 'x'; +insert into t1 values (6, repeat('%', @@innodb_page_size/2)); +XA END 'x'; +XA PREPARE 'x'; +disconnect dml; +connection default; +flush table t1 for export; +# restart +FOUND 1 /InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile/ in mysqld.1.err +FOUND 1 /InnoDB: Recovered page \[page id: space=[1-9][0-9]*, page number=3\]/ in mysqld.1.err +XA ROLLBACK 'x'; check table t1; Table Op Msg_type Msg_text test.t1 check status OK @@ -58,216 +33,5 @@ f1 f2 3 //////////// 4 ------------ 5 ............ -# Test End -# --------------------------------------------------------------- -# Test Begin: Test if recovery works if first page of user -# tablespace is corrupted. -select space from information_schema.innodb_sys_tables -where name = 'test/t1' into @space_id; -Warnings: -Warning 1287 ' INTO FROM...' instead -# Ensure that dirty pages of table t1 is flushed. -flush tables t1 for export; -unlock tables; -begin; -insert into t1 values (6, repeat('%', 12)); -# Make the first page dirty for table t1 -set global innodb_saved_page_number_debug = 0; -set global innodb_fil_make_page_dirty_debug = @space_id; -# Ensure that dirty pages of table t1 are flushed. -set global innodb_buf_flush_list_now = 1; -# Kill the server -# Corrupt the first page (page_no=0) of the user tablespace. -# restart -check table t1; -Table Op Msg_type Msg_text -test.t1 check status OK -select f1, f2 from t1; -f1 f2 -1 ############ -2 ++++++++++++ -3 //////////// -4 ------------ -5 ............ -# Test End -# --------------------------------------------------------------- -# Test Begin: Test if recovery works if 2nd page of user -# tablespace is full of zeroes. -select space from information_schema.innodb_sys_tables -where name = 'test/t1' into @space_id; -Warnings: -Warning 1287 ' INTO FROM...' instead -# Ensure that dirty pages of table t1 is flushed. -flush tables t1 for export; -unlock tables; -begin; -insert into t1 values (6, repeat('%', 400)); -# Make the 2nd page dirty for table t1 -set global innodb_saved_page_number_debug = 1; -set global innodb_fil_make_page_dirty_debug = @space_id; -# Ensure that dirty pages of table t1 are flushed. -set global innodb_buf_flush_list_now = 1; -# Kill the server -# Make the 2nd page (page_no=1) of the tablespace all zeroes. -# restart -check table t1; -Table Op Msg_type Msg_text -test.t1 check status OK -select f1, f2 from t1; -f1 f2 -1 ############ -2 ++++++++++++ -3 //////////// -4 ------------ -5 ............ -# Test End -# --------------------------------------------------------------- -# Test Begin: Test if recovery works if 2nd page of user -# tablespace is corrupted. -select space from information_schema.innodb_sys_tables -where name = 'test/t1' into @space_id; -Warnings: -Warning 1287 ' INTO FROM...' instead -# Ensure that dirty pages of table t1 is flushed. -flush tables t1 for export; -unlock tables; -begin; -insert into t1 values (6, repeat('%', 400)); -# Make the 2nd page dirty for table t1 -set global innodb_saved_page_number_debug = 1; -set global innodb_fil_make_page_dirty_debug = @space_id; -# Ensure that the dirty pages of table t1 are flushed. -set global innodb_buf_flush_list_now = 1; -# Kill the server -# Corrupt the 2nd page (page_no=1) of the user tablespace. -# restart -check table t1; -Table Op Msg_type Msg_text -test.t1 check status OK -select f1, f2 from t1; -f1 f2 -1 ############ -2 ++++++++++++ -3 //////////// -4 ------------ -5 ............ -# Test End -# --------------------------------------------------------------- -# Test Begin: Test if recovery works if first page of -# system tablespace is full of zeroes. -begin; -insert into t1 values (6, repeat('%', 400)); -# Ensure that all dirty pages in the system are flushed. -set global innodb_buf_flush_list_now = 1; -# Make the first page dirty for system tablespace -set global innodb_saved_page_number_debug = 0; -set global innodb_fil_make_page_dirty_debug = 0; -# Ensure that the dirty page of system tablespace is also flushed. -set global innodb_buf_flush_list_now = 1; -# Kill the server -# Make the first page (page_no=0) of the system tablespace -# all zeroes. -# restart -check table t1; -Table Op Msg_type Msg_text -test.t1 check status OK -select f1, f2 from t1; -f1 f2 -1 ############ -2 ++++++++++++ -3 //////////// -4 ------------ -5 ............ -# Test End -# --------------------------------------------------------------- -# Test Begin: Test if recovery works if first page of -# system tablespace is corrupted. -begin; -insert into t1 values (6, repeat('%', 400)); -# Ensure that all dirty pages in the system are flushed. -set global innodb_buf_flush_list_now = 1; -# Make the first page dirty for system tablespace -set global innodb_saved_page_number_debug = 0; -set global innodb_fil_make_page_dirty_debug = 0; -# Ensure that the dirty page of system tablespace is also flushed. -set global innodb_buf_flush_list_now = 1; -# Kill the server -# Corrupt the first page (page_no=0) of the system tablespace. -# restart -check table t1; -Table Op Msg_type Msg_text -test.t1 check status OK -select f1, f2 from t1; -f1 f2 -1 ############ -2 ++++++++++++ -3 //////////// -4 ------------ -5 ............ -# Test End -# --------------------------------------------------------------- -# Test Begin: Test if recovery works if 2nd page of -# system tablespace is full of zeroes. -begin; -insert into t1 values (6, repeat('%', 400)); -# Ensure that all dirty pages in the system are flushed. -set global innodb_buf_flush_list_now = 1; -# Make the second page dirty for system tablespace -set global innodb_saved_page_number_debug = 1; -set global innodb_fil_make_page_dirty_debug = 0; -# Ensure that the dirty page of system tablespace is also flushed. -set global innodb_buf_flush_list_now = 1; -# Kill the server -# Make the 2nd page (page_no=1) of the system tablespace -# all zeroes. -# restart -check table t1; -Table Op Msg_type Msg_text -test.t1 check status OK -select f1, f2 from t1; -f1 f2 -1 ############ -2 ++++++++++++ -3 //////////// -4 ------------ -5 ............ -# Test End -# --------------------------------------------------------------- -# Test Begin: Test if recovery works if 2nd page of -# system tablespace is corrupted. -begin; -insert into t1 values (6, repeat('%', 400)); -# Ensure that all dirty pages in the system are flushed. -set global innodb_buf_flush_list_now = 1; -# Make the second page dirty for system tablespace -set global innodb_saved_page_number_debug = 1; -set global innodb_fil_make_page_dirty_debug = 0; -# Ensure that the dirty page of system tablespace is also flushed. -set global innodb_buf_flush_list_now = 1; -# Kill the server -# Make the 2nd page (page_no=1) of the system tablespace -# all zeroes. -# restart -check table t1; -Table Op Msg_type Msg_text -test.t1 check status OK -FOUND 1 /InnoDB: .*test.t1\.ibd/ in mysqld.1.err -select f1, f2 from t1; -f1 f2 -1 ############ -2 ++++++++++++ -3 //////////// -4 ------------ -5 ............ drop table t1; -# -# MDEV-12600 crash during install_db with innodb_page_size=32K -# and ibdata1=3M -# -# restart: --innodb-log-group-home-dir=MYSQLTEST_VARDIR/tmp/doublewrite --innodb-data-home-dir=MYSQLTEST_VARDIR/tmp/doublewrite --innodb-data-file-path=ibdata1:1M;ibdata2:1M:autoextend -SELECT * FROM INFORMATION_SCHEMA.ENGINES -WHERE engine = 'innodb' -AND support IN ('YES', 'DEFAULT', 'ENABLED'); -ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -FOUND 1 /\[ERROR\] InnoDB: Cannot create doublewrite buffer/ in mysqld.1.err -# restart +# End of 10.5 tests diff --git a/mysql-test/suite/innodb/r/doublewrite_debug.result b/mysql-test/suite/innodb/r/doublewrite_debug.result new file mode 100644 index 00000000000..960610a7091 --- /dev/null +++ b/mysql-test/suite/innodb/r/doublewrite_debug.result @@ -0,0 +1,92 @@ +# +# Bug #17335427 INNODB CAN NOT USE THE DOUBLEWRITE BUFFER PROPERLY +# Bug #18144349 INNODB CANNOT USE THE DOUBLEWRITE BUFFER FOR THE FIRST +# PAGE OF SYSTEM TABLESPACE +# +show variables like 'innodb_doublewrite'; +Variable_name Value +innodb_doublewrite ON +show variables like 'innodb_fil_make_page_dirty_debug'; +Variable_name Value +innodb_fil_make_page_dirty_debug 0 +show variables like 'innodb_saved_page_number_debug'; +Variable_name Value +innodb_saved_page_number_debug 0 +create table t1 (f1 int primary key, f2 blob) engine=innodb; +start transaction; +insert into t1 values(1, repeat('#',12)); +insert into t1 values(2, repeat('+',12)); +insert into t1 values(3, repeat('/',12)); +insert into t1 values(4, repeat('-',12)); +insert into t1 values(5, repeat('.',12)); +commit work; +# Test Begin: Test if recovery works if 1st page and 2nd page +# of system tablespace is full of zeroes. +SET GLOBAL innodb_fast_shutdown = 0; +# restart +begin; +insert into t1 values (6, repeat('%', 400)); +# Make the first page dirty for system tablespace +set global innodb_saved_page_number_debug = 0; +set global innodb_fil_make_page_dirty_debug = 0; +# Make the second page dirty for system tablespace +set global innodb_saved_page_number_debug = 1; +set global innodb_fil_make_page_dirty_debug = 0; +set global innodb_buf_flush_list_now = 1; +# Make the 1st page (page_no=0) and 2nd page (page_no=1) +# of the system tablespace all zeroes. +# restart +FOUND 1 /InnoDB: Restoring page \[page id: space=0, page number=0\] of datafile/ in mysqld.1.err +FOUND 1 /InnoDB: Recovered page \[page id: space=0, page number=1\]/ in mysqld.1.err +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +select f1, f2 from t1; +f1 f2 +1 ############ +2 ++++++++++++ +3 //////////// +4 ------------ +5 ............ +# Test End +# --------------------------------------------------------------- +# Test Begin: Test if recovery works if 1st page of +# system tablespace is corrupted and 2nd page as corrupted. +set global innodb_log_checkpoint_now = 1; +begin; +insert into t1 values (6, repeat('%', 400)); +# Make the first page dirty for system tablespace +set global innodb_saved_page_number_debug = 0; +set global innodb_fil_make_page_dirty_debug = 0; +# Make the second page dirty for system tablespace +set global innodb_saved_page_number_debug = 1; +set global innodb_fil_make_page_dirty_debug = 0; +set global innodb_buf_flush_list_now = 1; +# Corrupt the 1st page (page_no=0) and 2nd page of the system tablespace. +# restart +FOUND 2 /InnoDB: Restoring page \[page id: space=0, page number=0\] of datafile/ in mysqld.1.err +FOUND 2 /InnoDB: Recovered page \[page id: space=0, page number=1\]/ in mysqld.1.err +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +select f1, f2 from t1; +f1 f2 +1 ############ +2 ++++++++++++ +3 //////////// +4 ------------ +5 ............ +drop table t1; +# Test End +# --------------------------------------------------------------- +# +# MDEV-12600 crash during install_db with innodb_page_size=32K +# and ibdata1=3M +# +# restart: --innodb-log-group-home-dir=MYSQLTEST_VARDIR/tmp/doublewrite --innodb-data-home-dir=MYSQLTEST_VARDIR/tmp/doublewrite --innodb-data-file-path=ibdata1:1M;ibdata2:1M:autoextend +SELECT * FROM INFORMATION_SCHEMA.ENGINES +WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +FOUND 1 /\[ERROR\] InnoDB: Cannot create doublewrite buffer/ in mysqld.1.err +# restart diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test index bd4f5fadcc3..89e6577b434 100644 --- a/mysql-test/suite/innodb/t/doublewrite.test +++ b/mysql-test/suite/innodb/t/doublewrite.test @@ -1,17 +1,11 @@ + --echo # ---echo # Bug #17335427 INNODB CAN NOT USE THE DOUBLEWRITE BUFFER PROPERLY ---echo # Bug #18144349 INNODB CANNOT USE THE DOUBLEWRITE BUFFER FOR THE FIRST ---echo # PAGE OF SYSTEM TABLESPACE +--echo # MDEV-32242 innodb.doublewrite test case always is skipped --echo # --source include/innodb_page_size.inc ---source include/have_debug.inc --source include/not_embedded.inc -# This test is slow on buildbot. ---source include/big_test.inc -# Slow shutdown and restart to make sure ibuf merge is finished -SET GLOBAL innodb_fast_shutdown = 0; --disable_query_log call mtr.add_suppression("InnoDB: Data file .* uses page size .* but the innodb_page_size start-up parameter is"); call mtr.add_suppression("InnoDB: adjusting FSP_SPACE_FLAGS"); @@ -22,22 +16,14 @@ call mtr.add_suppression("Plugin 'InnoDB' (init function returned error|registra call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile"); call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: "); call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd"); +call mtr.add_suppression("\\[Warning\\] Found 1 prepared XA transactions"); --enable_query_log ---source include/restart_mysqld.inc let INNODB_PAGE_SIZE=`select @@innodb_page_size`; let MYSQLD_DATADIR=`select @@datadir`; let ALGO=`select @@innodb_checksum_algorithm`; let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; -show variables like 'innodb_doublewrite'; -show variables like 'innodb_fil_make_page_dirty_debug'; -show variables like 'innodb_saved_page_number_debug'; - -connect (stop_purge,localhost,root,,); -START TRANSACTION WITH CONSISTENT SNAPSHOT; -connection default; - create table t1 (f1 int primary key, f2 blob) engine=innodb; start transaction; @@ -48,35 +34,24 @@ insert into t1 values(4, repeat('-',12)); insert into t1 values(5, repeat('.',12)); commit work; ---echo # --------------------------------------------------------------- ---echo # Test Begin: Test if recovery works if first page of user ---echo # tablespace is full of zeroes. +# Slow shutdown and restart to make sure ibuf merge is finished +SET GLOBAL innodb_fast_shutdown = 0; +let $shutdown_timeout=; +--source include/restart_mysqld.inc -select space from information_schema.innodb_sys_tables -where name = 'test/t1' into @space_id; +connect (dml,localhost,root,,); +XA START 'x'; +insert into t1 values (6, repeat('%', @@innodb_page_size/2)); +XA END 'x'; +XA PREPARE 'x'; +disconnect dml; +connection default; -begin; -insert into t1 values (6, repeat('%', 12)); ---echo # Ensure that dirty pages of table t1 are flushed. -set global innodb_buf_flush_list_now = 1; +flush table t1 for export; ---source ../include/no_checkpoint_start.inc - ---echo # Make the first page dirty for table t1 -set global innodb_saved_page_number_debug = 0; -set global innodb_fil_make_page_dirty_debug = @space_id; - ---echo # Ensure that dirty pages of table t1 are flushed. -set global innodb_buf_flush_list_now = 1; - ---let CLEANUP_IF_CHECKPOINT=drop table t1; ---source ../include/no_checkpoint_end.inc -disconnect stop_purge; - ---echo # Make the first page (page_no=0) of the user tablespace ---echo # full of zeroes. ---echo # ---echo # MDEV-11623: Use old FSP_SPACE_FLAGS in the doublewrite buffer. +let $restart_parameters=; +let $shutdown_timeout=0; +--source include/shutdown_mysqld.inc perl; use IO::Handle; @@ -90,16 +65,15 @@ my $page_size = $ENV{INNODB_PAGE_SIZE}; my $page; do "$ENV{MTR_SUITE_DIR}/../innodb/include/crc32.pl"; open(FILE, "+<", $fname) or die; +sysseek(FILE, ($page_size/2), 0); +syswrite(FILE, chr(0) x ($page_size/2)); +sysseek(FILE, 3*$page_size, 0); sysread(FILE, $page, $page_size)==$page_size||die "Unable to read $name\n"; -my $page1 = $page; -substr($page1, 34, 4) = pack("N", 0); -my $polynomial0 = 0x82f63b78; # CRC-32C -my $ck0 = mycrc32(substr($page1, 0, ($page_size-4)), 0, $polynomial0); -substr($page1, ($page_size - 4), 4) = pack("N", $ck0); -sysseek(FILE, 0, 0)||die "Unable to seek $fname\n"; -die unless syswrite(FILE, $page1, $page_size) == $page_size; +sysseek(FILE, 3*$page_size, 0)||die "Unable to seek $fname\n"; +syswrite(FILE, chr(0) x ($page_size/2)); close FILE; +# Change the flag offset of page 0 in doublewrite buffer open(FILE, "+<", "$ENV{MYSQLD_DATADIR}ibdata1")||die "cannot open ibdata1\n"; sysseek(FILE, 6 * $page_size - 190, 0)||die "Unable to seek ibdata1\n"; sysread(FILE, $_, 12) == 12||die "Unable to read TRX_SYS\n"; @@ -112,28 +86,23 @@ for (my $d = $d1; $d < $d2 + 64; $d++) sysread(FILE, $_, $page_size)==$page_size||die "Cannot read doublewrite\n"; next unless $_ eq $page; sysseek(FILE, $d * $page_size, 0)||die "Unable to seek ibdata1\n"; - # Write buggy MariaDB 10.1.x FSP_SPACE_FLAGS to the doublewrite buffer - my($flags) = unpack "x[54]N", $_; - my $badflags = ($flags & 0x3f); - my $compression_level=6; - $badflags |= 1<<6|$compression_level<<7 if ($flags & 1 << 16); - $badflags |= ($flags & 15 << 6) << 7; # PAGE_SSIZE - + # Write buggy FSP_SPACE_FLAGS to the doublewrite buffer for page + my $badflags = 0x0006FFFF; substr ($_, 54, 4) = pack("N", $badflags); if ($algo =~ /full_crc32/) { - my $ck = mycrc32(substr($_, 0, $page_size - 4), 0, $polynomial); - substr($_, $page_size - 4, 4) = pack("N", $ck); + my $ck = mycrc32(substr($_, 0, $page_size - 4), 0, $polynomial); + substr($_, $page_size - 4, 4) = pack("N", $ck); } else { - # Replace the innodb_checksum_algorithm=crc32 checksum - my $ck= pack("N", - mycrc32(substr($_, 4, 22), 0, $polynomial) ^ - mycrc32(substr($_, 38, $page_size - 38 - 8), 0, - $polynomial)); - substr ($_, 0, 4) = $ck; - substr ($_, $page_size - 8, 4) = $ck; + # Replace the innodb_checksum_algorithm=crc32 checksum + my $ck= pack("N", + mycrc32(substr($_, 4, 22), 0, $polynomial) ^ + mycrc32(substr($_, 38, $page_size - 38 - 8), 0, + $polynomial)); + substr ($_, 0, 4) = $ck; + substr ($_, $page_size - 8, 4) = $ck; } syswrite(FILE, $_, $page_size)==$page_size||die; close(FILE); @@ -143,323 +112,13 @@ die "Did not find the page in the doublewrite buffer ($d1,$d2)\n"; EOF --source include/start_mysqld.inc - -check table t1; -select f1, f2 from t1; - ---echo # Test End ---echo # --------------------------------------------------------------- ---echo # Test Begin: Test if recovery works if first page of user ---echo # tablespace is corrupted. - -select space from information_schema.innodb_sys_tables -where name = 'test/t1' into @space_id; - ---echo # Ensure that dirty pages of table t1 is flushed. -flush tables t1 for export; -unlock tables; - -begin; -insert into t1 values (6, repeat('%', 12)); - ---source ../include/no_checkpoint_start.inc - ---echo # Make the first page dirty for table t1 -set global innodb_saved_page_number_debug = 0; -set global innodb_fil_make_page_dirty_debug = @space_id; - ---echo # Ensure that dirty pages of table t1 are flushed. -set global innodb_buf_flush_list_now = 1; - ---source include/no_checkpoint_end.inc - ---echo # Corrupt the first page (page_no=0) of the user tablespace. -perl; -use IO::Handle; -my $fname= "$ENV{'MYSQLD_DATADIR'}test/t1.ibd"; -my $page_size = $ENV{INNODB_PAGE_SIZE}; -open(FILE, "+<", $fname) or die; -sysread(FILE, $page, $page_size)==$page_size||die "Unable to read $name\n"; -substr($page, 28, 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 - -check table t1; -select f1, f2 from t1; - ---echo # Test End ---echo # --------------------------------------------------------------- ---echo # Test Begin: Test if recovery works if 2nd page of user ---echo # tablespace is full of zeroes. - -select space from information_schema.innodb_sys_tables -where name = 'test/t1' into @space_id; - ---echo # Ensure that dirty pages of table t1 is flushed. -flush tables t1 for export; -unlock tables; - -begin; -insert into t1 values (6, repeat('%', 400)); - ---source ../include/no_checkpoint_start.inc - ---echo # Make the 2nd page dirty for table t1 -set global innodb_saved_page_number_debug = 1; -set global innodb_fil_make_page_dirty_debug = @space_id; - ---echo # Ensure that dirty pages of table t1 are flushed. -set global innodb_buf_flush_list_now = 1; - ---source include/no_checkpoint_end.inc - ---echo # Make the 2nd page (page_no=1) of the tablespace all zeroes. -perl; -use IO::Handle; -my $fname= "$ENV{'MYSQLD_DATADIR'}test/t1.ibd"; -open(FILE, "+<", $fname) or die; -FILE->autoflush(1); -binmode FILE; -seek(FILE, $ENV{'INNODB_PAGE_SIZE'}, SEEK_SET); -print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}); -close FILE; -EOF - ---source include/start_mysqld.inc - -check table t1; -select f1, f2 from t1; - ---echo # Test End ---echo # --------------------------------------------------------------- ---echo # Test Begin: Test if recovery works if 2nd page of user ---echo # tablespace is corrupted. - -select space from information_schema.innodb_sys_tables -where name = 'test/t1' into @space_id; - ---echo # Ensure that dirty pages of table t1 is flushed. -flush tables t1 for export; -unlock tables; - -begin; -insert into t1 values (6, repeat('%', 400)); - ---source ../include/no_checkpoint_start.inc - ---echo # Make the 2nd page dirty for table t1 -set global innodb_saved_page_number_debug = 1; -set global innodb_fil_make_page_dirty_debug = @space_id; - ---echo # Ensure that the dirty pages of table t1 are flushed. -set global innodb_buf_flush_list_now = 1; - ---source include/no_checkpoint_end.inc - ---echo # Corrupt the 2nd page (page_no=1) of the user tablespace. -perl; -use IO::Handle; -my $fname= "$ENV{'MYSQLD_DATADIR'}test/t1.ibd"; -open(FILE, "+<", $fname) or die; -FILE->autoflush(1); -binmode FILE; -seek(FILE, $ENV{'INNODB_PAGE_SIZE'}, SEEK_SET); -print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}/2); -close FILE; -EOF - ---source include/start_mysqld.inc - -check table t1; -select f1, f2 from t1; - ---echo # Test End ---echo # --------------------------------------------------------------- ---echo # Test Begin: Test if recovery works if first page of ---echo # system tablespace is full of zeroes. - -begin; -insert into t1 values (6, repeat('%', 400)); - ---echo # Ensure that all dirty pages in the system are flushed. -set global innodb_buf_flush_list_now = 1; - ---echo # Make the first page dirty for system tablespace -set global innodb_saved_page_number_debug = 0; -set global innodb_fil_make_page_dirty_debug = 0; - ---echo # Ensure that the dirty page of system tablespace is also flushed. -# We do this after the transaction starts and all dirty pages have been flushed -# already. So flushing of this specified dirty page will surely keep the -# copy in doublewrite buffer, and no more writes to doublewrite buffer would -# overwrite the copy. Thus, we can safely modify the original page when server -# is down. So do the following testings. -set global innodb_buf_flush_list_now = 1; - ---source include/kill_mysqld.inc - ---echo # Make the first page (page_no=0) of the system tablespace ---echo # all zeroes. -perl; -use IO::Handle; -my $fname= "$ENV{'MYSQLD_DATADIR'}ibdata1"; -open(FILE, "+<", $fname) or die; -FILE->autoflush(1); -binmode FILE; -print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}); -close FILE; -EOF - ---source include/start_mysqld.inc - -check table t1; -select f1, f2 from t1; - ---echo # Test End ---echo # --------------------------------------------------------------- ---echo # Test Begin: Test if recovery works if first page of ---echo # system tablespace is corrupted. - -begin; -insert into t1 values (6, repeat('%', 400)); - ---echo # Ensure that all dirty pages in the system are flushed. -set global innodb_buf_flush_list_now = 1; - ---echo # Make the first page dirty for system tablespace -set global innodb_saved_page_number_debug = 0; -set global innodb_fil_make_page_dirty_debug = 0; - ---echo # Ensure that the dirty page of system tablespace is also flushed. -set global innodb_buf_flush_list_now = 1; - ---source include/kill_mysqld.inc - ---echo # Corrupt the first page (page_no=0) of the system tablespace. -perl; -use IO::Handle; -my $fname= "$ENV{'MYSQLD_DATADIR'}ibdata1"; -open(FILE, "+<", $fname) or die; -FILE->autoflush(1); -binmode FILE; -print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}/2); -close FILE; -EOF - ---source include/start_mysqld.inc - -check table t1; -select f1, f2 from t1; - ---echo # Test End ---echo # --------------------------------------------------------------- ---echo # Test Begin: Test if recovery works if 2nd page of ---echo # system tablespace is full of zeroes. - -begin; -insert into t1 values (6, repeat('%', 400)); - ---echo # Ensure that all dirty pages in the system are flushed. -set global innodb_buf_flush_list_now = 1; - ---echo # Make the second page dirty for system tablespace -set global innodb_saved_page_number_debug = 1; -set global innodb_fil_make_page_dirty_debug = 0; - ---echo # Ensure that the dirty page of system tablespace is also flushed. -set global innodb_buf_flush_list_now = 1; - ---source include/kill_mysqld.inc - ---echo # Make the 2nd page (page_no=1) of the system tablespace ---echo # all zeroes. -perl; -use IO::Handle; -my $fname= "$ENV{'MYSQLD_DATADIR'}ibdata1"; -open(FILE, "+<", $fname) or die; -FILE->autoflush(1); -binmode FILE; -seek(FILE, $ENV{'INNODB_PAGE_SIZE'}, SEEK_SET); -print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}); -close FILE; -EOF - ---source include/start_mysqld.inc - -check table t1; -select f1, f2 from t1; - ---echo # Test End ---echo # --------------------------------------------------------------- ---echo # Test Begin: Test if recovery works if 2nd page of ---echo # system tablespace is corrupted. - -begin; -insert into t1 values (6, repeat('%', 400)); - ---echo # Ensure that all dirty pages in the system are flushed. -set global innodb_buf_flush_list_now = 1; - ---echo # Make the second page dirty for system tablespace -set global innodb_saved_page_number_debug = 1; -set global innodb_fil_make_page_dirty_debug = 0; - ---echo # Ensure that the dirty page of system tablespace is also flushed. -set global innodb_buf_flush_list_now = 1; - ---source include/kill_mysqld.inc - ---echo # Make the 2nd page (page_no=1) of the system tablespace ---echo # all zeroes. -perl; -use IO::Handle; -my $fname= "$ENV{'MYSQLD_DATADIR'}ibdata1"; -open(FILE, "+<", $fname) or die; -FILE->autoflush(1); -binmode FILE; -seek(FILE, $ENV{'INNODB_PAGE_SIZE'}, SEEK_SET); -print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}/2); -close FILE; -EOF - ---source include/start_mysqld.inc - -check table t1; ---let SEARCH_PATTERN= InnoDB: .*test.t1\\.ibd +let SEARCH_PATTERN=InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile; --source include/search_pattern_in_file.inc - +let SEARCH_PATTERN=InnoDB: Recovered page \[page id: space=[1-9][0-9]*, page number=3\]; +--source include/search_pattern_in_file.inc +XA ROLLBACK 'x'; +check table t1; select f1, f2 from t1; - drop table t1; ---echo # ---echo # MDEV-12600 crash during install_db with innodb_page_size=32K ---echo # and ibdata1=3M ---echo # -let bugdir= $MYSQLTEST_VARDIR/tmp/doublewrite; ---mkdir $bugdir - -let $check_no_innodb=SELECT * FROM INFORMATION_SCHEMA.ENGINES -WHERE engine = 'innodb' -AND support IN ('YES', 'DEFAULT', 'ENABLED'); - ---let $ibp=--innodb-log-group-home-dir=$bugdir --innodb-data-home-dir=$bugdir ---let $ibd=$ibp --innodb-undo-tablespaces=0 ---let $ibp=$ibp --innodb-data-file-path=ibdata1:1M;ibdata2:1M:autoextend - ---let $restart_parameters= $ibp ---source include/restart_mysqld.inc -eval $check_no_innodb; ---let SEARCH_PATTERN= \[ERROR\] InnoDB: Cannot create doublewrite buffer ---source include/search_pattern_in_file.inc ---let $restart_parameters= ---source include/restart_mysqld.inc - ---remove_file $bugdir/ibdata1 ---remove_file $bugdir/ibdata2 ---remove_file $bugdir/ib_logfile0 ---rmdir $bugdir +--echo # End of 10.5 tests diff --git a/mysql-test/suite/innodb/t/doublewrite_debug.combinations b/mysql-test/suite/innodb/t/doublewrite_debug.combinations new file mode 100644 index 00000000000..4f52013f6fc --- /dev/null +++ b/mysql-test/suite/innodb/t/doublewrite_debug.combinations @@ -0,0 +1,7 @@ +[strict_crc32] +--innodb-checksum-algorithm=strict_crc32 +--innodb-use-atomic-writes=0 + +[strict_full_crc32] +--innodb-checksum-algorithm=strict_full_crc32 +--innodb-use-atomic-writes=0 diff --git a/mysql-test/suite/innodb/t/doublewrite_debug.test b/mysql-test/suite/innodb/t/doublewrite_debug.test new file mode 100644 index 00000000000..86809cc43c0 --- /dev/null +++ b/mysql-test/suite/innodb/t/doublewrite_debug.test @@ -0,0 +1,162 @@ +--echo # +--echo # Bug #17335427 INNODB CAN NOT USE THE DOUBLEWRITE BUFFER PROPERLY +--echo # Bug #18144349 INNODB CANNOT USE THE DOUBLEWRITE BUFFER FOR THE FIRST +--echo # PAGE OF SYSTEM TABLESPACE +--echo # + +--source include/innodb_page_size.inc +--source include/have_debug.inc +--source include/not_embedded.inc +--disable_query_log +call mtr.add_suppression("InnoDB: Data file .* uses page size .* but the innodb_page_size start-up parameter is"); +call mtr.add_suppression("InnoDB: adjusting FSP_SPACE_FLAGS"); +call mtr.add_suppression("InnoDB: New log files created"); +call mtr.add_suppression("InnoDB: Cannot create doublewrite buffer: the first file in innodb_data_file_path must be at least (3|6|12)M\\."); +call mtr.add_suppression("InnoDB: Database creation was aborted"); +call mtr.add_suppression("Plugin 'InnoDB' (init function returned error|registration as a STORAGE ENGINE failed)"); +call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile"); +call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: "); +call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd"); +--enable_query_log + +let INNODB_PAGE_SIZE=`select @@innodb_page_size`; +let MYSQLD_DATADIR=`select @@datadir`; +let ALGO=`select @@innodb_checksum_algorithm`; +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; + +show variables like 'innodb_doublewrite'; +show variables like 'innodb_fil_make_page_dirty_debug'; +show variables like 'innodb_saved_page_number_debug'; + +create table t1 (f1 int primary key, f2 blob) engine=innodb; + +start transaction; +insert into t1 values(1, repeat('#',12)); +insert into t1 values(2, repeat('+',12)); +insert into t1 values(3, repeat('/',12)); +insert into t1 values(4, repeat('-',12)); +insert into t1 values(5, repeat('.',12)); +commit work; + +--echo # Test Begin: Test if recovery works if 1st page and 2nd page +--echo # of system tablespace is full of zeroes. + +# Slow shutdown and restart to make sure ibuf merge is finished +SET GLOBAL innodb_fast_shutdown = 0; +let $shutdown_timeout=; +--source include/restart_mysqld.inc +begin; +insert into t1 values (6, repeat('%', 400)); + +--echo # Make the first page dirty for system tablespace +set global innodb_saved_page_number_debug = 0; +set global innodb_fil_make_page_dirty_debug = 0; + +--echo # Make the second page dirty for system tablespace +set global innodb_saved_page_number_debug = 1; +set global innodb_fil_make_page_dirty_debug = 0; + +set global innodb_buf_flush_list_now = 1; +let $shutdown_timeout=0; +--source include/shutdown_mysqld.inc + +--echo # Make the 1st page (page_no=0) and 2nd page (page_no=1) +--echo # of the system tablespace all zeroes. +perl; +use IO::Handle; +my $fname= "$ENV{'MYSQLD_DATADIR'}ibdata1"; +open(FILE, "+<", $fname) or die; +FILE->autoflush(1); +binmode FILE; +print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}); +seek(FILE, $ENV{'INNODB_PAGE_SIZE'}, SEEK_SET); +print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}); +close FILE; +EOF + +--source include/start_mysqld.inc + +let SEARCH_PATTERN=InnoDB: Restoring page \[page id: space=0, page number=0\] of datafile; +--source include/search_pattern_in_file.inc + +let SEARCH_PATTERN=InnoDB: Recovered page \[page id: space=0, page number=1\]; +--source include/search_pattern_in_file.inc + +check table t1; +select f1, f2 from t1; + +--echo # Test End +--echo # --------------------------------------------------------------- +--echo # Test Begin: Test if recovery works if 1st page of +--echo # system tablespace is corrupted and 2nd page as corrupted. + +set global innodb_log_checkpoint_now = 1; +begin; +insert into t1 values (6, repeat('%', 400)); + +--echo # Make the first page dirty for system tablespace +set global innodb_saved_page_number_debug = 0; +set global innodb_fil_make_page_dirty_debug = 0; + +--echo # Make the second page dirty for system tablespace +set global innodb_saved_page_number_debug = 1; +set global innodb_fil_make_page_dirty_debug = 0; + +set global innodb_buf_flush_list_now = 1; +let $shutdown_timeout=0; +--source include/shutdown_mysqld.inc + +--echo # Corrupt the 1st page (page_no=0) and 2nd page of the system tablespace. +perl; +use IO::Handle; +my $fname= "$ENV{'MYSQLD_DATADIR'}ibdata1"; +open(FILE, "+<", $fname) or die; +FILE->autoflush(1); +binmode FILE; +print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}/2); +seek(FILE, $ENV{'INNODB_PAGE_SIZE'}, SEEK_SET); +print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}/2); +close FILE; +EOF + +--source include/start_mysqld.inc + +let SEARCH_PATTERN=InnoDB: Restoring page \[page id: space=0, page number=0\] of datafile; +--source include/search_pattern_in_file.inc + +let SEARCH_PATTERN=InnoDB: Recovered page \[page id: space=0, page number=1\]; +--source include/search_pattern_in_file.inc + +check table t1; +select f1, f2 from t1; +drop table t1; +let $shutdown_timeout=; +--echo # Test End +--echo # --------------------------------------------------------------- +--echo # +--echo # MDEV-12600 crash during install_db with innodb_page_size=32K +--echo # and ibdata1=3M +--echo # +let bugdir= $MYSQLTEST_VARDIR/tmp/doublewrite; +--mkdir $bugdir + +let $check_no_innodb=SELECT * FROM INFORMATION_SCHEMA.ENGINES +WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); + +--let $ibp=--innodb-log-group-home-dir=$bugdir --innodb-data-home-dir=$bugdir +--let $ibd=$ibp --innodb-undo-tablespaces=0 +--let $ibp=$ibp --innodb-data-file-path=ibdata1:1M;ibdata2:1M:autoextend + +--let $restart_parameters= $ibp +--source include/restart_mysqld.inc +eval $check_no_innodb; +--let SEARCH_PATTERN= \[ERROR\] InnoDB: Cannot create doublewrite buffer +--source include/search_pattern_in_file.inc +--let $restart_parameters= +--source include/restart_mysqld.inc + +--remove_file $bugdir/ibdata1 +--remove_file $bugdir/ibdata2 +--remove_file $bugdir/ib_logfile0 +--rmdir $bugdir diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index efeddda3dec..5e239633f22 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -18326,11 +18326,15 @@ static void buf_flush_list_now_set(THD*, st_mysql_sys_var*, void*, const void* save) { - if (*(my_bool*) save) { - mysql_mutex_unlock(&LOCK_global_system_variables); - buf_flush_sync(); - mysql_mutex_lock(&LOCK_global_system_variables); - } + if (!*(my_bool*) save) + return; + const uint s= srv_fil_make_page_dirty_debug; + mysql_mutex_unlock(&LOCK_global_system_variables); + if (s) + buf_flush_sync(); + else + while (buf_flush_list_space(fil_system.sys_space, nullptr)); + mysql_mutex_lock(&LOCK_global_system_variables); } /** Override current MERGE_THRESHOLD setting for all indexes at dictionary From bc5e904043d4c50fb0cc0cbdce4149866bf4e6e0 Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Thu, 7 Dec 2023 11:47:45 +0000 Subject: [PATCH 404/477] MDEV-32884 Improve S3 options comaptibility The previous commit for MDEV-32884 fixed the s3_protocol_version option, which was previous only using "Auto", no matter what it was set to. This patch does several things to keep the old behaviour whilst correcting for new behaviour and laying the groundwork for the future. This includes: * `Original` now means v2 protocol, which it would have been due to the option not working, so upgrades will stil work. * A new `Legacy` option has been added to mean v1 protocol. * Options `Path` and `Domain` have been added, these will be the only two options apart from `Auto` in a future release, and are more aligned with what this variable means. * Fixed the s3.debug test so that it works with v2 protocol. * Fixed the s3.amazon test so that it works with region subdomains. * Added additional modes to the s3.amazon test. * Added s3.not_amazon test for the remaining modes. This replaces PR #2902. --- mysql-test/suite/s3/amazon.result | 10 ++++++++++ mysql-test/suite/s3/amazon.test | 18 +++++++++++++++++- mysql-test/suite/s3/debug.result | 6 +++--- mysql-test/suite/s3/debug.test | 2 +- storage/maria/aria_s3_copy.cc | 19 +++++++++++++++++-- storage/maria/ha_s3.cc | 5 ++++- storage/maria/s3_func.c | 20 ++++++++++++++++++-- 7 files changed, 70 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/s3/amazon.result b/mysql-test/suite/s3/amazon.result index 29075118a63..b24969ab921 100644 --- a/mysql-test/suite/s3/amazon.result +++ b/mysql-test/suite/s3/amazon.result @@ -4,4 +4,14 @@ create table t1 (pk int primary key, a int); insert into t1 values (1,1),(2,2),(3,3),(4,4); alter table t1 engine=S3; drop table t1; +set @@global.s3_protocol_version="Amazon"; +create table t1 (pk int primary key, a int); +insert into t1 values (1,1),(2,2),(3,3),(4,4); +alter table t1 engine=S3; +drop table t1; +set @@global.s3_protocol_version="Domain"; +create table t1 (pk int primary key, a int); +insert into t1 values (1,1),(2,2),(3,3),(4,4); +alter table t1 engine=S3; +drop table t1; set @@global.s3_protocol_version=@save_s3_protocol_version; diff --git a/mysql-test/suite/s3/amazon.test b/mysql-test/suite/s3/amazon.test index 3c64cc2841b..bc9439ab2cc 100644 --- a/mysql-test/suite/s3/amazon.test +++ b/mysql-test/suite/s3/amazon.test @@ -1,6 +1,6 @@ --source include/have_s3.inc -if (`SELECT @@s3_host_name <> "s3.amazonaws.com"`) +if (`SELECT @@s3_host_name NOT LIKE "%.amazonaws.com"`) { skip Not connected to AWS; } @@ -20,6 +20,22 @@ insert into t1 values (1,1),(2,2),(3,3),(4,4); alter table t1 engine=S3; drop table t1; +set @@global.s3_protocol_version="Amazon"; + +create table t1 (pk int primary key, a int); +insert into t1 values (1,1),(2,2),(3,3),(4,4); +--replace_result $database database +alter table t1 engine=S3; +drop table t1; + +set @@global.s3_protocol_version="Domain"; + +create table t1 (pk int primary key, a int); +insert into t1 values (1,1),(2,2),(3,3),(4,4); +--replace_result $database database +alter table t1 engine=S3; +drop table t1; + # # clean up # diff --git a/mysql-test/suite/s3/debug.result b/mysql-test/suite/s3/debug.result index 69d7a0ac9ea..2dffcff86ee 100644 --- a/mysql-test/suite/s3/debug.result +++ b/mysql-test/suite/s3/debug.result @@ -18,15 +18,15 @@ select count(*) from t1; count(*) 100 flush table t1; -NOT FOUND /storage-engine/s3_test_/ in mysqld.1.err +NOT FOUND /s3_test_/ in mysqld.1.err set @@global.s3_debug=1; select count(*) from t1; count(*) 100 set @@global.s3_debug=0; -FOUND 6 /storage-engine/s3_test_/ in mysqld.1.err +FOUND 6 /s3_test_/ in mysqld.1.err select count(*) from t1; count(*) 100 drop table t1; -FOUND 6 /storage-engine/s3_test_/ in mysqld.1.err +FOUND 6 /s3_test_/ in mysqld.1.err diff --git a/mysql-test/suite/s3/debug.test b/mysql-test/suite/s3/debug.test index d891678c85f..67787d729ee 100644 --- a/mysql-test/suite/s3/debug.test +++ b/mysql-test/suite/s3/debug.test @@ -21,7 +21,7 @@ select count(*) from t1; flush table t1; --let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err ---let SEARCH_PATTERN=storage-engine/s3_test_ +--let SEARCH_PATTERN=s3_test_ --source include/search_pattern_in_file.inc set @@global.s3_debug=1; select count(*) from t1; diff --git a/storage/maria/aria_s3_copy.cc b/storage/maria/aria_s3_copy.cc index b35c40ef2a6..3636e2bec78 100644 --- a/storage/maria/aria_s3_copy.cc +++ b/storage/maria/aria_s3_copy.cc @@ -87,7 +87,9 @@ static struct my_option my_long_options[] = &opt_block_size, &opt_block_size, 0, GET_ULONG, REQUIRED_ARG, 4*1024*1024, 64*1024, 16*1024*1024, MALLOC_OVERHEAD, 1024, 0 }, {"s3_protocol_version", 'L', - "Protocol used to communication with S3. One of \"Auto\", \"Amazon\" or \"Original\".", + "Protocol used to communication with S3. One of \"Auto\", \"Legacy\", " + "\"Original\", \"Amazon\", \"Path\" or \"Domain\". " + "Note: \"Legacy\", \"Original\" and \"Amazon\" are deprecated.", &opt_protocol_version, &opt_protocol_version, &s3_protocol_typelib, GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Force copy even if target exists", @@ -220,7 +222,20 @@ int main(int argc, char** argv) if (opt_protocol_version) { - uint8_t protocol_version= (uint8_t) opt_protocol_version; + uint8_t protocol_version; + switch (opt_protocol_version) + { + case 1: /* Legacy means v1 */ + case 4: /* Path means v1 */ + protocol_version= 1; + break; + case 2: /* Original means v2 */ + case 3: /* Amazon means v2 */ + case 5: /* Domain means v2 */ + protocol_version= 2; + break; + } + ms3_set_option(global_s3_client, MS3_OPT_FORCE_PROTOCOL_VERSION, &protocol_version); } diff --git a/storage/maria/ha_s3.cc b/storage/maria/ha_s3.cc index 0f5cecf5c38..0abb3f076f5 100644 --- a/storage/maria/ha_s3.cc +++ b/storage/maria/ha_s3.cc @@ -170,7 +170,10 @@ static MYSQL_SYSVAR_BOOL(replicate_alter_as_create_select, static MYSQL_SYSVAR_ENUM(protocol_version, s3_protocol_version, PLUGIN_VAR_RQCMDARG, "Protocol used to communication with S3. One of " - "\"Auto\", \"Amazon\" or \"Original\".", + "\"Auto\", \"Legacy\", \"Original\", \"Amazon\", " + "\"Path\" or \"Domain\". " + "Note: \"Legacy\", \"Original\" and \"Amazon\" are " + "deprecated.", NULL, NULL, 0, &s3_protocol_typelib); static MYSQL_SYSVAR_ULONG(pagecache_age_threshold, diff --git a/storage/maria/s3_func.c b/storage/maria/s3_func.c index 3d18ba8800d..4ee3c9e86de 100644 --- a/storage/maria/s3_func.c +++ b/storage/maria/s3_func.c @@ -39,7 +39,7 @@ static int s3_read_file_from_disk(const char *filename, uchar **to, /* Used by ha_s3.cc and tools to define different protocol options */ -static const char *protocol_types[]= {"Auto", "Original", "Amazon", NullS}; +static const char *protocol_types[]= {"Auto", "Legacy", "Original", "Amazon", "Path", "Domain", NullS}; TYPELIB s3_protocol_typelib= {array_elements(protocol_types)-1,"", protocol_types, NULL}; @@ -155,8 +155,24 @@ ms3_st *s3_open_connection(S3_INFO *s3) my_errno= HA_ERR_NO_SUCH_TABLE; } if (s3->protocol_version) + { + uint8_t protocol_version; + switch (s3->protocol_version) + { + case 1: /* Legacy means v1 */ + case 4: /* Path means v1 */ + protocol_version= 1; + break; + case 2: /* Original means v2 */ + case 3: /* Amazon means v2 */ + case 5: /* Domain means v2 */ + protocol_version= 2; + break; + } + ms3_set_option(s3_client, MS3_OPT_FORCE_PROTOCOL_VERSION, - &s3->protocol_version); + &protocol_version); + } if (s3->port) ms3_set_option(s3_client, MS3_OPT_PORT_NUMBER, &s3->port); From 9be7e03f70e9ef66b6e695aa46fd0dffd0976448 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Tue, 5 Dec 2023 14:27:39 -0700 Subject: [PATCH 405/477] =?UTF-8?q?MDEV-32953:=20main.rpl=5Fmysqldump=5Fsl?= =?UTF-8?q?ave=20Fails=20with=20"Master=20binlog=20wasn=E2=80=99t=20delete?= =?UTF-8?q?d"=20Assertion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because --delete-master-logs immediately purges logs after flushing, it is possible the binlog dump thread would still be using the old log when the purge executes, disallowing the file from being deleted. This patch institutes a work-around in the test as follows: 1) temporarily stop the slave so there is no chance the old binlog is still being referenced. 2) set master_use_gtid=Slave_pos so the slave can still appear up-to-date on the master after the master flushes/purges its logs (while the slave is offline). Otherwise (i.e. if using binlog file/pos), the slave would point to a purged log file, and receive an error immediately upon connecting to the master. Reviewed By ============ Andrei Elkin --- mysql-test/main/rpl_mysqldump_slave.result | 7 +++++ mysql-test/main/rpl_mysqldump_slave.test | 32 +++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/rpl_mysqldump_slave.result b/mysql-test/main/rpl_mysqldump_slave.result index c5458ec374c..9f93e3c405e 100644 --- a/mysql-test/main/rpl_mysqldump_slave.result +++ b/mysql-test/main/rpl_mysqldump_slave.result @@ -72,6 +72,13 @@ id int insert into t values (1); insert into t values (2); drop table t; +connection slave; +include/stop_slave.inc +change master to master_use_gtid=slave_pos; +connection master; +# Ensuring the binlog dump thread is killed on primary... -- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000002', MASTER_LOG_POS=BINLOG_START; -- SET GLOBAL gtid_slave_pos='0-1-1005'; +connection slave; +include/start_slave.inc include/rpl_end.inc diff --git a/mysql-test/main/rpl_mysqldump_slave.test b/mysql-test/main/rpl_mysqldump_slave.test index 315b4def2a4..0273e196db5 100644 --- a/mysql-test/main/rpl_mysqldump_slave.test +++ b/mysql-test/main/rpl_mysqldump_slave.test @@ -85,7 +85,7 @@ DROP TABLE t2; # # MDEV-32611 Added test for mysqldump --delete-master-logs option. -# This options is alias of +# This options is alias of # get binlogs: show master status -> flush logs -> purge binary logs to # sequence and this test is derived using the same pattern. # @@ -101,6 +101,33 @@ insert into t values (2); drop table t; +--sync_slave_with_master + +# MDEV-32953: Because --delete-master-logs immediately purges logs after +# flushing, it is possible the binlog dump threads will still be using the old +# log when the purge executes, disallowing the file from being deleted. +# Therefore, we temporarily stop the slave so there is no chance the old binlog +# is still being referenced. master_use_gtid=Slave_pos is necessary to still +# appear up-to-date to the master on restart after the master has flushed the +# logs (while the slave is offline). Otherwise (i.e. if using binlog file/pos), +# the slave would point to a purged log file, and receive an error immediately +# upon connecting to the master. +--source include/stop_slave.inc +change master to master_use_gtid=slave_pos; + +connection master; + +--echo # Ensuring the binlog dump thread is killed on primary... +--disable_query_log +--let $binlog_dump_thd_tid= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND LIKE 'Binlog Dump'` +if ($binlog_dump_thd_tid) +{ + --eval kill $binlog_dump_thd_tid +} +--let $wait_condition= SELECT COUNT(*)=0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND LIKE 'Binlog Dump' +--source include/wait_condition.inc +--enable_query_log + --let $predump_binlog_filename= query_get_value(SHOW MASTER STATUS, File, 1) # Execute mysqldump with delete-master-logs option @@ -125,4 +152,7 @@ if ($postdump_first_binary_log_filename != $postdump_binlog_filename) --die Master binlog wasn't deleted after mariadb-dump with --delete-master-logs. } +connection slave; +--source include/start_slave.inc + --source include/rpl_end.inc From c8346c0bacfdbe3fd61c67becff9934e75e08ed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 8 Dec 2023 09:31:34 +0200 Subject: [PATCH 406/477] MDEV-31939 Adaptive flush recommendation ignores dirty ratio and checkpoint age buf_flush_page_cleaner(): Pass pct_lwm=srv_max_dirty_pages_pct_lwm (innodb_max_dirty_pages_pct_lwm) to page_cleaner_flush_pages_recommendation() unless the dirty page ratio of the buffer pool is below that. Starting with commit d4265fbde587bd79b6fe3793225d3f4798ee955e we used to always pass pct_lwm=0.0, which was not intended. Reviewed by: Vladislav Vaintroub --- storage/innobase/buf/buf0flu.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 186fb89ddce..c0c743ede57 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -2379,10 +2379,11 @@ static os_thread_ret_t DECLARE_THREAD(buf_flush_page_cleaner)(void*) else { maybe_unemployed: - const bool below{dirty_pct < pct_lwm}; - pct_lwm= 0.0; - if (below) + if (dirty_pct < pct_lwm) + { + pct_lwm= 0.0; goto possibly_unemployed; + } } } else if (dirty_pct < srv_max_buf_pool_modified_pct) From a356a940d256abd132ea237eb8c84fa78c756276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 8 Dec 2023 10:55:13 +0200 Subject: [PATCH 407/477] MDEV-32971 Assertion !recv_sys.is_corrupt_fs() failed on recovery recv_recovery_from_checkpoint_start(): Relax a too strict debug assertion that occasionally fails in the test encryption.innodb-redo-nokeys when fil_ibd_load() returns FIL_LOAD_INVALID due to missing crypt_info. This assertion had been removed in MariaDB Server 10.8 as part of commit 685d958e38b825ad9829be311f26729cccf37c46 (MDEV-14425). --- storage/innobase/log/log0recv.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index d52a62cec99..05120871b0a 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3507,7 +3507,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) recv_group_scan_log_recs(checkpoint_lsn, &contiguous_lsn, false); /* The first scan should not have stored or applied any records. */ ut_ad(recv_sys.pages.empty()); - ut_ad(!recv_sys.found_corrupt_fs); + ut_ad(!recv_sys.found_corrupt_fs || !srv_force_recovery); if (srv_read_only_mode && recv_needed_recovery) { mysql_mutex_unlock(&log_sys.mutex); From 02d67cecb6e443895e7a93759918224b226efc75 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 31 Aug 2023 13:14:03 +1000 Subject: [PATCH 408/477] MDEV-32043 mariadb-upgrade should remove bundled plugins from mysql.plugin Also in the startup, lets not "Error" on attempting to install a mysql.plugin that is already there. We use the 'if_not_exists' parameter to true to downgrade this to a "Note". Also corrects: MDEV-32041 "plugin already loaded" should be a Warning, not an Error --- mysql-test/main/mysql_upgrade.result | 8 ++++++++ mysql-test/main/mysql_upgrade.test | 11 +++++++++++ scripts/mysql_system_tables_fix.sql | 5 +++++ sql/sql_plugin.cc | 2 +- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/mysql_upgrade.result b/mysql-test/main/mysql_upgrade.result index 64d6cd12753..a640d7e3ee6 100644 --- a/mysql-test/main/mysql_upgrade.result +++ b/mysql-test/main/mysql_upgrade.result @@ -1058,4 +1058,12 @@ test Phase 7/7: Running 'FLUSH PRIVILEGES' OK set global sql_safe_updates=@orig_sql_safe_updates; +# +# MDEV-32043 Remove plugins previously external that are now built in (unix_socket) +# +INSERT INTO mysql.plugin SELECT 'unix_socket', 'auth_socket.so' + FROM dual WHERE convert(@@version_compile_os using latin1) not in ('Win32', 'Win64', 'Windows'); +# mariadb-upgrade --force --silent 2>&1 +SELECT * FROM mysql.plugin WHERE name='unix_socket'; +name dl # End of 10.4 tests diff --git a/mysql-test/main/mysql_upgrade.test b/mysql-test/main/mysql_upgrade.test index f7a1bdf7be0..df7f802905d 100644 --- a/mysql-test/main/mysql_upgrade.test +++ b/mysql-test/main/mysql_upgrade.test @@ -495,4 +495,15 @@ set global sql_safe_updates=ON; --remove_file $MYSQLD_DATADIR/mysql_upgrade_info set global sql_safe_updates=@orig_sql_safe_updates; +--echo # +--echo # MDEV-32043 Remove plugins previously external that are now built in (unix_socket) +--echo # + +INSERT INTO mysql.plugin SELECT 'unix_socket', 'auth_socket.so' + FROM dual WHERE convert(@@version_compile_os using latin1) not in ('Win32', 'Win64', 'Windows'); +--echo # mariadb-upgrade --force --silent 2>&1 +--exec $MYSQL_UPGRADE --force --silent 2>&1 +SELECT * FROM mysql.plugin WHERE name='unix_socket'; +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info + --echo # End of 10.4 tests diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index fe3470352ef..7d2cc7d9103 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -180,6 +180,11 @@ UPDATE user SET plugin='unix_socket' WHERE plugin='auth_socket'; DELETE FROM plugin WHERE name='auth_socket'; +# Delete plugins that are now inbuilt but might not have been before (MDEV-32043) +DELETE plugin + FROM information_schema.PLUGINS is_p + JOIN plugin ON plugin.name = is_p.PLUGIN_NAME + WHERE is_p.PLUGIN_LIBRARY IS NULL; ALTER TABLE user MODIFY Password char(41) character set latin1 collate latin1_bin NOT NULL default '', diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 19c5f86c765..9f144ca5a73 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1929,7 +1929,7 @@ static void plugin_load(MEM_ROOT *tmp_root) the mutex here to satisfy the assert */ mysql_mutex_lock(&LOCK_plugin); - plugin_add(tmp_root, false, &name, &dl, MYF(ME_ERROR_LOG)); + plugin_add(tmp_root, true, &name, &dl, MYF(ME_ERROR_LOG)); free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); mysql_mutex_unlock(&LOCK_plugin); } From 2d775fd01acb7954b89c7e8032b863e9d6765d00 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 30 Nov 2023 05:32:09 +0400 Subject: [PATCH 409/477] Cleanup: Removing the unused method Type_handler::get_handler_by_cmp_type It's not used in 10.5+ --- sql/sql_type.cc | 16 ---------------- sql/sql_type.h | 1 - 2 files changed, 17 deletions(-) diff --git a/sql/sql_type.cc b/sql/sql_type.cc index e7058f6b4ed..13e61a40be2 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -1451,22 +1451,6 @@ Type_handler_string_result::charset_for_protocol(const Item *item) const } -const Type_handler * -Type_handler::get_handler_by_cmp_type(Item_result type) -{ - switch (type) { - case REAL_RESULT: return &type_handler_double; - case INT_RESULT: return &type_handler_slonglong; - case DECIMAL_RESULT: return &type_handler_newdecimal; - case STRING_RESULT: return &type_handler_long_blob; - case TIME_RESULT: return &type_handler_datetime; - case ROW_RESULT: return &type_handler_row; - } - DBUG_ASSERT(0); - return &type_handler_string; -} - - /* If we have a mixture of: - a MariaDB standard (built-in permanent) data type, and diff --git a/sql/sql_type.h b/sql/sql_type.h index ee3eb454ead..edce7f45abe 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -3669,7 +3669,6 @@ public: static const Type_handler *blob_type_handler(const Item *item); static const Type_handler *get_handler_by_field_type(enum_field_types type); static const Type_handler *get_handler_by_real_type(enum_field_types type); - static const Type_handler *get_handler_by_cmp_type(Item_result type); static const Type_collection * type_collection_for_aggregation(const Type_handler *h1, const Type_handler *h2); From 5775df012701144a76eb96501336d53c61fb28a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Sun, 10 Dec 2023 13:19:21 +0200 Subject: [PATCH 410/477] MDEV-20142 encryption.innodb_encrypt_temporary_tables fails The data type of the column INFORMATION_SCHEMA.GLOBAL_STATUS.VARIABLE_VALUE is a character string. Therefore, if we want to compare some values as integers, we must explicitly cast them to integer type, to avoid an awkward comparison where '10'<'9' because the first digit is smaller. --- .../r/innodb_encrypt_temporary_tables.result | 16 ++++++++++------ .../t/innodb_encrypt_temporary_tables.test | 12 ++++++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/encryption/r/innodb_encrypt_temporary_tables.result b/mysql-test/suite/encryption/r/innodb_encrypt_temporary_tables.result index 541680ae862..d86ca6f9c00 100644 --- a/mysql-test/suite/encryption/r/innodb_encrypt_temporary_tables.result +++ b/mysql-test/suite/encryption/r/innodb_encrypt_temporary_tables.result @@ -1,6 +1,8 @@ -SELECT variable_value into @old_encrypted FROM information_schema.global_status +SELECT CAST(variable_value AS INT) INTO @old_encrypted +FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_temp_blocks_encrypted'; -SELECT variable_value into @old_decrypted FROM information_schema.global_status +SELECT CAST(variable_value AS INT) INTO @old_decrypted +FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_temp_blocks_decrypted'; CREATE TEMPORARY TABLE t1(f1 CHAR(200), f2 CHAR(200)) ENGINE=InnoDB; INSERT INTO t1 (f1,f2) SELECT '', '' FROM seq_1_to_8192; @@ -12,11 +14,13 @@ COUNT(*) SELECT COUNT(*) FROM t2; COUNT(*) 8192 -SELECT variable_value > @old_encrypted FROM information_schema.global_status +SELECT CAST(variable_value AS INT) > @old_encrypted +FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_temp_blocks_encrypted'; -variable_value > @old_encrypted +CAST(variable_value AS INT) > @old_encrypted 1 -SELECT variable_value > @old_decrypted FROM information_schema.global_status +SELECT CAST(variable_value AS INT) > @old_decrypted +FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_temp_blocks_decrypted'; -variable_value > @old_decrypted +CAST(variable_value AS INT) > @old_decrypted 1 diff --git a/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.test b/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.test index d99a55b9b44..83abb783c9e 100644 --- a/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.test +++ b/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.test @@ -2,10 +2,12 @@ --source include/have_innodb.inc --source include/have_file_key_management_plugin.inc -SELECT variable_value into @old_encrypted FROM information_schema.global_status +SELECT CAST(variable_value AS INT) INTO @old_encrypted +FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_temp_blocks_encrypted'; -SELECT variable_value into @old_decrypted FROM information_schema.global_status +SELECT CAST(variable_value AS INT) INTO @old_decrypted +FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_temp_blocks_decrypted'; CREATE TEMPORARY TABLE t1(f1 CHAR(200), f2 CHAR(200)) ENGINE=InnoDB; @@ -17,8 +19,10 @@ INSERT INTO t2 (f1,f2,f3) SELECT '', '', '' FROM seq_1_to_8192; SELECT COUNT(*) FROM t1; SELECT COUNT(*) FROM t2; -SELECT variable_value > @old_encrypted FROM information_schema.global_status +SELECT CAST(variable_value AS INT) > @old_encrypted +FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_temp_blocks_encrypted'; -SELECT variable_value > @old_decrypted FROM information_schema.global_status +SELECT CAST(variable_value AS INT) > @old_decrypted +FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_temp_blocks_decrypted'; From 4ced4898fd0a713c54c5d698a5dc893945bb5b30 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 7 Dec 2023 17:44:43 +0400 Subject: [PATCH 411/477] MDEV-32958 Unusable key notes do not get reported for some operations Enable unusable key notes for non-equality predicates: <, <=, =>, >, BETWEEN, IN, LIKE Note, in some scenarios it displays duplicate notes, e.g. for queries with ORDER BY: SELECT * FROM t1 WHERE indexed_string_column >= 10 ORDER BY indexed_string_column LIMIT 5; This should be tolarable. Getting rid of the diplicate note completely would need a much more complex patch, which is not desiable in 10.6. Details: - Changing RANGE_OPT_PARAM::note_unusable_keys from bool to a new data type Item_func::Bitmap, so the caller can choose with a better granuality which predicates should raise unusable key notes inside the range optimizer: a. all predicates (=, <=>, <, <=, =>, >, BETWEEN, IN, LIKE) b. all predicates except equality (=, <=>) c. none of the predicates "b." is needed because in some scenarios equality predicates (=, <=>) send unusable key notes at an earlier stage, before the range optimizer, during update_ref_and_keys(). Calling the range optimizer with "all predicates" would produce duplicate notes for = and <=> in such cases. - Fixing get_quick_record_count() to call the range optimizer with "all predicates except equality" instead of "none of the predicates". Before this change the range optimizer suppressed all notes for non-equality predicates: <, <=, =>, >, BETWEEN, IN, LIKE. This actually fixes the reported problem. - Fixing JOIN::make_range_rowid_filters() to call the range optimizer with "all predicates except equality" instead of "all predicates". Before this change the range optimizer produced duplicate notes for = and <=> during a rowid_filter optimization. - Cleanup: Adding the op_collation argument to Field::raise_note_cannot_use_key_part() and displaying the operation collation rather than the argument collation in the unusable key note. This is important for operations with more than two arguments: BETWEEN and IN, e.g.: SELECT * FROM t1 WHERE column_utf8mb3_general_ci BETWEEN 'a' AND 'b' COLLATE utf8mb3_unicode_ci; SELECT * FROM t1 WHERE column_utf8mb3_general_ci IN ('a', 'b' COLLATE utf8mb3_unicode_ci); The note for 'a' now prints utf8mb3_unicode_ci as the collation. which is the collation of the entire operation: Cannot use key key1 part[0] for lookup: "`column_utf8mb3_general_ci`" of collation `utf8mb3_general_ci` >= "'a'" of collation `utf8mb3_unicode_ci` Before this change it printed the collation of 'a', so the note was confusing: Cannot use key key1 part[0] for lookup: "`column_utf8mb3_general_ci`" of collation `utf8mb3_general_ci` >= "'a'" of collation `utf8mb3_general_ci`" --- mysql-test/main/ctype_collate.result | 6 + mysql-test/main/func_in.result | 2 + mysql-test/main/group_min_max.result | 8 + mysql-test/main/mrr_icp_extra.result | 6 + .../main/myisam_explain_non_select_all.result | 6 + mysql-test/main/subselect4.result | 4 + mysql-test/main/type_varchar.result | 207 ++++++++++++++++++ mysql-test/main/type_varchar.test | 64 ++++++ mysql-test/main/view.result | 4 + mysql-test/suite/innodb/r/innodb_mysql.result | 12 + .../type_inet/type_inet6_myisam.result | 2 + sql/field.cc | 3 +- sql/field.h | 1 + sql/item_func.h | 32 +++ sql/opt_range.cc | 26 ++- sql/opt_range.h | 13 +- sql/sql_delete.cc | 3 +- sql/sql_help.cc | 3 +- sql/sql_select.cc | 32 ++- sql/sql_update.cc | 3 +- 20 files changed, 412 insertions(+), 25 deletions(-) diff --git a/mysql-test/main/ctype_collate.result b/mysql-test/main/ctype_collate.result index d53efe89b40..eafe7ff3d7b 100644 --- a/mysql-test/main/ctype_collate.result +++ b/mysql-test/main/ctype_collate.result @@ -614,18 +614,24 @@ id select_type table type possible_keys key key_len ref rows Extra EXPLAIN SELECT * FROM t1 WHERE s2 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` >= "'a'" of collation `latin1_german1_ci` EXPLAIN SELECT * FROM t1 WHERE s1 IN ('a','b' COLLATE latin1_german1_ci); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range s1 s1 11 NULL 2 Using index condition EXPLAIN SELECT * FROM t1 WHERE s2 IN ('a','b' COLLATE latin1_german1_ci); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` = "'a'" of collation `latin1_german1_ci` EXPLAIN SELECT * FROM t1 WHERE s1 LIKE 'a' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range s1 s1 11 NULL 1 Using index condition EXPLAIN SELECT * FROM t1 WHERE s2 LIKE 'a' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` like "'a' collate latin1_german1_ci" of collation `latin1_german1_ci` DROP TABLE t1; create table t1(f1 varchar(10) character set latin2 collate latin2_hungarian_ci, key(f1)); insert into t1 set f1=0x3F3F9DC73F; diff --git a/mysql-test/main/func_in.result b/mysql-test/main/func_in.result index 58dfcbcf31f..3a7a34e1011 100644 --- a/mysql-test/main/func_in.result +++ b/mysql-test/main/func_in.result @@ -531,6 +531,8 @@ Warning 1292 Truncated incorrect DECIMAL value: 'b' explain select f1 from t1 where f1 in (2,1); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index t1f1_idx t1f1_idx 2 NULL 3 Using where; Using index +Warnings: +Note 1105 Cannot use key `t1f1_idx` part[0] for lookup: `test`.`t1`.`f1` of type `char` = "2" of type `int` create table t2(f2 int, index t2f2(f2)); insert into t2 values(0),(1),(2); select f2 from t2 where f2 in ('a',2); diff --git a/mysql-test/main/group_min_max.result b/mysql-test/main/group_min_max.result index e44d59bb6e9..dcc9d984a5c 100644 --- a/mysql-test/main/group_min_max.result +++ b/mysql-test/main/group_min_max.result @@ -3298,6 +3298,8 @@ explain SELECT b, min(a) FROM t1 WHERE a > ('0' = b) AND b = 'z' GROUP BY b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref b b 4 const 1 Using where; Using index +Warnings: +Note 1105 Cannot use key `b` part[1] for lookup: `test`.`t1`.`a` of type `varchar` > "'0' = 'z'" of type `boolean` SELECT b, min(a) FROM t1 WHERE a > ('0' = b) AND b = 'z' GROUP BY b; b min(a) explain @@ -3984,12 +3986,18 @@ id select_type table type possible_keys key key_len ref rows Extra EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND DATE'2001-01-05' GROUP BY id; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL id 27 NULL 64 Using where; Using index +Warnings: +Note 1105 Cannot use key `id` part[1] for lookup: `test`.`t1`.`a` of type `varchar` >= "DATE'2001-01-04'" of type `date` EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND '2001-01-05' GROUP BY id; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL id 27 NULL 64 Using where; Using index +Warnings: +Note 1105 Cannot use key `id` part[1] for lookup: `test`.`t1`.`a` of type `varchar` >= "DATE'2001-01-04'" of type `date` EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND DATE'2001-01-05' GROUP BY id; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL id 27 NULL 64 Using where; Using index +Warnings: +Note 1105 Cannot use key `id` part[1] for lookup: `test`.`t1`.`a` of type `varchar` >= "('2001-01-04')" of type `date` DROP TABLE t1; # # MIN() optimization didn't work correctly with BETWEEN when using too diff --git a/mysql-test/main/mrr_icp_extra.result b/mysql-test/main/mrr_icp_extra.result index 1b33b008f35..48b3b91d271 100644 --- a/mysql-test/main/mrr_icp_extra.result +++ b/mysql-test/main/mrr_icp_extra.result @@ -38,18 +38,24 @@ id select_type table type possible_keys key key_len ref rows Extra EXPLAIN SELECT * FROM t1 WHERE s2 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` >= "'a'" of collation `latin1_german1_ci` EXPLAIN SELECT * FROM t1 WHERE s1 IN ('a','b' COLLATE latin1_german1_ci); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range s1 s1 11 NULL 2 Using index condition; Rowid-ordered scan EXPLAIN SELECT * FROM t1 WHERE s2 IN ('a','b' COLLATE latin1_german1_ci); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` = "'a'" of collation `latin1_german1_ci` EXPLAIN SELECT * FROM t1 WHERE s1 LIKE 'a' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range s1 s1 11 NULL 1 Using index condition; Rowid-ordered scan EXPLAIN SELECT * FROM t1 WHERE s2 LIKE 'a' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` like "'a' collate latin1_german1_ci" of collation `latin1_german1_ci` DROP TABLE t1; # # diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result index b72df544a3f..e28c2a0fec3 100644 --- a/mysql-test/main/myisam_explain_non_select_all.result +++ b/mysql-test/main/myisam_explain_non_select_all.result @@ -1528,6 +1528,8 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` > "10" of type `int` Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` <= "18" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` > "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` <= "18" of type `int` Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`i` AS `i` from `test`.`t1` where `test`.`t1`.`i` > 10 and `test`.`t1`.`i` <= 18 order by `test`.`t1`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value @@ -1591,6 +1593,8 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "18" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "18" of type `int` Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`i` AS `i` from `test`.`t1` where `test`.`t1`.`i` >= 10 and `test`.`t1`.`i` < 18 order by `test`.`t1`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value @@ -2142,6 +2146,8 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` > "10" of type `int` Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` <= "18" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` > "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` <= "18" of type `int` Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value diff --git a/mysql-test/main/subselect4.result b/mysql-test/main/subselect4.result index 7a3c7b76ee4..6ef175bbfd4 100644 --- a/mysql-test/main/subselect4.result +++ b/mysql-test/main/subselect4.result @@ -1892,6 +1892,8 @@ id select_type table type possible_keys key key_len ref rows Extra 2 SUBQUERY SUBQUERY2_t1 index NULL col_int_key 5 NULL 2 Using index 2 SUBQUERY SUBQUERY2_t2 ALL col_varchar_key NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) 3 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 +Warnings: +Note 1105 Cannot use key `col_varchar_key` part[0] for lookup: `test`.`t1`.`col_varchar_key` of type `varchar` < "0" of type `bigint` SELECT col_int_key FROM t2 WHERE (SELECT SUBQUERY2_t1.col_int_key @@ -1917,6 +1919,8 @@ id select_type table type possible_keys key key_len ref rows Extra 2 SUBQUERY SUBQUERY2_t1 index NULL col_int_key 5 NULL 2 Using index 2 SUBQUERY SUBQUERY2_t2 ALL col_varchar_key NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) 3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +Warnings: +Note 1105 Cannot use key `col_varchar_key` part[0] for lookup: `test`.`t1`.`col_varchar_key` of type `varchar` < "0" of type `bigint` SELECT col_int_key FROM t2 WHERE (SELECT SUBQUERY2_t1.col_int_key diff --git a/mysql-test/main/type_varchar.result b/mysql-test/main/type_varchar.result index cc3ccc00907..6c0339a6010 100644 --- a/mysql-test/main/type_varchar.result +++ b/mysql-test/main/type_varchar.result @@ -967,10 +967,217 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL i NULL NULL NULL 31 Using where; Using filesort Warnings: Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` > "30" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` > "30" of type `int` EXPLAIN SELECT * FROM t1 WHERE i>=30 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL i NULL NULL NULL 31 Using where; Using filesort Warnings: Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "30" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "30" of type `int` +DROP TABLE t1; +SET note_verbosity=DEFAULT; +# +# MDEV-32958 Unusable key notes do not get reported for some operations +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (c1 varchar(10), KEY(c1)) CHARACTER SET latin1; +INSERT INTO t1 VALUES ('a'); +INSERT INTO t1 VALUES ('b'); +INSERT INTO t1 VALUES ('c'); +INSERT INTO t1 VALUES ('d'); +INSERT INTO t1 VALUES ('e'); +INSERT INTO t1 VALUES ('f'); +INSERT INTO t1 VALUES ('g'); +INSERT INTO t1 VALUES ('h'); +INSERT INTO t1 VALUES ('i'); +INSERT INTO t1 VALUES ('j'); +EXPLAIN SELECT * FROM t1 WHERE c1=10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` = "10" of type `int` +SELECT * FROM t1 WHERE c1=10; +c1 +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` = "10" of type `int` +Warning 1292 Truncated incorrect DECIMAL value: 'a' +Warning 1292 Truncated incorrect DECIMAL value: 'b' +Warning 1292 Truncated incorrect DECIMAL value: 'c' +Warning 1292 Truncated incorrect DECIMAL value: 'd' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'f' +Warning 1292 Truncated incorrect DECIMAL value: 'g' +Warning 1292 Truncated incorrect DECIMAL value: 'h' +Warning 1292 Truncated incorrect DECIMAL value: 'i' +Warning 1292 Truncated incorrect DECIMAL value: 'j' +EXPLAIN SELECT * FROM t1 WHERE c1<10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` < "10" of type `int` +SELECT * FROM t1 WHERE c1<10; +c1 +a +b +c +d +e +f +g +h +i +j +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` < "10" of type `int` +Warning 1292 Truncated incorrect DECIMAL value: 'a' +Warning 1292 Truncated incorrect DECIMAL value: 'b' +Warning 1292 Truncated incorrect DECIMAL value: 'c' +Warning 1292 Truncated incorrect DECIMAL value: 'd' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'f' +Warning 1292 Truncated incorrect DECIMAL value: 'g' +Warning 1292 Truncated incorrect DECIMAL value: 'h' +Warning 1292 Truncated incorrect DECIMAL value: 'i' +Warning 1292 Truncated incorrect DECIMAL value: 'j' +EXPLAIN SELECT * FROM t1 WHERE c1 BETWEEN 10 AND 11; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` >= "10" of type `int` +SELECT * FROM t1 WHERE c1 BETWEEN 10 AND 11; +c1 +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` >= "10" of type `int` +Warning 1292 Truncated incorrect DECIMAL value: 'a' +Warning 1292 Truncated incorrect DECIMAL value: 'b' +Warning 1292 Truncated incorrect DECIMAL value: 'c' +Warning 1292 Truncated incorrect DECIMAL value: 'd' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'f' +Warning 1292 Truncated incorrect DECIMAL value: 'g' +Warning 1292 Truncated incorrect DECIMAL value: 'h' +Warning 1292 Truncated incorrect DECIMAL value: 'i' +Warning 1292 Truncated incorrect DECIMAL value: 'j' +EXPLAIN SELECT * FROM t1 WHERE c1 BETWEEN 10 AND '11'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` >= "10" of type `int` +SELECT * FROM t1 WHERE c1 BETWEEN 10 AND '11'; +c1 +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` >= "10" of type `int` +Warning 1292 Truncated incorrect DOUBLE value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'b' +Warning 1292 Truncated incorrect DOUBLE value: 'c' +Warning 1292 Truncated incorrect DOUBLE value: 'd' +Warning 1292 Truncated incorrect DOUBLE value: 'e' +Warning 1292 Truncated incorrect DOUBLE value: 'f' +Warning 1292 Truncated incorrect DOUBLE value: 'g' +Warning 1292 Truncated incorrect DOUBLE value: 'h' +Warning 1292 Truncated incorrect DOUBLE value: 'i' +Warning 1292 Truncated incorrect DOUBLE value: 'j' +EXPLAIN SELECT * FROM t1 WHERE c1 IN (10,20); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` = "10" of type `int` +SELECT * FROM t1 WHERE c1 IN (10,20); +c1 +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` = "10" of type `int` +Warning 1292 Truncated incorrect DECIMAL value: 'a' +Warning 1292 Truncated incorrect DECIMAL value: 'b' +Warning 1292 Truncated incorrect DECIMAL value: 'c' +Warning 1292 Truncated incorrect DECIMAL value: 'd' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'f' +Warning 1292 Truncated incorrect DECIMAL value: 'g' +Warning 1292 Truncated incorrect DECIMAL value: 'h' +Warning 1292 Truncated incorrect DECIMAL value: 'i' +Warning 1292 Truncated incorrect DECIMAL value: 'j' +EXPLAIN SELECT * FROM t1 WHERE c1 IN (_latin1'a' COLLATE latin1_german2_ci,'b'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of collation `latin1_swedish_ci` = "_latin1'a' collate latin1_german2_ci" of collation `latin1_german2_ci` +SELECT * FROM t1 WHERE c1 IN (_latin1'a' COLLATE latin1_german2_ci,'b'); +c1 +a +b +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of collation `latin1_swedish_ci` = "_latin1'a' collate latin1_german2_ci" of collation `latin1_german2_ci` +EXPLAIN SELECT * FROM t1 WHERE c1 IN ('a',_latin1'b' COLLATE latin1_german2_ci); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of collation `latin1_swedish_ci` = "'a'" of collation `latin1_german2_ci` +SELECT * FROM t1 WHERE c1 IN ('a',_latin1'b' COLLATE latin1_german2_ci); +c1 +a +b +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of collation `latin1_swedish_ci` = "'a'" of collation `latin1_german2_ci` +DROP TABLE t1; +CREATE TABLE t1(a INT, i CHAR(2), INDEX(i(1))); +INSERT INTO t1 (i) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), +(20),(21),(22),(23),(24),(25),(26),(27),(28),(29), +(30),(31),(32),(33),(34),(35); +EXPLAIN SELECT * FROM t1 WHERE i >= 10 ORDER BY i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL i NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +SELECT * FROM t1 WHERE i >= 10 ORDER BY i LIMIT 5; +a i +NULL 10 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +EXPLAIN UPDATE t1 SET a = 1 WHERE i = 10 ORDER BY a, i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` = "10" of type `int` +EXPLAIN UPDATE t1 SET a = 1 WHERE i < 10 ORDER BY a, i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "10" of type `int` +EXPLAIN DELETE FROM t1 WHERE i = 10 ORDER BY a, i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` = "10" of type `int` +EXPLAIN DELETE FROM t1 WHERE i < 10 ORDER BY a, i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "10" of type `int` +EXPLAIN UPDATE t1 SET a = 1 WHERE i = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` = "10" of type `int` +EXPLAIN UPDATE t1 SET a = 1 WHERE i < 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "10" of type `int` +EXPLAIN DELETE FROM t1 WHERE i = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` = "10" of type `int` +EXPLAIN DELETE FROM t1 WHERE i < 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "10" of type `int` DROP TABLE t1; SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_varchar.test b/mysql-test/main/type_varchar.test index 620d25f3f7f..feb270272c1 100644 --- a/mysql-test/main/type_varchar.test +++ b/mysql-test/main/type_varchar.test @@ -434,3 +434,67 @@ EXPLAIN SELECT * FROM t1 WHERE i>30 ORDER BY i LIMIT 5; EXPLAIN SELECT * FROM t1 WHERE i>=30 ORDER BY i LIMIT 5; DROP TABLE t1; SET note_verbosity=DEFAULT; + + +--echo # +--echo # MDEV-32958 Unusable key notes do not get reported for some operations +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (c1 varchar(10), KEY(c1)) CHARACTER SET latin1; +INSERT INTO t1 VALUES ('a'); +INSERT INTO t1 VALUES ('b'); +INSERT INTO t1 VALUES ('c'); +INSERT INTO t1 VALUES ('d'); +INSERT INTO t1 VALUES ('e'); +INSERT INTO t1 VALUES ('f'); +INSERT INTO t1 VALUES ('g'); +INSERT INTO t1 VALUES ('h'); +INSERT INTO t1 VALUES ('i'); +INSERT INTO t1 VALUES ('j'); + +EXPLAIN SELECT * FROM t1 WHERE c1=10; +SELECT * FROM t1 WHERE c1=10; + +EXPLAIN SELECT * FROM t1 WHERE c1<10; +SELECT * FROM t1 WHERE c1<10; + +EXPLAIN SELECT * FROM t1 WHERE c1 BETWEEN 10 AND 11; +SELECT * FROM t1 WHERE c1 BETWEEN 10 AND 11; + +EXPLAIN SELECT * FROM t1 WHERE c1 BETWEEN 10 AND '11'; +SELECT * FROM t1 WHERE c1 BETWEEN 10 AND '11'; + +EXPLAIN SELECT * FROM t1 WHERE c1 IN (10,20); +SELECT * FROM t1 WHERE c1 IN (10,20); + +EXPLAIN SELECT * FROM t1 WHERE c1 IN (_latin1'a' COLLATE latin1_german2_ci,'b'); +SELECT * FROM t1 WHERE c1 IN (_latin1'a' COLLATE latin1_german2_ci,'b'); + +EXPLAIN SELECT * FROM t1 WHERE c1 IN ('a',_latin1'b' COLLATE latin1_german2_ci); +SELECT * FROM t1 WHERE c1 IN ('a',_latin1'b' COLLATE latin1_german2_ci); + +DROP TABLE t1; + + +CREATE TABLE t1(a INT, i CHAR(2), INDEX(i(1))); +INSERT INTO t1 (i) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), + (20),(21),(22),(23),(24),(25),(26),(27),(28),(29), + (30),(31),(32),(33),(34),(35); + +EXPLAIN SELECT * FROM t1 WHERE i >= 10 ORDER BY i LIMIT 5; +SELECT * FROM t1 WHERE i >= 10 ORDER BY i LIMIT 5; + +EXPLAIN UPDATE t1 SET a = 1 WHERE i = 10 ORDER BY a, i LIMIT 5; +EXPLAIN UPDATE t1 SET a = 1 WHERE i < 10 ORDER BY a, i LIMIT 5; +EXPLAIN DELETE FROM t1 WHERE i = 10 ORDER BY a, i LIMIT 5; +EXPLAIN DELETE FROM t1 WHERE i < 10 ORDER BY a, i LIMIT 5; + +EXPLAIN UPDATE t1 SET a = 1 WHERE i = 10; +EXPLAIN UPDATE t1 SET a = 1 WHERE i < 10; +EXPLAIN DELETE FROM t1 WHERE i = 10; +EXPLAIN DELETE FROM t1 WHERE i < 10; + +DROP TABLE t1; + +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result index 0f47c47bc32..a962776a4dc 100644 --- a/mysql-test/main/view.result +++ b/mysql-test/main/view.result @@ -4422,12 +4422,14 @@ SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` < "0" of type `int` Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 'JJ' or `test`.`t1`.`a` = 'VV' and `test`.`t1`.`a` <> 0 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` < "0" of type `int` Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 'JJ' or `test`.`t1`.`a` = 'VV' and `test`.`t1`.`a` <> 0 # t1 and v1 should return the same result set SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV'; @@ -4448,12 +4450,14 @@ SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` < "0" of type `int` Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 'JJ' or `test`.`t1`.`a` = 'VV' and `test`.`t1`.`a` <> 0 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a > 'JJ' OR a AND a = 'VV'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` < "0" of type `int` Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 'JJ' or `test`.`t1`.`a` = 'VV' and `test`.`t1`.`a` <> 0 DROP VIEW v1; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index aa8cc118ce6..d142c0e499e 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -2382,6 +2382,10 @@ key_len NULL ref NULL rows 6 Extra Using where +Warnings: +Level Note +Code 1105 +Message Cannot use key `PRIMARY` part[0] for lookup: `test`.`bar`.`c` of type `char` > "2" of type `int` EXPLAIN SELECT c FROM foo WHERE c>2;; id 1 select_type SIMPLE @@ -2393,6 +2397,10 @@ key_len NULL ref NULL rows 6 Extra Using where +Warnings: +Level Note +Code 1105 +Message Cannot use key `PRIMARY` part[0] for lookup: `test`.`foo`.`c` of type `char` > "2" of type `int` EXPLAIN SELECT c FROM foo2 WHERE c>2;; id 1 select_type SIMPLE @@ -2404,6 +2412,10 @@ key_len 5 ref NULL rows 6 Extra Using where; Using index +Warnings: +Level Note +Code 1105 +Message Cannot use key `PRIMARY` part[0] for lookup: `test`.`foo2`.`c` of type `char` > "2" of type `int` DROP TABLE foo, bar, foo2; # # Bug#41348: INSERT INTO tbl SELECT * FROM temp_tbl overwrites locking type of temp table diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result b/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result index da67e05a163..0f20e16db9c 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result @@ -98,6 +98,8 @@ c EXPLAIN SELECT * FROM t1 WHERE c>CAST('::1' AS INET6); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index c c 67 NULL 3 Using where; Using index +Warnings: +Note 1105 Cannot use key `c` part[0] for lookup: `test`.`t1`.`c` of type `varchar` > "cast('::1' as inet6)" of type `inet6` SELECT * FROM t1 WHERE c=CAST('::1' AS INET6); c 0::1 diff --git a/sql/field.cc b/sql/field.cc index 4a6b6616340..e4b814924e4 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -11284,6 +11284,7 @@ void Field::set_warning_truncated_wrong_value(const char *type_arg, void Field::raise_note_cannot_use_key_part(THD *thd, uint keynr, uint part, const LEX_CSTRING &op, + CHARSET_INFO *op_collation, Item *value, Data_type_compatibility reason) const @@ -11304,7 +11305,7 @@ void Field::raise_note_cannot_use_key_part(THD *thd, case Data_type_compatibility::INCOMPATIBLE_COLLATION: { const LEX_CSTRING colf(charset()->coll_name); - const LEX_CSTRING colv(value->collation.collation->coll_name); + const LEX_CSTRING colv(op_collation->coll_name); push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR, "Cannot use key %`.*s part[%u] for lookup: " diff --git a/sql/field.h b/sql/field.h index 1f31d6042cd..51fdc8124e6 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1642,6 +1642,7 @@ public: void print_key_value_binary(String *out, const uchar* key, uint32 length); void raise_note_cannot_use_key_part(THD *thd, uint keynr, uint part, const LEX_CSTRING &op, + CHARSET_INFO *op_collation, Item *value, const Data_type_compatibility reason) const; diff --git a/sql/item_func.h b/sql/item_func.h index 1390fab014f..aa5bbd4bb96 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -79,6 +79,38 @@ public: CASE_SEARCHED_FUNC, // Used by ColumnStore/Spider CASE_SIMPLE_FUNC, // Used by ColumnStore/spider, }; + + /* + A function bitmap. Useful when some operation needs to be applied only + to certain functions. For now we only need to distinguish some + comparison predicates. + */ + enum Bitmap : ulonglong + { + BITMAP_NONE= 0, + BITMAP_EQ= 1ULL << EQ_FUNC, + BITMAP_EQUAL= 1ULL << EQUAL_FUNC, + BITMAP_NE= 1ULL << NE_FUNC, + BITMAP_LT= 1ULL << LT_FUNC, + BITMAP_LE= 1ULL << LE_FUNC, + BITMAP_GE= 1ULL << GE_FUNC, + BITMAP_GT= 1ULL << GT_FUNC, + BITMAP_LIKE= 1ULL << LIKE_FUNC, + BITMAP_BETWEEN= 1ULL << BETWEEN, + BITMAP_IN= 1ULL << IN_FUNC, + BITMAP_MULT_EQUAL= 1ULL << MULT_EQUAL_FUNC, + BITMAP_OTHER= 1ULL << 63, + BITMAP_ALL= 0xFFFFFFFFFFFFFFFFULL, + BITMAP_ANY_EQUALITY= BITMAP_EQ | BITMAP_EQUAL | BITMAP_MULT_EQUAL, + BITMAP_EXCEPT_ANY_EQUALITY= BITMAP_ALL & ~BITMAP_ANY_EQUALITY, + }; + + ulonglong bitmap_bit() const + { + Functype type= functype(); + return 1ULL << (type > 63 ? 63 : type); + } + static scalar_comparison_op functype_to_scalar_comparison_op(Functype type) { switch (type) { diff --git a/sql/opt_range.cc b/sql/opt_range.cc index b7800e83bd8..72703a018ad 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2690,7 +2690,7 @@ SQL_SELECT::test_quick_select(THD *thd, bool ordered_output, bool remove_false_parts_of_where, bool only_single_index_range_scan, - bool suppress_unusable_key_notes) + Item_func::Bitmap note_unusable_keys) { uint idx; double scan_time; @@ -2784,9 +2784,9 @@ SQL_SELECT::test_quick_select(THD *thd, param.max_key_parts= 0; param.remove_false_where_parts= remove_false_parts_of_where; param.force_default_mrr= ordered_output; - param.note_unusable_keys= (!suppress_unusable_key_notes && - thd->give_notes_for_unusable_keys()); - + param.note_unusable_keys= thd->give_notes_for_unusable_keys() ? + note_unusable_keys : + Item_func::BITMAP_NONE; param.possible_keys.clear_all(); thd->no_errors=1; // Don't warn about NULL @@ -3993,7 +3993,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond) range_par->remove_jump_scans= FALSE; range_par->real_keynr[0]= 0; range_par->alloced_sel_args= 0; - range_par->note_unusable_keys= 0; + range_par->note_unusable_keys= Item_func::BITMAP_NONE; thd->no_errors=1; // Don't warn about NULL thd->mem_root=&alloc; @@ -8756,9 +8756,11 @@ Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param, if (field->result_type() == STRING_RESULT && field->charset() != compare_collation()) { - if (param->note_unusable_keys) + if (param->note_unusable_keys & BITMAP_LIKE) field->raise_note_cannot_use_key_part(param->thd, keynr, key_part->part, - func_name_cstring(), value, + func_name_cstring(), + compare_collation(), + value, Data_type_compatibility:: INCOMPATIBLE_COLLATION); DBUG_RETURN(0); @@ -8774,9 +8776,11 @@ Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param, field->type_handler() == &type_handler_enum || field->type_handler() == &type_handler_set) { - if (param->note_unusable_keys) + if (param->note_unusable_keys & BITMAP_LIKE) field->raise_note_cannot_use_key_part(param->thd, keynr, key_part->part, - func_name_cstring(), value, + func_name_cstring(), + compare_collation(), + value, Data_type_compatibility:: INCOMPATIBLE_DATA_TYPE); DBUG_RETURN(0); @@ -8881,7 +8885,8 @@ Field::can_optimize_scalar_range(const RANGE_OPT_PARAM *param, TODO: Perhaps we also need to raise a similar note when a partition could not be used (when using_real_indexes==false). */ - if (param->using_real_indexes && param->note_unusable_keys) + if (param->using_real_indexes && param->note_unusable_keys && + (param->note_unusable_keys & cond->bitmap_bit())) { DBUG_ASSERT(keynr < table->s->keys); /* @@ -8895,6 +8900,7 @@ Field::can_optimize_scalar_range(const RANGE_OPT_PARAM *param, */ raise_note_cannot_use_key_part(param->thd, keynr, key_part->part, scalar_comparison_op_to_lex_cstring(op), + cond->compare_collation(), value, compat); } return compat; diff --git a/sql/opt_range.h b/sql/opt_range.h index de9a9464447..18b3c33cafa 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -713,7 +713,10 @@ public: */ bool remove_false_where_parts; - bool note_unusable_keys; // Give SQL notes for unusable keys + /* + Which functions should give SQL notes for unusable keys. + */ + Item_func::Bitmap note_unusable_keys; /* used_key_no -> table_key_no translation table. Only makes sense if @@ -1718,12 +1721,14 @@ class SQL_SELECT :public Sql_alloc { true - for ERROR and IMPOSSIBLE_RANGE false - Ok */ - bool check_quick(THD *thd, bool force_quick_range, ha_rows limit) + bool check_quick(THD *thd, bool force_quick_range, ha_rows limit, + Item_func::Bitmap note_unusable_keys) { key_map tmp; tmp.set_all(); return test_quick_select(thd, tmp, 0, limit, force_quick_range, - FALSE, FALSE, FALSE) != OK; + FALSE, FALSE, FALSE, + note_unusable_keys) != OK; } /* @@ -1753,7 +1758,7 @@ class SQL_SELECT :public Sql_alloc { bool ordered_output, bool remove_false_parts_of_where, bool only_single_index_range_scan, - bool suppress_unusable_key_notes = 0); + Item_func::Bitmap note_unusable_keys); }; typedef enum SQL_SELECT::quick_select_return_type quick_select_return; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 296d075d7f9..5de19084b0f 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -530,7 +530,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, select=make_select(table, 0, 0, conds, (SORT_INFO*) 0, 0, &error); if (unlikely(error)) DBUG_RETURN(TRUE); - if ((select && select->check_quick(thd, safe_update, limit)) || !limit) + if ((select && select->check_quick(thd, safe_update, limit, + Item_func::BITMAP_ALL)) || !limit) { query_plan.set_impossible_where(); if (thd->lex->describe || thd->lex->analyze_stmt) diff --git a/sql/sql_help.cc b/sql/sql_help.cc index f9932f11798..34e77e3773f 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -667,7 +667,8 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, SQL_SELECT *res= make_select(table, 0, 0, cond, 0, 0, error); if (unlikely(*error) || - (likely(res) && unlikely(res->check_quick(thd, 0, HA_POS_ERROR))) || + (likely(res) && unlikely(res->check_quick(thd, 0, HA_POS_ERROR, + Item_func::BITMAP_ALL))) || (likely(res) && res->quick && unlikely(res->quick->reset()))) { delete res; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fcd640dd9b2..74e2c74f597 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1958,9 +1958,14 @@ bool JOIN::make_range_rowid_filters() bool force_index_save= tab->table->force_index; tab->table->force_index= true; quick_select_return rc; + /* + EQ_FUNC and EQUAL_FUNC already sent unusable key notes (if any) + during update_ref_and_keys(). Have only other functions raise notes + from can_optimize_scalar_range(). + */ rc= sel->test_quick_select(thd, filter_map, (table_map) 0, (ha_rows) HA_POS_ERROR, true, false, true, - true); + true, Item_func::BITMAP_EXCEPT_ANY_EQUALITY); tab->table->force_index= force_index_save; if (rc == SQL_SELECT::ERROR || thd->is_error()) { @@ -5188,10 +5193,16 @@ static bool get_quick_record_count(THD *thd, SQL_SELECT *select, { select->head=table; table->reginfo.impossible_range=0; + /* + EQ_FUNC and EQUAL_FUNC already sent unusable key notes (if any) + during update_ref_and_keys(). Have only other functions raise notes + from can_optimize_scalar_range(). + */ error= select->test_quick_select(thd, *(key_map *)keys, (table_map) 0, limit, 0, FALSE, TRUE, /* remove_where_parts*/ - FALSE, TRUE); + FALSE, + Item_func::BITMAP_EXCEPT_ANY_EQUALITY); if (error == SQL_SELECT::OK && select->quick) { @@ -7000,6 +7011,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field) { field->raise_note_cannot_use_key_part(thd, key, part, equal_str, + key_field->cond->compare_collation(), key_field->val, compat); } @@ -12706,7 +12718,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) HA_POS_ERROR : join->unit->lim.get_select_limit()), 0, - FALSE, FALSE, FALSE)) == + FALSE, FALSE, FALSE, + Item_func::BITMAP_ALL)) == SQL_SELECT::IMPOSSIBLE_RANGE) { /* @@ -12721,7 +12734,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) OPTION_FOUND_ROWS ? HA_POS_ERROR : join->unit->lim.get_select_limit()), - 0, FALSE, FALSE, FALSE, TRUE)) == + 0, FALSE, FALSE, FALSE, + Item_func::BITMAP_NONE)) == SQL_SELECT::IMPOSSIBLE_RANGE) DBUG_RETURN(1); // Impossible WHERE } @@ -22746,7 +22760,9 @@ test_if_quick_select(JOIN_TAB *tab) 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); + FALSE, + /* no unusable key notes */ + Item_func::BITMAP_NONE); if (tab->explain_plan && tab->explain_plan->range_checked_fer) tab->explain_plan->range_checked_fer->collect_data(tab->select->quick); @@ -24797,7 +24813,8 @@ 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); + TRUE, TRUE, FALSE, FALSE, + Item_func::BITMAP_ALL); // if we cannot use quick select if (res != SQL_SELECT::OK || !tab->select->quick) { @@ -24902,7 +24919,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, join->select_options & OPTION_FOUND_ROWS ? HA_POS_ERROR : join->unit->lim.get_select_limit(), - TRUE, FALSE, FALSE, FALSE); + TRUE, FALSE, FALSE, FALSE, + Item_func::BITMAP_ALL); if (res == SQL_SELECT::ERROR) { *fatal_error= true; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index c36556df534..7fd5c864c06 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -579,7 +579,8 @@ int mysql_update(THD *thd, select= make_select(table, 0, 0, conds, (SORT_INFO*) 0, 0, &error); if (unlikely(error || !limit || thd->is_error() || - (select && select->check_quick(thd, safe_update, limit)))) + (select && select->check_quick(thd, safe_update, limit, + Item_func::BITMAP_ALL)))) { query_plan.set_impossible_where(); if (thd->lex->describe || thd->lex->analyze_stmt) From 9bf50a0eec111739b896e1e5d14d15abf21ffae5 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Mon, 11 Dec 2023 12:27:11 +0700 Subject: [PATCH 412/477] MDEV-32965: Assertion `thd->active_stmt_arena_to_use()-> is_stmt_prepare_or_first_sp_execute() || thd->active_stmt_arena_to_use()-> is_conventional() || thd->active_stmt_arena_to_use()->state == Query_arena::STMT_SP_QUERY_ARGUMENTS' failed This patch fixes too strong condition in assert at the method Item_func_group_concat::fix_fields that is true in case of a stored routine and obviously broken for a prepared statement. --- mysql-test/main/ps.result | 10 ++++++++++ mysql-test/main/ps.test | 12 ++++++++++++ sql/item_sum.cc | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result index 408b1ec2666..32560ab2b2c 100644 --- a/mysql-test/main/ps.result +++ b/mysql-test/main/ps.result @@ -5805,5 +5805,15 @@ END; $ ERROR 42000: EXECUTE..USING does not support subqueries or stored functions # +# MDEV-32965: Assertion `thd->active_stmt_arena_to_use()-> is_stmt_prepare_or_first_sp_execute() || thd->active_stmt_arena_to_use()-> is_conventional() || thd->active_stmt_arena_to_use()->state == Query_arena::STMT_SP_QUERY_ARGUMENTS' failed +# +CREATE TABLE t (f VARCHAR(8)) CHARACTER SET utf8; +INSERT INTO t VALUES ('foo'),('bar'); +EXECUTE IMMEDIATE 'SELECT GROUP_CONCAT(@x) FROM t GROUP BY @x := f'; +GROUP_CONCAT(@x) +0 +0 +DROP TABLE t; +# # End of 10.4 tests # diff --git a/mysql-test/main/ps.test b/mysql-test/main/ps.test index a24d045d63b..70213e05391 100644 --- a/mysql-test/main/ps.test +++ b/mysql-test/main/ps.test @@ -5231,6 +5231,18 @@ $ delimiter ;$ +--echo # +--echo # MDEV-32965: Assertion `thd->active_stmt_arena_to_use()-> is_stmt_prepare_or_first_sp_execute() || thd->active_stmt_arena_to_use()-> is_conventional() || thd->active_stmt_arena_to_use()->state == Query_arena::STMT_SP_QUERY_ARGUMENTS' failed +--echo # +CREATE TABLE t (f VARCHAR(8)) CHARACTER SET utf8; + +INSERT INTO t VALUES ('foo'),('bar'); +EXECUTE IMMEDIATE 'SELECT GROUP_CONCAT(@x) FROM t GROUP BY @x := f'; + +# Cleanup + +DROP TABLE t; + --echo # --echo # End of 10.4 tests --echo # diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 048307fdeb2..30ed3f93437 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -4099,7 +4099,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) String *new_separator; DBUG_ASSERT(thd->active_stmt_arena_to_use()-> - is_stmt_prepare_or_first_sp_execute() || + is_stmt_prepare_or_first_stmt_execute() || thd->active_stmt_arena_to_use()-> is_conventional() || thd->active_stmt_arena_to_use()->state == From 03ee23bcbbb1d816da332ea694f1479ba1c92e97 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 11 Dec 2023 10:42:37 +0400 Subject: [PATCH 413/477] MDEV-17226 Column Data in Truncated on UNION to the length of the first value if using REPLACE This problem was earlier fixed by: commit 55b27888005083d30339d6f3a2aee034121d8693 Adding MTR tests only. --- mysql-test/main/func_replace.result | 124 ++++++++++++++++++++++++++++ mysql-test/main/func_replace.test | 86 +++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 mysql-test/main/func_replace.result create mode 100644 mysql-test/main/func_replace.test diff --git a/mysql-test/main/func_replace.result b/mysql-test/main/func_replace.result new file mode 100644 index 00000000000..7f354d529df --- /dev/null +++ b/mysql-test/main/func_replace.result @@ -0,0 +1,124 @@ +# +# Start of 10.5 tests +# +# +# MDEV-17226 Column Data in Truncated on UNION to the length of the first value if using REPLACE +# +CREATE TABLE t1 ( +id INT UNSIGNED NOT NULL AUTO_INCREMENT, +col1 VARCHAR (2), +col2 VARCHAR (2), +PRIMARY KEY (id) +); +CREATE TABLE t2 ( +id INT UNSIGNED NOT NULL AUTO_INCREMENT, +col1 VARCHAR (1), +col2 VARCHAR (2), +PRIMARY KEY (id) +); +INSERT INTO t1 (col1, col2) VALUES ("a", "ba"); +INSERT INTO t2 (col1, col2) VALUES ("a", "ba"); +SELECT 'a' UNION ALL SELECT REPLACE('a', col1, col2) FROM t1; +a +a +ba +SELECT 'a' UNION ALL SELECT REPLACE('a', col1, col2) FROM t2; +a +a +ba +SELECT REPLACE('z', col1, col2) FROM t1 UNION ALL SELECT REPLACE('a', col1, col2) FROM t1; +REPLACE('z', col1, col2) +z +ba +SELECT REPLACE('z', col1, col2) FROM t2 UNION ALL SELECT REPLACE('a', col1, col2) FROM t2; +REPLACE('z', col1, col2) +z +ba +DROP TABLE t1, t2; +CREATE TABLE t1 ( +id INT UNSIGNED NOT NULL AUTO_INCREMENT, +col1 VARCHAR (2), +col2 VARCHAR (2), +PRIMARY KEY (id) +); +INSERT INTO t1 (col1, col2) VALUES ('a', 'ba'); +SELECT REPLACE('a', col1, col2) FROM t1; +REPLACE('a', col1, col2) +ba +CREATE TABLE t2 AS SELECT 'a' UNION ALL SELECT REPLACE('a', col1, col2) FROM t1; +SELECT * FROM t2; +a +a +ba +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` varchar(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t1, t2; +CREATE TABLE t1 ( +id INT UNSIGNED NOT NULL AUTO_INCREMENT, +col1 VARCHAR (1), +col2 VARCHAR (10), +PRIMARY KEY (id) +); +INSERT INTO t1 (col1, col2) VALUES ('a', '0123456789'); +SELECT REPLACE('aa', col1, col2) FROM t1; +REPLACE('aa', col1, col2) +01234567890123456789 +CREATE TABLE t2 AS SELECT 'a' UNION ALL SELECT REPLACE('aa', col1, col2) FROM t1; +SELECT * FROM t2; +a +a +01234567890123456789 +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` varchar(20) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t1, t2; +CREATE TABLE t1 ( +id INT UNSIGNED NOT NULL AUTO_INCREMENT, +col1 VARCHAR (1), +col2 VARCHAR (20), +PRIMARY KEY (id) +); +INSERT INTO t1 (col1, col2) VALUES ('a', 'aaaaaaaaaabbbbbbbbbb'); +SELECT REPLACE('aa', col1, col2) FROM t1; +REPLACE('aa', col1, col2) +aaaaaaaaaabbbbbbbbbbaaaaaaaaaabbbbbbbbbb +CREATE TABLE t2 AS SELECT 'a' UNION ALL SELECT REPLACE('aa', col1, col2) FROM t1; +SELECT * FROM t2; +a +a +aaaaaaaaaabbbbbbbbbbaaaaaaaaaabbbbbbbbbb +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` varchar(40) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t1, t2; +CREATE TABLE t1 ( +id INT UNSIGNED NOT NULL AUTO_INCREMENT, +col1 VARCHAR (1), +col2 VARCHAR (30), +PRIMARY KEY (id) +); +INSERT INTO t1 (col1, col2) VALUES ('a', 'aaaaaaaaaabbbbbbbbbbcccccccccc'); +SELECT REPLACE('aaa', col1, col2) FROM t1; +REPLACE('aaa', col1, col2) +aaaaaaaaaabbbbbbbbbbccccccccccaaaaaaaaaabbbbbbbbbbccccccccccaaaaaaaaaabbbbbbbbbbcccccccccc +CREATE TABLE t2 AS SELECT 'a' UNION ALL SELECT REPLACE('aaa', col1, col2) FROM t1; +SELECT * FROM t2; +a +a +aaaaaaaaaabbbbbbbbbbccccccccccaaaaaaaaaabbbbbbbbbbccccccccccaaaaaaaaaabbbbbbbbbbcccccccccc +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` varchar(90) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t1, t2; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/func_replace.test b/mysql-test/main/func_replace.test new file mode 100644 index 00000000000..f06ef99261a --- /dev/null +++ b/mysql-test/main/func_replace.test @@ -0,0 +1,86 @@ +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-17226 Column Data in Truncated on UNION to the length of the first value if using REPLACE +--echo # + +CREATE TABLE t1 ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + col1 VARCHAR (2), + col2 VARCHAR (2), + PRIMARY KEY (id) +); +CREATE TABLE t2 ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + col1 VARCHAR (1), + col2 VARCHAR (2), + PRIMARY KEY (id) +); +INSERT INTO t1 (col1, col2) VALUES ("a", "ba"); +INSERT INTO t2 (col1, col2) VALUES ("a", "ba"); +SELECT 'a' UNION ALL SELECT REPLACE('a', col1, col2) FROM t1; +SELECT 'a' UNION ALL SELECT REPLACE('a', col1, col2) FROM t2; +SELECT REPLACE('z', col1, col2) FROM t1 UNION ALL SELECT REPLACE('a', col1, col2) FROM t1; +SELECT REPLACE('z', col1, col2) FROM t2 UNION ALL SELECT REPLACE('a', col1, col2) FROM t2; +DROP TABLE t1, t2; + + + +CREATE TABLE t1 ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + col1 VARCHAR (2), + col2 VARCHAR (2), + PRIMARY KEY (id) +); +INSERT INTO t1 (col1, col2) VALUES ('a', 'ba'); +SELECT REPLACE('a', col1, col2) FROM t1; +CREATE TABLE t2 AS SELECT 'a' UNION ALL SELECT REPLACE('a', col1, col2) FROM t1; +SELECT * FROM t2; +SHOW CREATE TABLE t2; +DROP TABLE t1, t2; + +CREATE TABLE t1 ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + col1 VARCHAR (1), + col2 VARCHAR (10), + PRIMARY KEY (id) +); +INSERT INTO t1 (col1, col2) VALUES ('a', '0123456789'); +SELECT REPLACE('aa', col1, col2) FROM t1; +CREATE TABLE t2 AS SELECT 'a' UNION ALL SELECT REPLACE('aa', col1, col2) FROM t1; +SELECT * FROM t2; +SHOW CREATE TABLE t2; +DROP TABLE t1, t2; + +CREATE TABLE t1 ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + col1 VARCHAR (1), + col2 VARCHAR (20), + PRIMARY KEY (id) +); +INSERT INTO t1 (col1, col2) VALUES ('a', 'aaaaaaaaaabbbbbbbbbb'); +SELECT REPLACE('aa', col1, col2) FROM t1; +CREATE TABLE t2 AS SELECT 'a' UNION ALL SELECT REPLACE('aa', col1, col2) FROM t1; +SELECT * FROM t2; +SHOW CREATE TABLE t2; +DROP TABLE t1, t2; + +CREATE TABLE t1 ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + col1 VARCHAR (1), + col2 VARCHAR (30), + PRIMARY KEY (id) +); +INSERT INTO t1 (col1, col2) VALUES ('a', 'aaaaaaaaaabbbbbbbbbbcccccccccc'); +SELECT REPLACE('aaa', col1, col2) FROM t1; +CREATE TABLE t2 AS SELECT 'a' UNION ALL SELECT REPLACE('aaa', col1, col2) FROM t1; +SELECT * FROM t2; +SHOW CREATE TABLE t2; +DROP TABLE t1, t2; + + +--echo # +--echo # End of 10.5 tests +--echo # From 47f2b16a8cd6d3e50c49be4b868ac7dff9fefc88 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Thu, 7 Dec 2023 20:16:41 +0700 Subject: [PATCH 414/477] MDEV-31296: Crash in Item_func::fix_fields when prepared statement with subqueries and window function is executed with sql_mode = ONLY_FULL_GROUP_BY Crash was caused by referencing a null pointer on getting the number of the nesting levels of the set function for the current select_lex at the method Item_field::fix_fields. The current select for processing is taken from Name_resolution_context that filled in at the function set_new_item_local_context() and where initialization of the data member Name_resolution_context was mistakenly removed by the commit d6ee351bbb66b023e8c477b039aa469b053f84ad (Revert "MDEV-24454 Crash at change_item_tree") To fix the issue, correct initialization of data member Name_resolution_context::select_lex that was removed by the commit d6ee351bbb66b023e8c477b039aa469b053f84ad is restored. --- mysql-test/main/win.result | 13 +++++++++++++ mysql-test/main/win.test | 14 ++++++++++++++ .../suite/encryption/r/tempfiles_encrypted.result | 13 +++++++++++++ sql/sql_base.cc | 1 + 4 files changed, 41 insertions(+) diff --git a/mysql-test/main/win.result b/mysql-test/main/win.result index bcfea2f1419..249ada4383a 100644 --- a/mysql-test/main/win.result +++ b/mysql-test/main/win.result @@ -4415,5 +4415,18 @@ NULL DROP FUNCTION f; DROP TABLE t; # +# MDEV-31296: Crash in Item_func::fix_fields when prepared statement +# with subqueries and window function is executed with +# sql_mode = ONLY_FULL_GROUP_BY +# +CREATE TABLE t1 ( a INT, i INT) ; +CREATE TABLE t2 ( a INT); +INSERT INTO t2 VALUES (4000); +SET SESSION sql_mode = "ONLY_FULL_GROUP_BY"; +EXECUTE IMMEDIATE "SELECT SUM(i) OVER (ORDER BY i) FROM t1 NATURAL JOIN t2"; +SUM(i) OVER (ORDER BY i) +# Clean up +DROP TABLE t1, t2; +# # End of 10.6 tests # diff --git a/mysql-test/main/win.test b/mysql-test/main/win.test index 0c610f35453..2eed8783d44 100644 --- a/mysql-test/main/win.test +++ b/mysql-test/main/win.test @@ -2898,6 +2898,20 @@ EXECUTE IMMEDIATE "SELECT LEAD(c) OVER (ORDER BY c) FROM (SELECT 1 AS c) AS a NA DROP FUNCTION f; DROP TABLE t; +--echo # +--echo # MDEV-31296: Crash in Item_func::fix_fields when prepared statement +--echo # with subqueries and window function is executed with +--echo # sql_mode = ONLY_FULL_GROUP_BY +--echo # +CREATE TABLE t1 ( a INT, i INT) ; +CREATE TABLE t2 ( a INT); +INSERT INTO t2 VALUES (4000); +SET SESSION sql_mode = "ONLY_FULL_GROUP_BY"; +EXECUTE IMMEDIATE "SELECT SUM(i) OVER (ORDER BY i) FROM t1 NATURAL JOIN t2"; + +--echo # Clean up +DROP TABLE t1, t2; + --echo # --echo # End of 10.6 tests --echo # diff --git a/mysql-test/suite/encryption/r/tempfiles_encrypted.result b/mysql-test/suite/encryption/r/tempfiles_encrypted.result index 9dfca3aadcb..87e1536b55d 100644 --- a/mysql-test/suite/encryption/r/tempfiles_encrypted.result +++ b/mysql-test/suite/encryption/r/tempfiles_encrypted.result @@ -4421,6 +4421,19 @@ NULL DROP FUNCTION f; DROP TABLE t; # +# MDEV-31296: Crash in Item_func::fix_fields when prepared statement +# with subqueries and window function is executed with +# sql_mode = ONLY_FULL_GROUP_BY +# +CREATE TABLE t1 ( a INT, i INT) ; +CREATE TABLE t2 ( a INT); +INSERT INTO t2 VALUES (4000); +SET SESSION sql_mode = "ONLY_FULL_GROUP_BY"; +EXECUTE IMMEDIATE "SELECT SUM(i) OVER (ORDER BY i) FROM t1 NATURAL JOIN t2"; +SUM(i) OVER (ORDER BY i) +# Clean up +DROP TABLE t1, t2; +# # End of 10.6 tests # # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 39ad812e9c0..2bb9aaec322 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -6930,6 +6930,7 @@ set_new_item_local_context(THD *thd, Item_ident *item, TABLE_LIST *table_ref) if (!(context= new (thd->mem_root) Name_resolution_context)) return TRUE; context->init(); + context->select_lex= table_ref->select_lex; context->first_name_resolution_table= context->last_name_resolution_table= table_ref; item->context= context; From 7e34bb5ce12c543dec96d07d30598154f9880d55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 11 Dec 2023 10:31:49 +0200 Subject: [PATCH 415/477] MDEV-11905: Simplify encryption.innodb_encrypt_discard_import The test was populating unnecessarily large tables and restarting the server several times for no real reason. Let us hope that a smaller version of the test will produce more stable results. Occasionally, some unencrypted contents in the table t2 was revealed in the old test. --- .../r/innodb_encryption_discard_import.result | 67 ++++++++----------- .../t/innodb_encryption_discard_import.test | 60 +++++------------ 2 files changed, 45 insertions(+), 82 deletions(-) diff --git a/mysql-test/suite/encryption/r/innodb_encryption_discard_import.result b/mysql-test/suite/encryption/r/innodb_encryption_discard_import.result index 7ee30423fe7..18082027660 100644 --- a/mysql-test/suite/encryption/r/innodb_encryption_discard_import.result +++ b/mysql-test/suite/encryption/r/innodb_encryption_discard_import.result @@ -13,11 +13,13 @@ set current_num = current_num + 1; end while; end// commit; -set autocommit=0; -call innodb_insert_proc(10000); +begin; +set statement unique_checks=0, foreign_key_checks=0 for +call innodb_insert_proc(100); commit; -set autocommit=1; +DROP PROCEDURE innodb_insert_proc; # Wait max 10 min for key encryption threads to encrypt all spaces +FLUSH TABLES t1, t2, t3 FOR EXPORT; # tablespaces should be now encrypted # t1 yes on expecting NOT FOUND NOT FOUND /foobar/ in t1.ibd @@ -25,15 +27,16 @@ NOT FOUND /foobar/ in t1.ibd NOT FOUND /temp/ in t2.ibd # t3 ... on expecting NOT FOUND NOT FOUND /barfoo/ in t3.ibd -# restart db.opt +t1.cfg t1.frm t1.ibd +t2.cfg t2.frm t2.ibd +t3.cfg t3.frm t3.ibd -FLUSH TABLES t1, t2, t3 FOR EXPORT; backup: t1 backup: t2 backup: t3 @@ -55,17 +58,18 @@ restore: t1 .ibd and .cfg files restore: t2 .ibd and .cfg files restore: t3 .ibd and .cfg files ALTER TABLE t1 IMPORT TABLESPACE; -SELECT COUNT(1) FROM t1; -COUNT(1) -10000 +SELECT COUNT(*) FROM t1; +COUNT(*) +100 ALTER TABLE t2 IMPORT TABLESPACE; -SELECT COUNT(1) FROM t2; -COUNT(1) -10000 +SELECT COUNT(*) FROM t2; +COUNT(*) +100 ALTER TABLE t3 IMPORT TABLESPACE; -SELECT COUNT(1) FROM t3; -COUNT(1) -10000 +SELECT COUNT(*) FROM t3; +COUNT(*) +100 +FLUSH TABLES t1, t2, t3 FOR EXPORT; # tablespaces should remain encrypted after import # t1 yes on expecting NOT FOUND NOT FOUND /foobar/ in t1.ibd @@ -73,8 +77,8 @@ NOT FOUND /foobar/ in t1.ibd NOT FOUND /temp/ in t2.ibd # t3 ... on expecting NOT FOUND NOT FOUND /barfoo/ in t3.ibd -# restart -ALTER TABLE t1 ENGINE InnoDB; +UNLOCK TABLES; +ALTER TABLE t1 FORCE; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -82,7 +86,7 @@ t1 CREATE TABLE `t1` ( `a` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci `encrypted`=yes -ALTER TABLE t2 ENGINE InnoDB; +ALTER TABLE t2 FORCE; SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( @@ -90,7 +94,7 @@ t2 CREATE TABLE `t2` ( `a` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci -ALTER TABLE t3 ENGINE InnoDB; +ALTER TABLE t3 FORCE; SHOW CREATE TABLE t3; Table Create Table t3 CREATE TABLE `t3` ( @@ -98,30 +102,17 @@ t3 CREATE TABLE `t3` ( `a` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=COMPRESSED `encrypted`=yes -# Restarting server -# restart -# Done restarting server # Verify that tables are still usable -SELECT COUNT(1) FROM t1; -COUNT(1) -10000 -SELECT COUNT(1) FROM t2; -COUNT(1) -10000 -SELECT COUNT(1) FROM t3; -COUNT(1) -10000 -# Tablespaces should be encrypted after restart +CHECK TABLE t1, t2, t3 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t2 check status OK +test.t3 check status OK +FLUSH TABLES t1, t2, t3 FOR EXPORT; # t1 yes on expecting NOT FOUND NOT FOUND /foobar/ in t1.ibd # t2 ... on expecting NOT FOUND NOT FOUND /temp/ in t2.ibd # t3 ... on expecting NOT FOUND -NOT FOUND /barfoo/ in t3.ibd -# restart -# Wait max 10 min for key encryption threads to encrypt all spaces -# Success! -# Restart mysqld --innodb_encrypt_tables=0 --innodb_encryption_threads=0 -# restart: --innodb_encrypt_tables=0 --innodb_encryption_threads=0 -DROP PROCEDURE innodb_insert_proc; +UNLOCK TABLES; DROP TABLE t1, t2, t3; diff --git a/mysql-test/suite/encryption/t/innodb_encryption_discard_import.test b/mysql-test/suite/encryption/t/innodb_encryption_discard_import.test index 22755571618..5f02d966e7e 100644 --- a/mysql-test/suite/encryption/t/innodb_encryption_discard_import.test +++ b/mysql-test/suite/encryption/t/innodb_encryption_discard_import.test @@ -6,7 +6,6 @@ let MYSQLD_DATADIR = `SELECT @@datadir`; --let SEARCH_RANGE = 10000000 ---let $id = `SELECT RAND()` --let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd --let t2_IBD = $MYSQLD_DATADIR/test/t2.ibd --let t3_IBD = $MYSQLD_DATADIR/test/t3.ibd @@ -30,19 +29,18 @@ end// delimiter ;// commit; -set autocommit=0; -call innodb_insert_proc(10000); +begin; +set statement unique_checks=0, foreign_key_checks=0 for +call innodb_insert_proc(100); commit; -set autocommit=1; +DROP PROCEDURE innodb_insert_proc; --echo # Wait max 10 min for key encryption threads to encrypt all spaces --let $wait_timeout= 600 --let $wait_condition=SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 AND ROTATING_OR_FLUSHING <> 0 --source include/wait_condition.inc -# shutdown so that grep is safe ---source include/shutdown_mysqld.inc - +FLUSH TABLES t1, t2, t3 FOR EXPORT; --echo # tablespaces should be now encrypted --let SEARCH_PATTERN=foobar --echo # t1 yes on expecting NOT FOUND @@ -57,11 +55,8 @@ set autocommit=1; -- let SEARCH_FILE=$t3_IBD -- source include/search_pattern_in_file.inc ---source include/start_mysqld.inc let MYSQLD_DATADIR =`SELECT @@datadir`; - --list_files $MYSQLD_DATADIR/test -FLUSH TABLES t1, t2, t3 FOR EXPORT; perl; do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; ib_backup_tablespaces("test", "t1","t2","t3"); @@ -80,14 +75,13 @@ ib_restore_tablespaces("test", "t1","t2","t3"); EOF ALTER TABLE t1 IMPORT TABLESPACE; -SELECT COUNT(1) FROM t1; +SELECT COUNT(*) FROM t1; ALTER TABLE t2 IMPORT TABLESPACE; -SELECT COUNT(1) FROM t2; +SELECT COUNT(*) FROM t2; ALTER TABLE t3 IMPORT TABLESPACE; -SELECT COUNT(1) FROM t3; +SELECT COUNT(*) FROM t3; -# shutdown so that grep is safe ---source include/shutdown_mysqld.inc +FLUSH TABLES t1, t2, t3 FOR EXPORT; --echo # tablespaces should remain encrypted after import --let SEARCH_PATTERN=foobar @@ -103,28 +97,18 @@ SELECT COUNT(1) FROM t3; -- let SEARCH_FILE=$t3_IBD -- source include/search_pattern_in_file.inc ---source include/start_mysqld.inc - -ALTER TABLE t1 ENGINE InnoDB; +UNLOCK TABLES; +ALTER TABLE t1 FORCE; SHOW CREATE TABLE t1; -ALTER TABLE t2 ENGINE InnoDB; +ALTER TABLE t2 FORCE; SHOW CREATE TABLE t2; -ALTER TABLE t3 ENGINE InnoDB; +ALTER TABLE t3 FORCE; SHOW CREATE TABLE t3; ---echo # Restarting server --- source include/restart_mysqld.inc ---echo # Done restarting server - --echo # Verify that tables are still usable -SELECT COUNT(1) FROM t1; -SELECT COUNT(1) FROM t2; -SELECT COUNT(1) FROM t3; +CHECK TABLE t1, t2, t3 EXTENDED; +FLUSH TABLES t1, t2, t3 FOR EXPORT; -# shutdown so that grep is safe ---source include/shutdown_mysqld.inc - ---echo # Tablespaces should be encrypted after restart --let SEARCH_PATTERN=foobar --echo # t1 yes on expecting NOT FOUND -- let SEARCH_FILE=$t1_IBD @@ -136,19 +120,7 @@ SELECT COUNT(1) FROM t3; --echo # t3 ... on expecting NOT FOUND --let SEARCH_PATTERN=barfoo -- let SEARCH_FILE=$t3_IBD --- source include/search_pattern_in_file.inc ---source include/start_mysqld.inc +UNLOCK TABLES; ---echo # Wait max 10 min for key encryption threads to encrypt all spaces ---let $wait_timeout= 600 ---let $wait_condition=SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 AND ROTATING_OR_FLUSHING <> 0 ---source include/wait_condition.inc - ---echo # Success! ---echo # Restart mysqld --innodb_encrypt_tables=0 --innodb_encryption_threads=0 --- let $restart_parameters=--innodb_encrypt_tables=0 --innodb_encryption_threads=0 --- source include/restart_mysqld.inc - -DROP PROCEDURE innodb_insert_proc; DROP TABLE t1, t2, t3; From 1e80601b826730f11544cc8b58e28c3e73f0cd33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 11 Dec 2023 10:37:12 +0200 Subject: [PATCH 416/477] MDEV-16264 fixup: Remove a useless test Let us remove a test that frequently fails with a result difference. This test had been added in fc279d7ea263d8fd5f588b360a59c6891896f0b0 to cover a bug in thd_destructor_proxy(), which was replaced with simpler logic in 5e62b6a5e06eb02cbde1e34e95e26f42d87fce02 (MDEV-16264). --- .../innodb/r/purge_thread_shutdown.result | 27 ------------ .../suite/innodb/t/purge_thread_shutdown.test | 43 ------------------- 2 files changed, 70 deletions(-) delete mode 100644 mysql-test/suite/innodb/r/purge_thread_shutdown.result delete mode 100644 mysql-test/suite/innodb/t/purge_thread_shutdown.test diff --git a/mysql-test/suite/innodb/r/purge_thread_shutdown.result b/mysql-test/suite/innodb/r/purge_thread_shutdown.result deleted file mode 100644 index 85ac77e6d49..00000000000 --- a/mysql-test/suite/innodb/r/purge_thread_shutdown.result +++ /dev/null @@ -1,27 +0,0 @@ -connect con1, localhost, root; -create table t1 (a int) engine=innodb; -insert t1 values (1),(2),(3),(4); -delete from t1 where a=1; -select user,state from information_schema.processlist order by 2; -user state -root -root Filling schema table -set global debug_dbug='+d,only_kill_system_threads'; -set global innodb_fast_shutdown=0; -shutdown; -connection default; -disconnect con1; -select user,state from information_schema.processlist order by 2; -user state -root Filling schema table -set global innodb_fast_shutdown=1; -select user,state from information_schema.processlist order by 2; -user state -root Filling schema table -delete from t1 where a=3; -set global innodb_fast_shutdown=0; -ERROR 42000: Variable 'innodb_fast_shutdown' can't be set to the value of '0' -kill ID; -ERROR 70100: Connection was killed -# restart -drop table t1; diff --git a/mysql-test/suite/innodb/t/purge_thread_shutdown.test b/mysql-test/suite/innodb/t/purge_thread_shutdown.test deleted file mode 100644 index 762336cf0d1..00000000000 --- a/mysql-test/suite/innodb/t/purge_thread_shutdown.test +++ /dev/null @@ -1,43 +0,0 @@ -source include/have_innodb.inc; -source include/not_embedded.inc; -source include/have_debug.inc; - -connect con1, localhost, root; -create table t1 (a int) engine=innodb; -insert t1 values (1),(2),(3),(4); -delete from t1 where a=1; - -select user,state from information_schema.processlist order by 2; - -set global debug_dbug='+d,only_kill_system_threads'; -set global innodb_fast_shutdown=0; - ---let $_expect_file_name= `select regexp_replace(@@tmpdir, '^.*/','')` ---let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/$_expect_file_name.expect -exec echo "wait" > $_expect_file_name; -send shutdown; - -connection default; -disconnect con1; - -sleep 5; -select user,state from information_schema.processlist order by 2; -set global innodb_fast_shutdown=1; - -let $wait_condition=select count(*) = 0 from information_schema.processlist where user='system user'; -source include/wait_condition.inc; -select user,state from information_schema.processlist order by 2; - -delete from t1 where a=3; -error ER_WRONG_VALUE_FOR_VAR; -set global innodb_fast_shutdown=0; - -# Get id with space prefix to ensure that replace_result doesn't replace -# the error code -let $me=`select concat(' ', connection_id())`; -replace_result $me ID; -error ER_CONNECTION_KILLED; -eval kill $me; - -source include/start_mysqld.inc; -drop table t1; From da9ffca908a0e61935409cf2166ad8bd985765bb Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 24 Nov 2023 07:38:16 +0100 Subject: [PATCH 417/477] MDEV-29816 rpl.rpl_parallel_29322 occasionally fails in BB Make sure the old binlog dump thread is not still running when manipulating binlog files; otherwise there is a small chance it will see an invalid partial file and report an I/O error. Signed-off-by: Kristian Nielsen --- mysql-test/suite/rpl/include/rpl_parallel_29322.inc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mysql-test/suite/rpl/include/rpl_parallel_29322.inc b/mysql-test/suite/rpl/include/rpl_parallel_29322.inc index 54eb13d7f09..b32d463294a 100644 --- a/mysql-test/suite/rpl/include/rpl_parallel_29322.inc +++ b/mysql-test/suite/rpl/include/rpl_parallel_29322.inc @@ -66,6 +66,17 @@ if ($same_version_binlogs) if (!$same_version_binlogs) { + # Make sure the dump thread is gone before moving around binlog files. Else + # it might see an empty file and give error (MDEV-29816). + --let $dump_thrid= `Select id FROM information_schema.processlist WHERE Command='Binlog Dump'` + if ($dump_thrid) { + --disable_query_log + --error 0,ER_NO_SUCH_THREAD + eval KILL CONNECTION $dump_thrid; + --enable_query_log + --let $wait_condition= SELECT COUNT(*)=0 FROM information_schema.processlist WHERE Command='Binlog Dump' + --source include/wait_condition.inc + } --move_file $datadir/master-bin.000002 $datadir/master-bin.000002.sav --copy_file $MYSQL_TEST_DIR/std_data/mdev29078-mysql-bin.000001 $datadir/master-bin.000002 --exec $MYSQL_BINLOG --short-form $datadir/master-bin.000002 From 50ce001afd6ca354fc679ce95c53194eeedbdd98 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Mon, 11 Dec 2023 10:48:42 +0100 Subject: [PATCH 418/477] MDEV-13792: innodb.purge_thread_shutdown failed in buildbot with wrong result (sporadic) Omit `state` when selecting processlist to verify which threads are running. The state changes as threads are running (enter_state()), and this causes sporadic test failures. Signed-off-by: Kristian Nielsen --- .../innodb/r/purge_thread_shutdown.result | 40 +++++++++---------- .../suite/innodb/t/purge_thread_shutdown.test | 6 +-- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/mysql-test/suite/innodb/r/purge_thread_shutdown.result b/mysql-test/suite/innodb/r/purge_thread_shutdown.result index a87cba89917..e40c10561dc 100644 --- a/mysql-test/suite/innodb/r/purge_thread_shutdown.result +++ b/mysql-test/suite/innodb/r/purge_thread_shutdown.result @@ -2,32 +2,32 @@ connect con1, localhost, root; create table t1 (a int) engine=innodb; insert t1 values (1),(2),(3),(4); delete from t1 where a=1; -select user,state from information_schema.processlist order by 2; -user state -root -root Filling schema table -system user InnoDB purge coordinator -system user InnoDB purge worker -system user InnoDB purge worker -system user InnoDB purge worker -system user InnoDB shutdown handler +select user from information_schema.processlist order by 1; +user +root +root +system user +system user +system user +system user +system user set global debug_dbug='+d,only_kill_system_threads'; set global innodb_fast_shutdown=0; shutdown; connection default; disconnect con1; -select user,state from information_schema.processlist order by 2; -user state -root Filling schema table -system user InnoDB purge coordinator -system user InnoDB purge worker -system user InnoDB purge worker -system user InnoDB purge worker -system user InnoDB slow shutdown wait +select user from information_schema.processlist order by 1; +user +root +system user +system user +system user +system user +system user set global innodb_fast_shutdown=1; -select user,state from information_schema.processlist order by 2; -user state -root Filling schema table +select user from information_schema.processlist order by 1; +user +root delete from t1 where a=3; set global innodb_fast_shutdown=0; ERROR 42000: Variable 'innodb_fast_shutdown' can't be set to the value of '0' diff --git a/mysql-test/suite/innodb/t/purge_thread_shutdown.test b/mysql-test/suite/innodb/t/purge_thread_shutdown.test index 762336cf0d1..1cc8849f083 100644 --- a/mysql-test/suite/innodb/t/purge_thread_shutdown.test +++ b/mysql-test/suite/innodb/t/purge_thread_shutdown.test @@ -7,7 +7,7 @@ create table t1 (a int) engine=innodb; insert t1 values (1),(2),(3),(4); delete from t1 where a=1; -select user,state from information_schema.processlist order by 2; +select user from information_schema.processlist order by 1; set global debug_dbug='+d,only_kill_system_threads'; set global innodb_fast_shutdown=0; @@ -21,12 +21,12 @@ connection default; disconnect con1; sleep 5; -select user,state from information_schema.processlist order by 2; +select user from information_schema.processlist order by 1; set global innodb_fast_shutdown=1; let $wait_condition=select count(*) = 0 from information_schema.processlist where user='system user'; source include/wait_condition.inc; -select user,state from information_schema.processlist order by 2; +select user from information_schema.processlist order by 1; delete from t1 where a=3; error ER_WRONG_VALUE_FOR_VAR; From 5ca63b2b8b4fafd82314f6d6595128b3b12a2311 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Mon, 11 Dec 2023 11:14:53 +0100 Subject: [PATCH 419/477] MDEV-26632: multi source replication filters breaking GTID semantic Add a test case that demonstrates a working setup as described in MDEV-26632. This requires --gtid-ignore-duplicates=1 and --gtid-strict-mode=0. In A->B->C, B filters some (but not all) events from A. C is promoted to create A->C->B, and the current GTID position in B contains a GTID from A that is not present in C (due to filtering). Demonstrate that B can still connect with GTID to C, starting at the "hole" in the binlog stream on C originating from A. Signed-off-by: Kristian Nielsen --- .../rpl/r/rpl_gtid_slave_filtering.result | 78 +++++++++++++ .../suite/rpl/t/rpl_gtid_slave_filtering.cnf | 28 +++++ .../suite/rpl/t/rpl_gtid_slave_filtering.test | 109 ++++++++++++++++++ 3 files changed, 215 insertions(+) create mode 100644 mysql-test/suite/rpl/r/rpl_gtid_slave_filtering.result create mode 100644 mysql-test/suite/rpl/t/rpl_gtid_slave_filtering.cnf create mode 100644 mysql-test/suite/rpl/t/rpl_gtid_slave_filtering.test diff --git a/mysql-test/suite/rpl/r/rpl_gtid_slave_filtering.result b/mysql-test/suite/rpl/r/rpl_gtid_slave_filtering.result new file mode 100644 index 00000000000..84080b94de8 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_gtid_slave_filtering.result @@ -0,0 +1,78 @@ +include/rpl_init.inc [topology=1->2->3] +*** Test GTID master switch in a topology with filtered events. +*** With --gtid-ignore-duplicate and --gtid-strict-mode, should allow +*** GTID connect at a GTID position that is filtered on the new master. +connection server_1; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1); +CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t3 VALUES (1,1); +INSERT INTO t1 VALUES (2,1); +INSERT INTO t3 VALUES (2,1); +include/save_master_gtid.inc +connection server_2; +CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,2); +include/sync_with_master_gtid.inc +include/save_master_gtid.inc +connection server_3; +include/sync_with_master_gtid.inc +*** Promote 3 as new master, demote 2 as slave of 3. +*** GTID position of 2 in domain 0 is filtered on 3. +connection server_2; +include/stop_slave.inc +connection server_3; +include/stop_slave.inc +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_1, +MASTER_USE_GTID=SLAVE_POS; +connection server_2; +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_3, +MASTER_USE_GTID=SLAVE_POS; +include/start_slave.inc +connection server_3; +include/start_slave.inc +connection server_1; +INSERT INTO t1 VALUES (3,1); +INSERT INTO t3 VALUES (3,1); +include/save_master_gtid.inc +connection server_3; +INSERT INTO t2 VALUES (2,2); +include/sync_with_master_gtid.inc +include/save_master_gtid.inc +connection server_2; +include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +a b +1 1 +2 1 +3 1 +SELECT * FROM t3 ORDER BY a; +ERROR 42S02: Table 'test.t3' doesn't exist +SELECT * FROM t2 ORDER BY a; +a b +1 2 +2 2 +*** Restore original topology. +connection server_3; +include/stop_slave.inc +connection server_2; +include/stop_slave.inc +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_1, +MASTER_USE_GTID=SLAVE_POS; +include/start_slave.inc +connection server_3; +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_2, +MASTER_USE_GTID=SLAVE_POS; +include/start_slave.inc +connection server_1; +DROP TABLE t1; +DROP TABLE t3; +include/save_master_gtid.inc +connection server_2; +DROP TABLE t2; +include/sync_with_master_gtid.inc +include/save_master_gtid.inc +connection server_3; +include/sync_with_master_gtid.inc +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_slave_filtering.cnf b/mysql-test/suite/rpl/t/rpl_gtid_slave_filtering.cnf new file mode 100644 index 00000000000..a57dbbf3f56 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_slave_filtering.cnf @@ -0,0 +1,28 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb +gtid-domain-id=1 +gtid-strict-mode=0 +gtid-ignore-duplicates=1 + +[mysqld.2] +log-slave-updates +loose-innodb +gtid-domain-id=0 +replicate-ignore-table=test.t3 +gtid-strict-mode=0 +gtid-ignore-duplicates=1 + +[mysqld.3] +log-slave-updates +loose-innodb +gtid-domain-id=0 +replicate-ignore-table=test.t3 +gtid-strict-mode=0 +gtid-ignore-duplicates=1 + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket diff --git a/mysql-test/suite/rpl/t/rpl_gtid_slave_filtering.test b/mysql-test/suite/rpl/t/rpl_gtid_slave_filtering.test new file mode 100644 index 00000000000..842bae8234c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_slave_filtering.test @@ -0,0 +1,109 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_mixed.inc + +--let $rpl_topology=1->2->3 +--source include/rpl_init.inc + +--echo *** Test GTID master switch in a topology with filtered events. +--echo *** With --gtid-ignore-duplicate and --gtid-strict-mode, should allow +--echo *** GTID connect at a GTID position that is filtered on the new master. + +--connection server_1 + +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1); +CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t3 VALUES (1,1); +INSERT INTO t1 VALUES (2,1); +INSERT INTO t3 VALUES (2,1); +--source include/save_master_gtid.inc + +--connection server_2 +CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,2); + +--let $slave_timeout= 10 +--source include/sync_with_master_gtid.inc +--source include/save_master_gtid.inc + +--connection server_3 +--source include/sync_with_master_gtid.inc + +--echo *** Promote 3 as new master, demote 2 as slave of 3. +--echo *** GTID position of 2 in domain 0 is filtered on 3. + +--connection server_2 +--source include/stop_slave.inc + +--connection server_3 +--source include/stop_slave.inc +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1, + MASTER_USE_GTID=SLAVE_POS; + +--connection server_2 +--replace_result $SERVER_MYPORT_3 SERVER_MYPORT_3 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_3, + MASTER_USE_GTID=SLAVE_POS; +--source include/start_slave.inc + +--connection server_3 +--source include/start_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (3,1); +INSERT INTO t3 VALUES (3,1); +--source include/save_master_gtid.inc + +--connection server_3 +INSERT INTO t2 VALUES (2,2); + +--source include/sync_with_master_gtid.inc +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 ORDER BY a; +# Verify that table t3 is being filtered. +--error 1146 +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + + +--echo *** Restore original topology. + +--connection server_3 +--source include/stop_slave.inc + +--connection server_2 +--source include/stop_slave.inc +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1, + MASTER_USE_GTID=SLAVE_POS; +--source include/start_slave.inc + +--connection server_3 +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2, + MASTER_USE_GTID=SLAVE_POS; +--source include/start_slave.inc + + +# Cleanup + +--connection server_1 +DROP TABLE t1; +DROP TABLE t3; +--source include/save_master_gtid.inc + +--connection server_2 +DROP TABLE t2; +--source include/sync_with_master_gtid.inc +--source include/save_master_gtid.inc + +--connection server_3 +--source include/sync_with_master_gtid.inc + +--source include/rpl_end.inc From 917a7386bfbdcbb75d8e031f0cd40e6574f35a48 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Thu, 16 Nov 2023 12:46:30 +0100 Subject: [PATCH 420/477] MDEV-32819: main.show_explain failed in buildbot The testcase had a race in two places where a KILL QUERY is made towards a running query in another connection. The query can complete early so the kill is lost, and the test fails due to expecting ER_QUERY_INTERRUPTED. Fix by removing the KILL QUERY. It is not needed, as the query completes by itself after SHOW EXPLAIN FOR. Signed-off-by: Kristian Nielsen --- mysql-test/main/show_explain.result | 11 +++++++---- mysql-test/main/show_explain.test | 4 ---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/mysql-test/main/show_explain.result b/mysql-test/main/show_explain.result index 6bdc773aa4c..22ac7de6153 100644 --- a/mysql-test/main/show_explain.result +++ b/mysql-test/main/show_explain.result @@ -244,9 +244,7 @@ set @foo= (select max(a) from t0 where sin(a) >0); connection default; show explain for $thr2; ERROR HY000: Target is not executing an operation with a query plan -kill query $thr2; connection con1; -ERROR 70100: Query execution was interrupted SET debug_dbug=@old_debug; # # Attempt SHOW EXPLAIN for an UPDATE @@ -568,9 +566,14 @@ SELECT * FROM v1, t2; connection default; show explain for $thr2; ERROR HY000: Target is not executing an operation with a query plan -kill query $thr2; connection con1; -ERROR 70100: Query execution was interrupted +a b +8 4 +8 5 +8 6 +8 7 +8 8 +8 9 SET debug_dbug=@old_debug; DROP VIEW v1; DROP TABLE t2, t3; diff --git a/mysql-test/main/show_explain.test b/mysql-test/main/show_explain.test index e6cf3971738..749c08b1804 100644 --- a/mysql-test/main/show_explain.test +++ b/mysql-test/main/show_explain.test @@ -273,9 +273,7 @@ connection default; --source include/wait_condition.inc --error ER_TARGET_NOT_EXPLAINABLE evalp show explain for $thr2; -evalp kill query $thr2; connection con1; ---error ER_QUERY_INTERRUPTED reap; SET debug_dbug=@old_debug; @@ -504,9 +502,7 @@ connection default; --source include/wait_condition.inc --error ER_TARGET_NOT_EXPLAINABLE evalp show explain for $thr2; -evalp kill query $thr2; connection con1; ---error ER_QUERY_INTERRUPTED reap; SET debug_dbug=@old_debug; DROP VIEW v1; From a016b18a58f06bac0833444c1c43c536dce21a65 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Mon, 11 Dec 2023 14:29:04 +0100 Subject: [PATCH 421/477] MDEV-27849: rpl.rpl_start_alter_XXX fail sporadically in buildbot The problem is that these tests run optimistic parallel replication with non-transactional mysql.gtid_slave_pos table. Very occasionally InnoDB stats update may race with one another and cause a parallel replication deadlock kill after the mysql.gtid_slave_pos table has been updated. Since mysql.gtid_slave_pos is non-transactional, the update cannot be rolled back, and transaction retry will fail with a duplicate key error in mysql.gtid_slave_pos. Fixed by altering the storage engine to InnoDB for the table. Signed-off-by: Kristian Nielsen --- mysql-test/suite/rpl/r/rpl_start_alter_1.result | 1 + mysql-test/suite/rpl/r/rpl_start_alter_2.result | 1 + mysql-test/suite/rpl/r/rpl_start_alter_3.result | 1 + mysql-test/suite/rpl/r/rpl_start_alter_4.result | 1 + mysql-test/suite/rpl/r/rpl_start_alter_5.result | 1 + mysql-test/suite/rpl/r/rpl_start_alter_6.result | 1 + mysql-test/suite/rpl/r/rpl_start_alter_7.result | 4 ++++ mysql-test/suite/rpl/r/rpl_start_alter_8.result | 4 ++++ mysql-test/suite/rpl/r/rpl_start_alter_mysqlbinlog_1.result | 2 ++ mysql-test/suite/rpl/r/rpl_start_alter_mysqlbinlog_2.result | 4 ++++ mysql-test/suite/rpl/t/rpl_start_alter_1.test | 1 + mysql-test/suite/rpl/t/rpl_start_alter_2.test | 2 ++ mysql-test/suite/rpl/t/rpl_start_alter_3.test | 2 ++ mysql-test/suite/rpl/t/rpl_start_alter_4.test | 1 + mysql-test/suite/rpl/t/rpl_start_alter_5.test | 1 + mysql-test/suite/rpl/t/rpl_start_alter_6.test | 1 + mysql-test/suite/rpl/t/rpl_start_alter_7.test | 4 ++++ mysql-test/suite/rpl/t/rpl_start_alter_8.test | 4 ++++ mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_1.test | 2 ++ mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.test | 4 ++++ 20 files changed, 42 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_start_alter_1.result b/mysql-test/suite/rpl/r/rpl_start_alter_1.result index 9edb23216fe..de7c0875344 100644 --- a/mysql-test/suite/rpl/r/rpl_start_alter_1.result +++ b/mysql-test/suite/rpl/r/rpl_start_alter_1.result @@ -1,6 +1,7 @@ include/master-slave.inc [connection master] connection master; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; set global binlog_alter_two_phase = ON; set binlog_alter_two_phase = ON; connection slave; diff --git a/mysql-test/suite/rpl/r/rpl_start_alter_2.result b/mysql-test/suite/rpl/r/rpl_start_alter_2.result index a862fc5556a..49af973fb61 100644 --- a/mysql-test/suite/rpl/r/rpl_start_alter_2.result +++ b/mysql-test/suite/rpl/r/rpl_start_alter_2.result @@ -1,6 +1,7 @@ include/master-slave.inc [connection master] connection master; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; set global binlog_alter_two_phase = ON; set binlog_alter_two_phase = ON; connection slave; diff --git a/mysql-test/suite/rpl/r/rpl_start_alter_3.result b/mysql-test/suite/rpl/r/rpl_start_alter_3.result index 97754401471..31d0023bb46 100644 --- a/mysql-test/suite/rpl/r/rpl_start_alter_3.result +++ b/mysql-test/suite/rpl/r/rpl_start_alter_3.result @@ -1,6 +1,7 @@ include/master-slave.inc [connection master] connection master; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; set global binlog_alter_two_phase = ON; set binlog_alter_two_phase = ON; connection slave; diff --git a/mysql-test/suite/rpl/r/rpl_start_alter_4.result b/mysql-test/suite/rpl/r/rpl_start_alter_4.result index 9d7d6376bba..819bcda0c00 100644 --- a/mysql-test/suite/rpl/r/rpl_start_alter_4.result +++ b/mysql-test/suite/rpl/r/rpl_start_alter_4.result @@ -1,6 +1,7 @@ include/master-slave.inc [connection master] connection master; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; set global binlog_alter_two_phase = ON; set binlog_alter_two_phase = ON; connection slave; diff --git a/mysql-test/suite/rpl/r/rpl_start_alter_5.result b/mysql-test/suite/rpl/r/rpl_start_alter_5.result index 4e592c1931f..ef19cd8f380 100644 --- a/mysql-test/suite/rpl/r/rpl_start_alter_5.result +++ b/mysql-test/suite/rpl/r/rpl_start_alter_5.result @@ -1,6 +1,7 @@ include/master-slave.inc [connection master] connection master; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; set global binlog_alter_two_phase = ON; set binlog_alter_two_phase = ON; connection slave; diff --git a/mysql-test/suite/rpl/r/rpl_start_alter_6.result b/mysql-test/suite/rpl/r/rpl_start_alter_6.result index 6c26d511ee2..59a8363165f 100644 --- a/mysql-test/suite/rpl/r/rpl_start_alter_6.result +++ b/mysql-test/suite/rpl/r/rpl_start_alter_6.result @@ -1,6 +1,7 @@ include/master-slave.inc [connection master] connection master; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; set global binlog_alter_two_phase = ON; set binlog_alter_two_phase = ON; connection slave; diff --git a/mysql-test/suite/rpl/r/rpl_start_alter_7.result b/mysql-test/suite/rpl/r/rpl_start_alter_7.result index cfe31497179..df7664d4aa2 100644 --- a/mysql-test/suite/rpl/r/rpl_start_alter_7.result +++ b/mysql-test/suite/rpl/r/rpl_start_alter_7.result @@ -10,6 +10,10 @@ Warnings: Note 1255 Slave already has been stopped set global binlog_alter_two_phase=true; connection server_3; +SET STATEMENT sql_log_bin=0 FOR +CALL mtr.add_suppression("The table mysql.gtid_slave_pos was removed. This change will not take full effect until all SQL threads have been restarted"); +SET STATEMENT sql_log_bin=0 FOR +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; SET GLOBAL slave_parallel_threads=8; set global slave_parallel_mode=optimistic; set global gtid_strict_mode=1; diff --git a/mysql-test/suite/rpl/r/rpl_start_alter_8.result b/mysql-test/suite/rpl/r/rpl_start_alter_8.result index 8002f295f5c..406f2d1f6fc 100644 --- a/mysql-test/suite/rpl/r/rpl_start_alter_8.result +++ b/mysql-test/suite/rpl/r/rpl_start_alter_8.result @@ -10,6 +10,10 @@ Warnings: Note 1255 Slave already has been stopped set global binlog_alter_two_phase=true; connection server_3; +SET STATEMENT sql_log_bin=0 FOR +CALL mtr.add_suppression("The table mysql.gtid_slave_pos was removed. This change will not take full effect until all SQL threads have been restarted"); +SET STATEMENT sql_log_bin=0 FOR +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; SET GLOBAL slave_parallel_threads=20; set global slave_parallel_mode=optimistic; set global gtid_strict_mode=1; diff --git a/mysql-test/suite/rpl/r/rpl_start_alter_mysqlbinlog_1.result b/mysql-test/suite/rpl/r/rpl_start_alter_mysqlbinlog_1.result index bf9d9be0ec6..b11804ed1c7 100644 --- a/mysql-test/suite/rpl/r/rpl_start_alter_mysqlbinlog_1.result +++ b/mysql-test/suite/rpl/r/rpl_start_alter_mysqlbinlog_1.result @@ -4,6 +4,8 @@ connection master; set global binlog_alter_two_phase=true; connection slave; include/stop_slave.inc +SET STATEMENT sql_log_bin=0 FOR +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; set global gtid_strict_mode=1; # Legacy Master Slave connect master_node,127.0.0.1,root,,$db_name, $M_port; diff --git a/mysql-test/suite/rpl/r/rpl_start_alter_mysqlbinlog_2.result b/mysql-test/suite/rpl/r/rpl_start_alter_mysqlbinlog_2.result index 2c1ae667fd6..55bec7d3998 100644 --- a/mysql-test/suite/rpl/r/rpl_start_alter_mysqlbinlog_2.result +++ b/mysql-test/suite/rpl/r/rpl_start_alter_mysqlbinlog_2.result @@ -49,6 +49,10 @@ connection server_2; SET @save_binlog_alter_two_phase= @@GLOBAL.binlog_alter_two_phase; SET GLOBAL binlog_alter_two_phase = ON; connection server_3; +SET STATEMENT sql_log_bin=0 FOR +CALL mtr.add_suppression("The table mysql.gtid_slave_pos was removed. This change will not take full effect until all SQL threads have been restarted"); +SET STATEMENT sql_log_bin=0 FOR +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; SET @save_gtid_strict_mode= @@GLOBAL.gtid_strict_mode; SET @slave_parallel_threads= @@GLOBAL.slave_parallel_threads; SET @slave_parallel_mode= @@GLOBAL.slave_parallel_mode; diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_1.test b/mysql-test/suite/rpl/t/rpl_start_alter_1.test index 9ce061f1031..b16f6a53393 100644 --- a/mysql-test/suite/rpl/t/rpl_start_alter_1.test +++ b/mysql-test/suite/rpl/t/rpl_start_alter_1.test @@ -6,6 +6,7 @@ --source include/master-slave.inc --connection master +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; --let $binlog_alter_two_phase= `select @@binlog_alter_two_phase` set global binlog_alter_two_phase = ON; set binlog_alter_two_phase = ON; diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_2.test b/mysql-test/suite/rpl/t/rpl_start_alter_2.test index 457409c51a6..a5cef2e51e5 100644 --- a/mysql-test/suite/rpl/t/rpl_start_alter_2.test +++ b/mysql-test/suite/rpl/t/rpl_start_alter_2.test @@ -8,9 +8,11 @@ --source include/have_debug.inc --source include/master-slave.inc --connection master +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; --let $binlog_alter_two_phase= `select @@binlog_alter_two_phase` set global binlog_alter_two_phase = ON; set binlog_alter_two_phase = ON; + --connection slave --let $gtid_strict_mode= `select @@gtid_strict_mode` --let $slave_parallel_threads= `select @@slave_parallel_threads` diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_3.test b/mysql-test/suite/rpl/t/rpl_start_alter_3.test index b280aeb9e5e..8207dcbbc25 100644 --- a/mysql-test/suite/rpl/t/rpl_start_alter_3.test +++ b/mysql-test/suite/rpl/t/rpl_start_alter_3.test @@ -9,9 +9,11 @@ --source include/master-slave.inc --source include/have_debug.inc --connection master +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; --let $binlog_alter_two_phase= `select @@binlog_alter_two_phase` set global binlog_alter_two_phase = ON; set binlog_alter_two_phase = ON; + --connection slave --let $gtid_strict_mode= `select @@gtid_strict_mode` --let $slave_parallel_threads= `select @@slave_parallel_threads` diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_4.test b/mysql-test/suite/rpl/t/rpl_start_alter_4.test index 8c67b50a7bf..f4edc4b928c 100644 --- a/mysql-test/suite/rpl/t/rpl_start_alter_4.test +++ b/mysql-test/suite/rpl/t/rpl_start_alter_4.test @@ -9,6 +9,7 @@ --source include/master-slave.inc --source include/have_debug.inc --connection master +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; --let $binlog_alter_two_phase= `select @@binlog_alter_two_phase` set global binlog_alter_two_phase = ON; set binlog_alter_two_phase = ON; diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_5.test b/mysql-test/suite/rpl/t/rpl_start_alter_5.test index 10d0d523a68..b2d31f21039 100644 --- a/mysql-test/suite/rpl/t/rpl_start_alter_5.test +++ b/mysql-test/suite/rpl/t/rpl_start_alter_5.test @@ -9,6 +9,7 @@ --source include/master-slave.inc --source include/have_debug.inc --connection master +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; --let $binlog_alter_two_phase= `select @@binlog_alter_two_phase` set global binlog_alter_two_phase = ON; set binlog_alter_two_phase = ON; diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_6.test b/mysql-test/suite/rpl/t/rpl_start_alter_6.test index fc49ea4a406..6c2b50156d0 100644 --- a/mysql-test/suite/rpl/t/rpl_start_alter_6.test +++ b/mysql-test/suite/rpl/t/rpl_start_alter_6.test @@ -10,6 +10,7 @@ --source include/master-slave.inc --source include/have_debug.inc --connection master +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; --let $binlog_alter_two_phase= `select @@binlog_alter_two_phase` set global binlog_alter_two_phase = ON; set binlog_alter_two_phase = ON; diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_7.test b/mysql-test/suite/rpl/t/rpl_start_alter_7.test index 7225c075ea7..21c21c85c59 100644 --- a/mysql-test/suite/rpl/t/rpl_start_alter_7.test +++ b/mysql-test/suite/rpl/t/rpl_start_alter_7.test @@ -21,6 +21,10 @@ stop slave; set global binlog_alter_two_phase=true; --connection server_3 +SET STATEMENT sql_log_bin=0 FOR + CALL mtr.add_suppression("The table mysql.gtid_slave_pos was removed. This change will not take full effect until all SQL threads have been restarted"); +SET STATEMENT sql_log_bin=0 FOR + ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; --let $gtid_strict_mode= `select @@gtid_strict_mode` --let $slave_parallel_threads= `select @@slave_parallel_threads` --let $slave_parallel_mode= `select @@slave_parallel_mode` diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_8.test b/mysql-test/suite/rpl/t/rpl_start_alter_8.test index 4ab8e2b01e5..c8c5ac74404 100644 --- a/mysql-test/suite/rpl/t/rpl_start_alter_8.test +++ b/mysql-test/suite/rpl/t/rpl_start_alter_8.test @@ -21,6 +21,10 @@ stop slave; set global binlog_alter_two_phase=true; --connection server_3 +SET STATEMENT sql_log_bin=0 FOR + CALL mtr.add_suppression("The table mysql.gtid_slave_pos was removed. This change will not take full effect until all SQL threads have been restarted"); +SET STATEMENT sql_log_bin=0 FOR + ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; --let $gtid_strict_mode= `select @@gtid_strict_mode` --let $slave_parallel_threads= `select @@slave_parallel_threads` --let $slave_parallel_mode= `select @@slave_parallel_mode` diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_1.test b/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_1.test index f655d3c10ba..a2f6adcc554 100644 --- a/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_1.test +++ b/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_1.test @@ -10,6 +10,8 @@ set global binlog_alter_two_phase=true; --connection slave --source include/stop_slave.inc +SET STATEMENT sql_log_bin=0 FOR + ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; set global gtid_strict_mode=1; --echo # Legacy Master Slave diff --git a/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.test b/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.test index c7d5bd66e2b..9d9675c6487 100644 --- a/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.test +++ b/mysql-test/suite/rpl/t/rpl_start_alter_mysqlbinlog_2.test @@ -57,6 +57,10 @@ SET @save_binlog_alter_two_phase= @@GLOBAL.binlog_alter_two_phase; SET GLOBAL binlog_alter_two_phase = ON; --connection server_3 +SET STATEMENT sql_log_bin=0 FOR + CALL mtr.add_suppression("The table mysql.gtid_slave_pos was removed. This change will not take full effect until all SQL threads have been restarted"); +SET STATEMENT sql_log_bin=0 FOR + ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; SET @save_gtid_strict_mode= @@GLOBAL.gtid_strict_mode; SET @slave_parallel_threads= @@GLOBAL.slave_parallel_threads; SET @slave_parallel_mode= @@GLOBAL.slave_parallel_mode; From 8dad51481b1e3f02e025bf06b4af7f699d76f58c Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 29 Nov 2023 06:53:31 -0700 Subject: [PATCH 422/477] MDEV-10653: SHOW SLAVE STATUS Can Deadlock an Errored Slave MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AKA rpl.rpl_parallel, binlog_encryption.rpl_parallel fails in buildbot with timeout in include A replication parallel worker thread can deadlock with another connection running SHOW SLAVE STATUS. That is, if the replication worker thread is in do_gco_wait() and is killed, it will already hold the LOCK_parallel_entry, and during error reporting, try to grab the err_lock. SHOW SLAVE STATUS, however, grabs these locks in reverse order. It will initially grab the err_lock, and then try to grab LOCK_parallel_entry. This leads to a deadlock when both threads have grabbed their first lock without the second. This patch implements the MDEV-31894 proposed fix to optimize the workers_idle() check to compare the last in-use relay log’s queued_count==dequeued_count for idleness. This removes the need for workers_idle() to grab LOCK_parallel_entry, as these values are atomically updated. Huge thanks to Kristian Nielsen for diagnosing the problem! Reviewed By: ============ Kristian Nielsen Andrei Elkin --- .../r/rpl_deadlock_show_slave_status.result | 66 ++++++++++ .../rpl/t/rpl_deadlock_show_slave_status.test | 121 ++++++++++++++++++ sql/rpl_parallel.cc | 19 +-- sql/rpl_parallel.h | 3 +- sql/rpl_rli.h | 2 +- sql/slave.cc | 11 +- 6 files changed, 203 insertions(+), 19 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_deadlock_show_slave_status.result create mode 100644 mysql-test/suite/rpl/t/rpl_deadlock_show_slave_status.test diff --git a/mysql-test/suite/rpl/r/rpl_deadlock_show_slave_status.result b/mysql-test/suite/rpl/r/rpl_deadlock_show_slave_status.result new file mode 100644 index 00000000000..12ad5870d4a --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_deadlock_show_slave_status.result @@ -0,0 +1,66 @@ +include/master-slave.inc +[connection master] +# +# Initialize test data +connection master; +create table t1 (a int) engine=innodb; +insert into t1 values (1); +include/save_master_gtid.inc +connection slave; +include/sync_with_master_gtid.inc +include/stop_slave.inc +call mtr.add_suppression("Connection was killed"); +call mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends"); +set @save_parallel_threads= @@global.slave_parallel_threads; +set @save_parallel_mode= @@global.slave_parallel_mode; +set @save_transaction_retries= @@global.slave_transaction_retries; +set @save_innodb_lock_wait_timeout= @@global.innodb_lock_wait_timeout; +set @@global.slave_parallel_threads= 2; +set @@global.slave_parallel_mode= CONSERVATIVE; +set @@global.slave_transaction_retries= 0; +set @@global.innodb_lock_wait_timeout= 10; +# Grabbing lock on innodb row to force future replication transaction to wait (and eventually timeout) +BEGIN; +select * from t1 where a=1 for update; +a +1 +connection master; +set @old_dbug= @@session.debug_dbug; +set @@session.debug_dbug="+d,binlog_force_commit_id"; +SET @commit_id= 10000; +update t1 set a=2 where a=1; +SET @commit_id= 10001; +insert into t1 values (3); +set @@session.debug_dbug= @old_dbug; +connection slave; +start slave; +# Waiting for first transaction to start (and be held at innodb row lock).. +# Waiting for next transaction to start and hold at do_gco_wait().. +connection slave1; +set @@session.debug_dbug="+d,hold_sss_with_err_lock"; +show slave status; +connection slave; +set debug_sync="now wait_for sss_got_err_lock"; +kill ; +set debug_sync="now signal sss_continue"; +connection slave1; +# Waiting for SHOW SLAVE STATUS to complete.. +# ..done +connection slave; +ROLLBACK; +include/wait_for_slave_sql_error.inc [errno=1927] +# +# Cleanup +connection master; +drop table t1; +include/save_master_gtid.inc +connection slave; +set debug_sync= "RESET"; +set @@global.slave_parallel_threads= @save_parallel_threads; +set @@global.slave_parallel_mode= @save_parallel_mode; +set @@global.slave_transaction_retries= @save_transaction_retries; +set @@global.innodb_lock_wait_timeout= @save_innodb_lock_wait_timeout; +start slave sql_thread; +include/sync_with_master_gtid.inc +include/rpl_end.inc +# End of rpl_deadlock_show_slave_status.test diff --git a/mysql-test/suite/rpl/t/rpl_deadlock_show_slave_status.test b/mysql-test/suite/rpl/t/rpl_deadlock_show_slave_status.test new file mode 100644 index 00000000000..ecf3b62ba36 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_deadlock_show_slave_status.test @@ -0,0 +1,121 @@ +# +# Verify that SHOW SLAVE STATUS will not cause deadlocks on the replica. +# A deadlock has been seen in do_gco_wait if the thread is killed, as it will +# hold the LOCK_parallel_entry, and during error reporting, try to grab the +# err_lock. Prior to MDEV-10653, SHOW SLAVE STATUS would grab these locks in +# the reverse order, as calling workers_idle() used to grab LOCK_parallel_entry +# with the err_lock already grabbed (though the MDEV-10653 patch changed the +# workles_idle() implementation to remove the need for locking the +# parallel_entry). +# +# References: +# MDEV-10653: SHOW SLAVE STATUS Can Deadlock an Errored Slave +# + +--source include/master-slave.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_binlog_format_row.inc + +--echo # +--echo # Initialize test data +--connection master +create table t1 (a int) engine=innodb; +insert into t1 values (1); +--source include/save_master_gtid.inc + +--connection slave +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc + +call mtr.add_suppression("Connection was killed"); +call mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends"); + +set @save_parallel_threads= @@global.slave_parallel_threads; +set @save_parallel_mode= @@global.slave_parallel_mode; +set @save_transaction_retries= @@global.slave_transaction_retries; +set @save_innodb_lock_wait_timeout= @@global.innodb_lock_wait_timeout; + +set @@global.slave_parallel_threads= 2; +set @@global.slave_parallel_mode= CONSERVATIVE; +set @@global.slave_transaction_retries= 0; +set @@global.innodb_lock_wait_timeout= 10; + +--echo # Grabbing lock on innodb row to force future replication transaction to wait (and eventually timeout) +BEGIN; +select * from t1 where a=1 for update; + +--connection master + +set @old_dbug= @@session.debug_dbug; +set @@session.debug_dbug="+d,binlog_force_commit_id"; + + +# GCO 1 +SET @commit_id= 10000; +# T1 +update t1 set a=2 where a=1; + +# GCO 2 +SET @commit_id= 10001; +# T2 +insert into t1 values (3); + +set @@session.debug_dbug= @old_dbug; + +--connection slave +start slave; + +--echo # Waiting for first transaction to start (and be held at innodb row lock).. +--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE 'Update_rows_log_event::find_row(%)' and command LIKE 'Slave_worker'; +--source include/wait_condition.inc + +--echo # Waiting for next transaction to start and hold at do_gco_wait().. +--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE 'Waiting for prior transaction to start commit%' and command LIKE 'Slave_worker'; +--source include/wait_condition.inc + +--connection slave1 +set @@session.debug_dbug="+d,hold_sss_with_err_lock"; +--send show slave status + +--connection slave +set debug_sync="now wait_for sss_got_err_lock"; + +--let $t2_tid= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for prior transaction to start commit%'` +--replace_result $t2_tid "" +--eval kill $t2_tid +--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE command LIKE 'Killed'; +--source include/wait_condition.inc + +set debug_sync="now signal sss_continue"; + +--connection slave1 +--echo # Waiting for SHOW SLAVE STATUS to complete.. +--disable_result_log +--reap +--enable_result_log +--echo # ..done + +--connection slave +ROLLBACK; +--let $slave_sql_errno= 1927 +--source include/wait_for_slave_sql_error.inc + + +--echo # +--echo # Cleanup +--connection master +drop table t1; +--source include/save_master_gtid.inc + +--connection slave +set debug_sync= "RESET"; +set @@global.slave_parallel_threads= @save_parallel_threads; +set @@global.slave_parallel_mode= @save_parallel_mode; +set @@global.slave_transaction_retries= @save_transaction_retries; +set @@global.innodb_lock_wait_timeout= @save_innodb_lock_wait_timeout; +start slave sql_thread; +--source include/sync_with_master_gtid.inc + +--source include/rpl_end.inc +--echo # End of rpl_deadlock_show_slave_status.test diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index fc4434b75de..397b45c4eef 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -2537,23 +2537,10 @@ rpl_parallel::stop_during_until() bool -rpl_parallel::workers_idle() +rpl_parallel::workers_idle(Relay_log_info *rli) { - struct rpl_parallel_entry *e; - uint32 i, max_i; - - max_i= domain_hash.records; - for (i= 0; i < max_i; ++i) - { - bool active; - e= (struct rpl_parallel_entry *)my_hash_element(&domain_hash, i); - mysql_mutex_lock(&e->LOCK_parallel_entry); - active= e->current_sub_id > e->last_committed_sub_id; - mysql_mutex_unlock(&e->LOCK_parallel_entry); - if (active) - break; - } - return (i == max_i); + return rli->last_inuse_relaylog->queued_count == + rli->last_inuse_relaylog->dequeued_count; } diff --git a/sql/rpl_parallel.h b/sql/rpl_parallel.h index 6b03306692b..07ff7f70293 100644 --- a/sql/rpl_parallel.h +++ b/sql/rpl_parallel.h @@ -369,9 +369,10 @@ struct rpl_parallel { rpl_parallel_entry *find(uint32 domain_id); void wait_for_done(THD *thd, Relay_log_info *rli); void stop_during_until(); - bool workers_idle(); int wait_for_workers_idle(THD *thd); int do_event(rpl_group_info *serial_rgi, Log_event *ev, ulonglong event_size); + + static bool workers_idle(Relay_log_info *rli); }; diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index 1391c5cde82..9fc1a384355 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -622,7 +622,7 @@ struct inuse_relaylog { rpl_gtid *relay_log_state; uint32 relay_log_state_count; /* Number of events in this relay log queued for worker threads. */ - int64 queued_count; + Atomic_counter queued_count; /* Number of events completed by worker threads. */ Atomic_counter dequeued_count; /* Set when all events have been read from a relaylog. */ diff --git a/sql/slave.cc b/sql/slave.cc index 84b245fa1be..2cc11b9ed42 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3123,6 +3123,14 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full, mysql_mutex_lock(&mi->err_lock); /* err_lock is to protect mi->rli.last_error() */ mysql_mutex_lock(&mi->rli.err_lock); + + DBUG_EXECUTE_IF("hold_sss_with_err_lock", { + DBUG_ASSERT(!debug_sync_set_action( + thd, STRING_WITH_LEN("now SIGNAL sss_got_err_lock " + "WAIT_FOR sss_continue"))); + DBUG_SET("-d,hold_sss_with_err_lock"); + }); + protocol->store(mi->host, &my_charset_bin); protocol->store(mi->user, &my_charset_bin); protocol->store((uint32) mi->port); @@ -3197,7 +3205,8 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full, while the slave is processing ignored events, such as those skipped due to slave_skip_counter. */ - if (mi->using_parallel() && idle && !mi->rli.parallel.workers_idle()) + if (mi->using_parallel() && idle && + !rpl_parallel::workers_idle(&mi->rli)) idle= false; } if (idle) From b94ae3870bb9f94913eeb7e99b243ef16fe1ad4b Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 12 Dec 2023 11:27:20 +1100 Subject: [PATCH 423/477] [fixup] galera: Fix an accidental logical inversion in a recent merge The merge was 13dd787530863954fcd17fbaf83d46e7170667f6 --- sql/sql_alter.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index c7bbe783fe5..dc98f9c8d93 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -554,7 +554,7 @@ bool Sql_cmd_alter_table::execute(THD *thd) } wsrep::key_array keys; - if (wsrep_append_fk_parent_table(thd, first_table, &keys)) + if (!wsrep_append_fk_parent_table(thd, first_table, &keys)) { WSREP_TO_ISOLATION_BEGIN_ALTER(lex->name.str ? select_lex->db.str : first_table->db.str, From 7fae2fa4606db01ef0c328437c4f24222b4d9373 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sun, 8 Oct 2023 00:41:48 +0300 Subject: [PATCH 424/477] MDEV-30482 libmariadb3 - debian/libmariadb3.symbols not updated Add missing symbols and their introduced C/C version. --- debian/libmariadb3.symbols | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/libmariadb3.symbols b/debian/libmariadb3.symbols index c79676472c6..f7dab874378 100644 --- a/debian/libmariadb3.symbols +++ b/debian/libmariadb3.symbols @@ -1,6 +1,7 @@ libmariadb.so.3 libmariadb3 #MINVER# * Build-Depends-Package: libmariadb-dev libmariadb_3@libmariadb_3 3.0.0 + libmariadb_3_3_5@libmariadb_3_3_5 3.3.5 libmariadbclient_18@libmariadbclient_18 3.0.0 libmysqlclient_18@libmysqlclient_18 3.0.0 ma_pvio_register_callback@libmariadb_3 3.0.0 @@ -8,6 +9,7 @@ libmariadb.so.3 libmariadb3 #MINVER# mariadb_connection@libmariadb_3 3.0.0 mariadb_convert_string@libmariadb_3 3.0.0 mariadb_deinitialize_ssl@libmariadb_3 3.0.0 + mariadb_field_attr@libmariadb_3 3.3.1 mariadb_free_rpl_event@libmariadb_3 3.1.0 mariadb_get_charset_by_name@libmariadb_3 3.0.0 mariadb_get_charset_by_nr@libmariadb_3 3.0.0 @@ -15,8 +17,12 @@ libmariadb.so.3 libmariadb3 #MINVER# mariadb_get_infov@libmariadb_3 3.0.0 mariadb_reconnect@libmariadb_3 3.0.0 mariadb_rpl_close@libmariadb_3 3.1.0 + mariadb_rpl_errno@libmariadb_3_3_5 3.3.2 + mariadb_rpl_error@libmariadb_3_3_5 3.3.2 + mariadb_rpl_extract_rows@libmariadb_3_3_5 3.3.2 mariadb_rpl_fetch@libmariadb_3 3.1.0 mariadb_rpl_get_optionsv@libmariadb_3 3.1.0 + mariadb_rpl_init_ex@libmariadb_3 3.3.0 mariadb_rpl_open@libmariadb_3 3.1.0 mariadb_rpl_optionsv@libmariadb_3 3.1.0 mariadb_stmt_execute_direct@libmariadb_3 3.0.0 From bd010292557a571089c91e75b77fe773ab4ee2d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 11 Dec 2023 15:26:22 +0200 Subject: [PATCH 425/477] MDEV-29972 Crash emitting "Unsupported meta-data version number" error message row_import_read_meta_data(): Use ER_NOT_SUPPORTED_YET instead of ER_IO_READ_ERROR to have a matching error message pattern. --- mysql-test/std_data/mysql80/t2.cfg | Bin 0 -> 637 bytes mysql-test/std_data/mysql80/t2.ibd | Bin 0 -> 114688 bytes .../suite/innodb/r/innodb-wl5522-1.result | 14 +++++++++++- .../suite/innodb/t/innodb-wl5522-1.test | 21 +++++++++++++++++- storage/innobase/row/row0import.cc | 13 +++-------- 5 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 mysql-test/std_data/mysql80/t2.cfg create mode 100644 mysql-test/std_data/mysql80/t2.ibd diff --git a/mysql-test/std_data/mysql80/t2.cfg b/mysql-test/std_data/mysql80/t2.cfg new file mode 100644 index 0000000000000000000000000000000000000000..81f92978393cb4d9af715bc26b68af49349169dd GIT binary patch literal 637 zcmb7>-Acni5QR6X(I8dv5qts-NWr_Rxd}vD(ujJs1d~8PYccDEFXOA$`Su4Qc;kWD zojr5rFHuSzD5Z{OS=0B~tm&^VF6FIK(+%d_WcVI)?lZAH96>ZPODHubo=oJ}7Yjmy zh(WwoyPb0#m&yY%2qOH${6<%cM_uHS0Ei`nK?d~G{NxhWtg>o!oV z4Kj?Q^=t__f<}I+$3GYP0oII3?f?J) literal 0 HcmV?d00001 diff --git a/mysql-test/std_data/mysql80/t2.ibd b/mysql-test/std_data/mysql80/t2.ibd new file mode 100644 index 0000000000000000000000000000000000000000..be2b46a7af1d52f803c88f381759f35557d88f48 GIT binary patch literal 114688 zcmeI*e^kwB0>|<1y-A88l8k21hz%u0#uX-7(aDcOGPP+Z{n(psjq)Qk5gMh`FeUzt8i1?sK2# z)#<-JPouoG>jbID#-~el%Wdt38A3PduC2($tMrnJj`*?@zfHuew)he>Vrj3%X3GqM zT6)r2zwlh@|4;9e3&X^xt+h1n#ku7<&C+cDE-izo5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0;rH!L9i>7v$ec>io20R#|0009ILKmY** z5I_I{1Q0*~0R#|0;Pn?6CFcHRV$MI&+qMOVW$Ts3 zc7ERG-=%%7S8;7yf0wrFbL)F?y)U+ZMgHx}=ZXLV2q1s}0tg_000IagfB*srAbKfKppoT?*{FHI|}-Em>su}&W#7v$PbQ7wsWS-Kz-zdF+Mt@-lSjCo71 zT(~d3Q+h5Jti^${iOL{9rE0lKJW-&#AcQXeFvM4EHAM-6zUE%rQ1K$@v{b#;iJz}6 zD;DcSv7;$0Rh3jW`^0GdX&T>3SL3|c>F)&V8;{#}*~Dkob)}7~w@!q6@64yRi5~AH zExZ;py)HaDD0a|(8-Kmc$HoL^9JP!~b6@LO9jID4GIqNrtihz}qsUzjn|e%|qWi_d zyuJ~E-B#~*POSNBO82QQ<1*)7Z8|U{*?PwD$6Fdtncg*3PyRU7W^>UDBg6b*Jrq@z zt_=>>ku_uV-i%*Yf415K0F-Pw@*W_1Lv}GHXRCcbefQn*6Z!V4?IJ3 zR*bok8`@mIbZL*cE(hjJHL9HS`9|l$gqrofG5hNyeM&T$qwX!g6&{*aaPw-jlUn&f zc>12;aRo7s@#_Vle{+pU(00&*Ox4+^S`d1k5`S#*VX3#>oPrIk^qVas5{n!6D7QK& zqQbL_v*N-96CXvv)`aY;MS;P8+WX{(H~*dzdCAaOU!JWvIp)#CqG0R%_|o;w$3wr= z*}bE0^p6*Qo|yP~iD{`vw!!Z29Cw9|OB&jJ<*cB|_I|O7`TA+otCpQGX&9dQpkPLM zMZ?T>dUe*dR`cxMs8J+*H`ej`s*n0v`t7ZmZ#*?$W?0dGNWnTJ2 zi~97;99`ggw9Dpf`yaFZaLn`CH){iroC%8c`$2eUR&MHl)gk>xe&*hJNshjAt~zJw z?oas2x-@se9_9N>2OC=0W$8aCGyTHJxcG15f;V`3skb^7kL_(!cVK3nN2$&DEAKjo zl#Rbr7Lf72Nnl0V8SQUJ8=Fn}tkCcLwrr*UPOtu-j+vs!-sN}d(D}-U>8|qzPt3Br zIMi(WX1!3K!ZOF|jW)v)O+FbqDy34HXfbwQbm8Xlra|f}UFYtLHB|&E&sq)13RrS_ zP>K3}c&+`&gd<9y=EFv-+@8fOe45;t>ppF9%AqUgbQ}ie+*@^LM@(|^rB7!m2bcQP zdwBQK?&f@Pgl@HWg?rxPbvf#So+oDxzG*dJONo2`UY4pQryo@+9PBLqV!mzkFRp#k z&)qf*9ByE@*D6jGpmlAZ!|3?b94+0SCI#vCktr$%S_FP_@PqM{6IPzi6*RR6mZryB zteKFaF!NrN>U$<>!S`eDtghH{{kmcPqN3j=8(ApKFE>xHtKe5UGdQo1J*VB=A(-UjfJnEtG zZ_>z`Zgfw(y>r)*X)0CC&aRNXJ7vtF6HuN;|JM<+E*E9OrEGW z>=@|Tczn0w++_o|3C^RcT{4VEls5E>@LBWwb;eFhhI^)(&puyq(%h$_t}5@dXp7nD zK~{%mu2kJu{dBomu93SBz2EI_RawuJ8)gTKPi;2&%4ORjgFV{+Sp3V)XU|p!3@}TO zem^M)Ablzy_V4N-`hJzsl~gN)W1BW{Z96!bWp&6_WZwg=ls8z{ula1wWZs2 zjMj>G-DUb>=Dnp?SDLoH_iaHK+|oOubFbJi(;SSFnY(rFeOGEw5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILcr66P{J)g@mva8E#d=vJ0tg_000IagfB*srAb Date: Thu, 16 Nov 2023 14:56:56 +0100 Subject: [PATCH 426/477] MDEV-28971 SEQUENCEs do not work with streaming replication Return an error if user attempts to use SEQUENCEs in combination with streaming replication in a Galera cluster. This is currently not supported. Signed-off-by: Julius Goryavsky --- .../suite/galera_sr/r/MDEV-28971.result | 17 ++++++++++++ mysql-test/suite/galera_sr/t/MDEV-28971.test | 20 ++++++++++++++ sql/ha_sequence.cc | 27 ++++++++++++++----- 3 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 mysql-test/suite/galera_sr/r/MDEV-28971.result create mode 100644 mysql-test/suite/galera_sr/t/MDEV-28971.test diff --git a/mysql-test/suite/galera_sr/r/MDEV-28971.result b/mysql-test/suite/galera_sr/r/MDEV-28971.result new file mode 100644 index 00000000000..0826f5e6b66 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/MDEV-28971.result @@ -0,0 +1,17 @@ +connection node_2; +connection node_1; +CREATE SEQUENCE SEQ NOCACHE ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size=1; +SET collation_connection=utf16_thai_520_w2; +SET autocommit=0; +CREATE TABLE t1 (a BLOB UNIQUE); +INSERT INTO t1 VALUES ('AAF'); +SELECT SETVAL (SEQ, 100); +ERROR 42000: This version of MariaDB doesn't yet support 'SEQUENCEs with streaming replication in Galera cluster' +ALTER TABLE t1 ADD CONSTRAINT constraint_1 UNIQUE (a); +Warnings: +Note 1831 Duplicate index `constraint_1`. This is deprecated and will be disallowed in a future release +INSERT INTO t1 VALUES(); +ALTER TABLE t1 ADD KEY(b (50)); +ERROR 42000: Key column 'b' doesn't exist in table +DROP TABLE t1,SEQ; diff --git a/mysql-test/suite/galera_sr/t/MDEV-28971.test b/mysql-test/suite/galera_sr/t/MDEV-28971.test new file mode 100644 index 00000000000..81238f94b4a --- /dev/null +++ b/mysql-test/suite/galera_sr/t/MDEV-28971.test @@ -0,0 +1,20 @@ +# +# MDEV-28971 - Assertion `total_length + thd->wsrep_sr().log_position() == saved_pos' +# failed in int wsrep_write_cache_inc(THD*, IO_CACHE*, size_t*) +# + +--source include/galera_cluster.inc + +CREATE SEQUENCE SEQ NOCACHE ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size=1; +SET collation_connection=utf16_thai_520_w2; +SET autocommit=0; +CREATE TABLE t1 (a BLOB UNIQUE); +INSERT INTO t1 VALUES ('AAF'); +--error ER_NOT_SUPPORTED_YET +SELECT SETVAL (SEQ, 100); +ALTER TABLE t1 ADD CONSTRAINT constraint_1 UNIQUE (a); +INSERT INTO t1 VALUES(); +--error ER_KEY_COLUMN_DOES_NOT_EXITS +ALTER TABLE t1 ADD KEY(b (50)); +DROP TABLE t1,SEQ; diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc index 03aee6a43dc..5afc37134d2 100644 --- a/sql/ha_sequence.cc +++ b/sql/ha_sequence.cc @@ -261,13 +261,26 @@ int ha_sequence::write_row(const uchar *buf) } #ifdef WITH_WSREP - /* We need to start Galera transaction for select NEXT VALUE FOR - sequence if it is not yet started. Note that ALTER is handled - as TOI. */ - if (WSREP_ON && WSREP(thd) && - !thd->wsrep_trx().active() && - wsrep_thd_is_local(thd)) - wsrep_start_transaction(thd, thd->wsrep_next_trx_id()); + if (WSREP_ON && WSREP(thd) && wsrep_thd_is_local(thd)) + { + if (sequence_locked && + (wsrep_thd_is_SR(thd) || wsrep_streaming_enabled(thd))) + { + my_error(ER_NOT_SUPPORTED_YET, MYF(0), + "SEQUENCEs with streaming replication in Galera cluster"); + DBUG_RETURN(HA_ERR_UNSUPPORTED); + } + + /* + We need to start Galera transaction for select NEXT VALUE FOR + sequence if it is not yet started. Note that ALTER is handled + as TOI. + */ + if (!thd->wsrep_trx().active()) + { + wsrep_start_transaction(thd, thd->wsrep_next_trx_id()); + } + } #endif if (likely(!(error= file->update_first_row(buf)))) From 61daac54d62491fac9b699bccd639494da38a72f Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Tue, 12 Dec 2023 02:53:36 +0100 Subject: [PATCH 427/477] MDEV-27806 GTIDs diverge in Galera cluster after CTAS Add OPTION_GTID_BEGIN to applying side thread. This is needed to avoid intermediate commits when CREATE TABLE AS SELECT is applied, causing one more GTID to be consumed with respect to executing node. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/MDEV-27806.result | 52 +++++++++++++++++++ .../suite/galera/r/galera_as_master.result | 2 + mysql-test/suite/galera/t/MDEV-27806.opt | 1 + mysql-test/suite/galera/t/MDEV-27806.test | 51 ++++++++++++++++++ .../suite/galera/t/galera_as_master.test | 6 +++ sql/wsrep_applier.cc | 5 ++ sql/wsrep_high_priority_service.cc | 3 ++ 7 files changed, 120 insertions(+) create mode 100644 mysql-test/suite/galera/r/MDEV-27806.result create mode 100644 mysql-test/suite/galera/t/MDEV-27806.opt create mode 100644 mysql-test/suite/galera/t/MDEV-27806.test diff --git a/mysql-test/suite/galera/r/MDEV-27806.result b/mysql-test/suite/galera/r/MDEV-27806.result new file mode 100644 index 00000000000..0f7ac79e4cd --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-27806.result @@ -0,0 +1,52 @@ +connection node_2; +connection node_1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +INSERT INTO t1 VALUES (1),(2),(3); +CREATE TABLE ts1 AS SELECT * FROM t1; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000002 # Gtid # # BEGIN GTID #-#-# +mysqld-bin.000002 # Query # # use `test`; CREATE TABLE `ts1` ( + `f1` int(11) NOT NULL +) +mysqld-bin.000002 # Annotate_rows # # CREATE TABLE ts1 AS SELECT * FROM t1 +mysqld-bin.000002 # Table_map # # table_id: # (test.ts1) +mysqld-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F +mysqld-bin.000002 # Xid # # COMMIT /* XID */ +connection node_2; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000003 # Gtid # # BEGIN GTID #-#-# +mysqld-bin.000003 # Query # # use `test`; CREATE TABLE `ts1` ( + `f1` int(11) NOT NULL +) +mysqld-bin.000003 # Annotate_rows # # CREATE TABLE ts1 AS SELECT * FROM t1 +mysqld-bin.000003 # Table_map # # table_id: # (test.ts1) +mysqld-bin.000003 # Write_rows_v1 # # table_id: # flags: STMT_END_F +mysqld-bin.000003 # Xid # # COMMIT /* XID */ +BINLOG_POSITIONS_MATCH +1 +DROP TABLE t1,ts1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +CREATE TABLE ts1 AS SELECT * FROM t1; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000002 # Gtid # # BEGIN GTID #-#-# +mysqld-bin.000002 # Query # # use `test`; CREATE TABLE `ts1` ( + `f1` int(11) NOT NULL +) +mysqld-bin.000002 # Xid # # COMMIT /* XID */ +connection node_2; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000003 # Gtid # # BEGIN GTID #-#-# +mysqld-bin.000003 # Query # # use `test`; CREATE TABLE `ts1` ( + `f1` int(11) NOT NULL +) +mysqld-bin.000003 # Query # # COMMIT +BINLOG_POSITIONS_MATCH +1 +DROP TABLE t1,ts1; +CALL mtr.add_suppression("Ignoring server id for non bootstrap node"); diff --git a/mysql-test/suite/galera/r/galera_as_master.result b/mysql-test/suite/galera/r/galera_as_master.result index 4aca328be56..dd3e017379c 100644 --- a/mysql-test/suite/galera/r/galera_as_master.result +++ b/mysql-test/suite/galera/r/galera_as_master.result @@ -52,6 +52,8 @@ DROP TABLE t1, t4; SET SQL_LOG_BIN=OFF; DROP TABLE t2, t3; connection node_3; +BINLOG_POSITIONS_MATCH +1 STOP SLAVE; RESET SLAVE ALL; CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work'); diff --git a/mysql-test/suite/galera/t/MDEV-27806.opt b/mysql-test/suite/galera/t/MDEV-27806.opt new file mode 100644 index 00000000000..009e761eb2c --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-27806.opt @@ -0,0 +1 @@ +--log-bin --log-slave-updates --gtid-strict-mode --wsrep_gtid_mode=on diff --git a/mysql-test/suite/galera/t/MDEV-27806.test b/mysql-test/suite/galera/t/MDEV-27806.test new file mode 100644 index 00000000000..62a0ca483e0 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-27806.test @@ -0,0 +1,51 @@ +# +# MDEV-27806 GTIDs diverge after CTAS +# +--source include/galera_cluster.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +INSERT INTO t1 VALUES (1),(2),(3); +CREATE TABLE ts1 AS SELECT * FROM t1; +--let binlog_pos= `SELECT @@gtid_binlog_pos` + +--let $MASTER_MYPORT=$NODE_MYPORT_1 +--let $binlog_file=LAST +--let $binlog_limit=8,20 +--source include/show_binlog_events.inc + +--connection node_2 +--let $binlog_limit=7,20 +--source include/show_binlog_events.inc + +--disable_query_log +--eval SELECT STRCMP(@@gtid_binlog_pos, "$binlog_pos") = 0 AS BINLOG_POSITIONS_MATCH; +--enable_query_log + +DROP TABLE t1,ts1; + + +# +# Same as above, with empty CREATE TABLE AS SELECT +# +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +CREATE TABLE ts1 AS SELECT * FROM t1; +--let binlog_pos= `SELECT @@gtid_binlog_pos` + +--let $MASTER_MYPORT=$NODE_MYPORT_1 +--let $binlog_file=LAST +--let $binlog_limit=18,20 +--source include/show_binlog_events.inc + +--connection node_2 +--let $binlog_limit=17,20 +--source include/show_binlog_events.inc + +--disable_query_log +--eval SELECT STRCMP(@@gtid_binlog_pos, "$binlog_pos") = 0 AS BINLOG_POSITIONS_MATCH; +--enable_query_log + +DROP TABLE t1,ts1; + +CALL mtr.add_suppression("Ignoring server id for non bootstrap node"); diff --git a/mysql-test/suite/galera/t/galera_as_master.test b/mysql-test/suite/galera/t/galera_as_master.test index 1c439ffff63..a5554a735fe 100644 --- a/mysql-test/suite/galera/t/galera_as_master.test +++ b/mysql-test/suite/galera/t/galera_as_master.test @@ -52,12 +52,18 @@ DROP TABLE t1, t4; SET SQL_LOG_BIN=OFF; DROP TABLE t2, t3; +--let binlog_pos=`SELECT @@gtid_binlog_pos;` + --connection node_3 --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't4'; --source include/wait_condition.inc +--disable_query_log +--eval SELECT STRCMP(@@gtid_binlog_pos, "$binlog_pos") = 0 AS BINLOG_POSITIONS_MATCH; +--enable_query_log + STOP SLAVE; RESET SLAVE ALL; diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index fd51dbf9439..ff6a0a7f60e 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -196,6 +196,11 @@ int wsrep_apply_events(THD* thd, (thd->variables.option_bits & ~OPTION_SKIP_REPLICATION) | (ev->flags & LOG_EVENT_SKIP_REPLICATION_F ? OPTION_SKIP_REPLICATION : 0); + if (ev->get_type_code() == GTID_EVENT) + { + thd->variables.option_bits &= ~OPTION_GTID_BEGIN; + } + ev->thd= thd; exec_res= ev->apply_event(thd->wsrep_rgi); DBUG_PRINT("info", ("exec_event result: %d", exec_res)); diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc index d1e58ed5bad..1988088d0a8 100644 --- a/sql/wsrep_high_priority_service.cc +++ b/sql/wsrep_high_priority_service.cc @@ -534,6 +534,7 @@ int Wsrep_applier_service::apply_write_set(const wsrep::ws_meta& ws_meta, THD* thd= m_thd; thd->variables.option_bits |= OPTION_BEGIN; + thd->variables.option_bits |= OPTION_GTID_BEGIN; thd->variables.option_bits |= OPTION_NOT_AUTOCOMMIT; DBUG_ASSERT(thd->wsrep_trx().active()); DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_executing); @@ -570,6 +571,8 @@ int Wsrep_applier_service::apply_write_set(const wsrep::ws_meta& ws_meta, thd->wsrep_cs().fragment_applied(ws_meta.seqno()); } thd_proc_info(thd, "wsrep applied write set"); + + thd->variables.option_bits &= ~OPTION_GTID_BEGIN; DBUG_RETURN(ret); } From 9f5078a1d79031c4a781d378af18df9c8c9d2321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 12 Dec 2023 11:43:23 +0200 Subject: [PATCH 428/477] MDEV-20139 innodb.innodb_buffer_pool_dump_pct failed in buildbot with timeout This test was using a sleep of 1 second in an attempt to ensure that the timestamp that is part of an InnoDB status string would increase. This not only prolongs the test execution time by 1+1 seconds, but it also is inaccurate. It is possible that the actual sleep duration is less than a second. Let us wait for the creation of the file ib_buffer_pool and then wait for the buffer pool dump completion. In that way, the test can complete in a dozen or two milliseconds (1% of the previous duration) and work more reliably. --- .../r/innodb_buffer_pool_dump_pct.result | 9 ---- .../innodb/t/innodb_buffer_pool_dump_pct.test | 47 +++++++++---------- 2 files changed, 21 insertions(+), 35 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb_buffer_pool_dump_pct.result b/mysql-test/suite/innodb/r/innodb_buffer_pool_dump_pct.result index fa17487df97..33adf9baebb 100644 --- a/mysql-test/suite/innodb/r/innodb_buffer_pool_dump_pct.result +++ b/mysql-test/suite/innodb/r/innodb_buffer_pool_dump_pct.result @@ -3,17 +3,8 @@ col2 VARCHAR(25), col3 varchar(25)) ENGINE=InnoDB; CREATE INDEX idx1 ON tab5(col2(10)); CREATE INDEX idx2 ON tab5(col3(10)); SET GLOBAL innodb_buffer_pool_dump_pct=100; -SELECT variable_value INTO @IBPDS -FROM information_schema.global_status -WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS'; SET GLOBAL innodb_buffer_pool_dump_now=ON; SET GLOBAL innodb_buffer_pool_dump_pct=1; -SELECT @@global.innodb_buffer_pool_dump_pct; -@@global.innodb_buffer_pool_dump_pct -1 -SELECT variable_value INTO @IBPDS -FROM information_schema.global_status -WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS'; SET GLOBAL innodb_buffer_pool_dump_now=ON; SET GLOBAL innodb_buffer_pool_dump_pct=DEFAULT; DROP TABLE tab5; diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_dump_pct.test b/mysql-test/suite/innodb/t/innodb_buffer_pool_dump_pct.test index 381091165ef..b393ca70778 100644 --- a/mysql-test/suite/innodb/t/innodb_buffer_pool_dump_pct.test +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_dump_pct.test @@ -35,49 +35,44 @@ SET GLOBAL innodb_buffer_pool_dump_pct=100; # - The granularity of the timestamp is one second. # - There could have been some dump caused by some previous test # just a few milliseconds before. -# In order to avoid conflict with previous tests, read the current value -# of INNODB_BUFFER_POOL_DUMP_STATUS -# and confirm that the timestamp is different after the dump #*********************************************************** -# Read the current value to compare with the new value. -SELECT variable_value INTO @IBPDS -FROM information_schema.global_status -WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS'; +--error 0,1 +--remove_file $MYSQLD_DATADIR/ib_buffer_pool + SET GLOBAL innodb_buffer_pool_dump_now=ON; - -# Sleep one second in order to ensure that the time stamp is -# different at next dump ---sleep 1 - +perl; +my $f="$ENV{MYSQLD_DATADIR}/ib_buffer_pool"; +my $count=300; +until (-e $f) +{ + select(undef, undef, undef, .1); + die "File $f was not created\n" if (0 > --$count); +} +EOF let $wait_condition = SELECT count(*) = 1 FROM information_schema.global_status WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS' -AND variable_value != @IBPDS AND variable_value like 'Buffer pool(s) dump completed at%'; --source include/wait_condition.inc --move_file $MYSQLD_DATADIR/ib_buffer_pool $MYSQLD_DATADIR/ib_buffer_pool100 SET GLOBAL innodb_buffer_pool_dump_pct=1; -SELECT @@global.innodb_buffer_pool_dump_pct; - -# Read the current value to compare with the new value. ---disable_warnings -SELECT variable_value INTO @IBPDS -FROM information_schema.global_status -WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS'; ---enable_warnings - SET GLOBAL innodb_buffer_pool_dump_now=ON; -# Sleep one second in order to ensure that the time stamp is -# different at next dump ---sleep 1 +perl; +my $f="$ENV{MYSQLD_DATADIR}/ib_buffer_pool"; +my $count=300; +until (-e $f) +{ + select(undef, undef, undef, .1); + die "File $f was not created\n" if (0 > --$count); +} +EOF let $wait_condition = SELECT count(*) = 1 FROM information_schema.global_status WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS' -AND variable_value != @IBPDS AND variable_value like 'Buffer pool(s) dump completed at%'; --source include/wait_condition.inc From 68e7909be945895dd0bee1b9d069d8a50488fab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 12 Dec 2023 14:40:45 +0200 Subject: [PATCH 429/477] MDEV-31000 Assertion failed on ALTER TABLE...page_compressed=1 ha_innobase::check_if_supported_inplace_alter(): On ALTER_OPTIONS, if innodb_file_per_table=1 and the table resides in the system tablespace, require that the table be rebuilt (and moved to an .ibd file). Reviewed by: Thirunarayanan Balathandayuthapani Tested by: Matthias Leich --- mysql-test/suite/innodb/r/alter_table.result | 13 ++++++++++++- mysql-test/suite/innodb/t/alter_table.test | 12 +++++++++++- storage/innobase/handler/handler0alter.cc | 8 ++++++-- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/innodb/r/alter_table.result b/mysql-test/suite/innodb/r/alter_table.result index fc0d447e48d..015507f2303 100644 --- a/mysql-test/suite/innodb/r/alter_table.result +++ b/mysql-test/suite/innodb/r/alter_table.result @@ -117,5 +117,16 @@ ERROR 42000: Incorrect column specifier for column 'c' CREATE TABLE t1 (c DATETIME AUTO_INCREMENT UNIQUE) ENGINE=InnoDB; ERROR 42000: Incorrect column specifier for column 'c' # -# End of 10.4 tests +# MDEV-31000 Assertion failed on ALTER TABLE...page_compressed=1 # +SET @save_file_per_table=@@GLOBAL.innodb_file_per_table; +SET GLOBAL innodb_file_per_table=0; +CREATE TABLE t (c INT PRIMARY KEY) ENGINE=INNODB; +SET GLOBAL innodb_file_per_table=1; +ALTER TABLE t page_compressed=1; +SET GLOBAL innodb_file_per_table=@save_file_per_table; +SELECT space>0 FROM information_schema.innodb_sys_tables WHERE name='test/t'; +space>0 +1 +DROP TABLE t; +# End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/alter_table.test b/mysql-test/suite/innodb/t/alter_table.test index ae247e7cada..3ab5199025b 100644 --- a/mysql-test/suite/innodb/t/alter_table.test +++ b/mysql-test/suite/innodb/t/alter_table.test @@ -121,6 +121,16 @@ CREATE TABLE t1 (c TIMESTAMP AUTO_INCREMENT UNIQUE) ENGINE=InnoDB; CREATE TABLE t1 (c DATETIME AUTO_INCREMENT UNIQUE) ENGINE=InnoDB; --echo # ---echo # End of 10.4 tests +--echo # MDEV-31000 Assertion failed on ALTER TABLE...page_compressed=1 --echo # +SET @save_file_per_table=@@GLOBAL.innodb_file_per_table; +SET GLOBAL innodb_file_per_table=0; +CREATE TABLE t (c INT PRIMARY KEY) ENGINE=INNODB; +SET GLOBAL innodb_file_per_table=1; +ALTER TABLE t page_compressed=1; +SET GLOBAL innodb_file_per_table=@save_file_per_table; +SELECT space>0 FROM information_schema.innodb_sys_tables WHERE name='test/t'; +DROP TABLE t; + +--echo # End of 10.4 tests diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index b61949620f7..74c2703218d 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -2155,12 +2155,16 @@ innodb_instant_alter_column_allowed_reason: } } + bool need_rebuild = false; + switch (ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE) { case ALTER_OPTIONS: - if (alter_options_need_rebuild(ha_alter_info, table)) { + if ((srv_file_per_table && !m_prebuilt->table->space_id) + || alter_options_need_rebuild(ha_alter_info, table)) { reason_rebuild = my_get_err_msg( ER_ALTER_OPERATION_TABLE_OPTIONS_NEED_REBUILD); ha_alter_info->unsupported_reason = reason_rebuild; + need_rebuild= true; break; } /* fall through */ @@ -2272,7 +2276,7 @@ innodb_instant_alter_column_allowed_reason: /* We should be able to do the operation in-place. See if we can do it online (LOCK=NONE) or without rebuild. */ - bool online = true, need_rebuild = false; + bool online = true; const uint fulltext_indexes = innobase_fulltext_exist(altered_table); /* Fix the key parts. */ From bb565ee566c908f35caf336f84b613bf8362a8a6 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 10 Dec 2023 10:53:27 +0100 Subject: [PATCH 430/477] MDEV-32884 backward compatibility fixes * restore old ENUM values order, in case someone used SET @@s3_protocol_version=1 * restore old behavior for Original and Amazon protocol values, they behave as "Auto" and do not force a specific protocol version Approved by Andrew Hutchings --- storage/maria/aria_s3_copy.cc | 6 ++---- storage/maria/s3_func.c | 8 +++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/storage/maria/aria_s3_copy.cc b/storage/maria/aria_s3_copy.cc index 3636e2bec78..b8a0f5b7921 100644 --- a/storage/maria/aria_s3_copy.cc +++ b/storage/maria/aria_s3_copy.cc @@ -220,17 +220,15 @@ int main(int argc, char** argv) ms3_set_option(global_s3_client, MS3_OPT_BUFFER_CHUNK_SIZE, &block_size); - if (opt_protocol_version) + if (opt_protocol_version > 2) { uint8_t protocol_version; switch (opt_protocol_version) { - case 1: /* Legacy means v1 */ + case 3: /* Legacy means v1 */ case 4: /* Path means v1 */ protocol_version= 1; break; - case 2: /* Original means v2 */ - case 3: /* Amazon means v2 */ case 5: /* Domain means v2 */ protocol_version= 2; break; diff --git a/storage/maria/s3_func.c b/storage/maria/s3_func.c index 4ee3c9e86de..d85dc8a0b40 100644 --- a/storage/maria/s3_func.c +++ b/storage/maria/s3_func.c @@ -39,7 +39,7 @@ static int s3_read_file_from_disk(const char *filename, uchar **to, /* Used by ha_s3.cc and tools to define different protocol options */ -static const char *protocol_types[]= {"Auto", "Legacy", "Original", "Amazon", "Path", "Domain", NullS}; +static const char *protocol_types[]= {"Auto", "Original", "Amazon", "Legacy", "Path", "Domain", NullS}; TYPELIB s3_protocol_typelib= {array_elements(protocol_types)-1,"", protocol_types, NULL}; @@ -154,17 +154,15 @@ ms3_st *s3_open_connection(S3_INFO *s3) errno, ms3_error(errno)); my_errno= HA_ERR_NO_SUCH_TABLE; } - if (s3->protocol_version) + if (s3->protocol_version > 2) { uint8_t protocol_version; switch (s3->protocol_version) { - case 1: /* Legacy means v1 */ + case 3: /* Legacy means v1 */ case 4: /* Path means v1 */ protocol_version= 1; break; - case 2: /* Original means v2 */ - case 3: /* Amazon means v2 */ case 5: /* Domain means v2 */ protocol_version= 2; break; From c2a5d93580b04b6d4a55da59f07eaac2c1365445 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 21 Nov 2023 12:01:31 +0100 Subject: [PATCH 431/477] main.long_host failures test uses +d,getnameinfo_fake_long_host to return a fake long hostname in ip_to_hostname(). But this dbug keyword is only checked after the lookup in the hostname cache. the test has to flush the hostname cache in case previous tests had it populated with fake ip addresses (perfschema tests do that) also, remove redundant `connection` directives --- mysql-test/main/long_host.result | 8 +------- mysql-test/main/long_host.test | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/mysql-test/main/long_host.result b/mysql-test/main/long_host.result index 57b637de587..2a92220f2fa 100644 --- a/mysql-test/main/long_host.result +++ b/mysql-test/main/long_host.result @@ -19,9 +19,9 @@ create table mariadbtestdb2.t2 (a int); create table mariadbtestdb.t3 (a int); SET @saved_dbug = @@GLOBAL.debug_dbug; set global debug_dbug= "+d,vio_peer_addr_fake_ipv4,getnameinfo_fake_long_host,getaddrinfo_fake_good_ipv4"; +flush hosts; # check connect connect con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,; -connection con1; select current_user(); current_user() user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678@host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345 @@ -34,7 +34,6 @@ connection default; grant SELECT ON *.* TO user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678@host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345; disconnect con1; connect con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,; -connection con1; select * from mariadbtestdb.t1; a b select * from mariadbtestdb2.t2; @@ -44,7 +43,6 @@ connection default; REVOKE ALL PRIVILEGES, GRANT OPTION FROM user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678@host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345; disconnect con1; connect con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,; -connection con1; select * from mariadbtestdb.t1; ERROR 42000: SELECT command denied to user 'user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678'@'host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345' for table `mariadbtestdb`.`t1` select * from mariadbtestdb2.t2; @@ -54,7 +52,6 @@ connection default; grant SELECT ON mariadbtestdb.* TO user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678@host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345; disconnect con1; connect con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,; -connection con1; select * from mariadbtestdb.t1; a b select * from mariadbtestdb2.t2; @@ -67,7 +64,6 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM user5678901_345678902_345678903_3456789 grant SELECT ON mariadbtestdb.t1 TO user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678@host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345; disconnect con1; connect con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,; -connection con1; select * from mariadbtestdb.t1; a b select * from mariadbtestdb2.t2; @@ -80,7 +76,6 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM user5678901_345678902_345678903_3456789 grant SELECT (a) ON mariadbtestdb.t1 TO user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678@host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345; disconnect con1; connect con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,; -connection con1; select * from mariadbtestdb.t1; ERROR 42000: SELECT command denied to user 'user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678'@'host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345' for table `mariadbtestdb`.`t1` select * from mariadbtestdb2.t2; @@ -99,7 +94,6 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM user5678901_345678902_345678903_3456789 grant role5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678 to user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678@host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345; disconnect con1; connect con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,; -connection con1; select * from mariadbtestdb.t1; ERROR 42000: SELECT command denied to user 'user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678'@'host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345' for table `mariadbtestdb`.`t1` select * from mariadbtestdb2.t2; diff --git a/mysql-test/main/long_host.test b/mysql-test/main/long_host.test index 0c082bf6fb4..a24c9c74cb0 100644 --- a/mysql-test/main/long_host.test +++ b/mysql-test/main/long_host.test @@ -33,11 +33,11 @@ create table mariadbtestdb.t3 (a int); SET @saved_dbug = @@GLOBAL.debug_dbug; set global debug_dbug= "+d,vio_peer_addr_fake_ipv4,getnameinfo_fake_long_host,getaddrinfo_fake_good_ipv4"; +flush hosts; --echo # check connect connect (con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,); -connection con1; select current_user(); --echo # check global privileges @@ -51,7 +51,6 @@ connection default; grant SELECT ON *.* TO user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678@host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345; disconnect con1; connect (con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,); -connection con1; select * from mariadbtestdb.t1; select * from mariadbtestdb2.t2; @@ -62,7 +61,6 @@ connection default; REVOKE ALL PRIVILEGES, GRANT OPTION FROM user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678@host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345; disconnect con1; connect (con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,); -connection con1; --error ER_TABLEACCESS_DENIED_ERROR select * from mariadbtestdb.t1; --error ER_TABLEACCESS_DENIED_ERROR @@ -75,7 +73,6 @@ connection default; grant SELECT ON mariadbtestdb.* TO user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678@host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345; disconnect con1; connect (con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,); -connection con1; select * from mariadbtestdb.t1; --error ER_TABLEACCESS_DENIED_ERROR select * from mariadbtestdb2.t2; @@ -88,7 +85,6 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM user5678901_345678902_345678903_3456789 grant SELECT ON mariadbtestdb.t1 TO user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678@host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345; disconnect con1; connect (con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,); -connection con1; select * from mariadbtestdb.t1; --error ER_TABLEACCESS_DENIED_ERROR select * from mariadbtestdb2.t2; @@ -102,7 +98,6 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM user5678901_345678902_345678903_3456789 grant SELECT (a) ON mariadbtestdb.t1 TO user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678@host5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678913_345678914_345678915_345678916_345678917_345678918_345678919_345678920_345678921_345678922_345678923_345678924_345678925_345; disconnect con1; connect (con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,); -connection con1; --error ER_TABLEACCESS_DENIED_ERROR select * from mariadbtestdb.t1; --error ER_TABLEACCESS_DENIED_ERROR @@ -130,7 +125,6 @@ grant role5678901_345678902_345678903_345678904_345678905_345678906_345678907_34 disconnect con1; connect (con1,"127.0.0.1","user5678901_345678902_345678903_345678904_345678905_345678906_345678907_345678908_345678909_345678910_345678911_345678912_345678",,test,$MASTER_MYPORT,); -connection con1; --error ER_TABLEACCESS_DENIED_ERROR select * from mariadbtestdb.t1; From 4231cf6d3f8fbeafac76a718452ddb3f7abba48b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 8 Nov 2023 15:44:18 +0100 Subject: [PATCH 432/477] MDEV-32617 deprecate secure_auth=0 --- mysql-test/main/change_user.result | 4 ++++ mysql-test/main/connect.result | 4 ++++ mysql-test/main/set_password.result | 4 ++++ .../sys_vars/r/old_passwords_func.result | 6 ++++++ .../suite/sys_vars/r/secure_auth_basic.result | 20 +++++++++++++++++++ .../suite/sys_vars/r/secure_auth_func.result | 6 ++++++ .../suite/sys_vars/r/secure_auth_grant.result | 6 ++++++ sql/mysqld.cc | 3 +++ sql/mysqld.h | 2 +- sql/sys_vars.cc | 5 +++-- 10 files changed, 57 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/change_user.result b/mysql-test/main/change_user.result index fa934fbf09a..c91522dc6ce 100644 --- a/mysql-test/main/change_user.result +++ b/mysql-test/main/change_user.result @@ -1,4 +1,6 @@ set global secure_auth=0; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release create user test_nopw; grant select on test.* to test_nopw; create user test_oldpw identified by password "09301740536db389"; @@ -90,6 +92,8 @@ NULL FLUSH STATUS; Value of com_select did not change set global secure_auth=default; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release set timestamp=unix_timestamp('2010-10-10 10:10:10'); select now(); now() diff --git a/mysql-test/main/connect.result b/mysql-test/main/connect.result index 74387168d98..6642b8a1c6e 100644 --- a/mysql-test/main/connect.result +++ b/mysql-test/main/connect.result @@ -1,4 +1,6 @@ SET global secure_auth=0; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release connect con1,localhost,root,,mysql; show tables; Tables_in_mysql @@ -412,6 +414,8 @@ test test drop procedure p1; SET global secure_auth=default; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release # # MDEV-19282: Log more specific warning with log_warnings=2 if # connection is aborted prior to authentication diff --git a/mysql-test/main/set_password.result b/mysql-test/main/set_password.result index a3d8683ee64..19ca628f1f7 100644 --- a/mysql-test/main/set_password.result +++ b/mysql-test/main/set_password.result @@ -1,4 +1,6 @@ set global secure_auth=0; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release create user natauth@localhost identified via 'mysql_native_password' using '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29'; create user invalidauth@localhost identified via 'mysql_native_password' using 'invalid'; create user newpass@localhost identified by password '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29'; @@ -186,6 +188,8 @@ drop user natauth@localhost, newpass@localhost, newpassnat@localhost; drop user invalidauth@localhost, invalidpass@localhost, invalidpassnat@localhost,invalidmysql57auth@localhost; drop user oldauth@localhost, oldpass@localhost, oldpassold@localhost; set global secure_auth=default; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release # switching from mysql.global_priv to mysql.user create user foo@localhost identified with mysql_native_password; update mysql.user set authentication_string=password('foo'), plugin='mysql_native_password' where user='foo' and host='localhost'; diff --git a/mysql-test/suite/sys_vars/r/old_passwords_func.result b/mysql-test/suite/sys_vars/r/old_passwords_func.result index 6bd060932a8..fb250eeb669 100644 --- a/mysql-test/suite/sys_vars/r/old_passwords_func.result +++ b/mysql-test/suite/sys_vars/r/old_passwords_func.result @@ -9,6 +9,8 @@ SET GLOBAL old_passwords = TRUE; SET SESSION old_passwords = TRUE; CREATE USER 'userOldPass'@'localhost' IDENTIFIED BY 'pass3'; SET GLOBAL secure_auth = FALSE; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release connect con1,localhost,userNewPass1,pass1,; SELECT CURRENT_USER(); CURRENT_USER() @@ -30,6 +32,8 @@ disconnect con2; disconnect con3; '#------------------------FN_DYNVARS_115_02---------------------------#' SET GLOBAL secure_auth = TRUE; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release connect con1,localhost,userNewPass1,pass1,; SELECT CURRENT_USER(); CURRENT_USER() @@ -55,3 +59,5 @@ DROP USER 'userOldPass'@'localhost'; SET @@GLOBAL.old_passwords = @global_old_passwords; SET @@SESSION.old_passwords = @session_old_passwords; SET @@GLOBAL.secure_auth = @global_secure_auth; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release diff --git a/mysql-test/suite/sys_vars/r/secure_auth_basic.result b/mysql-test/suite/sys_vars/r/secure_auth_basic.result index 35f283de278..66763fc5f8d 100644 --- a/mysql-test/suite/sys_vars/r/secure_auth_basic.result +++ b/mysql-test/suite/sys_vars/r/secure_auth_basic.result @@ -4,7 +4,11 @@ SELECT @global_start_value; 1 '#--------------------FN_DYNVARS_143_01------------------------#' SET @@global.secure_auth = 1; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SET @@global.secure_auth = DEFAULT; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SELECT @@global.secure_auth; @@global.secure_auth 1 @@ -17,15 +21,21 @@ SELECT @@secure_auth; SELECT global.secure_auth; ERROR 42S02: Unknown table 'global' in field list SET global secure_auth = 1; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SELECT @@global.secure_auth; @@global.secure_auth 1 '#--------------------FN_DYNVARS_143_03------------------------#' SET @@global.secure_auth = 0; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SELECT @@global.secure_auth; @@global.secure_auth 0 SET @@global.secure_auth = 1; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SELECT @@global.secure_auth; @@global.secure_auth 1 @@ -83,23 +93,33 @@ VARIABLE_VALUE ON '#---------------------FN_DYNVARS_143_08-------------------------#' SET @@global.secure_auth = OFF; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SELECT @@global.secure_auth; @@global.secure_auth 0 SET @@global.secure_auth = ON; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SELECT @@global.secure_auth; @@global.secure_auth 1 '#---------------------FN_DYNVARS_143_09----------------------#' SET @@global.secure_auth = TRUE; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SELECT @@global.secure_auth; @@global.secure_auth 1 SET @@global.secure_auth = FALSE; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SELECT @@global.secure_auth; @@global.secure_auth 0 SET @@global.secure_auth = @global_start_value; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SELECT @@global.secure_auth; @@global.secure_auth 1 diff --git a/mysql-test/suite/sys_vars/r/secure_auth_func.result b/mysql-test/suite/sys_vars/r/secure_auth_func.result index 97d22facd9d..ee0d6146225 100644 --- a/mysql-test/suite/sys_vars/r/secure_auth_func.result +++ b/mysql-test/suite/sys_vars/r/secure_auth_func.result @@ -8,6 +8,8 @@ SELECT @@GLOBAL.secure_auth; 1 / ON Expected '#--------------------FN_DYNVARS_144_02-------------------------#' SET GLOBAL secure_auth = OFF; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release CREATE USER 'testUser'@'localhost' IDENTIFIED BY 'newpass'; connect con_user1,localhost,testUser,newpass,; connection default; @@ -16,6 +18,8 @@ connect con_user2,localhost,testUser,newpass,; connection default; '#--------------------FN_DYNVARS_144_03-------------------------#' SET GLOBAL secure_auth = ON; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SET PASSWORD FOR 'testUser'@'localhost' = PASSWORD('newpass'); connect con_user3,localhost,testUser,newpass,; connection default; @@ -27,6 +31,8 @@ SET PASSWORD FOR 'testUser'@'localhost' = PASSWORD('newpass'); connect con_user4,localhost,testUser,newpass,; connection default; SET GLOBAL secure_auth = @old_secure_auth; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release disconnect con_user1; disconnect con_user2; disconnect con_user3; diff --git a/mysql-test/suite/sys_vars/r/secure_auth_grant.result b/mysql-test/suite/sys_vars/r/secure_auth_grant.result index ed33eb33951..ea4b1b09d54 100644 --- a/mysql-test/suite/sys_vars/r/secure_auth_grant.result +++ b/mysql-test/suite/sys_vars/r/secure_auth_grant.result @@ -23,6 +23,8 @@ GRANT CONNECTION ADMIN ON *.* TO user1@localhost; connect user1,localhost,user1,,; connection user1; SET GLOBAL secure_auth=1; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SET secure_auth=1; ERROR HY000: Variable 'secure_auth' is a GLOBAL variable and should be set with SET GLOBAL SET SESSION secure_auth=1; @@ -36,6 +38,8 @@ GRANT SUPER ON *.* TO user1@localhost; connect user1,localhost,user1,,; connection user1; SET GLOBAL secure_auth=1; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release SET secure_auth=1; ERROR HY000: Variable 'secure_auth' is a GLOBAL variable and should be set with SET GLOBAL SET SESSION secure_auth=1; @@ -44,3 +48,5 @@ disconnect user1; connection default; DROP USER user1@localhost; SET @@global.secure_auth=@global; +Warnings: +Warning 1287 '@@secure_auth' is deprecated and will be removed in a future release diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c0dd56ab3d5..9e2575511be 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7978,6 +7978,9 @@ mysqld_get_one_option(const struct my_option *opt, const char *argument, test_flags= argument ? ((uint) atoi(argument) & ~TEST_BLOCKING) : 0; opt_endinfo=1; break; + case OPT_SECURE_AUTH: + WARN_DEPRECATED_NO_REPLACEMENT(NULL, "--secure-auth"); + break; case OPT_THREAD_CONCURRENCY: WARN_DEPRECATED_NO_REPLACEMENT(NULL, "THREAD_CONCURRENCY"); break; diff --git a/sql/mysqld.h b/sql/mysqld.h index fc8afa06638..25b99e873e6 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -828,7 +828,7 @@ enum options_mysqld OPT_WSREP_SYNC_WAIT, #endif /* WITH_WSREP */ OPT_MYSQL_COMPATIBILITY, - OPT_TLS_VERSION, + OPT_TLS_VERSION, OPT_SECURE_AUTH, OPT_MYSQL_TO_BE_IMPLEMENTED, OPT_which_is_always_the_last }; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 6e84d51a578..34a8d7e3fe0 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3226,8 +3226,9 @@ Sys_secure_auth( "secure_auth", "Disallow authentication for accounts that have old (pre-4.1) " "passwords", - GLOBAL_VAR(opt_secure_auth), CMD_LINE(OPT_ARG), - DEFAULT(TRUE)); + GLOBAL_VAR(opt_secure_auth), CMD_LINE(OPT_ARG, OPT_SECURE_AUTH), + DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0), + DEPRECATED("")); // since 10.6.17 static bool check_require_secure_transport(sys_var *self, THD *thd, set_var *var) { From d9cb1a2b7e71b70763aa582fe4615c0ca709b720 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 24 Nov 2023 17:45:16 +0100 Subject: [PATCH 433/477] MDEV-32751 sys schema view session_ssl_status is empty * treat FUNC/ARRAY variables as SESSION (otherwise they won't be shown) * allow SHOW_SIMPLE_FUNC everywhere where SHOW_FUNC is * increase row buffer size to avoid "too short" assert --- mysql-test/main/ssl.result | 18 ++++++++++++++++++ mysql-test/main/ssl.test | 2 ++ storage/perfschema/pfs_variable.cc | 12 ++++++++---- storage/perfschema/table_helper.h | 2 +- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/ssl.result b/mysql-test/main/ssl.result index 794830e5529..4f8ce517330 100644 --- a/mysql-test/main/ssl.result +++ b/mysql-test/main/ssl.result @@ -1,4 +1,22 @@ connect ssl_con,localhost,root,,,,,SSL; +select variable_name from performance_schema.status_by_thread where VARIABLE_NAME LIKE 'Ssl%'; +variable_name +Ssl_cipher +Ssl_cipher_list +Ssl_default_timeout +Ssl_server_not_after +Ssl_server_not_before +Ssl_verify_depth +Ssl_verify_mode +Ssl_version +Ssl_cipher +Ssl_cipher_list +Ssl_default_timeout +Ssl_server_not_after +Ssl_server_not_before +Ssl_verify_depth +Ssl_verify_mode +Ssl_version SELECT (VARIABLE_VALUE <> '') AS have_ssl FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='Ssl_cipher'; have_ssl 1 diff --git a/mysql-test/main/ssl.test b/mysql-test/main/ssl.test index d3830bb7007..a3a978f1001 100644 --- a/mysql-test/main/ssl.test +++ b/mysql-test/main/ssl.test @@ -13,6 +13,8 @@ connect (ssl_con,localhost,root,,,,,SSL); +select variable_name from performance_schema.status_by_thread where VARIABLE_NAME LIKE 'Ssl%'; + # Check ssl turned on SELECT (VARIABLE_VALUE <> '') AS have_ssl FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='Ssl_cipher'; diff --git a/storage/perfschema/pfs_variable.cc b/storage/perfschema/pfs_variable.cc index 239c55b623c..60ed9f943b1 100644 --- a/storage/perfschema/pfs_variable.cc +++ b/storage/perfschema/pfs_variable.cc @@ -66,7 +66,7 @@ static inline SHOW_SCOPE show_scope_from_type(enum enum_mysql_show_type type) case SHOW_SIMPLE_FUNC: case SHOW_UNDEF: default: - return SHOW_SCOPE_UNDEF; + return SHOW_SCOPE_ALL; } return SHOW_SCOPE_UNDEF; } @@ -716,6 +716,7 @@ bool PFS_status_variable_cache::can_aggregate(enum_mysql_show_type variable_type case SHOW_CHAR_PTR: case SHOW_ARRAY: case SHOW_FUNC: + case SHOW_SIMPLE_FUNC: case SHOW_INT: case SHOW_LONG: case SHOW_LONGLONG: @@ -1152,16 +1153,19 @@ void PFS_status_variable_cache::manifest(THD *thd, const SHOW_VAR *show_var_arra reevaluate the new SHOW_TYPE and value. Handle nested case where SHOW_FUNC resolves to another SHOW_FUNC. */ - if (show_var_ptr->type == SHOW_FUNC) + if (show_var_ptr->type == SHOW_FUNC || show_var_ptr->type == SHOW_SIMPLE_FUNC) { show_var_tmp= *show_var_ptr; /* Execute the function reference in show_var_tmp->value, which returns show_var_tmp with a new type and new value. */ - for (const SHOW_VAR *var= show_var_ptr; var->type == SHOW_FUNC; var= &show_var_tmp) + for (const SHOW_VAR *var= show_var_ptr; + var->type == SHOW_FUNC || var->type == SHOW_SIMPLE_FUNC; + var= &show_var_tmp) { - ((mysql_show_var_func)(var->value))(thd, &show_var_tmp, value_buf.data, NULL, m_query_scope); + ((mysql_show_var_func)(var->value))(thd, &show_var_tmp, value_buf.data, + &thd->status_var, m_query_scope); } show_var_ptr= &show_var_tmp; } diff --git a/storage/perfschema/table_helper.h b/storage/perfschema/table_helper.h index ddea4c08b36..87572ef2525 100644 --- a/storage/perfschema/table_helper.h +++ b/storage/perfschema/table_helper.h @@ -659,7 +659,7 @@ public: private: void make_row(const CHARSET_INFO *cs, const char* str, size_t length); - char m_str[1024]; + char m_str[2048]; uint m_length; const CHARSET_INFO *m_charset; }; From c5904702cdae585203fb1b7948d9008a6994c8a4 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 29 Nov 2023 17:19:14 +0100 Subject: [PATCH 434/477] cleanup: remove partition-specific code around update_auto_increment() --- sql/ha_partition.cc | 31 ++----------------------------- sql/ha_partition.h | 3 +-- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 4b0d2b909a1..c13b60f2cd8 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4186,6 +4186,7 @@ int ha_partition::external_lock(THD *thd, int lock_type) m_part_info->part_expr->walk(&Item::register_field_in_read_map, 1, 0); if ((error= m_part_info->vers_set_hist_part(thd))) goto err_handler; + need_info_for_auto_inc(); } DBUG_RETURN(0); @@ -4509,33 +4510,8 @@ int ha_partition::write_row(const uchar * buf) */ if (have_auto_increment) { - if (!table_share->next_number_keypart) - if (unlikely(error= update_next_auto_inc_val())) - goto exit; - - /* - If we have failed to set the auto-increment value for this row, - it is highly likely that we will not be able to insert it into - the correct partition. We must check and fail if necessary. - */ if (unlikely(error= update_auto_increment())) goto exit; - - /* - Don't allow generation of auto_increment value the partitions handler. - If a partitions handler would change the value, then it might not - match the partition any longer. - This can occur if 'SET INSERT_ID = 0; INSERT (NULL)', - So allow this by adding 'MODE_NO_AUTO_VALUE_ON_ZERO' to sql_mode. - The partitions handler::next_insert_id must always be 0. Otherwise - we need to forward release_auto_increment, or reset it for all - partitions. - */ - if (table->next_number_field->val_int() == 0) - { - table->auto_increment_field_not_null= TRUE; - thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO; - } } old_map= dbug_tmp_use_all_columns(table, &table->read_set); error= m_part_info->get_partition_id(m_part_info, &part_id, &func_value); @@ -10897,10 +10873,7 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment, else { THD *thd= ha_thd(); - /* - This is initialized in the beginning of the first write_row call. - */ - DBUG_ASSERT(part_share->auto_inc_initialized); + update_next_auto_inc_val(); /* Get a lock for handling the auto_increment in part_share for avoiding two concurrent statements getting the same number. diff --git a/sql/ha_partition.h b/sql/ha_partition.h index b4f6982101e..a38aca2691b 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -1406,9 +1406,8 @@ private: { ulonglong nr= (((Field_num*) field)->unsigned_flag || field->val_int() > 0) ? field->val_int() : 0; + update_next_auto_inc_val(); lock_auto_increment(); - DBUG_ASSERT(part_share->auto_inc_initialized || - !can_use_for_auto_inc_init()); /* must check when the mutex is taken */ if (nr >= part_share->next_auto_inc_val) part_share->next_auto_inc_val= nr + 1; From 81609d8625ae6b252eb2e98e94ed077fb260b05a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 29 Nov 2023 17:19:40 +0100 Subject: [PATCH 435/477] cleanup: remove innodb-specific code around update_auto_increment() removed dead code --- storage/innobase/handler/ha_innodb.cc | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 5e239633f22..b492810ccf4 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7665,20 +7665,6 @@ ha_innobase::write_row( #endif if ((error_result = update_auto_increment())) { - /* We don't want to mask autoinc overflow errors. */ - - /* Handle the case where the AUTOINC sub-system - failed during initialization. */ - if (m_prebuilt->autoinc_error == DB_UNSUPPORTED) { - error_result = ER_AUTOINC_READ_FAILED; - /* Set the error message to report too. */ - my_error(ER_AUTOINC_READ_FAILED, MYF(0)); - goto func_exit; - } else if (m_prebuilt->autoinc_error != DB_SUCCESS) { - error = m_prebuilt->autoinc_error; - goto report_error; - } - /* MySQL errors are passed straight back. */ goto func_exit; } @@ -7816,7 +7802,6 @@ set_max_autoinc: } } -report_error: /* Cleanup and exit. */ if (error == DB_TABLESPACE_DELETED) { ib_senderrf( From e472b682e068319e2a27373903cd46fb93093286 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 29 Nov 2023 18:56:59 +0100 Subject: [PATCH 436/477] MDEV-32839 LONG UNIQUE gives error when used with REPLACE calculate auto-inc value even if long duplicate check fails - this is what the engine does for normal uniques. auto-inc value is needed if it's a REPLACE --- mysql-test/main/long_unique_bugs.result | 79 +++++++++++++++++++++++++ mysql-test/main/long_unique_bugs.test | 71 ++++++++++++++++++++++ sql/handler.cc | 5 ++ 3 files changed, 155 insertions(+) diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result index 630936b472d..e5c14afd9c4 100644 --- a/mysql-test/main/long_unique_bugs.result +++ b/mysql-test/main/long_unique_bugs.result @@ -572,5 +572,84 @@ insert into t1 values (1,10),(2,20); update t1 set b = 30 limit 1; drop table t1; # +# MDEV-32839 LONG UNIQUE gives error when used with REPLACE +# +create table t1 ( +f1 bigint(20) not null auto_increment primary key, +f2 varchar(30) default null, +f3 varchar(30) default null, +f4 varchar(255) default null, +f5 varchar(30) default null, +f6 varchar(255) default null, +f7 varchar(255) default null, +unique problem_key (f3,f5,f6,f2,f4,f7) using hash +) engine=myisam; +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +select * from t1; +f1 f2 f3 f4 f5 f6 f7 +2 00004 0001009089999 netstes psit d +4 00004 0001009089999 netstes psit e +drop table t1; +create table t1 ( +f1 bigint(20) not null auto_increment primary key, +f2 varchar(30) default null, +f3 varchar(30) default null, +f4 varchar(255) default null, +f5 varchar(30) default null, +f6 varchar(255) default null, +f7 varchar(255) default null, +unique problem_key (f3,f5,f6,f2,f4,f7) using hash +) engine=innodb; +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +select * from t1; +f1 f2 f3 f4 f5 f6 f7 +2 00004 0001009089999 netstes psit d +4 00004 0001009089999 netstes psit e +drop table t1; +create table t1 ( +f1 bigint(20) not null auto_increment primary key, +f2 varchar(30) default null, +f3 varchar(30) default null, +f4 varchar(255) default null, +f5 varchar(30) default null, +f6 varchar(255) default null, +f7 varchar(255) default null, +unique problem_key (f3,f5,f6,f2,f4,f7) using hash +) engine=myisam partition by key(f1) partitions 2; +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +select * from t1; +f1 f2 f3 f4 f5 f6 f7 +2 00004 0001009089999 netstes psit d +4 00004 0001009089999 netstes psit e +drop table t1; +create table t1 ( +f1 bigint(20) not null auto_increment primary key, +f2 varchar(30) default null, +f3 varchar(30) default null, +f4 varchar(255) default null, +f5 varchar(30) default null, +f6 varchar(255) default null, +f7 varchar(255) default null, +unique problem_key (f3,f5,f6,f2,f4,f7) using hash +) engine=innodb partition by key(f1) partitions 2; +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +select * from t1; +f1 f2 f3 f4 f5 f6 f7 +2 00004 0001009089999 netstes psit d +4 00004 0001009089999 netstes psit e +drop table t1; +# # End of 10.5 tests # diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test index ed283424404..5fed7c72d9a 100644 --- a/mysql-test/main/long_unique_bugs.test +++ b/mysql-test/main/long_unique_bugs.test @@ -563,6 +563,77 @@ insert into t1 values (1,10),(2,20); update t1 set b = 30 limit 1; drop table t1; +--echo # +--echo # MDEV-32839 LONG UNIQUE gives error when used with REPLACE +--echo # +create table t1 ( + f1 bigint(20) not null auto_increment primary key, + f2 varchar(30) default null, + f3 varchar(30) default null, + f4 varchar(255) default null, + f5 varchar(30) default null, + f6 varchar(255) default null, + f7 varchar(255) default null, + unique problem_key (f3,f5,f6,f2,f4,f7) using hash +) engine=myisam; +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +select * from t1; +drop table t1; + +create table t1 ( + f1 bigint(20) not null auto_increment primary key, + f2 varchar(30) default null, + f3 varchar(30) default null, + f4 varchar(255) default null, + f5 varchar(30) default null, + f6 varchar(255) default null, + f7 varchar(255) default null, + unique problem_key (f3,f5,f6,f2,f4,f7) using hash +) engine=innodb; +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +select * from t1; +drop table t1; + +create table t1 ( + f1 bigint(20) not null auto_increment primary key, + f2 varchar(30) default null, + f3 varchar(30) default null, + f4 varchar(255) default null, + f5 varchar(30) default null, + f6 varchar(255) default null, + f7 varchar(255) default null, + unique problem_key (f3,f5,f6,f2,f4,f7) using hash +) engine=myisam partition by key(f1) partitions 2; +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +select * from t1; +drop table t1; + +create table t1 ( + f1 bigint(20) not null auto_increment primary key, + f2 varchar(30) default null, + f3 varchar(30) default null, + f4 varchar(255) default null, + f5 varchar(30) default null, + f6 varchar(255) default null, + f7 varchar(255) default null, + unique problem_key (f3,f5,f6,f2,f4,f7) using hash +) engine=innodb partition by key(f1) partitions 2; +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'd'); +insert t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netstes', 'psit', 'e'); +select * from t1; +drop table t1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/sql/handler.cc b/sql/handler.cc index cc46fb678d7..2e2961bef5f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7263,7 +7263,12 @@ int handler::ha_write_row(const uchar *buf) { DBUG_ASSERT(inited == NONE || lookup_handler != this); if ((error= check_duplicate_long_entries(buf))) + { + if (table->next_number_field && buf == table->record[0]) + if (int err= update_auto_increment()) + error= err; DBUG_RETURN(error); + } } MYSQL_INSERT_ROW_START(table_share->db.str, table_share->table_name.str); From 6193d0cabb241478984ea7ba8a6f7e5d4015b627 Mon Sep 17 00:00:00 2001 From: Sergei Glushchenko Date: Thu, 22 Jun 2023 16:52:40 +1000 Subject: [PATCH 437/477] MDEV-20286 mariabackup fails when innodb_max_dirty_pages_pct contains a fraction (is not an integer) This is a port of the Percona Server commit 5265f42e290573e9591f8ca28ab66afc051f89a3 which is the same as their bug PXB-1807: xtrabackup does not accept fractional values for innodb_max_dirty_pages_pct Problem: Variable specified as double in MySQL server, but read as long in the xtrabackup. This causes xtrabackup to fail at startup when the value contains decimal point. Fix: Make xtrabackup to interpret the value as double to be compatible with server. --- extra/mariabackup/xtrabackup.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 0c018b97d29..b8d3d729d88 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -1647,8 +1647,11 @@ struct my_option xb_server_options[] = "Path to InnoDB log files.", &srv_log_group_home_dir, &srv_log_group_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT, - "Percentage of dirty pages allowed in bufferpool.", (G_PTR*) &srv_max_buf_pool_modified_pct, - (G_PTR*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0}, + "Percentage of dirty pages allowed in bufferpool.", + (G_PTR*) &srv_max_buf_pool_modified_pct, + (G_PTR*) &srv_max_buf_pool_modified_pct, 0, GET_DOUBLE, REQUIRED_ARG, + (longlong)getopt_double2ulonglong(90), (longlong)getopt_double2ulonglong(0), + getopt_double2ulonglong(100), 0, 0, 0}, {"innodb_use_native_aio", OPT_INNODB_USE_NATIVE_AIO, "Use native AIO if supported on this platform.", (G_PTR*) &srv_use_native_aio, From 7504985dafe0724f09ac07c0514623ba6c39eaee Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 5 Oct 2023 16:55:34 +0300 Subject: [PATCH 438/477] MDEV-21587: disk.disk{_notembedded} test result MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow for a CI system to be almost out of space, or having so little use, that the Total space is the same as available or used. Thanks Otto Kekäläinen for the bug report and testing. --- plugin/disks/mysql-test/disks/disks.result | 4 ++-- plugin/disks/mysql-test/disks/disks.test | 2 +- plugin/disks/mysql-test/disks/disks_notembedded.result | 8 ++++---- plugin/disks/mysql-test/disks/disks_notembedded.test | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugin/disks/mysql-test/disks/disks.result b/plugin/disks/mysql-test/disks/disks.result index 229f8dbf353..2c124faa91f 100644 --- a/plugin/disks/mysql-test/disks/disks.result +++ b/plugin/disks/mysql-test/disks/disks.result @@ -7,6 +7,6 @@ DISKS CREATE TEMPORARY TABLE `DISKS` ( `Used` bigint(32) NOT NULL, `Available` bigint(32) NOT NULL ) ENGINE=MEMORY DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci -select sum(Total) > sum(Available), sum(Total)>sum(Used) from information_schema.disks; -sum(Total) > sum(Available) sum(Total)>sum(Used) +select sum(Total) >= sum(Available), sum(Total)>=sum(Used) from information_schema.disks; +sum(Total) >= sum(Available) sum(Total)>=sum(Used) 1 1 diff --git a/plugin/disks/mysql-test/disks/disks.test b/plugin/disks/mysql-test/disks/disks.test index 7189c548342..9adc3f01ebc 100644 --- a/plugin/disks/mysql-test/disks/disks.test +++ b/plugin/disks/mysql-test/disks/disks.test @@ -1,3 +1,3 @@ --replace_regex /varchar\([0-9]+\)/varchar(pathlen)/ show create table information_schema.disks; -select sum(Total) > sum(Available), sum(Total)>sum(Used) from information_schema.disks; +select sum(Total) >= sum(Available), sum(Total)>=sum(Used) from information_schema.disks; diff --git a/plugin/disks/mysql-test/disks/disks_notembedded.result b/plugin/disks/mysql-test/disks/disks_notembedded.result index 974294744cc..ea2ccc85bfb 100644 --- a/plugin/disks/mysql-test/disks/disks_notembedded.result +++ b/plugin/disks/mysql-test/disks/disks_notembedded.result @@ -6,16 +6,16 @@ CREATE USER user1@localhost; GRANT SELECT ON *.* TO user1@localhost; connect con1,localhost,user1,,; connection con1; -select sum(Total) > sum(Available), sum(Total)>sum(Used) from information_schema.disks; -sum(Total) > sum(Available) sum(Total)>sum(Used) +select sum(Total) >= sum(Available), sum(Total) >= sum(Used) from information_schema.disks; +sum(Total) >= sum(Available) sum(Total) >= sum(Used) NULL NULL disconnect con1; connection default; GRANT FILE ON *.* TO user1@localhost; connect con1,localhost,user1,,; connection con1; -select sum(Total) > sum(Available), sum(Total)>sum(Used) from information_schema.disks; -sum(Total) > sum(Available) sum(Total)>sum(Used) +select sum(Total) >= sum(Available), sum(Total) >= sum(Used) from information_schema.disks; +sum(Total) >= sum(Available) sum(Total) >= sum(Used) 1 1 connection default; DROP USER user1@localhost; diff --git a/plugin/disks/mysql-test/disks/disks_notembedded.test b/plugin/disks/mysql-test/disks/disks_notembedded.test index a0f6c2e5887..4481da9f176 100644 --- a/plugin/disks/mysql-test/disks/disks_notembedded.test +++ b/plugin/disks/mysql-test/disks/disks_notembedded.test @@ -10,7 +10,7 @@ GRANT SELECT ON *.* TO user1@localhost; connect (con1,localhost,user1,,); connection con1; -select sum(Total) > sum(Available), sum(Total)>sum(Used) from information_schema.disks; +select sum(Total) >= sum(Available), sum(Total) >= sum(Used) from information_schema.disks; disconnect con1; connection default; @@ -18,7 +18,7 @@ GRANT FILE ON *.* TO user1@localhost; connect (con1,localhost,user1,,); connection con1; -select sum(Total) > sum(Available), sum(Total)>sum(Used) from information_schema.disks; +select sum(Total) >= sum(Available), sum(Total) >= sum(Used) from information_schema.disks; connection default; DROP USER user1@localhost; From 736a54f49c72d89fb82ef4165e96cddb506cf555 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 13 Dec 2023 00:37:57 +0100 Subject: [PATCH 439/477] perfschema: use LOCK_thd_kill to "keep THD during materialization" fixes the failure of ./mtr --ps sys_vars.gtid_slave_pos_grant sysschema.v_session_ssl_status safe_mutex: Found wrong usage of mutex 'LOCK_thd_data' and 'LOCK_active_mi' --- storage/perfschema/pfs_variable.cc | 14 +++++++------- storage/perfschema/pfs_variable.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/storage/perfschema/pfs_variable.cc b/storage/perfschema/pfs_variable.cc index 60ed9f943b1..aa07686139b 100644 --- a/storage/perfschema/pfs_variable.cc +++ b/storage/perfschema/pfs_variable.cc @@ -254,7 +254,7 @@ int PFS_system_variable_cache::do_materialize_all(THD *unsafe_thd) } /* Release lock taken in get_THD(). */ - mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data); + mysql_mutex_unlock(&m_safe_thd->LOCK_thd_kill); m_materialized= true; ret= 0; @@ -354,7 +354,7 @@ int PFS_system_variable_cache::do_materialize_session(PFS_thread *pfs_thread) } /* Release lock taken in get_THD(). */ - mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data); + mysql_mutex_unlock(&m_safe_thd->LOCK_thd_kill); m_materialized= true; ret= 0; @@ -407,7 +407,7 @@ int PFS_system_variable_cache::do_materialize_session(PFS_thread *pfs_thread, ui } /* Release lock taken in get_THD(). */ - mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data); + mysql_mutex_unlock(&m_safe_thd->LOCK_thd_kill); m_materialized= true; ret= 0; @@ -458,7 +458,7 @@ int PFS_system_variable_cache::do_materialize_session(THD *unsafe_thd) } /* Release lock taken in get_THD(). */ - mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data); + mysql_mutex_unlock(&m_safe_thd->LOCK_thd_kill); m_materialized= true; ret= 0; @@ -990,7 +990,7 @@ int PFS_status_variable_cache::do_materialize_all(THD* unsafe_thd) manifest(m_safe_thd, m_show_var_array.front(), status_vars, "", false, false); /* Release lock taken in get_THD(). */ - mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data); + mysql_mutex_unlock(&m_safe_thd->LOCK_thd_kill); m_materialized= true; ret= 0; @@ -1036,7 +1036,7 @@ int PFS_status_variable_cache::do_materialize_session(THD* unsafe_thd) manifest(m_safe_thd, m_show_var_array.front(), status_vars, "", false, true); /* Release lock taken in get_THD(). */ - mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data); + mysql_mutex_unlock(&m_safe_thd->LOCK_thd_kill); m_materialized= true; ret= 0; @@ -1078,7 +1078,7 @@ int PFS_status_variable_cache::do_materialize_session(PFS_thread *pfs_thread) manifest(m_safe_thd, m_show_var_array.front(), status_vars, "", false, true); /* Release lock taken in get_THD(). */ - mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data); + mysql_mutex_unlock(&m_safe_thd->LOCK_thd_kill); m_materialized= true; ret= 0; diff --git a/storage/perfschema/pfs_variable.h b/storage/perfschema/pfs_variable.h index d3ad4c7f900..fda8dc692d9 100644 --- a/storage/perfschema/pfs_variable.h +++ b/storage/perfschema/pfs_variable.h @@ -212,7 +212,7 @@ public: return false; /* Hold this lock to keep THD during materialization. */ - mysql_mutex_lock(&thd->LOCK_thd_data); + mysql_mutex_lock(&thd->LOCK_thd_kill); return true; } void set_unsafe_thd(THD *unsafe_thd) { m_unsafe_thd= unsafe_thd; } From fbe604d88396db5214008a784061b501a9a93445 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 14 Nov 2023 10:01:08 +1100 Subject: [PATCH 440/477] MDEV-32795: ALTER SEQUENCE IF NOT EXISTS non_existing_seq Errors rather than note Like all IF NOT EXISTS syntax, a Note should be generated. The original commit of Seqeuences cleared the IF NOT EXISTS part in the sql/sql_yacc.yy with lex->create_info.init(). Without this bit set there was no way it could do anything other than error. To remedy this removal, the sql_yacc.yy components have been minimised as they where all set at the beginning of the ALTER. This way the opt_if_not_exists correctly set the IF_EXISTS flag. In MDEV-13005 (bb4dd70e7c65) the error code changed, requiring ER_UNKNOWN_SEQUENCES to be handled in the function No_such_table_error_handler::handle_condition. --- mysql-test/suite/sql_sequence/alter.result | 6 +++++- mysql-test/suite/sql_sequence/alter.test | 6 +++++- sql/sql_base.cc | 4 +++- sql/sql_yacc.yy | 4 ---- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/sql_sequence/alter.result b/mysql-test/suite/sql_sequence/alter.result index 90de2ebfcc0..68d42e52784 100644 --- a/mysql-test/suite/sql_sequence/alter.result +++ b/mysql-test/suite/sql_sequence/alter.result @@ -210,8 +210,12 @@ create table t1 (a int); alter sequence t1 minvalue=100; ERROR 42S02: 'test.t1' is not a SEQUENCE drop table t1; +# +# MDEV-32795: ALTER SEQUENCE IF NOT EXISTS non_existing_seq Errors rather than note +# alter sequence if exists t1 minvalue=100; -ERROR 42S02: Unknown SEQUENCE: 't1' +Warnings: +Note 4091 Unknown SEQUENCE: 'test.t1' alter sequence t1 minvalue=100; ERROR 42S02: Unknown SEQUENCE: 't1' create sequence t1; diff --git a/mysql-test/suite/sql_sequence/alter.test b/mysql-test/suite/sql_sequence/alter.test index e6bbaba614a..a771c9bba2f 100644 --- a/mysql-test/suite/sql_sequence/alter.test +++ b/mysql-test/suite/sql_sequence/alter.test @@ -120,8 +120,12 @@ create table t1 (a int); alter sequence t1 minvalue=100; drop table t1; ---error ER_UNKNOWN_SEQUENCES +--echo # +--echo # MDEV-32795: ALTER SEQUENCE IF NOT EXISTS non_existing_seq Errors rather than note +--echo # + alter sequence if exists t1 minvalue=100; + --error ER_UNKNOWN_SEQUENCES alter sequence t1 minvalue=100; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 627dc6ff5f6..4e8598a8d65 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -77,7 +77,9 @@ No_such_table_error_handler::handle_condition(THD *, Sql_condition ** cond_hdl) { *cond_hdl= NULL; - if (sql_errno == ER_NO_SUCH_TABLE || sql_errno == ER_NO_SUCH_TABLE_IN_ENGINE) + if (sql_errno == ER_NO_SUCH_TABLE + || sql_errno == ER_NO_SUCH_TABLE_IN_ENGINE + || sql_errno == ER_UNKNOWN_SEQUENCES) { m_handled_errors++; return TRUE; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0b893c952bd..f6f826e3e07 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8128,11 +8128,7 @@ alter: | ALTER SEQUENCE_SYM opt_if_exists { LEX *lex= Lex; - lex->name= null_clex_str; - lex->table_type= TABLE_TYPE_UNKNOWN; lex->sql_command= SQLCOM_ALTER_SEQUENCE; - lex->create_info.init(); - lex->no_write_to_binlog= 0; DBUG_ASSERT(!lex->m_sql_cmd); if (Lex->main_select_push()) MYSQL_YYABORT; From 9a7deb1c36f9ed08a1ce48e7fd635b45c721dcd6 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 31 Oct 2023 22:09:31 +0100 Subject: [PATCH 441/477] MDEV-32542 plugins.compression - multiple buildbot failures more robust plugins.compression test --- .../suite/plugins/r/compression,innodb-lz4.rdiff | 12 ++++++++---- .../suite/plugins/r/compression,innodb-lzma.rdiff | 12 ++++++++---- .../suite/plugins/r/compression,innodb-lzo.rdiff | 12 ++++++++---- .../suite/plugins/r/compression,innodb-snappy.rdiff | 12 ++++++++---- .../suite/plugins/r/compression,mroonga-lz4.rdiff | 11 ++++++++--- mysql-test/suite/plugins/r/compression.result | 7 ++++++- mysql-test/suite/plugins/t/compression.combinations | 5 +++++ mysql-test/suite/plugins/t/compression.test | 4 +++- 8 files changed, 54 insertions(+), 21 deletions(-) diff --git a/mysql-test/suite/plugins/r/compression,innodb-lz4.rdiff b/mysql-test/suite/plugins/r/compression,innodb-lz4.rdiff index 06fdb0bd4f0..791aecda080 100644 --- a/mysql-test/suite/plugins/r/compression,innodb-lz4.rdiff +++ b/mysql-test/suite/plugins/r/compression,innodb-lz4.rdiff @@ -10,15 +10,19 @@ +set global innodb_compression_algorithm = lz4; call mtr.add_suppression("Background Page read failed to read, uncompress, or decrypt"); call mtr.add_suppression("Table is compressed or encrypted but uncompress or decrypt failed"); - call mtr.add_suppression("Table .*t1.* is compressed with (\\w+), which is not currently loaded. Please load the \\1 provider plugin to open the table"); -@@ -15,8 +15,8 @@ + call mtr.add_suppression("Table `test`.`t1` is corrupted. Please drop the table and recreate"); +@@ -16,12 +16,12 @@ 0 abcabcabc 300 1 defdefdef 3000 2 ghighighi 30000 -# restart: --disable-provider-bzip2 +# restart: --disable-provider-lz4 select a, left(b, 9), length(b) from t1; --ERROR HY000: Table test/t1 is compressed with bzip2, which is not currently loaded. Please load the bzip2 provider plugin to open the table -+ERROR HY000: Table test/t1 is compressed with lz4, which is not currently loaded. Please load the lz4 provider plugin to open the table + ERROR 42S02: Table 'test.t1' doesn't exist in engine + show warnings; + Level Code Message +-Warning 4185 MariaDB tried to use the BZip2 compression, but its provider plugin is not loaded ++Warning 4185 MariaDB tried to use the LZ4 compression, but its provider plugin is not loaded + Error 1932 Table 'test.t1' doesn't exist in engine drop table t1; # restart diff --git a/mysql-test/suite/plugins/r/compression,innodb-lzma.rdiff b/mysql-test/suite/plugins/r/compression,innodb-lzma.rdiff index ee348934a54..13c42f82b43 100644 --- a/mysql-test/suite/plugins/r/compression,innodb-lzma.rdiff +++ b/mysql-test/suite/plugins/r/compression,innodb-lzma.rdiff @@ -10,15 +10,19 @@ +set global innodb_compression_algorithm = lzma; call mtr.add_suppression("Background Page read failed to read, uncompress, or decrypt"); call mtr.add_suppression("Table is compressed or encrypted but uncompress or decrypt failed"); - call mtr.add_suppression("Table .*t1.* is compressed with (\\w+), which is not currently loaded. Please load the \\1 provider plugin to open the table"); -@@ -15,8 +15,8 @@ + call mtr.add_suppression("Table `test`.`t1` is corrupted. Please drop the table and recreate"); +@@ -16,12 +16,12 @@ 0 abcabcabc 300 1 defdefdef 3000 2 ghighighi 30000 -# restart: --disable-provider-bzip2 +# restart: --disable-provider-lzma select a, left(b, 9), length(b) from t1; --ERROR HY000: Table test/t1 is compressed with bzip2, which is not currently loaded. Please load the bzip2 provider plugin to open the table -+ERROR HY000: Table test/t1 is compressed with lzma, which is not currently loaded. Please load the lzma provider plugin to open the table + ERROR 42S02: Table 'test.t1' doesn't exist in engine + show warnings; + Level Code Message +-Warning 4185 MariaDB tried to use the BZip2 compression, but its provider plugin is not loaded ++Warning 4185 MariaDB tried to use the LZMA compression, but its provider plugin is not loaded + Error 1932 Table 'test.t1' doesn't exist in engine drop table t1; # restart diff --git a/mysql-test/suite/plugins/r/compression,innodb-lzo.rdiff b/mysql-test/suite/plugins/r/compression,innodb-lzo.rdiff index d7cdc41092a..cc7783cc4f8 100644 --- a/mysql-test/suite/plugins/r/compression,innodb-lzo.rdiff +++ b/mysql-test/suite/plugins/r/compression,innodb-lzo.rdiff @@ -10,15 +10,19 @@ +set global innodb_compression_algorithm = lzo; call mtr.add_suppression("Background Page read failed to read, uncompress, or decrypt"); call mtr.add_suppression("Table is compressed or encrypted but uncompress or decrypt failed"); - call mtr.add_suppression("Table .*t1.* is compressed with (\\w+), which is not currently loaded. Please load the \\1 provider plugin to open the table"); -@@ -15,8 +15,8 @@ + call mtr.add_suppression("Table `test`.`t1` is corrupted. Please drop the table and recreate"); +@@ -16,12 +16,12 @@ 0 abcabcabc 300 1 defdefdef 3000 2 ghighighi 30000 -# restart: --disable-provider-bzip2 +# restart: --disable-provider-lzo select a, left(b, 9), length(b) from t1; --ERROR HY000: Table test/t1 is compressed with bzip2, which is not currently loaded. Please load the bzip2 provider plugin to open the table -+ERROR HY000: Table test/t1 is compressed with lzo, which is not currently loaded. Please load the lzo provider plugin to open the table + ERROR 42S02: Table 'test.t1' doesn't exist in engine + show warnings; + Level Code Message +-Warning 4185 MariaDB tried to use the BZip2 compression, but its provider plugin is not loaded ++Warning 4185 MariaDB tried to use the LZO compression, but its provider plugin is not loaded + Error 1932 Table 'test.t1' doesn't exist in engine drop table t1; # restart diff --git a/mysql-test/suite/plugins/r/compression,innodb-snappy.rdiff b/mysql-test/suite/plugins/r/compression,innodb-snappy.rdiff index e9c7485d118..98c4427a758 100644 --- a/mysql-test/suite/plugins/r/compression,innodb-snappy.rdiff +++ b/mysql-test/suite/plugins/r/compression,innodb-snappy.rdiff @@ -10,15 +10,19 @@ +set global innodb_compression_algorithm = snappy; call mtr.add_suppression("Background Page read failed to read, uncompress, or decrypt"); call mtr.add_suppression("Table is compressed or encrypted but uncompress or decrypt failed"); - call mtr.add_suppression("Table .*t1.* is compressed with (\\w+), which is not currently loaded. Please load the \\1 provider plugin to open the table"); -@@ -15,8 +15,8 @@ + call mtr.add_suppression("Table `test`.`t1` is corrupted. Please drop the table and recreate"); +@@ -16,12 +16,12 @@ 0 abcabcabc 300 1 defdefdef 3000 2 ghighighi 30000 -# restart: --disable-provider-bzip2 +# restart: --disable-provider-snappy select a, left(b, 9), length(b) from t1; --ERROR HY000: Table test/t1 is compressed with bzip2, which is not currently loaded. Please load the bzip2 provider plugin to open the table -+ERROR HY000: Table test/t1 is compressed with snappy, which is not currently loaded. Please load the snappy provider plugin to open the table + ERROR 42S02: Table 'test.t1' doesn't exist in engine + show warnings; + Level Code Message +-Warning 4185 MariaDB tried to use the BZip2 compression, but its provider plugin is not loaded ++Warning 4185 MariaDB tried to use the Snappy compression, but its provider plugin is not loaded + Error 1932 Table 'test.t1' doesn't exist in engine drop table t1; # restart diff --git a/mysql-test/suite/plugins/r/compression,mroonga-lz4.rdiff b/mysql-test/suite/plugins/r/compression,mroonga-lz4.rdiff index 9b155ff3a1d..ac186d3c566 100644 --- a/mysql-test/suite/plugins/r/compression,mroonga-lz4.rdiff +++ b/mysql-test/suite/plugins/r/compression,mroonga-lz4.rdiff @@ -1,6 +1,6 @@ --- suite/plugins/r/compression.result +++ suite/plugins/r/compression.reject -@@ -1,12 +1,8 @@ +@@ -1,13 +1,8 @@ # -# Testing bzip2 compression provider with innodb +# Testing lz4 compression provider with mroonga @@ -9,20 +9,25 @@ -set global innodb_compression_algorithm = bzip2; -call mtr.add_suppression("Background Page read failed to read, uncompress, or decrypt"); -call mtr.add_suppression("Table is compressed or encrypted but uncompress or decrypt failed"); +-call mtr.add_suppression("Table `test`.`t1` is corrupted. Please drop the table and recreate"); -call mtr.add_suppression("Table .*t1.* is compressed with (\\w+), which is not currently loaded. Please load the \\1 provider plugin to open the table"); -create table t1 (a int, b text ) engine = innodb page_compressed = 1; +create table t1 (a int, b text COMMENT 'FLAGS "COLUMN_SCALAR|COMPRESS_LZ4"') engine = mroonga charset = utf8; insert t1 (a, b) values (0, repeat("abc", 100)); insert t1 (a, b) values (1, repeat("def", 1000)); insert t1 (a, b) values (2, repeat("ghi", 10000)); -@@ -14,8 +11,20 @@ +@@ -16,12 +11,20 @@ 0 abcabcabc 300 1 defdefdef 3000 2 ghighighi 30000 -# restart: --disable-provider-bzip2 +# restart: --disable-provider-lz4 select a, left(b, 9), length(b) from t1; --ERROR HY000: Table test/t1 is compressed with bzip2, which is not currently loaded. Please load the bzip2 provider plugin to open the table +-ERROR 42S02: Table 'test.t1' doesn't exist in engine +-show warnings; +-Level Code Message +-Warning 4185 MariaDB tried to use the BZip2 compression, but its provider plugin is not loaded +-Error 1932 Table 'test.t1' doesn't exist in engine +a left(b, 9) length(b) +0 0 +1 0 diff --git a/mysql-test/suite/plugins/r/compression.result b/mysql-test/suite/plugins/r/compression.result index dd267f282c5..d7c11abc95b 100644 --- a/mysql-test/suite/plugins/r/compression.result +++ b/mysql-test/suite/plugins/r/compression.result @@ -5,6 +5,7 @@ call mtr.add_suppression("MariaDB tried to use the .+ compression, but its provi set global innodb_compression_algorithm = bzip2; call mtr.add_suppression("Background Page read failed to read, uncompress, or decrypt"); call mtr.add_suppression("Table is compressed or encrypted but uncompress or decrypt failed"); +call mtr.add_suppression("Table `test`.`t1` is corrupted. Please drop the table and recreate"); call mtr.add_suppression("Table .*t1.* is compressed with (\\w+), which is not currently loaded. Please load the \\1 provider plugin to open the table"); create table t1 (a int, b text ) engine = innodb page_compressed = 1; insert t1 (a, b) values (0, repeat("abc", 100)); @@ -17,6 +18,10 @@ a left(b, 9) length(b) 2 ghighighi 30000 # restart: --disable-provider-bzip2 select a, left(b, 9), length(b) from t1; -ERROR HY000: Table test/t1 is compressed with bzip2, which is not currently loaded. Please load the bzip2 provider plugin to open the table +ERROR 42S02: Table 'test.t1' doesn't exist in engine +show warnings; +Level Code Message +Warning 4185 MariaDB tried to use the BZip2 compression, but its provider plugin is not loaded +Error 1932 Table 'test.t1' doesn't exist in engine drop table t1; # restart diff --git a/mysql-test/suite/plugins/t/compression.combinations b/mysql-test/suite/plugins/t/compression.combinations index 645ca60e5f0..17ea9e8244f 100644 --- a/mysql-test/suite/plugins/t/compression.combinations +++ b/mysql-test/suite/plugins/t/compression.combinations @@ -1,25 +1,30 @@ [innodb-bzip2] innodb +innodb-fast-shutdown=0 plugin-load-add=$PROVIDER_BZIP2_SO loose-provider-bzip2 [innodb-lz4] innodb +innodb-fast-shutdown=0 plugin-load-add=$PROVIDER_LZ4_SO loose-provider-lz4 [innodb-lzma] innodb +innodb-fast-shutdown=0 plugin-load-add=$PROVIDER_LZMA_SO loose-provider-lzma [innodb-lzo] innodb +innodb-fast-shutdown=0 plugin-load-add=$PROVIDER_LZO_SO loose-provider-lzo [innodb-snappy] innodb +innodb-fast-shutdown=0 plugin-load-add=$PROVIDER_SNAPPY_SO loose-provider-snappy diff --git a/mysql-test/suite/plugins/t/compression.test b/mysql-test/suite/plugins/t/compression.test index c97c5725e1d..df892acfdc4 100644 --- a/mysql-test/suite/plugins/t/compression.test +++ b/mysql-test/suite/plugins/t/compression.test @@ -21,6 +21,7 @@ if ($engine == "innodb") { let $table_params = page_compressed = 1; call mtr.add_suppression("Background Page read failed to read, uncompress, or decrypt"); call mtr.add_suppression("Table is compressed or encrypted but uncompress or decrypt failed"); + call mtr.add_suppression("Table `test`.`t1` is corrupted. Please drop the table and recreate"); call mtr.add_suppression("Table .*t1.* is compressed with (\\w+), which is not currently loaded. Please load the \\1 provider plugin to open the table"); } if ($engine == "mroonga") { @@ -39,8 +40,9 @@ let $restart_parameters = --disable-provider-$alg; source include/restart_mysqld.inc; if ($engine == "innodb") { - error ER_PROVIDER_NOT_LOADED; + error ER_NO_SUCH_TABLE_IN_ENGINE; select a, left(b, 9), length(b) from t1; + show warnings; } if ($engine == "mroonga"){ select a, left(b, 9), length(b) from t1; From c17aca2f11c21ed53c7f0ce5f0cb39403e20feb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Dec 2023 15:01:50 +0200 Subject: [PATCH 442/477] MDEV-18322 Assertion "wrong page type" on instant ALTER TABLE row_ins_clust_index_entry_low(): Invoke btr_set_instant() in the same mini-transaction that has successfully inserted the metadata record. In this way, if inserting the metadata record fails before any undo log record was written for it, the index root page will remain consistent. innobase_instant_try(): Remove the btr_set_instant() call. Reviewed by: Thirunarayanan Balathandayuthapani Tested by: Matthias Leich --- .../suite/innodb/r/instant_alter_bugs.result | 24 ++++++++++++++++++ .../suite/innodb/t/instant_alter_bugs.test | 25 +++++++++++++++++++ storage/innobase/handler/handler0alter.cc | 4 --- storage/innobase/row/row0ins.cc | 20 ++++++++++----- 4 files changed, 63 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/innodb/r/instant_alter_bugs.result b/mysql-test/suite/innodb/r/instant_alter_bugs.result index 92c27a35bd4..ded6cc671ef 100644 --- a/mysql-test/suite/innodb/r/instant_alter_bugs.result +++ b/mysql-test/suite/innodb/r/instant_alter_bugs.result @@ -495,4 +495,28 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; CREATE TABLE t1 (i int AS (0) STORED, j INT) ENGINE=InnoDB; ALTER TABLE t1 ADD COLUMN i INT GENERATED ALWAYS AS (1), DROP COLUMN i; DROP TABLE t1; +# +# MDEV-18322 Assertion "wrong_page_type" on instant ALTER +# +BEGIN NOT ATOMIC +DECLARE c TEXT +DEFAULT(SELECT CONCAT('CREATE TABLE t1 (c', +GROUP_CONCAT(seq SEPARATOR ' CHAR(200), c'), +' CHAR(211)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT') +FROM seq_1_to_40); +EXECUTE IMMEDIATE c; +END; +$$ +INSERT INTO t1 SET c1=NULL; +ALTER TABLE t1 ADD c41 INT FIRST; +ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8123. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs +ALTER TABLE t1 ADD c41 INT FIRST; +ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8123. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +DROP TABLE t1; # End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/instant_alter_bugs.test b/mysql-test/suite/innodb/t/instant_alter_bugs.test index debd5d30562..88b2549623b 100644 --- a/mysql-test/suite/innodb/t/instant_alter_bugs.test +++ b/mysql-test/suite/innodb/t/instant_alter_bugs.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/have_sequence.inc SET @save_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=1; @@ -526,4 +527,28 @@ CREATE TABLE t1 (i int AS (0) STORED, j INT) ENGINE=InnoDB; ALTER TABLE t1 ADD COLUMN i INT GENERATED ALWAYS AS (1), DROP COLUMN i; DROP TABLE t1; +--echo # +--echo # MDEV-18322 Assertion "wrong_page_type" on instant ALTER +--echo # + +DELIMITER $$; +BEGIN NOT ATOMIC + DECLARE c TEXT + DEFAULT(SELECT CONCAT('CREATE TABLE t1 (c', + GROUP_CONCAT(seq SEPARATOR ' CHAR(200), c'), + ' CHAR(211)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT') + FROM seq_1_to_40); + EXECUTE IMMEDIATE c; +END; +$$ +DELIMITER ;$$ +INSERT INTO t1 SET c1=NULL; +--error ER_TOO_BIG_ROWSIZE +ALTER TABLE t1 ADD c41 INT FIRST; +--error ER_TOO_BIG_ROWSIZE +ALTER TABLE t1 ADD c41 INT FIRST; +CHECK TABLE t1; +SELECT COUNT(*) FROM t1; +DROP TABLE t1; + --echo # End of 10.4 tests diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 74c2703218d..be02fc9e0a6 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -6130,10 +6130,6 @@ empty_table: goto err_exit; } - btr_set_instant(root, *index, &mtr); - mtr.commit(); - mtr.start(); - index->set_modified(mtr); err = row_ins_clust_index_entry_low( BTR_NO_LOCKING_FLAG, BTR_MODIFY_TREE, index, index->n_uniq, entry, 0, thr); diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 6765ba546d5..088981e5b5b 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -2657,14 +2657,17 @@ row_ins_clust_index_entry_low( ut_ad(!dict_index_is_online_ddl(index)); ut_ad(!index->table->persistent_autoinc); ut_ad(!index->is_instant()); + ut_ad(!entry->info_bits); mtr.set_log_mode(MTR_LOG_NO_REDO); } else { index->set_modified(mtr); - if (UNIV_UNLIKELY(entry->is_metadata())) { + if (UNIV_UNLIKELY(entry->info_bits != 0)) { + ut_ad(entry->is_metadata()); ut_ad(index->is_instant()); ut_ad(!dict_index_is_online_ddl(index)); ut_ad(mode == BTR_MODIFY_TREE); + ut_ad(flags == BTR_NO_LOCKING_FLAG); } else { if (mode == BTR_MODIFY_LEAF && dict_index_is_online_ddl(index)) { @@ -2716,11 +2719,6 @@ row_ins_clust_index_entry_low( #endif /* UNIV_DEBUG */ if (UNIV_UNLIKELY(entry->info_bits != 0)) { - ut_ad(entry->is_metadata()); - ut_ad(flags == BTR_NO_LOCKING_FLAG); - ut_ad(index->is_instant()); - ut_ad(!dict_index_is_online_ddl(index)); - const rec_t* rec = btr_cur_get_rec(cursor); if (rec_get_info_bits(rec, page_rec_is_comp(rec)) @@ -2830,7 +2828,17 @@ do_insert: } } + if (err == DB_SUCCESS && entry->info_bits) { + if (buf_block_t* root + = btr_root_block_get(index, RW_X_LATCH, &mtr)) { + btr_set_instant(root, *index, &mtr); + } else { + ut_ad("cannot find root page" == 0); + } + } + if (big_rec != NULL) { + ut_ad(err == DB_SUCCESS); mtr_commit(&mtr); /* Online table rebuild could read (and From b545f72ddca68e5f08b492603e2e086962a3431d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 15 Nov 2023 22:38:27 +0100 Subject: [PATCH 443/477] cleanup: rpl.rpl_invoked_features --- .../suite/rpl/r/rpl_invoked_features.result | 32 +++---- .../suite/rpl/t/rpl_invoked_features.test | 89 +++++-------------- 2 files changed, 32 insertions(+), 89 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_invoked_features.result b/mysql-test/suite/rpl/r/rpl_invoked_features.result index 43a8e8625de..7f632844976 100644 --- a/mysql-test/suite/rpl/r/rpl_invoked_features.result +++ b/mysql-test/suite/rpl/r/rpl_invoked_features.result @@ -1,15 +1,7 @@ include/master-slave.inc [connection master] -USE test; -DROP VIEW IF EXISTS v1,v11; -DROP TABLE IF EXISTS t1,t2,t3,t11,t12,t13; -DROP PROCEDURE IF EXISTS p1; -DROP PROCEDURE IF EXISTS p11; -DROP FUNCTION IF EXISTS f1; -DROP FUNCTION IF EXISTS f2; -DROP EVENT IF EXISTS e1; -DROP EVENT IF EXISTS e11; - +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +# Create tables CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, c VARCHAR(64)) ENGINE=myisam; INSERT INTO t1 VALUES (1,1,'1'); INSERT INTO t1 VALUES (2,2,UUID()); @@ -22,7 +14,7 @@ INSERT INTO t11 VALUES (2,2,UUID()); CREATE TABLE t12 (a INT UNIQUE, b INT, c VARCHAR(64)) ENGINE=innodb; INSERT INTO t12 VALUES (1,1,'1'); INSERT INTO t12 VALUES (2,2,UUID()); - +# Create invoked features CREATE VIEW v1 AS SELECT * FROM t1; CREATE VIEW v11 AS SELECT * FROM t11; CREATE TRIGGER t1_tr1 BEFORE INSERT ON t1 FOR EACH ROW @@ -78,7 +70,7 @@ CREATE PROCEDURE p11 (IN x INT, IN y VARCHAR(64)) BEGIN INSERT IGNORE INTO t11 VALUES (x,x,y); END| - +# Do some actions for non-transactional tables CREATE TABLE t3 SELECT * FROM v1; INSERT INTO t1 VALUES (3,3,''); UPDATE t1 SET c='2' WHERE a = 1; @@ -90,7 +82,7 @@ INSERT INTO t1 VALUES(6,6,f1(6)); INSERT INTO t1 VALUES (102,102,''); INSERT INTO t1 VALUES(7,7,f2(7)); INSERT INTO t1 VALUES (103,103,''); - +# Do some actions for transactional tables CREATE TABLE t13 SELECT * FROM v11; INSERT INTO t11 VALUES (3,3,''); UPDATE t11 SET c='2' WHERE a = 1; @@ -102,12 +94,12 @@ INSERT INTO t11 VALUES(6,6,f1(6)); INSERT INTO t11 VALUES (102,102,''); INSERT INTO t11 VALUES(7,7,f2(7)); INSERT INTO t11 VALUES (103,103,''); - +# Scheduler is on SET GLOBAL EVENT_SCHEDULER = on; ALTER EVENT e1 ENABLE; ALTER EVENT e11 ENABLE; SET GLOBAL EVENT_SCHEDULER = off; - +# Check original objects SHOW TABLES LIKE 't%'; Tables_in_test (t%) t1 @@ -268,7 +260,7 @@ a b 102 102 103 103 connection slave; - +# Check replicated objects SHOW TABLES LIKE 't%'; Tables_in_test (t%) t1 @@ -297,7 +289,7 @@ SELECT event_name, status FROM information_schema.events WHERE event_schema='tes event_name status e1 SLAVESIDE_DISABLED e11 SLAVESIDE_DISABLED - +# Check replicated data SELECT COUNT(*) FROM t1; COUNT(*) 12 @@ -429,7 +421,7 @@ a b 102 102 103 103 connection master; - +# Remove UUID() before comparing and sort tables UPDATE t1 SET c=''; UPDATE t2 SET c=''; UPDATE t3 SET c=''; @@ -439,10 +431,8 @@ UPDATE t13 SET c=''; ALTER TABLE t3 ORDER BY a; ALTER TABLE t13 ORDER BY a; connection slave; - - +# Compare a data from master and slave connection master; - DROP VIEW IF EXISTS v1,v11; DROP TABLE IF EXISTS t1,t2,t3,t11,t12,t13; DROP PROCEDURE IF EXISTS p1; diff --git a/mysql-test/suite/rpl/t/rpl_invoked_features.test b/mysql-test/suite/rpl/t/rpl_invoked_features.test index 91391cf8372..8c04e6fae68 100644 --- a/mysql-test/suite/rpl/t/rpl_invoked_features.test +++ b/mysql-test/suite/rpl/t/rpl_invoked_features.test @@ -8,9 +8,7 @@ --source include/have_innodb.inc --source include/master-slave.inc -disable_query_log; call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); -enable_query_log; # --disable_warnings/--enable_warnings added before/after query # if one uses UUID() function because we need to avoid warnings @@ -22,60 +20,35 @@ enable_query_log; # Transactional engine --let $engine_type2= innodb - -# -# Clean up -# - -USE test; ---disable_warnings -DROP VIEW IF EXISTS v1,v11; -DROP TABLE IF EXISTS t1,t2,t3,t11,t12,t13; -DROP PROCEDURE IF EXISTS p1; -DROP PROCEDURE IF EXISTS p11; -DROP FUNCTION IF EXISTS f1; -DROP FUNCTION IF EXISTS f2; -DROP EVENT IF EXISTS e1; -DROP EVENT IF EXISTS e11; ---enable_warnings - - # # Prepare objects (tables etc) # -# Create tables +--echo # Create tables ---echo eval CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, c VARCHAR(64)) ENGINE=$engine_type; INSERT INTO t1 VALUES (1,1,'1'); ---disable_warnings +--disable_warnings ONCE INSERT INTO t1 VALUES (2,2,UUID()); ---enable_warnings eval CREATE TABLE t2 (a INT UNIQUE, b INT, c VARCHAR(64)) ENGINE=$engine_type; INSERT INTO t2 VALUES (1,1,'1'); ---disable_warnings +--disable_warnings ONCE INSERT INTO t2 VALUES (2,2,UUID()); ---enable_warnings eval CREATE TABLE t11 (a INT NOT NULL PRIMARY KEY, b INT, c VARCHAR(64)) ENGINE=$engine_type2; INSERT INTO t11 VALUES (1,1,'1'); ---disable_warnings +--disable_warnings ONCE INSERT INTO t11 VALUES (2,2,UUID()); ---enable_warnings eval CREATE TABLE t12 (a INT UNIQUE, b INT, c VARCHAR(64)) ENGINE=$engine_type2; INSERT INTO t12 VALUES (1,1,'1'); ---disable_warnings +--disable_warnings ONCE INSERT INTO t12 VALUES (2,2,UUID()); ---enable_warnings -# Create invoked features ---echo -# Create view for tables t1,t11 +--echo # Create invoked features + CREATE VIEW v1 AS SELECT * FROM t1; CREATE VIEW v11 AS SELECT * FROM t11; -# Create triggers for t1,t11 DELIMITER |; CREATE TRIGGER t1_tr1 BEFORE INSERT ON t1 FOR EACH ROW @@ -102,7 +75,6 @@ BEGIN UPDATE t13 SET c = ''; END| -# Create events which will run every 1 sec CREATE EVENT e1 ON SCHEDULE EVERY 1 SECOND DISABLE DO BEGIN ALTER EVENT e1 DISABLE; @@ -115,7 +87,6 @@ BEGIN CALL p11(10, ''); END| -# Create functions and procedures used for events CREATE FUNCTION f1 (x INT) RETURNS VARCHAR(64) BEGIN IF x > 5 THEN @@ -146,46 +117,39 @@ DELIMITER ;| # Start test case # -# Do some actions for non-transactional tables ---echo +--echo # Do some actions for non-transactional tables CREATE TABLE t3 SELECT * FROM v1; INSERT INTO t1 VALUES (3,3,''); UPDATE t1 SET c='2' WHERE a = 1; ---disable_warnings +--disable_warnings ONCE INSERT INTO t1 VALUES(4,4,f1(4)); ---enable_warnings INSERT INTO t1 VALUES (100,100,''); ---disable_warnings CALL p1(5, UUID()); ---enable_warnings INSERT INTO t1 VALUES (101,101,''); ---disable_warnings +--disable_warnings ONCE INSERT INTO t1 VALUES(6,6,f1(6)); ---enable_warnings INSERT INTO t1 VALUES (102,102,''); ---disable_warnings +--disable_warnings ONCE INSERT INTO t1 VALUES(7,7,f2(7)); ---enable_warnings INSERT INTO t1 VALUES (103,103,''); -# Do some actions for transactional tables ---echo ---disable_warnings +--echo # Do some actions for transactional tables CREATE TABLE t13 SELECT * FROM v11; INSERT INTO t11 VALUES (3,3,''); UPDATE t11 SET c='2' WHERE a = 1; +--disable_warnings ONCE INSERT INTO t11 VALUES(4,4,f1(4)); INSERT INTO t11 VALUES (100,100,''); CALL p11(5, UUID()); INSERT INTO t11 VALUES (101,101,''); +--disable_warnings ONCE INSERT INTO t11 VALUES(6,6,f1(6)); INSERT INTO t11 VALUES (102,102,''); +--disable_warnings ONCE INSERT INTO t11 VALUES(7,7,f2(7)); INSERT INTO t11 VALUES (103,103,''); ---enable_warnings -# Scheduler is on ---echo +--echo # Scheduler is on # Temporally events fire sequentally due Bug#29020. SET GLOBAL EVENT_SCHEDULER = on; # Wait while events will executed @@ -197,8 +161,7 @@ let $wait_condition= SELECT COUNT(*) = 1 FROM t11 WHERE t11.a = 10; --source include/wait_condition.inc SET GLOBAL EVENT_SCHEDULER = off; -# Check original objects ---echo +--echo # Check original objects --sorted_result SHOW TABLES LIKE 't%'; --sorted_result @@ -229,8 +192,7 @@ SELECT a,b FROM v11 ORDER BY a; --sync_slave_with_master slave -# Check replicated objects ---echo +--echo # Check replicated objects --sorted_result SHOW TABLES LIKE 't%'; --sorted_result @@ -242,8 +204,7 @@ SELECT routine_type, routine_name FROM information_schema.routines WHERE routine --sorted_result SELECT event_name, status FROM information_schema.events WHERE event_schema='test'; -# Check replicated data ---echo +--echo # Check replicated data SELECT COUNT(*) FROM t1; SELECT a,b FROM t1 ORDER BY a; SELECT COUNT(*) FROM t2; @@ -259,10 +220,8 @@ SELECT COUNT(*) FROM t13; SELECT a,b FROM t13 ORDER BY a; SELECT a,b FROM v11 ORDER BY a; -# Remove UUID() before comparing and sort tables - --connection master ---echo +--echo # Remove UUID() before comparing and sort tables UPDATE t1 SET c=''; UPDATE t2 SET c=''; UPDATE t3 SET c=''; @@ -277,25 +236,19 @@ ALTER TABLE t13 ORDER BY a; --sync_slave_with_master slave -# Compare a data from master and slave ---echo +--echo # Compare a data from master and slave --exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_master.sql --exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_slave.sql --diff_files $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_master.sql $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_slave.sql - # # Clean up # -# Remove dumps ---echo --remove_file $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_master.sql --remove_file $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_slave.sql -# Remove tables,views,procedures,functions --connection master ---echo DROP VIEW IF EXISTS v1,v11; DROP TABLE IF EXISTS t1,t2,t3,t11,t12,t13; DROP PROCEDURE IF EXISTS p1; From 187cbfca7cb75ed809d809450152d2c92779f35e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 15 Nov 2023 14:17:26 +0100 Subject: [PATCH 444/477] MDEV-32810 events.events_1 fails in 11.1 and above fix test cases like ... prepare the test, create a table or a user create event ... on schedule every 1 second ... do something ... ... verify that something was done ... cleanup drop event, table or user here the event scheduler can manage to start the worker for the second execution of the event, then cleanup happens and the worker realizes that it cannot change the security context (as the user is dropped) or cannot insert (as the table is dropped). followup for 279b0db8c60 (that removed suppression of /Event Schedule/) --- mysql-test/suite/events/events_1.result | 4 ---- mysql-test/suite/events/events_1.test | 10 ++++------ mysql-test/suite/rpl/r/rpl_invoked_features.result | 1 + mysql-test/suite/rpl/t/rpl_invoked_features.test | 1 + 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/events/events_1.result b/mysql-test/suite/events/events_1.result index 24f3aa35b56..2db478ad040 100644 --- a/mysql-test/suite/events/events_1.result +++ b/mysql-test/suite/events/events_1.result @@ -2,10 +2,6 @@ set sql_mode=""; call mtr.add_suppression("Column count of mysql.event is wrong. Expected .*, found .*\. The table is probably corrupted"); call mtr.add_suppression("Incorrect definition of table mysql.event:.*"); call mtr.add_suppression("Event Scheduler: .* DROP command denied to user"); -drop database if exists events_test; -drop database if exists db_x; -drop database if exists mysqltest_db2; -drop database if exists mysqltest_no_such_database; create database events_test; use events_test; CREATE USER pauline@localhost; diff --git a/mysql-test/suite/events/events_1.test b/mysql-test/suite/events/events_1.test index 63b0c50909f..cace9eb349d 100644 --- a/mysql-test/suite/events/events_1.test +++ b/mysql-test/suite/events/events_1.test @@ -11,12 +11,6 @@ call mtr.add_suppression("Column count of mysql.event is wrong. Expected .*, fou call mtr.add_suppression("Incorrect definition of table mysql.event:.*"); call mtr.add_suppression("Event Scheduler: .* DROP command denied to user"); ---disable_warnings -drop database if exists events_test; -drop database if exists db_x; -drop database if exists mysqltest_db2; -drop database if exists mysqltest_no_such_database; ---enable_warnings create database events_test; use events_test; @@ -44,6 +38,8 @@ DROP EVENT e_x1; DROP EVENT e_x2; disconnect priv_conn; connection default; +let $wait_condition= SELECT count(*)=1 from information_schema.processlist; +--source include/wait_condition.inc DROP DATABASE db_x; DROP USER pauline@localhost; USE events_test; @@ -103,6 +99,8 @@ delimiter ;| set global event_scheduler = on; let $wait_condition= SELECT count(*)>0 from mysql.event where name='e_43' and interval_value= 5; --source include/wait_condition.inc +let $wait_condition= SELECT count(*)=2 from information_schema.processlist; +--source include/wait_condition.inc select db, name, body, status, interval_field, interval_value from mysql.event; drop event e_43; drop table test_nested; diff --git a/mysql-test/suite/rpl/r/rpl_invoked_features.result b/mysql-test/suite/rpl/r/rpl_invoked_features.result index 7f632844976..2835ecb3df7 100644 --- a/mysql-test/suite/rpl/r/rpl_invoked_features.result +++ b/mysql-test/suite/rpl/r/rpl_invoked_features.result @@ -1,6 +1,7 @@ include/master-slave.inc [connection master] call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +call mtr.add_suppression("Event Scheduler: .* Duplicate entry '10' for key 'a'"); # Create tables CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, c VARCHAR(64)) ENGINE=myisam; INSERT INTO t1 VALUES (1,1,'1'); diff --git a/mysql-test/suite/rpl/t/rpl_invoked_features.test b/mysql-test/suite/rpl/t/rpl_invoked_features.test index 8c04e6fae68..514329a566d 100644 --- a/mysql-test/suite/rpl/t/rpl_invoked_features.test +++ b/mysql-test/suite/rpl/t/rpl_invoked_features.test @@ -9,6 +9,7 @@ --source include/master-slave.inc call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +call mtr.add_suppression("Event Scheduler: .* Duplicate entry '10' for key 'a'"); # --disable_warnings/--enable_warnings added before/after query # if one uses UUID() function because we need to avoid warnings From b4712242dd6d2a50ebe3eb01d22a076820c6a65e Mon Sep 17 00:00:00 2001 From: Rex Date: Wed, 11 Oct 2023 15:05:58 +1200 Subject: [PATCH 445/477] MDEV-31279 Crash when lateral derived is guaranteed to return no rows Consider this query SELECT t1.* FROM t1, (SELECT t2.b FROM t2 WHERE NOT EXISTS (SELECT 1 FROM t3) GROUP BY b) sq where sq.b = t1.a; If SELECT 1 FROM t3 is expensive, for example t3 has > thd->variables.expensive_subquery_limit, first evaluation is deferred to mysql_derived_fill(). There it is noted that, in the above case NOT EXISTS (SELECT 1 FROM t3) is constant and false. This causes the join variable zero_result_cause to be set to "Impossible WHERE noticed after reading const tables" and the handler for this join is never "opened" via handler::ha_open. When mysql_derived_fill() is called for the next group of results, this unopened handler is not taken into account. reviewed by Igor Babaev (igor@mariadb.com) --- mysql-test/main/derived_split_innodb.result | 15 +++++++++++++++ mysql-test/main/derived_split_innodb.test | 18 ++++++++++++++++++ sql/sql_derived.cc | 3 +++ 3 files changed, 36 insertions(+) diff --git a/mysql-test/main/derived_split_innodb.result b/mysql-test/main/derived_split_innodb.result index 22974251c56..91241627b73 100644 --- a/mysql-test/main/derived_split_innodb.result +++ b/mysql-test/main/derived_split_innodb.result @@ -826,4 +826,19 @@ SELECT * FROM t1 JOIN t2 WHERE (t1.a, t2.b) IN (SELECT * FROM v); a b DROP VIEW v; DROP TABLE t1, t2, t3; +# +# MDEV-31279 Crash when lateral derived is guaranteed to return no rows +# +CREATE TABLE t1 (a CHAR(1)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('1'),('2'); +CREATE TABLE t2 (b INT, KEY(b)) ENGINE=MyISAM; +ALTER TABLE t2 DISABLE KEYS; +INSERT INTO t2 VALUES (1),(2),(3); +ALTER TABLE t2 ENABLE KEYS; +CREATE TABLE t3 (c INT) ENGINE=MyISAM; +INSERT INTO t3 (c) SELECT seq FROM seq_1_to_101; +SELECT * FROM t1 WHERE t1.a IN (SELECT b FROM +(SELECT t2.b FROM t2 WHERE NOT EXISTS (SELECT 1 FROM t3) GROUP BY b) sq); +a +DROP TABLE t1, t2, t3; # End of 10.4 tests diff --git a/mysql-test/main/derived_split_innodb.test b/mysql-test/main/derived_split_innodb.test index 3c51f54fe02..e2f41a17994 100644 --- a/mysql-test/main/derived_split_innodb.test +++ b/mysql-test/main/derived_split_innodb.test @@ -483,4 +483,22 @@ SELECT * FROM t1 JOIN t2 WHERE (t1.a, t2.b) IN (SELECT * FROM v); DROP VIEW v; DROP TABLE t1, t2, t3; +--echo # +--echo # MDEV-31279 Crash when lateral derived is guaranteed to return no rows +--echo # + +CREATE TABLE t1 (a CHAR(1)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('1'),('2'); +CREATE TABLE t2 (b INT, KEY(b)) ENGINE=MyISAM; +ALTER TABLE t2 DISABLE KEYS; +INSERT INTO t2 VALUES (1),(2),(3); +ALTER TABLE t2 ENABLE KEYS; +CREATE TABLE t3 (c INT) ENGINE=MyISAM; +INSERT INTO t3 (c) SELECT seq FROM seq_1_to_101; + +SELECT * FROM t1 WHERE t1.a IN (SELECT b FROM + (SELECT t2.b FROM t2 WHERE NOT EXISTS (SELECT 1 FROM t3) GROUP BY b) sq); + +DROP TABLE t1, t2, t3; + --echo # End of 10.4 tests diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 54ef1c3a59f..782894444df 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1227,6 +1227,9 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) goto err; JOIN *join= unit->first_select()->join; join->first_record= false; + if (join->zero_result_cause) + goto err; + for (uint i= join->top_join_tab_count; i < join->top_join_tab_count + join->aggr_tables; i++) From 2c60d43d7df134c3875b3760a5d54ac72da01f5f Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 13 Dec 2023 16:24:34 +1100 Subject: [PATCH 446/477] MDEV-33006 Missing required privilege CONNECTION ADMIN opt_kill_long_query_type being an enum could be 0 corresponding to ALL. When ALL is specified, the CONNECTION ADMIN is still required. Also check REPLICA MONITOR privilege and make the tests find the results by recording stderr. Noticed thanks to bug report by Tim van Dijen. Fixes: 79b58f1ca893b8affc5075d0a548563d376cd481 --- extra/mariabackup/xtrabackup.cc | 4 ++-- .../suite/mariabackup/backup_grants.result | 5 ++-- .../suite/mariabackup/backup_grants.test | 23 +++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index fc977d98050..54dabd826b1 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -6403,7 +6403,7 @@ static bool check_all_privileges() } /* KILL ... */ - if (!opt_no_lock && (opt_kill_long_queries_timeout || opt_kill_long_query_type)) { + if (!opt_no_lock && opt_kill_long_queries_timeout) { check_result |= check_privilege( granted_privileges, "CONNECTION ADMIN", "*", "*", @@ -6424,7 +6424,7 @@ static bool check_all_privileges() if (opt_galera_info || opt_slave_info || opt_safe_slave_backup) { check_result |= check_privilege(granted_privileges, - "SLAVE MONITOR", "*", "*", + "REPLICA MONITOR", "*", "*", PRIVILEGE_WARNING); } diff --git a/mysql-test/suite/mariabackup/backup_grants.result b/mysql-test/suite/mariabackup/backup_grants.result index 56899f8d9c0..6bd6c9f42cd 100644 --- a/mysql-test/suite/mariabackup/backup_grants.result +++ b/mysql-test/suite/mariabackup/backup_grants.result @@ -3,12 +3,13 @@ FOUND 1 /missing required privilege RELOAD/ in backup.log FOUND 1 /missing required privilege PROCESS/ in backup.log FOUND 1 /GRANT USAGE ON/ in backup.log GRANT RELOAD, PROCESS on *.* to backup@localhost; -NOT FOUND /missing required privilege REPLICA MONITOR/ in backup.log +FOUND 1 /missing required privilege REPLICA MONITOR/ in backup.log GRANT REPLICA MONITOR ON *.* TO backup@localhost; REVOKE REPLICA MONITOR ON *.* FROM backup@localhost; +FOUND 1 /missing required privilege CONNECTION ADMIN/ in backup.log GRANT CONNECTION ADMIN ON *.* TO backup@localhost; FOUND 1 /missing required privilege REPLICATION SLAVE ADMIN/ in backup.log -NOT FOUND /missing required privilege REPLICA MONITOR/ in backup.log +FOUND 1 /missing required privilege REPLICA MONITOR/ in backup.log GRANT REPLICATION SLAVE ADMIN ON *.* TO backup@localhost; GRANT REPLICA MONITOR ON *.* TO backup@localhost; DROP USER backup@localhost; diff --git a/mysql-test/suite/mariabackup/backup_grants.test b/mysql-test/suite/mariabackup/backup_grants.test index 894ae73aeb9..18db3489a94 100644 --- a/mysql-test/suite/mariabackup/backup_grants.test +++ b/mysql-test/suite/mariabackup/backup_grants.test @@ -10,7 +10,7 @@ rmdir $targetdir; # backup fails without --no-lock, because of FTWRL --disable_result_log error 1; -exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log 2>&1; --enable_result_log let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/backup.log; @@ -31,7 +31,7 @@ rmdir $targetdir; # --slave-info and galera info require REPLICA MONITOR --disable_result_log error 1; -exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup --slave-info --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup --slave-info --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log 2>&1; --enable_result_log rmdir $targetdir; @@ -47,16 +47,15 @@ REVOKE REPLICA MONITOR ON *.* FROM backup@localhost; # TODO need a query that would delay a BACKUP STAGE START/ BACKUP STAGE BLOCK_COMMIT longer than the kill-long-queries-timeout #--send SELECT SLEEP(9) kill_me -## kill-long-query-type=(not empty) requires CONNECTION ADMIN -#--disable_result_log -#error 1; -#--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup --kill-long-query-type=all --kill-long-queries-timeout=4 --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log; -#--reap -#--enable_result_log -#rmdir $targetdir; -# -#--let SEARCH_PATTERN= missing required privilege CONNECTION ADMIN -#--source include/search_pattern_in_file.inc + +# kill-long-query-type=(not empty) requires CONNECTION ADMIN +--disable_result_log +--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup --kill-long-query-type=ALL --kill-long-queries-timeout=4 --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log 2>&1; +--enable_result_log +rmdir $targetdir; + +--let SEARCH_PATTERN= missing required privilege CONNECTION ADMIN +--source include/search_pattern_in_file.inc GRANT CONNECTION ADMIN ON *.* TO backup@localhost; --disable_result_log From 852e1383e305d5b88e62b7246a914ee1e16e4b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Dec 2023 15:40:29 +0200 Subject: [PATCH 447/477] MDEV-21245 InnoDB: Using a partial-field key prefix in search ha_innobase::compare_key_parts(): If a full column index is being replaced with a column prefix index, return Compare_keys::NotEqual. --- .../r/innodb_prefix_index_restart_server.result | 16 ++++++++++++++++ .../t/innodb_prefix_index_restart_server.test | 14 ++++++++++++++ storage/innobase/handler/ha_innodb.cc | 4 ++++ 3 files changed, 34 insertions(+) diff --git a/mysql-test/suite/innodb/r/innodb_prefix_index_restart_server.result b/mysql-test/suite/innodb/r/innodb_prefix_index_restart_server.result index 1e97c21c253..1ccf79e4517 100644 --- a/mysql-test/suite/innodb/r/innodb_prefix_index_restart_server.result +++ b/mysql-test/suite/innodb/r/innodb_prefix_index_restart_server.result @@ -90,3 +90,19 @@ worklog5743; col_1_text = REPEAT("a", 3500) col_2_text = REPEAT("o", 3500) 1 1 DROP TABLE worklog5743; +# +# MDEV-21245 InnoDB: Using a partial-field key prefix in search +# +CREATE TABLE t1 (a VARCHAR(255), KEY k(a)) DEFAULT CHARSET=utf8mb3 +ENGINE=InnoDB; +INSERT INTO t1 set a=''; +alter table t1 change a a varchar(3000); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 1 +Warnings: +Note 1071 Specified key was too long; max key length is 3072 bytes +SELECT * FROM t1 WHERE a IN (''); +a + +DROP TABLE t1; +# End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/innodb_prefix_index_restart_server.test b/mysql-test/suite/innodb/t/innodb_prefix_index_restart_server.test index 1fb7c6d0f77..fa93e95c642 100644 --- a/mysql-test/suite/innodb/t/innodb_prefix_index_restart_server.test +++ b/mysql-test/suite/innodb/t/innodb_prefix_index_restart_server.test @@ -93,3 +93,17 @@ SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM worklog5743; DROP TABLE worklog5743; + +--echo # +--echo # MDEV-21245 InnoDB: Using a partial-field key prefix in search +--echo # +CREATE TABLE t1 (a VARCHAR(255), KEY k(a)) DEFAULT CHARSET=utf8mb3 +ENGINE=InnoDB; +INSERT INTO t1 set a=''; +--enable_info +alter table t1 change a a varchar(3000); +--disable_info +SELECT * FROM t1 WHERE a IN (''); +DROP TABLE t1; + +--echo # End of 10.4 tests diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 086f30e119e..4c27a70a0f3 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -21199,6 +21199,10 @@ Compare_keys ha_innobase::compare_key_parts( if (old_part.length >= new_part.length) return Compare_keys::NotEqual; + if (old_part.length == old_field.key_length() && + new_part.length != new_field.key_length) + return Compare_keys::NotEqual; + return Compare_keys::EqualButKeyPartLength; } From 0f510d8b5a0089814edbadeebd68a1b83f8db9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 14 Dec 2023 13:15:51 +0200 Subject: [PATCH 448/477] MDEV-32751 fixup: cmake -DPLUGIN_PERFSCHEMA=NO --- mysql-test/main/ssl.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/main/ssl.test b/mysql-test/main/ssl.test index a3a978f1001..642af380be9 100644 --- a/mysql-test/main/ssl.test +++ b/mysql-test/main/ssl.test @@ -10,6 +10,7 @@ --source include/count_sessions.inc --source include/default_charset.inc +--source include/have_perfschema.inc connect (ssl_con,localhost,root,,,,,SSL); From f21a6cbf6ee720b35cf3be011dbc4725ad99a5bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 14 Dec 2023 13:16:28 +0200 Subject: [PATCH 449/477] MDEV-32939 If tables are frequently created, renamed, dropped, a backup cannot be restored During mariadb-backup --backup, a table could be renamed, created and dropped. We could have both oldname.ibd and oldname.new, and one of the files would be deleted before the InnoDB recovery starts. The desired end result would be that we will recover both oldname.ibd and newname.ibd. During normal crash recovery, at most one file operation (create, rename, delete) may require to be replayed from the write-ahead log before the DDL recovery starts. deferred_spaces.create(): In mariadb-backup --prepare, try to create the file in case it does not exist. fil_name_process(): Display a message about not found files not only if innodb_force_recovery is set, but also in mariadb-backup --prepare. If we are processing a FILE_RENAME for a tablespace whose recovery is deferred, suppress the message and adjust the file name in case fil_ibd_load() returns FIL_LOAD_NOT_FOUND or FIL_LOAD_DEFER. fil_ibd_load(): Remove a redundant file name comparison. The caller already compared that the file names are different. We used to wrongly return FIL_LOAD_OK instead of FIL_LOAD_ID_CHANGED if only the schema name differed, such as a/t1.ibd and b/t1.ibd. Tested by: Matthias Leich Reviewed by: Thirunarayanan Balathandayuthapani --- storage/innobase/fil/fil0fil.cc | 24 ++++++---------- storage/innobase/log/log0recv.cc | 48 ++++++++++++++++++++++++++------ storage/innobase/os/os0file.cc | 39 ++++++++++++++++---------- 3 files changed, 72 insertions(+), 39 deletions(-) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 1e0b7a9c8c5..35acb78ea3b 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -2486,21 +2486,15 @@ fil_ibd_load( mysql_mutex_unlock(&fil_system.mutex); if (space) { - /* Compare the filename we are trying to open with the - filename from the first node of the tablespace we opened - previously. Fail if it is different. */ - fil_node_t* node = UT_LIST_GET_FIRST(space->chain); - if (0 != strcmp(innobase_basename(filename), - innobase_basename(node->name))) { - ib::info() - << "Ignoring data file '" << filename - << "' with space ID " << space->id - << ". Another data file called " << node->name - << " exists with the same space ID."; - space = NULL; - return(FIL_LOAD_ID_CHANGED); - } - return(FIL_LOAD_OK); + sql_print_information("InnoDB: Ignoring data file '%s'" + " with space ID " ULINTPF + ". Another data file called %s" + " exists" + " with the same space ID.", + filename, space->id, + UT_LIST_GET_FIRST(space->chain)->name); + space = NULL; + return FIL_LOAD_ID_CHANGED; } if (srv_operation == SRV_OPERATION_RESTORE) { diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index cad85b4ceca..56374f2442a 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -855,7 +855,22 @@ processed: filename= tbl_name + 1; } } - space->add(filename, OS_FILE_CLOSED, size, false, false); + pfs_os_file_t handle= OS_FILE_CLOSED; + if (srv_operation == SRV_OPERATION_RESTORE) + { + /* During mariadb-backup --backup, a table could be renamed, + created and dropped, and we may be missing the file at this + point of --prepare. Try to create the file if it does not exist + already. If the file exists, we'll pass handle=OS_FILE_CLOSED + and the file will be opened normally in fil_space_t::acquire() + inside recv_sys_t::recover_deferred(). */ + bool success; + handle= os_file_create(innodb_data_file_key, filename, + OS_FILE_CREATE | OS_FILE_ON_ERROR_NO_EXIT | + OS_FILE_ON_ERROR_SILENT, + OS_FILE_AIO, OS_DATA_FILE, false, &success); + } + space->add(filename, handle, size, false, false); space->recv_size= it->second.size; space->size_in_header= size; return space; @@ -1278,7 +1293,8 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id, file_name_t& f = p.first->second; - if (auto d = deferred_spaces.find(space_id)) { + auto d = deferred_spaces.find(space_id); + if (d) { if (deleted) { d->deleted = true; goto got_deleted; @@ -1345,23 +1361,37 @@ same_space: FILE_* record. */ ut_ad(space == NULL); - if (srv_force_recovery) { + if (srv_operation == SRV_OPERATION_RESTORE && d + && ftype == FILE_RENAME) { +rename: + d->file_name = fname.name; + f.name = fname.name; + break; + } + + if (srv_force_recovery + || srv_operation == SRV_OPERATION_RESTORE) { /* Without innodb_force_recovery, missing tablespaces will only be reported in recv_init_crash_recovery_spaces(). Enable some more diagnostics when forcing recovery. */ - - ib::info() - << "At LSN: " << recv_sys.recovered_lsn - << ": unable to open file " - << fname.name - << " for tablespace " << space_id; + sql_print_information("InnoDB: At LSN: " LSN_PF + ": unable to open file " + "%s for tablespace " + UINT32PF, + recv_sys.recovered_lsn, + fname.name.c_str(), + space_id); } break; case FIL_LOAD_DEFER: + if (d && ftype == FILE_RENAME + && srv_operation == SRV_OPERATION_RESTORE) { + goto rename; + } /* Skip the deferred spaces when lsn is already processed */ if (store != store_t::STORE_IF_EXISTS) { diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 48731c03315..7628939f2dd 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -4146,7 +4146,6 @@ bool fil_node_t::read_page0() != DB_SUCCESS) { sql_print_error("InnoDB: Unable to read first page of file %s", name); -corrupted: aligned_free(page); return false; } @@ -4163,25 +4162,35 @@ corrupted: if (!fil_space_t::is_valid_flags(flags, space->id)) { ulint cflags= fsp_flags_convert_from_101(flags); - if (cflags == ULINT_UNDEFINED) + if (cflags != ULINT_UNDEFINED) { -invalid: - ib::error() << "Expected tablespace flags " - << ib::hex(space->flags) - << " but found " << ib::hex(flags) - << " in the file " << name; - goto corrupted; + ulint cf= cflags & ~FSP_FLAGS_MEM_MASK; + ulint sf= space->flags & ~FSP_FLAGS_MEM_MASK; + + if (fil_space_t::is_flags_equal(cf, sf) || + fil_space_t::is_flags_equal(sf, cf)) + { + flags= cflags; + goto flags_ok; + } } - ulint cf= cflags & ~FSP_FLAGS_MEM_MASK; - ulint sf= space->flags & ~FSP_FLAGS_MEM_MASK; - - if (!fil_space_t::is_flags_equal(cf, sf) && - !fil_space_t::is_flags_equal(sf, cf)) - goto invalid; - flags= cflags; + aligned_free(page); + goto invalid; } + if (!fil_space_t::is_flags_equal((flags & ~FSP_FLAGS_MEM_MASK), + (space->flags & ~FSP_FLAGS_MEM_MASK)) && + !fil_space_t::is_flags_equal((space->flags & ~FSP_FLAGS_MEM_MASK), + (flags & ~FSP_FLAGS_MEM_MASK))) + { +invalid: + sql_print_error("InnoDB: Expected tablespace flags 0x%zx but found 0x%zx" + " in the file %s", space->flags, flags, name); + return false; + } + + flags_ok: ut_ad(!(flags & FSP_FLAGS_MEM_MASK)); /* Try to read crypt_data from page 0 if it is not yet read. */ From 655f78a2381bd574bbeb0cdc74f410cf96736bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 14 Dec 2023 15:24:19 +0200 Subject: [PATCH 450/477] MDEV-18322 Assertion "wrong page type" on instant ALTER TABLE row_ins_clust_index_entry_low(): Invoke btr_set_instant() in the same mini-transaction that has successfully inserted the metadata record. In this way, if inserting the metadata record fails before any undo log record was written for it, the index root page will remain consistent. innobase_instant_try(): Remove the btr_set_instant() call. This is a 10.6 version of c17aca2f11c21ed53c7f0ce5f0cb39403e20feb9. Tested by: Matthias Leich Reviewed by: Thirunarayanan Balathandayuthapani --- .../suite/innodb/r/instant_alter_bugs.result | 24 ++++++++++++++++++ .../suite/innodb/t/instant_alter_bugs.test | 25 +++++++++++++++++++ storage/innobase/handler/handler0alter.cc | 16 +++++------- storage/innobase/row/row0ins.cc | 21 +++++++++++----- 4 files changed, 70 insertions(+), 16 deletions(-) diff --git a/mysql-test/suite/innodb/r/instant_alter_bugs.result b/mysql-test/suite/innodb/r/instant_alter_bugs.result index 7d5f7e9cc4f..1183618f992 100644 --- a/mysql-test/suite/innodb/r/instant_alter_bugs.result +++ b/mysql-test/suite/innodb/r/instant_alter_bugs.result @@ -493,6 +493,30 @@ DROP TABLE t1; CREATE TABLE t1 (i int AS (0) STORED, j INT) ENGINE=InnoDB; ALTER TABLE t1 ADD COLUMN i INT GENERATED ALWAYS AS (1), DROP COLUMN i; DROP TABLE t1; +# +# MDEV-18322 Assertion "wrong_page_type" on instant ALTER +# +BEGIN NOT ATOMIC +DECLARE c TEXT +DEFAULT(SELECT CONCAT('CREATE TABLE t1 (c', +GROUP_CONCAT(seq SEPARATOR ' CHAR(200), c'), +' CHAR(211)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT') +FROM seq_1_to_40); +EXECUTE IMMEDIATE c; +END; +$$ +INSERT INTO t1 SET c1=NULL; +ALTER TABLE t1 ADD c41 INT FIRST; +ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8123. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs +ALTER TABLE t1 ADD c41 INT FIRST; +ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8123. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +DROP TABLE t1; # End of 10.4 tests SET GLOBAL innodb_stats_persistent = @save_stats_persistent; # End of 10.6 tests diff --git a/mysql-test/suite/innodb/t/instant_alter_bugs.test b/mysql-test/suite/innodb/t/instant_alter_bugs.test index 5a83eb16e1c..8a4299e52ff 100644 --- a/mysql-test/suite/innodb/t/instant_alter_bugs.test +++ b/mysql-test/suite/innodb/t/instant_alter_bugs.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/have_sequence.inc SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; SET GLOBAL innodb_stats_persistent = 0; @@ -529,6 +530,30 @@ CREATE TABLE t1 (i int AS (0) STORED, j INT) ENGINE=InnoDB; ALTER TABLE t1 ADD COLUMN i INT GENERATED ALWAYS AS (1), DROP COLUMN i; DROP TABLE t1; +--echo # +--echo # MDEV-18322 Assertion "wrong_page_type" on instant ALTER +--echo # + +DELIMITER $$; +BEGIN NOT ATOMIC + DECLARE c TEXT + DEFAULT(SELECT CONCAT('CREATE TABLE t1 (c', + GROUP_CONCAT(seq SEPARATOR ' CHAR(200), c'), + ' CHAR(211)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT') + FROM seq_1_to_40); + EXECUTE IMMEDIATE c; +END; +$$ +DELIMITER ;$$ +INSERT INTO t1 SET c1=NULL; +--error ER_TOO_BIG_ROWSIZE +ALTER TABLE t1 ADD c41 INT FIRST; +--error ER_TOO_BIG_ROWSIZE +ALTER TABLE t1 ADD c41 INT FIRST; +CHECK TABLE t1; +SELECT COUNT(*) FROM t1; +DROP TABLE t1; + --echo # End of 10.4 tests SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 9ce277362e4..b8a9a7e5d96 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -6201,24 +6201,20 @@ empty_table: /* Convert the table to the instant ALTER TABLE format. */ mtr.commit(); mtr.start(); - index->set_modified(mtr); - if (buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, &mtr, + if (buf_block_t* root = btr_root_block_get(index, RW_S_LATCH, &mtr, &err)) { if (fil_page_get_type(root->page.frame) != FIL_PAGE_INDEX) { DBUG_ASSERT("wrong page type" == 0); err = DB_CORRUPTION; goto func_exit; } - - btr_set_instant(root, *index, &mtr); - mtr.commit(); - mtr.start(); - index->set_modified(mtr); - err = row_ins_clust_index_entry_low( - BTR_NO_LOCKING_FLAG, BTR_MODIFY_TREE, index, - index->n_uniq, entry, 0, thr); } + mtr.commit(); + mtr.start(); + err = row_ins_clust_index_entry_low( + BTR_NO_LOCKING_FLAG, BTR_MODIFY_TREE, index, + index->n_uniq, entry, 0, thr); goto func_exit; } diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 5bcb6cf595b..5d75e88227e 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -2634,14 +2634,17 @@ row_ins_clust_index_entry_low( ut_ad(!dict_index_is_online_ddl(index)); ut_ad(!index->table->persistent_autoinc); ut_ad(!index->is_instant()); + ut_ad(!entry->info_bits); mtr.set_log_mode(MTR_LOG_NO_REDO); } else { index->set_modified(mtr); - if (UNIV_UNLIKELY(entry->is_metadata())) { + if (UNIV_UNLIKELY(entry->info_bits != 0)) { + ut_ad(entry->is_metadata()); ut_ad(index->is_instant()); ut_ad(!dict_index_is_online_ddl(index)); ut_ad(mode == BTR_MODIFY_TREE); + ut_ad(flags == BTR_NO_LOCKING_FLAG); } else { if (mode == BTR_MODIFY_LEAF && dict_index_is_online_ddl(index)) { @@ -2766,11 +2769,6 @@ err_exit: skip_bulk_insert: if (UNIV_UNLIKELY(entry->info_bits != 0)) { - ut_ad(entry->is_metadata()); - ut_ad(flags == BTR_NO_LOCKING_FLAG); - ut_ad(index->is_instant()); - ut_ad(!dict_index_is_online_ddl(index)); - const rec_t* rec = btr_pcur_get_rec(&pcur); if (rec_get_info_bits(rec, page_rec_is_comp(rec)) @@ -2874,9 +2872,20 @@ do_insert: } } + if (err == DB_SUCCESS && entry->info_bits) { + if (buf_block_t* root + = btr_root_block_get(index, RW_X_LATCH, &mtr, + &err)) { + btr_set_instant(root, *index, &mtr); + } else { + ut_ad("cannot find root page" == 0); + } + } + mtr.commit(); if (big_rec) { + ut_ad(err == DB_SUCCESS); /* Online table rebuild could read (and ignore) the incomplete record at this point. If online rebuild is in progress, the From be4ac773b02bb8e4ea944f65f7e4fe882855f7fc Mon Sep 17 00:00:00 2001 From: Robin Newhouse Date: Tue, 12 Dec 2023 23:28:41 +0000 Subject: [PATCH 451/477] Explicitly recommend target branches in CODING_STANDARDS When making commits, the branches to target are not clearly defined in public documentation, and frequently change. As the development branch and the earliest maintained branches progress, it should be reflected in CODING_STANDARDS.md. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services. --- .github/pull_request_template.md | 5 +++-- CODING_STANDARDS.md | 13 ++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b519bfd8f3c..09704ad84d7 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -32,7 +32,8 @@ Without automated tests, future regressions in the expected behavior can't be au If the changes are not amenable to automated testing, please explain why not and carefully describe how to test manually. ## Basing the PR against the correct MariaDB version - [ ] *This is a new feature and the PR is based against the latest MariaDB development branch.* @@ -43,5 +44,5 @@ Tick one of the following boxes [x] to help us understand if the base branch for Maintainers are happy to point out inconsistencies but in order to speed up the review and merge process we ask you to check the CODING standards. --> ## PR quality check -- [ ] I checked the [CODING_STANDARDS.md](https://github.com/MariaDB/server/blob/11.0/CODING_STANDARDS.md) file and my PR conforms to this where appropriate. +- [ ] I checked the [CODING_STANDARDS.md](https://github.com/MariaDB/server/blob/-/CODING_STANDARDS.md) file and my PR conforms to this where appropriate. - [ ] For any trivial modifications to the PR, I am ok with the reviewer making the changes themselves. diff --git a/CODING_STANDARDS.md b/CODING_STANDARDS.md index 4310fb553e7..136602b37bd 100644 --- a/CODING_STANDARDS.md +++ b/CODING_STANDARDS.md @@ -37,14 +37,21 @@ The commit messages are typically rendered in [Markdown format](https://docs.git When updating your code, please make sure you perform a rebase, not a merge with the latest branch. Pull requests should be a simple fast-forward of the branch they are intended to land on. -The correct way to rebase (if working on top of 10.3 branch): +The correct way to rebase (if working on top of 10.11 branch): ```sh -git fetch upstream/10.3 # This assumes upstream is github.com/MariaDB/server -git rebase upstream/10.3 +git fetch upstream/10.11 # This assumes upstream is github.com/MariaDB/server +git rebase upstream/10.11 git push --force my_branch ``` +### Target branch + +Pull requests should be based against the correct MariaDB version. +New features should be based against the latest MariaDB development branch, which is the current GitHub default branch: https://github.com/MariaDB/server/blob/-/VERSION +Bug fixes should be based against the earliest maintained branch in which the bug can be reproduced. +The earliest maintained branch is found at https://mariadb.org/about/#maintenance-policy. + ## Coding Style (C / C++ files) Everyone has a preferred coding style, there is no real correct style for all projects around the world. From 4eca64e33105d2495ebebd028405998e79b5cc5a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 14 Dec 2023 20:25:58 +0100 Subject: [PATCH 452/477] add missing result file --- .../spider/bugfix/r/mdev_28739_simple.result | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_28739_simple.result diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28739_simple.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28739_simple.result new file mode 100644 index 00000000000..db232f8a6d3 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28739_simple.result @@ -0,0 +1,20 @@ +# +# MDEV-28739 Trying to lock uninitialized mutex or hang upon shutdown after using Spider with query_cache +# +for master_1 +for child2 +for child3 +set global query_cache_type= on; +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +SELECT * FROM t1; +c +# restart +drop table t1, t2; +drop server srv; +for master_1 +for child2 +for child3 From c5d7036e1aa1e9aa91946506ee81d6d02881e710 Mon Sep 17 00:00:00 2001 From: Sisi Huang Date: Sun, 10 Dec 2023 08:16:48 -0800 Subject: [PATCH 453/477] MDEV-32942 Fix Memory Leak in my_print_defaults with Non-Existing Config Files --- extra/my_print_defaults.c | 1 + 1 file changed, 1 insertion(+) diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c index 9880d4d60d7..f62ae86ae53 100644 --- a/extra/my_print_defaults.c +++ b/extra/my_print_defaults.c @@ -183,6 +183,7 @@ int main(int argc, char **argv) if ((error= load_defaults(config_file, (const char **) load_default_groups, &count, &arguments))) { + my_free(load_default_groups); my_end(0); if (error == 4) return 0; From a2c6d61db82654de61133bb5de2ae79340e96a67 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 15 Dec 2023 00:33:54 +0100 Subject: [PATCH 454/477] don't use dynstr_append() in mysqltest.cc followup for ad796aaa943 --- client/mysqltest.cc | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index d3af3c216a9..b25f4621ec0 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -91,6 +91,8 @@ static my_bool non_blocking_api_enabled= 0; #define CLOSED_CONNECTION "-closed_connection-" +#define dynstr_append DO_NO_USE + #ifndef HAVE_SETENV static int setenv(const char *name, const char *value, int overwrite); #endif @@ -1864,7 +1866,7 @@ static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...) if (strncmp(arg, "--", 2) == 0) dynstr_append_os_quoted(&ds_cmdline, arg, NullS); else - dynstr_append(&ds_cmdline, arg); + dynstr_append_mem(&ds_cmdline, arg, strlen(arg)); dynstr_append_mem(&ds_cmdline, STRING_WITH_LEN(" ")); } @@ -2021,11 +2023,11 @@ void show_diff(DYNAMIC_STRING* ds, dynstr_append_mem(&ds_tmp, message, sizeof(message)); dynstr_append_mem(&ds_tmp, STRING_WITH_LEN(" --- ")); - dynstr_append(&ds_tmp, filename1); + dynstr_append_mem(&ds_tmp, filename1, strlen(filename1)); dynstr_append_mem(&ds_tmp, STRING_WITH_LEN(" >>>\n")); cat_file(&ds_tmp, filename1); dynstr_append_mem(&ds_tmp, STRING_WITH_LEN("<<<\n --- ")); - dynstr_append(&ds_tmp, filename1); + dynstr_append_mem(&ds_tmp, filename1, strlen(filename1)); dynstr_append_mem(&ds_tmp, STRING_WITH_LEN(" >>>\n")); cat_file(&ds_tmp, filename2); dynstr_append_mem(&ds_tmp, STRING_WITH_LEN("<<<<\n")); @@ -3276,13 +3278,15 @@ static int replace(DYNAMIC_STRING *ds_str, { DYNAMIC_STRING ds_tmp; const char *start= strstr(ds_str->str, search_str); + size_t prefixlen= start - ds_str->str; if (!start) return 1; init_dynamic_string(&ds_tmp, "", ds_str->length + replace_len, 256); - dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str); + dynstr_append_mem(&ds_tmp, ds_str->str, prefixlen); dynstr_append_mem(&ds_tmp, replace_str, replace_len); - dynstr_append(&ds_tmp, start + search_len); + dynstr_append_mem(&ds_tmp, start + search_len, + ds_str->length - prefixlen - search_len); dynstr_set(ds_str, ds_tmp.str); dynstr_free(&ds_tmp); return 0; @@ -3737,7 +3741,7 @@ void do_remove_files_wildcard(struct st_command *command) wild_compare(file->name, ds_wild.str, 0)) continue; ds_file_to_remove.length= directory_length; - dynstr_append(&ds_file_to_remove, file->name); + dynstr_append_mem(&ds_file_to_remove, file->name, strlen(file->name)); DBUG_PRINT("info", ("removing file: %s", ds_file_to_remove.str)); if ((error= (my_delete(ds_file_to_remove.str, MYF(MY_WME)) != 0))) sys_errno= my_errno; @@ -7575,7 +7579,7 @@ void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD* field, } else { - dynstr_append(ds, field->name); + dynstr_append_mem(ds, field->name, strlen(field->name)); dynstr_append_mem(ds, "\t", 1); replace_dynstr_append_mem(ds, val, len); dynstr_append_mem(ds, "\n", 1); @@ -7736,12 +7740,12 @@ void append_info(DYNAMIC_STRING *ds, ulonglong affected_rows, const char *info) { char buf[40], buff2[21]; - sprintf(buf,"affected rows: %s\n", llstr(affected_rows, buff2)); - dynstr_append(ds, buf); + size_t len= sprintf(buf,"affected rows: %s\n", llstr(affected_rows, buff2)); + dynstr_append_mem(ds, buf, len); if (info) { dynstr_append_mem(ds, STRING_WITH_LEN("info: ")); - dynstr_append(ds, info); + dynstr_append_mem(ds, info, strlen(info)); dynstr_append_mem(ds, STRING_WITH_LEN("\n")); } } @@ -9613,7 +9617,7 @@ void mark_progress(struct st_command* command __attribute__((unused)), dynstr_append_mem(&ds_progress, "\t", 1); /* Filename */ - dynstr_append(&ds_progress, cur_file->file_name); + dynstr_append_mem(&ds_progress, cur_file->file_name, strlen(cur_file->file_name)); dynstr_append_mem(&ds_progress, ":", 1); /* Line in file */ @@ -11895,7 +11899,7 @@ void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input, for (i= 0; i < lines.elements ; i++) { const char **line= dynamic_element(&lines, i, const char**); - dynstr_append(ds, *line); + dynstr_append_mem(ds, *line, strlen(*line)); dynstr_append_mem(ds, STRING_WITH_LEN("\n")); } From 686865e112fa4840376745194349845f8d00a2a7 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 15 Dec 2023 15:29:26 +0530 Subject: [PATCH 455/477] Adjust the MDEV-26052 test case for MDEV-29092 --- mysql-test/suite/innodb/r/truncate_foreign.result | 9 +++++---- mysql-test/suite/innodb/t/truncate_foreign.test | 10 ++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/innodb/r/truncate_foreign.result b/mysql-test/suite/innodb/r/truncate_foreign.result index e587baa5288..e001e3ba507 100644 --- a/mysql-test/suite/innodb/r/truncate_foreign.result +++ b/mysql-test/suite/innodb/r/truncate_foreign.result @@ -77,25 +77,26 @@ DROP TABLE t1; call mtr.add_suppression("InnoDB: In ALTER TABLE `test`\\.`t1` has or is"); CREATE TABLE t1 (pk INT, a INT, PRIMARY KEY (pk), KEY (a)) ENGINE=InnoDB; SET FOREIGN_KEY_CHECKS=0; -ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (a), ALGORITHM=COPY; +ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t2 (a), ALGORITHM=COPY; INSERT INTO t1 VALUES (1,1); +CREATE TABLE t2(f1 INT PRIMARY KEY)ENGINE=InnoDB; LOCK TABLES t1 WRITE; SET FOREIGN_KEY_CHECKS=1; TRUNCATE t1; ERROR HY000: Cannot add foreign key constraint for `t1` INSERT INTO t1 VALUES (2,2); -ERROR HY000: Table 't1' was not locked with LOCK TABLES +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t2` (`a`)) SELECT * FROM t1; pk a 1 1 UNLOCK TABLES; INSERT INTO t1 VALUES (2,2); -ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t2` (`a`)) SET FOREIGN_KEY_CHECKS=0; INSERT INTO t1 VALUES (2,2); SELECT * FROM t1; pk a 1 1 2 2 -DROP TABLE t1; +DROP TABLE t2, t1; # End of 10.6 tests diff --git a/mysql-test/suite/innodb/t/truncate_foreign.test b/mysql-test/suite/innodb/t/truncate_foreign.test index abbe1b3df87..c29c141015a 100644 --- a/mysql-test/suite/innodb/t/truncate_foreign.test +++ b/mysql-test/suite/innodb/t/truncate_foreign.test @@ -89,16 +89,14 @@ call mtr.add_suppression("InnoDB: In ALTER TABLE `test`\\.`t1` has or is"); CREATE TABLE t1 (pk INT, a INT, PRIMARY KEY (pk), KEY (a)) ENGINE=InnoDB; SET FOREIGN_KEY_CHECKS=0; -ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (a), ALGORITHM=COPY; +ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t2 (a), ALGORITHM=COPY; INSERT INTO t1 VALUES (1,1); +CREATE TABLE t2(f1 INT PRIMARY KEY)ENGINE=InnoDB; LOCK TABLES t1 WRITE; SET FOREIGN_KEY_CHECKS=1; --error ER_CANNOT_ADD_FOREIGN TRUNCATE t1; -# Whether TRUNCATE succeeds or fails, it will reload FOREIGN KEY constraints. -# As a result, ha_innobase::referenced_by_foreign_key() will retun TRUE -# (for the self-referential key), and the statement will fail. ---error ER_TABLE_NOT_LOCKED +--error ER_NO_REFERENCED_ROW_2 INSERT INTO t1 VALUES (2,2); SELECT * FROM t1; UNLOCK TABLES; @@ -107,6 +105,6 @@ INSERT INTO t1 VALUES (2,2); SET FOREIGN_KEY_CHECKS=0; INSERT INTO t1 VALUES (2,2); SELECT * FROM t1; -DROP TABLE t1; +DROP TABLE t2, t1; --echo # End of 10.6 tests From 59a984b4d87aab8214218d187ddb10744c864600 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 15 Dec 2023 15:43:19 +0530 Subject: [PATCH 456/477] MDEV-32725 innodb.import_update_stats accesses uninitialized ib_table->stat_n_rows - InnoDB should write all zeros into a table and its indexes statistics members when table is unreadable. --- mysql-test/suite/innodb/t/import_update_stats.test | 1 - storage/innobase/dict/dict0stats.cc | 11 ++--------- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/include/dict0stats.h | 9 +++++++++ 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/mysql-test/suite/innodb/t/import_update_stats.test b/mysql-test/suite/innodb/t/import_update_stats.test index 128213c77b2..e1b1ae5d87f 100644 --- a/mysql-test/suite/innodb/t/import_update_stats.test +++ b/mysql-test/suite/innodb/t/import_update_stats.test @@ -4,7 +4,6 @@ --source include/not_embedded.inc --source include/have_innodb.inc ---source include/not_valgrind.inc # MDEV-32725 FIXME let MYSQLD_DATADIR =`SELECT @@datadir`; SET @old_innodb_file_per_table = @@innodb_file_per_table; diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 5371fe50dbc..16f4adb70d9 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -530,16 +530,9 @@ dict_stats_empty_index( } } -/*********************************************************************//** -Write all zeros (or 1 where it makes sense) into a table and its indexes' -statistics members. The resulting stats correspond to an empty table. */ -static -void -dict_stats_empty_table( -/*===================*/ - dict_table_t* table, /*!< in/out: table */ +void dict_stats_empty_table( + dict_table_t* table, bool empty_defrag_stats) - /*!< in: whether to empty defrag stats */ { mutex_enter(&dict_sys.mutex); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 4c27a70a0f3..1f181032333 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -14316,7 +14316,7 @@ ha_innobase::info_low( DBUG_ASSERT(ib_table->get_ref_count() > 0); if (!ib_table->is_readable()) { - ib_table->stat_initialized = true; + dict_stats_empty_table(ib_table, true); } if (flag & HA_STATUS_TIME) { diff --git a/storage/innobase/include/dict0stats.h b/storage/innobase/include/dict0stats.h index dccb354f803..441e3613b72 100644 --- a/storage/innobase/include/dict0stats.h +++ b/storage/innobase/include/dict0stats.h @@ -240,4 +240,13 @@ dict_stats_report_error(dict_table_t* table, bool defragment = false) void test_dict_stats_all(); #endif /* UNIV_ENABLE_UNIT_TEST_DICT_STATS */ +/** Write all zeros (or 1 where it makes sense) into a table +and its indexes'statistics members. The resulting stats +correspond to an empty table. +@param table table stats to be emptied +@param empty_defrag_stats empty the defrag stats */ +void +dict_stats_empty_table( + dict_table_t* table, + bool empty_defrag_stats); #endif /* dict0stats_h */ From 87a5d16911bb94d383480fdd49e20876ed1400f2 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 15 Dec 2023 12:06:54 +0100 Subject: [PATCH 457/477] add another missing result file see also 4eca64e3310 --- .../spider/bugfix/r/mdev_28683.result | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_28683.result diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28683.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28683.result new file mode 100644 index 00000000000..358c794ef86 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28683.result @@ -0,0 +1,22 @@ +# +# MDEV-28683 Spider: SIGSEGV in spider_db_direct_delete, SIGSEGV in spider_db_connect, ASAN: heap-use-after-free in spider_db_direct_delete +# +for master_1 +for child2 +for child3 +CREATE TABLE t (c INT) ENGINE=Spider; +SELECT * FROM t; +ERROR HY000: Unable to connect to foreign data source: localhost +INSERT INTO t (SELECT 1 FROM t); +ERROR HY000: Unable to connect to foreign data source: localhost +LOCK TABLES t WRITE CONCURRENT; +DELETE FROM t; +ERROR HY000: Unable to connect to foreign data source: localhost +UNLOCK TABLES; +DROP TABLE t; +for master_1 +for child2 +for child3 +# +# end of test mdev_28683 +# From f98d2ef5b4ab633d74fb245a8b6520fe86514de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 15 Dec 2023 15:38:31 +0200 Subject: [PATCH 458/477] MDEV-33009 Server hangs for a long time with innodb_undo_log_truncate=ON trx_purge_truncate_history(): Release buf_pool.flush_list_mutex before starting a rescan of buf_pool.flush_list, to ensure that the buf_flush_page_cleaner thread (which may be holding buf_pool.mutex) will be able to proceed. This fixes up commit a0f02f743848fb6ef6d2a51960f77e1e38da1682 (MDEV-32757). Tested by: Axel Schwenke Reviewed by: Vladislav Lesin --- storage/innobase/trx/trx0purge.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index b06e3cb3e1b..702e76fc284 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -681,6 +681,13 @@ void trx_purge_truncate_history() if (prev != buf_pool.flush_hp.get()) { + /* The functions buf_pool_t::release_freed_page() or + buf_do_flush_list_batch() may be right now holding + buf_pool.mutex and waiting to acquire + buf_pool.flush_list_mutex. Ensure that they can proceed, + to avoid extreme waits. */ + mysql_mutex_unlock(&buf_pool.flush_list_mutex); + mysql_mutex_lock(&buf_pool.flush_list_mutex); /* Rescan, because we may have lost the position. */ bpage= UT_LIST_GET_LAST(buf_pool.flush_list); continue; From 0930eb86cb00edb2ae285c3250ca51bae126e5e5 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 15 Dec 2023 19:58:31 +0100 Subject: [PATCH 459/477] Spider cannot run DDL (e.g. create tables) before ddl recovery use signal_ddl_recovery_done callback for that. also make the server to call signal_ddl_recovery_done() when loading plugins at run-time (so that plugins would't need to detect that on their own) --- sql/handler.cc | 6 +++++- storage/spider/spd_table.cc | 16 ++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index a0bc758c00c..58a2eb3e43a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -629,7 +629,7 @@ int ha_finalize_handlerton(st_plugin_int *plugin) const char *hton_no_exts[]= { 0 }; - +static bool ddl_recovery_done= false; int ha_initialize_handlerton(st_plugin_int *plugin) { @@ -779,6 +779,9 @@ int ha_initialize_handlerton(st_plugin_int *plugin) resolve_sysvar_table_options(hton); update_discovery_counters(hton, 1); + if (ddl_recovery_done && hton->signal_ddl_recovery_done) + hton->signal_ddl_recovery_done(hton); + DBUG_RETURN(ret); err_deinit: @@ -975,6 +978,7 @@ void ha_signal_ddl_recovery_done() DBUG_ENTER("ha_signal_ddl_recovery_done"); plugin_foreach(NULL, signal_ddl_recovery_done, MYSQL_STORAGE_ENGINE_PLUGIN, NULL); + ddl_recovery_done= true; DBUG_VOID_RETURN; } diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index c11a6b6a40d..65a00f5da34 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -7123,6 +7123,15 @@ bool spider_init_system_tables() } +/* + Spider is typically loaded before ddl_recovery, but DDL statements + cannot be executed before ddl_recovery, so we delay system table creation. +*/ +static void spider_after_ddl_recovery(handlerton *) +{ + spider_init_system_tables(); +} + int spider_db_init( void *p ) { @@ -7153,6 +7162,7 @@ int spider_db_init( spider_hton->close_cursor_read_view = spider_close_cursor_read_view; */ spider_hton->panic = spider_panic; + spider_hton->signal_ddl_recovery_done= spider_after_ddl_recovery; spider_hton->close_connection = spider_close_connection; spider_hton->start_consistent_snapshot = spider_start_consistent_snapshot; spider_hton->flush_logs = spider_flush_logs; @@ -7490,11 +7500,6 @@ int spider_db_init( spider_udf_table_mon_list_hash[roop_count].array.size_of_element); } - if (spider_init_system_tables()) - { - goto error_system_table_creation; - } - #ifndef WITHOUT_SPIDER_BG_SEARCH if (!(spider_table_sts_threads = (SPIDER_THREAD *) spider_bulk_malloc(NULL, SPD_MID_DB_INIT_12, MYF(MY_WME | MY_ZEROFILL), @@ -7595,7 +7600,6 @@ error_init_udf_table_mon_list_hash: error_init_udf_table_mon_cond: for (; roop_count >= 0; roop_count--) pthread_cond_destroy(&spider_udf_table_mon_conds[roop_count]); -error_system_table_creation: roop_count = spider_param_udf_table_mon_mutex_count() - 1; error_init_udf_table_mon_mutex: for (; roop_count >= 0; roop_count--) From aff5ed3988a3add17d607e6184288f82b567dbee Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 16 Dec 2023 19:46:58 +0100 Subject: [PATCH 460/477] MDEV-33046 race condition in InnoDB dict_stats_schedule() it can be invoked with ms=0. In that case dict_stats_func is invoked immediately, it calls dict_stats_process_entry_from_recalc_pool() which at the end might try to call dict_stats_schedule() again to queue another recalc. And it can happen that the first dict_stats_schedule(0) call didn't release dict_stats_mutex yet, so the second dict_stats_schedule() won't queue a recalc. And as a result the table won't have its stats recalculated at all, not now, not later. This causes innodb.innodb_stats_auto_recalc to fail sporadically. This commit doesn't fix it but makes it less likely to occur which happens to be enough for the test to pass. Proper fix is coming soon. --- storage/innobase/dict/dict0stats_bg.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index a66aac226a3..8354943adec 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -412,7 +412,7 @@ static void dict_stats_schedule(int ms) void dict_stats_schedule_now() { - dict_stats_schedule(0); + dict_stats_schedule(10); } /** Shut down the dict_stats_thread. */ From 4c2e9718413e754715e9836ea603511fc6fec0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 18 Dec 2023 10:37:11 +0200 Subject: [PATCH 461/477] MDEV-33052 MSAN use-of-uninitialized-value in buf_read_ahead_linear() buf_read_ahead_linear(): Suppress a warning of comparing potentially uninitialized FIL_PAGE_PREV and FIL_PAGE_NEXT fields. --- storage/innobase/buf/buf0rea.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index c81017bb024..26bfb7eb0fc 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -643,6 +643,12 @@ hard_fail: uint32_t prev= mach_read_from_4(my_assume_aligned<4>(f + FIL_PAGE_PREV)); uint32_t next= mach_read_from_4(my_assume_aligned<4>(f + FIL_PAGE_NEXT)); + /* The underlying file page of this buffer pool page could actually + be marked as freed, or a read of the page into the buffer pool might + be in progress. We may read uninitialized data here. + Suppress warnings of comparing uninitialized values. */ + MEM_MAKE_DEFINED(&prev, sizeof prev); + MEM_MAKE_DEFINED(&next, sizeof next); if (prev == FIL_NULL || next == FIL_NULL) goto hard_fail; page_id_t id= page_id; From fa2e1c3948f090aa644b3f83708a117366882e93 Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Fri, 15 Dec 2023 16:06:24 +0530 Subject: [PATCH 462/477] MDEV-33015: Server crashes upon JSON_SCHEMA_VALID reading NULL from a user variable Analysis: Since the item is NULL, it's json value is NULL but we proceed to parse it anyway. Fix: If json value is NULL, return NULL. --- mysql-test/main/func_json.result | 7 +++++++ mysql-test/main/func_json.test | 8 ++++++++ sql/item_jsonfunc.cc | 14 +++++++++----- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 04f25011963..042aef1a220 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -4737,4 +4737,11 @@ NULL # PREPARE s FROM 'SELECT JSON_SCHEMA_VALID (?,''{}'') FROM DUAL'; ERROR HY000: Variable schema is not supported. +# +# MDEV-33015: Server crashes upon JSON_SCHEMA_VALID reading NULL from a user variable +# +SET @a= NULL; +SELECT JSON_SCHEMA_VALID(@a,'{}'); +JSON_SCHEMA_VALID(@a,'{}') +NULL # End of 11.1 test diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index 57d7213293d..fb793519014 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -3708,4 +3708,12 @@ SELECT JSON_SCHEMA_VALID(NULL, NULL); --error ER_JSON_NO_VARIABLE_SCHEMA PREPARE s FROM 'SELECT JSON_SCHEMA_VALID (?,''{}'') FROM DUAL'; +--echo # +--echo # MDEV-33015: Server crashes upon JSON_SCHEMA_VALID reading NULL from a user variable +--echo # + +SET @a= NULL; +SELECT JSON_SCHEMA_VALID(@a,'{}'); + + --echo # End of 11.1 test diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 61fa8953d87..6815b3d3f66 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -4809,17 +4809,21 @@ bool Item_func_json_schema_valid::fix_length_and_dec(THD *thd) String *js= NULL; - if (!is_schema_constant || (null_value= args[0]->null_value)) + if (!is_schema_constant) { - if (!is_schema_constant) - { - my_error(ER_JSON_NO_VARIABLE_SCHEMA, MYF(0)); - } + + my_error(ER_JSON_NO_VARIABLE_SCHEMA, MYF(0)); null_value= 1; return 0; } + null_value= args[0]->null_value; js= args[0]->val_json(&tmp_js); + if (!js) + { + null_value= 1; + return 0; + } json_scan_start(&je, js->charset(), (const uchar *) js->ptr(), (const uchar *) js->ptr() + js->length()); if (!create_object_and_handle_keyword(thd, &je, &keyword_list, From 07a0173f1c478a8fe237702c7fc161dda82106c6 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 18 Dec 2023 17:37:30 +0100 Subject: [PATCH 463/477] perfschema: LOCK_all_status_vars not LOCK_status to iterate over all status variables one should use LOCK_all_status_vars not LOCK_status this fixes sporadic mutex lock inversion in plugins.password_reuse_check: * acl_cache->lock is taken over complex operations that might increment status counters (under LOCK_status). * acl_cache->lock is needed to get the values of Acl% status variables when iterating over status variables --- storage/perfschema/pfs_variable.cc | 64 ++++++++++++------------------ storage/perfschema/pfs_visitor.cc | 3 +- 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/storage/perfschema/pfs_variable.cc b/storage/perfschema/pfs_variable.cc index aa07686139b..3f7fd73683a 100644 --- a/storage/perfschema/pfs_variable.cc +++ b/storage/perfschema/pfs_variable.cc @@ -762,7 +762,7 @@ bool PFS_status_variable_cache::filter_show_var(const SHOW_VAR *show_var, bool s /** Build an array of SHOW_VARs from the global status array. Expand nested subarrays, filter unwanted variables. - NOTE: Must be done inside of LOCK_status to guard against plugin load/unload. + NOTE: Must be done under LOCK_all_status_vars */ bool PFS_status_variable_cache::init_show_var_array(enum_var_type scope, bool strict) { @@ -881,14 +881,12 @@ char * PFS_status_variable_cache::make_show_var_name(const char* prefix, const c */ bool PFS_status_variable_cache::do_initialize_session(void) { - /* Acquire LOCK_status to guard against plugin load/unload. */ - //if (m_current_thd->fill_status_recursion_level++ == 0) - mysql_mutex_lock(&LOCK_status); + /* Acquire LOCK_all_status_vars to guard against plugin load/unload. */ + mysql_rwlock_rdlock(&LOCK_all_status_vars); bool ret= init_show_var_array(OPT_SESSION, true); - //if (m_current_thd->fill_status_recursion_level-- == 1) - mysql_mutex_unlock(&LOCK_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); return ret; } @@ -917,13 +915,12 @@ int PFS_status_variable_cache::do_materialize_global(void) m_materialized= false; DEBUG_SYNC(m_current_thd, "before_materialize_global_status_array"); - /* Acquire LOCK_status to guard against plugin load/unload. */ - //if (m_current_thd->fill_status_recursion_level++ == 0) - mysql_mutex_lock(&LOCK_status); + /* Acquire LOCK_all_status_vars to guard against plugin load/unload. */ + mysql_rwlock_rdlock(&LOCK_all_status_vars); /* - Build array of SHOW_VARs from global status array. Do this within - LOCK_status to ensure that the array remains unchanged during + Build array of SHOW_VARs from global status array. Do this under + LOCK_all_status_vars to ensure that the array remains unchanged during materialization. */ if (!m_external_init) @@ -946,8 +943,7 @@ int PFS_status_variable_cache::do_materialize_global(void) */ manifest(m_current_thd, m_show_var_array.front(), &status_totals, "", false, true); - //if (m_current_thd->fill_status_recursion_level-- == 1) - mysql_mutex_unlock(&LOCK_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); m_materialized= true; DEBUG_SYNC(m_current_thd, "after_materialize_global_status_array"); @@ -967,13 +963,11 @@ int PFS_status_variable_cache::do_materialize_all(THD* unsafe_thd) m_materialized= false; m_cache.clear(); - /* Avoid recursive acquisition of LOCK_status. */ - //if (m_current_thd->fill_status_recursion_level++ == 0) - mysql_mutex_lock(&LOCK_status); + mysql_rwlock_rdlock(&LOCK_all_status_vars); /* - Build array of SHOW_VARs from global status array. Do this within - LOCK_status to ensure that the array remains unchanged while this + Build array of SHOW_VARs from global status array. Do this under + LOCK_all_status_vars to ensure that the array remains unchanged while this thread is materialized. */ if (!m_external_init) @@ -996,8 +990,7 @@ int PFS_status_variable_cache::do_materialize_all(THD* unsafe_thd) ret= 0; } - //if (m_current_thd->fill_status_recursion_level-- == 1) - mysql_mutex_unlock(&LOCK_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); return ret; } @@ -1013,13 +1006,11 @@ int PFS_status_variable_cache::do_materialize_session(THD* unsafe_thd) m_materialized= false; m_cache.clear(); - /* Avoid recursive acquisition of LOCK_status. */ - //if (m_current_thd->fill_status_recursion_level++ == 0) - mysql_mutex_lock(&LOCK_status); + mysql_rwlock_rdlock(&LOCK_all_status_vars); /* - Build array of SHOW_VARs from global status array. Do this within - LOCK_status to ensure that the array remains unchanged while this + Build array of SHOW_VARs from global status array. Do this under + LOCK_all_status_vars to ensure that the array remains unchanged while this thread is materialized. */ if (!m_external_init) @@ -1042,8 +1033,7 @@ int PFS_status_variable_cache::do_materialize_session(THD* unsafe_thd) ret= 0; } - //if (m_current_thd->fill_status_recursion_level-- == 1) - mysql_mutex_unlock(&LOCK_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); return ret; } @@ -1060,9 +1050,8 @@ int PFS_status_variable_cache::do_materialize_session(PFS_thread *pfs_thread) m_materialized= false; m_cache.clear(); - /* Acquire LOCK_status to guard against plugin load/unload. */ - //if (m_current_thd->fill_status_recursion_level++ == 0) - mysql_mutex_lock(&LOCK_status); + /* Acquire LOCK_all_status_vars to guard against plugin load/unload. */ + mysql_rwlock_rdlock(&LOCK_all_status_vars); /* The SHOW_VAR array must be initialized externally. */ assert(m_initialized); @@ -1084,8 +1073,7 @@ int PFS_status_variable_cache::do_materialize_session(PFS_thread *pfs_thread) ret= 0; } - //if (m_current_thd->fill_status_recursion_level-- == 1) - mysql_mutex_unlock(&LOCK_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); return ret; } @@ -1104,9 +1092,8 @@ int PFS_status_variable_cache::do_materialize_client(PFS_client *pfs_client) m_materialized= false; m_cache.clear(); - /* Acquire LOCK_status to guard against plugin load/unload. */ - //if (m_current_thd->fill_status_recursion_level++ == 0) - mysql_mutex_lock(&LOCK_status); + /* Acquire LOCK_all_status_vars to guard against plugin load/unload. */ + mysql_rwlock_rdlock(&LOCK_all_status_vars); /* The SHOW_VAR array must be initialized externally. */ assert(m_initialized); @@ -1123,8 +1110,7 @@ int PFS_status_variable_cache::do_materialize_client(PFS_client *pfs_client) */ manifest(m_current_thd, m_show_var_array.front(), &status_totals, "", false, true); - //if (m_current_thd->fill_status_recursion_level-- == 1) - mysql_mutex_unlock(&LOCK_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); m_materialized= true; return 0; @@ -1217,7 +1203,7 @@ Status_variable::Status_variable(const SHOW_VAR *show_var, STATUS_VAR *status_va /** Resolve status value, convert to string. show_var->value is an offset into status_vars. - NOTE: Assumes LOCK_status is held. + NOTE: Assumes LOCK_all_status_vars is held. */ void Status_variable::init(const SHOW_VAR *show_var, STATUS_VAR *status_vars, enum_var_type query_scope) { @@ -1283,7 +1269,7 @@ void sum_account_status(PFS_client *pfs_account, STATUS_VAR *status_totals) /** Reset aggregated status counter stats for account, user and host. - NOTE: Assumes LOCK_status is held. + NOTE: Assumes LOCK_all_status_vars is held. */ void reset_pfs_status_stats() { diff --git a/storage/perfschema/pfs_visitor.cc b/storage/perfschema/pfs_visitor.cc index 92a5c99e13b..7e3027ac9a6 100644 --- a/storage/perfschema/pfs_visitor.cc +++ b/storage/perfschema/pfs_visitor.cc @@ -1356,8 +1356,7 @@ PFS_connection_status_visitor::~PFS_connection_status_visitor() = default; /** Aggregate from global status. */ void PFS_connection_status_visitor::visit_global() { - /* NOTE: Requires lock on LOCK_status. */ - mysql_mutex_assert_owner(&LOCK_status); + /* NOTE: Requires lock on LOCK_all_status_vars. */ add_to_status(m_status_vars, &global_status_var); } From 11ae6c9af102bc158558bd1588399367ccbd2a5f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 18 Dec 2023 17:42:50 +0100 Subject: [PATCH 464/477] InnoDB: downgrade a warning to a note "InnoDB: The last skipped log record LSN X is not equal to page LSN Y" is not an actionable message for the user, so it should be a note, not a warning --- storage/innobase/log/log0recv.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 7dca721a309..c76ee2ee470 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3234,7 +3234,7 @@ static buf_block_t *recv_recover_page(buf_block_t *block, mtr_t &mtr, skipped_after_init = false; ut_ad(end_lsn == page_lsn); if (end_lsn != page_lsn) { - sql_print_warning( + sql_print_information( "InnoDB: The last skipped log record" " LSN " LSN_PF " is not equal to page LSN " LSN_PF, From eb37a76659ce3daf84e9adf91f8ff629062f9837 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 18 Dec 2023 22:13:23 +0100 Subject: [PATCH 465/477] fix test failures with ASAN ASAN uses *a lot* more stack. use not_asan.inc for tests that recursively put a lot of data on the stack --- mysql-test/main/execution_constants.test | 1 + mysql-test/main/lotofstack.result | 101 ++++++++++++++ mysql-test/main/lotofstack.test | 133 ++++++++++++++++++ mysql-test/main/sp_notembedded.result | 119 ----------------- mysql-test/main/sp_notembedded.test | 163 ----------------------- 5 files changed, 235 insertions(+), 282 deletions(-) create mode 100644 mysql-test/main/lotofstack.result create mode 100644 mysql-test/main/lotofstack.test diff --git a/mysql-test/main/execution_constants.test b/mysql-test/main/execution_constants.test index 285197cd1f4..49b1da8f8e9 100644 --- a/mysql-test/main/execution_constants.test +++ b/mysql-test/main/execution_constants.test @@ -1,5 +1,6 @@ # In embedded server we don't really have a control over stack usage -- source include/not_embedded.inc +-- source include/not_asan.inc # # Bug#21476: Lost Database Connection During Query diff --git a/mysql-test/main/lotofstack.result b/mysql-test/main/lotofstack.result new file mode 100644 index 00000000000..553dcb3b1b4 --- /dev/null +++ b/mysql-test/main/lotofstack.result @@ -0,0 +1,101 @@ +create function bug10100f(prm int) returns int +begin +if prm > 1 then +return prm * bug10100f(prm - 1); +end if; +return 1; +end| +set statement sql_mode = '' for +create procedure bug10100p(prm int, inout res int) +begin +set res = res * prm; +if prm > 1 then +call bug10100p(prm - 1, res); +end if; +end| +set statement sql_mode = '' for +create procedure bug10100t(prm int) +begin +declare res int; +set res = 1; +call bug10100p(prm, res); +select res; +end| +create table t3 (a int)| +insert into t3 values (0)| +create view v1 as select a from t3| +create procedure bug10100pt(level int, lim int) +begin +if level < lim then +update t3 set a=level; +FLUSH TABLES; +call bug10100pt(level+1, lim); +else +select * from t3; +end if; +end| +create procedure bug10100pv(level int, lim int) +begin +if level < lim then +update v1 set a=level; +FLUSH TABLES; +call bug10100pv(level+1, lim); +else +select * from v1; +end if; +end| +prepare stmt2 from "select * from t3;"; +create procedure bug10100pd(level int, lim int) +begin +if level < lim then +select level; +prepare stmt1 from "update t3 set a=a+2"; +execute stmt1; +FLUSH TABLES; +execute stmt1; +FLUSH TABLES; +execute stmt1; +FLUSH TABLES; +deallocate prepare stmt1; +execute stmt2; +select * from t3; +call bug10100pd(level+1, lim); +else +execute stmt2; +end if; +end| +create procedure bug10100pc(level int, lim int) +begin +declare lv int; +declare c cursor for select a from t3; +open c; +if level < lim then +select level; +fetch c into lv; +select lv; +update t3 set a=level+lv; +FLUSH TABLES; +call bug10100pc(level+1, lim); +else +select * from t3; +end if; +close c; +end| +set @@max_sp_recursion_depth=255| +set @var=1| +call bug10100p(255, @var)| +call bug10100pt(1,255)| +call bug10100pv(1,255)| +call bug10100pd(1,255)| +call bug10100pc(1,255)| +set @@max_sp_recursion_depth=0| +deallocate prepare stmt2| +drop function bug10100f| +drop procedure bug10100p| +drop procedure bug10100t| +drop procedure bug10100pt| +drop procedure bug10100pv| +drop procedure bug10100pd| +drop procedure bug10100pc| +drop view v1| +drop table t3| diff --git a/mysql-test/main/lotofstack.test b/mysql-test/main/lotofstack.test new file mode 100644 index 00000000000..a658fb00e9f --- /dev/null +++ b/mysql-test/main/lotofstack.test @@ -0,0 +1,133 @@ +# +# For tests that need a lot of stack - they likely won't work under ASAN +# +source include/not_asan.inc; +source include/not_embedded.inc; + +# +# Bug#10100 function (and stored procedure?) recursivity problem +# +# routines with simple recursion +delimiter |; +create function bug10100f(prm int) returns int +begin + if prm > 1 then + return prm * bug10100f(prm - 1); + end if; + return 1; +end| +set statement sql_mode = '' for +create procedure bug10100p(prm int, inout res int) +begin + set res = res * prm; + if prm > 1 then + call bug10100p(prm - 1, res); + end if; +end| +set statement sql_mode = '' for +create procedure bug10100t(prm int) +begin + declare res int; + set res = 1; + call bug10100p(prm, res); + select res; +end| + +# a procedure which use tables and recursion +create table t3 (a int)| +insert into t3 values (0)| +create view v1 as select a from t3| +create procedure bug10100pt(level int, lim int) +begin + if level < lim then + update t3 set a=level; + FLUSH TABLES; + call bug10100pt(level+1, lim); + else + select * from t3; + end if; +end| +# view & recursion +create procedure bug10100pv(level int, lim int) +begin + if level < lim then + update v1 set a=level; + FLUSH TABLES; + call bug10100pv(level+1, lim); + else + select * from v1; + end if; +end| +# dynamic sql & recursion +prepare stmt2 from "select * from t3;"; +create procedure bug10100pd(level int, lim int) +begin + if level < lim then + select level; + prepare stmt1 from "update t3 set a=a+2"; + execute stmt1; + FLUSH TABLES; + execute stmt1; + FLUSH TABLES; + execute stmt1; + FLUSH TABLES; + deallocate prepare stmt1; + execute stmt2; + select * from t3; + call bug10100pd(level+1, lim); + else + execute stmt2; + end if; +end| +# cursor & recursion +create procedure bug10100pc(level int, lim int) +begin + declare lv int; + declare c cursor for select a from t3; + open c; + if level < lim then + select level; + fetch c into lv; + select lv; + update t3 set a=level+lv; + FLUSH TABLES; + call bug10100pc(level+1, lim); + else + select * from t3; + end if; + close c; +end| + +# end of the stack checking +set @@max_sp_recursion_depth=255| +set @var=1| +# disable log because error about stack overrun contains numbers which +# depend on a system +-- disable_ps_protocol +-- disable_result_log +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100p(255, @var)| +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100pt(1,255)| +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100pv(1,255)| +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100pd(1,255)| +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100pc(1,255)| +-- enable_result_log +-- enable_ps_protocol +set @@max_sp_recursion_depth=0| + +deallocate prepare stmt2| + +drop function bug10100f| +drop procedure bug10100p| +drop procedure bug10100t| +drop procedure bug10100pt| +drop procedure bug10100pv| +drop procedure bug10100pd| +drop procedure bug10100pc| +drop view v1| +drop table t3| +delimiter ;| diff --git a/mysql-test/main/sp_notembedded.result b/mysql-test/main/sp_notembedded.result index e03361598a6..927e03d2a4d 100644 --- a/mysql-test/main/sp_notembedded.result +++ b/mysql-test/main/sp_notembedded.result @@ -1,7 +1,5 @@ set @old_concurrent_insert= @@global.concurrent_insert; set @@global.concurrent_insert= 0; -drop table if exists t1,t3; -drop procedure if exists bug4902| create procedure bug4902() begin show grants for 'root'@'localhost'; @@ -15,7 +13,6 @@ Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO `root`@`localhost` WITH GRANT OPTION GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION drop procedure bug4902| -drop procedure if exists bug4902_2| create procedure bug4902_2() begin show processlist; @@ -23,13 +20,10 @@ end| call bug4902_2()| show warnings| Level Code Message -Note 1305 PROCEDURE test.bug4902_2 does not exist call bug4902_2()| show warnings| Level Code Message -Note 1305 PROCEDURE test.bug4902_2 does not exist drop procedure bug4902_2| -drop procedure if exists bug6807| create procedure bug6807() begin declare a int; @@ -42,116 +36,6 @@ ERROR 70100: Query execution was interrupted call bug6807()| ERROR 70100: Query execution was interrupted drop procedure bug6807| -drop function if exists bug10100f| -drop procedure if exists bug10100p| -drop procedure if exists bug10100t| -drop procedure if exists bug10100pt| -drop procedure if exists bug10100pv| -drop procedure if exists bug10100pd| -drop procedure if exists bug10100pc| -create function bug10100f(prm int) returns int -begin -if prm > 1 then -return prm * bug10100f(prm - 1); -end if; -return 1; -end| -set statement sql_mode = '' for -create procedure bug10100p(prm int, inout res int) -begin -set res = res * prm; -if prm > 1 then -call bug10100p(prm - 1, res); -end if; -end| -set statement sql_mode = '' for -create procedure bug10100t(prm int) -begin -declare res int; -set res = 1; -call bug10100p(prm, res); -select res; -end| -create table t3 (a int)| -insert into t3 values (0)| -create view v1 as select a from t3| -create procedure bug10100pt(level int, lim int) -begin -if level < lim then -update t3 set a=level; -FLUSH TABLES; -call bug10100pt(level+1, lim); -else -select * from t3; -end if; -end| -create procedure bug10100pv(level int, lim int) -begin -if level < lim then -update v1 set a=level; -FLUSH TABLES; -call bug10100pv(level+1, lim); -else -select * from v1; -end if; -end| -prepare stmt2 from "select * from t3;"; -create procedure bug10100pd(level int, lim int) -begin -if level < lim then -select level; -prepare stmt1 from "update t3 set a=a+2"; -execute stmt1; -FLUSH TABLES; -execute stmt1; -FLUSH TABLES; -execute stmt1; -FLUSH TABLES; -deallocate prepare stmt1; -execute stmt2; -select * from t3; -call bug10100pd(level+1, lim); -else -execute stmt2; -end if; -end| -create procedure bug10100pc(level int, lim int) -begin -declare lv int; -declare c cursor for select a from t3; -open c; -if level < lim then -select level; -fetch c into lv; -select lv; -update t3 set a=level+lv; -FLUSH TABLES; -call bug10100pc(level+1, lim); -else -select * from t3; -end if; -close c; -end| -set @@max_sp_recursion_depth=255| -set @var=1| -call bug10100p(255, @var)| -call bug10100pt(1,255)| -call bug10100pv(1,255)| -call bug10100pd(1,255)| -call bug10100pc(1,255)| -set @@max_sp_recursion_depth=0| -deallocate prepare stmt2| -drop function bug10100f| -drop procedure bug10100p| -drop procedure bug10100t| -drop procedure bug10100pt| -drop procedure bug10100pv| -drop procedure bug10100pd| -drop procedure bug10100pc| -drop view v1| -drop table t3| -drop procedure if exists bug15298_1; -drop procedure if exists bug15298_2; create user 'mysqltest_1'@'localhost'; grant all privileges on test.* to 'mysqltest_1'@'localhost'; create procedure 15298_1 () sql security definer show grants for current_user; @@ -170,8 +54,6 @@ disconnect con1; drop user mysqltest_1@localhost; drop procedure 15298_1; drop procedure 15298_2; -drop table if exists t1; -drop procedure if exists p1; create table t1 (value varchar(15)); create procedure p1() update t1 set value='updated' where value='old'; call p1(); @@ -283,7 +165,6 @@ disconnect con2; # functions in databases which names contained dot. # connection default; -DROP DATABASE IF EXISTS `my.db`; create database `my.db`; use `my.db`; CREATE FUNCTION f1(a int) RETURNS INT RETURN a; diff --git a/mysql-test/main/sp_notembedded.test b/mysql-test/main/sp_notembedded.test index 12bacff4e87..9aca03fbdc5 100644 --- a/mysql-test/main/sp_notembedded.test +++ b/mysql-test/main/sp_notembedded.test @@ -7,19 +7,12 @@ set @@global.concurrent_insert= 0; # Save the initial number of concurrent sessions --source include/count_sessions.inc ---disable_warnings -drop table if exists t1,t3; ---enable_warnings delimiter |; - # # Bug#4902 Stored procedure with SHOW WARNINGS leads to packet error # # Added tests for show grants command ---disable_warnings -drop procedure if exists bug4902| ---enable_warnings create procedure bug4902() begin show grants for 'root'@'localhost'; @@ -38,9 +31,6 @@ call bug4902()| drop procedure bug4902| # We need separate SP for SHOW PROCESSLIST since we want use replace_column ---disable_warnings -drop procedure if exists bug4902_2| ---enable_warnings create procedure bug4902_2() begin show processlist; @@ -58,9 +48,6 @@ drop procedure bug4902_2| # # Bug#6807 Stored procedure crash if CREATE PROCEDURE ... KILL QUERY # ---disable_warnings -drop procedure if exists bug6807| ---enable_warnings create procedure bug6807() begin declare a int; @@ -77,152 +64,11 @@ call bug6807()| drop procedure bug6807| - -# -# Bug#10100 function (and stored procedure?) recursivity problem -# ---disable_warnings -drop function if exists bug10100f| -drop procedure if exists bug10100p| -drop procedure if exists bug10100t| -drop procedure if exists bug10100pt| -drop procedure if exists bug10100pv| -drop procedure if exists bug10100pd| -drop procedure if exists bug10100pc| ---enable_warnings -# routines with simple recursion -create function bug10100f(prm int) returns int -begin - if prm > 1 then - return prm * bug10100f(prm - 1); - end if; - return 1; -end| -set statement sql_mode = '' for -create procedure bug10100p(prm int, inout res int) -begin - set res = res * prm; - if prm > 1 then - call bug10100p(prm - 1, res); - end if; -end| -set statement sql_mode = '' for -create procedure bug10100t(prm int) -begin - declare res int; - set res = 1; - call bug10100p(prm, res); - select res; -end| - -# a procedure which use tables and recursion -create table t3 (a int)| -insert into t3 values (0)| -create view v1 as select a from t3| -create procedure bug10100pt(level int, lim int) -begin - if level < lim then - update t3 set a=level; - FLUSH TABLES; - call bug10100pt(level+1, lim); - else - select * from t3; - end if; -end| -# view & recursion -create procedure bug10100pv(level int, lim int) -begin - if level < lim then - update v1 set a=level; - FLUSH TABLES; - call bug10100pv(level+1, lim); - else - select * from v1; - end if; -end| -# dynamic sql & recursion -prepare stmt2 from "select * from t3;"; -create procedure bug10100pd(level int, lim int) -begin - if level < lim then - select level; - prepare stmt1 from "update t3 set a=a+2"; - execute stmt1; - FLUSH TABLES; - execute stmt1; - FLUSH TABLES; - execute stmt1; - FLUSH TABLES; - deallocate prepare stmt1; - execute stmt2; - select * from t3; - call bug10100pd(level+1, lim); - else - execute stmt2; - end if; -end| -# cursor & recursion -create procedure bug10100pc(level int, lim int) -begin - declare lv int; - declare c cursor for select a from t3; - open c; - if level < lim then - select level; - fetch c into lv; - select lv; - update t3 set a=level+lv; - FLUSH TABLES; - call bug10100pc(level+1, lim); - else - select * from t3; - end if; - close c; -end| - -# end of the stack checking -set @@max_sp_recursion_depth=255| -set @var=1| -# disable log because error about stack overrun contains numbers which -# depend on a system --- disable_ps_protocol --- disable_result_log --- error ER_STACK_OVERRUN_NEED_MORE -call bug10100p(255, @var)| --- error ER_STACK_OVERRUN_NEED_MORE -call bug10100pt(1,255)| --- error ER_STACK_OVERRUN_NEED_MORE -call bug10100pv(1,255)| --- error ER_STACK_OVERRUN_NEED_MORE -call bug10100pd(1,255)| --- error ER_STACK_OVERRUN_NEED_MORE -call bug10100pc(1,255)| --- enable_result_log --- enable_ps_protocol -set @@max_sp_recursion_depth=0| - -deallocate prepare stmt2| - -drop function bug10100f| -drop procedure bug10100p| -drop procedure bug10100t| -drop procedure bug10100pt| -drop procedure bug10100pv| -drop procedure bug10100pd| -drop procedure bug10100pc| -drop view v1| -drop table t3| - delimiter ;| - # # Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context # ---disable_warnings -drop procedure if exists bug15298_1; -drop procedure if exists bug15298_2; ---enable_warnings create user 'mysqltest_1'@'localhost'; grant all privileges on test.* to 'mysqltest_1'@'localhost'; create procedure 15298_1 () sql security definer show grants for current_user; @@ -242,11 +88,6 @@ drop procedure 15298_2; # Bug#29936 Stored Procedure DML ignores low_priority_updates setting # ---disable_warnings -drop table if exists t1; -drop procedure if exists p1; ---enable_warnings - create table t1 (value varchar(15)); create procedure p1() update t1 set value='updated' where value='old'; @@ -411,10 +252,6 @@ DROP FUNCTION f1; connection default; ---disable_warnings -DROP DATABASE IF EXISTS `my.db`; ---enable_warnings - create database `my.db`; use `my.db`; From 25c627885a29aa883f0b08b0239976cee5bf7676 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 18 Dec 2023 23:05:58 +0100 Subject: [PATCH 466/477] hashicorp plugin: any 404 from the vault means "no key found" e.g. it could be {"errors":["no handler for route \"mariadbtest/data/1\". route entry not found."]} --- .../hashicorp_key_management_plugin.cc | 28 ++++--------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/plugin/hashicorp_key_management/hashicorp_key_management_plugin.cc b/plugin/hashicorp_key_management/hashicorp_key_management_plugin.cc index 7c72af688e4..bdc2f7345f1 100644 --- a/plugin/hashicorp_key_management/hashicorp_key_management_plugin.cc +++ b/plugin/hashicorp_key_management/hashicorp_key_management_plugin.cc @@ -593,32 +593,16 @@ int HCData::curl_run (const char *url, std::string *response, { const char *res = response->c_str(); /* - Error 404 requires special handling - in case the server - returned an empty array of error strings (the value of the - "error" object in JSON is equal to an empty array), we should - ignore this error at this level, since this means the missing - key (this problem is handled at a higher level), but if the - error object contains anything other than empty array, then - we need to print the error message to the log: + Error 404 requires special handling - we should ignore this + error at this level, since this means the missing key (this + problem is handled at a higher level) */ if (http_code == 404) { - const char *err; - int err_len; - if (json_get_object_key(res, res + response->size(), - "errors", &err, &err_len) == JSV_ARRAY) - { - const char *ev; - int ev_len; - if (json_get_array_item(err, err + err_len, 0, &ev, &ev_len) == - JSV_NOTHING) - { - *response = std::string(""); - is_error = false; - } - } + *response = std::string(""); + is_error = false; } - if (is_error) + else if (is_error) { my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER "Hashicorp server error: %d, response: %s", From be694384d41d33934eb36cb0b722c3ac109d04d0 Mon Sep 17 00:00:00 2001 From: hsser Date: Sat, 16 Dec 2023 21:54:01 -0800 Subject: [PATCH 467/477] MDEV-31925 Fix for File Leak in mysql_upgrade with --check-if-upgrade-is-needed Option This commit addresses the file leakage problem encountered with the mysql_upgrade --check-if-upgrade-is-needed command. --- client/mysql_upgrade.c | 7 +++++- .../main/mysql_upgrade_file_leak.result | 4 ++++ mysql-test/main/mysql_upgrade_file_leak.test | 24 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 mysql-test/main/mysql_upgrade_file_leak.result create mode 100644 mysql-test/main/mysql_upgrade_file_leak.test diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index ea18c1c5ba7..70e2d341c5b 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1374,7 +1374,12 @@ int main(int argc, char **argv) open_mysql_upgrade_file(); if (opt_check_upgrade) - exit(upgrade_already_done(0) == 0); + { + int upgrade_needed = upgrade_already_done(0); + free_used_memory(); + my_end(my_end_arg); + exit(upgrade_needed == 0); + } /* Find mysqlcheck */ find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name); diff --git a/mysql-test/main/mysql_upgrade_file_leak.result b/mysql-test/main/mysql_upgrade_file_leak.result new file mode 100644 index 00000000000..648a0c97802 --- /dev/null +++ b/mysql-test/main/mysql_upgrade_file_leak.result @@ -0,0 +1,4 @@ +Running mysql_upgrade with --check-if-upgrade-is-needed +Checking for absence of temporary files by mysql_upgrade +No temporary files found +End of 10.4 tests diff --git a/mysql-test/main/mysql_upgrade_file_leak.test b/mysql-test/main/mysql_upgrade_file_leak.test new file mode 100644 index 00000000000..44f178322b4 --- /dev/null +++ b/mysql-test/main/mysql_upgrade_file_leak.test @@ -0,0 +1,24 @@ +-- source include/mysql_upgrade_preparation.inc + +# +# MDEV-31925 mysqld_upgrade --check-if-upgrade-is-needed leaks files +# + +# Run mysql_upgrade with --check-if-upgrade-is-needed +--echo Running mysql_upgrade with --check-if-upgrade-is-needed +--exec $MYSQL_UPGRADE --check-if-upgrade-is-needed 2>&1 + +# Check if temporary files related to mysql_upgrade are cleared +--echo Checking for absence of temporary files by mysql_upgrade +--perl + +# Use the temporary directory path from the MySQL configuration +my $tmpdir = "$ENV{MYSQL_TMP_DIR}"; + +die "Test failed: Found temporary file left by mysql_upgrade\n" if (glob("$tmpdir/mysql_upgrade-*")); +print "No temporary files found\n"; +EOF + +let $MYSQLD_DATADIR= `select @@datadir`; +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info +--echo End of 10.4 tests From 98287bd2d6877969514469ebfbf27f9951b99657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 19 Dec 2023 11:15:08 +0200 Subject: [PATCH 468/477] MDEV-33009 Server hangs for a long time with innodb_undo_log_truncate=ON trx_purge_truncate_history(): Release buf_pool.flush_list_mutex and 'dummily' acquire and release buf_pool.mutex before starting a rescan of buf_pool.flush_list, to ensure that the buf_flush_page_cleaner thread (which may be holding buf_pool.mutex) will be able to proceed. This fixes up commit 5dbe7a8c9aa88b7ed17311c2f1df651c9da7783b (MDEV-32757). Tested by: Axel Schwenke (on Ubuntu 18.04 and Ubuntu 20.04) Reviewed by: Vladislav Lesin --- storage/innobase/trx/trx0purge.cc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index be9ee4793ba..e4bcf21f94a 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -687,8 +687,8 @@ not_free: mini-transaction commit and the server was killed, then discarding the to-be-trimmed pages without flushing would break crash recovery. */ - mysql_mutex_lock(&buf_pool.flush_list_mutex); rescan: + mysql_mutex_lock(&buf_pool.flush_list_mutex); for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); bpage; ) { ut_ad(bpage->oldest_modification()); @@ -730,7 +730,17 @@ not_free: mysql_mutex_lock(&buf_pool.flush_list_mutex); if (prev != buf_pool.flush_hp.get()) + { + /* The functions buf_pool_t::release_freed_page() or + buf_do_flush_list_batch() may be right now holding + buf_pool.mutex and waiting to acquire + buf_pool.flush_list_mutex. Ensure that they can proceed, + to avoid extreme waits. */ + mysql_mutex_unlock(&buf_pool.flush_list_mutex); + mysql_mutex_lock(&buf_pool.mutex); + mysql_mutex_unlock(&buf_pool.mutex); goto rescan; + } } bpage= prev; From a204ce2788987a611bb3b6798afdc7f4f2553556 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Sun, 17 Dec 2023 13:57:26 +0100 Subject: [PATCH 469/477] MDEV-33045: Server crashes in Item_func_binlog_gtid_pos::val_str / Binary_string::c_ptr_safe Item::val_str() sets the Item::null_value flag, so call it before checking the flag, not after. Signed-off-by: Kristian Nielsen --- mysql-test/suite/binlog_encryption/rpl_gtid_basic.result | 7 +++++++ mysql-test/suite/rpl/r/rpl_gtid_basic.result | 7 +++++++ mysql-test/suite/rpl/t/rpl_gtid_basic.test | 7 +++++++ sql/item_strfunc.cc | 6 +++--- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/binlog_encryption/rpl_gtid_basic.result b/mysql-test/suite/binlog_encryption/rpl_gtid_basic.result index 5771b0f405f..99721813159 100644 --- a/mysql-test/suite/binlog_encryption/rpl_gtid_basic.result +++ b/mysql-test/suite/binlog_encryption/rpl_gtid_basic.result @@ -182,6 +182,13 @@ BINLOG_GTID_POS('master-bin.000001',18446744073709551616) NULL Warnings: Warning 1916 Got overflow when converting '18446744073709551616' to INT. Value truncated +SET sql_log_bin= 0; +CREATE TABLE t1 AS SELECT MASTER_POS_WAIT(@binlog_file, 4, 0); +SELECT BINLOG_GTID_POS(@binlog_file, 4); +BINLOG_GTID_POS(@binlog_file, 4) +NULL +DROP TABLE t1; +SET sql_log_bin= 1; *** Some tests of @@GLOBAL.gtid_binlog_state *** connection server_2; include/sync_with_master_gtid.inc diff --git a/mysql-test/suite/rpl/r/rpl_gtid_basic.result b/mysql-test/suite/rpl/r/rpl_gtid_basic.result index aefb80a7c13..afc700a72c5 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_basic.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_basic.result @@ -182,6 +182,13 @@ BINLOG_GTID_POS('master-bin.000001',18446744073709551616) NULL Warnings: Warning 1916 Got overflow when converting '18446744073709551616' to INT. Value truncated +SET sql_log_bin= 0; +CREATE TABLE t1 AS SELECT MASTER_POS_WAIT(@binlog_file, 4, 0); +SELECT BINLOG_GTID_POS(@binlog_file, 4); +BINLOG_GTID_POS(@binlog_file, 4) +NULL +DROP TABLE t1; +SET sql_log_bin= 1; *** Some tests of @@GLOBAL.gtid_binlog_state *** connection server_2; include/sync_with_master_gtid.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_basic.test b/mysql-test/suite/rpl/t/rpl_gtid_basic.test index 70bd0087f7a..a7af234d47e 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_basic.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_basic.test @@ -162,6 +162,13 @@ eval SELECT BINLOG_GTID_POS('$valid_binlog_name',0); eval SELECT BINLOG_GTID_POS('$valid_binlog_name',18446744073709551615); eval SELECT BINLOG_GTID_POS('$valid_binlog_name',18446744073709551616); +# MDEV-33045: Server crashes in Item_func_binlog_gtid_pos::val_str / Binary_string::c_ptr_safe +SET sql_log_bin= 0; +CREATE TABLE t1 AS SELECT MASTER_POS_WAIT(@binlog_file, 4, 0); +SELECT BINLOG_GTID_POS(@binlog_file, 4); +DROP TABLE t1; +SET sql_log_bin= 1; + --echo *** Some tests of @@GLOBAL.gtid_binlog_state *** --connection server_2 diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 92d5e196da4..0373d2a94a6 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3232,12 +3232,12 @@ String *Item_func_binlog_gtid_pos::val_str(String *str) String name_str, *name; longlong pos; - if (args[0]->null_value || args[1]->null_value) - goto err; - name= args[0]->val_str(&name_str); pos= args[1]->val_int(); + if (args[0]->null_value || args[1]->null_value) + goto err; + if (pos < 0 || pos > UINT_MAX32) goto err; From 1cbba45e6ed1dd4f08614198f9596ef828a8ada4 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Sun, 17 Dec 2023 18:30:38 +0100 Subject: [PATCH 470/477] Attempt to fix rare race in test for MDEV-8031 The error-injection inject_mdev8031 simulates a deadlock kill in a specific place, by setting killed_for_retry to RETRY_KILL_KILLED directly. If a real deadlock kill triggers at the same time, it is possible for the thread to complete its transaction retry and set rgi_slave to NULL before the real readlock kill can complete in the background. This will cause a segfault due to null-pointer access. Fix by changing the error injection to do a real background deadlock kill, which ensures that the thread will wait for any pending background kills to complete. Signed-off-by: Kristian Nielsen --- sql/rpl_parallel.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index 397b45c4eef..d9ff07fa740 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -856,8 +856,7 @@ do_retry: thd->wait_for_commit_ptr->unregister_wait_for_prior_commit(); DBUG_EXECUTE_IF("inject_mdev8031", { /* Simulate that we get deadlock killed at this exact point. */ - rgi->killed_for_retry= rpl_group_info::RETRY_KILL_KILLED; - thd->set_killed(KILL_CONNECTION); + slave_background_kill_request(thd); }); #ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("rpl_parallel_simulate_wait_at_retry", { From eaa4968fc564444ce9c8803da87f685fb182b447 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Sun, 17 Dec 2023 18:35:14 +0100 Subject: [PATCH 471/477] MDEV-10653: Fix segfault in SHOW MASTER STATUS with NULL inuse_relaylog The previous patch for MDEV-10653 changes the rpl_parallel::workers_idle() function to use Relay_log_info::last_inuse_relaylog to check for idle workers. But the code was missing a NULL check. Also, there was one place during SQL slave thread start which was missing mutex synchronisation when updating inuse_relaylog. Signed-off-by: Kristian Nielsen --- sql/rpl_parallel.cc | 6 ++++-- sql/slave.cc | 8 +++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index d9ff07fa740..ac96d92eb5d 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -2538,8 +2538,10 @@ rpl_parallel::stop_during_until() bool rpl_parallel::workers_idle(Relay_log_info *rli) { - return rli->last_inuse_relaylog->queued_count == - rli->last_inuse_relaylog->dequeued_count; + mysql_mutex_assert_owner(&rli->data_lock); + return !rli->last_inuse_relaylog || + rli->last_inuse_relaylog->queued_count == + rli->last_inuse_relaylog->dequeued_count; } diff --git a/sql/slave.cc b/sql/slave.cc index 2cc11b9ed42..f4d76e447cd 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -5369,19 +5369,25 @@ pthread_handler_t handle_slave_sql(void *arg) } else rli->gtid_skip_flag = GTID_SKIP_NOT; + mysql_mutex_lock(&rli->data_lock); if (init_relay_log_pos(rli, rli->group_relay_log_name, rli->group_relay_log_pos, - 1 /*need data lock*/, &errmsg, + 0 /*need data lock*/, &errmsg, 1 /*look for a description_event*/)) { rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, NULL, "Error initializing relay log position: %s", errmsg); + mysql_mutex_unlock(&rli->data_lock); goto err_before_start; } rli->reset_inuse_relaylog(); if (rli->alloc_inuse_relaylog(rli->group_relay_log_name)) + { + mysql_mutex_unlock(&rli->data_lock); goto err_before_start; + } + mysql_mutex_unlock(&rli->data_lock); strcpy(rli->future_event_master_log_name, rli->group_master_log_name); THD_CHECK_SENTRY(thd); From 476ff0927ac4487b9c5ea64916b94f2bb5246dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 19 Dec 2023 14:45:39 +0200 Subject: [PATCH 472/477] MDEV-33062 innodb_undo_log_truncate=ON prevents fast shutdown trx_purge_truncate_history(): If a fast shutdown has been initiated, disregard innodb_undo_log_truncate=ON and return. --- storage/innobase/trx/trx0purge.cc | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 702e76fc284..a7e3e7367b1 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -645,6 +645,16 @@ void trx_purge_truncate_history() mini-transaction commit and the server was killed, then discarding the to-be-trimmed pages without flushing would break crash recovery. */ + + rescan: + if (UNIV_UNLIKELY(srv_shutdown_state != SRV_SHUTDOWN_NONE) && + srv_fast_shutdown) + { + fast_shutdown: + mtr.commit(); + return; + } + mysql_mutex_lock(&buf_pool.flush_list_mutex); for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); bpage; ) @@ -687,10 +697,7 @@ void trx_purge_truncate_history() buf_pool.flush_list_mutex. Ensure that they can proceed, to avoid extreme waits. */ mysql_mutex_unlock(&buf_pool.flush_list_mutex); - mysql_mutex_lock(&buf_pool.flush_list_mutex); - /* Rescan, because we may have lost the position. */ - bpage= UT_LIST_GET_LAST(buf_pool.flush_list); - continue; + goto rescan; } } @@ -699,6 +706,10 @@ void trx_purge_truncate_history() mysql_mutex_unlock(&buf_pool.flush_list_mutex); + if (UNIV_UNLIKELY(srv_shutdown_state != SRV_SHUTDOWN_NONE) && + srv_fast_shutdown) + goto fast_shutdown; + /* Adjust the tablespace metadata. */ if (!fil_truncate_prepare(space.id)) { From a057a6e41f22035a8f2b53f9602f33e15f941680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 20 Dec 2023 09:21:27 +1100 Subject: [PATCH 473/477] MDEV-24670 memory pressure - mariadb-backup postfix mariadb-backup wasn't meant to have memory pressure sensors so restrict the operation to SRV_OPERATIONAL_NORMAL mode. Reviewed by Daniel Black. --- storage/innobase/buf/buf0buf.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index a55048e83df..e8274b4a856 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1309,7 +1309,8 @@ bool buf_pool_t::create() btr_search_sys_create(); #ifdef __linux__ - buf_mem_pressure_detect_init(); + if (srv_operation == SRV_OPERATION_NORMAL) + buf_mem_pressure_detect_init(); #endif ut_ad(is_initialised()); return false; From 9d2c3d388ecbf89b636b93ab56a7a7b36984637d Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 20 Dec 2023 09:48:36 +1100 Subject: [PATCH 474/477] MDEV-24670 memory pressure - warnings/notes Errors outputted as notes are weird, and when a user cannot do anything about them, why output them at all. Point taken, removed these, and left positive message on initialization (from Marko). Thanks Elena Stepanova. --- storage/innobase/buf/buf0buf.cc | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index e8274b4a856..0ca556f1c8e 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -786,16 +786,7 @@ public: if ((m_fds[m_num_fds].fd= open(memcgroup.c_str(), O_RDWR | O_NONBLOCK | O_CLOEXEC)) < 0) { - switch (errno) { - case EPERM: - /* https://lore.kernel.org/all/CAMw=ZnQ56cm4Txgy5EhGYvR+Jt4s-KVgoA9_65HKWVMOXp7a9A@mail.gmail.com/T/#m3bd2a73c5ee49965cb73a830b1ccaa37ccf4e427 */ - sql_print_information("InnoDB: Failed to initialize memory pressure EPERM, " - "file permissions."); - break; - default: - sql_print_information("InnoDB: Failed to initialize memory pressure: %s", - strerror(errno)); - } + /* User can't do anything about it, no point giving warning */ shutdown(); return false; } @@ -803,7 +794,7 @@ public: ssize_t slen= strlen(*trig); if (write(m_fds[m_num_fds].fd, *trig, slen) < slen) { - sql_print_warning("InnoDB: Failed create trigger for memory pressure \"%s\"", *trig); + /* we may fail this one, but continue to the next */ my_close(m_fds[m_num_fds].fd, MYF(MY_WME)); continue; } @@ -815,7 +806,7 @@ public: if ((m_event_fd= eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK)) == -1) { - sql_print_warning("InnoDB: No memory pressure - can't create eventfd"); + /* User can't do anything about it, no point giving warning */ shutdown(); return false; } @@ -824,6 +815,7 @@ public: m_fds[m_num_fds].events= POLLIN; m_num_fds++; m_thd= std::thread(pressure_routine, this); + sql_print_information("InnoDB: Initialized memory pressure event listener"); return true; } From f9ae553067143a9db496e49929488c4b87bb2d24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 20 Dec 2023 15:56:00 +0200 Subject: [PATCH 475/477] MDEV-33098: Disable the test --- mysql-test/suite/innodb/disabled.def | 1 + 1 file changed, 1 insertion(+) create mode 100644 mysql-test/suite/innodb/disabled.def diff --git a/mysql-test/suite/innodb/disabled.def b/mysql-test/suite/innodb/disabled.def new file mode 100644 index 00000000000..e78d33745b2 --- /dev/null +++ b/mysql-test/suite/innodb/disabled.def @@ -0,0 +1 @@ +doublewrite_debug : MDEV-33098 occasionally fails to start up InnoDB From 7e0348917cfc112a46018eb57bc9992984425542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 20 Dec 2023 16:02:27 +0200 Subject: [PATCH 476/477] MDEV-32068 merge fixup btr_pcur_move_to_next_page(): Add code that was wrongly deleted in the merge commit 8c8bce05d22e0e97e844fb2518e23aa04a544cd9 --- storage/innobase/btr/btr0pcur.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index afbb7e7cfd6..0bf279ab371 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -536,10 +536,11 @@ btr_pcur_move_to_next_page( } dberr_t err; + bool first_access = false; buf_block_t* next_block = btr_block_get( *cursor->index(), next_page_no, rw_lock_type_t(cursor->latch_mode & (RW_X_LATCH | RW_S_LATCH)), - mtr, &err); + mtr, &err, &first_access); if (UNIV_UNLIKELY(!next_block)) { return err; @@ -558,6 +559,10 @@ btr_pcur_move_to_next_page( const auto s = mtr->get_savepoint(); mtr->rollback_to_savepoint(s - 2, s - 1); + if (first_access) { + buf_read_ahead_linear(next_block->page.id(), + next_block->zip_size()); + } return DB_SUCCESS; } From 63fb478f88e0061d149f5cdd3c4d21d4a35c7bd9 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 21 Dec 2023 15:19:53 +0100 Subject: [PATCH 477/477] post-merge: typo fixed make_item_func_call_generic() should take `db_int`, not `db` --- sql/sql_lex.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 1c004886abf..3c9c4f2331c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -9770,7 +9770,7 @@ Item *LEX::make_item_func_call_generic(THD *thd, if (!db_int.str || check_routine_name(&name)) return NULL; - return make_item_func_call_generic(thd, (Lex_ident_sys)db, name, args); + return make_item_func_call_generic(thd, Lex_ident_sys(db_int.str, db_int.length), name, args); }