[Commits] aaebd623e98: Apply patch: Support parsing index comments for partial indexes
revision-id: aaebd623e98e59db3efe1b231307e4142240c485 (percona-202102-53-gaaebd623e98) parent(s): f286a3586f1fec1f9c7bad5314136e176ea30653 author: Sergei Petrunia committer: Sergei Petrunia timestamp: 2021-05-17 17:43:41 +0300 message: Apply patch: Support parsing index comments for partial indexes Summary: This adds support for parsing the comment section on secondary keys for partial index keywords. This is then populated onto the `Rdb_key_def` structure. This isn't persisted to the data dictionary because we don't really need this information for compaction (unlike some of our TTL related fields). Test Plan: mtr Reviewers: luqun, herman, yzha, #mysql_eng Subscribers: pgl Differential Revision: https://phabricator.intern.facebook.com/D25933175 --- .../rocksdb/r/partial_index_validation.result | 237 +++++++++++++++++++++ .../suite/rocksdb/t/partial_index_validation.test | 237 +++++++++++++++++++++ storage/rocksdb/ha_rocksdb.cc | 5 + storage/rocksdb/rdb_datadic.cc | 160 ++++++++++---- storage/rocksdb/rdb_datadic.h | 15 +- storage/rocksdb/rdb_global.h | 12 ++ 6 files changed, 618 insertions(+), 48 deletions(-) diff --git a/mysql-test/suite/rocksdb/r/partial_index_validation.result b/mysql-test/suite/rocksdb/r/partial_index_validation.result new file mode 100644 index 00000000000..b0303aab4fa --- /dev/null +++ b/mysql-test/suite/rocksdb/r/partial_index_validation.result @@ -0,0 +1,237 @@ +# +# Negative test cases +# +CREATE TABLE t ( +c1 INT, +c2 INT, +PRIMARY KEY (c1) COMMENT 'p0_cfname=aaa;p1_cfname=bbb;p2_cfname=ccc', +KEY (c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB +PARTITION BY LIST(c1) ( +PARTITION p0 VALUES IN (1, 4, 7), +PARTITION p1 VALUES IN (2, 5, 8), +PARTITION p2 VALUES IN (3, 6, 9) +); +ERROR 42000: Partial indexes not supported for partitioned tables. +CREATE TABLE t ( +c1 INT, +c2 INT, +PRIMARY KEY (c1) COMMENT 'p0_cfname=aaa;p1_cfname=bbb;p2_cfname=ccc', +KEY (c2) COMMENT 'p0_partial_group_keyparts=2;p0_partial_group_threshold=10000' +) ENGINE=ROCKSDB +PARTITION BY LIST(c1) ( +PARTITION p0 VALUES IN (1, 4, 7), +PARTITION p1 VALUES IN (2, 5, 8), +PARTITION p2 VALUES IN (3, 6, 9) +); +ERROR 42000: Partial indexes not supported for partitioned tables. +CREATE TABLE t ( +c1 INT, +c2 INT, +PRIMARY KEY (c1) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +ERROR HY000: Primary key cannot be a partial index. +CREATE TABLE t ( +c1 INT, +c2 INT, +KEY (c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +ERROR 42000: Autoincrement key cannot be a partial index. +CREATE TABLE t ( +c1 INT, +c2 INT, +PRIMARY KEY (c1), +UNIQUE KEY (c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +ERROR 42000: Unique key cannot be a partial index. +CREATE TABLE t ( +c1 INT, +c2 INT AUTO_INCREMENT, +PRIMARY KEY (c1), +KEY (c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +ERROR 42000: Autoincrement key cannot be a partial index. +CREATE TABLE t ( +c1 INT, +c2 INT, +PRIMARY KEY (c1), +KEY (c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=asdf' +) ENGINE=ROCKSDB; +ERROR HY000: Invalid partial index group size threshold. +CREATE TABLE t ( +c1 INT, +c2 INT, +PRIMARY KEY (c1), +KEY (c2) COMMENT 'partial_group_keyparts=asdf;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +ERROR HY000: Invalid number of keyparts in partial index group. +CREATE TABLE t ( +c1 INT, +c2 INT, +c3 INT, +c4 INT, +PRIMARY KEY (c1, c2), +KEY (c1, c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +ERROR HY000: Too many keyparts in partial index group. +CREATE TABLE t ( +c1 INT, +c2 INT, +c3 INT, +c4 INT, +PRIMARY KEY (c1, c2), +KEY (c1, c2, c4) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +ERROR HY000: Too many keyparts in partial index group. +CREATE TABLE t ( +c1 INT, +c2 INT, +c3 INT, +c4 INT, +PRIMARY KEY (c1, c2), +KEY (c1, c2, c4) COMMENT 'partial_group_keyparts=3;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +ERROR HY000: Too many keyparts in partial index group. +CREATE TABLE t ( +c1 INT, +c2 INT, +c3 INT, +c4 INT, +PRIMARY KEY (c1, c2, c3), +KEY (c1, c2, c4) COMMENT 'partial_group_keyparts=3;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +ERROR HY000: Too many keyparts in partial index group. +CREATE TABLE t ( +c1 INT, +c2 INT, +c3 INT, +c4 INT, +PRIMARY KEY (c2, c3, c4), +KEY (c1, c2, c4) COMMENT 'partial_group_keyparts=3;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +ERROR HY000: Too many keyparts in partial index group. +CREATE TABLE t ( +c1 INT, +c2 VARCHAR(255), +c3 INT, +c4 INT, +PRIMARY KEY (c1, c2(5), c3), +KEY (c1, c2(4), c4) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +ERROR HY000: Mismatched keyparts in partial index group. +# +# Positive test cases +# +CREATE TABLE t ( +c1 INT, +c2 INT, +c3 INT, +c4 INT, +c5 INT, +PRIMARY KEY (c1, c2, c5), +KEY (c1, c2, c4) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +DROP TABLE t; +CREATE TABLE t ( +c1 INT, +c2 INT, +c3 INT, +c4 INT, +PRIMARY KEY (c1, c2, c3), +KEY (c1, c2, c4) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +DROP TABLE t; +CREATE TABLE t ( +c1 INT, +c2 INT, +c3 INT, +c4 INT, +PRIMARY KEY (c1, c2, c3), +KEY (c1, c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +DROP TABLE t; +CREATE TABLE t ( +c1 INT, +c2 VARCHAR(255), +c3 INT, +c4 INT, +PRIMARY KEY (c1, c2(4), c3), +KEY (c1, c2(4), c4) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +DROP TABLE t; +CREATE TABLE t ( +c1 INT, +c2 VARCHAR(255), +c3 INT, +c4 INT, +PRIMARY KEY (c1, c2(4), c3), +KEY (c1, c2(4), c4) COMMENT 'partial_group_keyparts=1;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +DROP TABLE t; +CREATE TABLE t ( +id1 bigint(20) unsigned NOT NULL DEFAULT '0', +id1_type int(10) unsigned NOT NULL DEFAULT '0', +id2 bigint(20) unsigned NOT NULL DEFAULT '0', +id2_type int(10) unsigned NOT NULL DEFAULT '0', +assoc_type bigint(20) unsigned NOT NULL DEFAULT '0', +visibility tinyint(3) NOT NULL DEFAULT '0', +data varchar(255) COLLATE latin1_bin NOT NULL DEFAULT '', +time int(10) unsigned NOT NULL DEFAULT '0', +version bigint(20) unsigned NOT NULL DEFAULT '0', +PRIMARY KEY (assoc_type, id1, id2) COMMENT 'cf_assoc', +KEY id1_type (assoc_type, id1, visibility, time, id2, version, data) COMMENT 'cfname=rev:cf_assoc_id1_type;partial_group_keyparts=1;partial_group_threshold=10000' +) ENGINE=ROCKSDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; +Warnings: +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +DROP TABLE t; +CREATE TABLE t ( +id1 binary(16) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', +raw_key text COLLATE latin1_bin, +id2 bigint(20) unsigned NOT NULL DEFAULT '0', +id2_type int(10) unsigned NOT NULL DEFAULT '0', +assoc_type bigint(20) unsigned NOT NULL DEFAULT '0', +visibility tinyint(3) NOT NULL DEFAULT '0', +data varchar(255) COLLATE latin1_bin NOT NULL DEFAULT '', +time int(10) unsigned NOT NULL DEFAULT '0', +version bigint(20) unsigned NOT NULL DEFAULT '0', +PRIMARY KEY (assoc_type, id1, id2) COMMENT 'cf_assoc', +KEY id1_type (assoc_type, id1, visibility, time, id2, version, data) COMMENT 'cfname=rev:cf_assoc_id1_type;partial_group_keyparts=1;partial_group_threshold=10000' +) ENGINE=ROCKSDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; +Warnings: +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +DROP TABLE t; +CREATE TABLE t ( +id1 bigint(20) unsigned NOT NULL DEFAULT '0', +id1_type int(10) unsigned NOT NULL DEFAULT '0', +id2 bigint(20) unsigned NOT NULL DEFAULT '0', +id2_type int(10) unsigned NOT NULL DEFAULT '0', +assoc_type bigint(20) unsigned NOT NULL DEFAULT '0', +visibility tinyint(4) NOT NULL DEFAULT '0', +data text COLLATE latin1_bin NOT NULL, +time int(10) unsigned NOT NULL DEFAULT '0', +version bigint(20) unsigned NOT NULL DEFAULT '0', +PRIMARY KEY (assoc_type, id1, id2) COMMENT 'cf_assoc', +KEY id1_type (assoc_type, id1, visibility, time, id2, version, data(255)) COMMENT 'cfname=rev:cf_assoc_id1_type;partial_group_keyparts=1;partial_group_threshold=10000' +) ENGINE=ROCKSDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; +Warnings: +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +Warning 1681 Integer display width is deprecated and will be removed in a future release. +DROP TABLE t; diff --git a/mysql-test/suite/rocksdb/t/partial_index_validation.test b/mysql-test/suite/rocksdb/t/partial_index_validation.test new file mode 100644 index 00000000000..92cd859a904 --- /dev/null +++ b/mysql-test/suite/rocksdb/t/partial_index_validation.test @@ -0,0 +1,237 @@ + +--echo # +--echo # Negative test cases +--echo # + +--error ER_NOT_SUPPORTED_YET +CREATE TABLE t ( + c1 INT, + c2 INT, + PRIMARY KEY (c1) COMMENT 'p0_cfname=aaa;p1_cfname=bbb;p2_cfname=ccc', + KEY (c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB +PARTITION BY LIST(c1) ( + PARTITION p0 VALUES IN (1, 4, 7), + PARTITION p1 VALUES IN (2, 5, 8), + PARTITION p2 VALUES IN (3, 6, 9) +); + +--error ER_NOT_SUPPORTED_YET +CREATE TABLE t ( + c1 INT, + c2 INT, + PRIMARY KEY (c1) COMMENT 'p0_cfname=aaa;p1_cfname=bbb;p2_cfname=ccc', + KEY (c2) COMMENT 'p0_partial_group_keyparts=2;p0_partial_group_threshold=10000' +) ENGINE=ROCKSDB +PARTITION BY LIST(c1) ( + PARTITION p0 VALUES IN (1, 4, 7), + PARTITION p1 VALUES IN (2, 5, 8), + PARTITION p2 VALUES IN (3, 6, 9) +); + +--error ER_WRONG_ARGUMENTS +CREATE TABLE t ( + c1 INT, + c2 INT, + PRIMARY KEY (c1) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; + +--error ER_NOT_SUPPORTED_YET +CREATE TABLE t ( + c1 INT, + c2 INT, + KEY (c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; + +--error ER_NOT_SUPPORTED_YET +CREATE TABLE t ( + c1 INT, + c2 INT, + PRIMARY KEY (c1), + UNIQUE KEY (c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; + +--error ER_NOT_SUPPORTED_YET +CREATE TABLE t ( + c1 INT, + c2 INT AUTO_INCREMENT, + PRIMARY KEY (c1), + KEY (c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; + +--error ER_WRONG_ARGUMENTS +CREATE TABLE t ( + c1 INT, + c2 INT, + PRIMARY KEY (c1), + KEY (c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=asdf' +) ENGINE=ROCKSDB; + +--error ER_WRONG_ARGUMENTS +CREATE TABLE t ( + c1 INT, + c2 INT, + PRIMARY KEY (c1), + KEY (c2) COMMENT 'partial_group_keyparts=asdf;partial_group_threshold=10000' +) ENGINE=ROCKSDB; + +--error ER_WRONG_ARGUMENTS +CREATE TABLE t ( + c1 INT, + c2 INT, + c3 INT, + c4 INT, + PRIMARY KEY (c1, c2), + KEY (c1, c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; + +--error ER_WRONG_ARGUMENTS +CREATE TABLE t ( + c1 INT, + c2 INT, + c3 INT, + c4 INT, + PRIMARY KEY (c1, c2), + KEY (c1, c2, c4) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; + +--error ER_WRONG_ARGUMENTS +CREATE TABLE t ( + c1 INT, + c2 INT, + c3 INT, + c4 INT, + PRIMARY KEY (c1, c2), + KEY (c1, c2, c4) COMMENT 'partial_group_keyparts=3;partial_group_threshold=10000' +) ENGINE=ROCKSDB; + +--error ER_WRONG_ARGUMENTS +CREATE TABLE t ( + c1 INT, + c2 INT, + c3 INT, + c4 INT, + PRIMARY KEY (c1, c2, c3), + KEY (c1, c2, c4) COMMENT 'partial_group_keyparts=3;partial_group_threshold=10000' +) ENGINE=ROCKSDB; + +--error ER_WRONG_ARGUMENTS +CREATE TABLE t ( + c1 INT, + c2 INT, + c3 INT, + c4 INT, + PRIMARY KEY (c2, c3, c4), + KEY (c1, c2, c4) COMMENT 'partial_group_keyparts=3;partial_group_threshold=10000' +) ENGINE=ROCKSDB; + +--error ER_WRONG_ARGUMENTS +CREATE TABLE t ( + c1 INT, + c2 VARCHAR(255), + c3 INT, + c4 INT, + PRIMARY KEY (c1, c2(5), c3), + KEY (c1, c2(4), c4) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; + +--echo # +--echo # Positive test cases +--echo # + +CREATE TABLE t ( + c1 INT, + c2 INT, + c3 INT, + c4 INT, + c5 INT, + PRIMARY KEY (c1, c2, c5), + KEY (c1, c2, c4) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +DROP TABLE t; + +CREATE TABLE t ( + c1 INT, + c2 INT, + c3 INT, + c4 INT, + PRIMARY KEY (c1, c2, c3), + KEY (c1, c2, c4) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +DROP TABLE t; + +CREATE TABLE t ( + c1 INT, + c2 INT, + c3 INT, + c4 INT, + PRIMARY KEY (c1, c2, c3), + KEY (c1, c2) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +DROP TABLE t; + +CREATE TABLE t ( + c1 INT, + c2 VARCHAR(255), + c3 INT, + c4 INT, + PRIMARY KEY (c1, c2(4), c3), + KEY (c1, c2(4), c4) COMMENT 'partial_group_keyparts=2;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +DROP TABLE t; + +CREATE TABLE t ( + c1 INT, + c2 VARCHAR(255), + c3 INT, + c4 INT, + PRIMARY KEY (c1, c2(4), c3), + KEY (c1, c2(4), c4) COMMENT 'partial_group_keyparts=1;partial_group_threshold=10000' +) ENGINE=ROCKSDB; +DROP TABLE t; + +CREATE TABLE t ( + id1 bigint(20) unsigned NOT NULL DEFAULT '0', + id1_type int(10) unsigned NOT NULL DEFAULT '0', + id2 bigint(20) unsigned NOT NULL DEFAULT '0', + id2_type int(10) unsigned NOT NULL DEFAULT '0', + assoc_type bigint(20) unsigned NOT NULL DEFAULT '0', + visibility tinyint(3) NOT NULL DEFAULT '0', + data varchar(255) COLLATE latin1_bin NOT NULL DEFAULT '', + time int(10) unsigned NOT NULL DEFAULT '0', + version bigint(20) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (assoc_type, id1, id2) COMMENT 'cf_assoc', + KEY id1_type (assoc_type, id1, visibility, time, id2, version, data) COMMENT 'cfname=rev:cf_assoc_id1_type;partial_group_keyparts=1;partial_group_threshold=10000' +) ENGINE=ROCKSDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; +DROP TABLE t; + +CREATE TABLE t ( + id1 binary(16) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', + raw_key text COLLATE latin1_bin, + id2 bigint(20) unsigned NOT NULL DEFAULT '0', + id2_type int(10) unsigned NOT NULL DEFAULT '0', + assoc_type bigint(20) unsigned NOT NULL DEFAULT '0', + visibility tinyint(3) NOT NULL DEFAULT '0', + data varchar(255) COLLATE latin1_bin NOT NULL DEFAULT '', + time int(10) unsigned NOT NULL DEFAULT '0', + version bigint(20) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (assoc_type, id1, id2) COMMENT 'cf_assoc', + KEY id1_type (assoc_type, id1, visibility, time, id2, version, data) COMMENT 'cfname=rev:cf_assoc_id1_type;partial_group_keyparts=1;partial_group_threshold=10000' +) ENGINE=ROCKSDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; +DROP TABLE t; + + +CREATE TABLE t ( + id1 bigint(20) unsigned NOT NULL DEFAULT '0', + id1_type int(10) unsigned NOT NULL DEFAULT '0', + id2 bigint(20) unsigned NOT NULL DEFAULT '0', + id2_type int(10) unsigned NOT NULL DEFAULT '0', + assoc_type bigint(20) unsigned NOT NULL DEFAULT '0', + visibility tinyint(4) NOT NULL DEFAULT '0', + data text COLLATE latin1_bin NOT NULL, + time int(10) unsigned NOT NULL DEFAULT '0', + version bigint(20) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (assoc_type, id1, id2) COMMENT 'cf_assoc', + KEY id1_type (assoc_type, id1, visibility, time, id2, version, data(255)) COMMENT 'cfname=rev:cf_assoc_id1_type;partial_group_keyparts=1;partial_group_threshold=10000' +) ENGINE=ROCKSDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; +DROP TABLE t; diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index c484dfb5894..15c8b289a5e 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -8251,6 +8251,11 @@ int ha_rocksdb::create_key_def(uint32_t dbnum_arg, const TABLE *const table_arg, if (!ttl_column.empty()) { (*new_key_def)->m_ttl_column = ttl_column; } + + if ((*new_key_def)->extract_partial_index_info(table_arg, tbl_def_arg)) { + DBUG_RETURN(HA_EXIT_FAILURE); + } + // initialize key_def (*new_key_def)->setup(table_arg, tbl_def_arg); DBUG_RETURN(HA_EXIT_SUCCESS); diff --git a/storage/rocksdb/rdb_datadic.cc b/storage/rocksdb/rdb_datadic.cc index a9bdad0620e..c26a9f9437b 100644 --- a/storage/rocksdb/rdb_datadic.cc +++ b/storage/rocksdb/rdb_datadic.cc @@ -289,6 +289,8 @@ Rdb_key_def::Rdb_key_def( m_key_parts(0), m_ttl_pk_key_part_offset(UINT_MAX), m_ttl_field_index(UINT_MAX), + m_partial_index_keyparts(0), + m_partial_index_threshold(0), m_prefix_extractor(nullptr), m_maxlength(0) // means 'not intialized' { @@ -316,6 +318,8 @@ Rdb_key_def::Rdb_key_def(const Rdb_key_def &k) m_key_parts(k.m_key_parts), m_ttl_pk_key_part_offset(k.m_ttl_pk_key_part_offset), m_ttl_field_index(UINT_MAX), + m_partial_index_keyparts(k.m_partial_index_keyparts), + m_partial_index_threshold(k.m_partial_index_threshold), m_prefix_extractor(k.m_prefix_extractor), m_maxlength(k.m_maxlength) { mysql_mutex_init(0, &m_mutex, MY_MUTEX_INIT_FAST); @@ -465,6 +469,8 @@ void Rdb_key_def::setup(const TABLE *const tbl, Rdb_key_def::extract_ttl_col(tbl, tbl_def, &m_ttl_column, &m_ttl_field_index, true); + extract_partial_index_info(tbl, tbl_def); + size_t max_len = INDEX_ID_SIZE; int unpack_len = 0; int max_part_len = 0; @@ -701,57 +707,129 @@ uint Rdb_key_def::extract_ttl_col(const TABLE *const table_arg, return HA_EXIT_SUCCESS; } -const std::string Rdb_key_def::gen_qualifier_for_table( - const char *const qualifier, const std::string &partition_name) { - bool has_partition = !partition_name.empty(); - std::string qualifier_str = ""; +uint Rdb_key_def::extract_partial_index_info( + const TABLE *const table_arg, const Rdb_tbl_def *const tbl_def_arg) { + // Nothing to parse if this is a hidden PK. + if (m_index_type == INDEX_TYPE_HIDDEN_PRIMARY) { + return HA_EXIT_SUCCESS; + } - if (!strcmp(qualifier, RDB_CF_NAME_QUALIFIER)) { - return has_partition ? gen_cf_name_qualifier_for_partition(partition_name) - : qualifier_str + RDB_CF_NAME_QUALIFIER + - RDB_QUALIFIER_VALUE_SEP; - } else if (!strcmp(qualifier, RDB_TTL_DURATION_QUALIFIER)) { - return has_partition - ? gen_ttl_duration_qualifier_for_partition(partition_name) - : qualifier_str + RDB_TTL_DURATION_QUALIFIER + - RDB_QUALIFIER_VALUE_SEP; - } else if (!strcmp(qualifier, RDB_TTL_COL_QUALIFIER)) { - return has_partition ? gen_ttl_col_qualifier_for_partition(partition_name) - : qualifier_str + RDB_TTL_COL_QUALIFIER + - RDB_QUALIFIER_VALUE_SEP; - } else { - DBUG_ASSERT(0); + std::string key_comment(table_arg->key_info[m_keyno].comment.str, + table_arg->key_info[m_keyno].comment.length); + + bool per_part_match = false; + std::string keyparts_str = Rdb_key_def::parse_comment_for_qualifier( + key_comment, table_arg, tbl_def_arg, &per_part_match, + RDB_PARTIAL_INDEX_KEYPARTS_QUALIFIER); + + std::string threshold_str = Rdb_key_def::parse_comment_for_qualifier( + key_comment, table_arg, tbl_def_arg, &per_part_match, + RDB_PARTIAL_INDEX_THRESHOLD_QUALIFIER); + + if (threshold_str.empty()) { + m_partial_index_keyparts = 0; + m_partial_index_threshold = 0; + return HA_EXIT_SUCCESS; } - return qualifier_str; -} + if (table_arg->part_info != nullptr) { + my_printf_error(ER_NOT_SUPPORTED_YET, + "Partial indexes not supported for partitioned tables.", + MYF(0)); + return HA_EXIT_FAILURE; + } -/* - Formats the string and returns the column family name assignment part for a - specific partition. -*/ -const std::string Rdb_key_def::gen_cf_name_qualifier_for_partition( - const std::string &prefix) { - DBUG_ASSERT(!prefix.empty()); + if (is_primary_key()) { + my_printf_error(ER_WRONG_ARGUMENTS, + "Primary key cannot be a partial index.", MYF(0)); + return HA_EXIT_FAILURE; + } - return prefix + RDB_PER_PARTITION_QUALIFIER_NAME_SEP + RDB_CF_NAME_QUALIFIER + - RDB_QUALIFIER_VALUE_SEP; -} + if (table_arg->key_info[m_keyno].flags & HA_NOSAME) { + my_printf_error(ER_NOT_SUPPORTED_YET, + "Unique key cannot be a partial index.", MYF(0)); + return HA_EXIT_FAILURE; + } + + if (table_arg->s->next_number_index == m_keyno) { + my_printf_error(ER_NOT_SUPPORTED_YET, + "Autoincrement key cannot be a partial index.", MYF(0)); + return HA_EXIT_FAILURE; + } + + if (table_has_hidden_pk(table_arg)) { + my_printf_error(ER_NOT_SUPPORTED_YET, + "Table with no primary key cannot have a partial index.", + MYF(0)); + return HA_EXIT_FAILURE; + } + + m_partial_index_threshold = std::strtoull(threshold_str.c_str(), nullptr, 0); + if (!m_partial_index_threshold) { + my_printf_error(ER_WRONG_ARGUMENTS, + "Invalid partial index group size threshold.", MYF(0)); + return HA_EXIT_FAILURE; + } + + m_partial_index_keyparts = std::strtoull(keyparts_str.c_str(), nullptr, 0); + if (!m_partial_index_keyparts) { + my_printf_error(ER_WRONG_ARGUMENTS, + "Invalid number of keyparts in partial index group.", + MYF(0)); + return HA_EXIT_FAILURE; + } + + uint n_keyparts = + std::min(table_arg->key_info[table_arg->s->primary_key].actual_key_parts, + table_arg->key_info[m_keyno].actual_key_parts); + if (n_keyparts <= m_partial_index_keyparts) { + my_printf_error(ER_WRONG_ARGUMENTS, + "Too many keyparts in partial index group.", MYF(0)); + return HA_EXIT_FAILURE; + } -const std::string Rdb_key_def::gen_ttl_duration_qualifier_for_partition( - const std::string &prefix) { - DBUG_ASSERT(!prefix.empty()); + // Verify that PK/SK actually share a common prefix. + KEY_PART_INFO *key_part_sk = table_arg->key_info[m_keyno].key_part; + KEY_PART_INFO *key_part_pk = + table_arg->key_info[table_arg->s->primary_key].key_part; + + n_keyparts = std::min(n_keyparts, m_partial_index_keyparts); + + for (uint i = 0; i < n_keyparts; i++) { + if (key_part_sk->fieldnr != key_part_pk->fieldnr || + key_part_sk->field->field_length != key_part_pk->field->field_length) { + my_printf_error(ER_WRONG_ARGUMENTS, + "Mismatched keyparts in partial index group.", MYF(0)); + return HA_EXIT_FAILURE; + } + key_part_sk++; + key_part_pk++; + } - return prefix + RDB_PER_PARTITION_QUALIFIER_NAME_SEP + - RDB_TTL_DURATION_QUALIFIER + RDB_QUALIFIER_VALUE_SEP; + return HA_EXIT_SUCCESS; } -const std::string Rdb_key_def::gen_ttl_col_qualifier_for_partition( - const std::string &prefix) { - DBUG_ASSERT(!prefix.empty()); +const std::string Rdb_key_def::gen_qualifier_for_table( + const char *const qualifier, const std::string &partition_name) { + bool has_partition = !partition_name.empty(); + std::string qualifier_str = ""; + + if (has_partition) { + qualifier_str += partition_name + RDB_PER_PARTITION_QUALIFIER_NAME_SEP; + } - return prefix + RDB_PER_PARTITION_QUALIFIER_NAME_SEP + RDB_TTL_COL_QUALIFIER + - RDB_QUALIFIER_VALUE_SEP; + if (!strcmp(qualifier, RDB_CF_NAME_QUALIFIER) || + !strcmp(qualifier, RDB_TTL_DURATION_QUALIFIER) || + !strcmp(qualifier, RDB_TTL_COL_QUALIFIER) || + !strcmp(qualifier, RDB_PARTIAL_INDEX_KEYPARTS_QUALIFIER) || + !strcmp(qualifier, RDB_PARTIAL_INDEX_THRESHOLD_QUALIFIER)) { + qualifier_str += std::string(qualifier) + RDB_QUALIFIER_VALUE_SEP; + } else { + DBUG_ASSERT(false); + return std::string(""); + } + + return qualifier_str; } const std::string Rdb_key_def::parse_comment_for_qualifier( diff --git a/storage/rocksdb/rdb_datadic.h b/storage/rocksdb/rdb_datadic.h index f6917836f23..2c5828a6b8a 100644 --- a/storage/rocksdb/rdb_datadic.h +++ b/storage/rocksdb/rdb_datadic.h @@ -583,6 +583,10 @@ class Rdb_key_def { bool skip_checks = false); inline bool has_ttl() const { return m_ttl_duration > 0; } + uint extract_partial_index_info(const TABLE *const table_arg, + const Rdb_tbl_def *const tbl_def_arg); + inline bool is_partial_index() const { return m_partial_index_threshold > 0; } + static bool has_index_flag(uint32 index_flags, enum INDEX_FLAG flag); static uint32 calculate_index_flag_offset(uint32 index_flags, enum INDEX_FLAG flag, @@ -593,13 +597,6 @@ class Rdb_key_def { static const std::string gen_qualifier_for_table( const char *const qualifier, const std::string &partition_name = ""); - static const std::string gen_cf_name_qualifier_for_partition( - const std::string &s); - static const std::string gen_ttl_duration_qualifier_for_partition( - const std::string &s); - static const std::string gen_ttl_col_qualifier_for_partition( - const std::string &s); - static const std::string parse_comment_for_qualifier( const std::string &comment, const TABLE *const table_arg, const Rdb_tbl_def *const tbl_def_arg, bool *per_part_match_found, @@ -926,6 +923,10 @@ class Rdb_key_def { */ uint m_ttl_field_index; + uint m_partial_index_keyparts; + + uint m_partial_index_threshold; + /* Prefix extractor for the column family of the key definiton */ std::shared_ptr<const rocksdb::SliceTransform> m_prefix_extractor; diff --git a/storage/rocksdb/rdb_global.h b/storage/rocksdb/rdb_global.h index a7c628e541e..9f5c8cf76e8 100644 --- a/storage/rocksdb/rdb_global.h +++ b/storage/rocksdb/rdb_global.h @@ -165,6 +165,18 @@ const char *const RDB_TTL_DURATION_QUALIFIER = "ttl_duration"; */ const char *const RDB_TTL_COL_QUALIFIER = "ttl_col"; +/* + Qualifier name for number of prefix keyparts in partial index +*/ +const char *const RDB_PARTIAL_INDEX_KEYPARTS_QUALIFIER = + "partial_group_keyparts"; + +/* + Qualifier name for materialization threshold in partial index +*/ +const char *const RDB_PARTIAL_INDEX_THRESHOLD_QUALIFIER = + "partial_group_threshold"; + /* Default, minimal valid, and maximum valid sampling rate values when collecting statistics about table.
participants (1)
-
psergey