[Commits] aaebd623e98: Apply patch: Support parsing index comments for partial indexes

psergey sergey at mariadb.com
Mon May 17 17:43:41 EEST 2021


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.


More information about the commits mailing list