diff --git a/.travis.yml b/.travis.yml index 6142e76e1e0..95e0796099b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -111,8 +111,8 @@ addons: apt: sources: - ubuntu-toolchain-r-test - - sourceline: 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main' - - sourceline: 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-6.0 main' + - llvm-toolchain-trusty-5.0 + - llvm-toolchain-trusty-6.0 packages: # make sure these include all compilers and all build dependencies (see list above) - gcc-5 - g++-5 diff --git a/client/mysqldump.c b/client/mysqldump.c index 1958d5c173a..ae92adbc8ba 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2129,7 +2129,7 @@ static void print_xml_row(FILE *xml_file, const char *row_name, { create_stmt_ptr= (*row)[i]; create_stmt_len= lengths[i]; -#ifndef DBUG_OFF +#ifdef DBUG_ASSERT_EXISTS body_found= 1; #endif } diff --git a/cmake/make_dist.cmake.in b/cmake/make_dist.cmake.in index 43498f1f888..6fad17137fd 100644 --- a/cmake/make_dist.cmake.in +++ b/cmake/make_dist.cmake.in @@ -110,7 +110,7 @@ CONFIGURE_FILE(${CMAKE_BINARY_DIR}/sql/sql_yacc.cc CONFIGURE_FILE(${CMAKE_BINARY_DIR}/sql/sql_yacc_ora.hh ${PACKAGE_DIR}/sql/sql_yacc_ora.hh COPYONLY) CONFIGURE_FILE(${CMAKE_BINARY_DIR}/sql/sql_yacc_ora.cc - ${PACKAGE_DIR}/sql/sql_yacc_orac.cc COPYONLY) + ${PACKAGE_DIR}/sql/sql_yacc_ora.cc COPYONLY) # Add documentation, if user has specified where to find them IF(MYSQL_DOCS_LOCATION) diff --git a/debian/mariadb-plugin-tokudb.install b/debian/mariadb-plugin-tokudb.install index 8bbed858be4..40dd0e78c65 100644 --- a/debian/mariadb-plugin-tokudb.install +++ b/debian/mariadb-plugin-tokudb.install @@ -4,5 +4,5 @@ usr/bin/tokuft_logprint usr/bin/tokuftdump usr/lib/mysql/plugin/ha_tokudb.so usr/share/doc/mariadb-server-10.4/README.md usr/share/doc/mariadb-plugin-tokudb/README.md -usr/share/man/man1/tokuft_logdump.1 +usr/share/man/man1/tokuft_logprint.1 usr/share/man/man1/tokuftdump.1 diff --git a/extra/mariabackup/encryption_plugin.cc b/extra/mariabackup/encryption_plugin.cc index 7f230256e7a..6335cdf3cd7 100644 --- a/extra/mariabackup/encryption_plugin.cc +++ b/extra/mariabackup/encryption_plugin.cc @@ -51,6 +51,36 @@ static void add_to_plugin_load_list(const char *plugin_def) static char XTRABACKUP_EXE[] = "xtrabackup"; +/* + Read "plugin-load" value (encryption plugin) from backup-my.cnf during + prepare phase. + The value is stored during backup phase. +*/ +static std::string get_encryption_plugin_from_cnf() +{ + FILE *f = fopen("backup-my.cnf", "r"); + if (!f) + { + msg("cannot open backup-my.cnf for reading\n"); + exit(EXIT_FAILURE); + } + char line[512]; + std::string plugin_load; + while (fgets(line, sizeof(line), f)) + { + if (strncmp(line, "plugin_load=", 12) == 0) + { + plugin_load = line + 12; + // remote \n at the end of string + plugin_load.resize(plugin_load.size() - 1); + break; + } + } + fclose(f); + return plugin_load; +} + + void encryption_plugin_backup_init(MYSQL *mysql) { MYSQL_RES *result; @@ -78,7 +108,17 @@ void encryption_plugin_backup_init(MYSQL *mysql) std::string plugin_load(name); if (library) + { + /* Remove shared library suffixes, in case we'll prepare on different OS.*/ + const char *extensions[] = { ".dll", ".so", 0 }; + for (size_t i = 0; extensions[i]; i++) + { + const char *ext = extensions[i]; + if (ends_with(library, ext)) + library[strlen(library) - strlen(ext)] = 0; + } plugin_load += std::string("=") + library; + } oss << "plugin_load=" << plugin_load << std::endl; @@ -140,14 +180,18 @@ extern int finalize_encryption_plugin(st_plugin_int *plugin); void encryption_plugin_prepare_init(int argc, char **argv) { - - if (!xb_plugin_load) + std::string plugin_load= get_encryption_plugin_from_cnf(); + if (plugin_load.size()) + { + msg("Loading encryption plugin from %s\n", plugin_load.c_str()); + } + else { finalize_encryption_plugin(0); return; } - add_to_plugin_load_list(xb_plugin_load); + add_to_plugin_load_list(plugin_load.c_str()); if (xb_plugin_dir) strncpy(opt_plugin_dir, xb_plugin_dir, FN_REFLEN); diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 8006404de15..80211084a76 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -359,9 +359,8 @@ struct ddl_tracker_t { /* For DDL operation found in redo log, */ space_id_to_name_t id_to_name; }; -const space_id_t REMOVED_SPACE_ID = ULINT_MAX; -static ddl_tracker_t ddl_tracker; +static ddl_tracker_t ddl_tracker; /* Whether xtrabackup_binlog_info should be created on recovery */ static bool recover_binlog_info; @@ -617,9 +616,8 @@ void backup_file_op(ulint space_id, const byte* flags, /** Callback whenever MLOG_INDEX_LOAD happens. -@param[in] space_id space id to check -@return false */ -void backup_optimized_ddl_op(ulint space_id) +@param[in] space_id space id to check */ +static void backup_optimized_ddl_op(ulint space_id) { // TODO : handle incremental if (xtrabackup_incremental) @@ -630,6 +628,15 @@ void backup_optimized_ddl_op(ulint space_id) pthread_mutex_unlock(&backup_mutex); } +/** Callback whenever MLOG_TRUNCATE happens. */ +static void backup_truncate_fail() +{ + msg("mariabackup: Incompatible TRUNCATE operation detected.%s\n", + opt_lock_ddl_per_table + ? "" + : " Use --lock-ddl-per-table to lock all tables before backup."); +} + /* ======== Date copying thread context ======== */ typedef struct { @@ -702,7 +709,6 @@ enum options_xtrabackup OPT_INNODB_LOG_CHECKSUMS, OPT_XTRA_INCREMENTAL_FORCE_SCAN, OPT_DEFAULTS_GROUP, - OPT_PLUGIN_LOAD, OPT_INNODB_ENCRYPT_LOG, OPT_CLOSE_FILES, OPT_CORE_FILE, @@ -1209,7 +1215,7 @@ struct my_option xb_server_options[] = "Use native AIO if supported on this platform.", (G_PTR*) &srv_use_native_aio, (G_PTR*) &srv_use_native_aio, 0, GET_BOOL, NO_ARG, - FALSE, 0, 0, 0, 0, 0}, + TRUE, 0, 0, 0, 0, 0}, {"innodb_page_size", OPT_INNODB_PAGE_SIZE, "The universal page size of the database.", (G_PTR*) &innobase_page_size, (G_PTR*) &innobase_page_size, 0, @@ -1261,11 +1267,7 @@ struct my_option xb_server_options[] = &xb_plugin_dir, &xb_plugin_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - { "plugin-load", OPT_PLUGIN_LOAD, "encrypton plugin to load during 'prepare' phase.", - &xb_plugin_load, &xb_plugin_load, - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - - { "innodb-encrypt-log", OPT_INNODB_ENCRYPT_LOG, "encrypton plugin to load", + { "innodb-encrypt-log", OPT_INNODB_ENCRYPT_LOG, "Whether to encrypt innodb log", &srv_encrypt_log, &srv_encrypt_log, 0, GET_BOOL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, @@ -2703,7 +2705,7 @@ static os_thread_ret_t DECLARE_THREAD(log_copying_thread)(void*) log_mutex_enter(); bool completed = metadata_to_lsn - && metadata_to_lsn < log_copy_scanned_lsn; + && metadata_to_lsn <= log_copy_scanned_lsn; log_mutex_exit(); if (completed) { break; @@ -4181,12 +4183,13 @@ fail_before_log_copying_thread_start: /* copy log file by current position */ log_copy_scanned_lsn = checkpoint_lsn_start; recv_sys->recovered_lsn = log_copy_scanned_lsn; + log_optimized_ddl_op = backup_optimized_ddl_op; + log_truncate = backup_truncate_fail; if (xtrabackup_copy_logfile()) goto fail_before_log_copying_thread_start; log_copying_stop = os_event_create(0); - log_optimized_ddl_op = backup_optimized_ddl_op; os_thread_create(log_copying_thread, NULL, &log_copying_thread_id); /* FLUSH CHANGED_PAGE_BITMAPS call */ diff --git a/include/myisamchk.h b/include/myisamchk.h index 1a9605aac46..67c8a20e0b8 100644 --- a/include/myisamchk.h +++ b/include/myisamchk.h @@ -100,12 +100,13 @@ typedef struct st_handler_check_param time_t backup_time; /* To sign backup files */ ulong rec_per_key_part[HA_MAX_KEY_SEG * HA_MAX_POSSIBLE_KEY]; double new_rec_per_key_part[HA_MAX_KEY_SEG * HA_MAX_POSSIBLE_KEY]; - uint out_flag, warning_printed, error_printed, note_printed, verbose; + uint out_flag, error_printed, verbose; uint opt_sort_key, total_files, max_level; uint key_cache_block_size, pagecache_block_size; int tmpfile_createflag, err_count; myf myf_rw; uint16 language; + my_bool warning_printed, note_printed, wrong_trd_printed; my_bool using_global_keycache, opt_lock_memory, opt_follow_links; my_bool retry_repair, force_sort, calc_checksum, static_row_size; char temp_filename[FN_REFLEN]; diff --git a/man/CMakeLists.txt b/man/CMakeLists.txt index f5899577a47..9c34ede59c7 100644 --- a/man/CMakeLists.txt +++ b/man/CMakeLists.txt @@ -26,12 +26,15 @@ SET(MAN1_SERVER innochecksum.1 my_print_defaults.1 myisam_ftdump.1 myisamchk.1 mysqld_safe_helper.1 tokuftdump.1 wsrep_sst_common.1 wsrep_sst_mysqldump.1 wsrep_sst_rsync.1 wsrep_sst_xtrabackup-v2.1 wsrep_sst_xtrabackup.1 - galera_recovery.1 galera_new_cluster.1 tokuft_logdump.1) + galera_recovery.1 galera_new_cluster.1 tokuft_logprint.1 + mysql_ldb.1 + wsrep_sst_mariabackup.1 mbstream.1 mariabackup.1 + wsrep_sst_rsync_wan.1) SET(MAN8_SERVER mysqld.8) SET(MAN1_CLIENT msql2mysql.1 mysql.1 mysql_find_rows.1 mysql_waitpid.1 mysqlaccess.1 mysqladmin.1 mysqlbinlog.1 mysqlcheck.1 mysqldump.1 mysqlimport.1 mysqlshow.1 mysqlslap.1 - mysql_plugin.1) + mysql_plugin.1 mysql_embedded.1) SET(MAN1_DEVEL mysql_config.1) SET(MAN1_TEST mysql-stress-test.pl.1 mysql-test-run.pl.1 mysql_client_test.1 mysqltest_embedded.1 mysql_client_test_embedded.1 my_safe_process.1) diff --git a/man/mariabackup.1 b/man/mariabackup.1 new file mode 100644 index 00000000000..628c9cf74fa --- /dev/null +++ b/man/mariabackup.1 @@ -0,0 +1,16 @@ +'\" t +.\" +.TH "\FBMARIABACKUP\FR" "1" "9 August 2018" "MariaDB 10\&.1" "MariaDB Database System" +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH NAME +mariabackup \- Backup tool +.SH DESCRIPTION +Use \fBmariabackup \-\-help\fR for details on usage\. +.PP +For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/ diff --git a/man/mbstream.1 b/man/mbstream.1 new file mode 100644 index 00000000000..2aba73fe400 --- /dev/null +++ b/man/mbstream.1 @@ -0,0 +1,16 @@ +'\" t +.\" +.TH "\FBMBSTREAM\FR" "1" "9 August 2018" "MariaDB 10\&.1" "MariaDB Database System" +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH NAME +mbstream \- Serialize/deserialize files in the XBSTREAM format +.SH DESCRIPTION +Use \fBmbstream \-\-help\fR for details on usage\. +.PP +For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/ diff --git a/man/mysql_embedded.1 b/man/mysql_embedded.1 new file mode 100644 index 00000000000..735c4e05ae0 --- /dev/null +++ b/man/mysql_embedded.1 @@ -0,0 +1 @@ +.so man1/mysql.1 diff --git a/man/mysql_ldb.1 b/man/mysql_ldb.1 new file mode 100644 index 00000000000..5c08a1a14df --- /dev/null +++ b/man/mysql_ldb.1 @@ -0,0 +1,16 @@ +'\" t +.\" +.TH "\FBMYSQL_LDB\FR" "1" "9 August 2018" "MariaDB 10\&.2" "MariaDB Database System" +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH NAME +mysql_ldb \- RocksDB tool +.SH DESCRIPTION +Use \fBmysql_ldb \-\-help\fR for details on usage\. +.PP +For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/ diff --git a/man/tokuft_logdump.1 b/man/tokuft_logprint.1 similarity index 84% rename from man/tokuft_logdump.1 rename to man/tokuft_logprint.1 index f6cf08080f7..bc3b85a55d6 100644 --- a/man/tokuft_logdump.1 +++ b/man/tokuft_logprint.1 @@ -11,6 +11,6 @@ .SH NAME tokuft_logprint \- Dump the log from stdin to stdout .SH DESCRIPTION -Use: Dump the log from stdin to stdout\. +Use: Dump the log from stdin to stdout\. Use \fBtokuft_logprint \-\-help\fR for details on usage\. .PP For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/ diff --git a/man/wsrep_sst_mariabackup.1 b/man/wsrep_sst_mariabackup.1 new file mode 100644 index 00000000000..34ae4b6f82e --- /dev/null +++ b/man/wsrep_sst_mariabackup.1 @@ -0,0 +1,16 @@ +'\" t +.\" +.TH "\FBWSREP_SST_MARIABACKUP\FR" "1" "8 August 2018" "MariaDB 10\&.1" "MariaDB Database System" +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH NAME +wsrep_sst_mariabackup \- mariabackup\-based state snapshot transfer +.SH DESCRIPTION +Use: mariabackup-based state snapshot transfer\. +.PP +For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/ diff --git a/man/wsrep_sst_rsync.1 b/man/wsrep_sst_rsync.1 index 30fcfbfba19..bbaeb64016e 100644 --- a/man/wsrep_sst_rsync.1 +++ b/man/wsrep_sst_rsync.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBWSREP_SST_RSYNC\FR" "1" "9 May 2017" "MariaDB 10\&.3" "MariaDB Database System" +.TH "\FBWSREP_SST_RSYNC\FR" "1" "9 August 2018" "MariaDB 10\&.3" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- @@ -9,7 +9,7 @@ .\" disable justification (adjust text to left margin only) .ad l .SH NAME -wsrep_sst_mysqldump \- rsync-based state snapshot transfer +wsrep_sst_rsync \- rsync-based state snapshot transfer .SH DESCRIPTION Use: rsync-based state snapshot transfer\. .PP diff --git a/man/wsrep_sst_rsync_wan.1 b/man/wsrep_sst_rsync_wan.1 new file mode 100644 index 00000000000..6d465d554a8 --- /dev/null +++ b/man/wsrep_sst_rsync_wan.1 @@ -0,0 +1,16 @@ +'\" t +.\" +.TH "\FBWSREP_SST_RSYNC_WAN\FR" "1" "9 August 2018" "MariaDB 10\&.1" "MariaDB Database System" +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH NAME +wsrep_sst_rsync_wan \- rsync_wan (rsync with delta transfers)\-based state snapshot transfer +.SH DESCRIPTION +Use: rsync_wan\-based state snapshot transfer\. +.PP +For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/ diff --git a/mysql-test/collections/10.0-compatible.list b/mysql-test/collections/10.0-compatible.list new file mode 100644 index 00000000000..415c74ab00c --- /dev/null +++ b/mysql-test/collections/10.0-compatible.list @@ -0,0 +1,591 @@ +main.1st +main.adddate_454 +main.almost_full +main.alter_table_autoinc-5574 +main.alter_table_errors +main.alter_table_mdev539_maria +main.alter_table_mdev539_myisam +main.alter_table_online +main.alter_table_trans +main.analyze +main.analyze_stmt +main.analyze_stmt_orderby +main.analyze_stmt_slow_query_log +main.ansi +main.assign_key_cache +main.auth_rpl +main.auto_increment +main.auto_increment_ranges_innodb +main.auto_increment_ranges_myisam +main.bad_frm_crash_5029 +main.bench_count_distinct +main.bigint +main.binary +main.binary_to_hex +main.blackhole +main.blackhole_plugin +main.bool +main.bootstrap +main.bug12427262 +main.bug13633383 +main.bug46760 +main.bug47671 +main.bulk_replace +main.case +main.change_user +main.check_constraint_show +main.client_xml +main.comment_column +main.comment_column2 +main.comment_index +main.comments +main.comment_table +main.commit_1innodb +main.compare +main.compound +main.contributors +main.count_distinct +main.count_distinct2 +main.create_drop_db +main.create_drop_event +main.create_drop_function +main.create_drop_index +main.create_drop_procedure +main.create_drop_server +main.create_drop_trigger +main.create_drop_user +main.create_drop_view +main.create_not_windows +main.create_select_tmp +main.create-uca +main.create_user +main.create_w_max_indexes_64 +main.ctype_ascii +main.ctype_big5 +main.ctype_binary +main.ctype_collate +main.ctype_cp1250_ch +main.ctype_cp1251 +main.ctype_cp850 +main.ctype_cp932 +main.ctype_cp932_binlog_row +main.ctype_cp932_binlog_stm +main.ctype_create +main.ctype_eucjpms +main.ctype_euckr +main.ctype_filename +main.ctype_filesystem +main.ctype_gb2312 +main.ctype_gbk +main.ctype_gbk_binlog +main.ctype_gbk_export_import +main.ctype_hebrew +main.ctype_latin1 +main.ctype_latin1_de +main.ctype_latin2 +main.ctype_latin2_ch +main.ctype_ldml +main.ctype_many +main.ctype_mb +main.ctype_nopad_8bit +main.ctype_partitions +main.ctype_recoding +main.ctype_sjis +main.ctype_swe7 +main.ctype_tis620 +main.ctype_uca +main.ctype_uca_innodb +main.ctype_uca_partitions +main.ctype_ucs +main.ctype_ucs2_def +main.ctype_ucs2_query_cache +main.ctype_ucs2_uca +main.ctype_ujis +main.ctype_ujis_ucs2 +main.ctype_upgrade +main.ctype_utf16 +main.ctype_utf16_def +main.ctype_utf16le +main.ctype_utf16_uca +main.ctype_utf32 +main.ctype_utf32_uca +main.ctype_utf8 +main.ctype_utf8mb4 +main.ctype_utf8mb4_heap +main.ctype_utf8mb4_innodb +main.ctype_utf8mb4_myisam +main.ctype_utf8mb4_uca +main.ctype_utf8_uca +main.date_formats +main.datetime_456 +main.default_storage_engine +main.delete +main.delete_returning +main.deprecated_features +main.derived_cond_pushdown +main.derived_opt +main.derived_view +main.distinct +main.drop-no_root +main.dyncol +main.empty_server_name-8224 +main.empty_table +main.endspace +main.enforce_storage_engine_opt +main.errors +main.events_2 +main.events_logs_tests +main.events_microsec +main.events_restart +main.events_scheduling +main.events_slowlog +main.events_trans +main.execution_constants +main.explain +main.explain_json +main.explain_json_format_partitions +main.explain_json_innodb +main.explain_non_select +main.ext_key_noPK_6794 +main.fast_prefix_index_fetch_innodb +main.features +main.filesort_bad_i_s-7585 +main.flush2 +main.foreign_key +main.frm_bad_row_type-7333 +main.fulltext +main.fulltext2 +main.fulltext3 +main.fulltext_cache +main.fulltext_charsets +main.fulltext_derived_4257 +main.fulltext_derived_4316 +main.fulltext_distinct +main.fulltext_left_join +main.fulltext_multi +main.fulltext_order_by +main.fulltext_update +main.fulltext_var +main.func_analyse +main.func_concat +main.func_crypt +main.func_date_add +main.func_default +main.func_des_encrypt +main.func_digest +main.func_encrypt +main.func_encrypt_ucs2 +main.func_equal +main.func_gconcat +main.func_group_innodb +main.func_hybrid_type +main.func_if +main.func_in +main.func_isnull +main.func_like +main.func_math +main.func_op +main.func_regexp +main.func_regexp_pcre +main.func_rollback +main.func_sapdb +main.func_set +main.func_system +main.func_test +main.func_time +main.func_time_hires +main.func_timestamp +main.function_defaults +main.function_defaults_innodb +main.gcc296 +main.get_diagnostics +main.gis +main.gis2 +main.gis-alter_table_online +main.gis-precise +main.gis-rt-precise +main.gis-rtree +main.grant_4332 +main.greedy_optimizer +main.group_by +main.group_by_innodb +main.group_by_null +main.group_min_max +main.group_min_max_innodb +main.handler_read_last +main.handlersocket +main.having +main.help +main.host_cache_size_functionality +main.huge_frm-6224 +main.implicit_char_to_num_conversion +main.implicit_commit +main.in_datetime_241 +main.index_intersect +main.index_intersect_innodb +main.index_merge_innodb +main.index_merge_myisam +main.information_schema2 +main.information_schema_all_engines +main.information_schema_chmod +main.information_schema_inno +main.information_schema_parameters +main.information_schema_part +main.information_schema_routines +main.information_schema_stats +main.init_file +main.init_file_longline_3816 +main.init_file_set_password-7656 +main.innodb_bug878769 +main.innodb_ext_key +main.innodb_group +main.innodb_icp +main.innodb_ignore_builtin +main.innodb_mrr_cpk +main.innodb_utf8 +main.insert +main.insert_innodb +main.insert_select +main.insert_update +main.insert_update_autoinc-7150 +main.join +main.join_cache +main.join_crash +main.join_nested +main.join_nested_jcl6 +main.join_optimizer +main.join_outer +main.join_outer_innodb +main.join_outer_jcl6 +main.key +main.key_cache +main.key_diff +main.key_primary +main.keyread +main.keywords +main.last_value +main.limit +main.limit_rows_examined +main.loaddata_autocom_innodb +main.locale +main.log_errchk +main.log_slow +main.log_state_bug33693 +main.log_tables_upgrade +main.long_tmpdir +main.lowercase_mixed_tmpdir +main.lowercase_table +main.lowercase_table5 +main.lowercase_table_grant +main.lowercase_table_qcache +main.lowercase_utf8 +main.lowercase_view +main.mdev13607 +main.mdev_14586 +main.mdev316 +main.mdl +main.merge_innodb +main.merge_mmap +main.metadata +main.mix2_myisam_ucs2 +main.mrr_derived_crash_4610 +main.mrr_icp_extra +main.multi_statement +main.multi_update2 +main.multi_update_innodb +main.multi_update_tiny_hash +main.myisam-blob +main.myisam_enable_keys-10506 +main.myisam_explain_non_select_all +main.myisam_icp +main.myisam_mrr +main.myisampack +main.myisam-system +main.mysql +main.mysql5613mysql +main.mysql57_virtual +main.mysqladmin +main.mysql_binary_mode +main.mysqlcheck +main.mysql_comments +main.mysql_cp932 +main.mysqld--defaults-file +main.mysqld--help +main.mysqld_help_crash-9183 +main.mysqld_option_err +main.mysqldump-compat +main.mysqldump-nl +main.mysqldump-no-binlog +main.mysqldump_restore +main.mysql_not_windows +main.mysql_protocols +main.mysqlshow +main.mysqlslap +main.mysqltest_256 +main.mysqltest_cont_on_error +main.mysql_tzinfo_to_sql_symlink +main.mysql_upgrade_noengine +main.mysql_upgrade_no_innodb +main.mysql_upgrade_ssl +main.mysql_upgrade_view +main.negation_elimination +main.no_binlog +main.no_password_column-mdev-11170 +main.null +main.null_key +main.odbc +main.olap +main.old-mode +main.order_by +main.order_by_innodb +main.order_by-mdev-10122 +main.order_by_optimizer +main.order_by_optimizer_innodb +main.order_by_sortkey +main.order_by_zerolength-4285 +main.order_fill_sortbuf +main.outfile_loaddata +main.parser +main.parser_bug21114_innodb +main.parser_precedence +main.parser_stack +main.partition +main.partition_binlog +main.partition_binlog_stmt +main.partition_blackhole +main.partition_bug18198 +main.partition_cache_innodb +main.partition_cache_myisam +main.partition_charset +main.partition_column +main.partition_column_prune +main.partition_datatype +main.partition_disabled +main.partition_error +main.partition_example +main.partition_exchange +main.partition_explicit_prune +main.partition_hash +main.partition_key_cache +main.partition_list +main.partition_mgm +main.partition_mgm_err +main.partition_mgm_err2 +main.partition_myisam +main.partition_not_blackhole +main.partition_not_windows +main.partition_order +main.partition_pruning +main.partition_range +main.partition_rename_longfilename +main.partition_truncate +main.partition_utf8 +main.perror +main.plugin +main.plugin_auth_qa +main.plugin_auth_qa_2 +main.plugin_auth_qa_3 +main.plugin_innodb +main.plugin_load +main.plugin_loaderr +main.plugin_load_option +main.plugin_maturity +main.preload +main.profiling +main.progress_976225 +main.ps_10nestset +main.ps_11bugs +main.ps_1general +main.ps_2myisam +main.ps_3innodb +main.ps_4heap +main.ps_5merge +main.ps_change_master +main.ps_ddl1 +main.ps_max_subselect-5113 +main.ps_not_windows +main.query_cache +main.query_cache_innodb +main.query_cache_merge +main.query_cache_with_views +main.range +main.range_innodb +main.range_mrr_icp +main.range_vs_index_merge +main.range_vs_index_merge_innodb +main.renamedb +main.reopen_temp_table +main.repair +main.repair_symlink-5543 +main.replace +main.rollback +main.round +main.row +main.row-checksum +main.row-checksum-old +main.rowid_order_innodb +main.rpl_mysqldump_slave +main.second_frac-9175 +main.select +main.select_found +main.selectivity +main.selectivity_innodb +main.selectivity_no_engine +main.select_jcl6 +main.select_pkeycache +main.select_safe +main.servers +main.set_password +main.set_statement_notembedded +main.set_statement_notembedded_binlog +main.show +main.show_bad_definer-5553 +main.show_create_user +main.show_function_with_pad_char_to_full_length +main.show_profile +main.show_row_order-9226 +main.sighup-6580 +main.signal +main.signal_demo1 +main.signal_demo2 +main.signal_demo3 +main.signal_sqlmode +main.single_delete_update +main.single_delete_update_innodb +main.skip_grants +main.skip_log_bin +main.sp-big +main.sp-bugs +main.sp-bugs2 +main.sp-destruct +main.sp-dynamic +main.sp-error +main.sp-fib +main.sp_gis +main.sp-group +main.sp_missing_4665 +main.sp-no-code +main.sp-prelocking +main.sp_stress_case +main.sp_trans +main.sp_trans_log +main.sp-ucs2 +main.sp-vars +main.ssl_7937 +main.ssl_8k_key +main.ssl_and_innodb +main.ssl_ca +main.ssl_cert_verify +main.ssl_connect +main.ssl_crl_clients +main.stack-crash +main.statistics +main.statistics_index_crash-7362 +main.stat_tables +main.stat_tables_disabled +main.stat_tables_innodb +main.stat_tables_partition +main.stat_tables_repl +main.strict +main.strict_autoinc_1myisam +main.strict_autoinc_2innodb +main.strict_autoinc_3heap +main.str_to_datetime_457 +main.subselect2 +main.subselect3 +main.subselect3_jcl6 +main.subselect4 +main.subselect_cache +main.subselect-crash_15755 +main.subselect_exists2in +main.subselect_exists2in_costmat +main.subselect_extra +main.subselect_extra_no_semijoin +main.subselect_gis +main.subselect_innodb +main.subselect_mat +main.subselect_mat_cost +main.subselect_mat_cost_bugs +main.subselect_notembedded +main.subselect_nulls +main.subselect_partial_match +main.subselect_sj2 +main.subselect_sj2_jcl6 +main.subselect_sj2_mat +main.subselect_sj_aria +main.subselect_sj_mat +main.subselect_sj_nonmerged +main.sum_distinct +main.sysdate_is_now +main.system_mysql_db +main.system_mysql_db_refs +main.table_elim +main.table_elim_debug +main.table_keyinfo-6838 +main.tablelock +main.table_options +main.table_options-5867 +main.temporal_literal +main.temporal_scale_4283 +main.temp_table_frm +main.timezone +main.timezone2 +main.timezone3 +main.timezone4 +main.tmp_table_count-7586 +main.trigger_no_defaults-11698 +main.trigger_null-8605 +main.truncate +main.truncate_badse +main.truncate-stale-6500 +main.type_binary +main.type_bit +main.type_bit_innodb +main.type_blob +main.type_datetime_hires +main.type_decimal +main.type_enum +main.type_float +main.type_int +main.type_nchar +main.type_newdecimal +main.type_num +main.type_num_innodb +main.type_ranges +main.type_set +main.type_temporal_innodb +main.type_temporal_mysql56 +main.type_time +main.type_time_6065 +main.type_time_hires +main.type_timestamp_hires +main.type_uint +main.type_varchar +main.type_year +main.update_ignore_216 +main.update_innodb +main.upgrade +main.user_var +main.varbinary +main.variables_community +main.view_alias +main.warnings_engine_disabled +main.win_avg +main.win_big +main.win_big-mdev-10092 +main.win_big-mdev-11697 +main.win_bit +main.win_empty_over +main.win_first_last_value +main.win_insert_select +main.win_i_s +main.win_lead_lag +main.win_min_max +main.win_nth_value +main.win_orderby +main.win_percent_cume +main.win_rank +main.win_sum +main.xa_binlog +main.xml +main.xtradb_mrr diff --git a/mysql-test/include/search_pattern_in_file.inc b/mysql-test/include/search_pattern_in_file.inc index 21192b55efb..6bead628fb0 100644 --- a/mysql-test/include/search_pattern_in_file.inc +++ b/mysql-test/include/search_pattern_in_file.inc @@ -18,6 +18,11 @@ # Optionally, SEARCH_ABORT can be set to "FOUND" or "NOT FOUND" and this # will abort if the search result doesn't match the requested one. # +# Optionally, SEARCH_OUTPUT can be set to control the format of output. +# Supported formats: +# - (default) : "FOUND n /pattern/ in FILE " or "NOT FOUND ..." +# - "matches" : Each match is printed, on a separate line +# # In case of # - SEARCH_FILE and/or SEARCH_PATTERN is not set # - SEARCH_FILE cannot be opened @@ -75,7 +80,14 @@ perl; my @matches=($content =~ m/$search_pattern/gs); my $res=@matches ? "FOUND " . scalar(@matches) : "NOT FOUND"; $ENV{SEARCH_FILE} =~ s{^.*?([^/\\]+)$}{$1}; - print "$res /$search_pattern/ in $ENV{SEARCH_FILE}\n"; + + if ($ENV{SEARCH_OUTPUT} eq "matches") { + foreach (@matches) { + print $_ . "\n"; + } + } else { + print "$res /$search_pattern/ in $ENV{SEARCH_FILE}\n"; + } die "$ENV{SEARCH_ABORT}\n" - if $ENV{SEARCH_ABORT} && $res =~ /^$ENV{SEARCH_ABORT}/; + if $ENV{SEARCH_ABORT} && $res =~ /^$ENV{SEARCH_ABORT}/; EOF diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 2c983e3de3e..a1120ba6de7 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -16027,6 +16027,374 @@ a aa DROP FUNCTION f1; # +# MDEV-17011: condition pushdown into materialized derived used +# in INSERT SELECT, multi-table UPDATE and DELETE +# +CREATE TABLE t1 (a int ,b int) ENGINE=MyISAM; +INSERT INTO t1 VALUES +(1, 1), (1, 2), (2, 1), (2, 2), (3,1), (3,3), (4,2); +CREATE TABLE t2 (a int) ENGINE MYISAM; +INSERT INTO t2 VALUES +(3), (7), (1), (4), (1); +CREATE TABLE t3 (a int, b int) ENGINE MYISAM; +EXPLAIN FORMAT=JSON INSERT INTO t3 +SELECT * FROM (SELECT a, count(*) as c FROM t1 GROUP BY a) t WHERE a<=2; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 7, + "filtered": 100, + "attached_condition": "t.a <= 2", + "materialized": { + "query_block": { + "select_id": 2, + "filesort": { + "sort_key": "t1.a", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 7, + "filtered": 100, + "attached_condition": "t1.a <= 2" + } + } + } + } + } + } + } +} +INSERT INTO t3 +SELECT * FROM (SELECT a, count(*) as c FROM t1 GROUP BY a) t WHERE a<=2; +SELECT * FROM t3; +a b +1 2 +2 2 +EXPLAIN FORMAT=JSON UPDATE t2, (SELECT a, count(*) as c FROM t1 GROUP BY a) t SET t2.a=t.c+10 +WHERE t2.a= t.c and t.a>=3; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 5, + "filtered": 100, + "attached_condition": "t2.a is not null" + }, + "table": { + "table_name": "", + "access_type": "ref", + "possible_keys": ["key0"], + "key": "key0", + "key_length": "8", + "used_key_parts": ["c"], + "ref": ["test.t2.a"], + "rows": 2, + "filtered": 100, + "attached_condition": "t2.a = t.c and t.a >= 3", + "materialized": { + "query_block": { + "select_id": 2, + "filesort": { + "sort_key": "t1.a", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 7, + "filtered": 100, + "attached_condition": "t1.a >= 3" + } + } + } + } + } + } + } +} +UPDATE t2, (SELECT a, count(*) as c FROM t1 GROUP BY a) t SET t2.a=t.c+10 +WHERE t2.a= t.c and t.a>=3; +SELECT * FROM t2; +a +3 +7 +11 +4 +11 +EXPLAIN FORMAT=JSON DELETE t2 FROM t2, (SELECT a, count(*) as c FROM t1 GROUP BY a) t +WHERE t2.a= t.c+9 and t.a=2; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 5, + "filtered": 100 + }, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 7, + "filtered": 100, + "attached_condition": "t.a = 2 and t2.a = t.c + 9", + "materialized": { + "query_block": { + "select_id": 2, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 7, + "filtered": 100, + "attached_condition": "t1.a = 2" + } + } + } + } + } +} +DELETE t2 FROM t2, (SELECT a, count(*) as c FROM t1 GROUP BY a) t +WHERE t2.a= t.c+9 and t.a=2; +SELECT * FROM t2; +a +3 +7 +4 +DROP TABLE t1,t2,t3; +# +# MDEV-16765: pushdown condition with the CASE structure +# defined with Item_cond item +# +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (1,2), (3,4), (2,3); +SELECT * +FROM +( +SELECT CASE WHEN ((tab2.max_a=1) OR (tab2.max_a=2)) +THEN 1 ELSE 0 END AS max_a,b +FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2 +) AS tab1 +WHERE (tab1.max_a=1); +max_a b +1 2 +1 3 +EXPLAIN FORMAT=JSON SELECT * +FROM +( +SELECT CASE WHEN ((tab2.max_a=1) OR (tab2.max_a=2)) +THEN 1 ELSE 0 END AS max_a,b +FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2 +) AS tab1 +WHERE (tab1.max_a=1); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 3, + "filtered": 100, + "attached_condition": "case when (tab2.max_a = 1 or tab2.max_a = 2) then 1 else 0 end = 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "case when (max_a = 1 or max_a = 2) then 1 else 0 end = 1", + "filesort": { + "sort_key": "t1.b", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 3, + "filtered": 100 + } + } + } + } + } + } + } +} +SELECT * +FROM +( +SELECT CASE WHEN ((tab2.max_a=1) OR ((tab2.max_a>2) AND (tab2.max_a<4))) +THEN 1 ELSE 0 END AS max_a,b +FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2 +) AS tab1 +WHERE (tab1.max_a=1); +max_a b +1 2 +1 4 +EXPLAIN FORMAT=JSON SELECT * +FROM +( +SELECT CASE WHEN ((tab2.max_a=1) OR ((tab2.max_a>2) AND (tab2.max_a<4))) +THEN 1 ELSE 0 END AS max_a,b +FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2 +) AS tab1 +WHERE (tab1.max_a=1); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 3, + "filtered": 100, + "attached_condition": "case when (tab2.max_a = 1 or tab2.max_a > 2 and tab2.max_a < 4) then 1 else 0 end = 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "case when (max_a = 1 or max_a > 2 and max_a < 4) then 1 else 0 end = 1", + "filesort": { + "sort_key": "t1.b", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 3, + "filtered": 100 + } + } + } + } + } + } + } +} +SELECT * +FROM +( +SELECT CASE WHEN ((tab2.max_a>1) AND ((tab2.max_a=2) OR (tab2.max_a>2))) +THEN 1 ELSE 0 END AS max_a,b +FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2 +) AS tab1 +WHERE (tab1.max_a=1); +max_a b +1 3 +1 4 +EXPLAIN FORMAT=JSON SELECT * +FROM +( +SELECT CASE WHEN ((tab2.max_a>1) AND ((tab2.max_a=2) OR (tab2.max_a>2))) +THEN 1 ELSE 0 END AS max_a,b +FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2 +) AS tab1 +WHERE (tab1.max_a=1); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 3, + "filtered": 100, + "attached_condition": "case when (tab2.max_a > 1 and (tab2.max_a = 2 or tab2.max_a > 2)) then 1 else 0 end = 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "case when (max_a > 1 and (max_a = 2 or max_a > 2)) then 1 else 0 end = 1", + "filesort": { + "sort_key": "t1.b", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 3, + "filtered": 100 + } + } + } + } + } + } + } +} +SELECT * +FROM +( +SELECT CASE WHEN ((tab2.b=2) OR (tab2.b=4)) +THEN 1 ELSE 0 END AS max_a,b +FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2 +) AS tab1 +WHERE (tab1.max_a=1); +max_a b +1 2 +1 4 +EXPLAIN FORMAT=JSON SELECT * +FROM +( +SELECT CASE WHEN ((tab2.b=2) OR (tab2.b=4)) +THEN 1 ELSE 0 END AS max_a,b +FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2 +) AS tab1 +WHERE (tab1.max_a=1); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 3, + "filtered": 100, + "attached_condition": "case when (tab2.b = 2 or tab2.b = 4) then 1 else 0 end = 1", + "materialized": { + "query_block": { + "select_id": 3, + "filesort": { + "sort_key": "t1.b", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 3, + "filtered": 100, + "attached_condition": "case when (t1.b = 2 or t1.b = 4) then 1 else 0 end = 1" + } + } + } + } + } + } + } +} +DROP TABLE t1; +# +# MDEV-16803: pushdown condition with IN predicate in the derived table +# defined with several SELECT statements +# +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,2),(3,2),(1,1); +SELECT * FROM +( +SELECT a,b,1 as c +FROM t1 +UNION ALL +SELECT a,b,2 as c +FROM t1 +) AS tab +WHERE ((a,b) IN ((1,2),(3,2))); +a b c +1 2 1 +3 2 1 +1 2 2 +3 2 2 +DROP TABLE t1; +# Start of 10.3 tests +# # MDEV-16801: splittable materialized derived/views with # one grouping field from table without keys # diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index b75c56e9ff2..61541d2cdf5 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -2987,6 +2987,130 @@ DELIMITER ;$$ SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1)); DROP FUNCTION f1; +--echo # +--echo # MDEV-17011: condition pushdown into materialized derived used +--echo # in INSERT SELECT, multi-table UPDATE and DELETE +--echo # + +CREATE TABLE t1 (a int ,b int) ENGINE=MyISAM; +INSERT INTO t1 VALUES + (1, 1), (1, 2), (2, 1), (2, 2), (3,1), (3,3), (4,2); + +CREATE TABLE t2 (a int) ENGINE MYISAM; +INSERT INTO t2 VALUES + (3), (7), (1), (4), (1); + +CREATE TABLE t3 (a int, b int) ENGINE MYISAM; + +let $q1= +INSERT INTO t3 +SELECT * FROM (SELECT a, count(*) as c FROM t1 GROUP BY a) t WHERE a<=2; + +eval EXPLAIN FORMAT=JSON $q1; +eval $q1; + +SELECT * FROM t3; + +let $q2= +UPDATE t2, (SELECT a, count(*) as c FROM t1 GROUP BY a) t SET t2.a=t.c+10 + WHERE t2.a= t.c and t.a>=3; + +eval EXPLAIN FORMAT=JSON $q2; +eval $q2; + +SELECT * FROM t2; + +let $q3= +DELETE t2 FROM t2, (SELECT a, count(*) as c FROM t1 GROUP BY a) t + WHERE t2.a= t.c+9 and t.a=2; + +eval EXPLAIN FORMAT=JSON $q3; +eval $q3; + +SELECT * FROM t2; + +DROP TABLE t1,t2,t3; + +--echo # +--echo # MDEV-16765: pushdown condition with the CASE structure +--echo # defined with Item_cond item +--echo # + +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (1,2), (3,4), (2,3); + +LET $query= +SELECT * +FROM +( + SELECT CASE WHEN ((tab2.max_a=1) OR (tab2.max_a=2)) + THEN 1 ELSE 0 END AS max_a,b + FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2 +) AS tab1 +WHERE (tab1.max_a=1); +EVAL $query; +EVAL EXPLAIN FORMAT=JSON $query; + +LET $query= +SELECT * +FROM +( + SELECT CASE WHEN ((tab2.max_a=1) OR ((tab2.max_a>2) AND (tab2.max_a<4))) + THEN 1 ELSE 0 END AS max_a,b + FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2 +) AS tab1 +WHERE (tab1.max_a=1); +EVAL $query; +EVAL EXPLAIN FORMAT=JSON $query; + +LET $query= +SELECT * +FROM +( + SELECT CASE WHEN ((tab2.max_a>1) AND ((tab2.max_a=2) OR (tab2.max_a>2))) + THEN 1 ELSE 0 END AS max_a,b + FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2 +) AS tab1 +WHERE (tab1.max_a=1); +EVAL $query; +EVAL EXPLAIN FORMAT=JSON $query; + +LET $query= +SELECT * +FROM +( + SELECT CASE WHEN ((tab2.b=2) OR (tab2.b=4)) + THEN 1 ELSE 0 END AS max_a,b + FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2 +) AS tab1 +WHERE (tab1.max_a=1); +EVAL $query; +EVAL EXPLAIN FORMAT=JSON $query; + +DROP TABLE t1; + +--echo # +--echo # MDEV-16803: pushdown condition with IN predicate in the derived table +--echo # defined with several SELECT statements +--echo # + +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,2),(3,2),(1,1); + +SELECT * FROM +( + SELECT a,b,1 as c + FROM t1 + UNION ALL + SELECT a,b,2 as c + FROM t1 +) AS tab +WHERE ((a,b) IN ((1,2),(3,2))); + +DROP TABLE t1; + +--echo # Start of 10.3 tests + --echo # --echo # MDEV-16801: splittable materialized derived/views with --echo # one grouping field from table without keys diff --git a/mysql-test/main/func_isnull.result b/mysql-test/main/func_isnull.result index 15d87997e29..8cbd528f2de 100644 --- a/mysql-test/main/func_isnull.result +++ b/mysql-test/main/func_isnull.result @@ -106,5 +106,25 @@ Note 1003 select `test`.`t2`.`d1` AS `d1`,`test`.`t1`.`d1` AS `d1` from `test`.` DROP VIEW v1; DROP TABLE t1,t2; # +# MDEV-15475: Assertion `!table || (!table->read_set || +# bitmap_is_set(table->read_set, field_index))' +# failed on EXPLAIN EXTENDED with constant table and view +# +CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=MyISAM; +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1); +EXPLAIN EXTENDED SELECT ISNULL(pk) FROM v1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00 +Warnings: +Note 1003 select /*always not null*/ 1 is null AS `ISNULL(pk)` from dual +EXPLAIN EXTENDED SELECT IFNULL(pk,0) FROM v1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00 +Warnings: +Note 1003 select ifnull(1,0) AS `IFNULL(pk,0)` from dual +DROP VIEW v1; +DROP TABLE t1; +# # End of 5.5 tests # diff --git a/mysql-test/main/func_isnull.test b/mysql-test/main/func_isnull.test index 4c59fa3cbe8..7d1a7e83a1a 100644 --- a/mysql-test/main/func_isnull.test +++ b/mysql-test/main/func_isnull.test @@ -83,6 +83,22 @@ SELECT * FROM t2 LEFT JOIN v1 ON t2.d1=v1.d1 WHERE v1.d1 IS NULL; DROP VIEW v1; DROP TABLE t1,t2; + +--echo # +--echo # MDEV-15475: Assertion `!table || (!table->read_set || +--echo # bitmap_is_set(table->read_set, field_index))' +--echo # failed on EXPLAIN EXTENDED with constant table and view +--echo # + +CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=MyISAM; +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1); +EXPLAIN EXTENDED SELECT ISNULL(pk) FROM v1; +EXPLAIN EXTENDED SELECT IFNULL(pk,0) FROM v1; +# Cleanup +DROP VIEW v1; +DROP TABLE t1; + --echo # --echo # End of 5.5 tests --echo # diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result index b6f9ca8e628..840db182fe7 100644 --- a/mysql-test/main/func_time.result +++ b/mysql-test/main/func_time.result @@ -2805,6 +2805,11 @@ SEC_TO_TIME(MAKEDATE(0,RAND(~0))) 838:59:59 Warnings: Warning 1292 Truncated incorrect seconds value: '20000101' +SELECT PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli')); +PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli')) +24257 +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '-3S\xFA\xDE?\x00\x00\xCA\xB3\xEEE\xA4\xD1\xC1\xA8' # # End of 5.5 tests # @@ -3578,6 +3583,7 @@ DROP TABLE t1; # # MDEV-15363 Wrong result for CAST(LAST_DAY(TIME'00:00:00') AS TIME) # +set timestamp=unix_timestamp('2018-08-02 10:10:10'); SELECT LAST_DAY(TIME'00:00:00') AS c1, CAST(CAST(LAST_DAY(TIME'00:00:00') AS DATE) AS TIME) AS c2, diff --git a/mysql-test/main/func_time.test b/mysql-test/main/func_time.test index b03c14fb8ba..aebe3df761f 100644 --- a/mysql-test/main/func_time.test +++ b/mysql-test/main/func_time.test @@ -1705,6 +1705,10 @@ DO TO_DAYS(SEC_TO_TIME(TIME(CEILING(UUID())))); DO TO_DAYS(SEC_TO_TIME(MAKEDATE('',RAND(~(''))))); SELECT SEC_TO_TIME(MAKEDATE(0,RAND(~0))); +# +# MDEV-16810 AddressSanitizer: stack-buffer-overflow in int10_to_str +# +SELECT PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli')); --echo # --echo # End of 5.5 tests @@ -2158,6 +2162,7 @@ DROP TABLE t1; --echo # MDEV-15363 Wrong result for CAST(LAST_DAY(TIME'00:00:00') AS TIME) --echo # +set timestamp=unix_timestamp('2018-08-02 10:10:10'); SELECT LAST_DAY(TIME'00:00:00') AS c1, CAST(CAST(LAST_DAY(TIME'00:00:00') AS DATE) AS TIME) AS c2, diff --git a/mysql-test/main/group_min_max.result b/mysql-test/main/group_min_max.result index 36a44b05817..b3b660c4170 100644 --- a/mysql-test/main/group_min_max.result +++ b/mysql-test/main/group_min_max.result @@ -3893,5 +3893,22 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index a a 13 NULL 2 Using where; Using index drop table t1; # +# MDEV-15433: Optimizer does not use group by optimization with distinct +# +CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, a INT NOT NULL, KEY(a)); +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +EXPLAIN SELECT DISTINCT a FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL a 4 NULL 5 Using index for group-by +SELECT DISTINCT a FROM t1; +a +1 +2 +3 +4 +drop table t1; +# # End of 10.1 tests # diff --git a/mysql-test/main/group_min_max.test b/mysql-test/main/group_min_max.test index b0bc42d7f8c..adad9073235 100644 --- a/mysql-test/main/group_min_max.test +++ b/mysql-test/main/group_min_max.test @@ -1608,6 +1608,33 @@ explain select min(a) from t1 where a between "a" and "Cafeeeeeeeeeeeeeeeeeeeeee explain select min(a) from t1 where a between "abbbbbbbbbbbbbbbbbbbb" and "Cafe2"; drop table t1; +--echo # +--echo # MDEV-15433: Optimizer does not use group by optimization with distinct +--echo # + +CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, a INT NOT NULL, KEY(a)); +--disable_query_log +INSERT INTO t1(a) VALUES (1), (2), (3), (4); +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +--enable_query_log +OPTIMIZE TABLE t1; +EXPLAIN SELECT DISTINCT a FROM t1; +SELECT DISTINCT a FROM t1; +drop table t1; + --echo # --echo # End of 10.1 tests --echo # diff --git a/mysql-test/main/information_schema-big.result b/mysql-test/main/information_schema-big.result index cbd8191bc54..d4aa6deb2e2 100644 --- a/mysql-test/main/information_schema-big.result +++ b/mysql-test/main/information_schema-big.result @@ -20,6 +20,7 @@ table_name column_name ALL_PLUGINS PLUGIN_NAME APPLICABLE_ROLES GRANTEE CHARACTER_SETS CHARACTER_SET_NAME +CHECK_CONSTRAINTS CONSTRAINT_SCHEMA CLIENT_STATISTICS CLIENT COLLATIONS COLLATION_NAME COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME @@ -77,6 +78,7 @@ table_name column_name ALL_PLUGINS PLUGIN_NAME APPLICABLE_ROLES GRANTEE CHARACTER_SETS CHARACTER_SET_NAME +CHECK_CONSTRAINTS CONSTRAINT_SCHEMA CLIENT_STATISTICS CLIENT COLLATIONS COLLATION_NAME COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME diff --git a/mysql-test/main/information_schema.result b/mysql-test/main/information_schema.result index 6e987dd3266..b6e331a0382 100644 --- a/mysql-test/main/information_schema.result +++ b/mysql-test/main/information_schema.result @@ -51,6 +51,7 @@ c ALL_PLUGINS APPLICABLE_ROLES CHARACTER_SETS +CHECK_CONSTRAINTS CLIENT_STATISTICS COLLATIONS COLLATION_CHARACTER_SET_APPLICABILITY @@ -937,6 +938,7 @@ connection user10261; SELECT TABLE_NAME, COLUMN_NAME, PRIVILEGES FROM INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME='TABLE_NAME' and table_name not like 'innodb%'; TABLE_NAME COLUMN_NAME PRIVILEGES +CHECK_CONSTRAINTS TABLE_NAME select COLUMNS TABLE_NAME select COLUMN_PRIVILEGES TABLE_NAME select FILES TABLE_NAME select diff --git a/mysql-test/main/information_schema_all_engines.result b/mysql-test/main/information_schema_all_engines.result index 126a6f4bccd..0ce9f15f753 100644 --- a/mysql-test/main/information_schema_all_engines.result +++ b/mysql-test/main/information_schema_all_engines.result @@ -4,6 +4,7 @@ Tables_in_information_schema ALL_PLUGINS APPLICABLE_ROLES CHARACTER_SETS +CHECK_CONSTRAINTS CLIENT_STATISTICS COLLATIONS COLLATION_CHARACTER_SET_APPLICABILITY @@ -83,6 +84,7 @@ table_name column_name ALL_PLUGINS PLUGIN_NAME APPLICABLE_ROLES GRANTEE CHARACTER_SETS CHARACTER_SET_NAME +CHECK_CONSTRAINTS CONSTRAINT_SCHEMA CLIENT_STATISTICS CLIENT COLLATIONS COLLATION_NAME COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME @@ -162,6 +164,7 @@ table_name column_name ALL_PLUGINS PLUGIN_NAME APPLICABLE_ROLES GRANTEE CHARACTER_SETS CHARACTER_SET_NAME +CHECK_CONSTRAINTS CONSTRAINT_SCHEMA CLIENT_STATISTICS CLIENT COLLATIONS COLLATION_NAME COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME @@ -247,6 +250,7 @@ table_name group_concat(t.table_schema, '.', t.table_name) num1 ALL_PLUGINS information_schema.ALL_PLUGINS 1 APPLICABLE_ROLES information_schema.APPLICABLE_ROLES 1 CHARACTER_SETS information_schema.CHARACTER_SETS 1 +CHECK_CONSTRAINTS information_schema.CHECK_CONSTRAINTS 1 CLIENT_STATISTICS information_schema.CLIENT_STATISTICS 1 COLLATIONS information_schema.COLLATIONS 1 COLLATION_CHARACTER_SET_APPLICABILITY information_schema.COLLATION_CHARACTER_SET_APPLICABILITY 1 @@ -315,6 +319,7 @@ Database: information_schema | ALL_PLUGINS | | APPLICABLE_ROLES | | CHARACTER_SETS | +| CHECK_CONSTRAINTS | | CLIENT_STATISTICS | | COLLATIONS | | COLLATION_CHARACTER_SET_APPLICABILITY | @@ -384,6 +389,7 @@ Database: INFORMATION_SCHEMA | ALL_PLUGINS | | APPLICABLE_ROLES | | CHARACTER_SETS | +| CHECK_CONSTRAINTS | | CLIENT_STATISTICS | | COLLATIONS | | COLLATION_CHARACTER_SET_APPLICABILITY | @@ -453,5 +459,5 @@ Wildcard: inf_rmation_schema | information_schema | SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') GROUP BY TABLE_SCHEMA; table_schema count(*) -information_schema 64 +information_schema 65 mysql 30 diff --git a/mysql-test/main/mysql.result b/mysql-test/main/mysql.result index 09f014da627..06ef7e95bc9 100644 --- a/mysql-test/main/mysql.result +++ b/mysql-test/main/mysql.result @@ -538,8 +538,6 @@ a # # End of 10.1 tests # -ERROR 1300 (HY000): Invalid utf8 character string: 'test\xF0\x9F\x98\x81 ' -ERROR 1300 (HY000): Invalid binary character string: 'test\xF0\x9F\x98\x81 ' ERROR 1300 (HY000) at line 2: Invalid utf8 character string: 'test\xF0\x9F\x98\x81' set GLOBAL sql_mode=default; diff --git a/mysql-test/main/mysql.test b/mysql-test/main/mysql.test index 01953ba2112..c65860eb822 100644 --- a/mysql-test/main/mysql.test +++ b/mysql-test/main/mysql.test @@ -638,10 +638,7 @@ EOF --echo # End of 10.1 tests --echo # ---error 1 ---exec $MYSQL --default-character-set=utf8 -e "select 1" "test😁 " 2>&1 ---error 1 ---exec $MYSQL --default-character-set=binary -e "select 1" "test😁 " 2>&1 + --write_file $MYSQLTEST_VARDIR/tmp/mdev-6572.sql SET NAMES utf8; USE test😁 ; diff --git a/mysql-test/main/mysql_not_windows.result b/mysql-test/main/mysql_not_windows.result index 1df62d9a12d..96210a366a6 100644 --- a/mysql-test/main/mysql_not_windows.result +++ b/mysql-test/main/mysql_not_windows.result @@ -9,3 +9,5 @@ End of tests 2 X 3 +ERROR 1300 (HY000): Invalid utf8 character string: 'test\xF0\x9F\x98\x81 ' +ERROR 1300 (HY000): Invalid binary character string: 'test\xF0\x9F\x98\x81 ' diff --git a/mysql-test/main/mysql_not_windows.test b/mysql-test/main/mysql_not_windows.test index 591de74cbbf..816160c4f3e 100644 --- a/mysql-test/main/mysql_not_windows.test +++ b/mysql-test/main/mysql_not_windows.test @@ -22,3 +22,10 @@ exec $MYSQL test -e "select let $query = select 3 as X; exec $MYSQL test -e "$query"; + +# Not ran on Windows, since non-ASCII does not work on command line. +# (MDEV-16220) +--error 1 +--exec $MYSQL --default-character-set=utf8 -e "select 1" "test😁 " 2>&1 +--error 1 +--exec $MYSQL --default-character-set=binary -e "select 1" "test😁 " 2>&1 diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index ac490afe229..8032702ffbb 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -231,6 +231,11 @@ The following specify which files/extra groups are read (specified before remain cache, etc) --enforce-storage-engine=name Force the use of a storage engine for new tables + --eq-range-index-dive-limit=# + The optimizer will use existing index statistics instead + of doing index dives for equality ranges if the number of + equality ranges for the index is larger than or equal to + this number. If set to 0, index dives are always used. --event-scheduler[=name] Enable the event scheduler. Possible values are ON, OFF, and DISABLED (keep the event scheduler completely @@ -1404,6 +1409,7 @@ encrypt-binlog FALSE encrypt-tmp-disk-tables FALSE encrypt-tmp-files FALSE enforce-storage-engine (No default value) +eq-range-index-dive-limit 0 event-scheduler OFF expensive-subquery-limit 100 expire-logs-days 0 diff --git a/mysql-test/main/opt_tvc.result b/mysql-test/main/opt_tvc.result index 0ecae5bf157..fdbd932a433 100644 --- a/mysql-test/main/opt_tvc.result +++ b/mysql-test/main/opt_tvc.result @@ -486,34 +486,32 @@ a b deallocate prepare stmt; # use inside out access from tvc rows set @@in_predicate_conversion_threshold= default; -select * from t3 where a in (1,4,10); +select * from t3 where a in (1,4); a b 1 abc 1 todd 1 sm 4 yq -10 abc -explain extended select * from t3 where a in (1,4,10); +explain extended select * from t3 where a in (1,4); id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t3 range idx idx 5 NULL 5 100.00 Using index condition +1 SIMPLE t3 range idx idx 5 NULL 4 100.00 Using index condition Warnings: -Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t3` where `test`.`t3`.`a` in (1,4,10) +Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t3` where `test`.`t3`.`a` in (1,4) set @@in_predicate_conversion_threshold= 2; -select * from t3 where a in (1,4,10); +select * from t3 where a in (1,4); a b 1 abc 1 todd 1 sm 4 yq -10 abc -explain extended select * from t3 where a in (1,4,10); +explain extended select * from t3 where a in (1,4); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY ALL distinct_key NULL NULL NULL 2 100.00 1 PRIMARY t3 ref idx idx 5 tvc_0.1 3 100.00 2 MATERIALIZED ALL NULL NULL NULL NULL 2 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t3` semi join ((values (1),(4),(10)) `tvc_0`) where `test`.`t3`.`a` = `tvc_0`.`1` +Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t3` semi join ((values (1),(4)) `tvc_0`) where `test`.`t3`.`a` = `tvc_0`.`1` # use vectors in IN predeicate set @@in_predicate_conversion_threshold= 4; select * from t1 where (a,b) in ((1,2),(3,4)); @@ -540,9 +538,9 @@ explain extended select * from t2 where (a,b) in ((1,2),(8,9)) and (a,c) in ((1,3),(8,0),(5,1)); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY ALL distinct_key NULL NULL NULL 2 100.00 +1 PRIMARY ALL distinct_key NULL NULL NULL 3 100.00 1 PRIMARY t2 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join) -2 MATERIALIZED ALL NULL NULL NULL NULL 2 100.00 +2 MATERIALIZED ALL NULL NULL NULL NULL 3 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` semi join ((values (1,3),(8,0),(5,1)) `tvc_0`) where `test`.`t2`.`a` = `tvc_0`.`1` and `test`.`t2`.`c` = `tvc_0`.`3` and (`tvc_0`.`1`,`test`.`t2`.`b`) in (((1,2)),((8,9))) @@ -570,7 +568,7 @@ explain extended select * from t1 where (a,b) not in ((1,2),(8,9), (5,1)); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where -2 MATERIALIZED ALL NULL NULL NULL NULL 2 100.00 +2 MATERIALIZED ALL NULL NULL NULL NULL 3 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where !<`test`.`t1`.`a`,`test`.`t1`.`b`>(((`test`.`t1`.`a`,`test`.`t1`.`b`),(`test`.`t1`.`a`,`test`.`t1`.`b`) in ( (/* select#2 */ select `tvc_0`.`1`,`tvc_0`.`2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), (`test`.`t1`.`a` in on distinct_key where `test`.`t1`.`a` = ``.`1` and `test`.`t1`.`b` = ``.`2`)))) @@ -578,7 +576,7 @@ explain extended select * from t1 where (a,b) not in (select * from (values (1,2),(8,9), (5,1)) as tvc_0); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where -2 MATERIALIZED ALL NULL NULL NULL NULL 2 100.00 +2 MATERIALIZED ALL NULL NULL NULL NULL 3 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where !<`test`.`t1`.`a`,`test`.`t1`.`b`>(((`test`.`t1`.`a`,`test`.`t1`.`b`),(`test`.`t1`.`a`,`test`.`t1`.`b`) in ( (/* select#2 */ select `tvc_0`.`1`,`tvc_0`.`2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), (`test`.`t1`.`a` in on distinct_key where `test`.`t1`.`a` = ``.`1` and `test`.`t1`.`b` = ``.`2`)))) @@ -592,7 +590,7 @@ explain extended select * from t1 where b < 7 and (a,b) not in ((1,2),(8,9), (5,1)); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where -2 MATERIALIZED ALL NULL NULL NULL NULL 2 100.00 +2 MATERIALIZED ALL NULL NULL NULL NULL 3 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`b` < 7 and !<`test`.`t1`.`a`,`test`.`t1`.`b`>(((`test`.`t1`.`a`,`test`.`t1`.`b`),(`test`.`t1`.`a`,`test`.`t1`.`b`) in ( (/* select#2 */ select `tvc_0`.`1`,`tvc_0`.`2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), (`test`.`t1`.`a` in on distinct_key where `test`.`t1`.`a` = ``.`1` and `test`.`t1`.`b` = ``.`2`)))) @@ -608,7 +606,7 @@ explain extended select * from t2 where (a,c) not in ((1,2),(8,9), (5,1)); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 6 100.00 Using where -2 MATERIALIZED ALL NULL NULL NULL NULL 2 100.00 +2 MATERIALIZED ALL NULL NULL NULL NULL 3 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where !<`test`.`t2`.`a`,`test`.`t2`.`c`>(((`test`.`t2`.`a`,`test`.`t2`.`c`),(`test`.`t2`.`a`,`test`.`t2`.`c`) in ( (/* select#2 */ select `tvc_0`.`1`,`tvc_0`.`2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), (`test`.`t2`.`a` in on distinct_key where `test`.`t2`.`a` = ``.`1` and `test`.`t2`.`c` = ``.`2`)))) @@ -632,7 +630,7 @@ i EXPLAIN EXTENDED SELECT * FROM t1 WHERE i IN (NULL, NULL, NULL, NULL, NULL); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 -1 PRIMARY ALL NULL NULL NULL NULL 2 100.00 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +1 PRIMARY ALL NULL NULL NULL NULL 5 100.00 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`i` AS `i` from `test`.`t1` semi join ((values (NULL),(NULL),(NULL),(NULL),(NULL)) `tvc_0`) where `test`.`t1`.`i` = `tvc_0`.`NULL` diff --git a/mysql-test/main/opt_tvc.test b/mysql-test/main/opt_tvc.test index d5c9a5cbd3d..2d06a0a0b20 100644 --- a/mysql-test/main/opt_tvc.test +++ b/mysql-test/main/opt_tvc.test @@ -255,7 +255,7 @@ deallocate prepare stmt; --echo # use inside out access from tvc rows -let $query= select * from t3 where a in (1,4,10); +let $query= select * from t3 where a in (1,4); set @@in_predicate_conversion_threshold= default; eval $query; eval explain extended $query; diff --git a/mysql-test/main/range.result b/mysql-test/main/range.result index e2996b963bc..464c0bf031a 100644 --- a/mysql-test/main/range.result +++ b/mysql-test/main/range.result @@ -1048,30 +1048,6 @@ select a, hex(filler) from t1 where a not between 'b' and 'b'; a hex(filler) a 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 drop table t1,t2,t3; -create table t1 (a int); -insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); -create table t2 (a int, key(a)); -insert into t2 select 2*(A.a + 10*(B.a + 10*C.a)) from t1 A, t1 B, t1 C; -set @a="select * from t2 force index (a) where a NOT IN(0"; -select count(*) from (select @a:=concat(@a, ',', a) from t2 ) Z; -count(*) -1000 -set @a=concat(@a, ')'); -insert into t2 values (11),(13),(15); -set @b= concat("explain ", @a); -prepare stmt1 from @b; -execute stmt1; -id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t2 index NULL a 5 NULL 1003 Using where; Using index -2 MATERIALIZED ALL NULL NULL NULL NULL 2 -3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used -prepare stmt1 from @a; -execute stmt1; -a -11 -13 -15 -drop table t1, t2; CREATE TABLE t1 ( id int NOT NULL DEFAULT '0', b int NOT NULL DEFAULT '0', @@ -3005,5 +2981,46 @@ deallocate prepare stmt; set optimizer_switch=@save_optimizer_switch; drop table t1,t2,t3; # +# MDEV-16934: using system variable eq_range_index_dive_limit +# to reduce the number of index dives +# +create table t1 (a int, b varchar(31), index idx(a)); +insert into t1 values +(7,'xxxx'), (1,'yy'), (3,'aaa'), (1,'bbb'), (2,'zz'), +(4,'vvvvv'), (7,'ddd'), (9,'zzzzz'), (1,'cc'), (5,'ffff'); +insert into t1 select a+10, concat(b,'zz') from t1; +insert into t1 select a+15, concat(b,'yy') from t1; +insert into t1 select a+100, concat(b,'xx') from t1; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +select cast(count(a)/count(distinct a) as unsigned) as rec_per_key from t1; +rec_per_key +2 +set eq_range_index_dive_limit=0; +explain select * from t1 where a in (8, 15, 31, 1, 9); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range idx idx 5 NULL 7 Using index condition +select * from t1 where a in (8, 15, 31, 1, 9); +a b +1 yy +1 bbb +1 cc +9 zzzzz +15 ffffzz +set eq_range_index_dive_limit=2; +explain select * from t1 where a in (8, 15, 31, 1, 9); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range idx idx 5 NULL 10 Using index condition +select * from t1 where a in (8, 15, 31, 1, 9); +a b +1 yy +1 bbb +1 cc +9 zzzzz +15 ffffzz +set eq_range_index_dive_limit=default; +drop table t1; +# # End of 10.2 tests # diff --git a/mysql-test/main/range.test b/mysql-test/main/range.test index 36e0e32b28b..bd2299bac5f 100644 --- a/mysql-test/main/range.test +++ b/mysql-test/main/range.test @@ -862,30 +862,6 @@ select a, hex(filler) from t1 where a not between 'b' and 'b'; drop table t1,t2,t3; -# -# BUG#21282 -# -create table t1 (a int); -insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); -create table t2 (a int, key(a)); -insert into t2 select 2*(A.a + 10*(B.a + 10*C.a)) from t1 A, t1 B, t1 C; - -set @a="select * from t2 force index (a) where a NOT IN(0"; -select count(*) from (select @a:=concat(@a, ',', a) from t2 ) Z; -set @a=concat(@a, ')'); - -insert into t2 values (11),(13),(15); - -set @b= concat("explain ", @a); - -prepare stmt1 from @b; -execute stmt1; - -prepare stmt1 from @a; -execute stmt1; - -drop table t1, t2; - # # Bug #18165: range access for BETWEEN with a constant for the first argument # @@ -2041,6 +2017,39 @@ set optimizer_switch=@save_optimizer_switch; drop table t1,t2,t3; +--echo # +--echo # MDEV-16934: using system variable eq_range_index_dive_limit +--echo # to reduce the number of index dives +--echo # + +create table t1 (a int, b varchar(31), index idx(a)); + +insert into t1 values + (7,'xxxx'), (1,'yy'), (3,'aaa'), (1,'bbb'), (2,'zz'), + (4,'vvvvv'), (7,'ddd'), (9,'zzzzz'), (1,'cc'), (5,'ffff'); +insert into t1 select a+10, concat(b,'zz') from t1; +insert into t1 select a+15, concat(b,'yy') from t1; +insert into t1 select a+100, concat(b,'xx') from t1; + +analyze table t1; + +select cast(count(a)/count(distinct a) as unsigned) as rec_per_key from t1; + +let $q= +select * from t1 where a in (8, 15, 31, 1, 9); + +set eq_range_index_dive_limit=0; +eval explain $q; +eval $q; + +set eq_range_index_dive_limit=2; +eval explain $q; +eval $q; + +set eq_range_index_dive_limit=default; + +drop table t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/main/range_debug.result b/mysql-test/main/range_debug.result new file mode 100644 index 00000000000..5597671071e --- /dev/null +++ b/mysql-test/main/range_debug.result @@ -0,0 +1,24 @@ +create table t1 (a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t2 (a int, key(a)); +insert into t2 select 2*(A.a + 10*(B.a + 10*C.a)) from t1 A, t1 B, t1 C; +set in_predicate_conversion_threshold= 2000; +set @a="select * from t2 force index (a) where a NOT IN(0"; +select count(*) from (select @a:=concat(@a, ',', a) from t2 ) Z; +count(*) +1000 +set @a=concat(@a, ')'); +insert into t2 values (11),(13),(15); +set @b= concat("explain ", @a); +prepare stmt1 from @b; +execute stmt1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index a a 5 NULL 1003 Using where; Using index +prepare stmt1 from @a; +execute stmt1; +a +11 +13 +15 +set in_predicate_conversion_threshold= default; +drop table t1, t2; diff --git a/mysql-test/main/range_debug.test b/mysql-test/main/range_debug.test new file mode 100644 index 00000000000..ef331cdc84f --- /dev/null +++ b/mysql-test/main/range_debug.test @@ -0,0 +1,30 @@ +source include/have_debug.inc; +# +# BUG#21282 +# +create table t1 (a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t2 (a int, key(a)); +insert into t2 select 2*(A.a + 10*(B.a + 10*C.a)) from t1 A, t1 B, t1 C; + +set in_predicate_conversion_threshold= 2000; + +set @a="select * from t2 force index (a) where a NOT IN(0"; +select count(*) from (select @a:=concat(@a, ',', a) from t2 ) Z; +set @a=concat(@a, ')'); + +insert into t2 values (11),(13),(15); + +set @b= concat("explain ", @a); + +prepare stmt1 from @b; +execute stmt1; + +prepare stmt1 from @a; +execute stmt1; + +set in_predicate_conversion_threshold= default; + +drop table t1, t2; + + diff --git a/mysql-test/main/range_mrr_icp.result b/mysql-test/main/range_mrr_icp.result index 629d183bee7..b132e63b732 100644 --- a/mysql-test/main/range_mrr_icp.result +++ b/mysql-test/main/range_mrr_icp.result @@ -1050,30 +1050,6 @@ select a, hex(filler) from t1 where a not between 'b' and 'b'; a hex(filler) a 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 drop table t1,t2,t3; -create table t1 (a int); -insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); -create table t2 (a int, key(a)); -insert into t2 select 2*(A.a + 10*(B.a + 10*C.a)) from t1 A, t1 B, t1 C; -set @a="select * from t2 force index (a) where a NOT IN(0"; -select count(*) from (select @a:=concat(@a, ',', a) from t2 ) Z; -count(*) -1000 -set @a=concat(@a, ')'); -insert into t2 values (11),(13),(15); -set @b= concat("explain ", @a); -prepare stmt1 from @b; -execute stmt1; -id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t2 index NULL a 5 NULL 1003 Using where; Using index -2 MATERIALIZED ALL NULL NULL NULL NULL 2 -3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used -prepare stmt1 from @a; -execute stmt1; -a -11 -13 -15 -drop table t1, t2; CREATE TABLE t1 ( id int NOT NULL DEFAULT '0', b int NOT NULL DEFAULT '0', @@ -3017,6 +2993,47 @@ deallocate prepare stmt; set optimizer_switch=@save_optimizer_switch; drop table t1,t2,t3; # +# MDEV-16934: using system variable eq_range_index_dive_limit +# to reduce the number of index dives +# +create table t1 (a int, b varchar(31), index idx(a)); +insert into t1 values +(7,'xxxx'), (1,'yy'), (3,'aaa'), (1,'bbb'), (2,'zz'), +(4,'vvvvv'), (7,'ddd'), (9,'zzzzz'), (1,'cc'), (5,'ffff'); +insert into t1 select a+10, concat(b,'zz') from t1; +insert into t1 select a+15, concat(b,'yy') from t1; +insert into t1 select a+100, concat(b,'xx') from t1; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +select cast(count(a)/count(distinct a) as unsigned) as rec_per_key from t1; +rec_per_key +2 +set eq_range_index_dive_limit=0; +explain select * from t1 where a in (8, 15, 31, 1, 9); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range idx idx 5 NULL 7 Using index condition; Rowid-ordered scan +select * from t1 where a in (8, 15, 31, 1, 9); +a b +1 yy +1 bbb +9 zzzzz +1 cc +15 ffffzz +set eq_range_index_dive_limit=2; +explain select * from t1 where a in (8, 15, 31, 1, 9); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range idx idx 5 NULL 10 Using index condition; Rowid-ordered scan +select * from t1 where a in (8, 15, 31, 1, 9); +a b +1 yy +1 bbb +9 zzzzz +1 cc +15 ffffzz +set eq_range_index_dive_limit=default; +drop table t1; +# # End of 10.2 tests # set optimizer_switch=@mrr_icp_extra_tmp; diff --git a/mysql-test/main/subselect_extra_no_semijoin.result b/mysql-test/main/subselect_extra_no_semijoin.result index fc8d5759945..ec9ddb0452e 100644 --- a/mysql-test/main/subselect_extra_no_semijoin.result +++ b/mysql-test/main/subselect_extra_no_semijoin.result @@ -482,3 +482,25 @@ DROP TABLE t1,t2; set optimizer_switch= @tmp_subselect_extra_derived; set optimizer_switch= @subselect_extra_no_sj_tmp; set @optimizer_switch_for_subselect_extra_test=null; +# +# MDEV-6439: Server crashes in Explain_union::print_explain with explain in slow log, tis620 charset +# +connect con1,localhost,root,,; +SET NAMES tis620; +set @tmp= @@global.slow_query_log; +SET GLOBAL slow_query_log = 1; +SET long_query_time = 0.000001; +SET log_slow_verbosity = 'explain'; +CREATE TABLE t1 (a VARCHAR(3)) ENGINE=MyISAM; +SELECT * FROM t1 WHERE a >= ANY ( SELECT 'foo'); +a +SELECT * FROM t1 WHERE a >= ANY ( SELECT 'foo' UNION SELECT 'bar' ); +ERROR HY000: Illegal mix of collations (tis620_thai_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation '<=' +create table t2 (b int); +insert into t2 values (1),(2),(3); +SELECT * FROM t1 WHERE a >= ANY ( SELECT 'foo' FROM t2); +ERROR HY000: Illegal mix of collations (tis620_thai_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation '<=' +drop table t1,t2; +SET GLOBAL slow_query_log=@tmp; +disconnect con1; +connection default; diff --git a/mysql-test/main/subselect_extra_no_semijoin.test b/mysql-test/main/subselect_extra_no_semijoin.test index 4340f4165e7..681f92bd8c4 100644 --- a/mysql-test/main/subselect_extra_no_semijoin.test +++ b/mysql-test/main/subselect_extra_no_semijoin.test @@ -6,4 +6,33 @@ set @optimizer_switch_for_subselect_extra_test='semijoin=off,firstmatch=off,loo set optimizer_switch= @subselect_extra_no_sj_tmp; -set @optimizer_switch_for_subselect_extra_test=null; \ No newline at end of file +set @optimizer_switch_for_subselect_extra_test=null; + +--echo # +--echo # MDEV-6439: Server crashes in Explain_union::print_explain with explain in slow log, tis620 charset +--echo # + +## Using a separate client connection is easier than restoring state +connect(con1,localhost,root,,); + +SET NAMES tis620; +set @tmp= @@global.slow_query_log; +SET GLOBAL slow_query_log = 1; +SET long_query_time = 0.000001; +SET log_slow_verbosity = 'explain'; + +CREATE TABLE t1 (a VARCHAR(3)) ENGINE=MyISAM; +SELECT * FROM t1 WHERE a >= ANY ( SELECT 'foo'); +--error ER_CANT_AGGREGATE_2COLLATIONS +SELECT * FROM t1 WHERE a >= ANY ( SELECT 'foo' UNION SELECT 'bar' ); + +create table t2 (b int); +insert into t2 values (1),(2),(3); + +--error ER_CANT_AGGREGATE_2COLLATIONS +SELECT * FROM t1 WHERE a >= ANY ( SELECT 'foo' FROM t2); + +drop table t1,t2; +SET GLOBAL slow_query_log=@tmp; +disconnect con1; +connection default; diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result index e208dfe74c1..010ba03153b 100644 --- a/mysql-test/main/subselect_mat.result +++ b/mysql-test/main/subselect_mat.result @@ -499,7 +499,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where 2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <`test`.`t1`.`a1`,`test`.`t1`.`a2`>(((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(/* select#2 */ select '1 - 01','2 - 01' having ((`test`.`t1`.`a1`) = '1 - 01' or '1 - 01' is null) and ((`test`.`t1`.`a2`) = '2 - 01' or '2 - 01' is null) and '1 - 01' is null and '2 - 01' is null))) +Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <`test`.`t1`.`a1`,`test`.`t1`.`a2`>(((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(/* select#2 */ select '1 - 01','2 - 01' having ((`test`.`t1`.`a1`) = '1 - 01' or /*always not null*/ 1 is null) and ((`test`.`t1`.`a2`) = '2 - 01' or /*always not null*/ 1 is null) and '1 - 01' is null and '2 - 01' is null))) select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01'); a1 a2 1 - 01 2 - 01 @@ -509,7 +509,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where 2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <`test`.`t1`.`a1`,`test`.`t1`.`a2`>(((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(/* select#2 */ select '1 - 01','2 - 01' having ((`test`.`t1`.`a1`) = '1 - 01' or '1 - 01' is null) and ((`test`.`t1`.`a2`) = '2 - 01' or '2 - 01' is null) and '1 - 01' is null and '2 - 01' is null))) +Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <`test`.`t1`.`a1`,`test`.`t1`.`a2`>(((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(/* select#2 */ select '1 - 01','2 - 01' having ((`test`.`t1`.`a1`) = '1 - 01' or /*always not null*/ 1 is null) and ((`test`.`t1`.`a2`) = '2 - 01' or /*always not null*/ 1 is null) and '1 - 01' is null and '2 - 01' is null))) select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01' from dual); a1 a2 1 - 01 2 - 01 @@ -1925,7 +1925,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2` having `MAX(c)` is null or `MAX(c)` = 7) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = ``.`MAX(c)` and ((``.`MAX(c)` is null) or ``.`MAX(c)` = 7) +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2` having `MAX(c)` is null or `MAX(c)` = 7) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = ``.`MAX(c)` and ((/*always not null*/ 1 is null) or ``.`MAX(c)` = 7) SELECT * FROM t1 WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b); a b diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result index 7630b0b9c0f..983c6c31c65 100644 --- a/mysql-test/main/subselect_sj_mat.result +++ b/mysql-test/main/subselect_sj_mat.result @@ -520,7 +520,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where 2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <`test`.`t1`.`a1`,`test`.`t1`.`a2`>(((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(/* select#2 */ select '1 - 01','2 - 01' having ((`test`.`t1`.`a1`) = '1 - 01' or '1 - 01' is null) and ((`test`.`t1`.`a2`) = '2 - 01' or '2 - 01' is null) and '1 - 01' is null and '2 - 01' is null))) +Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <`test`.`t1`.`a1`,`test`.`t1`.`a2`>(((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(/* select#2 */ select '1 - 01','2 - 01' having ((`test`.`t1`.`a1`) = '1 - 01' or /*always not null*/ 1 is null) and ((`test`.`t1`.`a2`) = '2 - 01' or /*always not null*/ 1 is null) and '1 - 01' is null and '2 - 01' is null))) select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01'); a1 a2 1 - 01 2 - 01 @@ -530,7 +530,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where 2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <`test`.`t1`.`a1`,`test`.`t1`.`a2`>(((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(/* select#2 */ select '1 - 01','2 - 01' having ((`test`.`t1`.`a1`) = '1 - 01' or '1 - 01' is null) and ((`test`.`t1`.`a2`) = '2 - 01' or '2 - 01' is null) and '1 - 01' is null and '2 - 01' is null))) +Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <`test`.`t1`.`a1`,`test`.`t1`.`a2`>(((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(/* select#2 */ select '1 - 01','2 - 01' having ((`test`.`t1`.`a1`) = '1 - 01' or /*always not null*/ 1 is null) and ((`test`.`t1`.`a2`) = '2 - 01' or /*always not null*/ 1 is null) and '1 - 01' is null and '2 - 01' is null))) select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01' from dual); a1 a2 1 - 01 2 - 01 @@ -1963,7 +1963,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2` having `MAX(c)` is null or `MAX(c)` = 7) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = ``.`MAX(c)` and ((``.`MAX(c)` is null) or ``.`MAX(c)` = 7) +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2` having `MAX(c)` is null or `MAX(c)` = 7) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = ``.`MAX(c)` and ((/*always not null*/ 1 is null) or ``.`MAX(c)` = 7) SELECT * FROM t1 WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b); a b diff --git a/mysql-test/main/table_value_constr.result b/mysql-test/main/table_value_constr.result index 9129fd0a23b..454356bb5fb 100644 --- a/mysql-test/main/table_value_constr.result +++ b/mysql-test/main/table_value_constr.result @@ -2096,3 +2096,95 @@ v # with t as (values (),()) select 1 from t; ERROR HY000: Row with no elements is not allowed in table value constructor in this context +# +# MDEV-17017: TVC in derived table +# +create table t1 (a int); +insert into t1 values (9), (3), (2); +select * from (values (7), (5), (8), (1), (3), (8), (1)) t; +7 +7 +5 +8 +1 +3 +8 +1 +explain select * from (values (7), (5), (8), (1), (3), (8), (1)) t; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 7 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used +select * from (values (1,11), (7,77), (3,31), (4,42)) t; +1 11 +1 11 +7 77 +3 31 +4 42 +explain select * from (values (1,11), (7,77), (3,31), (4,42)) t; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 4 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used +select * from (values (7), (5), (8), (1) union values (3), (8), (1)) t; +7 +7 +5 +8 +1 +3 +explain select * from (values (7), (5), (8), (1) union values (3), (8), (1)) t; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 7 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +select * from (values (7), (5), (8), (1) union select * from t1) t; +7 +7 +5 +8 +1 +9 +3 +2 +explain select * from (values (7), (5), (8), (1) union select * from t1) t; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 7 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION t1 ALL NULL NULL NULL NULL 3 +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +drop table t1; +# +# MDEV-16930: expression in the first row of TVC specifying derived table +# +SELECT 1 + 1, 2, "abc"; +1 + 1 2 abc +2 2 abc +SELECT * FROM (SELECT 1 + 1, 2, "abc") t; +1 + 1 2 abc +2 2 abc +WITH cte AS (SELECT 1 + 1, 2, "abc") SELECT * FROM cte; +1 + 1 2 abc +2 2 abc +SELECT 1 + 1, 2, "abc" UNION SELECT 3+4, 3, "abc"; +1 + 1 2 abc +2 2 abc +7 3 abc +CREATE VIEW v1 AS SELECT 1 + 1, 2, "abc"; +SELECT * FROM v1; +1 + 1 2 abc +2 2 abc +DROP VIEW v1; +VALUES(1 + 1,2,"abc"); +1 + 1 2 abc +2 2 abc +SELECT * FROM (VALUES(1 + 1,2,"abc")) t; +1 + 1 2 abc +2 2 abc +PREPARE stmt FROM "SELECT * FROM (VALUES(1 + 1,2,'abc')) t"; +EXECUTE stmt; +1 + 1 2 abc +2 2 abc +EXECUTE stmt; +1 + 1 2 abc +2 2 abc +DEALLOCATE PREPARE stmt; diff --git a/mysql-test/main/table_value_constr.test b/mysql-test/main/table_value_constr.test index eb5ea59f829..0dd0a7a04b0 100644 --- a/mysql-test/main/table_value_constr.test +++ b/mysql-test/main/table_value_constr.test @@ -1075,3 +1075,51 @@ DELIMITER ;| --error ER_EMPTY_ROW_IN_TVC with t as (values (),()) select 1 from t; + +--echo # +--echo # MDEV-17017: TVC in derived table +--echo # + +create table t1 (a int); +insert into t1 values (9), (3), (2); + +let $q1= +select * from (values (7), (5), (8), (1), (3), (8), (1)) t; +eval $q1; +eval explain $q1; + +let $q2= +select * from (values (1,11), (7,77), (3,31), (4,42)) t; +eval $q2; +eval explain $q2; + +let $q3= +select * from (values (7), (5), (8), (1) union values (3), (8), (1)) t; +eval $q3; +eval explain $q3; + +let $q4= +select * from (values (7), (5), (8), (1) union select * from t1) t; +eval $q4; +eval explain $q4; + +drop table t1; + +--echo # +--echo # MDEV-16930: expression in the first row of TVC specifying derived table +--echo # + +SELECT 1 + 1, 2, "abc"; +SELECT * FROM (SELECT 1 + 1, 2, "abc") t; +WITH cte AS (SELECT 1 + 1, 2, "abc") SELECT * FROM cte; +SELECT 1 + 1, 2, "abc" UNION SELECT 3+4, 3, "abc"; +CREATE VIEW v1 AS SELECT 1 + 1, 2, "abc"; +SELECT * FROM v1; +DROP VIEW v1; + +VALUES(1 + 1,2,"abc"); +SELECT * FROM (VALUES(1 + 1,2,"abc")) t; +PREPARE stmt FROM "SELECT * FROM (VALUES(1 + 1,2,'abc')) t"; +EXECUTE stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; diff --git a/mysql-test/main/win.result b/mysql-test/main/win.result index fd0fbefdcc5..97801b5e285 100644 --- a/mysql-test/main/win.result +++ b/mysql-test/main/win.result @@ -3219,8 +3219,8 @@ DROP TABLE fv_test, fv_result; # CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (0),(1),(2); -SELECT LEAD(a) OVER (PARTITION BY a) as lead, -a AND LEAD(a) OVER (PARTITION BY a) AS a_and_lead_part +SELECT LEAD(a) OVER (PARTITION BY a ORDER BY a) as lead, +a AND LEAD(a) OVER (PARTITION BY a ORDER BY a) AS a_and_lead_part FROM t1; lead a_and_lead_part NULL 0 diff --git a/mysql-test/main/win.test b/mysql-test/main/win.test index cc16595fcd4..f038316ce98 100644 --- a/mysql-test/main/win.test +++ b/mysql-test/main/win.test @@ -2000,8 +2000,8 @@ DROP TABLE fv_test, fv_result; CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (0),(1),(2); -SELECT LEAD(a) OVER (PARTITION BY a) as lead, - a AND LEAD(a) OVER (PARTITION BY a) AS a_and_lead_part +SELECT LEAD(a) OVER (PARTITION BY a ORDER BY a) as lead, + a AND LEAD(a) OVER (PARTITION BY a ORDER BY a) AS a_and_lead_part FROM t1; SELECT a OR LEAD(a) OVER (ORDER BY a) AS a_or_lead_order diff --git a/mysql-test/main/win_lead_lag.result b/mysql-test/main/win_lead_lag.result index 5ead58fa11a..f3c0b8f7ef2 100644 --- a/mysql-test/main/win_lead_lag.result +++ b/mysql-test/main/win_lead_lag.result @@ -226,4 +226,15 @@ pk a b a+b lag(a + b) over (partition by a order by pk) + pk 9 2 2 4 12 10 2 0 2 14 11 2 10 12 13 +# +# MDEV-15204 - LAG function doesn't require ORDER BY in OVER clause +# +select pk, +lag(pk, 1) over () +from t1; +ERROR HY000: No order list in window specification for 'lag' +select pk, +lead(pk, 1) over () +from t1; +ERROR HY000: No order list in window specification for 'lead' drop table t1; diff --git a/mysql-test/main/win_lead_lag.test b/mysql-test/main/win_lead_lag.test index 2824f83789c..d154244ecd0 100644 --- a/mysql-test/main/win_lead_lag.test +++ b/mysql-test/main/win_lead_lag.test @@ -107,4 +107,17 @@ select pk, a, b, a+b, from t1 order by pk asc; +--echo # +--echo # MDEV-15204 - LAG function doesn't require ORDER BY in OVER clause +--echo # +--error ER_NO_ORDER_LIST_IN_WINDOW_SPEC +select pk, + lag(pk, 1) over () +from t1; + +--error ER_NO_ORDER_LIST_IN_WINDOW_SPEC +select pk, + lead(pk, 1) over () +from t1; + drop table t1; diff --git a/mysql-test/suite/compat/oracle/r/table_value_constr.result b/mysql-test/suite/compat/oracle/r/table_value_constr.result index 31dcecfdb18..18fce086f6e 100644 --- a/mysql-test/suite/compat/oracle/r/table_value_constr.result +++ b/mysql-test/suite/compat/oracle/r/table_value_constr.result @@ -2099,3 +2099,87 @@ v # with t as (values (),()) select 1 from t; ERROR HY000: Row with no elements is not allowed in table value constructor in this context +# +# MDEV-17017: TVC in derived table +# +create table t1 (a int); +insert into t1 values (9), (3), (2); +select * from (values (7), (5), (8), (1), (3), (8), (1)) t; +7 +7 +5 +8 +1 +3 +8 +1 +explain select * from (values (7), (5), (8), (1), (3), (8), (1)) t; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 7 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used +select * from (values (1,11), (7,77), (3,31), (4,42)) t; +1 11 +1 11 +7 77 +3 31 +4 42 +explain select * from (values (1,11), (7,77), (3,31), (4,42)) t; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 4 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used +select * from (values (7), (5), (8), (1) union values (3), (8), (1)) t; +7 +7 +5 +8 +1 +3 +explain select * from (values (7), (5), (8), (1) union values (3), (8), (1)) t; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 7 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +select * from (values (7), (5), (8), (1) union select * from t1) t; +7 +7 +5 +8 +1 +9 +3 +2 +explain select * from (values (7), (5), (8), (1) union select * from t1) t; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 7 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION t1 ALL NULL NULL NULL NULL 3 +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +drop table t1; +# +# MDEV-16930: expression in the first row of TVC specifying derived table +# +SELECT 1 + 1, 2, 'abc'; +1 + 1 2 abc +2 2 abc +SELECT * FROM (SELECT 1 + 1, 2, 'abc') t; +1 + 1 2 abc +2 2 abc +WITH cte AS (SELECT 1 + 1, 2, 'abc') SELECT * FROM cte; +1 + 1 2 abc +2 2 abc +SELECT 1 + 1, 2, 'abc' UNION SELECT 3+4, 3, 'abc'; +1 + 1 2 abc +2 2 abc +7 3 abc +CREATE VIEW v1 AS SELECT 1 + 1, 2, 'abc'; +SELECT * FROM v1; +1 + 1 2 abc +2 2 abc +DROP VIEW v1; +VALUES(1 + 1,2,'abc'); +1 + 1 2 abc +2 2 abc +SELECT * FROM (VALUES(1 + 1,2,'abc')) t; +1 + 1 2 abc +2 2 abc diff --git a/mysql-test/suite/compat/oracle/t/table_value_constr.test b/mysql-test/suite/compat/oracle/t/table_value_constr.test index 66519e93a36..37d25218664 100644 --- a/mysql-test/suite/compat/oracle/t/table_value_constr.test +++ b/mysql-test/suite/compat/oracle/t/table_value_constr.test @@ -1081,3 +1081,47 @@ DELIMITER ;| --error ER_EMPTY_ROW_IN_TVC with t as (values (),()) select 1 from t; + +--echo # +--echo # MDEV-17017: TVC in derived table +--echo # + +create table t1 (a int); +insert into t1 values (9), (3), (2); + +let $q1= +select * from (values (7), (5), (8), (1), (3), (8), (1)) t; +eval $q1; +eval explain $q1; + +let $q2= +select * from (values (1,11), (7,77), (3,31), (4,42)) t; +eval $q2; +eval explain $q2; + +let $q3= +select * from (values (7), (5), (8), (1) union values (3), (8), (1)) t; +eval $q3; +eval explain $q3; + +let $q4= +select * from (values (7), (5), (8), (1) union select * from t1) t; +eval $q4; +eval explain $q4; + +drop table t1; + +--echo # +--echo # MDEV-16930: expression in the first row of TVC specifying derived table +--echo # + +SELECT 1 + 1, 2, 'abc'; +SELECT * FROM (SELECT 1 + 1, 2, 'abc') t; +WITH cte AS (SELECT 1 + 1, 2, 'abc') SELECT * FROM cte; +SELECT 1 + 1, 2, 'abc' UNION SELECT 3+4, 3, 'abc'; +CREATE VIEW v1 AS SELECT 1 + 1, 2, 'abc'; +SELECT * FROM v1; +DROP VIEW v1; + +VALUES(1 + 1,2,'abc'); +SELECT * FROM (VALUES(1 + 1,2,'abc')) t; diff --git a/mysql-test/suite/funcs_1/r/is_check_constraints.result b/mysql-test/suite/funcs_1/r/is_check_constraints.result new file mode 100644 index 00000000000..678cfb8db2f --- /dev/null +++ b/mysql-test/suite/funcs_1/r/is_check_constraints.result @@ -0,0 +1,144 @@ +# +# MDEV-14474: Create INFORMATION_SCHEMA.CHECK_CONSTRAINTS +# +set check_constraint_checks=1; +use test; +create table t0 +( +t int, check (t>32) # table constraint +) ENGINE=myisam; +SELECT * from information_schema.check_constraints order by check_clause; +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME CONSTRAINT_1 +TABLE_NAME t0 +CHECK_CLAUSE `t` > 32 +ALTER TABLE t0 +ADD CONSTRAINT CHK_t0_t CHECK(t<100); +SELECT * from information_schema.check_constraints order by check_clause; +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME CHK_t0_t +TABLE_NAME t0 +CHECK_CLAUSE `t` < 100 +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME CONSTRAINT_1 +TABLE_NAME t0 +CHECK_CLAUSE `t` > 32 +ALTER TABLE t0 +DROP CONSTRAINT CHK_t0_t; +SELECT * from information_schema.check_constraints order by check_clause; +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME CONSTRAINT_1 +TABLE_NAME t0 +CHECK_CLAUSE `t` > 32 +CREATE TABLE t1 +( t int CHECK(t>2), # field constraint +tt int, CONSTRAINT CHK_tt CHECK(tt<100) # table constraint +) ENGINE=InnoDB; +SELECT * from information_schema.check_constraints order by check_clause; +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME CHK_tt +TABLE_NAME t1 +CHECK_CLAUSE `tt` < 100 +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME t +TABLE_NAME t1 +CHECK_CLAUSE `t` > 2 +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME CONSTRAINT_1 +TABLE_NAME t0 +CHECK_CLAUSE `t` > 32 +ALTER TABLE t1 +DROP CONSTRAINT CHK_tt; +SELECT * from information_schema.check_constraints order by check_clause; +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME t +TABLE_NAME t1 +CHECK_CLAUSE `t` > 2 +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME CONSTRAINT_1 +TABLE_NAME t0 +CHECK_CLAUSE `t` > 32 +create table t2 +( +name VARCHAR(30) CHECK(CHAR_LENGTH(name)>2), #field constraint +start_date DATE, +end_date DATE, +CONSTRAINT CHK_dates CHECK(start_date IS NULL) #table constraint +)ENGINE=Innodb; +SELECT * from information_schema.check_constraints order by check_clause; +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME name +TABLE_NAME t2 +CHECK_CLAUSE char_length(`name`) > 2 +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME CHK_dates +TABLE_NAME t2 +CHECK_CLAUSE `start_date` is null +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME t +TABLE_NAME t1 +CHECK_CLAUSE `t` > 2 +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME CONSTRAINT_1 +TABLE_NAME t0 +CHECK_CLAUSE `t` > 32 +ALTER TABLE t1 +ADD CONSTRAINT CHK_new_ CHECK(t>tt); +SELECT * from information_schema.check_constraints order by check_clause; +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME name +TABLE_NAME t2 +CHECK_CLAUSE char_length(`name`) > 2 +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME CHK_dates +TABLE_NAME t2 +CHECK_CLAUSE `start_date` is null +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME t +TABLE_NAME t1 +CHECK_CLAUSE `t` > 2 +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME CONSTRAINT_1 +TABLE_NAME t0 +CHECK_CLAUSE `t` > 32 +CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA test +CONSTRAINT_NAME CHK_new_ +TABLE_NAME t1 +CHECK_CLAUSE `t` > `tt` +create table t3 +( +a int, +b int check (b>0), # field constraint named 'b' +CONSTRAINT b check (b>10) # table constraint +) ENGINE=InnoDB; +select * from information_schema.check_constraints order by check_clause; +CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_NAME CHECK_CLAUSE +def test name t2 char_length(`name`) > 2 +def test b t3 `b` > 0 +def test b t3 `b` > 10 +def test CHK_dates t2 `start_date` is null +def test t t1 `t` > 2 +def test CONSTRAINT_1 t0 `t` > 32 +def test CHK_new_ t1 `t` > `tt` +drop table t0; +drop table t1; +drop table t2; +drop table t3; 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 d76efef3e08..dfaa5d75137 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is.result @@ -24,6 +24,11 @@ def information_schema CHARACTER_SETS CHARACTER_SET_NAME 1 '' NO varchar 32 96 N def information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) select NEVER NULL def information_schema CHARACTER_SETS DESCRIPTION 3 '' NO varchar 60 180 NULL NULL NULL utf8 utf8_general_ci varchar(60) select NEVER NULL def information_schema CHARACTER_SETS MAXLEN 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(3) select NEVER NULL +def information_schema CHECK_CONSTRAINTS CHECK_CLAUSE 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema CHECK_CONSTRAINTS TABLE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL def information_schema CLIENT_STATISTICS ACCESS_DENIED 22 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL def information_schema CLIENT_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select NEVER NULL def information_schema CLIENT_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL NULL double select NEVER NULL @@ -557,6 +562,11 @@ COL_CML TABLE_SCHEMA TABLE_NAME COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH C 3.0000 information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME varchar 32 96 utf8 utf8_general_ci varchar(32) 3.0000 information_schema CHARACTER_SETS DESCRIPTION varchar 60 180 utf8 utf8_general_ci varchar(60) NULL information_schema CHARACTER_SETS MAXLEN bigint NULL NULL NULL NULL bigint(3) +3.0000 information_schema CHECK_CONSTRAINTS CONSTRAINT_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512) +3.0000 information_schema CHECK_CONSTRAINTS CONSTRAINT_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64) +3.0000 information_schema CHECK_CONSTRAINTS CONSTRAINT_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) +3.0000 information_schema CHECK_CONSTRAINTS TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) +3.0000 information_schema CHECK_CONSTRAINTS CHECK_CLAUSE varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema CLIENT_STATISTICS CLIENT varchar 64 192 utf8 utf8_general_ci varchar(64) NULL information_schema CLIENT_STATISTICS TOTAL_CONNECTIONS bigint NULL NULL NULL NULL bigint(21) NULL information_schema CLIENT_STATISTICS CONCURRENT_CONNECTIONS bigint NULL NULL NULL NULL bigint(21) 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 b0d3c177580..96fb1e286c0 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 @@ -24,6 +24,11 @@ def information_schema CHARACTER_SETS CHARACTER_SET_NAME 1 '' NO varchar 32 96 N def information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME 2 '' NO varchar 32 96 NULL NULL NULL utf8 utf8_general_ci varchar(32) NEVER NULL def information_schema CHARACTER_SETS DESCRIPTION 3 '' NO varchar 60 180 NULL NULL NULL utf8 utf8_general_ci varchar(60) NEVER NULL def information_schema CHARACTER_SETS MAXLEN 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(3) NEVER NULL +def information_schema CHECK_CONSTRAINTS CHECK_CLAUSE 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_CATALOG 1 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_NAME 3 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema CHECK_CONSTRAINTS CONSTRAINT_SCHEMA 2 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema CHECK_CONSTRAINTS TABLE_NAME 4 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL def information_schema CLIENT_STATISTICS ACCESS_DENIED 22 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL def information_schema CLIENT_STATISTICS BINLOG_BYTES_WRITTEN 9 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL def information_schema CLIENT_STATISTICS BUSY_TIME 5 0 NO double NULL NULL 21 NULL NULL NULL NULL double NEVER NULL @@ -557,6 +562,11 @@ COL_CML TABLE_SCHEMA TABLE_NAME COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH C 3.0000 information_schema CHARACTER_SETS DEFAULT_COLLATE_NAME varchar 32 96 utf8 utf8_general_ci varchar(32) 3.0000 information_schema CHARACTER_SETS DESCRIPTION varchar 60 180 utf8 utf8_general_ci varchar(60) NULL information_schema CHARACTER_SETS MAXLEN bigint NULL NULL NULL NULL bigint(3) +3.0000 information_schema CHECK_CONSTRAINTS CONSTRAINT_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512) +3.0000 information_schema CHECK_CONSTRAINTS CONSTRAINT_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64) +3.0000 information_schema CHECK_CONSTRAINTS CONSTRAINT_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) +3.0000 information_schema CHECK_CONSTRAINTS TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) +3.0000 information_schema CHECK_CONSTRAINTS CHECK_CLAUSE varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema CLIENT_STATISTICS CLIENT varchar 64 192 utf8 utf8_general_ci varchar(64) NULL information_schema CLIENT_STATISTICS TOTAL_CONNECTIONS bigint NULL NULL NULL NULL bigint(21) NULL information_schema CLIENT_STATISTICS CONCURRENT_CONNECTIONS bigint NULL NULL NULL NULL bigint(21) diff --git a/mysql-test/suite/funcs_1/r/is_tables_is.result b/mysql-test/suite/funcs_1/r/is_tables_is.result index e0e5a82a265..5fee1e0050a 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_is.result +++ b/mysql-test/suite/funcs_1/r/is_tables_is.result @@ -89,6 +89,31 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA information_schema +TABLE_NAME CHECK_CONSTRAINTS +TABLE_TYPE SYSTEM VIEW +ENGINE MEMORY +VERSION 11 +ROW_FORMAT Fixed +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION utf8_general_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +MAX_INDEX_LENGTH #MIL# +TEMPORARY Y +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA information_schema TABLE_NAME CLIENT_STATISTICS TABLE_TYPE SYSTEM VIEW ENGINE MEMORY @@ -1105,6 +1130,31 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA information_schema +TABLE_NAME CHECK_CONSTRAINTS +TABLE_TYPE SYSTEM VIEW +ENGINE MEMORY +VERSION 11 +ROW_FORMAT Fixed +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION utf8_general_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +MAX_INDEX_LENGTH #MIL# +TEMPORARY Y +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA information_schema TABLE_NAME CLIENT_STATISTICS TABLE_TYPE SYSTEM VIEW ENGINE MEMORY diff --git a/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result b/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result index e0e5a82a265..5fee1e0050a 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result @@ -89,6 +89,31 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA information_schema +TABLE_NAME CHECK_CONSTRAINTS +TABLE_TYPE SYSTEM VIEW +ENGINE MEMORY +VERSION 11 +ROW_FORMAT Fixed +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION utf8_general_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +MAX_INDEX_LENGTH #MIL# +TEMPORARY Y +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA information_schema TABLE_NAME CLIENT_STATISTICS TABLE_TYPE SYSTEM VIEW ENGINE MEMORY @@ -1105,6 +1130,31 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA information_schema +TABLE_NAME CHECK_CONSTRAINTS +TABLE_TYPE SYSTEM VIEW +ENGINE MEMORY +VERSION 11 +ROW_FORMAT Fixed +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION utf8_general_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +MAX_INDEX_LENGTH #MIL# +TEMPORARY Y +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA information_schema TABLE_NAME CLIENT_STATISTICS TABLE_TYPE SYSTEM VIEW ENGINE MEMORY diff --git a/mysql-test/suite/funcs_1/t/is_check_constraints.test b/mysql-test/suite/funcs_1/t/is_check_constraints.test new file mode 100644 index 00000000000..b39abdc1b24 --- /dev/null +++ b/mysql-test/suite/funcs_1/t/is_check_constraints.test @@ -0,0 +1,69 @@ +--source include/have_innodb.inc +--echo # +--echo # MDEV-14474: Create INFORMATION_SCHEMA.CHECK_CONSTRAINTS +--echo # + +set check_constraint_checks=1; + +use test; +create table t0 +( + t int, check (t>32) # table constraint +) ENGINE=myisam; + +--vertical_results +SELECT * from information_schema.check_constraints order by check_clause; + +ALTER TABLE t0 +ADD CONSTRAINT CHK_t0_t CHECK(t<100); + +SELECT * from information_schema.check_constraints order by check_clause; + +ALTER TABLE t0 +DROP CONSTRAINT CHK_t0_t; + +SELECT * from information_schema.check_constraints order by check_clause; + +CREATE TABLE t1 +( t int CHECK(t>2), # field constraint + tt int, CONSTRAINT CHK_tt CHECK(tt<100) # table constraint +) ENGINE=InnoDB; + +SELECT * from information_schema.check_constraints order by check_clause; + +ALTER TABLE t1 +DROP CONSTRAINT CHK_tt; + +SELECT * from information_schema.check_constraints order by check_clause; + +create table t2 +( +name VARCHAR(30) CHECK(CHAR_LENGTH(name)>2), #field constraint +start_date DATE, +end_date DATE, +CONSTRAINT CHK_dates CHECK(start_date IS NULL) #table constraint +)ENGINE=Innodb; + +SELECT * from information_schema.check_constraints order by check_clause; + +ALTER TABLE t1 +ADD CONSTRAINT CHK_new_ CHECK(t>tt); + +SELECT * from information_schema.check_constraints order by check_clause; + + +# Create table with same field and table check constraint name +create table t3 +( +a int, +b int check (b>0), # field constraint named 'b' +CONSTRAINT b check (b>10) # table constraint +) ENGINE=InnoDB; + +--horizontal_results +select * from information_schema.check_constraints order by check_clause; + +drop table t0; +drop table t1; +drop table t2; +drop table t3; diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index c3b5e070158..28fc908c237 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -37,3 +37,10 @@ galera_ist_progress: MDEV-15236 galera_ist_progress fails when trying to read tr galera_concurrent_ctas : MDEV-15845 Test failure on galera.galera_concurrent_ctas pxc-421: Lock timeout exceeded galera_sst_mysqldump_with_key : MDEV-16890 Galera test failure +galera_sst_xtrabackup-v2-options : Failed to read uuid:seqno and wsrep_gtid_domain_id from joiner script +MW-328C : Timeouts +galera_gcs_fc_limit : Timeouts +pool_of_threads: WSREP has not yet prepared node for application use +galera_var_innodb_disallow_writes : Timeout +galera.galera_kill_ddl : MDEV-17108 Test failure on galera.galera_kill_ddl +MW-336 : nondeterministic wsrep_thread_count diff --git a/mysql-test/suite/galera/r/MW-336.result b/mysql-test/suite/galera/r/MW-336.result index 0bf8d9d3909..1b5d2984e39 100644 --- a/mysql-test/suite/galera/r/MW-336.result +++ b/mysql-test/suite/galera/r/MW-336.result @@ -2,39 +2,99 @@ CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; connection node_1; SET GLOBAL wsrep_slave_threads = 10; SET GLOBAL wsrep_slave_threads = 1; +SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); +COUNT(*) +11 +SHOW STATUS LIKE 'wsrep_thread_count'; +Variable_name Value +wsrep_thread_count 11 connection node_2; INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); connection node_1; SET GLOBAL wsrep_slave_threads = 10; SET GLOBAL wsrep_slave_threads = 20; SET GLOBAL wsrep_slave_threads = 1; connection node_2; INSERT INTO t1 VALUES (1); -INSERT INTO t1 VALUES (2); -INSERT INTO t1 VALUES (3); -INSERT INTO t1 VALUES (4); -INSERT INTO t1 VALUES (5); -INSERT INTO t1 VALUES (6); -INSERT INTO t1 VALUES (7); -INSERT INTO t1 VALUES (8); -INSERT INTO t1 VALUES (9); -connection node_1; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); SET GLOBAL wsrep_slave_threads = 10; SET GLOBAL wsrep_slave_threads = 0; Warnings: Warning 1292 Truncated incorrect wsrep_slave_threads value: '0' connection node_2; -INSERT INTO t1 VALUES (10); -INSERT INTO t1 VALUES (11); -INSERT INTO t1 VALUES (12); -INSERT INTO t1 VALUES (13); -INSERT INTO t1 VALUES (14); -INSERT INTO t1 VALUES (15); -INSERT INTO t1 VALUES (16); -INSERT INTO t1 VALUES (17); -INSERT INTO t1 VALUES (18); -INSERT INTO t1 VALUES (19); -INSERT INTO t1 VALUES (20); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); connection node_1; SET GLOBAL wsrep_slave_threads = 1; +connection node_2; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +connection node_1; DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/MW-44.result b/mysql-test/suite/galera/r/MW-44.result index 459a61030a4..a1e55318422 100644 --- a/mysql-test/suite/galera/r/MW-44.result +++ b/mysql-test/suite/galera/r/MW-44.result @@ -1,21 +1,10 @@ SET GLOBAL general_log='OFF'; TRUNCATE TABLE mysql.general_log; -SELECT COUNT(*) from mysql.general_log; -COUNT(*) -0 -SELECT * FROM mysql.general_log; -event_time user_host thread_id server_id command_type argument SET GLOBAL general_log='OFF'; TRUNCATE TABLE mysql.general_log; -SELECT COUNT(*) from mysql.general_log; -COUNT(*) -0 -SELECT * FROM mysql.general_log; -event_time user_host thread_id server_id command_type argument SET GLOBAL general_log='ON'; -SELECT COUNT(*) from mysql.general_log; -COUNT(*) -1 +SELECT argument from mysql.general_log WHERE argument NOT LIKE 'SELECT%'; +argument SET SESSION wsrep_osu_method=TOI; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; SET SESSION wsrep_osu_method=RSU; diff --git a/mysql-test/suite/galera/r/galera_sst_rsync_data_dir.result b/mysql-test/suite/galera/r/galera_sst_rsync_data_dir.result new file mode 100644 index 00000000000..d5c6a11f61f --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_rsync_data_dir.result @@ -0,0 +1,396 @@ +connection node_1; +connection node_2; +Performing State Transfer on a server that has been shut down cleanly and restarted +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Shutting down server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_shutdown_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +connection node_2; +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_shutdown_slave; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that starts from a clean var directory +This is accomplished by shutting down node #2 and removing its var directory before restarting it +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Shutting down server ... +connection node_1; +Cleaning var directory ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_clean_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +connection node_2; +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_clean_slave; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Killing server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +connection node_2; +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_kill_slave; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +connection node_2; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; +connection node_1; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +connection node_2; +SET wsrep_sync_wait = 0; +Killing server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +connection node_2; +Performing --wsrep-recover ... +connection node_2; +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_kill_slave_ddl; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +SET GLOBAL debug_dbug = $debug_orig; diff --git a/mysql-test/suite/galera/r/galera_var_desync_on.result b/mysql-test/suite/galera/r/galera_var_desync_on.result index a26acbd4d6b..26798e51926 100644 --- a/mysql-test/suite/galera/r/galera_var_desync_on.result +++ b/mysql-test/suite/galera/r/galera_var_desync_on.result @@ -2,7 +2,6 @@ CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; SET GLOBAL wsrep_provider_options = 'gcs.fc_limit=1'; -SET GLOBAL wsrep_desync = TRUE; FLUSH TABLES WITH READ LOCK; connection node_1; INSERT INTO t1 VALUES (2); @@ -19,7 +18,6 @@ SET SESSION wsrep_sync_wait = 0; SELECT COUNT(*) = 1 FROM t1; COUNT(*) = 1 1 -SET GLOBAL wsrep_desync = FALSE; UNLOCK TABLES; SET SESSION wsrep_sync_wait = 1; SELECT COUNT(*) = 10 FROM t1; diff --git a/mysql-test/suite/galera/t/MW-336.test b/mysql-test/suite/galera/t/MW-336.test index 8cd363aa019..4bdbfb2ecff 100644 --- a/mysql-test/suite/galera/t/MW-336.test +++ b/mysql-test/suite/galera/t/MW-336.test @@ -8,15 +8,28 @@ CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; --connection node_1 + SET GLOBAL wsrep_slave_threads = 10; SET GLOBAL wsrep_slave_threads = 1; + +--let $wait_timeout=600 --let $wait_condition = SELECT COUNT(*) = 11 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); --source include/wait_condition.inc +SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); +SHOW STATUS LIKE 'wsrep_thread_count'; + --connection node_2 -INSERT INTO t1 VALUES (1); +# Generate 11 replication events +--let $count = 11 +while ($count) +{ + INSERT INTO t1 VALUES (1); + --dec $count +} --connection node_1 + SET GLOBAL wsrep_slave_threads = 10; --let $wait_condition = SELECT COUNT(*) = 11 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); --source include/wait_condition.inc @@ -28,40 +41,40 @@ SET GLOBAL wsrep_slave_threads = 20; SET GLOBAL wsrep_slave_threads = 1; --connection node_2 -INSERT INTO t1 VALUES (1); -INSERT INTO t1 VALUES (2); -INSERT INTO t1 VALUES (3); -INSERT INTO t1 VALUES (4); -INSERT INTO t1 VALUES (5); -INSERT INTO t1 VALUES (6); -INSERT INTO t1 VALUES (7); -INSERT INTO t1 VALUES (8); -INSERT INTO t1 VALUES (9); - - ---connection node_1 ---let $wait_condition = SELECT COUNT(*) = 12 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); ---source include/wait_condition.inc +# Generate 21 replication events +--let $count = 21 +while ($count) +{ + INSERT INTO t1 VALUES (1); + --dec $count +} SET GLOBAL wsrep_slave_threads = 10; SET GLOBAL wsrep_slave_threads = 0; --connection node_2 -INSERT INTO t1 VALUES (10); -INSERT INTO t1 VALUES (11); -INSERT INTO t1 VALUES (12); -INSERT INTO t1 VALUES (13); -INSERT INTO t1 VALUES (14); -INSERT INTO t1 VALUES (15); -INSERT INTO t1 VALUES (16); -INSERT INTO t1 VALUES (17); -INSERT INTO t1 VALUES (18); -INSERT INTO t1 VALUES (19); -INSERT INTO t1 VALUES (20); +# Generate 21 replication events +--let $count = 21 +while ($count) +{ + INSERT INTO t1 VALUES (1); + --dec $count +} --connection node_1 --let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); --source include/wait_condition.inc SET GLOBAL wsrep_slave_threads = 1; + +--connection node_2 +# Generate 21 replication events +--let $count = 21 +while ($count) +{ + INSERT INTO t1 VALUES (1); + --dec $count +} + +--connection node_1 DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/MW-44.test b/mysql-test/suite/galera/t/MW-44.test index 7c988a29548..e8caa28c80e 100644 --- a/mysql-test/suite/galera/t/MW-44.test +++ b/mysql-test/suite/galera/t/MW-44.test @@ -8,20 +8,21 @@ --connection node_1 SET GLOBAL general_log='OFF'; TRUNCATE TABLE mysql.general_log; -SELECT COUNT(*) from mysql.general_log; -SELECT * FROM mysql.general_log; +--let $wait_condition = SELECT COUNT(*) = 0 FROM mysql.general_log; +--source include/wait_condition.inc --sleep 1 --connection node_2 SET GLOBAL general_log='OFF'; TRUNCATE TABLE mysql.general_log; -SELECT COUNT(*) from mysql.general_log; -SELECT * FROM mysql.general_log; +--let $wait_condition = SELECT COUNT(*) = 0 FROM mysql.general_log; +--source include/wait_condition.inc --sleep 1 --connection node_1 SET GLOBAL general_log='ON'; -SELECT COUNT(*) from mysql.general_log; +SELECT argument from mysql.general_log WHERE argument NOT LIKE 'SELECT%'; + SET SESSION wsrep_osu_method=TOI; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; SET SESSION wsrep_osu_method=RSU; diff --git a/mysql-test/suite/galera/t/galera_sst_rsync_data_dir.cnf b/mysql-test/suite/galera/t/galera_sst_rsync_data_dir.cnf new file mode 100644 index 00000000000..afe9796a11a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_rsync_data_dir.cnf @@ -0,0 +1,11 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=rsync + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' + +[mysqld.2] +innodb_data_home_dir=@ENV.MYSQL_TMP_DIR/rsync_test_2 +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' diff --git a/mysql-test/suite/galera/t/galera_sst_rsync_data_dir.test b/mysql-test/suite/galera/t/galera_sst_rsync_data_dir.test new file mode 100644 index 00000000000..68aa1068f75 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_rsync_data_dir.test @@ -0,0 +1,16 @@ +--source include/big_test.inc +--source include/galera_cluster.inc + +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + +--source suite/galera/include/galera_st_shutdown_slave.inc +--source suite/galera/include/galera_st_clean_slave.inc + +--source suite/galera/include/galera_st_kill_slave.inc +--source suite/galera/include/galera_st_kill_slave_ddl.inc +--source include/auto_increment_offset_restore.inc + +# cleanup temporary database files: +--remove_files_wildcard $MYSQL_TMP_DIR/rsync_test_2 * diff --git a/mysql-test/suite/galera/t/galera_var_desync_on.test b/mysql-test/suite/galera/t/galera_var_desync_on.test index 06c5d30a769..fbf660d3ab5 100644 --- a/mysql-test/suite/galera/t/galera_var_desync_on.test +++ b/mysql-test/suite/galera/t/galera_var_desync_on.test @@ -1,5 +1,7 @@ # -# Test wsrep_desync = ON . Node should temporarily not participate in flow control +# Desync will be done once the global read lock is acquired and resync will be done when +# it is released. +# Node should temporarily not participate in flow control # so even if fc_limit has been reached, the master should be able to continue to # commit transactions. # @@ -13,7 +15,6 @@ INSERT INTO t1 VALUES (1); --connection node_2 --let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` SET GLOBAL wsrep_provider_options = 'gcs.fc_limit=1'; -SET GLOBAL wsrep_desync = TRUE; # Block the slave applier thread FLUSH TABLES WITH READ LOCK; @@ -37,8 +38,6 @@ SET SESSION wsrep_sync_wait = 0; # No updates have arrived after the FLUSH TABLES SELECT COUNT(*) = 1 FROM t1; -# Resync the slave -SET GLOBAL wsrep_desync = FALSE; --disable_query_log --eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig'; --enable_query_log diff --git a/mysql-test/suite/maria/concurrent.result b/mysql-test/suite/maria/concurrent.result new file mode 100644 index 00000000000..caea6fd1fb9 --- /dev/null +++ b/mysql-test/suite/maria/concurrent.result @@ -0,0 +1,33 @@ +CREATE TABLE t1 (a INT, b CHAR(12), c INT, FULLTEXT KEY(b), KEY (c)) ENGINE=Aria; +CREATE TABLE t2 (a INT, b CHAR(12), c INT) ENGINE=Aria; +INSERT INTO t2 VALUES (1,'foo',8), (2,'bar',9); +connect con1,localhost,root,,test; +INSERT INTO t1 SELECT * FROM t2; +connection default; +select 1; +1 +1 +select 1; +1 +1 +select 1; +1 +1 +select 1; +1 +1 +select 1; +1 +1 +select 1; +1 +1 +select 1; +1 +1 +SELECT * FROM t1 WHERE a = ( SELECT 1 FROM non_existing_table2 ); +ERROR 42S02: Table 'test.non_existing_table2' doesn't exist +connection con1; +disconnect con1; +connection default; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/maria/concurrent.test b/mysql-test/suite/maria/concurrent.test new file mode 100644 index 00000000000..42adb082d40 --- /dev/null +++ b/mysql-test/suite/maria/concurrent.test @@ -0,0 +1,28 @@ +# +# MDEV-15797 Assertion `thd->killed != 0' failed in ha_maria::enable_indexes +# + +CREATE TABLE t1 (a INT, b CHAR(12), c INT, FULLTEXT KEY(b), KEY (c)) ENGINE=Aria; +CREATE TABLE t2 (a INT, b CHAR(12), c INT) ENGINE=Aria; +INSERT INTO t2 VALUES (1,'foo',8), (2,'bar',9); + +--connect (con1,localhost,root,,test) +--send + INSERT INTO t1 SELECT * FROM t2; +--connection default +select 1; +select 1; +select 1; +select 1; +select 1; +select 1; +select 1; +--error ER_NO_SUCH_TABLE +SELECT * FROM t1 WHERE a = ( SELECT 1 FROM non_existing_table2 ); +--connection con1 +--reap + +# Cleanup +--disconnect con1 +--connection default +DROP TABLE t1, t2; diff --git a/mysql-test/suite/maria/maria.result b/mysql-test/suite/maria/maria.result index 765a417e4f2..c17ae47322e 100644 --- a/mysql-test/suite/maria/maria.result +++ b/mysql-test/suite/maria/maria.result @@ -2227,9 +2227,9 @@ Block_size: 8192 Recordlength: 99 Table description: -Key Start Len Index Type -1 2 30 multip. varchar -2 33 30 multip. char NULL +Key Start Len Index Type +1 2 30 multip. varchar +2 33 30 multip. char NULL DROP TABLE t1; create table t1 (n int not null, c char(1)) transactional=1; show create table t1; diff --git a/mysql-test/suite/mariabackup/disabled.def b/mysql-test/suite/mariabackup/disabled.def deleted file mode 100644 index a7be04bfc16..00000000000 --- a/mysql-test/suite/mariabackup/disabled.def +++ /dev/null @@ -1 +0,0 @@ -unsupported_redo : MDEV-16791 allows optimized redo \ No newline at end of file diff --git a/mysql-test/suite/mariabackup/skip_innodb.opt b/mysql-test/suite/mariabackup/skip_innodb.opt new file mode 100644 index 00000000000..213331f5575 --- /dev/null +++ b/mysql-test/suite/mariabackup/skip_innodb.opt @@ -0,0 +1 @@ +--loose-skip-innodb \ No newline at end of file diff --git a/mysql-test/suite/mariabackup/skip_innodb.result b/mysql-test/suite/mariabackup/skip_innodb.result new file mode 100644 index 00000000000..0d56b55bf4b --- /dev/null +++ b/mysql-test/suite/mariabackup/skip_innodb.result @@ -0,0 +1,10 @@ +CREATE TABLE t(i int); +INSERT INTO t VALUES(1); +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +SELECT * from t; +i +1 +DROP TABLE t; diff --git a/mysql-test/suite/mariabackup/skip_innodb.test b/mysql-test/suite/mariabackup/skip_innodb.test new file mode 100644 index 00000000000..14e4bc007f6 --- /dev/null +++ b/mysql-test/suite/mariabackup/skip_innodb.test @@ -0,0 +1,12 @@ +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +CREATE TABLE t(i int); +INSERT INTO t VALUES(1); +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +exec $XTRABACKUP --prepare --target-dir=$targetdir; +-- source include/restart_and_restore.inc +--enable_result_log +SELECT * from t; +DROP TABLE t; + +rmdir $targetdir; \ No newline at end of file diff --git a/mysql-test/suite/mariabackup/truncate_during_backup.result b/mysql-test/suite/mariabackup/truncate_during_backup.result new file mode 100644 index 00000000000..f9d5c785749 --- /dev/null +++ b/mysql-test/suite/mariabackup/truncate_during_backup.result @@ -0,0 +1,4 @@ +CREATE TABLE t1 ENGINE=InnoDB SELECT 1; +DROP TABLE t1; +SET GLOBAL innodb_log_checkpoint_now=1; +SET GLOBAL innodb_log_checkpoint_now=DEFAULT; diff --git a/mysql-test/suite/mariabackup/truncate_during_backup.test b/mysql-test/suite/mariabackup/truncate_during_backup.test new file mode 100644 index 00000000000..c01a74588e7 --- /dev/null +++ b/mysql-test/suite/mariabackup/truncate_during_backup.test @@ -0,0 +1,19 @@ +--source include/have_debug.inc +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +mkdir $targetdir; + +CREATE TABLE t1 ENGINE=InnoDB SELECT 1; + +--let after_load_tablespaces=TRUNCATE test.t1 + +--disable_result_log +--error 1 +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events; +--enable_result_log + +--let after_load_tablespaces= + +DROP TABLE t1; +SET GLOBAL innodb_log_checkpoint_now=1; +SET GLOBAL innodb_log_checkpoint_now=DEFAULT; +rmdir $targetdir; diff --git a/mysql-test/suite/mariabackup/unsupported_redo.result b/mysql-test/suite/mariabackup/unsupported_redo.result index a1f95c099cd..fbad89be0ac 100644 --- a/mysql-test/suite/mariabackup/unsupported_redo.result +++ b/mysql-test/suite/mariabackup/unsupported_redo.result @@ -7,7 +7,7 @@ call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: "); call mtr.add_suppression("Table .* in the InnoDB data dictionary has tablespace id .*, but tablespace with that id or name does not exist"); CREATE TABLE t1(i INT PRIMARY KEY auto_increment, a int) ENGINE INNODB; ALTER TABLE t1 FORCE, ALGORITHM=INPLACE; -# Fails during full backup +# No longer fails during full backup DROP TABLE t1; CREATE TABLE t1(i INT PRIMARY KEY auto_increment, a int) ENGINE INNODB; INSERT INTO t1(a) select 1 union select 2 union select 3; diff --git a/mysql-test/suite/mariabackup/unsupported_redo.test b/mysql-test/suite/mariabackup/unsupported_redo.test index 319ee2c7571..b9456751b9c 100644 --- a/mysql-test/suite/mariabackup/unsupported_redo.test +++ b/mysql-test/suite/mariabackup/unsupported_redo.test @@ -11,33 +11,15 @@ let $basedir=$MYSQLTEST_VARDIR/tmp/backup; let $incremental_dir=$MYSQLTEST_VARDIR/tmp/backup_inc1; CREATE TABLE t1(i INT PRIMARY KEY auto_increment, a int) ENGINE INNODB; ---source ../../suite/innodb/include/no_checkpoint_start.inc ALTER TABLE t1 FORCE, ALGORITHM=INPLACE; -# Below mariabackup operation may complete successfully if checkpoint happens -# after the alter table command. - -echo # Fails during full backup; +echo # No longer fails during full backup; --disable_result_log ---error 0,1 exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir; --enable_result_log DROP TABLE t1; ---let MYSQLD_DATADIR=$basedir/ -perl; -open(OUT, ">$ENV{MYSQLTEST_VARDIR}/log/check.txt") || die; -print OUT ' ---let no_checkpoint_end=1 ---let CLEANUP_IF_CHECKPOINT=rmdir $basedir; ---source ../../suite/innodb/include/no_checkpoint_end.inc ---exit Backup failed to fail despite MLOG_INDEX_LOAD record -' if (-f "$ENV{MYSQLD_DATADIR}/xtrabackup_info"); -close(OUT); -EOF ---source $MYSQLTEST_VARDIR/log/check.txt ---remove_file $MYSQLTEST_VARDIR/log/check.txt rmdir $basedir; CREATE TABLE t1(i INT PRIMARY KEY auto_increment, a int) ENGINE INNODB; @@ -50,29 +32,14 @@ INSERT INTO t1(a) select 1 union select 2 union select 3; exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir; --enable_result_log ---source ../../suite/innodb/include/no_checkpoint_start.inc ALTER TABLE t1 FORCE, ALGORITHM=INPLACE; --disable_result_log ---error 0,1 exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$incremental_dir --incremental-basedir=$basedir; --enable_result_log DROP TABLE t1; ---let MYSQLD_DATADIR=$incremental_dir/ -perl; -open(OUT, ">$ENV{MYSQLTEST_VARDIR}/log/check.txt") || die; -print OUT ' ---let no_checkpoint_end=1 ---let CLEANUP_IF_CHECKPOINT=rmdir $basedir;rmdir $incremental_dir; ---source ../../suite/innodb/include/no_checkpoint_end.inc ---exit Backup failed to fail despite MLOG_INDEX_LOAD record -' if (-f "$ENV{MYSQLD_DATADIR}/xtrabackup_info"); -close(OUT); -EOF ---source $MYSQLTEST_VARDIR/log/check.txt ---remove_file $MYSQLTEST_VARDIR/log/check.txt rmdir $basedir;rmdir $incremental_dir; CREATE TABLE t1(i INT) ENGINE INNODB; diff --git a/mysql-test/suite/plugins/r/auth_ed25519.result b/mysql-test/suite/plugins/r/auth_ed25519.result index ee9320bbc6c..4785bef3ef7 100644 --- a/mysql-test/suite/plugins/r/auth_ed25519.result +++ b/mysql-test/suite/plugins/r/auth_ed25519.result @@ -33,7 +33,7 @@ PLUGIN_DESCRIPTION Elliptic curve ED25519 based authentication PLUGIN_LICENSE GPL LOAD_OPTION ON PLUGIN_MATURITY Stable -PLUGIN_AUTH_VERSION 1.0-alpha +PLUGIN_AUTH_VERSION 1.0 create user test1@localhost identified via ed25519 using 'ZIgUREUg5PVgQ6LskhXmO+eZLS0nC8be6HPjYWR4YJY'; show grants for test1@localhost; Grants for test1@localhost diff --git a/mysql-test/suite/rpl/r/rpl_row_spatial.result b/mysql-test/suite/rpl/r/rpl_row_spatial.result new file mode 100644 index 00000000000..86bac89a174 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_row_spatial.result @@ -0,0 +1,16 @@ +include/master-slave.inc +[connection master] +CREATE TABLE t1 (g POINT NOT NULL, SPATIAL INDEX(g)); +INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(1 1)')); +INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(2 1)')); +INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(1 2)')); +INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(2 2)')); +DELETE FROM t1 where MBREqual(g, ST_GEOMFROMTEXT('Point(1 2)')); +connection slave; +select count(*) from t1; +count(*) +3 +connection master; +DELETE FROM t1; +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_spatial.test b/mysql-test/suite/rpl/t/rpl_row_spatial.test new file mode 100644 index 00000000000..00c3dd7c54d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_spatial.test @@ -0,0 +1,17 @@ +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +CREATE TABLE t1 (g POINT NOT NULL, SPATIAL INDEX(g)); +INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(1 1)')); +INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(2 1)')); +INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(1 2)')); +INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(2 2)')); +DELETE FROM t1 where MBREqual(g, ST_GEOMFROMTEXT('Point(1 2)')); + +--sync_slave_with_master +select count(*) from t1; + +--connection master +DELETE FROM t1; +drop table t1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/sql_sequence/auto_increment.result b/mysql-test/suite/sql_sequence/auto_increment.result new file mode 100644 index 00000000000..bf0a04bbaf1 --- /dev/null +++ b/mysql-test/suite/sql_sequence/auto_increment.result @@ -0,0 +1,30 @@ +set global auto_increment_increment= 2, auto_increment_offset= 2; +create sequence s start with -3 minvalue= -1000 increment 0; +select nextval(s); +nextval(s) +-2 +select nextval(s); +nextval(s) +0 +flush tables; +select nextval(s); +nextval(s) +1998 +drop sequence s; +set global auto_increment_increment= 2, auto_increment_offset= 1; +create sequence s start with -3 minvalue= -1000 increment 0; +select nextval(s); +nextval(s) +-3 +select nextval(s); +nextval(s) +-1 +select nextval(s); +nextval(s) +1 +flush tables; +select nextval(s); +nextval(s) +1997 +drop sequence s; +set global auto_increment_increment= default, auto_increment_offset= default; diff --git a/mysql-test/suite/sql_sequence/auto_increment.test b/mysql-test/suite/sql_sequence/auto_increment.test new file mode 100644 index 00000000000..335bef7ea37 --- /dev/null +++ b/mysql-test/suite/sql_sequence/auto_increment.test @@ -0,0 +1,30 @@ +--source include/have_sequence.inc + +# +# tests with auto_increment_increment and auto_increment_offset +# + +set global auto_increment_increment= 2, auto_increment_offset= 2; + +create sequence s start with -3 minvalue= -1000 increment 0; + +select nextval(s); +select nextval(s); +flush tables; +select nextval(s); +drop sequence s; + +set global auto_increment_increment= 2, auto_increment_offset= 1; + +create sequence s start with -3 minvalue= -1000 increment 0; + +select nextval(s); +select nextval(s); +select nextval(s); +flush tables; +select nextval(s); +drop sequence s; + +# Clean up + +set global auto_increment_increment= default, auto_increment_offset= default; diff --git a/mysql-test/suite/sql_sequence/next.result b/mysql-test/suite/sql_sequence/next.result index d138c342c9d..b1b1bb69306 100644 --- a/mysql-test/suite/sql_sequence/next.result +++ b/mysql-test/suite/sql_sequence/next.result @@ -519,3 +519,18 @@ create temporary table tmp (i int); select next value for tmp; ERROR 42S02: 'test.tmp' is not a SEQUENCE drop table tmp; +# +# Test negative numbers +# +create sequence s start with 1 minvalue=-1000 maxvalue=1000 increment -1; +select next value for s; +next value for s +1 +select next value for s; +next value for s +0 +flush tables; +select next value for s; +next value for s +-999 +drop sequence s; diff --git a/mysql-test/suite/sql_sequence/next.test b/mysql-test/suite/sql_sequence/next.test index 79249002d8f..a1f91bd7823 100644 --- a/mysql-test/suite/sql_sequence/next.test +++ b/mysql-test/suite/sql_sequence/next.test @@ -269,3 +269,14 @@ create temporary table tmp (i int); --error ER_NOT_SEQUENCE select next value for tmp; drop table tmp; + +--echo # +--echo # Test negative numbers +--echo # + +create sequence s start with 1 minvalue=-1000 maxvalue=1000 increment -1; +select next value for s; +select next value for s; +flush tables; +select next value for s; +drop sequence s; 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 01c426b117f..e5a684e71fe 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -880,6 +880,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME EQ_RANGE_INDEX_DIVE_LIMIT +SESSION_VALUE 0 +GLOBAL_VALUE 0 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 0 +VARIABLE_SCOPE SESSION +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT The optimizer will use existing index statistics instead of doing index dives for equality ranges if the number of equality ranges for the index is larger than or equal to this number. If set to 0, index dives are always used. +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 4294967295 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ERROR_COUNT SESSION_VALUE 0 GLOBAL_VALUE NULL 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 9f9513867a9..08214e3e888 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -894,6 +894,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME EQ_RANGE_INDEX_DIVE_LIMIT +SESSION_VALUE 0 +GLOBAL_VALUE 0 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 0 +VARIABLE_SCOPE SESSION +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT The optimizer will use existing index statistics instead of doing index dives for equality ranges if the number of equality ranges for the index is larger than or equal to this number. If set to 0, index dives are always used. +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 4294967295 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ERROR_COUNT SESSION_VALUE 0 GLOBAL_VALUE NULL diff --git a/mysql-test/suite/vcol/r/index.result b/mysql-test/suite/vcol/r/index.result index 8860a728bd1..6ab9aa5eb29 100644 --- a/mysql-test/suite/vcol/r/index.result +++ b/mysql-test/suite/vcol/r/index.result @@ -89,3 +89,13 @@ pk left(c, 10) length(c) i 1 bar bar ba 60000 11 drop table t1; disconnect c1; +CREATE TABLE t1 (b BLOB, vb TEXT AS (b) PERSISTENT, KEY(vb(64))) ENGINE=InnoDB; +INSERT INTO t1 (b) VALUES ('foo'); +connect con1,localhost,root,,test; +CREATE TABLE t2 LIKE t1; +connection default; +DELETE FROM t1; +connection con1; +disconnect con1; +connection default; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/vcol/t/index.test b/mysql-test/suite/vcol/t/index.test index 72eed0a8a40..b93c337fab6 100644 --- a/mysql-test/suite/vcol/t/index.test +++ b/mysql-test/suite/vcol/t/index.test @@ -79,3 +79,19 @@ commit; select pk, left(c, 10), length(c), i from t1; drop table t1; disconnect c1; + +# +# MDEV-16961 Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed upon concurrent DELETE and DDL with virtual blob column +# + +CREATE TABLE t1 (b BLOB, vb TEXT AS (b) PERSISTENT, KEY(vb(64))) ENGINE=InnoDB; +INSERT INTO t1 (b) VALUES ('foo'); +--connect (con1,localhost,root,,test) +--send CREATE TABLE t2 LIKE t1 +--connection default +DELETE FROM t1; +--connection con1 +--reap +--disconnect con1 +--connection default +DROP TABLE t1, t2; diff --git a/mysql-test/suite/versioning/r/truncate.result b/mysql-test/suite/versioning/r/truncate.result index 308501915dc..d38b9eed162 100644 --- a/mysql-test/suite/versioning/r/truncate.result +++ b/mysql-test/suite/versioning/r/truncate.result @@ -100,5 +100,11 @@ ERROR 42S02: 'v' is a view unlock tables; drop view v; drop table t; +create table t1 (i int) with system versioning; +create procedure pr() delete history from t1 before system_time now(); +call pr; +call pr; +drop procedure pr; +drop table t1; drop database test; create database test; diff --git a/mysql-test/suite/versioning/t/truncate.test b/mysql-test/suite/versioning/t/truncate.test index 4e039a76567..1727c7787ef 100644 --- a/mysql-test/suite/versioning/t/truncate.test +++ b/mysql-test/suite/versioning/t/truncate.test @@ -107,5 +107,15 @@ unlock tables; drop view v; drop table t; +# +# MDEV-16783 Assertion `!conds' failed in mysql_delete upon 2nd execution of SP with DELETE HISTORY +# +create table t1 (i int) with system versioning; +create procedure pr() delete history from t1 before system_time now(); +call pr; +call pr; +drop procedure pr; +drop table t1; + drop database test; create database test; diff --git a/mysql-test/suite/wsrep/t/variables.test b/mysql-test/suite/wsrep/t/variables.test index 1315f090d5c..40b869422ff 100644 --- a/mysql-test/suite/wsrep/t/variables.test +++ b/mysql-test/suite/wsrep/t/variables.test @@ -101,8 +101,10 @@ SHOW STATUS LIKE 'wsrep_thread_count'; --echo # Setting wsrep_cluster_address triggers the creation of --echo # applier/rollbacker threads. SET GLOBAL wsrep_cluster_address= 'gcomm://'; + --echo # Wait for applier threads to get created. -sleep 3; +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; +--source include/wait_condition.inc --replace_regex /.*libgalera_smm.*/libgalera_smm.so/ SELECT @@global.wsrep_provider; @@ -113,8 +115,11 @@ SHOW STATUS LIKE 'wsrep_thread_count'; SET @wsrep_slave_threads_saved= @@global.wsrep_slave_threads; SET GLOBAL wsrep_slave_threads= 10; + --echo # Wait for applier threads to get created. -sleep 3; +--let $wait_condition = SELECT VARIABLE_VALUE = 11 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; +--source include/wait_condition.inc + SHOW STATUS LIKE 'threads_connected'; SHOW STATUS LIKE 'wsrep_thread_count'; diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests index d97792355b4..2c28c9a663b 100644 --- a/mysql-test/unstable-tests +++ b/mysql-test/unstable-tests @@ -23,7 +23,7 @@ # ############################################################################## -# Based on bb-10.3-release 36e59752e7fc70bc5179a3d730b5ce3ee58e4e30 +# Based on bb-10.3-release fac3e575b203e8d6a522a475f9aab4ec5041b146 #----------------------------------------------------------------------- @@ -32,12 +32,17 @@ archive.archive_symlink : MDEV-12170 archive.discover : MDEV-10510 - Table is marked as crashed archive.mysqlhotcopy_archive : MDEV-10995 - Hang on debug +archive-test_sql_discovery.discover : MDEV-16817 - Table marked as crashed + #----------------------------------------------------------------------- binlog.binlog_commit_wait : MDEV-10150 - Mismatch binlog.binlog_flush_binlogs_delete_domain : MDEV-14431 - Wrong exit code binlog.binlog_killed : MDEV-12925 - Wrong result +binlog.binlog_tmp_table_row : Added in 10.1.35, 10.2.17 binlog.binlog_xa_recover : MDEV-8517 - Extra checkpoint +binlog.load_data_stm_view : MDEV-16948 - Wrong result +binlog_tmp_table_row : Added in 10.3.9 #----------------------------------------------------------------------- @@ -47,6 +52,8 @@ binlog_encryption.encrypted_master_switch_to_unencrypted : MDEV-14190 binlog_encryption.encrypted_slave : Modified in 10.3.8 binlog_encryption.encryption_combo : MDEV-14199 - Table is marked as crashed binlog_encryption.rpl_binlog_errors : MDEV-12742 - Crash +binlog_encryption.rpl_checksum : MDEV-16951 - Wrong result +binlog_encryption.rpl_gtid_basic : MDEV-16947 - Server failed to start binlog_encryption.rpl_loadfile : MDEV-16645 - Timeout in include binlog_encryption.rpl_parallel : MDEV-10653 - Timeout in include binlog_encryption.rpl_relayrotate : MDEV-15194 - Timeout @@ -55,17 +62,13 @@ binlog_encryption.rpl_skip_replication : MDEV-13571 binlog_encryption.rpl_ssl : MDEV-14507 - Timeouts binlog_encryption.rpl_stm_relay_ign_space : MDEV-13278 - Wrong result (test assertion) binlog_encryption.rpl_sync : MDEV-13830 - Assertion failure +binlog_encryption.rpl_typeconv : MDEV-14362 - Lost connection to MySQL server during query #----------------------------------------------------------------------- -compat/oracle.column_compression : Added in 10.3.7 -compat/oracle.func_concat : Modified in 10.3.7 -compat/oracle.gis : Added in 10.3.7 +compat/oracle.events : Added in 10.3.9 compat/oracle.parser : Modified in 10.3.8 compat/oracle.sp-cursor-rowtype : Modified in 10.3.8 -compat/oracle.table_value_constr : Added in 10.3.7 -compat/oracle.versioning : Added in 10.3.7 -compat/oracle.win : Added in 10.3.7 #----------------------------------------------------------------------- @@ -79,7 +82,7 @@ encryption.create_or_replace : MDEV-12694 encryption.debug_key_management : MDEV-13841 - Timeout encryption.encrypt_and_grep : MDEV-13765 - Wrong result encryption.innochecksum : MDEV-13644 - Assertion failure -encryption.innodb-checksum-algorithm : MDEV-12898 - Deadlock of threads +encryption.innodb-checksum-algorithm : MDEV-12898 - Deadlock of threads; MDEV-16896 - Server crash encryption.innodb-compressed-blob : MDEV-14728 - Unable to get certificate encryption.innodb-discard-import : Modified in 10.3.8 encryption.innodb-encryption-alter : MDEV-13566 - Lock wait timeout @@ -97,6 +100,7 @@ encryption.innodb_encryption_discard_import : MDEV-16116 encryption.innodb_encryption_filekeys : MDEV-15673 - Timeout encryption.innodb_encryption_row_compressed : MDEV-16113 - Crash encryption.innodb_first_page : MDEV-10689 - Crash +encryption.innodb_lotoftables : MDEV-16111 - Wrong result encryption.innodb_scrub : MDEV-8139 - scrubbing tests need fixing encryption.innodb_scrub_background : MDEV-8139 - scrubbing tests need fixing encryption.innodb_scrub_compressed : MDEV-8139 - scrubbing tests need fixing @@ -109,18 +113,17 @@ engines/rr_trx.* : MDEV-10998 #----------------------------------------------------------------------- -federated.assisted_discovery : Modified in 10.3.7 +federated.assisted_discovery : Include file modified in 10.0.36 federated.federated_bug_35333 : MDEV-13410 - Wrong result federated.federated_bug_585688 : MDEV-14805 - Server crash, MDEV-12907 - Valgrind federated.federated_innodb : MDEV-10617 - Wrong checksum federated.federated_partition : MDEV-10417 - Fails on Mips federated.federated_transactions : MDEV-10617 - Wrong checksum federated.federatedx : MDEV-10617 - Wrong checksum -federated.federatedx_versioning : Added in 10.3.7 -federated.timestamps : Added in 10.3.7 #----------------------------------------------------------------------- +funcs_1.is_engines_federated : Include file modified in 10.0.36 funcs_1.memory_views : MDEV-11773 - timeout funcs_1.processlist_val_no_prot : MDEV-11223 - Wrong result funcs_1.processlist_val_ps : MDEV-12175 - Wrong plan @@ -153,63 +156,73 @@ galera_3nodes.* : Suite is no #----------------------------------------------------------------------- +gcol.gcol_rollback : MDEV-16954 - Unknown storage engine 'InnoDB' +gcol.gcol_update : Include file modified in 10.2.17, 10.3.9 +gcol.innodb_virtual_basic : MDEV-16950 - Failing assertion gcol.innodb_virtual_debug : MDEV-14134 - Crash, assertion failure; modified in 10.3.8 -gcol.innodb_virtual_index : Modified in 10.3.7 +gcol.innodb_virtual_debug_purge : MDEV-16952 - Wrong result; modified in 10.2.17, 10.3.9 +gcol.innodb_virtual_index : Include file modified in 10.2.17, 10.3.9 +gcol.innodb_virtual_purge : Include file modified in 10.3.9 #----------------------------------------------------------------------- -handler.heap : Modified in 10.3.7 -handler.innodb : Modified in 10.3.7 -handler.interface : Modified in 10.3.7 handler.ps : Added in 10.3.8 #----------------------------------------------------------------------- -heap.heap_auto_increment : MDEV-16652 - Out of range, modified in 10.3.8 +heap.heap_auto_increment : Modified in 10.3.8 #----------------------------------------------------------------------- innodb.101_compatibility : MDEV-13891 - Wrong result innodb.alter_copy : MDEV-16181 - Assertion failure -innodb.alter_foreign_crash : Added in 10.3.7 -innodb.alter_kill : MDEV-16273 - Unknown storage engine 'InnoDB'; added in 10.3.7 -innodb.alter_non_null : Added in 10.3.8 -innodb.alter_non_null_debug : Added in 10.3.8 -innodb.alter_not_null : Modified in 10.3.8 -innodb.alter_partitioned : Added in 10.3.7 -innodb.alter_rename_files : Added in 10.3.7 +innodb.alter_crash : MDEV-16944 - The process cannot access the file +innodb.alter_foreign_crash : Added in 10.2.16 +innodb.alter_kill : MDEV-16273 - Unknown storage engine 'InnoDB', MDEV-16946 - Wrong result +innodb.alter_not_null : Modified in 10.3.9 +innodb.alter_not_null_debug : Added in 10.3.9 +innodb.alter_partitioned_xa : Added in 10.0.36 +innodb.alter_rename_files : Added in 10.2.16 innodb.alter_sql_mode : Combinations added in 10.3.8 -innodb.analyze_table : Added in 10.3.7 +innodb.analyze_table : Added in 10.2.16 innodb.autoinc_persist : MDEV-15282 - Assertion failure innodb.binlog_consistent : MDEV-10618 - Server fails to start +innodb.dml_purge : Include file modified in 10.3.9 innodb.doublewrite : MDEV-12905 - Server crash innodb.group_commit_crash : MDEV-14191 - InnoDB registration failed innodb.group_commit_crash_no_optimize_thread : MDEV-13830 - Assertion failure +innodb.index_merge_threshold : Include files modified in 10.2.17, 10.3.9 +innodb.innodb-16k : Modified in 10.3.9 +innodb.innodb-32k-crash : MDEV-16953 - Corrupt log record found innodb.innodb-64k-crash : MDEV-13872 - Failure and crash on startup +innodb.innodb-alter : Modified in 10.0.36 innodb.innodb-alter-debug : MDEV-13182 - InnoDB: adjusting FSP_SPACE_FLAGS innodb.innodb-alter-table : MDEV-10619 - Testcase timeout innodb.innodb-alter-tempfile : MDEV-15285 - Table already exists innodb.innodb-alter-timestamp : Modified in 10.3.8 innodb.innodb-autoinc : Modified in 10.3.8 innodb.innodb-blob : Modified in 10.3.8 +innodb.innodb-corrupted-table : Modified in 10.3.9 innodb.innodb-fk : MDEV-13832 - Assertion failure on shutdown innodb.innodb-get-fk : MDEV-13276 - Server crash innodb.innodb-index-online : MDEV-14809 - Cannot save statistics +innodb.innodb-mdev-7513 : Modified in 10.3.9 innodb.innodb-mdev7046 : Modified in 10.3.8 -innodb.innodb-online-alter-gis : Modified in 10.3.7 +innodb.innodb-online-alter-gis : Modified in 10.2.16 innodb.innodb-page_compression_default : MDEV-13644 - Assertion failure; modified in 10.3.8 innodb.innodb-page_compression_lzma : MDEV-14353 - Wrong result innodb.innodb-page_compression_snappy : /MDEV-13644 - Assertion failure; modified in 10.3.8 innodb.innodb-page_compression_zip : MDEV-10641 - mutex problem innodb.innodb-table-online : MDEV-13894 - Wrong result; modified in 10.3.8 -innodb.innodb-wl5522 : MDEV-13644 - Assertion failure +innodb.innodb-wl5522 : MDEV-13644 - Assertion failure; modified in 10.3.9 innodb.innodb-wl5522-debug : MDEV-14200 - Wrong errno -innodb.innodb_bug13510739 : Modified in 10.3.7 innodb.innodb_bug14147491 : MDEV-11808 - Index is corrupt innodb.innodb_bug30423 : MDEV-7311 - Wrong result innodb.innodb_bug48024 : MDEV-14352 - Assertion failure -innodb.innodb_bug54044 : Modified in 10.3.7 +innodb.innodb_bug54044 : Modified in 10.2.16 innodb.innodb_bug59641 : MDEV-13830 - Assertion failure +innodb.innodb_buffer_pool_resize : MDEV-16964 - Assertion failure +innodb.innodb_buffer_pool_resize_with_chunks : MDEV-16964 - Assertion failure innodb.innodb_bulk_create_index_replication : MDEV-15273 - Slave failed to start innodb.innodb_defrag_stats_many_tables : MDEV-14198 - Table is full innodb.innodb_defragment_small : Modified in 10.3.8 @@ -219,49 +232,60 @@ innodb.innodb_max_recordsize_64k : MDEV-15203 innodb.innodb_monitor : MDEV-10939 - Testcase timeout innodb.innodb_query_cache : Added in 10.3.8 innodb.innodb_stats : MDEV-10682 - wrong result +innodb.innodb_stats_persistent : Include file modified in 10.2.17, 10.3.9 innodb.innodb_stats_persistent_debug : MDEV-14801 - Operation failed innodb.innodb_sys_semaphore_waits : MDEV-10331 - Semaphore wait innodb.innodb_zip_innochecksum2 : MDEV-13882 - Extra warnings innodb.innodb_zip_innochecksum3 : MDEV-14486 - Resource temporarily unavailable +innodb.instant_alter : Modified in 10.3.9 +innodb.instant_alter_crash : Include file modified in 10.3.9 +innodb.instant_alter_debug : Modified in 10.3.9 +innodb.instant_alter_rollback : Include file modified in 10.3.9 innodb.log_corruption : MDEV-13251 - Wrong result innodb.log_data_file_size : MDEV-14204 - Server failed to start innodb.log_file_name : MDEV-14193 - Exception innodb.log_file_size : MDEV-15668 - Not found pattern -innodb.monitor : MDEV-16179 - Wrong result -innodb.purge_secondary : MDEV-15681 - Wrong result +innodb.monitor : MDEV-16179 - Wrong result; modified in 10.3.9 +innodb.purge_secondary : MDEV-15681 - Wrong result; include file modified in 10.3.9 innodb.purge_thread_shutdown : MDEV-13792 - Wrong result innodb.read_only_recovery : MDEV-13886 - Server crash innodb.recovery_shutdown : MDEV-15671 - Checksum mismatch in datafile innodb.rename_table : Modified in 10.3.8 innodb.row_format_redundant : MDEV-15192 - Trying to access missing tablespace innodb.sp_temp_table : MDEV-16647 - Could not remove temporary table +innodb.strict_mode : Modified in 10.3.9 innodb.table_definition_cache_debug : MDEV-14206 - Extra warning innodb.table_flags : MDEV-13572 - Wrong result innodb.temp_table_savepoint : MDEV-16182 - Wrong result -innodb.temporary_table : MDEV-13265 - Wrong result; modified in 10.3.7 -innodb.tmpdir : Modified in 10.3.7 +innodb.temporary_table : MDEV-13265 - Wrong result; modified in 10.3.9 +innodb.truncate_purge_debug : Include file modified in 10.2.17, 10.3.9 innodb.update_time : MDEV-14804 - Wrong result +innodb.undo_log : Include file modified in 10.2.17, 10.3.9 innodb.xa_recovery : MDEV-15279 - mysqld got exception #----------------------------------------------------------------------- -innodb_fts.fulltext2 : Modified in 10.3.7 -innodb_fts.fulltext_var : Modified in 10.3.7 +innodb_fts.basic : Added in 10.0.36 +innodb_fts.fts_kill_query : Added in 10.1.35, 10.2.17, 10.3.9 innodb_fts.innodb-fts-fic : MDEV-14154 - Assertion failure -innodb_fts.innodb_fts_misc : Modified in 10.3.7 innodb_fts.innodb_fts_misc_debug : MDEV-14156 - Unexpected warning +innodb_fts.innodb_fts_multiple_index : Modified in 10.3.9 innodb_fts.innodb_fts_plugin : MDEV-13888 - Errors in server log innodb_fts.innodb_fts_stopword_charset : MDEV-13259 - Table crashed innodb_fts.sync : MDEV-14808 - Wrong result +innodb_fts.sync_ddl : Added in 10.1.35, 10.2.17, 10.3.9 #----------------------------------------------------------------------- +innodb_gis.create_spatial_index : Modified in 10.2.17, 10.3.9 +innodb_gis.kill_server : MDEV-16941 - Checksum mismatch +innodb_gis.rtree_compress : Include file modified in 10.2.17, 10.3.9 innodb_gis.rtree_compress2 : MDEV-16269 - Wrong result innodb_gis.rtree_concurrent_srch : MDEV-15284 - Wrong result with embedded -innodb_gis.rtree_purge : MDEV-15275 - Timeout +innodb_gis.rtree_purge : MDEV-15275 - Timeout; include file modified in 10.3.9 innodb_gis.rtree_recovery : MDEV-15274 - Error on check innodb_gis.rtree_split : MDEV-14208 - Too many arguments -innodb_gis.rtree_undo : MDEV-14456 - Timeout in include file +innodb_gis.rtree_undo : MDEV-14456 - Timeout in include file; include file modified in 10.3.9 innodb_gis.types : MDEV-15679 - Table is marked as crashed #----------------------------------------------------------------------- @@ -276,51 +300,70 @@ innodb_zip.wl6501_scale_1 : MDEV-13254 #----------------------------------------------------------------------- main.alter_table : Modified in 10.3.8 -main.alter_table_errors : Added in 10.3.7 main.alter_table_trans : MDEV-12084 - timeout main.analyze_stmt_slow_query_log : MDEV-12237 - Wrong result -main.ansi : Modified in 10.3.7 +main.assign_key_cache : Added in 10.0.36 +main.assign_key_cache_debug : Added in 10.0.36 main.auth_named_pipe : MDEV-14724 - System error 2 -main.auto_increment : MDEV-16652 - Out of range, modified in 10.3.8 +main.auto_increment : Modified in 10.3.8 +main.bootstrap : Modified in 10.1.35, 10.2.17, 10.3.9 +main.check_constraint : Modified in 10.2.17, 10.3.9 main.check : Modified in 10.3.8 -main.check_constraint : Modified in 10.3.7 -main.connect : MDEV-16270 - Wrong result +main.column_compression : Modified in 10.3.9 main.connect2 : MDEV-13885 - Server crash +main.connect_debug : Added in 10.0.36 +main.connect : MDEV-16270 - Wrong result main.count_distinct2 : MDEV-11768 - timeout main.create_delayed : MDEV-10605 - failed with timeout main.create_drop_event : MDEV-16271 - Wrong result -main.create_or_replace : Modified in 10.3.7 +main.create_or_replace : Modified in 10.2.16 +main.create_replace_tmp : Added in 10.2.17, 10.3.9 main.cte_nonrecursive : Modified in 10.3.8 -main.cte_recursive : Modified in 10.3.7 -main.ctype_utf16le : MDEV-10675: timeout or extra warnings -main.custom_aggregate_functions : Modified in 10.3.7 +main.cte_recursive : Modified in 10.2.17, 10.3.9 +main.cte_recursive_not_embedded : Added in 10.2.17, 10.3.9 +main.ctype_binary : Modified in 10.1.35, 10.2.17, 10.3.9 +main.ctype_eucjpms : Modified in 10.1.35, 10.2.17, 10.3.9 +main.ctype_euckr : Modified in 10.1.35, 10.2.17, 10.3.9 +main.ctype_gbk : Modified in 10.1.35, 10.2.17, 10.3.9 +main.ctype_latin1 : Modified in 10.1.35, 10.2.17, 10.3.9 +main.ctype_ucs : Modified in 10.1.35, 10.2.17, 10.3.9 +main.ctype_ujis : Modified in 10.1.35, 10.2.17, 10.3.9 +main.ctype_upgrade : MDEV-16945 - Error upon mysql_upgrade +main.ctype_utf16le : MDEV-10675: timeout or extra warnings; modified in 10.1.35, 10.2.17, 10.3.9 +main.ctype_utf16 : MDEV-10675: timeout or extra warnings; modified in 10.1.35, 10.2.17, 10.3.9 +main.ctype_utf32 : Modified in 10.1.35, 10.2.17, 10.3.9 +main.ctype_utf8mb4 : Modified in 10.1.35, 10.2.17, 10.3.9 +main.ctype_utf8 : Modified in 10.1.35, 10.2.17, 10.3.9 main.debug_sync : MDEV-10607 - internal error -main.derived_cond_pushdown : Modified in 10.3.8 +main.derived_cond_pushdown : Modified in 10.2.17, 10.3.9 +main.derived : Modified in 10.1.35, 10.2.17, 10.3.9 main.derived_opt : MDEV-11768 - timeout main.derived_view : Modified in 10.3.8 -main.distinct : MDEV-14194 - Crash; modified in 10.3.7 +main.distinct : MDEV-14194 - Crash main.drop_bad_db_type : MDEV-15676 - Wrong result main.events_2 : MDEV-13277 - Crash main.events_bugs : MDEV-12892 - Crash main.events_restart : MDEV-12236 - Server shutdown problem main.events_slowlog : MDEV-12821 - Wrong result -main.explain_slowquerylog : Modified in 10.3.7 -main.func_json : Modified in 10.3.8 +main.explain_slowquerylog : Modified in 10.2.16 +main.func_json : Modified in 10.3.9 main.func_misc : Modified in 10.3.8 -main.func_time : Modified in 10.3.8 main.func_time_hires : Modified in 10.3.8 +main.func_time : Modified in 10.3.9 main.gis : MDEV-13411 - wrong result on P8 -main.grant : Modified in 10.3.8 main.grant2 : Modified in 10.3.8 -main.grant_not_windows : Added in 10.3.7 +main.grant : Modified in 10.3.9 +main.grant_not_windows : Added in 10.2.16 main.having : Modified in 10.3.8 main.host_cache_size_functionality : MDEV-10606 - sporadic failure on shutdown main.index_intersect_innodb : MDEV-10643 - failed with timeout main.index_merge_innodb : MDEV-7142 - Plan mismatch main.innodb_mysql_lock : MDEV-7861 - Wrong result -main.insert_select : Modified in 10.3.7 -main.invisible_field_grant_completely : Added in 10.3.7 -main.invisible_field_grant_system : Added in 10.3.7 +main.insert_select : Modified in 10.2.16 +main.invisible_field_debug : Modified in 10.3.9 +main.join : Modified in 10.1.35, 10.2.17, 10.3.9 +main.join_cache : Modified in 10.1.35, 10.2.17, 10.3.9 +main.join_outer : Modified in 10.1.35, 10.2.17, 10.3.9 main.kill-2 : MDEV-13257 - Wrong result main.kill_processlist-6619 : MDEV-10793 - Wrong result main.limit : Modified in 10.3.8 @@ -328,39 +371,34 @@ main.lock : Modified in main.log_slow : MDEV-13263 - Wrong result main.log_tables-big : MDEV-13408 - wrong result main.max_statement_time : Modified in 10.3.8 +main.mdev375 : MDEV-10607 - sporadic "can't connect" main.mdev-504 : MDEV-15171 - warning main.merge : MDEV-10607 - sporadic "can't connect" -main.multi_update : Modified in 10.3.7 -main.mysql : Modified in 10.3.7 -main.mysql_client_test_comp : MDEV-16641 - exec failed +main.myisam : Modified in 10.0.36 +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 : Modified in 10.3.7 -main.mysql_upgrade_noengine : MDEV-14355 - Wrong result -main.mysql_upgrade_ssl : MDEV-13492 - Unknown SSL error +main.mysql_cp932 : Modified in 10.2.16 main.mysqld_option_err : MDEV-12747 - Timeout -main.mysqldump : MDEV-14800 - Stack smashing detected; modified in 10.3.8 +main.mysqldump : MDEV-14800 - Stack smashing detected; modified in 10.2.16, 10.3.8 main.mysqlhotcopy_myisam : MDEV-10995 - Hang on debug +main.mysql : Modified in 10.2.16 main.mysqlslap : Modified in 10.3.8 main.mysqltest : MDEV-13887 - Wrong result -main.mysqltest_tracking_info : Added in 10.3.8 +main.mysqltest_tracking_info : Added in 10.2.17, 10.3.8 +main.mysql_upgrade_noengine : MDEV-14355 - Wrong result +main.mysql_upgrade_ssl : MDEV-13492 - Unknown SSL error main.olap : Modified in 10.3.8 main.openssl_1 : MDEV-13492 - Unknown SSL error main.order_by_optimizer_innodb : MDEV-10683 - Wrong result -main.parser : Modified in 10.3.7 main.partition_debug_sync : MDEV-15669 - Deadlock found when trying to get lock -main.partition_innodb : Modified in 10.3.7 main.partition_innodb_plugin : MDEV-12901 - Valgrind warnings -main.partition_open_files_limit : Modified in 10.3.8 -main.ps : MDEV-11017 - Wrong result; modified in 10.3.8 -main.query_cache : MDEV-16180 - Wrong result +main.ps : MDEV-11017 - sporadic wrong Prepared_stmt_count; modified in 10.1.34 main.query_cache_debug : MDEV-15281 - Query cache is disabled +main.query_cache : MDEV-16180 - Wrong result main.range_vs_index_merge_innodb : MDEV-15283 - Server has gone away main.read_only_innodb : Modified in 10.3.8 -main.rename : Modified in 10.3.8 +main.rename : Modified in 10.3.9 main.reset_connection : Added in 10.3.8 -main.select : MDEV-15430 - Wrong result with clang-4 (compiler bug) -main.select_jcl6 : MDEV-15430 - Wrong result with clang-4 (compiler bug) -main.select_pkeycache : MDEV-15430 - Wrong result with clang-4 (compiler bug) main.selectivity : Modified in 10.3.8 main.session_tracker_last_gtid : Added in 10.3.8 main.set_password : Added in 10.3.8 @@ -368,55 +406,55 @@ main.set_statement : MDEV-13183 main.shm : MDEV-12727 - Mismatch, ERROR 2013 main.show_explain : MDEV-10674 - Wrong result code main.show_grants_with_plugin-7985 : Modified in 10.3.8 -main.sp : MDEV-7866 - Mismatch; modified in 10.3.8 -main.sp-code : Modified in 10.3.7 main.sp-condition-handler : Added in 10.3.8 main.sp-cursor : Modified in 10.3.8 +main.sp-innodb : Modified in 10.0.36 +main.sp : MDEV-7866 - Mismatch; modified in 10.3.8 +main.sp_notembedded : MDEV-10607 - internal error main.sp-row : Modified in 10.3.8 main.sp-security : Modified in 10.3.8 -main.sp_notembedded : MDEV-10607 - internal error main.sql_mode : Modified in 10.3.8 main.ssl_ca : MDEV-10895 - SSL connection error on Power main.ssl_cert_verify : MDEV-13735 - Server crash main.ssl_connect : MDEV-13492 - Unknown SSL error main.ssl_timeout : MDEV-11244 - Crash -main.stat_tables_par : MDEV-13266 - Wrong result -main.stat_tables_par_innodb : MDEV-14155 - Wrong rounding -main.statistics : Modified in 10.3.8 main.statistics_close : Added in 10.3.8 +main.statistics : Modified in 10.3.8 +main.stat_tables : Modified in 10.1.35, 10.2.17, 10.3.9 +main.stat_tables_par_innodb : MDEV-14155 - Wrong rounding +main.stat_tables_par : MDEV-13266 - Wrong result main.status : MDEV-13255 - Wrong result -main.subselect-crash_15755 : Added in 10.3.7 +main.subselect4 : Modified in 10.0.36 main.subselect_innodb : MDEV-10614 - Wrong result -main.subselect_sj2_mat : Modified in 10.3.8 -main.symlink-aria-11902 : MDEV-15098 - error 40 from storage engine -main.symlink-myisam-11902 : MDEV-15098 - Error 40 from storage engine +main.subselect : Modified in 10.1.35, 10.2.17, 10.3.9 +main.subselect_sj2_mat : Modified in 10.1.35, 10.2.17, 10.3.9 +main.subselect_sj_mat : Modified in 10.1.35, 10.2.17, 10.3.9 +main.subselect_sj : Modified in 10.0.36 main.tc_heuristic_recover : MDEV-14189 - Wrong result main.trigger : Modified in 10.3.8 main.type_bit : Modified in 10.3.8 main.type_blob : MDEV-15195 - Wrong result; modified in 10.3.8 main.type_datetime : MDEV-14322 - wrong result -main.type_datetime_hires : MDEV-15430 - Wrong result with clang-4 (compiler bug) main.type_decimal : Modified in 10.3.8 -main.type_float : MDEV-15430 - Wrong result with clang-4 (compiler bug) main.type_int : Modified in 10.3.8 -main.type_time_hires : MDEV-15430 - Wrong result with clang-4 (compiler bug) -main.type_timestamp_hires : MDEV-15430 - Wrong result with clang-4 (compiler bug) +main.union : Modified in 10.1.35, 10.2.17, 10.3.9 main.userstat : MDEV-12904 - SSL errors main.win : Modified in 10.3.8 -main.xa : MDEV-11769 - lock wait timeout +main.xa : MDEV-11769 - lock wait timeout; modified in 10.3.9 + #----------------------------------------------------------------------- -maria.alter : Modified in 10.3.7 +maria.alter : Modified in 10.2.16 maria.insert_select : MDEV-12757 - Timeout maria.insert_select-7314 : MDEV-16492 - Timeout maria.lock : Modified in 10.3.8 maria.maria : MDEV-14430 - Extra warning; modified in 10.3.8 -maria.maria-autoinc : MDEV-16652 - Out of range; added in 10.3.8 +maria.maria-autoinc : Added in 10.3.8 #----------------------------------------------------------------------- -mariabackup.absolute_ibdata_paths : MDEV-16642 - Wrong result +mariabackup.absolute_ibdata_paths : MDEV-16571 - Wrong result mariabackup.apply-log-only : MDEV-14192 - Assertion failure mariabackup.apply-log-only-incr : MDEV-14192 - Assertion failure; modified in 10.3.8 mariabackup.backup_ssl : MDEV-14192 - Assertion failure @@ -424,34 +462,43 @@ mariabackup.data_directory : MDEV-15270 mariabackup.full_backup : MDEV-16571 - Wrong result mariabackup.huge_lsn : MDEV-15662 - Sequence number is in the future mariabackup.incremental_backup : MDEV-14192 - Assertion failure -mariabackup.incremental_encrypted : MDEV-14188 - Wrong result, MDEV-15667 - timeout +mariabackup.incremental_encrypted : MDEV-15667 - timeout; modified in 10.3.9 +mariabackup.innodb_log_optimize_ddl : Added in 10.2.17, 10.3.9 +mariabackup.log_checksum_mismatch : MDEV-16571 - Wrong result mariabackup.lock_ddl_per_table : Modified in 10.3.8 mariabackup.mdev-14447 : MDEV-15201 - Timeout; modified in 10.3.8 mariabackup.partial_exclude : MDEV-15270 - Error on exec mariabackup.partition_datadir : Modified in 10.3.8 mariabackup.rename_during_mdl_lock : Added in 10.3.8 +mariabackup.unsupported_redo : MDEV-14192 - Crash; modified in 10.2.17, 10.3.9 mariabackup.xb_aws_key_management : MDEV-15680 - Error: xtrabackup_copy_logfile() failed mariabackup.xb_compressed_encrypted : MDEV-14812 - Segmentation fault -mariabackup.xb_file_key_management : MDEV-16650 - Wrong result +mariabackup.xb_file_key_management : MDEV-16571 - Wrong result mariabackup.xb_history : MDEV-16268 - Error on exec mariabackup.xb_page_compress : MDEV-14810 - status: 1, errno: 11 -mariabackup.xb_partition : MDEV-16643 - Table does not exist mariabackup.xb_rocksdb : Added in 10.3.8 mariabackup.xb_rocksdb_datadir : Added in 10.3.8 mariabackup.xb_rocksdb_datadir_debug : Added in 10.3.8 +mariabackup.xb_partition : MDEV-14192 - Crash mariabackup.xbstream : MDEV-14192 - Crash #----------------------------------------------------------------------- -mroonga/storage.* : MDEV-16127 - Wrong result - mroonga/storage.column_datetime_32bit_2038 : Wrong result on Alpha mroonga/storage.column_datetime_32bit_before_unix_epoch : Wrong result on Alpha mroonga/storage.column_datetime_32bit_max : Wrong result on Alpha mroonga/storage.column_datetime_32bit_out_of_range : Wrong result on Alpha +mroonga/storage.index_multiple_column_range_all_used_less_than : MDEV-16127 - Wrong result with GCC 8 +mroonga/storage.index_multiple_column_range_all_used_less_than_or_equal : MDEV-16127 - Wrong result with GCC 8 +mroonga/storage.index_multiple_column_range_partially_used_have_prefix_less_than : MDEV-16127 - Wrong result with GCC 8 +mroonga/storage.index_multiple_column_range_partially_used_have_prefix_less_than_or_equal : MDEV-16127 - Wrong result with GCC 8 +mroonga/storage.index_multiple_column_range_partially_used_no_prefix_less_than : MDEV-16127 - Wrong result with GCC 8 +mroonga/storage.index_multiple_column_range_partially_used_no_prefix_less_than_or_equal : MDEV-16127 - Wrong result with GCC 8 mroonga/storage.index_multiple_column_unique_date_32bit_equal : Wrong result on Alpha mroonga/storage.index_multiple_column_unique_date_order_32bit_desc : Wrong result on Alpha mroonga/storage.index_multiple_column_unique_datetime_index_read : MDEV-8643 - Valgrind +mroonga/storage.optimization_order_limit_optimized_datetime_less_than : MDEV-16127 - Wrong result with GCC 8 +mroonga/storage.optimization_order_limit_optimized_datetime_less_than_or_equal : MDEV-16127 - Wrong result with GCC 8 mroonga/storage.repair_table_no_index_file : MDEV-9364 - wrong result, MDEV-14807 - wrong error message mroonga/wrapper.repair_table_no_index_file : MDEV-14807 - Wrong error message @@ -474,7 +521,8 @@ parts.partition_auto_increment_maria : MDEV-14430 parts.partition_debug_innodb : MDEV-10891 - Can't create UNIX socket; MDEV-15095 - Table doesn't exist parts.partition_exch_qa_10 : MDEV-11765 - wrong result parts.partition_innodb_status_file : MDEV-12901 - Valgrind -parts.show_create : Added in 10.3.7 +parts.partition_special_innodb : MDEV-16942 - Timeout +parts.truncate_locked : Added in 10.1.35, 10.2.17, 10.3.9 #----------------------------------------------------------------------- @@ -494,6 +542,7 @@ perfschema.hostcache_ipv6_addrinfo_bad_allow : MDEV-13260 perfschema.hostcache_ipv6_ssl : MDEV-10696 - Crash perfschema.partition : Added in 10.3.8 perfschema.privilege_table_io : MDEV-13184 - Extra lines +perfschema.rpl_gtid_func : MDEV-16897 - Wrong result perfschema.socket_connect : MDEV-15677 - Wrong result perfschema.socket_summary_by_event_name_func : MDEV-10622 - Wrong result perfschema.stage_mdl_global : MDEV-11803 - wrong result on slow builders @@ -520,20 +569,19 @@ rocksdb.2pc_group_commit : MDEV-14455 rocksdb.add_index_inplace : MDEV-16648 - Crash rocksdb.allow_no_primary_key : MDEV-16634 - Crash rocksdb.allow_no_primary_key_with_sk : MDEV-16639 - Crash -rocksdb.analyze_table : Modified in 10.3.7 +rocksdb.analyze_table : Modified in 10.2.16 rocksdb.autoinc_crash_safe : MDEV-16637 - Crash rocksdb.autoinc_crash_safe_partition : MDEV-16639 - Crash -rocksdb.autoinc_debug : MDEV-16203 - Wrong result rocksdb.autoinc_secondary : MDEV-16638 - Crash rocksdb.autoinc_vars_thread : MDEV-16573 - Debug sync timed out rocksdb.bloomfilter2 : MDEV-16564 - Wrong result rocksdb.bloomfilter4 : MDEV-16649 - Crash -rocksdb.bulk_load_errors : MDEV-16575 - Wrong result -rocksdb.check_ignore_unknown_options : MDEV-16310 - Non-portable commands; modified in 10.3.8 +rocksdb.check_ignore_unknown_options : Modified in 10.3.8 rocksdb.deadlock : MDEV-16033 - Timeout rocksdb.drop_index_inplace : MDEV-14162 - Crash on shutdown rocksdb.drop_table : MDEV-14308 - Timeout rocksdb.drop_table2 : MDEV-16631 - Crash +rocksdb.drop_table3 : MDEV-16949 - Server crash rocksdb.issue255 : MDEV-16577 - Wrong plan; modified in 10.3.8 rocksdb.locking_issues : MDEV-14464 - Wrong result rocksdb.mariadb_ignore_dirs : MDEV-16639 - Crash @@ -546,9 +594,12 @@ rocksdb.rocksdb_parts : MDEV-13843 rocksdb.singledelete : MDEV-16633 - Crash rocksdb.truncate_table3 : MDEV-14506 - Lost connection to server rocksdb.ttl_primary_read_filtering : MDEV-16560 - Wrong result +rocksdb.ttl_secondary : MDEV-16943 - Timeout rocksdb.ttl_secondary_read_filtering : MDEV-16560 - Wrong result rocksdb.unique_check : MDEV-16576 - Wrong errno rocksdb.use_direct_reads_writes : MDEV-16646 - Crash +rocksdb.validate_datadic : MDEV-12445 - Memory leak +rocksdb.write_sync : MDEV-16965 - Wrong result #----------------------------------------------------------------------- @@ -557,7 +608,10 @@ rocksdb_rpl.rpl_binlog_xid_count : MDEV-16644 #----------------------------------------------------------------------- +rocksdb_sys_vars.rocksdb_rate_limiter_bytes_per_sec_basic : MDEV-16639 - Crash rocksdb_sys_vars.rocksdb_remove_mariabackup_checkpoint_basic : Added in 10.3.8 +rocksdb_sys_vars.rocksdb_update_cf_options_basic : MDEV-16955 - Bytes lost +rocksdb_sys_vars.rocksdb_update_cf_options : MDEV-16955 - Bytes lost #----------------------------------------------------------------------- @@ -570,8 +624,11 @@ roles.set_default_role_ps-6960 : Modified in rpl-tokudb.* : MDEV-14354 - Tests fail with tcmalloc +rpl-tokudb.rpl_tokudb_commit_after_flush : MDEV-16966 - Server crash + rpl.last_insert_id : MDEV-10625 - warnings in error log rpl.rename : Added in 10.3.8 +rpl.rpl_15867 : Added in 10.2.17, 10.3.9 rpl.rpl_auto_increment : MDEV-10417 - Fails on Mips rpl.rpl_auto_increment_bug45679 : MDEV-10417 - Fails on Mips rpl.rpl_auto_increment_update_failure : MDEV-10625 - warnings in error log @@ -583,6 +640,7 @@ rpl.rpl_ddl : MDEV-10417 rpl.rpl_do_grant : Modified in 10.3.8 rpl.rpl_domain_id_filter_io_crash : MDEV-12729 - Timeout in include file, MDEV-13677 - Server crash rpl.rpl_domain_id_filter_restart : MDEV-10684 - Wrong result +rpl.rpl_drop_db_fail : MDEV-16898 - Slave fails to start rpl.rpl_extra_col_master_innodb : MDEV-16570 - Extra warning rpl.rpl_extra_col_master_myisam : MDEV-14203 - Extra warning rpl.rpl_gtid_basic : MDEV-10681 - server startup problem @@ -602,9 +660,8 @@ rpl.rpl_insert_id_pk : MDEV-16567 rpl.rpl_insert_ignore : MDEV-14365 - Lost connection to MySQL server during query rpl.rpl_invoked_features : MDEV-10417 - Fails on Mips rpl.rpl_mariadb_slave_capability : MDEV-11018 - Extra lines in binlog -rpl.rpl_mdev12179 : Modified in 10.3.7 -rpl.rpl_mdev382 : Modified in 10.3.7 rpl.rpl_mdev6020 : MDEV-15272 - Server crash +rpl.rpl_mixed_implicit_commit_binlog : Included file modified in 10.0.36 rpl.rpl_mixed_mixing_engines : MDEV-14489 - Sync slave with master failed rpl.rpl_non_direct_mixed_mixing_engines : MDEV-14489 - Sync slave with master failed rpl.rpl_non_direct_row_mixing_engines : MDEV-16561 - Timeout in master_pos_wait @@ -619,13 +676,14 @@ rpl.rpl_parallel_retry : MDEV-11119 rpl.rpl_parallel_temptable : MDEV-10356 - Crash rpl.rpl_partition_innodb : MDEV-10417 - Fails on Mips rpl.rpl_password_boundaries : MDEV-11534 - Slave IO warnings -rpl.rpl_row_001 : MDEV-16653 - MTR's internal check fails +rpl.rpl_row_001 : MDEV-16653 - MTR's internal check fails; modified in 10.3.9 rpl.rpl_row_basic_11bugs : MDEV-12171 - Server failed to start rpl.rpl_row_basic_2myisam : MDEV-13875 - command "diff_files" failed rpl.rpl_row_drop_create_temp_table : MDEV-14487 - Wrong result rpl.rpl_row_img_blobs : MDEV-13875 - command "diff_files" failed rpl.rpl_row_img_eng_min : MDEV-13875 - diff_files failed rpl.rpl_row_img_eng_noblob : MDEV-13875 - command "diff_files" failed +rpl.rpl_row_implicit_commit_binlog : Included file modified in 10.0.36 rpl.rpl_row_index_choice : MDEV-15196 - Slave crash rpl.rpl_row_sp001 : MDEV-9329 - Fails on Ubuntu/s390x rpl.rpl_row_until : MDEV-14052 - Master will not send events with checksum @@ -633,6 +691,7 @@ rpl.rpl_semi_sync : MDEV-11220 rpl.rpl_semi_sync_after_sync : MDEV-14366 - Wrong result rpl.rpl_semi_sync_after_sync_row : MDEV-14366 - Wrong result rpl.rpl_semi_sync_event_after_sync : MDEV-11806 - warnings +rpl.rpl_semi_sync_master_shutdown : Added in 10.3.9 rpl.rpl_semi_sync_uninstall_plugin : MDEV-7140 - Assorted failures rpl.rpl_semi_sync_wait_point : MDEV-11807 - timeout in wait condition rpl.rpl_semisync_ali_issues : MDEV-16272 - Wrong result @@ -644,7 +703,8 @@ rpl.rpl_slave_load_tmpdir_not_exist : MDEV-14203 rpl.rpl_slow_query_log : MDEV-13250 - Test abort rpl.rpl_sp_effects : MDEV-13249 - Crash rpl.rpl_start_stop_slave : MDEV-13567 - Sync slave timeout -rpl.rpl_stm_000001 : MDEV-16274 - Connection attributes were truncated +rpl.rpl_stm_000001 : MDEV-16274 - Connection attributes were truncated; modified in 10.3.9 +rpl.rpl_stm_implicit_commit_binlog : Included file modified in 10.0.36 rpl.rpl_stm_mixing_engines : MDEV-14489 - Sync slave with master failed rpl.rpl_stm_multi_query : MDEV-9501 - Failed registering on master rpl.rpl_stm_relay_ign_space : MDEV-14360 - Test assertion @@ -669,6 +729,7 @@ sphinx.union-5539 : MDEV-10986 spider.* : MDEV-9329 - tests are too memory-consuming spider.basic_sql : MDEV-11186 - Internal check fails spider.spider_fixes_part : Modified in 10.3.8 +spider.timestamp : Added in 10.3.9 spider/bg.direct_aggregate : MDEV-7098 - Packets out of order spider/bg.direct_aggregate_part : MDEV-7098 - Trying to unlock mutex that wasn't locked @@ -699,7 +760,7 @@ stress.ddl_innodb : MDEV-10635 sys_vars.autocommit_func2 : MDEV-9329 - Fails on Ubuntu/s390x sys_vars.innodb_buffer_pool_dump_at_shutdown_basic : MDEV-14280 - Unexpected error -sys_vars.innodb_stats_include_delete_marked_basic : Modified in 10.3.7 +sys_vars.innodb_log_optimize_ddl_basic : Added in 10.2.17, 10.3.9 sys_vars.keep_files_on_create_basic : MDEV-10676 - timeout sys_vars.log_slow_admin_statements_func : MDEV-12235 - Server crash sys_vars.maximum_basic : Modified in 10.3.8 @@ -748,6 +809,7 @@ tokudb_bugs.frm_store : MDEV-12823 tokudb_bugs.frm_store2 : MDEV-12823 - Valgrind tokudb_bugs.frm_store3 : MDEV-12823 - Valgrind tokudb_bugs.xa : MDEV-11804 - Lock wait timeout +tokudb_bugs.xa-3 : MDEV-16953 - Corrupt log record found #----------------------------------------------------------------------- @@ -783,16 +845,13 @@ vcol.vcol_misc : MDEV-16651 #----------------------------------------------------------------------- versioning.alter : Modified in 10.3.8 -versioning.partition : Modified in 10.3.7 versioning.replace : Modified in 10.3.8 versioning.select : Modified in 10.3.8 -versioning.truncate : Modified in 10.3.7 versioning.trx_id : Modified in 10.3.8 versioning.trx_id_versioning_attribute_persistence : Added in 10.3.8 #----------------------------------------------------------------------- -wsrep.binlog_format : MDEV-11532 - Could not execute check-testcase wsrep.foreign_key : MDEV-14725 - WSREP has not yet prepared node wsrep.mdev_6832 : MDEV-14195 - Check testcase failed wsrep.pool_of_threads : MDEV-12234 - GLIBCXX_3.4.20 not found diff --git a/plugin/auth_ed25519/server_ed25519.c b/plugin/auth_ed25519/server_ed25519.c index 8870c271b18..23b4e7389c7 100644 --- a/plugin/auth_ed25519/server_ed25519.c +++ b/plugin/auth_ed25519/server_ed25519.c @@ -100,7 +100,7 @@ maria_declare_plugin(ed25519) 0x0100, NULL, NULL, - "1.0-alpha", + "1.0", MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; diff --git a/plugin/auth_pam/mapper/pam_user_map.c b/plugin/auth_pam/mapper/pam_user_map.c index c03ea12be74..e1d11acabb9 100644 --- a/plugin/auth_pam/mapper/pam_user_map.c +++ b/plugin/auth_pam/mapper/pam_user_map.c @@ -189,13 +189,15 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, s++; } from= s; - skip(isalnum(*s) || (*s == '_') || (*s == '.') || (*s == '-') || (*s == '$')); + skip(isalnum(*s) || (*s == '_') || (*s == '.') || (*s == '-') || + (*s == '$') || (*s == '\\') || (*s == '/')); end_from= s; skip(isspace(*s)); if (end_from == from || *s++ != ':') goto syntax_error; skip(isspace(*s)); to= s; - skip(isalnum(*s) || (*s == '_') || (*s == '.') || (*s == '-') || (*s == '$')); + skip(isalnum(*s) || (*s == '_') || (*s == '.') || (*s == '-') || + (*s == '$')); end_to= s; if (end_to == to) goto syntax_error; diff --git a/scripts/galera_recovery.sh b/scripts/galera_recovery.sh index 09de6721762..c58f3d8f6b9 100644 --- a/scripts/galera_recovery.sh +++ b/scripts/galera_recovery.sh @@ -107,8 +107,7 @@ else log "WSREP: mktemp failed" fi -parse_arguments `$print_defaults $cmdline_args --loose-verbose \ - mariadb mariadb_safe mysqld mysqld_safe safe_mysqld galera` +parse_arguments `$print_defaults $cmdline_args --loose-verbose --mysqld` # Perform wsrep position recovery if wsrep_on=1, skip otherwise. if [ "$wsrep_on" -eq 1 ]; then diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 21da52b015e..313821f522d 100755 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -27,6 +27,7 @@ WSREP_SST_OPT_PSWD=${WSREP_SST_OPT_PSWD:-} WSREP_SST_OPT_DEFAULT="" WSREP_SST_OPT_EXTRA_DEFAULT="" WSREP_SST_OPT_SUFFIX_DEFAULT="" +WSREP_SST_OPT_SUFFIX_VALUE="" while [ $# -gt 0 ]; do case "$1" in @@ -76,6 +77,7 @@ case "$1" in ;; '--defaults-group-suffix') readonly WSREP_SST_OPT_SUFFIX_DEFAULT="$1=$2" + readonly WSREP_SST_OPT_SUFFIX_VALUE="$2" shift ;; '--host') @@ -272,8 +274,8 @@ parse_cnf() reval=$($MY_PRINT_DEFAULTS "${group}" | awk -v var="${var}" 'BEGIN { OFS=FS="=" } { gsub(/_/,"-",$1); if ( $1=="--"var) lastval=substr($0,length($1)+2) } END { print lastval}') # use default if we haven't found a value - if [ -z $reval ]; then - [ -n $3 ] && reval=$3 + if [ -z "$reval" ]; then + [ -n "$3" ] && reval=$3 fi echo $reval } diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index ca78d4917ff..1bfdb83633a 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -41,6 +41,8 @@ cleanup_joiner() kill -9 $RSYNC_REAL_PID >/dev/null 2>&1 || \ : rm -rf "$RSYNC_CONF" + rm -f "$STUNNEL_CONF" + rm -f "$STUNNEL_PID" rm -rf "$MAGIC_FILE" rm -rf "$RSYNC_PID" wsrep_log_info "Joiner cleanup done." @@ -68,7 +70,7 @@ check_pid_and_port() local port_info="$(sockstat -46lp ${rsync_port} 2>/dev/null | \ grep ":${rsync_port}")" local is_rsync="$(echo $port_info | \ - grep '[[:space:]]\+rsync[[:space:]]\+'"$rsync_pid" 2>/dev/null)" + grep -E '[[:space:]]+(rsync|stunnel)[[:space:]]+'"$rsync_pid" 2>/dev/null)" ;; *) if ! command -v lsof > /dev/null; then @@ -79,7 +81,7 @@ check_pid_and_port() local port_info="$(lsof -i :$rsync_port -Pn 2>/dev/null | \ grep "(LISTEN)")" local is_rsync="$(echo $port_info | \ - grep -w '^rsync[[:space:]]\+'"$rsync_pid" 2>/dev/null)" + grep -E '^(rsync|stunnel)[[:space:]]+'"$rsync_pid" 2>/dev/null)" ;; esac @@ -120,6 +122,12 @@ is_local_ip() $get_addr_bin | grep "$address" > /dev/null } +STUNNEL_CONF="$WSREP_SST_OPT_DATA/stunnel.conf" +rm -f "$STUNNEL_CONF" + +STUNNEL_PID="$WSREP_SST_OPT_DATA/stunnel.pid" +rm -f "$STUNNEL_PID" + MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete" rm -rf "$MAGIC_FILE" @@ -147,6 +155,20 @@ else WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; pwd -P) fi +INNODB_DATA_HOME_DIR=${INNODB_DATA_HOME_DIR:-""} +# if INNODB_DATA_HOME_DIR env. variable is not set, try to get it from my.cnf +if [ -z "$INNODB_DATA_HOME_DIR" ]; then + INNODB_DATA_HOME_DIR=$(parse_cnf mysqld$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') +fi + +if [ -n "$INNODB_DATA_HOME_DIR" ]; then + # handle both relative and absolute paths + INNODB_DATA_HOME_DIR=$(cd $WSREP_SST_OPT_DATA; mkdir -p "$INNODB_DATA_HOME_DIR"; cd $INNODB_DATA_HOME_DIR; pwd -P) +else + # default to datadir + INNODB_DATA_HOME_DIR=$(cd $WSREP_SST_OPT_DATA; pwd -P) +fi + # Old filter - include everything except selected # FILTER=(--exclude '*.err' --exclude '*.pid' --exclude '*.sock' \ # --exclude '*.conf' --exclude core --exclude 'galera.*' \ @@ -155,11 +177,30 @@ fi # New filter - exclude everything except dirs (schemas) and innodb files FILTER="-f '- /lost+found' -f '- /.fseventsd' -f '- /.Trashes' - -f '+ /wsrep_sst_binlog.tar' -f '+ /ib_lru_dump' -f '+ /ibdata*' -f '+ /*/' -f '- /*'" + -f '+ /wsrep_sst_binlog.tar' -f '- $INNODB_DATA_HOME_DIR/ib_lru_dump' -f '- $INNODB_DATA_HOME_DIR/ibdata*' -f '+ /*/' -f '- /*'" + +SSTKEY=$(parse_cnf sst tkey "") +SSTCERT=$(parse_cnf sst tcert "") +STUNNEL="" +if [ -f "$SSTKEY" ] && [ -f "$SSTCERT" ] && wsrep_check_programs stunnel +then + STUNNEL="stunnel ${STUNNEL_CONF}" +fi if [ "$WSREP_SST_OPT_ROLE" = "donor" ] then +cat << EOF > "$STUNNEL_CONF" +CApath = ${SSTCERT%/*} +foreground = yes +pid = $STUNNEL_PID +debug = warning +client = yes +connect = ${WSREP_SST_OPT_ADDR%/*} +TIMEOUTclose = 0 +verifyPeer = yes +EOF + if [ $WSREP_SST_OPT_BYPASS -eq 0 ] then @@ -221,7 +262,8 @@ then # first, the normal directories, so that we can detect incompatible protocol RC=0 - eval rsync --owner --group --perms --links --specials \ + eval rsync ${STUNNEL:+--rsh="$STUNNEL"} \ + --owner --group --perms --links --specials \ --ignore-times --inplace --dirs --delete --quiet \ $WHOLE_FILE_OPT ${FILTER} "$WSREP_SST_OPT_DATA/" \ rsync://$WSREP_SST_OPT_ADDR >&2 || RC=$? @@ -243,8 +285,22 @@ then exit $RC fi + # Transfer InnoDB data files + rsync ${STUNNEL:+--rsh="$STUNNEL"} \ + --owner --group --perms --links --specials \ + --ignore-times --inplace --dirs --delete --quiet \ + $WHOLE_FILE_OPT -f '+ /ibdata*' -f '+ /ib_lru_dump' \ + -f '- **' "$INNODB_DATA_HOME_DIR/" \ + rsync://$WSREP_SST_OPT_ADDR-data_dir >&2 || RC=$? + + if [ $RC -ne 0 ]; then + wsrep_log_error "rsync innodb_data_home_dir returned code $RC:" + exit 255 # unknown error + fi + # second, we transfer InnoDB and Aria log files - rsync --owner --group --perms --links --specials \ + rsync ${STUNNEL:+--rsh="$STUNNEL"} \ + --owner --group --perms --links --specials \ --ignore-times --inplace --dirs --delete --quiet \ $WHOLE_FILE_OPT -f '+ /ib_logfile[0-9]*' -f '+ /aria_log.*' -f '+ /aria_log_control' -f '- **' "$WSREP_LOG_DIR/" \ rsync://$WSREP_SST_OPT_ADDR-log_dir >&2 || RC=$? @@ -264,7 +320,8 @@ then find . -maxdepth 1 -mindepth 1 -type d -not -name "lost+found" \ -print0 | xargs -I{} -0 -P $count \ - rsync --owner --group --perms --links --specials \ + rsync ${STUNNEL:+--rsh="$STUNNEL"} \ + --owner --group --perms --links --specials \ --ignore-times --inplace --recursive --delete --quiet \ $WHOLE_FILE_OPT --exclude '*/ib_logfile*' --exclude "*/aria_log.*" --exclude "*/aria_log_control" "$WSREP_SST_OPT_DATA"/{}/ \ rsync://$WSREP_SST_OPT_ADDR/{} >&2 || RC=$? @@ -287,7 +344,8 @@ then echo "continue" # now server can resume updating data echo "$STATE" > "$MAGIC_FILE" - rsync --archive --quiet --checksum "$MAGIC_FILE" rsync://$WSREP_SST_OPT_ADDR + rsync ${STUNNEL:+--rsh="$STUNNEL"} \ + --archive --quiet --checksum "$MAGIC_FILE" rsync://$WSREP_SST_OPT_ADDR echo "done $STATE" @@ -340,6 +398,8 @@ $SILENT path = $WSREP_SST_OPT_DATA [$MODULE-log_dir] path = $WSREP_LOG_DIR +[$MODULE-data_dir] + path = $INNODB_DATA_HOME_DIR EOF # rm -rf "$DATA"/ib_logfile* # we don't want old logs around @@ -348,14 +408,37 @@ EOF # If the IP is local listen only in it if is_local_ip "$RSYNC_ADDR" then - rsync --daemon --no-detach --address "$RSYNC_ADDR" --port "$RSYNC_PORT" --config "$RSYNC_CONF" & + RSYNC_EXTRA_ARGS="--address $RSYNC_ADDR" + STUNNEL_ACCEPT="$RSYNC_ADDR:$RSYNC_PORT" else - # Not local, possibly a NAT, listen in all interface - rsync --daemon --no-detach --port "$RSYNC_PORT" --config "$RSYNC_CONF" & + # Not local, possibly a NAT, listen on all interfaces + RSYNC_EXTRA_ARGS="" + STUNNEL_ACCEPT="$RSYNC_PORT" # Overwrite address with all RSYNC_ADDR="*" fi - RSYNC_REAL_PID=$! + + if [ -z "$STUNNEL" ] + then + rsync --daemon --no-detach --port "$RSYNC_PORT" --config "$RSYNC_CONF" ${RSYNC_EXTRA_ARGS} & + RSYNC_REAL_PID=$! + else + cat << EOF > "$STUNNEL_CONF" +key = $SSTKEY +cert = $SSTCERT +foreground = yes +pid = $STUNNEL_PID +debug = warning +client = no +[rsync] +accept = $STUNNEL_ACCEPT +exec = $(which rsync) +execargs = rsync --server --daemon --config=$RSYNC_CONF . +EOF + stunnel "$STUNNEL_CONF" & + RSYNC_REAL_PID=$! + RSYNC_PID=$STUNNEL_PID + fi until check_pid_and_port "$RSYNC_PID" "$RSYNC_REAL_PID" "$RSYNC_ADDR" "$RSYNC_PORT" do diff --git a/sql/field.cc b/sql/field.cc index 549fc157da9..743f12f3cc9 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7120,7 +7120,9 @@ int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr) void Field_string::sort_string(uchar *to,uint length) { - IF_DBUG(size_t tmp= ,) +#ifdef DBUG_ASSERT_EXISTS + size_t tmp= +#endif field_charset->coll->strnxfrm(field_charset, to, length, char_length() * @@ -7526,7 +7528,7 @@ void Field_varstring::sort_string(uchar *to,uint length) length-= length_bytes; } -#ifndef DBUG_OFF +#ifdef DBUG_ASSERT_EXISTS size_t rc= #endif field_charset->coll->strnxfrm(field_charset, to, length, @@ -8394,7 +8396,7 @@ void Field_blob::sort_string(uchar *to,uint length) store_bigendian(buf.length(), to + length, packlength); } -#ifndef DBUG_OFF +#ifdef DBUG_ASSERT_EXISTS size_t rc= #endif field_charset->coll->strnxfrm(field_charset, to, length, length, diff --git a/sql/field.h b/sql/field.h index 8b080a0d06f..ed61afe01eb 100644 --- a/sql/field.h +++ b/sql/field.h @@ -2390,7 +2390,6 @@ public: { return unpack_int64(to, from, from_end); } - void set_max(); bool is_max(); }; diff --git a/sql/filesort.cc b/sql/filesort.cc index 1855430b944..6901cee043f 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1004,7 +1004,9 @@ Type_handler_string_result::make_sort_key(uchar *to, Item *item, if (use_strnxfrm(cs)) { - IF_DBUG(size_t tmp_length= ,) +#ifdef DBUG_ASSERT_EXISTS + size_t tmp_length= +#endif cs->coll->strnxfrm(cs, to, sort_field->length, item->max_char_length() * cs->strxfrm_multiply, diff --git a/sql/handler.cc b/sql/handler.cc index e45607cad66..943722af3b3 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -74,7 +74,7 @@ KEY_CREATE_INFO default_key_create_info= ulong total_ha= 0; /* number of storage engines (from handlertons[]) that support 2pc */ ulong total_ha_2pc= 0; -#ifndef DBUG_OFF +#ifdef DBUG_ASSERT_EXISTS /* Number of non-mandatory 2pc handlertons whose initialization failed to estimate total_ha_2pc value under supposition of the failures @@ -661,7 +661,7 @@ err_deinit: (void) plugin->plugin->deinit(NULL); err: -#ifndef DBUG_OFF +#ifdef DBUG_ASSERT_EXISTS if (hton->prepare && hton->state == SHOW_OPTION_YES) failed_ha_2pc++; #endif @@ -3073,6 +3073,45 @@ void handler::adjust_next_insert_id_after_explicit_value(ulonglong nr) } +/** @brief + Computes the largest number X: + - smaller than or equal to "nr" + - of the form: auto_increment_offset + N * auto_increment_increment + where N>=0. + + SYNOPSIS + prev_insert_id + nr Number to "round down" + variables variables struct containing auto_increment_increment and + auto_increment_offset + + RETURN + The number X if it exists, "nr" otherwise. +*/ +inline ulonglong +prev_insert_id(ulonglong nr, struct system_variables *variables) +{ + if (unlikely(nr < variables->auto_increment_offset)) + { + /* + There's nothing good we can do here. That is a pathological case, where + the offset is larger than the column's max possible value, i.e. not even + the first sequence value may be inserted. User will receive warning. + */ + DBUG_PRINT("info",("auto_increment: nr: %lu cannot honour " + "auto_increment_offset: %lu", + (ulong) nr, variables->auto_increment_offset)); + return nr; + } + if (variables->auto_increment_increment == 1) + return nr; // optimization of the formula below + nr= (((nr - variables->auto_increment_offset)) / + (ulonglong) variables->auto_increment_increment); + return (nr * (ulonglong) variables->auto_increment_increment + + variables->auto_increment_offset); +} + + /** Update the auto_increment field if necessary. diff --git a/sql/handler.h b/sql/handler.h index f1080d56bb9..68a54cc207a 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -950,6 +950,7 @@ enum enum_schema_tables SCH_ALL_PLUGINS, SCH_APPLICABLE_ROLES, SCH_CHARSETS, + SCH_CHECK_CONSTRAINTS, SCH_COLLATIONS, SCH_COLLATION_CHARACTER_SET_APPLICABILITY, SCH_COLUMNS, diff --git a/sql/item.cc b/sql/item.cc index 7171a95c21d..f6198e1df68 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7637,7 +7637,7 @@ Item_direct_view_ref::grouping_field_transformer_for_where(THD *thd, void Item_field::print(String *str, enum_query_type query_type) { if (field && field->table->const_table && - !(query_type & QT_NO_DATA_EXPANSION)) + !(query_type & (QT_NO_DATA_EXPANSION | QT_VIEW_INTERNAL))) { print_value(str); return; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 189b315ede6..fb6d99b9498 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4984,6 +4984,19 @@ Item *Item_cond::build_clone(THD *thd) } +bool Item_cond::excl_dep_on_grouping_fields(st_select_lex *sel) +{ + List_iterator_fast li(list); + Item *item; + while ((item= li++)) + { + if (!item->excl_dep_on_grouping_fields(sel)) + return false; + } + return true; +} + + void Item_cond_and::mark_as_condition_AND_part(TABLE_LIST *embedding) { List_iterator li(list); @@ -5120,7 +5133,11 @@ longlong Item_func_isnull::val_int() void Item_func_isnull::print(String *str, enum_query_type query_type) { - args[0]->print_parenthesised(str, query_type, precedence()); + if (const_item() && !args[0]->maybe_null && + !(query_type & (QT_NO_DATA_EXPANSION | QT_VIEW_INTERNAL))) + str->append("/*always not null*/ 1"); + else + args[0]->print_parenthesised(str, query_type, precedence()); str->append(STRING_WITH_LEN(" is null")); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index e58644c1699..db1075b1936 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -2964,6 +2964,7 @@ public: Item_transformer transformer, uchar *arg_t); bool eval_not_null_tables(void *opt_arg); Item *build_clone(THD *thd); + bool excl_dep_on_grouping_fields(st_select_lex *sel); }; template class LI, class T> class Item_equal_iterator; diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h index 48851da7d96..b3e23748246 100644 --- a/sql/item_windowfunc.h +++ b/sql/item_windowfunc.h @@ -1085,6 +1085,8 @@ public: case Item_sum::DENSE_RANK_FUNC: case Item_sum::PERCENT_RANK_FUNC: case Item_sum::CUME_DIST_FUNC: + case Item_sum::LAG_FUNC: + case Item_sum::LEAD_FUNC: case Item_sum::PERCENTILE_CONT_FUNC: case Item_sum::PERCENTILE_DISC_FUNC: return true; diff --git a/sql/key.cc b/sql/key.cc index 34196a973c5..9ad1103fbe8 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -146,7 +146,8 @@ void key_copy(uchar *to_key, const uchar *from_record, KEY *key_info, { key_length-= HA_KEY_BLOB_LENGTH; length= MY_MIN(key_length, key_part->length); - uint bytes= key_part->field->get_key_image(to_key, length, Field::itRAW); + uint bytes= key_part->field->get_key_image(to_key, length, + key_info->flags & HA_SPATIAL ? Field::itMBR : Field::itRAW); if (with_zerofill && bytes < length) bzero((char*) to_key + bytes, length - bytes); to_key+= HA_KEY_BLOB_LENGTH; diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc index cf587ef4acd..d6952e71899 100644 --- a/sql/multi_range_read.cc +++ b/sql/multi_range_read.cc @@ -18,6 +18,7 @@ #include #include "sql_select.h" #include "key.h" +#include "sql_statistics.h" /**************************************************************************** * Default MRR implementation (MRR to non-MRR converter) @@ -64,7 +65,12 @@ handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq, ha_rows rows, total_rows= 0; uint n_ranges=0; THD *thd= table->in_use; + uint limit= thd->variables.eq_range_index_dive_limit; + bool use_statistics_for_eq_range= eq_ranges_exceeds_limit(seq, + seq_init_param, + limit); + /* Default MRR implementation doesn't need buffer */ *bufsz= 0; @@ -88,8 +94,15 @@ handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq, min_endp= range.start_key.length? &range.start_key : NULL; max_endp= range.end_key.length? &range.end_key : NULL; } + int keyparts_used= my_count_bits(range.start_key.keypart_map); if ((range.range_flag & UNIQUE_RANGE) && !(range.range_flag & NULL_RANGE)) rows= 1; /* there can be at most one row */ + else if (use_statistics_for_eq_range && + !(range.range_flag & NULL_RANGE) && + (range.range_flag & EQ_RANGE) && + table->key_info[keyno].actual_rec_per_key(keyparts_used - 1) > 0.5) + rows= + (ha_rows) table->key_info[keyno].actual_rec_per_key(keyparts_used - 1); else { if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3ed6846bde9..acb7532f922 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1476,9 +1476,9 @@ static NTService Service; ///< Service object for WinNT #endif /* __WIN__ */ #ifdef _WIN32 +#include /* ConvertStringSecurityDescriptorToSecurityDescriptor */ static char pipe_name[512]; static SECURITY_ATTRIBUTES saPipeSecurity; -static SECURITY_DESCRIPTOR sdPipeDescriptor; static HANDLE hPipe = INVALID_HANDLE_VALUE; #endif @@ -2711,21 +2711,20 @@ static void network_init(void) strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\", mysqld_unix_port, NullS); - bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity)); - bzero((char*) &sdPipeDescriptor, sizeof(sdPipeDescriptor)); - if (!InitializeSecurityDescriptor(&sdPipeDescriptor, - SECURITY_DESCRIPTOR_REVISION)) + /* + Create a security descriptor for pipe. + - Use low integrity level, so that it is possible to connect + from any process. + - Give Everyone read/write access to pipe. + */ + if (!ConvertStringSecurityDescriptorToSecurityDescriptor( + "S:(ML;; NW;;; LW) D:(A;; FRFW;;; WD)", + SDDL_REVISION_1, &saPipeSecurity.lpSecurityDescriptor, NULL)) { sql_perror("Can't start server : Initialize security descriptor"); unireg_abort(1); } - if (!SetSecurityDescriptorDacl(&sdPipeDescriptor, TRUE, NULL, FALSE)) - { - sql_perror("Can't start server : Set security descriptor"); - unireg_abort(1); - } saPipeSecurity.nLength = sizeof(SECURITY_ATTRIBUTES); - saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor; saPipeSecurity.bInheritHandle = FALSE; if ((hPipe= CreateNamedPipe(pipe_name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, @@ -6965,6 +6964,7 @@ pthread_handler_t handle_connections_namedpipes(void *arg) connect->host= my_localhost; create_new_thread(connect); } + LocalFree(saPipeSecurity.lpSecurityDescriptor); CloseHandle(connectOverlapped.hEvent); DBUG_LEAVE; decrement_handler_count(); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 107c0d8ed89..7faae008dab 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -14829,6 +14829,32 @@ void QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths(String *key_names, } +/* Check whether the number for equality ranges exceeds the set threshold */ + +bool eq_ranges_exceeds_limit(RANGE_SEQ_IF *seq, void *seq_init_param, + uint limit) +{ + KEY_MULTI_RANGE range; + range_seq_t seq_it; + uint count = 0; + + if (limit == 0) + { + /* 'Statistics instead of index dives' feature is turned off */ + return false; + } + seq_it= seq->init(seq_init_param, 0, 0); + while (!seq->next(seq_it, &range)) + { + if ((range.range_flag & EQ_RANGE) && !(range.range_flag & NULL_RANGE)) + { + if (++count >= limit) + return true; + } + } + return false; +} + #ifndef DBUG_OFF static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map, diff --git a/sql/opt_range.h b/sql/opt_range.h index bd85a12d4a1..d5416988b88 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -242,7 +242,7 @@ public: Number of children of this element in the RB-tree, plus 1 for this element itself. */ - uint16 elements; + uint32 elements; /* Valid only for elements which are RB-tree roots: Number of times this RB-tree is referred to (it is referred by SEL_ARG::next_key_part or by @@ -1724,6 +1724,9 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables, bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond); +bool eq_ranges_exceeds_limit(RANGE_SEQ_IF *seq, void *seq_init_param, + uint limit); + #ifdef WITH_PARTITION_STORAGE_ENGINE bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond); #endif diff --git a/sql/opt_range_mrr.cc b/sql/opt_range_mrr.cc index 515d94e8748..2981c8182ea 100644 --- a/sql/opt_range_mrr.cc +++ b/sql/opt_range_mrr.cc @@ -72,6 +72,7 @@ typedef struct st_sel_arg_range_seq range_seq_t sel_arg_range_seq_init(void *init_param, uint n_ranges, uint flags) { SEL_ARG_RANGE_SEQ *seq= (SEL_ARG_RANGE_SEQ*)init_param; + seq->param->range_count=0; seq->at_start= TRUE; seq->stack[0].key_tree= NULL; seq->stack[0].min_key= seq->param->min_key; @@ -272,25 +273,44 @@ walk_up_n_right: key_info= NULL; else key_info= &seq->param->table->key_info[seq->real_keyno]; - + /* - Conditions below: - (1) - range analysis is used for estimating condition selectivity - (2) - This is a unique key, and we have conditions for all its - user-defined key parts. - (3) - The table uses extended keys, this key covers all components, - and we have conditions for all key parts. + This is an equality range (keypart_0=X and ... and keypart_n=Z) if + (1) - There are no flags indicating open range (e.g., + "keypart_x > y") or GIS. + (2) - The lower bound and the upper bound of the range has the + same value (min_key == max_key). */ - if (!(cur->min_key_flag & ~NULL_RANGE) && !cur->max_key_flag && - (!key_info || // (1) - ((uint)key_tree->part+1 == key_info->user_defined_key_parts && // (2) - key_info->flags & HA_NOSAME) || // (2) - ((key_info->flags & HA_EXT_NOSAME) && // (3) - (uint)key_tree->part+1 == key_info->ext_key_parts) // (3) - ) && - range->start_key.length == range->end_key.length && - !memcmp(seq->param->min_key,seq->param->max_key,range->start_key.length)) - range->range_flag= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE); + const uint is_open_range = + (NO_MIN_RANGE | NO_MAX_RANGE | NEAR_MIN | NEAR_MAX | GEOM_FLAG); + const bool is_eq_range_pred = + !(cur->min_key_flag & is_open_range) && // (1) + !(cur->max_key_flag & is_open_range) && // (1) + range->start_key.length == range->end_key.length && // (2) + !memcmp(seq->param->min_key, seq->param->max_key, // (2) + range->start_key.length); + + if (is_eq_range_pred) + { + range->range_flag = EQ_RANGE; + + /* + Conditions below: + (1) - Range analysis is used for estimating condition selectivity + (2) - This is a unique key, and we have conditions for all its + user-defined key parts. + (3) - The table uses extended keys, this key covers all components, + and we have conditions for all key parts. + */ + if ( + !key_info || // (1) + ((uint)key_tree->part+1 == key_info->user_defined_key_parts && // (2) + key_info->flags & HA_NOSAME) || // (2) + ((key_info->flags & HA_EXT_NOSAME) && // (3) + (uint)key_tree->part+1 == key_info->ext_key_parts) // (3) + ) + range->range_flag |= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE); + } if (seq->param->is_ror_scan) { diff --git a/sql/protocol.cc b/sql/protocol.cc index 29004fe24e4..7eee9283989 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -711,7 +711,7 @@ uchar *net_store_data(uchar *to, const uchar *from, size_t length) uchar *net_store_data(uchar *to,int32 from) { - char buff[20]; + char buff[22]; uint length=(uint) (int10_to_str(from,buff,10)-buff); to=net_store_length_fast(to,length); memcpy(to,buff,length); @@ -1137,7 +1137,7 @@ bool Protocol_text::store_tiny(longlong from) DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY); field_pos++; #endif - char buff[20]; + char buff[22]; return net_store_data((uchar*) buff, (size_t) (int10_to_str((int) from, buff, -10) - buff)); } @@ -1151,7 +1151,7 @@ bool Protocol_text::store_short(longlong from) field_types[field_pos] == MYSQL_TYPE_SHORT); field_pos++; #endif - char buff[20]; + char buff[22]; return net_store_data((uchar*) buff, (size_t) (int10_to_str((int) from, buff, -10) - buff)); @@ -1166,7 +1166,7 @@ bool Protocol_text::store_long(longlong from) field_types[field_pos] == MYSQL_TYPE_LONG); field_pos++; #endif - char buff[20]; + char buff[22]; return net_store_data((uchar*) buff, (size_t) (int10_to_str((long int)from, buff, (from <0)?-10:10)-buff)); diff --git a/sql/sql_class.h b/sql/sql_class.h index 64ce52049d0..30622fde577 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -581,6 +581,7 @@ typedef struct system_variables ha_rows max_join_size; ha_rows expensive_subquery_limit; ulong auto_increment_increment, auto_increment_offset; + uint eq_range_index_dive_limit; ulong column_compression_zlib_strategy; ulong lock_wait_timeout; ulong join_cache_level; @@ -5023,7 +5024,8 @@ protected: SELECT_LEX_UNIT *unit; /* Something used only by the parser: */ public: - select_result(THD *thd_arg): select_result_sink(thd_arg) {} + ha_rows est_records; /* estimated number of records in the result */ + select_result(THD *thd_arg): select_result_sink(thd_arg), est_records(0) {} void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; } virtual ~select_result() {}; /** @@ -5595,7 +5597,6 @@ public: TMP_TABLE_PARAM tmp_table_param; int write_err; /* Error code from the last send_data->ha_write_row call. */ TABLE *table; - ha_rows records; select_unit(THD *thd_arg): select_result_interceptor(thd_arg), @@ -5633,7 +5634,6 @@ public: curr_sel= UINT_MAX; step= UNION_TYPE; write_err= 0; - records= 0; } void change_select(); }; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 80ee4a22419..326f2a64bbe 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -323,12 +323,16 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, DBUG_ASSERT(table); DBUG_ASSERT(!conds || thd->stmt_arena->is_stmt_execute()); - if (select_lex->vers_setup_conds(thd, table_list)) - DBUG_RETURN(TRUE); - DBUG_ASSERT(!conds); - conds= table_list->on_expr; - table_list->on_expr= NULL; + // conds could be cached from previous SP call + if (!conds) + { + if (select_lex->vers_setup_conds(thd, table_list)) + DBUG_RETURN(TRUE); + + conds= table_list->on_expr; + table_list->on_expr= NULL; + } } if (mysql_handle_list_of_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT)) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 20b1eb413cf..bff6dfb0e05 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -4765,18 +4765,18 @@ void SELECT_LEX::increase_derived_records(ha_rows records) return; } - select_unit *result= (select_unit*)unit->result; + select_result *result= unit->result; switch (linkage) { case INTERSECT_TYPE: // result of intersect can't be more then one of components - set_if_smaller(result->records, records); + set_if_smaller(result->est_records, records); case EXCEPT_TYPE: // in worse case none of record will be removed break; default: // usual UNION - result->records+= records; + result->est_records+= records; break; } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 147147f0191..201cb4f1dbe 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2565,6 +2565,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, case SCH_TABLE_NAMES: case SCH_TABLES: + case SCH_CHECK_CONSTRAINTS: case SCH_VIEWS: case SCH_TRIGGERS: case SCH_EVENTS: diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7a8631a4ac1..3b927510c80 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1701,8 +1701,7 @@ JOIN::optimize_inner() DBUG_RETURN(1); } - if (thd->lex->sql_command == SQLCOM_SELECT && - optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY)) + if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY)) { TABLE_LIST *tbl; List_iterator_fast li(select_lex->leaf_tables); @@ -1727,8 +1726,7 @@ JOIN::optimize_inner() DBUG_RETURN(TRUE); } - if (thd->lex->sql_command == SQLCOM_SELECT && - optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED)) + if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED)) { TABLE_LIST *tbl; List_iterator_fast li(select_lex->leaf_tables); @@ -1925,6 +1923,14 @@ JOIN::optimize_inner() error= 1; DBUG_RETURN(1); } + if (!group_list) + { + /* The output has only one row */ + order=0; + simple_order=1; + group_optimized_away= 1; + select_distinct=0; + } } /* Calculate how to do the join */ @@ -3811,7 +3817,7 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite, If there is SELECT in this statement with the same number it must be the same SELECT */ - DBUG_ASSERT(select_lex->select_number == UINT_MAX || + DBUG_SLOW_ASSERT(select_lex->select_number == UINT_MAX || select_lex->select_number == INT_MAX || !output || !output->get_select(select_lex->select_number) || @@ -6577,7 +6583,7 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab) Item_field *cur_item; key_map possible_keys(0); - if (join->group_list || join->simple_group) + if (join->group_list) { /* Collect all query fields referenced in the GROUP clause. */ for (cur_group= join->group_list; cur_group; cur_group= cur_group->next) (*cur_group->item)->walk(&Item::collect_item_field_processor, 0, diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index baaa4571c9e..1ed0bb38e64 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -542,7 +542,8 @@ void sequence_definition::adjust_values(longlong next_value) if ((real_increment= global_system_variables.auto_increment_increment) != 1) - offset= global_system_variables.auto_increment_offset; + offset= (global_system_variables.auto_increment_offset % + global_system_variables.auto_increment_increment); /* Ensure that next_free_value has the right offset, so that we @@ -564,7 +565,7 @@ void sequence_definition::adjust_values(longlong next_value) else { next_free_value+= to_add; - DBUG_ASSERT(next_free_value % real_increment == offset); + DBUG_ASSERT(llabs(next_free_value % real_increment) == offset); } } } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e8f42003691..ea6ef7d86fb 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2616,7 +2616,7 @@ static int show_create_view(THD *thd, TABLE_LIST *table, String *buff) We can't just use table->query, because our SQL_MODE may trigger a different syntax, like when ANSI_QUOTES is defined. */ - table->view->unit.print(buff, enum_query_type(QT_ORDINARY | + table->view->unit.print(buff, enum_query_type(QT_VIEW_INTERNAL | QT_ITEM_ORIGINAL_FUNC_NULLIF)); if (table->with_check != VIEW_CHECK_NONE) @@ -6795,6 +6795,42 @@ store_constraints(THD *thd, TABLE *table, const LEX_CSTRING *db_name, return schema_table_store_record(thd, table); } +static int get_check_constraints_record(THD *thd, TABLE_LIST *tables, + TABLE *table, bool res, + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) +{ + DBUG_ENTER("get_check_constraints_record"); + if (res) + { + if (thd->is_error()) + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, + thd->get_stmt_da()->sql_errno(), + thd->get_stmt_da()->message()); + thd->clear_error(); + DBUG_RETURN(0); + } + else if (!tables->view) + { + if (tables->table->s->table_check_constraints) + { + for (uint i= 0; i < tables->table->s->table_check_constraints; i++) + { + StringBuffer str(system_charset_info); + Virtual_column_info *check= tables->table->check_constraints[i]; + restore_record(table, s->default_values); + table->field[0]->store(STRING_WITH_LEN("def"), system_charset_info); + table->field[1]->store(db_name->str, db_name->length, system_charset_info); + table->field[2]->store(check->name.str, check->name.length, system_charset_info); + table->field[3]->store(table_name->str, table_name->length, system_charset_info); + check->print(&str); + table->field[4]->store(str.ptr(), str.length(), system_charset_info); + schema_table_store_record(thd, table); + } + } + } + DBUG_RETURN(res); +} static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, @@ -9715,6 +9751,18 @@ ST_FIELD_INFO spatial_ref_sys_fields_info[]= #endif /*HAVE_SPATIAL*/ +ST_FIELD_INFO check_constraints_fields_info[]= +{ + {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, + {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, + OPEN_FULL_TABLE}, + {"CONSTRAINT_NAME", 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}, + {"CHECK_CLAUSE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, + OPEN_FULL_TABLE}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} +}; /* Description of ST_FIELD_INFO in table.h @@ -9730,6 +9778,8 @@ ST_SCHEMA_TABLE schema_tables[]= fill_schema_applicable_roles, 0, 0, -1, -1, 0, 0}, {"CHARACTER_SETS", charsets_fields_info, 0, fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0, 0}, + {"CHECK_CONSTRAINTS", check_constraints_fields_info, 0, + get_all_tables, 0, get_check_constraints_record, 1, 2, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY}, {"COLLATIONS", collation_fields_info, 0, fill_schema_collation, make_old_format, 0, -1, -1, 0, 0}, {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info, diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h index c2700eaee41..714a9075f92 100644 --- a/sql/sql_statistics.h +++ b/sql/sql_statistics.h @@ -21,7 +21,7 @@ enum enum_use_stat_tables_mode { NEVER, COMPLEMENTARY, - PEFERABLY, + PREFERABLY, } Use_stat_tables_mode; typedef diff --git a/sql/sql_time.cc b/sql/sql_time.cc index 430eb192052..c1300c78ad9 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -264,7 +264,7 @@ bool get_date_from_daynr(long daynr,uint *ret_year,uint *ret_month, ulong convert_period_to_month(ulong period) { ulong a,b; - if (period == 0) + if (period == 0 || period > 999912) return 0L; if ((a=period/100) < YY_PART_YEAR) a+=2000; diff --git a/sql/sql_tvc.h b/sql/sql_tvc.h index 420311cccb2..128cc883dd8 100644 --- a/sql/sql_tvc.h +++ b/sql/sql_tvc.h @@ -50,6 +50,8 @@ public: have_query_plan(QEP_NOT_PRESENT_YET), explain(0), select_options(select_options_arg) { }; + + ha_rows get_records() { return lists_of_values.elements; } bool prepare(THD *thd_arg, SELECT_LEX *sl, select_result *tmp_result, diff --git a/sql/sql_union.cc b/sql/sql_union.cc index be987b82cba..29ea427842f 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1321,6 +1321,8 @@ bool st_select_lex_unit::optimize() thd->lex->current_select= lex_select_save; DBUG_RETURN(TRUE); } + if (derived) + sl->increase_derived_records(sl->tvc->get_records()); continue; } thd->lex->current_select= sl; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cf894325ba5..cc22908ec4b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1996,6 +1996,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); preload_list preload_list_or_parts preload_keys preload_keys_parts select_item_list select_item values_list no_braces delete_limit_clause fields opt_values values + no_braces_with_names opt_values_with_names values_with_names procedure_list procedure_list2 procedure_item field_def handler opt_generated_always opt_ignore opt_column opt_restrict @@ -13156,7 +13157,7 @@ insert_values: values_list: values_list ',' no_braces - | no_braces + | no_braces_with_names ; ident_eq_list: @@ -13209,11 +13210,31 @@ no_braces: } ; +no_braces_with_names: + '(' + { + if (unlikely(!(Lex->insert_list= new (thd->mem_root) List_item))) + MYSQL_YYABORT; + } + opt_values_with_names ')' + { + LEX *lex=Lex; + if (unlikely(lex->many_values.push_back(lex->insert_list, + thd->mem_root))) + MYSQL_YYABORT; + } + ; + opt_values: /* empty */ {} | values ; +opt_values_with_names: + /* empty */ {} + | values_with_names + ; + values: values ',' expr_or_default { @@ -13227,6 +13248,25 @@ values: } ; +values_with_names: + values_with_names ',' remember_name expr_or_default remember_end + { + if (unlikely(Lex->insert_list->push_back($4, thd->mem_root))) + MYSQL_YYABORT; + // give some name in case of using in table value constuctor (TVC) + if (!$4->name.str || $4->name.str == item_empty_name) + $4->set_name(thd, $3, (uint) ($5 - $3), thd->charset()); + } + | remember_name expr_or_default remember_end + { + if (unlikely(Lex->insert_list->push_back($2, thd->mem_root))) + MYSQL_YYABORT; + // give some name in case of using in table value constuctor (TVC) + if (!$2->name.str || $2->name.str == item_empty_name) + $2->set_name(thd, $1, (uint) ($3 - $1), thd->charset()); + } + ; + expr_or_default: expr { $$= $1;} | DEFAULT diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index ef12b9c0c53..d4838590075 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -1487,6 +1487,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); assign_to_keycache_parts preload_list preload_list_or_parts preload_keys preload_keys_parts select_item_list select_item values_list no_braces + no_braces_with_names opt_values_with_names values_with_names delete_limit_clause fields opt_values values procedure_list procedure_list2 procedure_item field_def handler opt_generated_always @@ -13384,7 +13385,7 @@ insert_values: values_list: values_list ',' no_braces - | no_braces + | no_braces_with_names ; ident_eq_list: @@ -13437,11 +13438,31 @@ no_braces: } ; +no_braces_with_names: + '(' + { + if (unlikely(!(Lex->insert_list= new (thd->mem_root) List_item))) + MYSQL_YYABORT; + } + opt_values_with_names ')' + { + LEX *lex=Lex; + if (unlikely(lex->many_values.push_back(lex->insert_list, + thd->mem_root))) + MYSQL_YYABORT; + } + ; + opt_values: /* empty */ {} | values ; +opt_values_with_names: + /* empty */ {} + | values_with_names + ; + values: values ',' expr_or_default { @@ -13455,6 +13476,25 @@ values: } ; +values_with_names: + values_with_names ',' remember_name expr_or_default remember_end + { + if (unlikely(Lex->insert_list->push_back($4, thd->mem_root))) + MYSQL_YYABORT; + // give some name in case of using in table value constuctor (TVC) + if (!$4->name.str || $4->name.str == item_empty_name) + $4->set_name(thd, $3, (uint) ($5 - $3), thd->charset()); + } + | remember_name expr_or_default remember_end + { + if (unlikely(Lex->insert_list->push_back($2, thd->mem_root))) + MYSQL_YYABORT; + // give some name in case of using in table value constuctor (TVC) + if (!$2->name.str || $2->name.str == item_empty_name) + $2->set_name(thd, $1, (uint) ($3 - $1), thd->charset()); + } + ; + expr_or_default: expr { $$= $1;} | DEFAULT diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 37ae2fbb68a..6d2dbbf646e 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2672,6 +2672,16 @@ static Sys_var_ulong Sys_div_precincrement( SESSION_VAR(div_precincrement), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, DECIMAL_MAX_SCALE), DEFAULT(4), BLOCK_SIZE(1)); +static Sys_var_uint Sys_eq_range_index_dive_limit( + "eq_range_index_dive_limit", + "The optimizer will use existing index statistics instead of " + "doing index dives for equality ranges if the number of equality " + "ranges for the index is larger than or equal to this number. " + "If set to 0, index dives are always used.", + SESSION_VAR(eq_range_index_dive_limit), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, UINT_MAX32), DEFAULT(0), + BLOCK_SIZE(1)); + static Sys_var_ulong Sys_range_alloc_block_size( "range_alloc_block_size", "Allocation block size for storing ranges during optimization", diff --git a/sql/table.cc b/sql/table.cc index b0468be17f2..de5a71f6af1 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6885,7 +6885,10 @@ void TABLE::mark_columns_used_by_virtual_fields(void) for (uint i= 0 ; i < s->fields ; i++) { if (bitmap_is_set(&tmp_set, i)) + { + s->field[i]->flags|= PART_INDIRECT_KEY_FLAG; field[i]->flags|= PART_INDIRECT_KEY_FLAG; + } } bitmap_clear_all(&tmp_set); } @@ -8335,7 +8338,7 @@ int TABLE_LIST::fetch_number_of_rows() } if (is_materialized_derived() && !fill_me) { - table->file->stats.records= ((select_unit*)(get_unit()->result))->records; + table->file->stats.records= get_unit()->result->est_records; set_if_bigger(table->file->stats.records, 2); table->used_stat_records= table->file->stats.records; } diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 699a4daf27a..6aa8a68f222 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -159,6 +159,7 @@ extern "C" time_t wsrep_thd_query_start(THD *thd); extern "C" query_id_t wsrep_thd_query_id(THD *thd); extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); +extern "C" void wsrep_set_data_home_dir(const char *data_dir); extern void wsrep_close_client_connections(my_bool wait_to_end); extern int wsrep_wait_committing_connections_close(int wait_time); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 8816a31330e..0a1d95f30b8 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -58,6 +58,13 @@ bool wsrep_sst_method_update (sys_var *self, THD* thd, enum_var_type type) return 0; } +static const char* data_home_dir = NULL; + +extern "C" +void wsrep_set_data_home_dir(const char *data_dir) +{ + data_home_dir= (data_dir && *data_dir) ? data_dir : NULL; +} static void make_wsrep_defaults_file() { @@ -595,6 +602,29 @@ static int sst_append_auth_env(wsp::env& env, const char* sst_auth) return -env.error(); } +#define DATA_HOME_DIR_ENV "INNODB_DATA_HOME_DIR" + +static int sst_append_data_dir(wsp::env& env, const char* data_dir) +{ + int const data_dir_size= strlen(DATA_HOME_DIR_ENV) + 1 /* = */ + + (data_dir ? strlen(data_dir) : 0) + 1 /* \0 */; + + wsp::string data_dir_str(data_dir_size); // for automatic cleanup on return + if (!data_dir_str()) return -ENOMEM; + + int ret= snprintf(data_dir_str(), data_dir_size, "%s=%s", + DATA_HOME_DIR_ENV, data_dir ? data_dir : ""); + + if (ret < 0 || ret >= data_dir_size) + { + WSREP_ERROR("sst_append_data_dir(): snprintf() failed: %d", ret); + return (ret < 0 ? ret : -EMSGSIZE); + } + + env.append(data_dir_str()); + return -env.error(); +} + static ssize_t sst_prepare_other (const char* method, const char* sst_auth, const char* addr_in, @@ -656,6 +686,16 @@ static ssize_t sst_prepare_other (const char* method, return ret; } + if (data_home_dir) + { + if ((ret= sst_append_data_dir(env, data_home_dir))) + { + WSREP_ERROR("sst_prepare_other(): appending data " + "directory failed: %d", ret); + return ret; + } + } + pthread_t tmp; sst_thread_arg arg(cmd_str(), env()); mysql_mutex_lock (&arg.lock); @@ -1347,6 +1387,16 @@ wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, return WSREP_CB_FAILURE; } + if (data_home_dir) + { + if ((ret= sst_append_data_dir(env, data_home_dir))) + { + WSREP_ERROR("wsrep_sst_donate_cb(): appending data " + "directory failed: %d", ret); + return WSREP_CB_FAILURE; + } + } + if (!strcmp (WSREP_SST_MYSQLDUMP, method)) { ret = sst_donate_mysqldump(data, ¤t_gtid->uuid, uuid_str, diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 7fe120beb8e..bc43b844a35 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -594,7 +594,9 @@ void wsrep_node_address_init (const char* value) static void wsrep_slave_count_change_update () { - wsrep_slave_count_change += (wsrep_slave_threads - wsrep_prev_slave_threads); + wsrep_slave_count_change = (wsrep_slave_threads - wsrep_prev_slave_threads); + WSREP_DEBUG("Change on slave threads: New %lu old %lu difference %lu", + wsrep_slave_threads, wsrep_prev_slave_threads, wsrep_slave_count_change); wsrep_prev_slave_threads = wsrep_slave_threads; } @@ -617,6 +619,12 @@ bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var) return true; } + if (thd->global_read_lock.is_acquired()) + { + my_message (ER_CANNOT_USER, "Global read lock acquired. Can't set 'wsrep_desync'", MYF(0)); + return true; + } + bool new_wsrep_desync= (bool) var->save_result.ulonglong_value; if (wsrep_desync == new_wsrep_desync) { if (new_wsrep_desync) { diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index db9e028b8f3..1041ad8614a 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -1279,8 +1279,6 @@ void btr_search_drop_page_hash_when_freed(const page_id_t& page_id) mtr_t mtr; dberr_t err = DB_SUCCESS; - ut_d(export_vars.innodb_ahi_drop_lookups++); - mtr_start(&mtr); /* If the caller has a latch on the page, then the caller must diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index 7ede67fd0e4..088741e8ce8 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, 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 @@ -391,7 +391,7 @@ buf_dump( /* leave tmp_filename to exist */ return; } - if ( (j % 1024) == 0) { + if (SHUTTING_DOWN() && !(j % 1024)) { service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, "Dumping buffer pool " ULINTPF "/" ULINTPF ", " diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 51190ff2ef6..3fba1679cdf 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -6110,7 +6110,7 @@ dict_table_get_index_on_name( while (index != NULL) { if (index->is_committed() == committed - && innobase_strcasecmp(index->name, name) == 0) { + && strcmp(index->name, name) == 0) { return(index); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 0bdb3834f6f..5e80a8a0e08 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -169,8 +169,6 @@ static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid); static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid); #endif /* WITH_WSREP */ -/** to protect innobase_open_files */ -static mysql_mutex_t innobase_share_mutex; /** to force correct commit order in binlog */ static ulong commit_threads = 0; static mysql_cond_t commit_cond; @@ -461,8 +459,6 @@ operation, we only do it every INNOBASE_WAKE_INTERVAL'th step. */ #define INNOBASE_WAKE_INTERVAL 32 static ulong innobase_active_counter = 0; -static hash_table_t* innobase_open_tables; - /** Allowed values of innodb_change_buffering */ static const char* innodb_change_buffering_names[] = { "none", /* IBUF_USE_NONE */ @@ -571,7 +567,6 @@ const struct _ft_vft_ext ft_vft_ext_result = {innobase_fts_get_version, /* Keys to register pthread mutexes/cond in the current file with performance schema */ -static mysql_pfs_key_t innobase_share_mutex_key; static mysql_pfs_key_t commit_cond_mutex_key; static mysql_pfs_key_t commit_cond_key; static mysql_pfs_key_t pending_checkpoint_mutex_key; @@ -580,7 +575,6 @@ static mysql_pfs_key_t thd_destructor_thread_key; static PSI_mutex_info all_pthread_mutexes[] = { PSI_KEY(commit_cond_mutex), PSI_KEY(pending_checkpoint_mutex), - PSI_KEY(innobase_share_mutex) }; static PSI_cond_info all_innodb_conds[] = { @@ -1072,10 +1066,6 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_truncated_status_writes, SHOW_LONG}, {"available_undo_logs", (char*) &export_vars.innodb_available_undo_logs, SHOW_LONG}, -#ifdef UNIV_DEBUG - {"ahi_drop_lookups", - (char*) &export_vars.innodb_ahi_drop_lookups, SHOW_LONG}, -#endif /* UNIV_DEBUG */ /* Status variables for page compression */ {"page_compression_saved", @@ -1195,23 +1185,6 @@ static SHOW_VAR innodb_status_variables[]= { {NullS, NullS, SHOW_LONG} }; -/************************************************************************//** -Handling the shared INNOBASE_SHARE structure that is needed to provide table -locking. Register the table name if it doesn't exist in the hash table. */ -static -INNOBASE_SHARE* -get_share( -/*======*/ - const char* table_name); /*!< in: table to lookup */ - -/************************************************************************//** -Free the shared object that was registered with get_share(). */ -static -void -free_share( -/*=======*/ - INNOBASE_SHARE* share); /*!< in/own: share to free */ - /*****************************************************************//** Frees a possible InnoDB trx object associated with the current THD. @return 0 or error number */ @@ -3848,6 +3821,12 @@ static int innodb_init_params() srv_data_home = innobase_data_home_dir ? innobase_data_home_dir : default_path; +#ifdef WITH_WSREP + /* If we use the wsrep API, then we need to tell the server + the path to the data files (for passing it to the SST scripts): */ + wsrep_set_data_home_dir(srv_data_home); +#endif /* WITH_WSREP */ + /*--------------- Shared tablespaces -------------------------*/ @@ -4289,10 +4268,6 @@ static int innodb_init(void* p) ibuf_max_size_update(srv_change_buffer_max_size); - innobase_open_tables = hash_create(200); - mysql_mutex_init(innobase_share_mutex_key, - &innobase_share_mutex, - MY_MUTEX_INIT_FAST); mysql_mutex_init(commit_cond_mutex_key, &commit_cond_m, MY_MUTEX_INIT_FAST); mysql_cond_init(commit_cond_key, &commit_cond, 0); @@ -4361,9 +4336,6 @@ innobase_end(handlerton*, ha_panic_function) } } - hash_table_free(innobase_open_tables); - innobase_open_tables = NULL; - st_my_thread_var* running = reinterpret_cast( my_atomic_loadptr_explicit( reinterpret_cast(&srv_running), @@ -4381,7 +4353,6 @@ innobase_end(handlerton*, ha_panic_function) innodb_shutdown(); innobase_space_shutdown(); - mysql_mutex_destroy(&innobase_share_mutex); mysql_mutex_destroy(&commit_cond_m); mysql_cond_destroy(&commit_cond); mysql_mutex_destroy(&pending_checkpoint_mutex); @@ -5617,6 +5588,7 @@ is consistent between KEY info from mysql and that from innodb index. @param[in] key_info Index info from mysql @param[in] index_info Index info from InnoDB @return true if all column types match. */ +static bool innobase_match_index_columns( const KEY* key_info, @@ -5906,90 +5878,33 @@ innobase_build_v_templ( s_templ->tb_name = table->s->table_name.str; } -/*******************************************************************//** -This function builds a translation table in INNOBASE_SHARE -structure for fast index location with mysql array number from its -table->key_info structure. This also provides the necessary translation -between the key order in mysql key_info and InnoDB ib_table->indexes if -they are not fully matched with each other. -Note we do not have any mutex protecting the translation table -building based on the assumption that there is no concurrent -index creation/drop and DMLs that requires index lookup. All table -handle will be closed before the index creation/drop. -@return true if index translation table built successfully */ -static -bool -innobase_build_index_translation( -/*=============================*/ - const TABLE* table, /*!< in: table in MySQL data - dictionary */ - dict_table_t* ib_table,/*!< in: table in InnoDB data - dictionary */ - INNOBASE_SHARE* share) /*!< in/out: share structure - where index translation table - will be constructed in. */ +/** Check consistency between .frm indexes and InnoDB indexes. +@param[in] table table object formed from .frm +@param[in] ib_table InnoDB table definition +@retval true if not errors were found */ +static bool +check_index_consistency(const TABLE* table, const dict_table_t* ib_table) { - DBUG_ENTER("innobase_build_index_translation"); - - bool ret = true; - - mutex_enter(&dict_sys->mutex); - - ulint mysql_num_index = table->s->keys; - ulint ib_num_index = UT_LIST_GET_LEN(ib_table->indexes); - dict_index_t** index_mapping = share->idx_trans_tbl.index_mapping; + ulint mysql_num_index = table->s->keys; + ulint ib_num_index = UT_LIST_GET_LEN(ib_table->indexes); + bool ret = true; /* If there exists inconsistency between MySQL and InnoDB dictionary (metadata) information, the number of index defined in MySQL - could exceed that in InnoDB, do not build index translation - table in such case */ + could exceed that in InnoDB, return error */ if (ib_num_index < mysql_num_index) { ret = false; goto func_exit; } - /* If index entry count is non-zero, nothing has - changed since last update, directly return TRUE */ - if (share->idx_trans_tbl.index_count) { - /* Index entry count should still match mysql_num_index */ - ut_a(share->idx_trans_tbl.index_count == mysql_num_index); - goto func_exit; - } - - /* The number of index increased, rebuild the mapping table */ - if (mysql_num_index > share->idx_trans_tbl.array_size) { - - index_mapping = reinterpret_cast( - ut_realloc(index_mapping, - mysql_num_index * sizeof(*index_mapping))); - - if (index_mapping == NULL) { - /* Report an error if index_mapping continues to be - NULL and mysql_num_index is a non-zero value */ - sql_print_error("InnoDB: fail to allocate memory for " - "index translation table. Number of " - "Index: " ULINTPF - ", array size:" ULINTPF, - mysql_num_index, - share->idx_trans_tbl.array_size); - ret = false; - goto func_exit; - } - - share->idx_trans_tbl.array_size = mysql_num_index; - } - /* For each index in the mysql key_info array, fetch its corresponding InnoDB index pointer into index_mapping array. */ for (ulint count = 0; count < mysql_num_index; count++) { - - /* Fetch index pointers into index_mapping according to mysql - index sequence */ - index_mapping[count] = dict_table_get_index_on_name( + const dict_index_t* index = dict_table_get_index_on_name( ib_table, table->key_info[count].name.str); - if (index_mapping[count] == 0) { + if (index == NULL) { sql_print_error("Cannot find index %s in InnoDB" " index dictionary.", table->key_info[count].name.str); @@ -6000,7 +5915,7 @@ innobase_build_index_translation( /* Double check fetched index has the same column info as those in mysql key_info. */ if (!innobase_match_index_columns(&table->key_info[count], - index_mapping[count])) { + index)) { sql_print_error("Found index %s whose column info" " does not match that of MariaDB.", table->key_info[count].name.str); @@ -6009,51 +5924,10 @@ innobase_build_index_translation( } } - /* Successfully built the translation table */ - share->idx_trans_tbl.index_count = mysql_num_index; - func_exit: - if (!ret) { - /* Build translation table failed. */ - ut_free(index_mapping); - - share->idx_trans_tbl.array_size = 0; - share->idx_trans_tbl.index_count = 0; - index_mapping = NULL; - } - - share->idx_trans_tbl.index_mapping = index_mapping; - - mutex_exit(&dict_sys->mutex); - - DBUG_RETURN(ret); + return ret; } -/*******************************************************************//** -This function uses index translation table to quickly locate the -requested index structure. -Note we do not have mutex protection for the index translatoin table -access, it is based on the assumption that there is no concurrent -translation table rebuild (fter create/drop index) and DMLs that -require index lookup. -@return dict_index_t structure for requested index. NULL if -fail to locate the index structure. */ -static -dict_index_t* -innobase_index_lookup( -/*==================*/ - INNOBASE_SHARE* share, /*!< in: share structure for index - translation table. */ - uint keynr) /*!< in: index number for the requested - index */ -{ - if (share->idx_trans_tbl.index_mapping == NULL - || keynr >= share->idx_trans_tbl.index_count) { - return(NULL); - } - - return(share->idx_trans_tbl.index_mapping[keynr]); -} /********************************************************************//** Get the upper limit of the MySQL integral and floating-point type. @return maximum allowed value for the field */ @@ -6183,11 +6057,6 @@ ha_innobase::open(const char* name, int, uint) m_user_thd = NULL; - if (!(m_share = get_share(name))) { - - DBUG_RETURN(1); - } - /* Will be allocated if it is needed in ::update_row() */ m_upd_buf = NULL; m_upd_buf_size = 0; @@ -6211,7 +6080,6 @@ ha_innobase::open(const char* name, int, uint) norm_name); } no_such_table: - free_share(m_share); set_my_errno(ENOENT); DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); @@ -6269,7 +6137,6 @@ no_such_table: } if (!thd_tablespace_op(thd)) { - free_share(m_share); set_my_errno(ENOENT); int ret_err = HA_ERR_NO_SUCH_TABLE; @@ -6326,9 +6193,10 @@ no_such_table: mutex_exit(&dict_sys->mutex); } - if (!innobase_build_index_translation(table, ib_table, m_share)) { - sql_print_error("Build InnoDB index translation table for" - " Table %s failed", name); + if (!check_index_consistency(table, ib_table)) { + sql_print_error("InnoDB indexes are inconsistent with what " + "defined in .frm for table %s", + name); } /* Allocate a buffer for a 'row reference'. A row reference is @@ -6424,9 +6292,6 @@ no_such_table: /* Index block size in InnoDB: used by MySQL in query optimization */ stats.block_size = srv_page_size; - /* Init table lock structure */ - thr_lock_data_init(&m_share->lock, &lock, NULL); - if (m_prebuilt->table == NULL || m_prebuilt->table->is_temporary() || m_prebuilt->table->persistent_autoinc @@ -6619,8 +6484,6 @@ ha_innobase::close() m_upd_buf_size = 0; } - free_share(m_share); - MONITOR_INC(MONITOR_TABLE_CLOSE); /* Tell InnoDB server that there might be work for @@ -8184,7 +8047,8 @@ ha_innobase::write_row( /* We need the upper limit of the col type to check for whether we update the table autoinc counter or not. */ - col_max_value = innobase_get_int_col_max_value(table->next_number_field); + col_max_value = innobase_get_int_col_max_value( + table->next_number_field); /* Get the value that MySQL attempted to store in the table.*/ auto_inc = table->next_number_field->val_uint(); @@ -9487,60 +9351,18 @@ ha_innobase::innobase_get_index( clustered index, even if it was internally generated by InnoDB */ { - KEY* key; + KEY* key = NULL; + dict_table_t* ib_table = m_prebuilt->table; dict_index_t* index; DBUG_ENTER("innobase_get_index"); if (keynr != MAX_KEY && table->s->keys > 0) { - - key = table->key_info + keynr; - - index = innobase_index_lookup(m_share, keynr); - - if (index != NULL) { - if (!key || ut_strcmp(index->name, key->name.str) != 0) { - ib::error() << " Index for key no " << keynr - << " mysql name " << (key ? key->name.str : "NULL") - << " InnoDB name " << index->name() - << " for table " << m_prebuilt->table->name.m_name; - - for(uint i=0; i < table->s->keys; i++) { - index = innobase_index_lookup(m_share, i); - key = table->key_info + keynr; - - if (index) { - ib::info() << " Index for key no " << keynr - << " mysql name " << (key ? key->name.str : "NULL") - << " InnoDB name " << index->name() - << " for table " << m_prebuilt->table->name.m_name; - } - } - - } - - ut_a(ut_strcmp(index->name, key->name.str) == 0); - } else { - /* Can't find index with keynr in the translation - table. Only print message if the index translation - table exists */ - if (m_share->idx_trans_tbl.index_mapping != NULL) { - sql_print_warning("InnoDB could not find" - " index %s key no %u for" - " table %s through its" - " index translation table", - key ? key->name.str : "NULL", - keynr, - m_prebuilt->table->name - .m_name); - } - - index = dict_table_get_index_on_name( - m_prebuilt->table, key->name.str); - } + key = &table->key_info[keynr]; + index = dict_table_get_index_on_name(ib_table, key->name.str); + ut_ad(index); } else { - key = 0; - index = dict_table_get_first_index(m_prebuilt->table); + index = dict_table_get_first_index(ib_table); } if (index == NULL) { @@ -9548,7 +9370,7 @@ ha_innobase::innobase_get_index( "InnoDB could not find key no %u with name %s" " from dict cache for table %s", keynr, key ? key->name.str : "NULL", - m_prebuilt->table->name.m_name); + ib_table->name.m_name); } DBUG_RETURN(index); @@ -13699,20 +13521,12 @@ innodb_set_buf_pool_size(ulonglong buf_pool_size) } /*********************************************************************//** -Calculates the key number used inside MySQL for an Innobase index. We will -first check the "index translation table" for a match of the index to get -the index number. If there does not exist an "index translation table", -or not able to find the index in the translation table, then we will fall back -to the traditional way of looping through dict_index_t list to find a -match. In this case, we have to take into account if we generated a -default clustered index for the table +Calculates the key number used inside MySQL for an Innobase index. @return the key number used inside MySQL */ static unsigned innobase_get_mysql_key_number_for_index( /*====================================*/ - INNOBASE_SHARE* share, /*!< in: share structure for index - translation table. */ const TABLE* table, /*!< in: table in MySQL data dictionary */ dict_table_t* ib_table,/*!< in: table in InnoDB data @@ -13742,27 +13556,8 @@ innobase_get_mysql_key_number_for_index( return(i); } - /* If index translation table exists, we will first check - the index through index translation table for a match. */ - if (share->idx_trans_tbl.index_mapping != NULL) { - for (i = 0; i < share->idx_trans_tbl.index_count; i++) { - if (share->idx_trans_tbl.index_mapping[i] == index) { - return(i); - } - } - - /* Print an error message if we cannot find the index - in the "index translation table". */ - if (index->is_committed()) { - sql_print_error("Cannot find index %s in InnoDB index" - " translation table.", index->name()); - } - } - - /* If we do not have an "index translation table", or not able - to find the index in the translation table, we'll directly find - matching index with information from mysql TABLE structure and - InnoDB dict_index_t list */ + /* Directly find matching index with information from mysql TABLE + structure and InnoDB dict_index_t list */ for (i = 0; i < table->s->keys; i++) { ind = dict_table_get_index_on_name( ib_table, table->key_info[i].name.str); @@ -14119,11 +13914,6 @@ ha_innobase::info_low( for (i = 0; i < table->s->keys; i++) { ulong j; - /* We could get index quickly through internal - index mapping with the index translation table. - The identity of index (match up index name with - that of table->key_info[i]) is already verified in - innobase_get_index(). */ dict_index_t* index = innobase_get_index(i); if (index == NULL) { @@ -14231,7 +14021,7 @@ ha_innobase::info_low( if (err_index) { errkey = innobase_get_mysql_key_number_for_index( - m_share, table, ib_table, err_index); + table, ib_table, err_index); } else { errkey = (unsigned int) ( (m_prebuilt->trx->error_key_num @@ -16061,7 +15851,7 @@ static int innodb_show_mutex_status( handlerton* -#ifndef DBUG_OFF +#ifdef DBUG_ASSERT_EXISTS hton #endif , @@ -16092,7 +15882,7 @@ static int innodb_show_rwlock_status( handlerton* -#ifndef DBUG_OFF +#ifdef DBUG_ASSERT_EXISTS hton #endif , @@ -16236,104 +16026,6 @@ innobase_show_status( /* Success */ return(false); } - -/************************************************************************//** -Handling the shared INNOBASE_SHARE structure that is needed to provide table -locking. Register the table name if it doesn't exist in the hash table. */ -static -INNOBASE_SHARE* -get_share( -/*======*/ - const char* table_name) -{ - INNOBASE_SHARE* share; - - mysql_mutex_lock(&innobase_share_mutex); - - ulint fold = ut_fold_string(table_name); - - HASH_SEARCH(table_name_hash, innobase_open_tables, fold, - INNOBASE_SHARE*, share, - ut_ad(share->use_count > 0), - !strcmp(share->table_name, table_name)); - - if (share == NULL) { - - uint length = (uint) strlen(table_name); - - /* TODO: invoke HASH_MIGRATE if innobase_open_tables - grows too big */ - - share = reinterpret_cast( - my_malloc(//PSI_INSTRUMENT_ME, - sizeof(*share) + length + 1, - MYF(MY_FAE | MY_ZEROFILL))); - - share->table_name = reinterpret_cast( - memcpy(share + 1, table_name, length + 1)); - - HASH_INSERT(INNOBASE_SHARE, table_name_hash, - innobase_open_tables, fold, share); - - thr_lock_init(&share->lock); - - /* Index translation table initialization */ - share->idx_trans_tbl.index_mapping = NULL; - share->idx_trans_tbl.index_count = 0; - share->idx_trans_tbl.array_size = 0; - } - - ++share->use_count; - - mysql_mutex_unlock(&innobase_share_mutex); - - return(share); -} - -/************************************************************************//** -Free the shared object that was registered with get_share(). */ -static -void -free_share( -/*=======*/ - INNOBASE_SHARE* share) /*!< in/own: table share to free */ -{ - mysql_mutex_lock(&innobase_share_mutex); - -#ifdef UNIV_DEBUG - INNOBASE_SHARE* share2; - ulint fold = ut_fold_string(share->table_name); - - HASH_SEARCH(table_name_hash, innobase_open_tables, fold, - INNOBASE_SHARE*, share2, - ut_ad(share->use_count > 0), - !strcmp(share->table_name, share2->table_name)); - - ut_a(share2 == share); -#endif /* UNIV_DEBUG */ - - --share->use_count; - - if (share->use_count == 0) { - ulint fold = ut_fold_string(share->table_name); - - HASH_DELETE(INNOBASE_SHARE, table_name_hash, - innobase_open_tables, fold, share); - - thr_lock_delete(&share->lock); - - /* Free any memory from index translation table */ - ut_free(share->idx_trans_tbl.index_mapping); - - my_free(share); - - /* TODO: invoke HASH_MIGRATE if innobase_open_tables - shrinks too much */ - } - - mysql_mutex_unlock(&innobase_share_mutex); -} - /*********************************************************************//** Returns number of THR_LOCK locks used for one instance of InnoDB table. InnoDB no longer relies on THR_LOCK locks so 0 value is returned. @@ -16785,11 +16477,11 @@ ha_innobase::get_auto_increment( "THD: %ld, current: %llu, autoinc: %llu", m_prebuilt->autoinc_increment, increment, - thd_get_thread_id(ha_thd()), + thd_get_thread_id(m_user_thd), current, autoinc); - - if (!wsrep_on(ha_thd())) { - current = autoinc - m_prebuilt->autoinc_increment; + if (!wsrep_on(m_user_thd)) { + current = autoinc + - m_prebuilt->autoinc_increment; } current = innobase_next_autoinc( @@ -20718,6 +20410,7 @@ static TABLE* innodb_acquire_mdl(THD* thd, dict_table_t* table) if (!table_name_parse(table->name, db_buf, tbl_buf, db_buf_len, tbl_buf_len)) { + table->release(); return NULL; } @@ -20800,6 +20493,7 @@ static TABLE* innodb_find_table_for_vc(THD* thd, dict_table_t* table) if (!table_name_parse(table->name, db_buf, tbl_buf, db_buf_len, tbl_buf_len)) { + ut_ad(!"invalid table name"); return NULL; } diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index f2bb8aa5ef2..c98779f6823 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -23,35 +23,6 @@ this program; if not, write to the Free Software Foundation, Inc., system clustered index when there is no primary key. */ extern const char innobase_index_reserve_name[]; -/* Structure defines translation table between mysql index and InnoDB -index structures */ -struct innodb_idx_translate_t { - - ulint index_count; /*!< number of valid index entries - in the index_mapping array */ - - ulint array_size; /*!< array size of index_mapping */ - - dict_index_t** index_mapping; /*!< index pointer array directly - maps to index in InnoDB from MySQL - array index */ -}; - -/** InnoDB table share */ -typedef struct st_innobase_share { - THR_LOCK lock; - const char* table_name; /*!< InnoDB table name */ - uint use_count; /*!< reference count, - incremented in get_share() - and decremented in - free_share() */ - void* table_name_hash; - /*!< hash table chain node */ - innodb_idx_translate_t - idx_trans_tbl; /*!< index translation table between - MySQL and InnoDB */ -} INNOBASE_SHARE; - /** Prebuilt structures in an InnoDB table handle used within MySQL */ struct row_prebuilt_t; @@ -496,9 +467,6 @@ protected: THR_LOCK_DATA lock; - /** information for MySQL table locking */ - INNOBASE_SHARE* m_share; - /** buffer used in updates */ uchar* m_upd_buf; @@ -635,17 +603,6 @@ trx_t* innobase_trx_allocate( MYSQL_THD thd); /*!< in: user thread handle */ -/** Match index columns between MySQL and InnoDB. -This function checks whether the index column information -is consistent between KEY info from mysql and that from innodb index. -@param[in] key_info Index info from mysql -@param[in] index_info Index info from InnoDB -@return true if all column types match. */ -bool -innobase_match_index_columns( - const KEY* key_info, - const dict_index_t* index_info); - /*********************************************************************//** This function checks each index name for a table against reserved system default primary index name 'GEN_CLUST_INDEX'. If a name diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index aadb0641a72..af0eac0dac4 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -5350,14 +5350,14 @@ new_clustered_failed: = dict_table_get_nth_col(user_table, i)); ut_d(const dict_index_t* index = user_table->indexes.start); - DBUG_ASSERT(col->mtype == old_col->mtype); - DBUG_ASSERT(col->prtype == old_col->prtype); - DBUG_ASSERT(col->mbminlen + DBUG_SLOW_ASSERT(col->mtype == old_col->mtype); + DBUG_SLOW_ASSERT(col->prtype == old_col->prtype); + DBUG_SLOW_ASSERT(col->mbminlen == old_col->mbminlen); - DBUG_ASSERT(col->mbmaxlen + DBUG_SLOW_ASSERT(col->mbmaxlen == old_col->mbmaxlen); - DBUG_ASSERT(col->len >= old_col->len); - DBUG_ASSERT(old_col->is_instant() + DBUG_SLOW_ASSERT(col->len >= old_col->len); + DBUG_SLOW_ASSERT(old_col->is_instant() == (dict_col_get_clust_pos( old_col, index) >= index->n_core_fields)); @@ -8491,36 +8491,17 @@ change_fields_versioning_try( DBUG_RETURN(false); } - uint virtual_count = 0; - List_iterator_fast it( ha_alter_info->alter_info->create_list); - for (uint i = 0; i < table->s->fields; i++) { - const Field* field = table->field[i]; - - if (innobase_is_v_fld(field)) { - virtual_count++; - continue; - } - - const Create_field* create_field = NULL; - while (const Create_field* cf = it++) { - if (cf->field == field) { - create_field = cf; - break; - } - } - it.rewind(); - DBUG_ASSERT(create_field); - + while (const Create_field* create_field = it++) { if (create_field->versioning == Column_definition::VERSIONING_NOT_SET) { continue; } const dict_table_t* new_table = ctx->new_table; - ulint pos = i - virtual_count; + const uint pos = innodb_col_no(create_field->field); const dict_col_t* col = dict_table_get_nth_col(new_table, pos); DBUG_ASSERT(!col->vers_sys_start()); @@ -8560,31 +8541,12 @@ change_fields_versioning_cache( DBUG_ASSERT(ctx); DBUG_ASSERT(ha_alter_info->handler_flags & ALTER_COLUMN_UNVERSIONED); - uint virtual_count = 0; - List_iterator_fast it( ha_alter_info->alter_info->create_list); - for (uint i = 0; i < table->s->fields; i++) { - const Field* field = table->field[i]; - - if (innobase_is_v_fld(field)) { - virtual_count++; - continue; - } - - const Create_field* create_field = NULL; - while (const Create_field* cf = it++) { - if (cf->field == field) { - create_field = cf; - break; - } - } - it.rewind(); - DBUG_ASSERT(create_field); - - dict_col_t* col - = dict_table_get_nth_col(ctx->new_table, i - virtual_count); + while (const Create_field* create_field = it++) { + dict_col_t* col = dict_table_get_nth_col( + ctx->new_table, innodb_col_no(create_field->field)); if (create_field->versioning == Column_definition::WITHOUT_VERSIONING) { @@ -9775,12 +9737,6 @@ foreign_fail: log_append_on_checkpoint(NULL); - /* Invalidate the index translation table. In partitioned - tables, there is no share. */ - if (m_share) { - m_share->idx_trans_tbl.index_count = 0; - } - /* Tell the InnoDB server that there might be work for utility threads: */ diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index eda991661c1..99530a3799c 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -139,10 +139,15 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply); /** Moves the parsing buffer data left to the buffer start. */ void recv_sys_justify_left_parsing_buf(); -/** Report optimized DDL operation (without redo log), corresponding to MLOG_INDEX_LOAD. +/** Report optimized DDL operation (without redo log), +corresponding to MLOG_INDEX_LOAD. @param[in] space_id tablespace identifier */ -extern void(*log_optimized_ddl_op)(ulint space_id); +extern void (*log_optimized_ddl_op)(ulint space_id); + +/** Report backup-unfriendly TRUNCATE operation (with separate log file), +corresponding to MLOG_TRUNCATE. */ +extern void (*log_truncate)(); /** Report an operation to create, delete, or rename a file during backup. @param[in] space_id tablespace identifier @@ -181,32 +186,6 @@ struct recv_t{ rec_list;/*!< list of log records for this page */ }; -/** States of recv_addr_t */ -enum recv_addr_state { - /** not yet processed */ - RECV_NOT_PROCESSED, - /** page is being read */ - RECV_BEING_READ, - /** log records are being applied on the page */ - RECV_BEING_PROCESSED, - /** log records have been applied on the page */ - RECV_PROCESSED, - /** log records have been discarded because the tablespace - does not exist */ - RECV_DISCARDED -}; - -/** Hashed page file address struct */ -struct recv_addr_t{ - enum recv_addr_state state; - /*!< recovery state of the page */ - unsigned space:32;/*!< space id */ - unsigned page_no:32;/*!< page number */ - UT_LIST_BASE_NODE_T(recv_t) - rec_list;/*!< list of log records for this page */ - hash_node_t addr_hash;/*!< hash node in the hash bucket chain */ -}; - struct recv_dblwr_t { /** Add a page frame to the doublewrite recovery buffer. */ void add(byte* page) { diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index a5a73265170..c0fa20d7725 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -1010,12 +1010,6 @@ struct export_var_t{ of used row log buffer */ ulint innodb_onlineddl_pct_progress; /*!< Online alter progress */ -#ifdef UNIV_DEBUG - ulint innodb_ahi_drop_lookups; /*!< number of adaptive hash - index lookups when freeing - file pages */ -#endif /* UNIV_DEBUG */ - int64_t innodb_page_compression_saved;/*!< Number of bytes saved by page compression */ int64_t innodb_index_pages_written; /*!< Number of index pages diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 07ae85ced5a..b7c4f8d37cd 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -3528,7 +3528,7 @@ lock_table_create( UT_LIST_ADD_LAST(trx->lock.trx_locks, lock); #ifdef WITH_WSREP - if (c_lock) { + if (c_lock && wsrep_on_trx(trx)) { if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { ut_list_insert(table->locks, c_lock, lock, TableLockGetNode()); @@ -3758,7 +3758,7 @@ lock_table_enqueue_waiting( } #ifdef WITH_WSREP - if (trx->lock.was_chosen_as_deadlock_victim) { + if (trx->lock.was_chosen_as_deadlock_victim && wsrep_on_trx(trx)) { return(DB_DEADLOCK); } #endif /* WITH_WSREP */ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 08f4f72efbc..a98397b0f7c 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -954,12 +954,6 @@ void log_write_up_to(lsn_t lsn, bool flush_to_disk, bool rotate_key) return; } - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { - service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, - "log write up to: " LSN_PF, - lsn); - } - loop: ut_ad(++loop_count < 128); @@ -1087,6 +1081,13 @@ loop: } } + if (UNIV_UNLIKELY(srv_shutdown_state != SRV_SHUTDOWN_NONE)) { + service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, + "InnoDB log write: " + LSN_PF "," LSN_PF, + log_sys.write_lsn, lsn); + } + if (log_sys.is_encrypted()) { log_crypt(write_buf + area_start, log_sys.write_lsn, area_end - area_start, diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 1cbb102bfdd..f8fccea5617 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -169,11 +169,45 @@ typedef std::map< static recv_spaces_t recv_spaces; -/** Report optimized DDL operation (without redo log), corresponding to MLOG_INDEX_LOAD. +/** States of recv_addr_t */ +enum recv_addr_state { + /** not yet processed */ + RECV_NOT_PROCESSED, + /** page is being read */ + RECV_BEING_READ, + /** log records are being applied on the page */ + RECV_BEING_PROCESSED, + /** log records have been applied on the page */ + RECV_PROCESSED, + /** log records have been discarded because the tablespace + does not exist */ + RECV_DISCARDED +}; + +/** Hashed page file address struct */ +struct recv_addr_t{ + /** recovery state of the page */ + recv_addr_state state; + /** tablespace identifier */ + unsigned space:32; + /** page number */ + unsigned page_no:32; + /** list of log records for this page */ + UT_LIST_BASE_NODE_T(recv_t) rec_list; + /** hash node in the hash bucket chain */ + hash_node_t addr_hash; +}; + +/** Report optimized DDL operation (without redo log), +corresponding to MLOG_INDEX_LOAD. @param[in] space_id tablespace identifier */ void (*log_optimized_ddl_op)(ulint space_id); +/** Report backup-unfriendly TRUNCATE operation (with separate log file), +corresponding to MLOG_TRUNCATE. */ +void (*log_truncate)(); + /** Report an operation to create, delete, or rename a file during backup. @param[in] space_id tablespace identifier @param[in] flags tablespace flags (NULL if not create) @@ -189,11 +223,9 @@ void (*log_file_op)(ulint space_id, const byte* flags, @param[in,out] name file name @param[in] len length of the file name @param[in] space_id the tablespace ID -@param[in] deleted whether this is a MLOG_FILE_DELETE record -@retval true if able to process file successfully. -@retval false if unable to process the file */ +@param[in] deleted whether this is a MLOG_FILE_DELETE record */ static -bool +void fil_name_process( char* name, ulint len, @@ -201,15 +233,13 @@ fil_name_process( bool deleted) { if (srv_operation == SRV_OPERATION_BACKUP) { - return true; + return; } ut_ad(srv_operation == SRV_OPERATION_NORMAL || srv_operation == SRV_OPERATION_RESTORE || srv_operation == SRV_OPERATION_RESTORE_EXPORT); - bool processed = true; - /* We will also insert space=NULL into the map, so that further checks can ensure that a MLOG_FILE_NAME record was scanned before applying any page records for the space_id. */ @@ -256,7 +286,6 @@ fil_name_process( << f.name << "' and '" << name << "'." " You must delete one of them."; recv_sys->found_corrupt_fs = true; - processed = false; } break; @@ -309,7 +338,6 @@ fil_name_process( " remove the .ibd file, you can set" " --innodb_force_recovery."; recv_sys->found_corrupt_fs = true; - processed = false; break; } @@ -320,7 +348,6 @@ fil_name_process( break; } } - return(processed); } /** Parse or process a MLOG_FILE_* record. @@ -1097,6 +1124,12 @@ recv_parse_or_apply_log_rec_body( } return(ptr + 8); case MLOG_TRUNCATE: + if (log_truncate) { + ut_ad(srv_operation != SRV_OPERATION_NORMAL); + log_truncate(); + recv_sys->found_corrupt_fs = true; + return NULL; + } return(truncate_t::parse_redo_entry(ptr, end_ptr, space_id)); default: @@ -1174,6 +1207,7 @@ parse_log: redo log been written with something older than InnoDB Plugin 1.0.4. */ ut_ad(offs == FIL_PAGE_TYPE + || srv_is_undo_tablespace(space_id) || offs == IBUF_TREE_SEG_HEADER + IBUF_HEADER + FSEG_HDR_OFFSET || offs == PAGE_BTR_IBUF_FREE_LIST @@ -1199,6 +1233,7 @@ parse_log: ut_ad(0 /* fil_crypt_rotate_page() writes this */ || offs == FIL_PAGE_SPACE_ID + || srv_is_undo_tablespace(space_id) || offs == IBUF_TREE_SEG_HEADER + IBUF_HEADER + FSEG_HDR_SPACE || offs == IBUF_TREE_SEG_HEADER diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index 36b9a135b10..fb8f62f5fe3 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -846,7 +846,8 @@ page_cur_insert_rec_write_log( ulint i; if (index->table->is_temporary()) { - ut_ad(!mlog_open(mtr, 0)); + mtr->set_modified(); + ut_ad(mtr->get_log_mode() == MTR_LOG_NO_REDO); return; } diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index aab445cb197..8758db3c346 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -3915,7 +3915,7 @@ row_import_for_mysql( DBUG_EXECUTE_IF("ib_import_reset_space_and_lsn_failure", err = DB_TOO_MANY_CONCURRENT_TRXS;); - +#ifdef BTR_CUR_HASH_ADAPT /* On DISCARD TABLESPACE, we did not drop any adaptive hash index entries. If we replaced the discarded tablespace with a smaller one here, there could still be some adaptive hash @@ -3932,6 +3932,7 @@ row_import_for_mysql( break; } } +#endif /* BTR_CUR_HASH_ADAPT */ if (err != DB_SUCCESS) { char table_name[MAX_FULL_NAME_LEN + 1]; diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index ba8a7044baa..000da4b0562 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -3934,17 +3934,6 @@ row_merge_drop_indexes( ut_ad(prev); ut_a(table->fts); fts_drop_index(table, index, trx); - /* Since - INNOBASE_SHARE::idx_trans_tbl - is shared between all open - ha_innobase handles to this - table, no thread should be - accessing this dict_index_t - object. Also, we should be - holding LOCK=SHARED MDL on the - table even after the MDL - upgrade timeout. */ - /* We can remove a DICT_FTS index from the cache, because we do not allow ADD FULLTEXT INDEX diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index a3c3d0eaaa6..7c68bf6f7c2 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -3536,6 +3536,7 @@ row_drop_table_for_mysql( if (!table->no_rollback()) { if (table->space != fil_system.sys_space) { +#ifdef BTR_CUR_HASH_ADAPT /* On DISCARD TABLESPACE, we would not drop the adaptive hash index entries. If the tablespace is missing here, delete-marking the record in SYS_INDEXES @@ -3557,6 +3558,7 @@ row_drop_table_for_mysql( goto funct_exit; } } +#endif /* BTR_CUR_HASH_ADAPT */ /* Delete the link file if used. */ if (DICT_TF_HAS_DATA_DIR(table->flags)) { diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index e2bbb5a3d5e..30eacbfc518 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -1076,9 +1076,7 @@ try_again: ut_ad(!node->table->is_temporary()); if (!fil_table_accessible(node->table)) { - dict_table_close(node->table, FALSE, FALSE); - node->table = NULL; - goto err_exit; + goto close_exit; } switch (type) { @@ -1113,6 +1111,7 @@ try_again: dict_set_corrupted() works on an index, and we do not have an index to call it with. */ dict_table_close(node->table, FALSE, FALSE); + node->table = NULL; err_exit: rw_lock_s_unlock(dict_operation_lock); return(false); diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index 187fa2a0929..fac01fe26cc 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -452,6 +452,7 @@ row_vers_build_clust_v_col( byte* record= 0; ut_ad(dict_index_has_virtual(index)); + ut_ad(index->table == clust_index->table); if (vcol_info != NULL) { vcol_info->set_used(); diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index ca60949ad5f..8f674f47b4c 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -2416,7 +2416,22 @@ static bool srv_purge_should_exit() return(true); } /* Slow shutdown was requested. */ - return !trx_sys.any_active_transactions() && !trx_sys.history_size(); + if (ulint history_size = trx_sys.history_size()) { +#if defined HAVE_SYSTEMD && !defined EMBEDDED_LIBRARY + static ib_time_t progress_time; + ib_time_t time = ut_time(); + if (time - progress_time >= 15) { + progress_time = time; + service_manager_extend_timeout( + INNODB_EXTEND_TIMEOUT_INTERVAL, + "InnoDB: to purge " ULINTPF " transactions", + history_size); + } +#endif + return false; + } + + return !trx_sys.any_active_transactions(); } /*********************************************************************//** @@ -2582,14 +2597,6 @@ srv_do_purge(ulint* n_total_purged) (++count % rseg_truncate_frequency) == 0); *n_total_purged += n_pages_purged; - - if (n_pages_purged) { - service_manager_extend_timeout( - INNODB_EXTEND_TIMEOUT_INTERVAL, - "InnoDB " ULINTPF " pages purged", n_pages_purged); - /* The previous round still did some work. */ - continue; - } } while (n_pages_purged > 0 && !purge_sys.paused() && !srv_purge_should_exit()); diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 32e050e9b91..8f6e585f66b 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -258,7 +258,12 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) trx_sys.get_max_trx_id(), mtr); } - /* Before any transaction-generating background threads or the + /* After the purge thread has been given permission to exit, + we may roll back transactions (trx->undo_no==0) + in THD::cleanup() invoked from unlink_thd() in fast shutdown, + or in trx_rollback_resurrected() in slow shutdown. + + Before any transaction-generating background threads or the purge have been started, recv_recovery_rollback_active() can start transactions in row_merge_drop_temp_indexes() and fts_drop_orphaned_tables(), and roll back recovered transactions. @@ -268,17 +273,15 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) innodb_force_recovery=2 or innodb_force_recovery=3. DROP TABLE may be executed at any innodb_force_recovery level. - After the purge thread has been given permission to exit, - in fast shutdown, we may roll back transactions (trx->undo_no==0) - in THD::cleanup() invoked from unlink_thd(), and we may also - continue to execute user transactions. */ + During fast shutdown, we may also continue to execute + user transactions. */ ut_ad(srv_undo_sources + || trx->undo_no == 0 || (!purge_sys.enabled() && (srv_startup_is_before_trx_rollback_phase || trx_rollback_is_active || srv_force_recovery >= SRV_FORCE_NO_BACKGROUND)) - || ((trx->undo_no == 0 || trx->mysql_thd - || trx->internal) + || ((trx->mysql_thd || trx->internal) && srv_fast_shutdown)); #ifdef WITH_WSREP diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index 18755d0457a..63ec73fc2b3 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -1444,7 +1444,7 @@ buf_block_t* trx_undo_assign_low(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo, dberr_t* err, mtr_t* mtr) { - const bool is_temp = rseg == trx->rsegs.m_noredo.rseg; + const bool is_temp __attribute__((unused)) = rseg == trx->rsegs.m_noredo.rseg; ut_ad(rseg == trx->rsegs.m_redo.rseg || rseg == trx->rsegs.m_noredo.rseg); diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index aa9f18966c4..6fe00e52081 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1512,6 +1512,7 @@ int ha_maria::repair(THD * thd, HA_CHECK_OPT *check_opt) while ((error= repair(thd, param, 0)) && param->retry_repair) { param->retry_repair= 0; + file->state->records= start_records; if (test_all_bits(param->testflag, (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK))) { @@ -2016,6 +2017,7 @@ int ha_maria::disable_indexes(uint mode) int ha_maria::enable_indexes(uint mode) { int error; + ha_rows start_rows= file->state->records; DBUG_PRINT("info", ("ha_maria::enable_indexes mode: %d", mode)); if (maria_is_all_keys_active(file->s->state.key_map, file->s->base.keys)) { @@ -2078,6 +2080,7 @@ int ha_maria::enable_indexes(uint mode) DBUG_ASSERT(thd->killed != 0); /* Repairing by sort failed. Now try standard repair method. */ param->testflag &= ~T_REP_BY_SORT; + file->state->records= start_rows; error= (repair(thd, param, 0) != HA_ADMIN_OK); /* If the standard repair succeeded, clear all error messages which diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 316a1a06ccc..d0613d4f0d8 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -149,7 +149,7 @@ void maria_chk_init_for_check(HA_CHECK *param, MARIA_HA *info) */ param->max_trid= ~(TrID) 0; } - else if (param->max_trid == 0) + else if (param->max_trid == 0 || param->max_trid == ~(TrID) 0) { if (!ma_control_file_inited()) param->max_trid= 0; /* Give warning for first trid found */ @@ -179,7 +179,7 @@ int maria_chk_status(HA_CHECK *param, MARIA_HA *info) if (share->state.open_count != (uint) (share->global_changed ? 1 : 0)) { /* Don't count this as a real warning, as check can correct this ! */ - uint save=param->warning_printed; + my_bool save=param->warning_printed; _ma_check_print_warning(param, share->state.open_count==1 ? "%d client is using or hasn't closed the table properly" : @@ -191,6 +191,7 @@ int maria_chk_status(HA_CHECK *param, MARIA_HA *info) } if (share->state.create_trid > param->max_trid) { + param->wrong_trd_printed= 1; /* Force should run zerofill */ _ma_check_print_warning(param, "Table create_trd (%llu) > current max_transaction id (%llu). Table needs to be repaired or zerofilled to be usable", share->state.create_trid, param->max_trid); @@ -643,7 +644,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info) (key_part_map) 1, HA_READ_KEY_EXACT)) { /* Don't count this as a real warning, as maria_chk can't correct it */ - uint save=param->warning_printed; + my_bool save=param->warning_printed; _ma_check_print_warning(param, "Found row where the auto_increment " "column has the value 0"); param->warning_printed=save; @@ -891,11 +892,10 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (level > param->max_level) param->max_level=level; - if (_ma_get_keynr(share, anc_page->buff) != - (uint) (keyinfo - share->keyinfo)) + if (_ma_get_keynr(share, anc_page->buff) != keyinfo->key_nr) _ma_check_print_error(param, "Page at %s is not marked for index %u", llstr(anc_page->pos, llbuff), - (uint) (keyinfo - share->keyinfo)); + (uint) keyinfo->key_nr); if ((page_flag & KEYPAGE_FLAG_HAS_TRANSID) && !share->base.born_transactional) { @@ -1011,6 +1011,7 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (subkeys < 0) { ha_rows tmp_keys=0; + share->ft2_keyinfo.key_nr= keyinfo->key_nr; if (chk_index_down(param,info,&share->ft2_keyinfo,record, temp_buff,&tmp_keys,key_checksum,1)) goto err; @@ -2381,6 +2382,7 @@ static int initialize_variables_for_repair(HA_CHECK *param, param->retry_repair= 0; param->warning_printed= 0; param->error_printed= 0; + param->wrong_trd_printed= 0; sort_param->sort_info= sort_info; sort_param->fix_datafile= ! rep_quick; @@ -5754,8 +5756,7 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, a_length= share->keypage_header + nod_flag; key_block->end_pos= anc_buff + share->keypage_header; bzero(anc_buff, share->keypage_header); - _ma_store_keynr(share, anc_buff, (uint) (sort_param->keyinfo - - share->keyinfo)); + _ma_store_keynr(share, anc_buff, sort_param->key); lastkey=0; /* No previous key in block */ } else diff --git a/storage/maria/ma_commit.c b/storage/maria/ma_commit.c index f557cd211e2..3850af8246c 100644 --- a/storage/maria/ma_commit.c +++ b/storage/maria/ma_commit.c @@ -98,12 +98,7 @@ int maria_commit(MARIA_HA *info) if (!info->s->now_transactional) return 0; trn= info->trn; - /* - trn is reset as it's checked in maria_close - Note that info is still linked in info->trn->used_instances, as this is - used in ha_maria::implicit_commit() - */ - info->trn= 0; + _ma_reset_trn_for_table(info); return ma_commit(trn); } diff --git a/storage/maria/ma_control_file.c b/storage/maria/ma_control_file.c index 3b7d2dd4850..3c536d2c46f 100644 --- a/storage/maria/ma_control_file.c +++ b/storage/maria/ma_control_file.c @@ -583,8 +583,8 @@ int ma_control_file_end(void) close_error= mysql_file_close(control_file_fd, MYF(MY_WME)); /* - As mysql_file_close() frees structures even if close() fails, we do the same, - i.e. we mark the file as closed in all cases. + As mysql_file_close() frees structures even if close() fails, we do the + same, i.e. we mark the file as closed in all cases. */ control_file_fd= -1; /* diff --git a/storage/maria/ma_control_file.h b/storage/maria/ma_control_file.h index 155c778c105..85e8f2c899d 100644 --- a/storage/maria/ma_control_file.h +++ b/storage/maria/ma_control_file.h @@ -42,7 +42,7 @@ extern LSN last_checkpoint_lsn; */ extern uint32 last_logno; -extern TrID max_trid_in_control_file; +extern TrID max_trid_in_control_file, max_long_trid; extern uint8 recovery_failures; diff --git a/storage/maria/ma_info.c b/storage/maria/ma_info.c index 081df0bc5ce..22b9c86f21d 100644 --- a/storage/maria/ma_info.c +++ b/storage/maria/ma_info.c @@ -56,7 +56,11 @@ int maria_status(MARIA_HA *info, register MARIA_INFO *x, uint flag) } if (flag & HA_STATUS_VARIABLE) { - x->records = info->state->records; + /* If table is locked, give versioned number otherwise last commited */ + if (info->lock_type == F_UNLCK) + x->records = share->state.state.records; + else + x->records = info->state->records; x->deleted = share->state.state.del; x->delete_length = share->state.state.empty; x->data_file_length = share->state.state.data_file_length; diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c index e41b7dd1177..389e1bc068b 100644 --- a/storage/maria/ma_page.c +++ b/storage/maria/ma_page.c @@ -153,8 +153,9 @@ my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info, if (page_size < 4 || page_size > share->max_index_block_size || _ma_get_keynr(share, tmp) != keyinfo->key_nr) { - DBUG_PRINT("error",("page %lu had wrong page length: %u keynr: %u", + DBUG_PRINT("error",("page %lu had wrong page length: %u page_header: %u keynr: %u", (ulong) (pos / block_size), page_size, + share->keypage_header, _ma_get_keynr(share, tmp))); DBUG_DUMP("page", tmp, page_size); info->last_keypage = HA_OFFSET_ERROR; diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index ea91c65ff3d..dbb8d46bdbc 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -49,7 +49,6 @@ static LSN current_group_end_lsn; /** Current group of REDOs is about this table and only this one */ static MARIA_HA *current_group_table; #endif -static TrID max_long_trid= 0; /**< max long trid seen by REDO phase */ static my_bool skip_DDLs; /**< if REDO phase should skip DDL records */ /** @brief to avoid writing a checkpoint if recovery did nothing. */ static my_bool checkpoint_useful; @@ -62,6 +61,7 @@ static uint recovery_warnings; /**< count of warnings */ static uint recovery_found_crashed_tables; HASH tables_to_redo; /* For maria_read_log */ ulong maria_recovery_force_crash_counter; +TrID max_long_trid= 0; /**< max long trid seen by REDO phase */ #define prototype_redo_exec_hook(R) \ static int exec_REDO_LOGREC_ ## R(const TRANSLOG_HEADER_BUFFER *rec) @@ -473,6 +473,7 @@ int maria_apply_log(LSN from_lsn, LSN end_lsn, fflush(stderr); } + set_if_bigger(max_trid_in_control_file, max_long_trid); if (take_checkpoints && checkpoint_useful) { /* No dirty pages, all tables are closed, no active transactions, save: */ @@ -3560,8 +3561,8 @@ void _ma_tmp_disable_logging_for_table(MARIA_HA *info, info->state may point to a state that was deleted by _ma_trnman_end_trans_hook() */ - share->state.common= *info->state; - info->state= &share->state.common; + share->state.no_logging= *info->state; + info->state= &share->state.no_logging; info->switched_transactional= TRUE; /* @@ -3622,6 +3623,10 @@ my_bool _ma_reenable_logging_for_table(MARIA_HA *info, my_bool flush_pages) _ma_copy_nontrans_state_information(info); _ma_reset_history(info->s); + /* Reset state to point to state.common, as on open() */ + info->state= &share->state.common; + *info->state= share->state.state; + if (flush_pages) { /* Ensure that recover is not executing any redo before this */ diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index 86a27a13136..ae3b95db6ec 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef HAVE_SYS_MMAN_H #include #endif @@ -93,12 +94,28 @@ ATTRIBUTE_NORETURN static void my_exit(int exit_code); HA_CHECK check_param; +/* + Register handler error messages for usage with my_error() + + NOTES + This is safe to call multiple times as my_error_register() + will ignore calls to register already registered error numbers. +*/ + +static const char **get_handler_error_messages(int e __attribute__((unused))) +{ + return handler_error_messages; +} + + /* Free memory and exit */ static void my_exit(int exit_code) { free_tmpdir(&maria_chk_tmpdir); free_defaults(default_argv); + my_error_unregister(HA_ERR_FIRST, + HA_ERR_FIRST+ array_elements(handler_error_messages)-1); my_end(check_param.testflag & T_INFO ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); exit(exit_code); @@ -120,6 +137,8 @@ int main(int argc, char **argv) maria_quick_table_bits=decode_bits; error=0; maria_init(); + my_error_register(get_handler_error_messages, HA_ERR_FIRST, + HA_ERR_FIRST+ array_elements(handler_error_messages)-1); maria_block_size= 0; /* Use block size from control file */ if (!opt_ignore_control_file && @@ -160,6 +179,20 @@ int main(int argc, char **argv) check_param.testflag&= ~T_REP; fflush(stdout); fflush(stderr); + if (check_param.wrong_trd_printed && + (check_param.testflag & T_FORCE_CREATE) && + !(check_param.error_printed | check_param.warning_printed)) + { + /* Only wrong create_trd. Run zerofill */ + ulonglong old_testflag= check_param.testflag; + check_param.testflag= T_ZEROFILL; + error|= maria_chk(&check_param, argv[-1]); + check_param.testflag= old_testflag; + check_param.error_printed= 0; + check_param.warning_printed= 0; + fflush(stdout); + fflush(stderr); + } if ((check_param.error_printed | check_param.warning_printed) && (check_param.testflag & T_FORCE_CREATE) && (!(check_param.testflag & (T_REP | T_REP_BY_SORT | T_SORT_RECORDS | @@ -174,7 +207,6 @@ int main(int argc, char **argv) fflush(stdout); fflush(stderr); } - else error|=new_error; if (argc && (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO)) @@ -693,8 +725,8 @@ get_one_option(int optid, } else { - if (check_param.testflag & T_FORCE_CREATE) - check_param.testflag= T_FORCE_SORT_MEMORY; + if (check_param.testflag & T_FORCE_CREATE) + check_param.testflag= T_FORCE_SORT_MEMORY; check_param.tmpfile_createflag= O_RDWR | O_TRUNC; check_param.testflag|= T_FORCE_CREATE | T_UPDATE_STATE; } @@ -981,8 +1013,8 @@ static int maria_chk(HA_CHECK *param, char *filename) MARIA_SHARE *share; DBUG_ENTER("maria_chk"); - param->out_flag=error=param->warning_printed=param->error_printed= - recreate=0; + param->out_flag= error= param->error_printed= recreate= 0; + param->warning_printed= param->wrong_trd_printed= 0; datafile=0; param->isam_file_name=filename; /* For error messages */ warning_printed_by_chk_status= 0; @@ -1128,7 +1160,7 @@ static int maria_chk(HA_CHECK *param, char *filename) { fprintf(stderr, "Aria table '%s' is not fixed because of errors\n", filename); - return(-1); + DBUG_RETURN(-1); } recreate=1; if (!(param->testflag & T_REP_ANY)) @@ -1150,7 +1182,7 @@ static int maria_chk(HA_CHECK *param, char *filename) param->total_deleted+=info->state->del; descript(param, info, filename); maria_close(info); /* Should always succeed */ - return(0); + DBUG_RETURN(0); } if (!stopwords_inited++) @@ -1617,7 +1649,7 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) buff, share->base.keys); } puts("\nTable description:"); - printf("Key Start Len Index Type"); + printf("Key Start Len Index Type"); if (param->testflag & T_VERBOSE) printf(" Rec/key Root Blocksize"); putchar('\n'); @@ -1649,7 +1681,7 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) pos=strmov(pos,null_txt); *pos=0; - printf("%-4d%-6ld%-3d %-8s%-23s", + printf("%-4d%-6ld%-3d %-9s%-23s", key+1,(long) keyseg->start+1,keyseg->length,text,buff); if (share->state.key_root[key] != HA_OFFSET_ERROR) llstr(share->state.key_root[key],buff); @@ -1674,7 +1706,7 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) if (keyseg->flag & HA_NULL_PART) pos=strmov(pos,null_txt); *pos=0; - printf(" %-6ld%-3d %-21s", + printf(" %-6ld%-3d %-21s", (long) keyseg->start+1,keyseg->length,buff); if (param->testflag & T_VERBOSE) printf("%11.0f", share->state.rec_per_key_part[keyseg_nr++]); diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 37b24492be6..d5f2b1e80fd 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -150,6 +150,8 @@ typedef struct st_maria_state_info MARIA_STATUS_INFO state; /* maria_ha->state points here for crash-safe but not versioned tables */ MARIA_STATUS_INFO common; + /* State for a versioned table that is temporary non versioned */ + MARIA_STATUS_INFO no_logging; ha_rows split; /* number of split blocks */ my_off_t dellink; /* Link to next removed block */ pgcache_page_no_t first_bitmap_with_space; diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index c638dcbe3e8..f6929438ac0 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -111,7 +111,7 @@ int chk_status(HA_CHECK *param, register MI_INFO *info) if (share->state.open_count != (uint) (info->s->global_changed ? 1 : 0)) { /* Don't count this as a real warning, as check can correct this ! */ - uint save=param->warning_printed; + my_bool save=param->warning_printed; mi_check_print_warning(param, share->state.open_count==1 ? "%d client is using or hasn't closed the table properly" : @@ -526,7 +526,7 @@ int chk_key(HA_CHECK *param, register MI_INFO *info) (key_part_map)1, HA_READ_KEY_EXACT)) { /* Don't count this as a real warning, as myisamchk can't correct it */ - uint save=param->warning_printed; + my_bool save=param->warning_printed; mi_check_print_warning(param, "Found row where the auto_increment " "column has the value 0"); param->warning_printed=save; @@ -1515,7 +1515,8 @@ int mi_repair(HA_CHECK *param, register MI_INFO *info, new_file= -1; sort_param.sort_info=&sort_info; param->retry_repair= 0; - param->warning_printed= param->error_printed= param->note_printed= 0; + param->warning_printed= param->note_printed= 0; + param->error_printed= 0; if (!(param->testflag & T_SILENT)) { @@ -2210,7 +2211,8 @@ int mi_repair_by_sort(HA_CHECK *param, register MI_INFO *info, } param->testflag|=T_REP_BY_SORT; /* for easy checking */ param->retry_repair= 0; - param->warning_printed= param->error_printed= param->note_printed= 0; + param->warning_printed= param->note_printed= 0; + param->error_printed= 0; if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) param->testflag|=T_CALC_CHECKSUM; diff --git a/storage/rocksdb/CMakeLists.txt b/storage/rocksdb/CMakeLists.txt index e56c5b1033e..090763a2ece 100644 --- a/storage/rocksdb/CMakeLists.txt +++ b/storage/rocksdb/CMakeLists.txt @@ -159,6 +159,9 @@ if (UNIX AND NOT APPLE) endif() TARGET_LINK_LIBRARIES(rocksdb rocksdb_aux_lib) + FIND_LIBRARY(LZ4_LIBRARY + NAMES liblz4${PIC_EXT}.a lz4 + HINTS ${WITH_LZ4}/lib) IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") @@ -186,8 +189,11 @@ IF(HAVE_SCHED_GETCPU) ENDIF() IF (WITH_TBB) + FIND_LIBRARY(TBB_LIBRARY + NAMES libtbb${PIC_EXT}.a tbb + HINTS ${WITH_TBB}/lib) SET(rocksdb_static_libs ${rocksdb_static_libs} - ${WITH_TBB}/lib/libtbb${PIC_EXT}.a) + ${TBB_LIBRARY}) ADD_DEFINITIONS(-DTBB) ENDIF() diff --git a/storage/rocksdb/build_rocksdb.cmake b/storage/rocksdb/build_rocksdb.cmake index d854bdaa03a..c36c761f92f 100644 --- a/storage/rocksdb/build_rocksdb.cmake +++ b/storage/rocksdb/build_rocksdb.cmake @@ -178,6 +178,7 @@ set(ROCKSDB_SOURCES db/db_info_dumper.cc db/db_iter.cc db/dbformat.cc + db/error_handler.cc db/event_helpers.cc db/experimental.cc db/external_sst_file_ingestion_job.cc @@ -188,6 +189,7 @@ set(ROCKSDB_SOURCES db/internal_stats.cc db/log_reader.cc db/log_writer.cc + db/logs_with_prep_tracker.cc db/malloc_stats.cc db/managed_iterator.cc db/memtable.cc @@ -284,6 +286,7 @@ set(ROCKSDB_SOURCES util/coding.cc util/compaction_job_stats_impl.cc util/comparator.cc + util/compression_context_cache.cc util/concurrent_arena.cc util/crc32c.cc util/delete_scheduler.cc @@ -304,6 +307,7 @@ set(ROCKSDB_SOURCES util/status_message.cc util/string_util.cc util/sync_point.cc + util/sync_point_impl.cc util/testutil.cc util/thread_local.cc util/threadpool_imp.cc @@ -352,6 +356,8 @@ set(ROCKSDB_SOURCES utilities/transactions/transaction_util.cc utilities/transactions/write_prepared_txn.cc utilities/transactions/write_prepared_txn_db.cc + utilities/transactions/write_unprepared_txn.cc + utilities/transactions/write_unprepared_txn_db.cc utilities/ttl/db_ttl_impl.cc utilities/write_batch_with_index/write_batch_with_index.cc utilities/write_batch_with_index/write_batch_with_index_internal.cc @@ -379,6 +385,13 @@ ENDFOREACH() if(MSVC) add_definitions(-DHAVE_SSE42 -DHAVE_PCLMUL) + # Workaround broken compilation with -DWIN32_LEAN_AND_MEAN + # (https://github.com/facebook/rocksdb/issues/4344) + set_source_files_properties(${ROCKSDB_SOURCE_DIR}/port/win/env_win.cc + PROPERTIES COMPILE_FLAGS "/FI\"windows.h\" /FI\"winioctl.h\"") + + # Workaround Win8.1 SDK bug, that breaks /permissive- + string(REPLACE "/permissive-" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") else() set(CMAKE_REQUIRED_FLAGS "-msse4.2 -mpclmul ${CXX11_FLAGS}") diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 2c7737a821d..49104911c69 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -32,6 +32,7 @@ /* C++ standard header files */ #include +#include #include #include #include @@ -127,6 +128,60 @@ const std::string DEFAULT_CF_NAME("default"); const std::string DEFAULT_SYSTEM_CF_NAME("__system__"); const std::string PER_INDEX_CF_NAME("$per_index_cf"); +class Rdb_explicit_snapshot; + +std::mutex explicit_snapshot_mutex; +ulonglong explicit_snapshot_counter = 0; +std::unordered_map> + explicit_snapshots; +static std::vector rdb_indexes_to_recalc; + +#ifdef MARIADB_NOT_YET +class Rdb_explicit_snapshot : public explicit_snapshot { + std::unique_ptr snapshot; + + public: + static std::shared_ptr + create(snapshot_info_st *ss_info, rocksdb::DB *db, + const rocksdb::Snapshot *snapshot) { + std::lock_guard lock(explicit_snapshot_mutex); + auto s = std::unique_ptr( + new rocksdb::ManagedSnapshot(db, snapshot)); + if (!s) { + return nullptr; + } + ss_info->snapshot_id = ++explicit_snapshot_counter; + auto ret = std::make_shared(*ss_info, std::move(s)); + if (!ret) { + return nullptr; + } + explicit_snapshots[ss_info->snapshot_id] = ret; + return ret; + } + + static std::shared_ptr + get(const ulonglong snapshot_id) { + std::lock_guard lock(explicit_snapshot_mutex); + auto elem = explicit_snapshots.find(snapshot_id); + if (elem == explicit_snapshots.end()) { + return nullptr; + } + return elem->second.lock(); + } + + rocksdb::ManagedSnapshot *get_snapshot() { return snapshot.get(); } + + Rdb_explicit_snapshot(snapshot_info_st ss_info, + std::unique_ptr snapshot) + : explicit_snapshot(ss_info), snapshot(std::move(snapshot)) {} + + virtual ~Rdb_explicit_snapshot() { + std::lock_guard lock(explicit_snapshot_mutex); + explicit_snapshots.erase(ss_info.snapshot_id); + } +}; +#endif + /** Updates row counters based on the table type and operation type. */ @@ -144,11 +199,15 @@ static handler *rocksdb_create_handler(my_core::handlerton *hton, my_core::TABLE_SHARE *table_arg, my_core::MEM_ROOT *mem_root); -static rocksdb::CompactRangeOptions getCompactRangeOptions() { +static rocksdb::CompactRangeOptions +getCompactRangeOptions(int concurrency = 0) { rocksdb::CompactRangeOptions compact_range_options; compact_range_options.bottommost_level_compaction = rocksdb::BottommostLevelCompaction::kForce; compact_range_options.exclusive_manual_compaction = false; + if (concurrency > 0) { + compact_range_options.max_subcompactions = concurrency; + } return compact_range_options; } @@ -187,6 +246,8 @@ Rdb_io_watchdog *io_watchdog = nullptr; static Rdb_background_thread rdb_bg_thread; +static Rdb_manual_compaction_thread rdb_mc_thread; + // List of table names (using regex) that are exceptions to the strict // collation check requirement. Regex_list_handler *rdb_collation_exceptions; @@ -200,30 +261,6 @@ static void rocksdb_flush_all_memtables() { } } -static void rocksdb_compact_column_family_stub( - THD *const thd, struct st_mysql_sys_var *const var, void *const var_ptr, - const void *const save) {} - -static int rocksdb_compact_column_family(THD *const thd, - struct st_mysql_sys_var *const var, - void *const var_ptr, - struct st_mysql_value *const value) { - char buff[STRING_BUFFER_USUAL_SIZE]; - int len = sizeof(buff); - - DBUG_ASSERT(value != nullptr); - - if (const char *const cf = value->val_str(value, buff, &len)) { - auto cfh = cf_manager.get_cf(cf); - if (cfh != nullptr && rdb != nullptr) { - sql_print_verbose_info("RocksDB: Manual compaction of column family: %s\n", - cf); - rdb->CompactRange(getCompactRangeOptions(), cfh, nullptr, nullptr); - } - } - return HA_EXIT_SUCCESS; -} - /////////////////////////////////////////////////////////// // Hash map: table name => open table handler /////////////////////////////////////////////////////////// @@ -249,6 +286,8 @@ struct Rdb_open_tables_map { Rdb_open_tables_map() : m_hash(get_hash_key, system_charset_info) { } + void free_hash(void) { m_hash.~Rdb_table_set(); } + std::vector get_table_names(void) const; }; @@ -368,6 +407,7 @@ static void rocksdb_drop_index_wakeup_thread( static my_bool rocksdb_pause_background_work = 0; static mysql_mutex_t rdb_sysvars_mutex; +static mysql_mutex_t rdb_block_cache_resize_mutex; static void rocksdb_set_pause_background_work( my_core::THD *const, @@ -450,6 +490,9 @@ static void rocksdb_set_wal_bytes_per_sync(THD *thd, struct st_mysql_sys_var *const var, void *const var_ptr, const void *const save); +static int rocksdb_validate_set_block_cache_size( + THD *thd, struct st_mysql_sys_var *const var, void *var_ptr, + struct st_mysql_value *value); ////////////////////////////////////////////////////////////////////////////// // Options definitions ////////////////////////////////////////////////////////////////////////////// @@ -510,11 +553,19 @@ static char* rocksdb_git_hash; char *compression_types_val= const_cast(get_rocksdb_supported_compression_types()); +static unsigned long rocksdb_write_policy = + rocksdb::TxnDBWritePolicy::WRITE_COMMITTED; +static my_bool rocksdb_error_on_suboptimal_collation = 1; +static uint32_t rocksdb_stats_recalc_rate = 0; +static uint32_t rocksdb_debug_manual_compaction_delay = 0; +static uint32_t rocksdb_max_manual_compactions = 0; std::atomic rocksdb_row_lock_deadlocks(0); std::atomic rocksdb_row_lock_wait_timeouts(0); std::atomic rocksdb_snapshot_conflict_errors(0); std::atomic rocksdb_wal_group_syncs(0); +std::atomic rocksdb_manual_compactions_processed(0); +std::atomic rocksdb_manual_compactions_running(0); @@ -600,6 +651,14 @@ static std::unique_ptr rocksdb_db_options = static std::shared_ptr rocksdb_rate_limiter; +/* This enum needs to be kept up to date with rocksdb::TxnDBWritePolicy */ +static const char *write_policy_names[] = {"write_committed", "write_prepared", + "write_unprepared", NullS}; + +static TYPELIB write_policy_typelib = {array_elements(write_policy_names) - 1, + "write_policy_typelib", + write_policy_names, nullptr}; + /* This enum needs to be kept up to date with rocksdb::InfoLogLevel */ static const char *info_log_level_names[] = {"debug_level", "info_level", "warn_level", "error_level", @@ -694,6 +753,14 @@ static int rocksdb_validate_flush_log_at_trx_commit( *static_cast(var_ptr) = static_cast(new_value); return HA_EXIT_SUCCESS; } +static void rocksdb_compact_column_family_stub( + THD *const thd, struct st_mysql_sys_var *const var, void *const var_ptr, + const void *const save) {} + +static int rocksdb_compact_column_family(THD *const thd, + struct st_mysql_sys_var *const var, + void *const var_ptr, + struct st_mysql_value *const value); static const char *index_type_names[] = {"kBinarySearch", "kHashSearch", NullS}; @@ -702,7 +769,8 @@ static TYPELIB index_type_typelib = {array_elements(index_type_names) - 1, nullptr}; const ulong RDB_MAX_LOCK_WAIT_SECONDS = 1024 * 1024 * 1024; -const ulong RDB_MAX_ROW_LOCKS = 1024 * 1024; +const ulong RDB_DEFAULT_MAX_ROW_LOCKS = 1024 * 1024; +const ulong RDB_MAX_ROW_LOCKS = 1024 * 1024 * 1024; const ulong RDB_DEFAULT_BULK_LOAD_SIZE = 1000; const ulong RDB_MAX_BULK_LOAD_SIZE = 1024 * 1024 * 1024; const size_t RDB_DEFAULT_MERGE_BUF_SIZE = 64 * 1024 * 1024; @@ -733,6 +801,11 @@ static MYSQL_THDVAR_ULONG(deadlock_detect_depth, PLUGIN_VAR_RQCMDARG, /*min*/ 2, /*max*/ ULONG_MAX, 0); +static MYSQL_THDVAR_BOOL( + commit_time_batch_for_recovery, PLUGIN_VAR_RQCMDARG, + "TransactionOptions::commit_time_batch_for_recovery for RocksDB", nullptr, + nullptr, FALSE); + static MYSQL_THDVAR_BOOL( trace_sst_api, PLUGIN_VAR_RQCMDARG, "Generate trace output in the log for each call to the SstFileWriter", @@ -744,6 +817,13 @@ static MYSQL_THDVAR_BOOL( "unique_checks and enables rocksdb_commit_in_the_middle.", rocksdb_check_bulk_load, nullptr, FALSE); +static MYSQL_THDVAR_BOOL(bulk_load_allow_sk, PLUGIN_VAR_RQCMDARG, + "Allow bulk loading of sk keys during bulk-load. " + "Can be changed only when bulk load is disabled.", + /* Intentionally reuse unsorted's check function */ + rocksdb_check_bulk_load_allow_unsorted, nullptr, + FALSE); + static MYSQL_THDVAR_BOOL(bulk_load_allow_unsorted, PLUGIN_VAR_RQCMDARG, "Allow unsorted input during bulk-load. " "Can be changed only when bulk load is disabled.", @@ -794,7 +874,7 @@ static MYSQL_THDVAR_BOOL(skip_bloom_filter_on_read, PLUGIN_VAR_RQCMDARG, static MYSQL_THDVAR_ULONG(max_row_locks, PLUGIN_VAR_RQCMDARG, "Maximum number of locks a transaction can have", nullptr, nullptr, - /*default*/ RDB_MAX_ROW_LOCKS, + /*default*/ RDB_DEFAULT_MAX_ROW_LOCKS, /*min*/ 1, /*max*/ RDB_MAX_ROW_LOCKS, 0); @@ -846,6 +926,12 @@ static MYSQL_THDVAR_ULONGLONG( /* min (0ms) */ RDB_MIN_MERGE_TMP_FILE_REMOVAL_DELAY, /* max */ SIZE_T_MAX, 1); +static MYSQL_THDVAR_INT( + manual_compaction_threads, PLUGIN_VAR_RQCMDARG, + "How many rocksdb threads to run for manual compactions", nullptr, nullptr, + /* default rocksdb.dboption max_subcompactions */ 0, + /* min */ 0, /* max */ 128, 0); + static MYSQL_SYSVAR_BOOL( create_if_missing, *reinterpret_cast(&rocksdb_db_options->create_if_missing), @@ -867,6 +953,12 @@ static MYSQL_SYSVAR_BOOL( "DBOptions::manual_wal_flush for RocksDB", nullptr, nullptr, rocksdb_db_options->manual_wal_flush); +static MYSQL_SYSVAR_ENUM(write_policy, rocksdb_write_policy, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "DBOptions::write_policy for RocksDB", nullptr, + nullptr, rocksdb::TxnDBWritePolicy::WRITE_COMMITTED, + &write_policy_typelib); + static MYSQL_SYSVAR_BOOL( create_missing_column_families, *reinterpret_cast( @@ -1077,7 +1169,9 @@ static MYSQL_SYSVAR_INT(table_cache_numshardbits, "DBOptions::table_cache_numshardbits for RocksDB", nullptr, nullptr, rocksdb_db_options->table_cache_numshardbits, - /* min */ 0, /* max */ INT_MAX, 0); + // LRUCache limits this to 19 bits, anything greater + // fails to create a cache and returns a nullptr + /* min */ 0, /* max */ 19, 0); static MYSQL_SYSVAR_UINT64_T(wal_ttl_seconds, rocksdb_db_options->WAL_ttl_seconds, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, @@ -1187,8 +1281,9 @@ static MYSQL_SYSVAR_BOOL( "DBOptions::enable_thread_tracking for RocksDB", nullptr, nullptr, true); static MYSQL_SYSVAR_LONGLONG(block_cache_size, rocksdb_block_cache_size, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "block_cache size for RocksDB", nullptr, nullptr, + PLUGIN_VAR_RQCMDARG, + "block_cache size for RocksDB", + rocksdb_validate_set_block_cache_size, nullptr, /* default */ RDB_DEFAULT_BLOCK_CACHE_SIZE, /* min */ RDB_MIN_BLOCK_CACHE_SIZE, /* max */ LONGLONG_MAX, @@ -1435,6 +1530,18 @@ static MYSQL_SYSVAR_BOOL( "on PK TTL data. This variable is a no-op in non-debug builds.", nullptr, nullptr, FALSE); +static MYSQL_SYSVAR_UINT( + max_manual_compactions, rocksdb_max_manual_compactions, PLUGIN_VAR_RQCMDARG, + "Maximum number of pending + ongoing number of manual compactions.", + nullptr, nullptr, /* default */ 10, /* min */ 0, /* max */ UINT_MAX, 0); + +static MYSQL_SYSVAR_UINT( + debug_manual_compaction_delay, rocksdb_debug_manual_compaction_delay, + PLUGIN_VAR_RQCMDARG, + "For debugging purposes only. Sleeping specified seconds " + "for simulating long running compactions.", + nullptr, nullptr, 0, /* min */ 0, /* max */ UINT_MAX, 0); + static MYSQL_SYSVAR_BOOL( reset_stats, rocksdb_reset_stats, PLUGIN_VAR_RQCMDARG, "Reset the RocksDB internal statistics without restarting the DB.", nullptr, @@ -1597,6 +1704,13 @@ static MYSQL_SYSVAR_UINT( RDB_DEFAULT_TBL_STATS_SAMPLE_PCT, /* everything */ 0, /* max */ RDB_TBL_STATS_SAMPLE_PCT_MAX, 0); +static MYSQL_SYSVAR_UINT( + stats_recalc_rate, rocksdb_stats_recalc_rate, PLUGIN_VAR_RQCMDARG, + "The number of indexes per second to recalculate statistics for. 0 to " + "disable background recalculation.", + nullptr, nullptr, 0 /* default value */, 0 /* min value */, + UINT_MAX /* max value */, 0); + static MYSQL_SYSVAR_BOOL( large_prefix, rocksdb_large_prefix, PLUGIN_VAR_RQCMDARG, "Support large index prefix length of 3072 bytes. If off, the maximum " @@ -1610,16 +1724,25 @@ static MYSQL_SYSVAR_BOOL( "detected.", nullptr, nullptr, FALSE); +static MYSQL_SYSVAR_BOOL(error_on_suboptimal_collation, + rocksdb_error_on_suboptimal_collation, + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, + "Raise an error instead of warning if a sub-optimal " + "collation is used", + nullptr, nullptr, TRUE); + static const int ROCKSDB_ASSUMED_KEY_VALUE_DISK_SIZE = 100; static struct st_mysql_sys_var *rocksdb_system_variables[] = { MYSQL_SYSVAR(lock_wait_timeout), MYSQL_SYSVAR(deadlock_detect), MYSQL_SYSVAR(deadlock_detect_depth), + MYSQL_SYSVAR(commit_time_batch_for_recovery), MYSQL_SYSVAR(max_row_locks), MYSQL_SYSVAR(write_batch_max_bytes), MYSQL_SYSVAR(lock_scanned_rows), MYSQL_SYSVAR(bulk_load), + MYSQL_SYSVAR(bulk_load_allow_sk), MYSQL_SYSVAR(bulk_load_allow_unsorted), MYSQL_SYSVAR(skip_unique_check_tables), MYSQL_SYSVAR(trace_sst_api), @@ -1637,6 +1760,7 @@ static struct st_mysql_sys_var *rocksdb_system_variables[] = { MYSQL_SYSVAR(create_if_missing), MYSQL_SYSVAR(two_write_queues), MYSQL_SYSVAR(manual_wal_flush), + MYSQL_SYSVAR(write_policy), MYSQL_SYSVAR(create_missing_column_families), MYSQL_SYSVAR(error_if_exists), MYSQL_SYSVAR(paranoid_checks), @@ -1754,6 +1878,11 @@ static struct st_mysql_sys_var *rocksdb_system_variables[] = { MYSQL_SYSVAR(large_prefix), MYSQL_SYSVAR(allow_to_start_after_corruption), MYSQL_SYSVAR(git_hash), + MYSQL_SYSVAR(error_on_suboptimal_collation), + MYSQL_SYSVAR(stats_recalc_rate), + MYSQL_SYSVAR(debug_manual_compaction_delay), + MYSQL_SYSVAR(max_manual_compactions), + MYSQL_SYSVAR(manual_compaction_threads), nullptr}; static rocksdb::WriteOptions @@ -1768,6 +1897,50 @@ rdb_get_rocksdb_write_options(my_core::THD *const thd) { return opt; } +static int rocksdb_compact_column_family(THD *const thd, + struct st_mysql_sys_var *const var, + void *const var_ptr, + struct st_mysql_value *const value) { + char buff[STRING_BUFFER_USUAL_SIZE]; + int len = sizeof(buff); + + DBUG_ASSERT(value != nullptr); + + if (const char *const cf = value->val_str(value, buff, &len)) { + auto cfh = cf_manager.get_cf(cf); + if (cfh != nullptr && rdb != nullptr) { + int mc_id = rdb_mc_thread.request_manual_compaction( + cfh, nullptr, nullptr, THDVAR(thd, manual_compaction_threads)); + if (mc_id == -1) { + my_error(ER_INTERNAL_ERROR, MYF(0), + "Can't schedule more manual compactions. " + "Increase rocksdb_max_manual_compactions or stop issuing " + "more manual compactions."); + return HA_EXIT_FAILURE; + } else if (mc_id < 0) { + return HA_EXIT_FAILURE; + } + // NO_LINT_DEBUG + sql_print_information("RocksDB: Manual compaction of column family: %s\n", + cf); + // Checking thd state every short cycle (100ms). This is for allowing to + // exiting this function without waiting for CompactRange to finish. + do { + my_sleep(100000); + } while (!thd->killed && + !rdb_mc_thread.is_manual_compaction_finished(mc_id)); + + if (thd->killed) { + // This cancels if requested compaction state is INITED. + // TODO(yoshinorim): Cancel running compaction as well once + // it is supported in RocksDB. + rdb_mc_thread.clear_manual_compaction_request(mc_id, true); + } + } + } + return HA_EXIT_SUCCESS; +} + /////////////////////////////////////////////////////////////////////////////////////////// /** @@ -1887,8 +2060,6 @@ protected: bool m_is_two_phase = false; private: - /* Number of RockDB savepoints taken */ - int m_n_savepoints; /* Number of write operations this transaction had when we took the last savepoint (the idea is not to take another savepoint if we haven't made @@ -1897,9 +2068,9 @@ private: ulonglong m_writes_at_last_savepoint; protected: - THD *m_thd = nullptr; - rocksdb::ReadOptions m_read_opts; +protected: + THD *m_thd = nullptr; static std::multiset s_tx_list; static mysql_mutex_t s_tx_list_mutex; @@ -1957,6 +2128,7 @@ protected: } public: + rocksdb::ReadOptions m_read_opts; const char *m_mysql_log_file_name; my_off_t m_mysql_log_offset; #ifdef MARIAROCKS_NOT_YET @@ -1967,6 +2139,7 @@ protected: String m_detailed_error; int64_t m_snapshot_timestamp = 0; bool m_ddl_transaction; + std::shared_ptr m_explicit_snapshot; /* Tracks the number of tables in use through external_lock. @@ -2032,7 +2205,7 @@ protected: if (s.IsDeadlock()) { my_core::thd_mark_transaction_to_rollback(thd, - false /* just statement */); + true /* whole transaction */); m_detailed_error = String(); table_handler->m_deadlock_counter.inc(); rocksdb_row_lock_deadlocks++; @@ -2049,7 +2222,7 @@ protected: } m_detailed_error = String(" (snapshot conflict)", system_charset_info); table_handler->m_deadlock_counter.inc(); - return HA_ERR_LOCK_DEADLOCK; + return HA_ERR_ROCKSDB_STATUS_BUSY; } if (s.IsIOError() || s.IsCorruption()) { @@ -2462,7 +2635,6 @@ public: entire transaction. */ do_set_savepoint(); - m_n_savepoints= 1; m_writes_at_last_savepoint= m_write_count; } @@ -2479,7 +2651,6 @@ public: { do_set_savepoint(); m_writes_at_last_savepoint= m_write_count; - m_n_savepoints++; } } @@ -2490,10 +2661,14 @@ public: void rollback_to_stmt_savepoint() { if (m_writes_at_last_savepoint != m_write_count) { do_rollback_to_savepoint(); - if (!--m_n_savepoints) { - do_set_savepoint(); - m_n_savepoints= 1; - } + /* + RollbackToSavePoint "removes the most recent SetSavePoint()", so + we need to set it again so that next statement can roll back to this + stage. + It's ok to do it here at statement end (instead of doing it at next + statement start) because setting a savepoint is cheap. + */ + do_set_savepoint(); m_writes_at_last_savepoint= m_write_count; } } @@ -2666,6 +2841,17 @@ public: void acquire_snapshot(bool acquire_now) override { if (m_read_opts.snapshot == nullptr) { +#ifdef MARIAROCKS_NOT_YET + const auto thd_ss = std::static_pointer_cast( + m_thd->get_explicit_snapshot()); + if (thd_ss) { + m_explicit_snapshot = thd_ss; + } + if (m_explicit_snapshot) { + auto snapshot = m_explicit_snapshot->get_snapshot()->snapshot(); + snapshot_created(snapshot); + } else +#endif if (is_tx_read_only()) { snapshot_created(rdb->GetSnapshot()); } else if (acquire_now) { @@ -2683,6 +2869,12 @@ public: if (m_read_opts.snapshot != nullptr) { m_snapshot_timestamp = 0; +#ifdef MARIAROCKS_NOT_YET + if (m_explicit_snapshot) { + m_explicit_snapshot.reset(); + need_clear = false; + } else +#endif if (is_tx_read_only()) { rdb->ReleaseSnapshot(m_read_opts.snapshot); need_clear = false; @@ -2792,6 +2984,10 @@ public: tx_opts.lock_timeout = rdb_convert_sec_to_ms(m_timeout_sec); tx_opts.deadlock_detect = THDVAR(m_thd, deadlock_detect); tx_opts.deadlock_detect_depth = THDVAR(m_thd, deadlock_detect_depth); + // If this variable is set, this will write commit time write batch + // information on recovery or memtable flush. + tx_opts.use_only_the_last_commit_time_batch_for_recovery = + THDVAR(m_thd, commit_time_batch_for_recovery); tx_opts.max_write_batch_size = THDVAR(m_thd, write_batch_max_bytes); write_opts.sync = (rocksdb_flush_log_at_trx_commit == FLUSH_LOG_SYNC); @@ -2886,7 +3082,7 @@ public: /* This is a rocksdb write batch. This class doesn't hold or wait on any transaction locks (skips rocksdb transaction API) thus giving better - performance. The commit is done through rdb->GetBaseDB()->Commit(). + performance. Currently this is only used for replication threads which are guaranteed to be non-conflicting. Any further usage of this class should completely @@ -2908,6 +3104,8 @@ private: bool commit_no_binlog() override { bool res = false; rocksdb::Status s; + rocksdb::TransactionDBWriteOptimizations optimize; + optimize.skip_concurrency_control = true; s = merge_auto_incr_map(m_batch->GetWriteBatch()); if (!s.ok()) { @@ -2918,7 +3116,7 @@ private: release_snapshot(); - s = rdb->GetBaseDB()->Write(write_opts, m_batch->GetWriteBatch()); + s = rdb->Write(write_opts, optimize, m_batch->GetWriteBatch()); if (!s.ok()) { rdb_handle_io_error(s, RDB_IO_ERROR_TX_COMMIT); res = true; @@ -2936,7 +3134,6 @@ error: return res; } -protected: /* Implementations of do_*savepoint based on rocksdB::WriteBatch savepoints */ void do_set_savepoint() override { m_batch->SetSavePoint(); @@ -2946,6 +3143,7 @@ protected: m_batch->RollbackToSavePoint(); } + public: bool is_writebatch_trx() const override { return true; } @@ -3033,6 +3231,13 @@ public: get_for_update(rocksdb::ColumnFamilyHandle *const column_family, const rocksdb::Slice &key, rocksdb::PinnableSlice *const value, bool exclusive) override { + if (value == nullptr) { + rocksdb::PinnableSlice pin_val; + rocksdb::Status s = get(column_family, key, &pin_val); + pin_val.Reset(); + return s; + } + return get(column_family, key, value); } @@ -3564,6 +3769,7 @@ static int rocksdb_commit(handlerton* hton, THD* thd, bool commit_tx) We get here when committing a statement within a transaction. */ tx->make_stmt_savepoint_permanent(); + tx->make_stmt_savepoint_permanent(); } if (my_core::thd_tx_isolation(thd) <= ISO_READ_COMMITTED) { @@ -3752,6 +3958,7 @@ private: if (!path_entry.path.empty() && !path_entry.limit_exceeded) { auto deadlocking_txn = *(path_entry.path.end() - 1); deadlock_info.victim_trx_id = deadlocking_txn.m_txn_id; + deadlock_info.deadlock_time = path_entry.deadlock_time; } return deadlock_info; } @@ -3799,16 +4006,18 @@ private: path_data += "\n*** DEADLOCK PATH\n" "=========================================\n"; const auto dl_info = get_dl_path_trx_info(path_entry); + const auto deadlock_time = dl_info.deadlock_time; for (auto it = dl_info.path.begin(); it != dl_info.path.end(); it++) { const auto trx_info = *it; path_data += format_string( + "TIMESTAMP: %" PRId64 "\n" "TRANSACTION ID: %u\n" "COLUMN FAMILY NAME: %s\n" "WAITING KEY: %s\n" "LOCK TYPE: %s\n" "INDEX NAME: %s\n" "TABLE NAME: %s\n", - trx_info.trx_id, trx_info.cf_name.c_str(), + deadlock_time, trx_info.trx_id, trx_info.cf_name.c_str(), trx_info.waiting_key.c_str(), trx_info.exclusive_lock ? "EXCLUSIVE" : "SHARED", trx_info.index_name.c_str(), trx_info.table_name.c_str()); @@ -4082,7 +4291,7 @@ static bool rocksdb_show_status(handlerton *const hton, THD *const thd, (ulonglong)internal_cache_count * kDefaultInternalCacheSize); str.append(buf); res |= print_stats(thd, "MEMORY_STATS", "rocksdb", str, stat_print); -#ifdef MARIAROCKS_NOT_YET + /* Show the background thread status */ std::vector thread_list; rocksdb::Status s = rdb->GetEnv()->GetThreadList(&thread_list); @@ -4119,8 +4328,27 @@ static bool rocksdb_show_status(handlerton *const hton, THD *const thd, str, stat_print); } } + +#ifdef MARIAROCKS_NOT_YET + /* Explicit snapshot information */ + str.clear(); + { + std::lock_guard lock(explicit_snapshot_mutex); + for (const auto &elem : explicit_snapshots) { + const auto &ss = elem.second.lock(); + DBUG_ASSERT(ss != nullptr); + const auto &info = ss->ss_info; + str += "\nSnapshot ID: " + std::to_string(info.snapshot_id) + + "\nBinlog File: " + info.binlog_file + + "\nBinlog Pos: " + std::to_string(info.binlog_pos) + + "\nGtid Executed: " + info.gtid_executed + "\n"; + } + } #endif + if (!str.empty()) { + res |= print_stats(thd, "EXPLICIT_SNAPSHOTS", "rocksdb", str, stat_print); + } #ifdef MARIAROCKS_NOT_YET } else if (stat_type == HA_ENGINE_TRX) { /* Handle the SHOW ENGINE ROCKSDB TRANSACTION STATUS command */ @@ -4143,6 +4371,50 @@ static inline void rocksdb_register_tx(handlerton *const hton, THD *const thd, static const char *ha_rocksdb_exts[] = {NullS}; +#ifdef MARIAROCKS_NOT_YET +static bool rocksdb_explicit_snapshot( + handlerton *const /* hton */, /*!< in: RocksDB handlerton */ + THD *const thd, /*!< in: MySQL thread handle */ + snapshot_info_st *ss_info) /*!< out: Snapshot information */ +{ + switch (ss_info->op) { + case snapshot_operation::SNAPSHOT_CREATE: { + if (mysql_bin_log_is_open()) { + mysql_bin_log_lock_commits(ss_info); + } + auto s = Rdb_explicit_snapshot::create(ss_info, rdb, rdb->GetSnapshot()); + if (mysql_bin_log_is_open()) { + mysql_bin_log_unlock_commits(ss_info); + } + + thd->set_explicit_snapshot(s); + return s == nullptr; + } + case snapshot_operation::SNAPSHOT_ATTACH: { + auto s = Rdb_explicit_snapshot::get(ss_info->snapshot_id); + if (!s) { + return true; + } + *ss_info = s->ss_info; + thd->set_explicit_snapshot(s); + return false; + } + case snapshot_operation::SNAPSHOT_RELEASE: { + if (!thd->get_explicit_snapshot()) { + return true; + } + *ss_info = thd->get_explicit_snapshot()->ss_info; + thd->set_explicit_snapshot(nullptr); + return false; + } + default: + DBUG_ASSERT(false); + return true; + } + return true; +} +#endif + /* Supporting START TRANSACTION WITH CONSISTENT [ROCKSDB] SNAPSHOT @@ -4165,10 +4437,15 @@ static const char *ha_rocksdb_exts[] = {NullS}; InnoDB and RocksDB transactions. */ static int rocksdb_start_tx_and_assign_read_view( - handlerton *const hton, /*!< in: RocksDB handlerton */ - THD* thd) /*!< in: MySQL thread handle of the - user for whom the transaction should - be committed */ + handlerton *const hton, /*!< in: RocksDB handlerton */ + THD *const thd /*!< in: MySQL thread handle of the + user for whom the transaction should + be committed */ +) +#ifdef MARIAROCKS_NOT_YET + snapshot_info_st *ss_info) /*!< in/out: Snapshot info like binlog file, pos, + gtid executed and snapshot ID */ +#endif { ulong const tx_isolation = my_core::thd_tx_isolation(thd); @@ -4176,14 +4453,25 @@ static int rocksdb_start_tx_and_assign_read_view( my_error(ER_ISOLATION_LEVEL_WITH_CONSISTENT_SNAPSHOT, MYF(0)); return HA_EXIT_FAILURE; } + +#ifdef MARIADB_NOT_YET + if (ss_info) { + if (mysql_bin_log_is_open()) { + mysql_bin_log_lock_commits(ss_info); + } else { + return HA_EXIT_FAILURE; + } +#endif + /* MariaDB: there is no need to call mysql_bin_log_lock_commits and then unlock back. SQL layer calls start_consistent_snapshot() for all engines, including the binlog under LOCK_commit_ordered mutex. + The mutex prevents binlog commits from happening (right?) while the storage engine(s) allocate read snapshots. That way, each storage engine is - synchronized with current binlog position. + synchronized with current binlog position. */ mysql_mutex_assert_owner(&LOCK_commit_ordered); @@ -4195,9 +4483,106 @@ static int rocksdb_start_tx_and_assign_read_view( rocksdb_register_tx(hton, thd, tx); tx->acquire_snapshot(true); +#ifdef MARIADB_NOT_YET + if (ss_info) { + mysql_bin_log_unlock_commits(ss_info); + } +#endif return HA_EXIT_SUCCESS; } +#ifdef MARIADB_NOT_YET +static int rocksdb_start_tx_with_shared_read_view( + handlerton *const hton, /*!< in: RocksDB handlerton */ + THD *const thd) /*!< in: MySQL thread handle of the + user for whom the transaction should + be committed */ +#ifdef MARIADB_NOT_YET + snapshot_info_st *ss_info) /*!< out: Snapshot info like binlog file, pos, + gtid executed and snapshot ID */ +#endif +{ + DBUG_ASSERT(thd != nullptr); + + int error = HA_EXIT_SUCCESS; + + ulong const tx_isolation = my_core::thd_tx_isolation(thd); + if (tx_isolation != ISO_REPEATABLE_READ) { + my_error(ER_ISOLATION_LEVEL_WITH_CONSISTENT_SNAPSHOT, MYF(0)); + return HA_EXIT_FAILURE; + } + + Rdb_transaction *tx = nullptr; +#ifdef MARIADB_NOT_YET + std::shared_ptr explicit_snapshot; + const auto op = ss_info->op; + + DBUG_ASSERT(op == snapshot_operation::SNAPSHOT_CREATE || + op == snapshot_operation::SNAPSHOT_ATTACH); + + // case: if binlogs are available get binlog file/pos and gtid info + if (op == snapshot_operation::SNAPSHOT_CREATE && mysql_bin_log_is_open()) { + mysql_bin_log_lock_commits(ss_info); + } + + if (op == snapshot_operation::SNAPSHOT_ATTACH) { + explicit_snapshot = Rdb_explicit_snapshot::get(ss_info->snapshot_id); + if (!explicit_snapshot) { + my_printf_error(ER_UNKNOWN_ERROR, "Snapshot %llu does not exist", MYF(0), + ss_info->snapshot_id); + error = HA_EXIT_FAILURE; + } + } +#endif + + // case: all good till now + if (error == HA_EXIT_SUCCESS) { + tx = get_or_create_tx(thd); + Rdb_perf_context_guard guard(tx, rocksdb_perf_context_level(thd)); + +#ifdef MARIADB_NOT_YET + if (explicit_snapshot) { + tx->m_explicit_snapshot = explicit_snapshot; + } +#endif + + DBUG_ASSERT(!tx->has_snapshot()); + tx->set_tx_read_only(true); + rocksdb_register_tx(hton, thd, tx); + tx->acquire_snapshot(true); + +#ifdef MARIADB_NOT_YET + // case: an explicit snapshot was not assigned to this transaction + if (!tx->m_explicit_snapshot) { + tx->m_explicit_snapshot = + Rdb_explicit_snapshot::create(ss_info, rdb, tx->m_read_opts.snapshot); + if (!tx->m_explicit_snapshot) { + my_printf_error(ER_UNKNOWN_ERROR, "Could not create snapshot", MYF(0)); + error = HA_EXIT_FAILURE; + } + } +#endif + } + +#ifdef MARIADB_NOT_YET + // case: unlock the binlog + if (op == snapshot_operation::SNAPSHOT_CREATE && mysql_bin_log_is_open()) { + mysql_bin_log_unlock_commits(ss_info); + } + + DBUG_ASSERT(error == HA_EXIT_FAILURE || tx->m_explicit_snapshot); + + // copy over the snapshot details to pass to the upper layers + if (tx->m_explicit_snapshot) { + *ss_info = tx->m_explicit_snapshot->ss_info; + ss_info->op = op; + } +#endif + + return error; +} +#endif + /* Dummy SAVEPOINT support. This is needed for long running transactions * like mysqldump (https://bugs.mysql.com/bug.php?id=71017). * Current SAVEPOINT does not correctly handle ROLLBACK and does not return @@ -4422,9 +4807,11 @@ static int rocksdb_init_func(void *const p) { rdb_bg_thread.init(rdb_signal_bg_psi_mutex_key, rdb_signal_bg_psi_cond_key); rdb_drop_idx_thread.init(rdb_signal_drop_idx_psi_mutex_key, rdb_signal_drop_idx_psi_cond_key); + rdb_mc_thread.init(rdb_signal_mc_psi_mutex_key, rdb_signal_mc_psi_cond_key); #else rdb_bg_thread.init(); rdb_drop_idx_thread.init(); + rdb_mc_thread.init(); #endif mysql_mutex_init(rdb_collation_data_mutex_key, &rdb_collation_data_mutex, MY_MUTEX_INIT_FAST); @@ -4445,6 +4832,8 @@ static int rocksdb_init_func(void *const p) { mysql_mutex_init(rdb_sysvars_psi_mutex_key, &rdb_sysvars_mutex, MY_MUTEX_INIT_FAST); + mysql_mutex_init(rdb_block_cache_resize_mutex_key, + &rdb_block_cache_resize_mutex, MY_MUTEX_INIT_FAST); Rdb_transaction::init_mutex(); rocksdb_hton->state = SHOW_OPTION_YES; @@ -4465,8 +4854,14 @@ static int rocksdb_init_func(void *const p) { rocksdb_hton->rollback = rocksdb_rollback; rocksdb_hton->show_status = rocksdb_show_status; +#ifdef MARIADB_NOT_YET + rocksdb_hton->explicit_snapshot = rocksdb_explicit_snapshot; +#endif rocksdb_hton->start_consistent_snapshot = rocksdb_start_tx_and_assign_read_view; +#ifdef MARIADB_NOT_YET + rocksdb_hton->start_shared_snapshot = rocksdb_start_tx_with_shared_read_view; +#endif rocksdb_hton->savepoint_set = rocksdb_savepoint; rocksdb_hton->savepoint_rollback = rocksdb_rollback_to_savepoint; rocksdb_hton->savepoint_rollback_can_release_mdl = @@ -4535,6 +4930,35 @@ static int rocksdb_init_func(void *const p) { DBUG_RETURN(HA_EXIT_FAILURE); } + // Check whether the filesystem backing rocksdb_datadir allows O_DIRECT + if (rocksdb_db_options->use_direct_reads) { + rocksdb::EnvOptions soptions; + rocksdb::Status check_status; + rocksdb::Env *const env = rocksdb_db_options->env; + + std::string fname = format_string("%s/DIRECT_CHECK", rocksdb_datadir); + if (env->FileExists(fname).ok()) { + std::unique_ptr file; + soptions.use_direct_reads = true; + check_status = env->NewSequentialFile(fname, &file, soptions); + } else { + std::unique_ptr file; + soptions.use_direct_writes = true; + check_status = env->ReopenWritableFile(fname, &file, soptions); + if (file != nullptr) { + file->Close(); + } + env->DeleteFile(fname); + } + + if (!check_status.ok()) { + sql_print_error("RocksDB: Unable to use direct io in rocksdb-datadir:" + "(%s)", check_status.getState()); + rdb_open_tables.free_hash(); + DBUG_RETURN(HA_EXIT_FAILURE); + } + } + if (rocksdb_db_options->allow_mmap_writes && rocksdb_db_options->use_direct_io_for_flush_and_compaction) { // See above comment for allow_mmap_reads. (NO_LINT_DEBUG) @@ -4687,8 +5111,10 @@ static int rocksdb_init_func(void *const p) { cf_options_map->get_defaults()); rocksdb::TransactionDBOptions tx_db_options; - tx_db_options.transaction_lock_timeout = 2; // 2 seconds + tx_db_options.transaction_lock_timeout = 2000; // 2 seconds tx_db_options.custom_mutex_factory = std::make_shared(); + tx_db_options.write_policy = + static_cast(rocksdb_write_policy); status = check_rocksdb_options_compatibility(rocksdb_datadir, main_opts, cf_descr); @@ -4710,7 +5136,7 @@ static int rocksdb_init_func(void *const p) { } cf_manager.init(std::move(cf_options_map), &cf_handles); - if (dict_manager.init(rdb->GetBaseDB(), &cf_manager)) { + if (dict_manager.init(rdb, &cf_manager)) { // NO_LINT_DEBUG sql_print_error("RocksDB: Failed to initialize data dictionary."); DBUG_RETURN(HA_EXIT_FAILURE); @@ -4771,6 +5197,21 @@ static int rocksdb_init_func(void *const p) { DBUG_RETURN(HA_EXIT_FAILURE); } + err = rdb_mc_thread.create_thread(MANUAL_COMPACTION_THREAD_NAME +#ifdef HAVE_PSI_INTERFACE + , + rdb_mc_psi_thread_key +#endif + ); + if (err != 0) { + // NO_LINT_DEBUG + sql_print_error( + "RocksDB: Couldn't start the manual compaction thread: (errno=%d)", + err); + rdb_open_tables.free_hash(); + DBUG_RETURN(HA_EXIT_FAILURE); + } + rdb_set_collation_exception_list(rocksdb_strict_collation_exceptions); if (rocksdb_pause_background_work) { @@ -4877,6 +5318,16 @@ static int rocksdb_done_func(void *const p) { sql_print_error("RocksDB: Couldn't stop the index thread: (errno=%d)", err); } + // signal the manual compaction thread to stop + rdb_mc_thread.signal(true); + // Wait for the manual compaction thread to finish. + err = rdb_mc_thread.join(); + if (err != 0) { + // NO_LINT_DEBUG + sql_print_error( + "RocksDB: Couldn't stop the manual compaction thread: (errno=%d)", err); + } + if (rdb_open_tables.m_hash.size()) { // Looks like we are getting unloaded and yet we have some open tables // left behind. @@ -4933,6 +5384,7 @@ static int rocksdb_done_func(void *const p) { rdb_open_tables.m_hash.~Rdb_table_set(); mysql_mutex_destroy(&rdb_open_tables.m_mutex); mysql_mutex_destroy(&rdb_sysvars_mutex); + mysql_mutex_destroy(&rdb_block_cache_resize_mutex); delete rdb_collation_exceptions; @@ -5348,7 +5800,6 @@ longlong ha_rocksdb::update_hidden_pk_val() { /* Get the id of the hidden pk id from m_last_rowkey */ int ha_rocksdb::read_hidden_pk_id_from_rowkey(longlong *const hidden_pk_id) { - DBUG_ASSERT(hidden_pk_id != nullptr); DBUG_ASSERT(table != nullptr); DBUG_ASSERT(has_hidden_pk(table)); @@ -5404,14 +5855,14 @@ ha_rocksdb::ha_rocksdb(my_core::handlerton *const hton, my_core::TABLE_SHARE *const table_arg) : handler(hton, table_arg), m_table_handler(nullptr), m_scan_it(nullptr), m_scan_it_skips_bloom(false), m_scan_it_snapshot(nullptr), + m_scan_it_lower_bound(nullptr), m_scan_it_upper_bound(nullptr), m_tbl_def(nullptr), m_pk_descr(nullptr), m_key_descr_arr(nullptr), m_pk_can_be_decoded(false), m_maybe_unpack_info(false), m_pk_tuple(nullptr), m_pk_packed_tuple(nullptr), m_sk_packed_tuple(nullptr), m_end_key_packed_tuple(nullptr), m_sk_match_prefix(nullptr), m_sk_match_prefix_buf(nullptr), m_sk_packed_tuple_old(nullptr), m_dup_sk_packed_tuple(nullptr), - m_dup_sk_packed_tuple_old(nullptr), m_eq_cond_lower_bound(nullptr), - m_eq_cond_upper_bound(nullptr), m_pack_buffer(nullptr), + m_dup_sk_packed_tuple_old(nullptr), m_pack_buffer(nullptr), m_lock_rows(RDB_LOCK_NONE), m_keyread_only(FALSE), m_encoder_arr(nullptr), m_row_checksums_checked(0), m_in_rpl_delete_rows(false), m_in_rpl_update_rows(false), m_force_skip_unique_check(false) {} @@ -5950,9 +6401,6 @@ int ha_rocksdb::convert_field_from_storage_format( int ha_rocksdb::convert_record_from_storage_format( const rocksdb::Slice *const key, const rocksdb::Slice *const value, uchar *const buf) { - DBUG_ASSERT(key != nullptr); - DBUG_ASSERT(buf != nullptr); - Rdb_string_reader reader(value); /* @@ -6196,7 +6644,6 @@ int ha_rocksdb::alloc_key_buffers(const TABLE *const table_arg, DBUG_ENTER_FUNC(); DBUG_ASSERT(m_pk_tuple == nullptr); - DBUG_ASSERT(tbl_def_arg != nullptr); std::shared_ptr *const kd_arr = tbl_def_arg->m_key_descr_arr; @@ -6248,9 +6695,9 @@ int ha_rocksdb::alloc_key_buffers(const TABLE *const table_arg, m_pack_buffer = reinterpret_cast(my_malloc(max_packed_sk_len, MYF(0))); - m_eq_cond_upper_bound = + m_scan_it_lower_bound = reinterpret_cast(my_malloc(max_packed_sk_len, MYF(0))); - m_eq_cond_lower_bound = + m_scan_it_upper_bound = reinterpret_cast(my_malloc(max_packed_sk_len, MYF(0))); /* @@ -6267,7 +6714,7 @@ int ha_rocksdb::alloc_key_buffers(const TABLE *const table_arg, if (m_pk_tuple == nullptr || m_pk_packed_tuple == nullptr || m_sk_packed_tuple == nullptr || m_sk_packed_tuple_old == nullptr || m_end_key_packed_tuple == nullptr || m_pack_buffer == nullptr || - m_eq_cond_upper_bound == nullptr || m_eq_cond_lower_bound == nullptr || + m_scan_it_upper_bound == nullptr || m_scan_it_lower_bound == nullptr || (alloc_alter_buffers && (m_dup_sk_packed_tuple == nullptr || m_dup_sk_packed_tuple_old == nullptr))) { // One or more of the above allocations failed. Clean up and exit @@ -6307,11 +6754,11 @@ void ha_rocksdb::free_key_buffers() { my_free(m_dup_sk_packed_tuple_old); m_dup_sk_packed_tuple_old = nullptr; - my_free(m_eq_cond_upper_bound); - m_eq_cond_upper_bound = nullptr; + my_free(m_scan_it_lower_bound); + m_scan_it_lower_bound = nullptr; - my_free(m_eq_cond_lower_bound); - m_eq_cond_lower_bound = nullptr; + my_free(m_scan_it_upper_bound); + m_scan_it_upper_bound = nullptr; } #ifdef MARIAROCKS_NOT_YET @@ -6569,9 +7016,8 @@ bool ha_rocksdb::get_error_message(const int error, String *const buf) { static_assert(HA_ERR_ROCKSDB_LAST > HA_ERR_LAST, "HA_ERR_ROCKSDB_LAST > HA_ERR_LAST"); - DBUG_ASSERT(buf != nullptr); - - if (error == HA_ERR_LOCK_WAIT_TIMEOUT || error == HA_ERR_LOCK_DEADLOCK) { + if (error == HA_ERR_LOCK_WAIT_TIMEOUT || error == HA_ERR_LOCK_DEADLOCK || + error == HA_ERR_ROCKSDB_STATUS_BUSY) { Rdb_transaction *const tx = get_tx_from_thd(ha_thd()); DBUG_ASSERT(tx != nullptr); buf->append(tx->m_detailed_error); @@ -6653,10 +7099,10 @@ int ha_rocksdb::rdb_error_to_mysql(const rocksdb::Status &s, } if (opt_msg) { - my_error(ER_RDB_STATUS_MSG, MYF(0), opt_msg, s.code(), - s.ToString().c_str()); + std::string concatenated_error = s.ToString() + " (" + std::string(opt_msg) + ")"; + my_error(ER_GET_ERRMSG, MYF(0), s.code(), concatenated_error.c_str(), rocksdb_hton_name); } else { - my_error(ER_RDB_STATUS_GENERAL, MYF(0), s.code(), s.ToString().c_str()); + my_error(ER_GET_ERRMSG, MYF(0), s.code(), s.ToString().c_str(), rocksdb_hton_name); } return err; @@ -6725,7 +7171,6 @@ int ha_rocksdb::create_key_defs( /* = nullptr */) const { DBUG_ENTER_FUNC(); - DBUG_ASSERT(table_arg != nullptr); DBUG_ASSERT(table_arg->s != nullptr); uint i; @@ -6796,9 +7241,7 @@ int ha_rocksdb::create_cfs( std::array *const cfs) const { DBUG_ENTER_FUNC(); - DBUG_ASSERT(table_arg != nullptr); DBUG_ASSERT(table_arg->s != nullptr); - DBUG_ASSERT(tbl_def_arg != nullptr); char tablename_sys[NAME_LEN + 1]; bool tsys_set= false; @@ -6904,10 +7347,6 @@ int ha_rocksdb::create_inplace_key_defs( const std::array &cfs) const { DBUG_ENTER_FUNC(); - DBUG_ASSERT(table_arg != nullptr); - DBUG_ASSERT(tbl_def_arg != nullptr); - DBUG_ASSERT(old_tbl_def_arg != nullptr); - std::shared_ptr *const old_key_descr = old_tbl_def_arg->m_key_descr_arr; std::shared_ptr *const new_key_descr = @@ -6975,11 +7414,6 @@ std::unordered_map ha_rocksdb::get_old_key_positions( const Rdb_tbl_def *const old_tbl_def_arg) const { DBUG_ENTER_FUNC(); - DBUG_ASSERT(table_arg != nullptr); - DBUG_ASSERT(old_table_arg != nullptr); - DBUG_ASSERT(tbl_def_arg != nullptr); - DBUG_ASSERT(old_tbl_def_arg != nullptr); - std::shared_ptr *const old_key_descr = old_tbl_def_arg->m_key_descr_arr; std::unordered_map old_key_pos; @@ -7045,9 +7479,6 @@ int ha_rocksdb::compare_keys(const KEY *const old_key, const KEY *const new_key) const { DBUG_ENTER_FUNC(); - DBUG_ASSERT(old_key != nullptr); - DBUG_ASSERT(new_key != nullptr); - /* Check index name. */ if (strcmp(old_key->name.str, new_key->name.str) != 0) { DBUG_RETURN(HA_EXIT_FAILURE); @@ -7078,9 +7509,6 @@ int ha_rocksdb::compare_key_parts(const KEY *const old_key, const KEY *const new_key) const { DBUG_ENTER_FUNC(); - DBUG_ASSERT(old_key != nullptr); - DBUG_ASSERT(new_key != nullptr); - /* Skip if key parts do not match, as it is a different key */ if (new_key->user_defined_key_parts != old_key->user_defined_key_parts) { DBUG_RETURN(HA_EXIT_FAILURE); @@ -7125,7 +7553,6 @@ int ha_rocksdb::create_key_def(const TABLE *const table_arg, const uint &i, const struct key_def_cf_info &cf_info) const { DBUG_ENTER_FUNC(); - DBUG_ASSERT(new_key_def != nullptr); DBUG_ASSERT(*new_key_def == nullptr); uint64 ttl_duration = 0; @@ -7212,8 +7639,6 @@ int ha_rocksdb::create_key_def(const TABLE *const table_arg, const uint &i, int rdb_normalize_tablename(const std::string &tablename, std::string *const strbuf) { - DBUG_ASSERT(strbuf != nullptr); - if (tablename.size() < 2 || tablename[0] != '.' || (tablename[1] != FN_LIBCHAR && tablename[1] != FN_LIBCHAR2)) { DBUG_ASSERT(0); // We were not passed table name? @@ -7537,8 +7962,6 @@ int ha_rocksdb::read_key_exact(const Rdb_key_def &kd, const bool &full_key_match, const rocksdb::Slice &key_slice, const int64_t ttl_filter_ts) { - DBUG_ASSERT(iter != nullptr); - /* We are looking for the first record such that index_tuple= lookup_tuple. @@ -7746,8 +8169,6 @@ int ha_rocksdb::calc_eq_cond_len(const Rdb_key_def &kd, } int ha_rocksdb::read_row_from_primary_key(uchar *const buf) { - DBUG_ASSERT(buf != nullptr); - int rc; const rocksdb::Slice &rkey = m_scan_it->key(); const uint pk_size = rkey.size(); @@ -7771,8 +8192,6 @@ int ha_rocksdb::read_row_from_primary_key(uchar *const buf) { int ha_rocksdb::read_row_from_secondary_key(uchar *const buf, const Rdb_key_def &kd, bool move_forward) { - DBUG_ASSERT(buf != nullptr); - int rc = 0; uint pk_size; @@ -7875,7 +8294,6 @@ ulong ha_rocksdb::index_flags(uint inx, uint part, bool all_parts) const { pair for. */ int ha_rocksdb::secondary_index_read(const int keyno, uchar *const buf) { - DBUG_ASSERT(buf != nullptr); DBUG_ASSERT(table != nullptr); #ifdef MARIAROCKS_NOT_YET stats.rows_requested++; @@ -8192,7 +8610,7 @@ int ha_rocksdb::index_read_map_impl(uchar *const buf, const uchar *const key, else rc = read_row_from_secondary_key(buf, kd, move_forward); - if (rc != HA_ERR_LOCK_DEADLOCK || !is_new_snapshot) + if (rc != HA_ERR_ROCKSDB_STATUS_BUSY || !is_new_snapshot) break; /* Exit the loop */ // release the snapshot and iterator so they will be regenerated @@ -8237,8 +8655,6 @@ int ha_rocksdb::index_read_map_impl(uchar *const buf, const uchar *const key, int ha_rocksdb::find_icp_matching_index_rec(const bool &move_forward, uchar *const buf) { - DBUG_ASSERT(buf != nullptr); - if (pushed_idx_cond && pushed_idx_cond_keyno == active_index) { const Rdb_key_def &kd = *m_key_descr_arr[active_index]; @@ -8552,8 +8968,6 @@ int ha_rocksdb::get_row_by_rowid(uchar *const buf, const char *const rowid, const bool skip_ttl_check) { DBUG_ENTER_FUNC(); - DBUG_ASSERT(buf != nullptr); - DBUG_ASSERT(rowid != nullptr); DBUG_ASSERT(table != nullptr); int rc; @@ -8766,8 +9180,6 @@ int ha_rocksdb::index_last(uchar *const buf) { int ha_rocksdb::index_first_intern(uchar *const buf) { DBUG_ENTER_FUNC(); - DBUG_ASSERT(buf != nullptr); - uchar *key; uint key_size; int rc; @@ -8797,7 +9209,7 @@ int ha_rocksdb::index_first_intern(uchar *const buf) { m_skip_scan_it_next_call = true; rc = index_next_with_direction(buf, true); - if (rc != HA_ERR_LOCK_DEADLOCK || !is_new_snapshot) + if (rc != HA_ERR_ROCKSDB_STATUS_BUSY || !is_new_snapshot) break; // exit the loop // release the snapshot and iterator so they will be regenerated @@ -8859,8 +9271,6 @@ int ha_rocksdb::index_first_intern(uchar *const buf) { int ha_rocksdb::index_last_intern(uchar *const buf) { DBUG_ENTER_FUNC(); - DBUG_ASSERT(buf != nullptr); - uchar *key; uint key_size; int rc; @@ -8902,7 +9312,7 @@ int ha_rocksdb::index_last_intern(uchar *const buf) { rc = secondary_index_read(active_index, buf); } - if (rc != HA_ERR_LOCK_DEADLOCK || !is_new_snapshot) + if (rc != HA_ERR_ROCKSDB_STATUS_BUSY || !is_new_snapshot) break; /* exit the loop */ // release the snapshot and iterator so they will be regenerated @@ -8987,7 +9397,6 @@ bool ha_rocksdb::commit_in_the_middle() { @retval false if bulk commit was skipped or succeeded */ bool ha_rocksdb::do_bulk_commit(Rdb_transaction *const tx) { - DBUG_ASSERT(tx != nullptr); return commit_in_the_middle() && tx->get_write_count() >= THDVAR(table->in_use, bulk_load_size) && tx->flush_batch(); @@ -9000,7 +9409,6 @@ bool ha_rocksdb::do_bulk_commit(Rdb_transaction *const tx) { 'auto-incremented' pk.) */ bool ha_rocksdb::has_hidden_pk(const TABLE *const table) const { - DBUG_ASSERT(table != nullptr); return Rdb_key_def::table_has_hidden_pk(table); } @@ -9010,9 +9418,7 @@ bool ha_rocksdb::has_hidden_pk(const TABLE *const table) const { */ bool ha_rocksdb::is_hidden_pk(const uint index, const TABLE *const table_arg, const Rdb_tbl_def *const tbl_def_arg) { - DBUG_ASSERT(table_arg != nullptr); DBUG_ASSERT(table_arg->s != nullptr); - DBUG_ASSERT(tbl_def_arg != nullptr); return (table_arg->s->primary_key == MAX_INDEXES && index == tbl_def_arg->m_key_count - 1); @@ -9021,9 +9427,7 @@ bool ha_rocksdb::is_hidden_pk(const uint index, const TABLE *const table_arg, /* Returns index of primary key */ uint ha_rocksdb::pk_index(const TABLE *const table_arg, const Rdb_tbl_def *const tbl_def_arg) { - DBUG_ASSERT(table_arg != nullptr); DBUG_ASSERT(table_arg->s != nullptr); - DBUG_ASSERT(tbl_def_arg != nullptr); return table_arg->s->primary_key == MAX_INDEXES ? tbl_def_arg->m_key_count - 1 : table_arg->s->primary_key; @@ -9032,9 +9436,7 @@ uint ha_rocksdb::pk_index(const TABLE *const table_arg, /* Returns true if given index number is a primary key */ bool ha_rocksdb::is_pk(const uint index, const TABLE *const table_arg, const Rdb_tbl_def *const tbl_def_arg) { - DBUG_ASSERT(table_arg != nullptr); DBUG_ASSERT(table_arg->s != nullptr); - DBUG_ASSERT(tbl_def_arg != nullptr); return index == table_arg->s->primary_key || is_hidden_pk(index, table_arg, tbl_def_arg); @@ -9049,9 +9451,6 @@ uint ha_rocksdb::max_supported_key_part_length() const { const char *ha_rocksdb::get_key_name(const uint index, const TABLE *const table_arg, const Rdb_tbl_def *const tbl_def_arg) { - DBUG_ASSERT(table_arg != nullptr); - DBUG_ASSERT(tbl_def_arg != nullptr); - if (is_hidden_pk(index, table_arg, tbl_def_arg)) { return HIDDEN_PK_NAME; } @@ -9065,9 +9464,6 @@ const char *ha_rocksdb::get_key_name(const uint index, const char *ha_rocksdb::get_key_comment(const uint index, const TABLE *const table_arg, const Rdb_tbl_def *const tbl_def_arg) { - DBUG_ASSERT(table_arg != nullptr); - DBUG_ASSERT(tbl_def_arg != nullptr); - if (is_hidden_pk(index, table_arg, tbl_def_arg)) { return nullptr; } @@ -9119,7 +9515,6 @@ const std::string ha_rocksdb::generate_cf_name(const uint index, } const std::string ha_rocksdb::get_table_comment(const TABLE *const table_arg) { - DBUG_ASSERT(table_arg != nullptr); DBUG_ASSERT(table_arg->s != nullptr); return table_arg->s->comment.str; @@ -9236,8 +9631,7 @@ int ha_rocksdb::check_and_lock_unique_pk(const uint &key_id, /* If the keys are the same, then no lock is needed */ - if (!Rdb_pk_comparator::bytewise_compare(row_info.new_pk_slice, - row_info.old_pk_slice)) { + if (!row_info.new_pk_slice.compare(row_info.old_pk_slice)) { *found = false; return HA_EXIT_SUCCESS; } @@ -9326,8 +9720,7 @@ int ha_rocksdb::check_and_lock_sk(const uint &key_id, rocksdb::Slice((const char *)m_sk_packed_tuple, size); /* - For UPDATEs, if the key has changed, we need to obtain a lock. INSERTs - always require locking. + Acquire lock on the old key in case of UPDATE */ if (row_info.old_data != nullptr) { size = kd.pack_record(table, m_pack_buffer, row_info.old_data, @@ -9336,14 +9729,18 @@ int ha_rocksdb::check_and_lock_sk(const uint &key_id, const rocksdb::Slice old_slice = rocksdb::Slice((const char *)m_sk_packed_tuple_old, size); - /* - For updates, if the keys are the same, then no lock is needed + const rocksdb::Status s = + get_for_update(row_info.tx, kd.get_cf(), old_slice, nullptr); + if (!s.ok()) { + return row_info.tx->set_status_error(table->in_use, s, kd, m_tbl_def, + m_table_handler); + } - Also check to see if the key has any fields set to NULL. If it does, then - this key is unique since NULL is not equal to each other, so no lock is - needed. + /* + If the old and new keys are the same we're done since we've already taken + the lock on the old key */ - if (!Rdb_pk_comparator::bytewise_compare(new_slice, old_slice)) { + if (!new_slice.compare(old_slice)) { return HA_EXIT_SUCCESS; } } @@ -9369,16 +9766,14 @@ int ha_rocksdb::check_and_lock_sk(const uint &key_id, The bloom filter may need to be disabled for this lookup. */ - uchar min_bound_buf[MAX_KEY_LENGTH]; - uchar max_bound_buf[MAX_KEY_LENGTH]; - rocksdb::Slice min_bound_slice; - rocksdb::Slice max_bound_slice; + uchar lower_bound_buf[Rdb_key_def::INDEX_NUMBER_SIZE]; + uchar upper_bound_buf[Rdb_key_def::INDEX_NUMBER_SIZE]; + rocksdb::Slice lower_bound_slice; + rocksdb::Slice upper_bound_slice; + const bool total_order_seek = !check_bloom_and_set_bounds( - ha_thd(), kd, new_slice, all_parts_used, - min_bound_buf, - max_bound_buf, - &min_bound_slice, - &max_bound_slice); + ha_thd(), kd, new_slice, all_parts_used, Rdb_key_def::INDEX_NUMBER_SIZE, + lower_bound_buf, upper_bound_buf, &lower_bound_slice, &upper_bound_slice); const bool fill_cache = !THDVAR(ha_thd(), skip_fill_cache); const rocksdb::Status s = @@ -9389,9 +9784,8 @@ int ha_rocksdb::check_and_lock_sk(const uint &key_id, } rocksdb::Iterator *const iter = row_info.tx->get_iterator( - kd.get_cf(), total_order_seek, fill_cache, - min_bound_slice, max_bound_slice, - true /* read current data */, + kd.get_cf(), total_order_seek, fill_cache, lower_bound_slice, + upper_bound_slice, true /* read current data */, false /* acquire snapshot */); /* Need to scan the transaction to see if there is a duplicate key. @@ -9553,7 +9947,7 @@ int ha_rocksdb::update_pk(const Rdb_key_def &kd, } } - if (table->next_number_field) { + if (table->found_next_number_field) { update_auto_incr_val_from_field(); } @@ -9601,9 +9995,11 @@ int ha_rocksdb::update_pk(const Rdb_key_def &kd, } int ha_rocksdb::update_sk(const TABLE *const table_arg, const Rdb_key_def &kd, - const struct update_row_info &row_info) { + const struct update_row_info &row_info, + const bool bulk_load_sk) { int new_packed_size; int old_packed_size; + int rc = HA_EXIT_SUCCESS; rocksdb::Slice new_key_slice; rocksdb::Slice new_value_slice; @@ -9681,18 +10077,23 @@ int ha_rocksdb::update_sk(const TABLE *const table_arg, const Rdb_key_def &kd, rocksdb::Slice(reinterpret_cast(m_sk_tails.ptr()), m_sk_tails.get_current_pos()); - row_info.tx->get_indexed_write_batch()->Put(kd.get_cf(), new_key_slice, - new_value_slice); + if (bulk_load_sk && row_info.old_data == nullptr) { + rc = bulk_load_key(row_info.tx, kd, new_key_slice, new_value_slice, true); + } else { + row_info.tx->get_indexed_write_batch()->Put(kd.get_cf(), new_key_slice, + new_value_slice); + } row_info.tx->update_bytes_written(bytes_written + new_key_slice.size() + new_value_slice.size()); - return HA_EXIT_SUCCESS; + return rc; } int ha_rocksdb::update_indexes(const struct update_row_info &row_info, const bool &pk_changed) { int rc; + bool bulk_load_sk; // The PK must be updated first to pull out the TTL value. rc = update_pk(*m_pk_descr, row_info, pk_changed); @@ -9700,13 +10101,17 @@ int ha_rocksdb::update_indexes(const struct update_row_info &row_info, return rc; } - // Update the remaining indexes. + // Update the remaining indexes. Allow bulk loading only if + // allow_sk is enabled + bulk_load_sk = rocksdb_enable_bulk_load_api && + THDVAR(table->in_use, bulk_load) && + THDVAR(table->in_use, bulk_load_allow_sk); for (uint key_id = 0; key_id < m_tbl_def->m_key_count; key_id++) { if (is_pk(key_id, table, m_tbl_def)) { continue; } - rc = update_sk(table, *m_key_descr_arr[key_id], row_info); + rc = update_sk(table, *m_key_descr_arr[key_id], row_info, bulk_load_sk); if (rc != HA_EXIT_SUCCESS) { return rc; } @@ -9804,28 +10209,22 @@ int ha_rocksdb::update_write_row(const uchar *const old_data, @param outer_u */ -void ha_rocksdb::setup_iterator_bounds(const Rdb_key_def &kd, - const rocksdb::Slice &eq_cond, - uchar *lower_bound_buf, - uchar *upper_bound_buf, - rocksdb::Slice *out_lower_bound, - rocksdb::Slice *out_upper_bound) { - uint eq_cond_len = eq_cond.size(); - memcpy(upper_bound_buf, eq_cond.data(), eq_cond_len); - kd.successor(upper_bound_buf, eq_cond_len); - memcpy(lower_bound_buf, eq_cond.data(), eq_cond_len); - kd.predecessor(lower_bound_buf, eq_cond_len); +void ha_rocksdb::setup_iterator_bounds( + const Rdb_key_def &kd, const rocksdb::Slice &eq_cond, size_t bound_len, + uchar *const lower_bound, uchar *const upper_bound, + rocksdb::Slice *lower_bound_slice, rocksdb::Slice *upper_bound_slice) { + uint min_len = std::min(eq_cond.size(), bound_len); + memcpy(upper_bound, eq_cond.data(), min_len); + kd.successor(upper_bound, min_len); + memcpy(lower_bound, eq_cond.data(), min_len); + kd.predecessor(lower_bound, min_len); if (kd.m_is_reverse_cf) { - *out_upper_bound = - rocksdb::Slice((const char *)lower_bound_buf, eq_cond_len); - *out_lower_bound = - rocksdb::Slice((const char *)upper_bound_buf, eq_cond_len); + *upper_bound_slice = rocksdb::Slice((const char *)lower_bound, min_len); + *lower_bound_slice = rocksdb::Slice((const char *)upper_bound, min_len); } else { - *out_upper_bound = - rocksdb::Slice((const char *)upper_bound_buf, eq_cond_len); - *out_lower_bound = - rocksdb::Slice((const char *)lower_bound_buf, eq_cond_len); + *upper_bound_slice = rocksdb::Slice((const char *)upper_bound, min_len); + *lower_bound_slice = rocksdb::Slice((const char *)lower_bound, min_len); } } @@ -9837,7 +10236,6 @@ void ha_rocksdb::setup_scan_iterator(const Rdb_key_def &kd, rocksdb::Slice *const slice, const bool use_all_keys, const uint eq_cond_len) { - DBUG_ASSERT(slice != nullptr); DBUG_ASSERT(slice->size() >= eq_cond_len); Rdb_transaction *const tx = get_or_create_tx(table->in_use); @@ -9845,11 +10243,10 @@ void ha_rocksdb::setup_scan_iterator(const Rdb_key_def &kd, bool skip_bloom = true; const rocksdb::Slice eq_cond(slice->data(), eq_cond_len); - if (check_bloom_and_set_bounds(ha_thd(), kd, eq_cond, use_all_keys, - m_eq_cond_lower_bound, - m_eq_cond_upper_bound, - &m_eq_cond_lower_bound_slice, - &m_eq_cond_upper_bound_slice)) { + if (check_bloom_and_set_bounds( + ha_thd(), kd, eq_cond, use_all_keys, eq_cond_len, + m_scan_it_lower_bound, m_scan_it_upper_bound, + &m_scan_it_lower_bound_slice, &m_scan_it_upper_bound_slice)) { skip_bloom = false; } @@ -9890,8 +10287,8 @@ void ha_rocksdb::setup_scan_iterator(const Rdb_key_def &kd, m_scan_it = rdb->NewIterator(read_opts, kd.get_cf()); } else { m_scan_it = tx->get_iterator(kd.get_cf(), skip_bloom, fill_cache, - m_eq_cond_lower_bound_slice, - m_eq_cond_upper_bound_slice); + m_scan_it_lower_bound_slice, + m_scan_it_upper_bound_slice); } m_scan_it_skips_bloom = skip_bloom; } @@ -9957,7 +10354,7 @@ int ha_rocksdb::rnd_next(uchar *const buf) { int rc; for (;;) { rc = rnd_next_with_direction(buf, true); - if (rc != HA_ERR_LOCK_DEADLOCK || !m_rnd_scan_is_new_snapshot) + if (rc != HA_ERR_ROCKSDB_STATUS_BUSY || !m_rnd_scan_is_new_snapshot) break; /* exit the loop */ // release the snapshot and iterator and then regenerate them @@ -10286,7 +10683,7 @@ int ha_rocksdb::info(uint flag) { if (static_cast(stats.data_file_length) < 0 || static_cast(stats.index_file_length) < 0 || static_cast(stats.records) < 0) { - if (analyze(nullptr, nullptr)) { + if (calculate_stats_for_table()) { DBUG_RETURN(HA_EXIT_FAILURE); } @@ -10364,10 +10761,21 @@ int ha_rocksdb::info(uint flag) { KEY *const k = &table->key_info[i]; for (uint j = 0; j < k->ext_key_parts; j++) { const Rdb_index_stats &k_stats = m_key_descr_arr[i]->m_stats; - uint x = k_stats.m_distinct_keys_per_prefix.size() > j && - k_stats.m_distinct_keys_per_prefix[j] > 0 - ? k_stats.m_rows / k_stats.m_distinct_keys_per_prefix[j] - : 0; + uint x; + + if (k_stats.m_distinct_keys_per_prefix.size() > j && + k_stats.m_distinct_keys_per_prefix[j] > 0) { + x = k_stats.m_rows / k_stats.m_distinct_keys_per_prefix[j]; + /* + If the number of rows is less than the number of prefixes (due to + sampling), the average number of rows with the same prefix is 1. + */ + if (x == 0) { + x = 1; + } + } else { + x = 0; + } if (x > stats.records) x = stats.records; if ((x == 0 && rocksdb_debug_optimizer_no_zero_cardinality) || @@ -10572,7 +10980,7 @@ THR_LOCK_DATA **ha_rocksdb::store_lock(THD *const thd, THR_LOCK_DATA **to, m_lock_rows = RDB_LOCK_WRITE; } else if (lock_type == TL_READ_WITH_SHARED_LOCKS) { m_lock_rows = RDB_LOCK_READ; - } else { + } else if (lock_type != TL_IGNORE) { m_lock_rows = RDB_LOCK_NONE; if (THDVAR(thd, lock_scanned_rows)) { /* @@ -10737,6 +11145,13 @@ int ha_rocksdb::external_lock(THD *const thd, int lock_type) { DBUG_RETURN(HA_ERR_UNSUPPORTED); } +#ifdef MARIADB_NOT_YET + if (thd->get_explicit_snapshot()) { + my_error(ER_UPDATES_WITH_EXPLICIT_SNAPSHOT, MYF(0)); + DBUG_RETURN(HA_ERR_UNSUPPORTED); + } +#endif + /* SQL layer signals us to take a write lock. It does so when starting DML statement. We should put locks on the rows we're reading. @@ -10958,8 +11373,6 @@ void Rdb_drop_index_thread::run() { } Rdb_tbl_def *ha_rocksdb::get_table_if_exists(const char *const tablename) { - DBUG_ASSERT(tablename != nullptr); - std::string str; if (rdb_normalize_tablename(tablename, &str) != HA_EXIT_SUCCESS) { // We were not passed table name? @@ -11022,6 +11435,12 @@ int ha_rocksdb::remove_rows(Rdb_tbl_def *const tbl) { char key_buf[MAX_KEY_LENGTH]; uint key_len; ulonglong bytes_written = 0; + + uchar lower_bound_buf[Rdb_key_def::INDEX_NUMBER_SIZE]; + uchar upper_bound_buf[Rdb_key_def::INDEX_NUMBER_SIZE]; + rocksdb::Slice lower_bound_slice; + rocksdb::Slice upper_bound_slice; + /* Remove all records in each index. (This is is not crash-safe, but it doesn't matter, because bulk row @@ -11032,13 +11451,12 @@ int ha_rocksdb::remove_rows(Rdb_tbl_def *const tbl) { kd.get_infimum_key(reinterpret_cast(key_buf), &key_len); rocksdb::ColumnFamilyHandle *cf = kd.get_cf(); const rocksdb::Slice table_key(key_buf, key_len); - setup_iterator_bounds(kd, table_key, - m_eq_cond_lower_bound, - m_eq_cond_upper_bound, - &m_eq_cond_lower_bound_slice, - &m_eq_cond_upper_bound_slice); - opts.iterate_lower_bound = &m_eq_cond_lower_bound_slice; - opts.iterate_upper_bound = &m_eq_cond_upper_bound_slice; + setup_iterator_bounds(kd, table_key, Rdb_key_def::INDEX_NUMBER_SIZE, + lower_bound_buf, upper_bound_buf, &lower_bound_slice, + &upper_bound_slice); + DBUG_ASSERT(key_len == Rdb_key_def::INDEX_NUMBER_SIZE); + opts.iterate_lower_bound = &lower_bound_slice; + opts.iterate_upper_bound = &upper_bound_slice; std::unique_ptr it(rdb->NewIterator(opts, cf)); it->Seek(table_key); @@ -11077,9 +11495,6 @@ int ha_rocksdb::remove_rows(Rdb_tbl_def *const tbl) { int ha_rocksdb::rename_table(const char *const from, const char *const to) { DBUG_ENTER_FUNC(); - DBUG_ASSERT(from != nullptr); - DBUG_ASSERT(to != nullptr); - std::string from_str; std::string to_str; std::string from_db; @@ -11330,29 +11745,28 @@ int ha_rocksdb::optimize(THD *const thd, HA_CHECK_OPT *const check_opt) { DBUG_RETURN(HA_EXIT_SUCCESS); } -int ha_rocksdb::calculate_stats(const TABLE *const table_arg, THD *const thd, - HA_CHECK_OPT *const check_opt) { +static int calculate_stats( + const std::unordered_map> + &to_recalc, + bool include_memtables) { DBUG_ENTER_FUNC(); // find per column family key ranges which need to be queried std::unordered_map> ranges; - std::unordered_set ids_to_check; - std::vector buf(table_arg->s->keys * 2 * - Rdb_key_def::INDEX_NUMBER_SIZE); std::unordered_map stats; - for (uint i = 0; i < table_arg->s->keys; i++) { - const auto bufp = &buf[i * 2 * Rdb_key_def::INDEX_NUMBER_SIZE]; - const Rdb_key_def &kd = *m_key_descr_arr[i]; - const GL_INDEX_ID index_id = kd.get_gl_index_id(); - ranges[kd.get_cf()].push_back(get_range(i, bufp)); + std::vector buf(to_recalc.size() * 2 * Rdb_key_def::INDEX_NUMBER_SIZE); + + uchar *bufp = buf.data(); + for (const auto &it : to_recalc) { + const GL_INDEX_ID index_id = it.first; + auto &kd = it.second; + ranges[kd->get_cf()].push_back(myrocks::get_range(*kd, bufp)); + bufp += 2 * Rdb_key_def::INDEX_NUMBER_SIZE; - ids_to_check.insert(index_id); - // Initialize the stats to 0. If there are no files that contain - // this gl_index_id, then 0 should be stored for the cached stats. stats[index_id] = Rdb_index_stats(index_id); - DBUG_ASSERT(kd.get_key_parts() > 0); - stats[index_id].m_distinct_keys_per_prefix.resize(kd.get_key_parts()); + DBUG_ASSERT(kd->get_key_parts() > 0); + stats[index_id].m_distinct_keys_per_prefix.resize(kd->get_key_parts()); } // get RocksDB table properties for these ranges @@ -11363,8 +11777,8 @@ int ha_rocksdb::calculate_stats(const TABLE *const table_arg, THD *const thd, it.first, &it.second[0], it.second.size(), &props); DBUG_ASSERT(props.size() >= old_size); if (!status.ok()) { - DBUG_RETURN( - rdb_error_to_mysql(status, "Could not access RocksDB properties")); + DBUG_RETURN(ha_rocksdb::rdb_error_to_mysql( + status, "Could not access RocksDB properties")); } } @@ -11385,61 +11799,62 @@ int ha_rocksdb::calculate_stats(const TABLE *const table_arg, THD *const thd, other SQL tables, it can be that we're only seeing a small fraction of table's entries (and so we can't update statistics based on that). */ - if (ids_to_check.find(it1.m_gl_index_id) == ids_to_check.end()) + if (stats.find(it1.m_gl_index_id) == stats.end()) { continue; + } - auto kd = ddl_manager.safe_find(it1.m_gl_index_id); - DBUG_ASSERT(kd != nullptr); - stats[it1.m_gl_index_id].merge(it1, true, kd->max_storage_fmt_length()); + auto it_index = to_recalc.find(it1.m_gl_index_id); + DBUG_ASSERT(it_index != to_recalc.end()); + if (it_index == to_recalc.end()) { + continue; + } + stats[it1.m_gl_index_id].merge( + it1, true, it_index->second->max_storage_fmt_length()); } num_sst++; } - // calculate memtable cardinality - Rdb_tbl_card_coll cardinality_collector(rocksdb_table_stats_sampling_pct); - auto read_opts = rocksdb::ReadOptions(); - read_opts.read_tier = rocksdb::ReadTier::kMemtableTier; - for (uint i = 0; i < table_arg->s->keys; i++) { - const Rdb_key_def &kd = *m_key_descr_arr[i]; - Rdb_index_stats &stat = stats[kd.get_gl_index_id()]; + if (include_memtables) { + // calculate memtable cardinality + Rdb_tbl_card_coll cardinality_collector(rocksdb_table_stats_sampling_pct); + auto read_opts = rocksdb::ReadOptions(); + read_opts.read_tier = rocksdb::ReadTier::kMemtableTier; + for (const auto &it_kd : to_recalc) { + const std::shared_ptr &kd = it_kd.second; + Rdb_index_stats &stat = stats[kd->get_gl_index_id()]; - uchar r_buf[Rdb_key_def::INDEX_NUMBER_SIZE * 2]; - auto r = get_range(i, r_buf); - uint64_t memtableCount; - uint64_t memtableSize; - rdb->GetApproximateMemTableStats(kd.get_cf(), r, &memtableCount, - &memtableSize); - if (memtableCount < (uint64_t)stat.m_rows / 10) { - // skip tables that already have enough stats from SST files to reduce - // overhead and avoid degradation of big tables stats by sampling from - // relatively tiny (less than 10% of full data set) memtable dataset - continue; - } - - std::unique_ptr it = std::unique_ptr( - rdb->NewIterator(read_opts, kd.get_cf())); - - uchar *first_key; - uint key_size; - if (is_pk(i, table, m_tbl_def)) { - first_key = m_pk_packed_tuple; - } else { - first_key = m_sk_packed_tuple; - } - kd.get_first_key(first_key, &key_size); - rocksdb::Slice first_index_key((const char *)first_key, key_size); - - cardinality_collector.Reset(); - for (it->Seek(first_index_key); is_valid(it.get()); it->Next()) { - const rocksdb::Slice key = it->key(); - if (!kd.covers_key(key)) { - break; // end of this index + uchar r_buf[Rdb_key_def::INDEX_NUMBER_SIZE * 2]; + auto r = myrocks::get_range(*kd, r_buf); + uint64_t memtableCount; + uint64_t memtableSize; + rdb->GetApproximateMemTableStats(kd->get_cf(), r, &memtableCount, + &memtableSize); + if (memtableCount < (uint64_t)stat.m_rows / 10) { + // skip tables that already have enough stats from SST files to reduce + // overhead and avoid degradation of big tables stats by sampling from + // relatively tiny (less than 10% of full data set) memtable dataset + continue; } - stat.m_rows++; - cardinality_collector.ProcessKey(key, &kd, &stat); + std::unique_ptr it = + std::unique_ptr( + rdb->NewIterator(read_opts, kd->get_cf())); + + rocksdb::Slice first_index_key((const char *)r_buf, + Rdb_key_def::INDEX_NUMBER_SIZE); + + cardinality_collector.Reset(); + for (it->Seek(first_index_key); is_valid(it.get()); it->Next()) { + const rocksdb::Slice key = it->key(); + if (!kd->covers_key(key)) { + break; // end of this index + } + stat.m_rows++; + + cardinality_collector.ProcessKey(key, kd.get(), &stat); + } + cardinality_collector.AdjustStats(&stat); } - cardinality_collector.AdjustStats(&stat); } // set and persist new stats @@ -11449,6 +11864,19 @@ int ha_rocksdb::calculate_stats(const TABLE *const table_arg, THD *const thd, DBUG_RETURN(HA_EXIT_SUCCESS); } +int ha_rocksdb::calculate_stats_for_table() { + DBUG_ENTER_FUNC(); + + std::unordered_map> + ids_to_check; + for (uint i = 0; i < table->s->keys; i++) { + ids_to_check.insert(std::make_pair(m_key_descr_arr[i]->get_gl_index_id(), + m_key_descr_arr[i])); + } + + DBUG_RETURN(calculate_stats(ids_to_check, true)); +} + /* @return HA_ADMIN_OK OK @@ -11457,7 +11885,16 @@ int ha_rocksdb::calculate_stats(const TABLE *const table_arg, THD *const thd, int ha_rocksdb::analyze(THD *const thd, HA_CHECK_OPT *const check_opt) { DBUG_ENTER_FUNC(); - if (table && calculate_stats(table, thd, check_opt) != HA_EXIT_SUCCESS) { + if (table) { + if (calculate_stats_for_table() != HA_EXIT_SUCCESS) { + DBUG_RETURN(HA_ADMIN_FAILED); + } + } + + // A call to ::info is needed to repopulate some SQL level structs. This is + // necessary for online analyze because we cannot rely on another ::open + // call to call info for us. + if (info(HA_STATUS_CONST | HA_STATUS_VARIABLE) != HA_EXIT_SUCCESS) { DBUG_RETURN(HA_ADMIN_FAILED); } @@ -12286,18 +12723,6 @@ bool ha_rocksdb::commit_inplace_alter_table( dict_manager.finish_indexes_operation( create_index_ids, Rdb_key_def::DDL_CREATE_INDEX_ONGOING); - /* - We need to recalculate the index stats here manually. The reason is that - the secondary index does not exist inside - m_index_num_to_keydef until it is committed to the data dictionary, which - prevents us from updating the stats normally as the ddl_manager cannot - find the proper gl_index_ids yet during adjust_stats calls. - */ - if (calculate_stats(altered_table, nullptr, nullptr)) { - /* Failed to update index statistics, should never happen */ - DBUG_ASSERT(0); - } - rdb_drop_idx_thread.signal(); } @@ -12368,6 +12793,8 @@ struct rocksdb_status_counters_t { uint64_t block_cache_data_hit; uint64_t block_cache_data_add; uint64_t bloom_filter_useful; + uint64_t bloom_filter_full_positive; + uint64_t bloom_filter_full_true_positive; uint64_t memtable_hit; uint64_t memtable_miss; uint64_t get_hit_l0; @@ -12442,6 +12869,8 @@ DEF_SHOW_FUNC(block_cache_data_miss, BLOCK_CACHE_DATA_MISS) DEF_SHOW_FUNC(block_cache_data_hit, BLOCK_CACHE_DATA_HIT) DEF_SHOW_FUNC(block_cache_data_add, BLOCK_CACHE_DATA_ADD) DEF_SHOW_FUNC(bloom_filter_useful, BLOOM_FILTER_USEFUL) +DEF_SHOW_FUNC(bloom_filter_full_positive, BLOOM_FILTER_FULL_POSITIVE) +DEF_SHOW_FUNC(bloom_filter_full_true_positive, BLOOM_FILTER_FULL_TRUE_POSITIVE) DEF_SHOW_FUNC(memtable_hit, MEMTABLE_HIT) DEF_SHOW_FUNC(memtable_miss, MEMTABLE_MISS) DEF_SHOW_FUNC(get_hit_l0, GET_HIT_L0) @@ -12676,6 +13105,8 @@ static SHOW_VAR rocksdb_status_vars[] = { DEF_STATUS_VAR(block_cache_data_hit), DEF_STATUS_VAR(block_cache_data_add), DEF_STATUS_VAR(bloom_filter_useful), + DEF_STATUS_VAR(bloom_filter_full_positive), + DEF_STATUS_VAR(bloom_filter_full_true_positive), DEF_STATUS_VAR(memtable_hit), DEF_STATUS_VAR(memtable_miss), DEF_STATUS_VAR(get_hit_l0), @@ -12733,6 +13164,10 @@ static SHOW_VAR rocksdb_status_vars[] = { &rocksdb_snapshot_conflict_errors, SHOW_LONGLONG), DEF_STATUS_VAR_PTR("wal_group_syncs", &rocksdb_wal_group_syncs, SHOW_LONGLONG), + DEF_STATUS_VAR_PTR("manual_compactions_processed", + &rocksdb_manual_compactions_processed, SHOW_LONGLONG), + DEF_STATUS_VAR_PTR("manual_compactions_running", + &rocksdb_manual_compactions_running, SHOW_LONGLONG), DEF_STATUS_VAR_PTR("number_sst_entry_put", &rocksdb_num_sst_entry_put, SHOW_LONGLONG), DEF_STATUS_VAR_PTR("number_sst_entry_delete", &rocksdb_num_sst_entry_delete, @@ -12806,24 +13241,193 @@ void Rdb_background_thread::run() { rdb_handle_io_error(s, RDB_IO_ERROR_BG_THREAD); } } + // Recalculate statistics for indexes. + if (rocksdb_stats_recalc_rate) { + std::unordered_map> + to_recalc; + + if (rdb_indexes_to_recalc.empty()) { + struct Rdb_index_collector : public Rdb_tables_scanner { + int add_table(Rdb_tbl_def *tdef) override { + for (uint i = 0; i < tdef->m_key_count; i++) { + rdb_indexes_to_recalc.push_back( + tdef->m_key_descr_arr[i]->get_gl_index_id()); + } + return HA_EXIT_SUCCESS; + } + } collector; + ddl_manager.scan_for_tables(&collector); + } + + while (to_recalc.size() < rocksdb_stats_recalc_rate && + !rdb_indexes_to_recalc.empty()) { + const auto index_id = rdb_indexes_to_recalc.back(); + rdb_indexes_to_recalc.pop_back(); + + std::shared_ptr keydef = + ddl_manager.safe_find(index_id); + + if (keydef) { + to_recalc.insert(std::make_pair(keydef->get_gl_index_id(), keydef)); + } + } + + if (!to_recalc.empty()) { + calculate_stats(to_recalc, false); + } + } + } // save remaining stats which might've left unsaved ddl_manager.persist_stats(); } -bool ha_rocksdb::check_bloom_and_set_bounds(THD *thd, const Rdb_key_def &kd, - const rocksdb::Slice &eq_cond, - const bool use_all_keys, - uchar *lower_bound_buf, - uchar *upper_bound_buf, - rocksdb::Slice *out_lower_bound, - rocksdb::Slice *out_upper_bound) { +/* + A background thread to handle manual compactions, + except for dropping indexes/tables. Every second, it checks + pending manual compactions, and it calls CompactRange if there is. +*/ +void Rdb_manual_compaction_thread::run() { + mysql_mutex_init(0, &m_mc_mutex, MY_MUTEX_INIT_FAST); + RDB_MUTEX_LOCK_CHECK(m_signal_mutex); + for (;;) { + if (m_stop) { + break; + } + timespec ts; + set_timespec(ts, 1); + + const auto ret MY_ATTRIBUTE((__unused__)) = + mysql_cond_timedwait(&m_signal_cond, &m_signal_mutex, &ts); + if (m_stop) { + break; + } + // make sure, no program error is returned + DBUG_ASSERT(ret == 0 || ret == ETIMEDOUT); + RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); + + RDB_MUTEX_LOCK_CHECK(m_mc_mutex); + // Grab the first item and proceed, if not empty. + if (m_requests.empty()) { + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); + RDB_MUTEX_LOCK_CHECK(m_signal_mutex); + continue; + } + Manual_compaction_request &mcr = m_requests.begin()->second; + DBUG_ASSERT(mcr.cf != nullptr); + DBUG_ASSERT(mcr.state == Manual_compaction_request::INITED); + mcr.state = Manual_compaction_request::RUNNING; + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); + + DBUG_ASSERT(mcr.state == Manual_compaction_request::RUNNING); + // NO_LINT_DEBUG + sql_print_information("Manual Compaction id %d cf %s started.", mcr.mc_id, + mcr.cf->GetName().c_str()); + rocksdb_manual_compactions_running++; + if (rocksdb_debug_manual_compaction_delay > 0) { + my_sleep(rocksdb_debug_manual_compaction_delay * 1000000); + } + // CompactRange may take a very long time. On clean shutdown, + // it is cancelled by CancelAllBackgroundWork, then status is + // set to shutdownInProgress. + const rocksdb::Status s = rdb->CompactRange( + getCompactRangeOptions(mcr.concurrency), mcr.cf, mcr.start, mcr.limit); + rocksdb_manual_compactions_running--; + if (s.ok()) { + // NO_LINT_DEBUG + sql_print_information("Manual Compaction id %d cf %s ended.", mcr.mc_id, + mcr.cf->GetName().c_str()); + } else { + // NO_LINT_DEBUG + sql_print_information("Manual Compaction id %d cf %s aborted. %s", + mcr.mc_id, mcr.cf->GetName().c_str(), s.getState()); + if (!s.IsShutdownInProgress()) { + rdb_handle_io_error(s, RDB_IO_ERROR_BG_THREAD); + } else { + DBUG_ASSERT(m_requests.size() == 1); + } + } + rocksdb_manual_compactions_processed++; + clear_manual_compaction_request(mcr.mc_id, false); + RDB_MUTEX_LOCK_CHECK(m_signal_mutex); + } + clear_all_manual_compaction_requests(); + DBUG_ASSERT(m_requests.empty()); + RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); + mysql_mutex_destroy(&m_mc_mutex); +} + +void Rdb_manual_compaction_thread::clear_all_manual_compaction_requests() { + RDB_MUTEX_LOCK_CHECK(m_mc_mutex); + m_requests.clear(); + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); +} + +void Rdb_manual_compaction_thread::clear_manual_compaction_request( + int mc_id, bool init_only) { + bool erase = true; + RDB_MUTEX_LOCK_CHECK(m_mc_mutex); + auto it = m_requests.find(mc_id); + if (it != m_requests.end()) { + if (init_only) { + Manual_compaction_request mcr = it->second; + if (mcr.state != Manual_compaction_request::INITED) { + erase = false; + } + } + if (erase) { + m_requests.erase(it); + } + } else { + // Current code path guarantees that erasing by the same mc_id happens + // at most once. INITED state may be erased by a thread that requested + // the compaction. RUNNING state is erased by mc thread only. + DBUG_ASSERT(0); + } + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); +} + +int Rdb_manual_compaction_thread::request_manual_compaction( + rocksdb::ColumnFamilyHandle *cf, rocksdb::Slice *start, + rocksdb::Slice *limit, int concurrency) { + int mc_id = -1; + RDB_MUTEX_LOCK_CHECK(m_mc_mutex); + if (m_requests.size() >= rocksdb_max_manual_compactions) { + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); + return mc_id; + } + Manual_compaction_request mcr; + mc_id = mcr.mc_id = ++m_latest_mc_id; + mcr.state = Manual_compaction_request::INITED; + mcr.cf = cf; + mcr.start = start; + mcr.limit = limit; + mcr.concurrency = concurrency; + m_requests.insert(std::make_pair(mcr.mc_id, mcr)); + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); + return mc_id; +} + +bool Rdb_manual_compaction_thread::is_manual_compaction_finished(int mc_id) { + bool finished = false; + RDB_MUTEX_LOCK_CHECK(m_mc_mutex); + if (m_requests.count(mc_id) == 0) { + finished = true; + } + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); + return finished; +} + +bool ha_rocksdb::check_bloom_and_set_bounds( + THD *thd, const Rdb_key_def &kd, const rocksdb::Slice &eq_cond, + const bool use_all_keys, size_t bound_len, uchar *const lower_bound, + uchar *const upper_bound, rocksdb::Slice *lower_bound_slice, + rocksdb::Slice *upper_bound_slice) { bool can_use_bloom = can_use_bloom_filter(thd, kd, eq_cond, use_all_keys); if (!can_use_bloom) { - setup_iterator_bounds(kd, eq_cond, - lower_bound_buf, upper_bound_buf, - out_lower_bound, out_upper_bound); + setup_iterator_bounds(kd, eq_cond, bound_len, lower_bound, upper_bound, + lower_bound_slice, upper_bound_slice); } return can_use_bloom; } @@ -12933,7 +13537,6 @@ void rdb_update_global_stats(const operation_type &type, uint count, int rdb_get_table_perf_counters(const char *const tablename, Rdb_perf_counters *const counters) { - DBUG_ASSERT(counters != nullptr); DBUG_ASSERT(tablename != nullptr); Rdb_table_handler *table_handler; @@ -12973,10 +13576,7 @@ const char *get_rdb_io_error_string(const RDB_IO_ERROR_TYPE err_type) { // so that we can capture as much data as possible to debug the root cause // more efficiently. #ifdef __GNUC__ -#pragma GCC push_options -#pragma GCC optimize("O0") #endif - void rdb_handle_io_error(const rocksdb::Status status, const RDB_IO_ERROR_TYPE err_type) { if (status.IsIOError()) { @@ -12991,6 +13591,9 @@ void rdb_handle_io_error(const rocksdb::Status status, } case RDB_IO_ERROR_BG_THREAD: { rdb_log_status_error(status, "BG thread failed to write to RocksDB"); + /* NO_LINT_DEBUG */ + sql_print_error("MyRocks: aborting on BG write error."); + abort(); break; } case RDB_IO_ERROR_GENERAL: { @@ -13026,9 +13629,7 @@ void rdb_handle_io_error(const rocksdb::Status status, } } #ifdef __GNUC__ -#pragma GCC pop_options #endif - Rdb_dict_manager *rdb_get_dict_manager(void) { return &dict_manager; } Rdb_ddl_manager *rdb_get_ddl_manager(void) { return &ddl_manager; } @@ -13329,6 +13930,42 @@ static void rocksdb_set_wal_bytes_per_sync( RDB_MUTEX_UNLOCK_CHECK(rdb_sysvars_mutex); } +/* + Validating and updating block cache size via sys_var::check path. + SetCapacity may take seconds when reducing block cache, and + sys_var::update holds LOCK_global_system_variables mutex, so + updating block cache size is done at check path instead. +*/ +static int rocksdb_validate_set_block_cache_size( + THD *thd MY_ATTRIBUTE((__unused__)), + struct st_mysql_sys_var *const var MY_ATTRIBUTE((__unused__)), + void *var_ptr, struct st_mysql_value *value) { + DBUG_ASSERT(value != nullptr); + + long long new_value; + + /* value is NULL */ + if (value->val_int(value, &new_value)) { + return HA_EXIT_FAILURE; + } + + if (new_value < RDB_MIN_BLOCK_CACHE_SIZE || + (uint64_t)new_value > (uint64_t)LONGLONG_MAX) { + return HA_EXIT_FAILURE; + } + + RDB_MUTEX_LOCK_CHECK(rdb_block_cache_resize_mutex); + const rocksdb::BlockBasedTableOptions &table_options = + rdb_get_table_options(); + + if (rocksdb_block_cache_size != new_value && table_options.block_cache) { + table_options.block_cache->SetCapacity(new_value); + } + *static_cast(var_ptr) = static_cast(new_value); + RDB_MUTEX_UNLOCK_CHECK(rdb_block_cache_resize_mutex); + return HA_EXIT_SUCCESS; +} + static int rocksdb_validate_update_cf_options(THD * /* unused */, struct st_mysql_sys_var * /*unused*/, @@ -13510,6 +14147,13 @@ double ha_rocksdb::read_time(uint index, uint ranges, ha_rows rows) { DBUG_RETURN((rows / 20.0) + 1); } +void ha_rocksdb::print_error(int error, myf errflag) { + if (error == HA_ERR_ROCKSDB_STATUS_BUSY) { + error = HA_ERR_LOCK_DEADLOCK; + } + handler::print_error(error, errflag); +} + std::string rdb_corruption_marker_file_name() { std::string ret(rocksdb_datadir); ret.append("/ROCKSDB_CORRUPTED"); @@ -13572,7 +14216,7 @@ maria_declare_plugin(rocksdb_se){ myrocks::rdb_i_s_perf_context, myrocks::rdb_i_s_perf_context_global, myrocks::rdb_i_s_cfoptions, myrocks::rdb_i_s_compact_stats, myrocks::rdb_i_s_global_info, myrocks::rdb_i_s_ddl, - myrocks::rdb_i_s_index_file_map, myrocks::rdb_i_s_lock_info, - myrocks::rdb_i_s_trx_info, + myrocks::rdb_i_s_sst_props, myrocks::rdb_i_s_index_file_map, + myrocks::rdb_i_s_lock_info, myrocks::rdb_i_s_trx_info, myrocks::rdb_i_s_deadlock_info maria_declare_plugin_end; diff --git a/storage/rocksdb/ha_rocksdb.h b/storage/rocksdb/ha_rocksdb.h index 5bf473a2fb0..9b3352594d9 100644 --- a/storage/rocksdb/ha_rocksdb.h +++ b/storage/rocksdb/ha_rocksdb.h @@ -107,6 +107,7 @@ struct Rdb_deadlock_info { std::string table_name; }; std::vector path; + int64_t deadlock_time; ulonglong victim_trx_id; }; @@ -147,6 +148,11 @@ const char *const BG_THREAD_NAME = "myrocks-bg"; */ const char *const INDEX_THREAD_NAME = "myrocks-index"; +/* + Name for the manual compaction thread. +*/ +const char *const MANUAL_COMPACTION_THREAD_NAME = "myrocks-mc"; + /* Separator between partition name and the qualifier. Sample usage: @@ -503,6 +509,12 @@ class ha_rocksdb : public my_core::handler { const rocksdb::Snapshot *m_scan_it_snapshot; + /* Buffers used for upper/lower bounds for m_scan_it. */ + uchar *m_scan_it_lower_bound; + uchar *m_scan_it_upper_bound; + rocksdb::Slice m_scan_it_lower_bound_slice; + rocksdb::Slice m_scan_it_upper_bound_slice; + Rdb_tbl_def *m_tbl_def; /* Primary Key encoder from KeyTupleFormat to StorageFormat */ @@ -566,12 +578,6 @@ class ha_rocksdb : public my_core::handler { uchar *m_dup_sk_packed_tuple; uchar *m_dup_sk_packed_tuple_old; - /* Buffers used for passing upper/bound eq conditions. */ - uchar *m_eq_cond_lower_bound; - uchar *m_eq_cond_upper_bound; - rocksdb::Slice m_eq_cond_lower_bound_slice; - rocksdb::Slice m_eq_cond_upper_bound_slice; - /* Temporary space for packing VARCHARs (we provide it to pack_record()/pack_index_tuple() calls). @@ -653,21 +659,20 @@ class ha_rocksdb : public my_core::handler { enum ha_rkey_function find_flag) const MY_ATTRIBUTE((__nonnull__, __warn_unused_result__)); void setup_iterator_bounds(const Rdb_key_def &kd, - const rocksdb::Slice &eq_cond, - uchar *lower_bound_buf, - uchar *upper_bound_buf, - rocksdb::Slice *out_lower_bound, - rocksdb::Slice *out_upper_bound); + const rocksdb::Slice &eq_cond, size_t bound_len, + uchar *const lower_bound, uchar *const upper_bound, + rocksdb::Slice *lower_bound_slice, + rocksdb::Slice *upper_bound_slice); bool can_use_bloom_filter(THD *thd, const Rdb_key_def &kd, const rocksdb::Slice &eq_cond, const bool use_all_keys); bool check_bloom_and_set_bounds(THD *thd, const Rdb_key_def &kd, const rocksdb::Slice &eq_cond, - const bool use_all_keys, - uchar *lower_bound_buf, - uchar *upper_bound_buf, - rocksdb::Slice *out_lower_bound, - rocksdb::Slice *out_upper_bound); + const bool use_all_keys, size_t bound_len, + uchar *const lower_bound, + uchar *const upper_bound, + rocksdb::Slice *lower_bound_slice, + rocksdb::Slice *upper_bound_slice); void setup_scan_iterator(const Rdb_key_def &kd, rocksdb::Slice *slice, const bool use_all_keys, const uint eq_cond_len) MY_ATTRIBUTE((__nonnull__)); @@ -1053,6 +1058,7 @@ public: } virtual double read_time(uint, uint, ha_rows rows) override; + virtual void print_error(int error, myf errflag) override; int open(const char *const name, int mode, uint test_if_locked) override MY_ATTRIBUTE((__warn_unused_result__)); @@ -1167,8 +1173,8 @@ private: MY_ATTRIBUTE((__nonnull__)); int compare_key_parts(const KEY *const old_key, - const KEY *const new_key) const; - MY_ATTRIBUTE((__nonnull__, __warn_unused_result__)); + const KEY *const new_key) const + MY_ATTRIBUTE((__nonnull__, __warn_unused_result__)); int compare_keys(const KEY *const old_key, const KEY *const new_key) const MY_ATTRIBUTE((__nonnull__, __warn_unused_result__)); @@ -1223,7 +1229,7 @@ private: int update_pk(const Rdb_key_def &kd, const struct update_row_info &row_info, const bool &pk_changed) MY_ATTRIBUTE((__warn_unused_result__)); int update_sk(const TABLE *const table_arg, const Rdb_key_def &kd, - const struct update_row_info &row_info) + const struct update_row_info &row_info, const bool bulk_load_sk) MY_ATTRIBUTE((__warn_unused_result__)); int update_indexes(const struct update_row_info &row_info, const bool &pk_changed) @@ -1277,7 +1283,9 @@ private: int finalize_bulk_load(bool print_client_error = true) MY_ATTRIBUTE((__warn_unused_result__)); -public: + int calculate_stats_for_table() MY_ATTRIBUTE((__warn_unused_result__)); + + public: int index_init(uint idx, bool sorted) override MY_ATTRIBUTE((__warn_unused_result__)); int index_end() override MY_ATTRIBUTE((__warn_unused_result__)); @@ -1370,9 +1378,6 @@ public: MY_ATTRIBUTE((__warn_unused_result__)); int analyze(THD *const thd, HA_CHECK_OPT *const check_opt) override MY_ATTRIBUTE((__warn_unused_result__)); - int calculate_stats(const TABLE *const table_arg, THD *const thd, - HA_CHECK_OPT *const check_opt) - MY_ATTRIBUTE((__warn_unused_result__)); enum_alter_inplace_result check_if_supported_inplace_alter( TABLE *altered_table, @@ -1402,7 +1407,7 @@ public: virtual void rpl_after_delete_rows() override; virtual void rpl_before_update_rows() override; virtual void rpl_after_update_rows() override; - virtual bool use_read_free_rpl(); + virtual bool use_read_free_rpl() override; #endif // MARIAROCKS_NOT_YET private: diff --git a/storage/rocksdb/ha_rocksdb_proto.h b/storage/rocksdb/ha_rocksdb_proto.h index 85c3968cc99..deb65edddd3 100644 --- a/storage/rocksdb/ha_rocksdb_proto.h +++ b/storage/rocksdb/ha_rocksdb_proto.h @@ -39,7 +39,12 @@ enum RDB_IO_ERROR_TYPE { const char *get_rdb_io_error_string(const RDB_IO_ERROR_TYPE err_type); void rdb_handle_io_error(const rocksdb::Status status, - const RDB_IO_ERROR_TYPE err_type); + const RDB_IO_ERROR_TYPE err_type) +#if defined(__clang__) + MY_ATTRIBUTE((optnone)); +#else + MY_ATTRIBUTE((optimize("O0"))); +#endif int rdb_normalize_tablename(const std::string &tablename, std::string *str) MY_ATTRIBUTE((__nonnull__, __warn_unused_result__)); diff --git a/storage/rocksdb/mysql-test/rocksdb/combinations b/storage/rocksdb/mysql-test/rocksdb/combinations new file mode 100644 index 00000000000..d49de3d38b3 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/combinations @@ -0,0 +1,6 @@ +[write_committed] +loose-rocksdb_write_policy=write_committed + +[write_prepared] +loose-rocksdb_write_policy=write_prepared +loose-rocksdb_commit_time_batch_for_recovery=on diff --git a/storage/rocksdb/mysql-test/rocksdb/include/have_write_committed.inc b/storage/rocksdb/mysql-test/rocksdb/include/have_write_committed.inc new file mode 100644 index 00000000000..681b966f680 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/include/have_write_committed.inc @@ -0,0 +1,3 @@ +if (`select count(*) = 0 from information_schema.session_variables where variable_name = 'rocksdb_write_policy' and variable_value = 'write_committed';`) { + --skip Test requires write_committed policy +} diff --git a/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result b/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result index 6325dc97cf5..32c0537c780 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result @@ -299,11 +299,13 @@ connection con1; show global variables like 'rocksdb_bulk_load%'; Variable_name Value rocksdb_bulk_load ON +rocksdb_bulk_load_allow_sk OFF rocksdb_bulk_load_allow_unsorted OFF rocksdb_bulk_load_size 1000 show session variables like 'rocksdb_bulk_load%'; Variable_name Value rocksdb_bulk_load ON +rocksdb_bulk_load_allow_sk OFF rocksdb_bulk_load_allow_unsorted OFF rocksdb_bulk_load_size 1000 CREATE TABLE t1 (i INT, j INT, PRIMARY KEY (i)) ENGINE = ROCKSDB; @@ -356,6 +358,7 @@ SET session rocksdb_merge_buf_size = 340; show variables like 'rocksdb_bulk_load%'; Variable_name Value rocksdb_bulk_load OFF +rocksdb_bulk_load_allow_sk OFF rocksdb_bulk_load_allow_unsorted OFF rocksdb_bulk_load_size 1000 CREATE TABLE t1 (a VARCHAR(80)) ENGINE=RocksDB; @@ -463,3 +466,24 @@ t1 CREATE TABLE `t1` ( KEY `kb` (`b`(8)) ) ENGINE=ROCKSDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin DROP TABLE t1; +SET @prior_rocksdb_table_stats_sampling_pct = @@rocksdb_table_stats_sampling_pct; +set global rocksdb_table_stats_sampling_pct = 100; +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY ka(a)) ENGINE=RocksDB; +INSERT INTO t1 (a, b) VALUES (1, 10); +INSERT INTO t1 (a, b) VALUES (2, 10); +INSERT INTO t1 (a, b) VALUES (3, 20); +INSERT INTO t1 (a, b) VALUES (4, 20); +set global rocksdb_force_flush_memtable_now=1; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +SHOW INDEX in 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 a A 4 NULL NULL LSMTREE +ALTER TABLE t1 ADD INDEX kb(b), ALGORITHM=INPLACE; +SHOW INDEX in 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 a A 4 NULL NULL LSMTREE +t1 1 kb 1 b A 2 NULL NULL YES LSMTREE +DROP TABLE t1; +SET global rocksdb_table_stats_sampling_pct = @prior_rocksdb_table_stats_sampling_pct; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace_sstfilewriter.result b/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace_sstfilewriter.result index 08f2329f688..0617232f1e3 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace_sstfilewriter.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace_sstfilewriter.result @@ -17,7 +17,7 @@ ALTER TABLE t1 ADD INDEX kb(b), ALGORITHM=INPLACE; set @tmp= @@rocksdb_max_row_locks; set session rocksdb_max_row_locks=1000; ALTER TABLE t1 ADD INDEX kb_copy(b), ALGORITHM=COPY; -ERROR HY000: Status error 10 received from RocksDB: Operation aborted: Failed to acquire lock due to max_num_locks limit +ERROR HY000: Got error 10 'Operation aborted: Failed to acquire lock due to max_num_locks limit' from ROCKSDB set session rocksdb_bulk_load=1; ALTER TABLE t1 ADD INDEX kb_copy(b), ALGORITHM=COPY; set session rocksdb_bulk_load=0; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/autoinc_debug.result b/storage/rocksdb/mysql-test/rocksdb/r/autoinc_debug.result index fe08cd7c361..604e5572eab 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/autoinc_debug.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/autoinc_debug.result @@ -59,12 +59,10 @@ insert into t values (); set debug_dbug="+d,crash_commit_before"; commit; ERROR HY000: Lost connection to MySQL server during query -select table_schema, table_name, auto_increment from information_schema.tables where table_name = 't'; -table_schema table_name auto_increment -test t 4 -select max(i) from t; -max(i) -3 +select max(i) into @row_max from t; +select table_schema, table_name, auto_increment > @row_max from information_schema.tables where table_name = 't'; +table_schema table_name auto_increment > @row_max +test t 1 # After engine prepare begin; insert into t values (); @@ -72,12 +70,10 @@ insert into t values (); set debug_dbug="+d,crash_commit_after_prepare"; commit; ERROR HY000: Lost connection to MySQL server during query -select table_schema, table_name, auto_increment from information_schema.tables where table_name = 't'; -table_schema table_name auto_increment -test t 4 -select max(i) from t; -max(i) -3 +select max(i) into @row_max from t; +select table_schema, table_name, auto_increment > @row_max from information_schema.tables where table_name = 't'; +table_schema table_name auto_increment > @row_max +test t 1 # After binlog begin; insert into t values (); @@ -85,12 +81,10 @@ insert into t values (); set debug_dbug="+d,crash_commit_after_log"; commit; ERROR HY000: Lost connection to MySQL server during query -select table_schema, table_name, auto_increment from information_schema.tables where table_name = 't'; -table_schema table_name auto_increment -test t 6 -select max(i) from t; -max(i) -5 +select max(i) into @row_max from t; +select table_schema, table_name, auto_increment > @row_max from information_schema.tables where table_name = 't'; +table_schema table_name auto_increment > @row_max +test t 1 # After everything begin; insert into t values (); @@ -98,10 +92,8 @@ insert into t values (); set debug_dbug="+d,crash_commit_after"; commit; ERROR HY000: Lost connection to MySQL server during query -select table_schema, table_name, auto_increment from information_schema.tables where table_name = 't'; -table_schema table_name auto_increment -test t 8 -select max(i) from t; -max(i) -7 +select max(i) into @row_max from t; +select table_schema, table_name, auto_increment > @row_max from information_schema.tables where table_name = 't'; +table_schema table_name auto_increment > @row_max +test t 1 drop table t; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars.result b/storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars.result index 8cc9b070a70..f59b841a595 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars.result @@ -150,3 +150,29 @@ CREATE TABLE t0(c0 BLOB) ENGINE=ROCKSDB; INSERT INTO t0 VALUES(0); ALTER TABLE t0 AUTO_INCREMENT=0; DROP TABLE t0; +#--------------------------------------------------------------- +# MDEV-16703 Assertion failed in load_auto_incr_value_from_index +#--------------------------------------------------------------- +CREATE TABLE t1 (pk INT AUTO_INCREMENT, a INT, PRIMARY KEY(pk)) ENGINE=RocksDB; +INSERT INTO t1 (a) VALUES (1); +UPDATE t1 SET pk = 3; +ALTER TABLE t1 AUTO_INCREMENT 2; +DROP TABLE t1; +#---------------------------------- +# Issue #792 Crash in autoincrement +#---------------------------------- +CREATE TABLE t1(C1 DOUBLE AUTO_INCREMENT KEY,C2 CHAR) ENGINE=ROCKSDB; +INSERT INTO t1 VALUES(2177,0); +DROP TABLE t1; +CREATE TABLE t0(c0 BLOB) ENGINE=ROCKSDB; +INSERT INTO t0 VALUES(0); +ALTER TABLE t0 AUTO_INCREMENT=0; +DROP TABLE t0; +#---------------------------------- +# Issue #869 Crash in autoincrement +#---------------------------------- +CREATE TABLE t1 (pk INT AUTO_INCREMENT, a INT, PRIMARY KEY(pk)) ENGINE=RocksDB; +INSERT INTO t1 (a) VALUES (1); +UPDATE t1 SET pk = 3; +ALTER TABLE t1 AUTO_INCREMENT 2; +DROP TABLE t1; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter_bulk_load.result b/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter_bulk_load.result new file mode 100644 index 00000000000..4b02d1103cf --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter_bulk_load.result @@ -0,0 +1,15 @@ +create table r1 (id bigint primary key, value bigint) engine=rocksdb; +create table r2 (id bigint, value bigint, primary key (id) comment 'cf2') engine=rocksdb; +set session rocksdb_bulk_load=1; +set session rocksdb_bulk_load=0; +select variable_value into @h from information_schema.global_status where variable_name='rocksdb_block_cache_filter_hit'; +insert into r1 values (100, 100); +select variable_value-@h from information_schema.global_status where variable_name='rocksdb_block_cache_filter_hit'; +variable_value-@h +1 +select variable_value into @h from information_schema.global_status where variable_name='rocksdb_block_cache_filter_hit'; +insert into r2 values (100, 100); +select variable_value-@h from information_schema.global_status where variable_name='rocksdb_block_cache_filter_hit'; +variable_value-@h +0 +DROP TABLE r1, r2; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_sk.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_sk.result new file mode 100644 index 00000000000..42f820a2a42 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_sk.result @@ -0,0 +1,229 @@ +SET rocksdb_bulk_load_size=15; +CREATE TABLE t4 (a INT, b INT, c INT, +PRIMARY KEY (a), +KEY (b), +KEY (c) COMMENT "rev:cf") ENGINE=ROCKSDB; +CREATE TABLE t3 (a INT, b INT, c INT, +PRIMARY KEY (a), +KEY (b), +KEY (c) COMMENT "rev:cf") ENGINE=ROCKSDB; +CREATE TABLE t2 (a INT, b INT, c INT, +PRIMARY KEY (a), +KEY (b), +KEY (c) COMMENT "rev:cf") ENGINE=ROCKSDB; +CREATE TABLE t1 (a INT, b INT, c INT, +PRIMARY KEY (a), +KEY (b), +KEY (c) COMMENT "rev:cf") ENGINE=ROCKSDB; +SET rocksdb_bulk_load=1; +INSERT INTO t1 SELECT * FROM t3 FORCE INDEX (PRIMARY) ORDER BY a; +SELECT count(*) FROM t1 FORCE INDEX (PRIMARY); +count(*) +0 +SELECT count(*) FROM t1 FORCE INDEX (b); +count(*) +10 +SELECT count(*) FROM t1 FORCE INDEX (c); +count(*) +10 +SET rocksdb_bulk_load=0; +SELECT * FROM t1 FORCE INDEX (PRIMARY); +a b c +-9 11 11 +-7 9 9 +-5 7 7 +-3 5 5 +-1 3 3 +2 0 0 +4 -2 -2 +6 -4 -4 +8 -6 -6 +10 -8 -8 +SELECT b FROM t1 FORCE INDEX (b); +b +-8 +-6 +-4 +-2 +0 +3 +5 +7 +9 +11 +SELECT c FROM t1 FORCE INDEX (c); +c +-8 +-6 +-4 +-2 +0 +3 +5 +7 +9 +11 +Checksums should match +CHECKSUM TABLE t3; +Table Checksum +test.t3 3862424802 +CHECKSUM TABLE t1; +Table Checksum +test.t1 3862424802 +SET rocksdb_bulk_load_allow_sk=1; +SET rocksdb_bulk_load=1; +INSERT INTO t4 SELECT * FROM t3 FORCE INDEX (PRIMARY) ORDER BY a; +SELECT count(*) FROM t4 FORCE INDEX (PRIMARY); +count(*) +0 +SELECT count(*) FROM t4 FORCE INDEX (b); +count(*) +0 +SELECT count(*) FROM t4 FORCE INDEX (c); +count(*) +0 +SET rocksdb_bulk_load=0; +SELECT * FROM t4 FORCE INDEX (PRIMARY); +a b c +-9 11 11 +-7 9 9 +-5 7 7 +-3 5 5 +-1 3 3 +2 0 0 +4 -2 -2 +6 -4 -4 +8 -6 -6 +10 -8 -8 +SELECT b FROM t4 FORCE INDEX (b); +b +-8 +-6 +-4 +-2 +0 +3 +5 +7 +9 +11 +SELECT c FROM t4 FORCE INDEX (c); +c +-8 +-6 +-4 +-2 +0 +3 +5 +7 +9 +11 +Checksums should match +CHECKSUM TABLE t3; +Table Checksum +test.t3 3862424802 +CHECKSUM TABLE t4; +Table Checksum +test.t4 3862424802 +SET rocksdb_bulk_load_allow_unsorted=1; +SET rocksdb_bulk_load_allow_sk=1; +SET rocksdb_bulk_load=1; +INSERT INTO t2 SELECT * FROM t3 WHERE b >= 0 ORDER BY b; +INSERT INTO t2 SELECT * FROM t3 WHERE b < 0 ORDER BY b; +SELECT count(*) FROM t2 FORCE INDEX (PRIMARY); +count(*) +0 +SELECT count(*) FROM t2 FORCE INDEX (b); +count(*) +0 +SELECT count(*) FROM t2 FORCE INDEX (c); +count(*) +0 +SELECT count(*) FROM t2 FORCE INDEX (PRIMARY); +count(*) +0 +SELECT count(*) FROM t2 FORCE INDEX (b); +count(*) +0 +SELECT count(*) FROM t2 FORCE INDEX (c); +count(*) +0 +SET rocksdb_bulk_load=0; +SELECT * FROM t2 FORCE INDEX (PRIMARY); +a b c +-19 21 21 +-17 19 19 +-15 17 17 +-13 15 15 +-11 13 13 +-9 11 11 +-7 9 9 +-5 7 7 +-3 5 5 +-1 3 3 +2 0 0 +4 -2 -2 +6 -4 -4 +8 -6 -6 +10 -8 -8 +12 -10 -10 +14 -12 -12 +16 -14 -14 +18 -16 -16 +20 -18 -18 +SELECT b FROM t2 FORCE INDEX (b); +b +-18 +-16 +-14 +-12 +-10 +-8 +-6 +-4 +-2 +0 +3 +5 +7 +9 +11 +13 +15 +17 +19 +21 +SELECT c FROM t2 FORCE INDEX (c); +c +-18 +-16 +-14 +-12 +-10 +-8 +-6 +-4 +-2 +0 +3 +5 +7 +9 +11 +13 +15 +17 +19 +21 +Checksums should match +CHECKSUM TABLE t3; +Table Checksum +test.t3 1495594118 +CHECKSUM TABLE t2; +Table Checksum +test.t2 1495594118 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/cardinality.result b/storage/rocksdb/mysql-test/rocksdb/r/cardinality.result index 4b201d523d9..d037c636a16 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/cardinality.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/cardinality.result @@ -82,4 +82,19 @@ t1 1 t1_5 2 c1 A 100000 NULL NULL YES LSMTREE SELECT table_name, table_rows FROM information_schema.tables WHERE table_schema = DATABASE(); table_name table_rows t1 100000 -drop table t1; +CREATE TABLE t2 (a INT, b INT, c INT, d INT, e INT, f INT, g INT, +PRIMARY KEY (a), KEY (c, b, a, d, e, f, g)) +ENGINE=ROCKSDB; +SET GLOBAL rocksdb_force_flush_memtable_now = 1; +ANALYZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 analyze status OK +cardinality of the columns after 'a' must be equal to the cardinality of column 'a' +SELECT CARDINALITY INTO @c FROM information_schema.statistics WHERE TABLE_NAME='t2' AND INDEX_NAME='c' AND COLUMN_NAME='a'; +SELECT COLUMN_NAME, CARDINALITY = @c FROM information_schema.statistics WHERE TABLE_NAME='t2' AND INDEX_NAME='c' AND SEQ_IN_INDEX > 3; +COLUMN_NAME CARDINALITY = @c +d 1 +e 1 +f 1 +g 1 +drop table t1, t2; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/collation.result b/storage/rocksdb/mysql-test/rocksdb/r/collation.result index e372cbe2109..10e0d9b0002 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/collation.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/collation.result @@ -1,6 +1,7 @@ -SET @start_global_value = @@global.ROCKSDB_STRICT_COLLATION_EXCEPTIONS; -DROP TABLE IF EXISTS t1; +call mtr.add_suppression("Invalid pattern"); CREATE TABLE t1 (id INT primary key, value varchar(50), value2 varbinary(50), value3 text) engine=rocksdb charset utf8; +ALTER TABLE t1 ADD INDEX (value); +ERROR HY000: Unsupported collation on string indexed column test.t1.value Use binary collation (binary, latin1_bin, utf8_bin). DROP TABLE t1; CREATE TABLE t1 (id INT primary key, value varchar(50), value2 varbinary(50), value3 text, index(value)) engine=rocksdb charset utf8; ERROR HY000: Unsupported collation on string indexed column test.t1.value Use binary collation (latin1_bin, binary, utf8_bin). @@ -13,6 +14,7 @@ SET GLOBAL rocksdb_strict_collation_check=1; CREATE TABLE t1 (id INT primary key, value varchar(50), value2 varbinary(50), value3 text, index(value2)) engine=rocksdb charset utf8; DROP TABLE t1; CREATE TABLE t1 (id varchar(20), value varchar(50), value2 varchar(50), value3 text, primary key (id), index(value, value2)) engine=rocksdb charset latin1 collate latin1_bin; +ALTER TABLE t1 collate=latin1_general_ci; DROP TABLE t1; CREATE TABLE t1 (id varchar(20), value varchar(50), value2 varchar(50), value3 text, primary key (id), index(value, value2)) engine=rocksdb charset utf8 collate utf8_bin; DROP TABLE t1; @@ -127,4 +129,16 @@ CREATE TABLE abcd (id INT PRIMARY KEY, value varchar(50), index(value)) engine=r ERROR HY000: Unsupported collation on string indexed column test.abcd.value Use binary collation (latin1_bin, binary, utf8_bin). DROP TABLE abc; SET GLOBAL rocksdb_strict_collation_exceptions=null; -SET GLOBAL rocksdb_strict_collation_exceptions=@start_global_value; +SET GLOBAL rocksdb_strict_collation_check=1; +CREATE TABLE t1 (id INT primary key, value varchar(50), value2 varbinary(50), value3 text, index(value)) engine=rocksdb charset utf8; +Warnings: +Warning 1210 Unsupported collation on string indexed column test.t1.value Use binary collation (binary, latin1_bin, utf8_bin). +DROP TABLE t1; +CREATE TABLE t1 (id INT primary key, value varchar(50), value2 varbinary(50), value3 text) engine=rocksdb charset utf8; +ALTER TABLE t1 ADD INDEX (value); +Warnings: +Warning 1210 Unsupported collation on string indexed column test.t1.value Use binary collation (binary, latin1_bin, utf8_bin). +DROP TABLE t1; +CREATE TABLE t1 (id varchar(20), value varchar(50), value2 varchar(50), value3 text, primary key (id), index(value, value2)) engine=rocksdb charset latin1 collate latin1_bin; +ALTER TABLE t1 collate=latin1_general_ci; +DROP TABLE t1; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/com_rpc_tx.result b/storage/rocksdb/mysql-test/rocksdb/r/com_rpc_tx.result new file mode 100644 index 00000000000..789ce12e900 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/r/com_rpc_tx.result @@ -0,0 +1,21 @@ +CREATE DATABASE db_rpc; +USE db_rpc; +CREATE TABLE t1(pk INT PRIMARY KEY) ENGINE=rocksdb; +SET GLOBAL rocksdb_enable_2pc=1; +SET autocommit = 0; +SET autocommit = 0; +BEGIN; +BEGIN; +SELECT * from t1; +pk +SELECT * from t1; +pk +INSERT INTO t1 VALUES(1); +INSERT INTO t1 VALUES(2); +COMMIT; +COMMIT; +SELECT * from db_rpc.t1; +pk +1 +2 +DROP DATABASE db_rpc; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/create_no_primary_key_table.result b/storage/rocksdb/mysql-test/rocksdb/r/create_no_primary_key_table.result new file mode 100644 index 00000000000..e5aeb57ebdf --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/r/create_no_primary_key_table.result @@ -0,0 +1,38 @@ +USE mysql; +CREATE TABLE mysql_table (a INT) ENGINE=ROCKSDB; +CREATE TABLE test.mysql_table (a INT) ENGINE=ROCKSDB; +ERROR HY000: Table without primary key cannot be created outside mysql schema. +USE test; +CREATE TABLE mysql_table (a INT) ENGINE=ROCKSDB; +ERROR HY000: Table without primary key cannot be created outside mysql schema. +CREATE TABLE IF NOT EXISTS mysql_table_2 (a INT) ENGINE=ROCKSDB; +ERROR HY000: Table without primary key cannot be created outside mysql schema. +CREATE TABLE mysql_table_no_cols ENGINE=ROCKSDB; +ERROR HY000: Table without primary key cannot be created outside mysql schema. +CREATE TABLE mysql.mysql_table_2 (a INT) ENGINE=ROCKSDB; +CREATE TABLE mysql_primkey (a INT PRIMARY KEY, b INT, c INT, d INT, INDEX (c)) ENGINE=ROCKSDB; +ALTER TABLE mysql_primkey DROP b, DROP a, ADD (f INT PRIMARY KEY); +ALTER TABLE mysql_primkey DROP PRIMARY KEY; +ERROR HY000: Table without primary key cannot be created outside mysql schema. +CREATE TABLE mysql_primkey2 (a INT PRIMARY KEY, b INT, c INT) ENGINE=ROCKSDB; +ALTER TABLE mysql_primkey2 DROP b; +ALTER TABLE mysql_primkey2 ADD (b INT); +ALTER TABLE mysql_primkey2 DROP c, DROP A; +ERROR HY000: Table without primary key cannot be created outside mysql schema. +CREATE TABLE mysql_primkey3 (a INT PRIMARY KEY, b INT, c INT, INDEX indexonb (b), INDEX indexonc (c)) ENGINE=ROCKSDB; +ALTER TABLE mysql_primkey3 DROP INDEX indexonb; +ALTER TABLE mysql_primkey3 DROP c; +ALTER TABLE mysql_primkey3 DROP PRIMARY KEY, ADD PRIMARY KEY(b); +CREATE TABLE mysql_primkey4(a INT, b INT, PRIMARY KEY(a), INDEX si (a, b)) ENGINE=ROCKSDB; +DROP INDEX si ON mysql_primkey4; +DROP INDEX `PRIMARY` ON mysql_primkey4; +ERROR HY000: Table without primary key cannot be created outside mysql schema. +ALTER TABLE mysql.mysql_table ADD PRIMARY KEY (a); +ALTER TABLE mysql.mysql_table DROP PRIMARY KEY; +DROP TABLE mysql_primkey; +DROP TABLE mysql_primkey2; +DROP TABLE mysql_primkey3; +DROP TABLE mysql_primkey4; +USE mysql; +DROP TABLE mysql_table; +DROP TABLE mysql_table_2; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/ddl_high_priority.result b/storage/rocksdb/mysql-test/rocksdb/r/ddl_high_priority.result index 39130475349..50733f81598 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/ddl_high_priority.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/ddl_high_priority.result @@ -45,7 +45,7 @@ set high_priority_ddl = 1; select @@high_priority_ddl; @@high_priority_ddl 1 -lock tables t1 write; +rename table t1 to t2; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 alter table t1 modify i bigint;; set high_priority_ddl = 0; @@ -98,7 +98,7 @@ set high_priority_ddl = 1; select @@high_priority_ddl; @@high_priority_ddl 1 -lock tables t1 write; +rename table t1 to t2; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 alter table t1 rename t1_new;; set high_priority_ddl = 0; @@ -152,7 +152,7 @@ set high_priority_ddl = 1; select @@high_priority_ddl; @@high_priority_ddl 1 -lock tables t1 write; +rename table t1 to t2; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 drop table t1;; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 @@ -202,7 +202,7 @@ set high_priority_ddl = 1; select @@high_priority_ddl; @@high_priority_ddl 1 -lock tables t1 write; +rename table t1 to t2; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 drop table t1;; set high_priority_ddl = 0; @@ -251,7 +251,7 @@ set high_priority_ddl = 1; select @@high_priority_ddl; @@high_priority_ddl 1 -lock tables t1 write; +rename table t1 to t2; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 alter table t1 modify i bigint;; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 @@ -302,7 +302,7 @@ set high_priority_ddl = 1; select @@high_priority_ddl; @@high_priority_ddl 1 -lock tables t1 write; +rename table t1 to t2; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 create index idx1 on t1 (i);; set high_priority_ddl = 0; @@ -342,7 +342,7 @@ set high_priority_ddl = 1; select @@high_priority_ddl; @@high_priority_ddl 1 -lock tables t1 write; +rename table t1 to t2; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 drop index idx1 on t1;; set high_priority_ddl = 0; @@ -390,7 +390,7 @@ set high_priority_ddl = 1; select @@high_priority_ddl; @@high_priority_ddl 1 -lock tables t1 write; +rename table t1 to t2; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 truncate t1;; set high_priority_ddl = 0; @@ -438,7 +438,7 @@ set high_priority_ddl = 1; select @@high_priority_ddl; @@high_priority_ddl 1 -lock tables t1 write; +rename table t1 to t2; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 create trigger ins_sum before insert on t1 for each row set @sum = @sum + new.i;; set high_priority_ddl = 0; @@ -478,7 +478,7 @@ set high_priority_ddl = 1; select @@high_priority_ddl; @@high_priority_ddl 1 -lock tables t1 write; +rename table t1 to t2; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 drop trigger ins_sum;; set high_priority_ddl = 0; @@ -528,7 +528,7 @@ set high_priority_ddl = 1; select @@high_priority_ddl; @@high_priority_ddl 1 -lock tables t1 write; +rename table t1 to t2; ERROR HY000: Lock wait timeout exceeded; try restarting transaction: Timeout on table metadata: test.t1 optimize table t1;; Table Op Msg_type Msg_text @@ -538,6 +538,55 @@ connection: default (for show processlist) show processlist; Id User Host db Command Time State Info Rows examined Rows sent Tid Srv_Id root test