This is an automated email from the ASF dual-hosted git repository. yuqi1129 pushed a commit to branch branch-1.3 in repository https://gitbox.apache.org/repos/asf/gravitino.git
commit 6dba8fa20c209858b628e8e7a42d37c23f355104 Author: StormSpirit <[email protected]> AuthorDate: Fri Jul 10 08:55:38 2026 +0800 [#11912] feat(clickhouse): support set data skipping index type (#11916) ### What changes were proposed in this pull request? - Add set data skipping index type to the Index API - Support set index in CREATE TABLE, ALTER TABLE, and table loading - Refactor index DDL generation into a shared helper ### Why are the changes needed? Fix: #11912 The ClickHouse catalog only supports minmax and bloom_filter skip indexes. Tables with set indexes load without error but index metadata is silently dropped, and explicit creation attempts fail. The set index type has no required parameters (unlike ngrambf_v1/tokenbf_v1), making it safe to add without a parameter-passing mechanism. ### Does this PR introduce any user-facing change? Yes. ClickHouse tables with set data skipping indexes can now be created and loaded through Gravitino with index metadata preserved. ### How was this patch tested? **Unit tests** (`TestClickHouseTableOperations`): - `testGetClickHouseIndexType`: verifies index type string-to-enum mapping (minmax, bloom_filter, set) **Integration tests** (`CatalogClickHouseIT`): - `testCreateAndLoadWithPartitionSortAndIndexes`: extended with SET index create/load round-trip - `testAlterTableAddIndexWithSetIndex`: ALTER TABLE ADD INDEX with SET type Both test classes require `-PskipDockerTests=false` to run. --------- Signed-off-by: jiangxt2 <[email protected]> --- .../org/apache/gravitino/rel/indexes/Index.java | 3 + .../catalog/clickhouse/ClickHouseConstants.java | 3 + .../operations/ClickHouseTableOperations.java | 66 +++++++++++++++++----- .../test/CatalogClickHouseClusterIT.java | 18 ++++++ .../integration/test/CatalogClickHouseIT.java | 45 +++++++++++++-- .../operations/TestClickHouseTableOperations.java | 40 +++++++++++++ docs/jdbc-clickhouse-catalog.md | 3 +- 7 files changed, 157 insertions(+), 21 deletions(-) diff --git a/api/src/main/java/org/apache/gravitino/rel/indexes/Index.java b/api/src/main/java/org/apache/gravitino/rel/indexes/Index.java index d299683889..9f725c19cc 100644 --- a/api/src/main/java/org/apache/gravitino/rel/indexes/Index.java +++ b/api/src/main/java/org/apache/gravitino/rel/indexes/Index.java @@ -129,5 +129,8 @@ public interface Index { /** Bloom filter data skipping index */ DATA_SKIPPING_BLOOM_FILTER, + + /** Set data skipping index */ + DATA_SKIPPING_SET, } } diff --git a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseConstants.java b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseConstants.java index 38428e82aa..a2fca9f7b7 100644 --- a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseConstants.java +++ b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/ClickHouseConstants.java @@ -57,5 +57,8 @@ public class ClickHouseConstants { // The name of the data skipping index type for bloom filter index in clickhouse. public static final String DATA_SKIPPING_BLOOM_FILTER = "bloom_filter"; + + // The name of the data skipping index type for set index in clickhouse. + public static final String DATA_SKIPPING_SET = "set"; } } diff --git a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/operations/ClickHouseTableOperations.java b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/operations/ClickHouseTableOperations.java index 118eed0989..688483a9ce 100644 --- a/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/operations/ClickHouseTableOperations.java +++ b/catalogs-contrib/catalog-jdbc-clickhouse/src/main/java/org/apache/gravitino/catalog/clickhouse/operations/ClickHouseTableOperations.java @@ -20,6 +20,7 @@ package org.apache.gravitino.catalog.clickhouse.operations; import static org.apache.gravitino.catalog.clickhouse.ClickHouseConstants.IndexConstants.DATA_SKIPPING_BLOOM_FILTER; import static org.apache.gravitino.catalog.clickhouse.ClickHouseConstants.IndexConstants.DATA_SKIPPING_MINMAX_VALUE; +import static org.apache.gravitino.catalog.clickhouse.ClickHouseConstants.IndexConstants.DATA_SKIPPING_SET; import static org.apache.gravitino.catalog.clickhouse.ClickHouseTablePropertiesMetadata.CLICKHOUSE_ENGINE_KEY; import static org.apache.gravitino.catalog.clickhouse.ClickHouseTablePropertiesMetadata.ENGINE_PROPERTY_ENTRY; import static org.apache.gravitino.catalog.clickhouse.ClickHouseTablePropertiesMetadata.GRAVITINO_ENGINE_KEY; @@ -483,23 +484,27 @@ public class ClickHouseTableOperations extends JdbcTableOperations { sqlBuilder.append(" PRIMARY KEY (").append(fieldStr).append(")"); break; case DATA_SKIPPING_MINMAX: - Preconditions.checkArgument( - StringUtils.isNotBlank(index.name()), "Data skipping index name must not be blank"); // The GRANULARITY value is always 1 here currently as we can't set it by Index: there is // no field for it. // TODO(yuqi) add a properties field to Index to support user defined GRANULARITY value. - sqlBuilder.append( - " INDEX %s %s TYPE minmax GRANULARITY 1" - .formatted(quoteIdentifier(index.name()), fieldStr)); + sqlBuilder + .append(" ") + .append(buildDataSkippingIndexDdl(index.name(), fieldStr, "minmax", 1)); break; case DATA_SKIPPING_BLOOM_FILTER: // The GRANULARITY value is always 3 here currently. // TODO(yuqi) add a properties field to Index to support user defined GRANULARITY value. - Preconditions.checkArgument( - StringUtils.isNotBlank(index.name()), "Data skipping index name must not be blank"); - sqlBuilder.append( - " INDEX %s %s TYPE bloom_filter GRANULARITY 3" - .formatted(quoteIdentifier(index.name()), fieldStr)); + sqlBuilder + .append(" ") + .append(buildDataSkippingIndexDdl(index.name(), fieldStr, "bloom_filter", 3)); + break; + case DATA_SKIPPING_SET: + // The max unique values (N) is always 0 (unlimited) here currently as we can't set it + // by Index: there is no field for it. ClickHouse requires set(N) syntax. + // TODO(yuqi) add a properties field to Index to support user defined max unique values. + sqlBuilder + .append(" ") + .append(buildDataSkippingIndexDdl(index.name(), fieldStr, "set(0)", 1)); break; default: throw new IllegalArgumentException( @@ -871,12 +876,16 @@ public class ClickHouseTableOperations extends JdbcTableOperations { String fieldStr = getIndexFieldStr(addIndex.getFieldNames()); switch (addIndex.getType()) { case DATA_SKIPPING_MINMAX: - return "ADD INDEX %s %s TYPE minmax GRANULARITY 1" - .formatted(quoteIdentifier(addIndex.getName()), fieldStr); + return "ADD " + buildDataSkippingIndexDdl(addIndex.getName(), fieldStr, "minmax", 1); case DATA_SKIPPING_BLOOM_FILTER: - return "ADD INDEX %s %s TYPE bloom_filter GRANULARITY 3" - .formatted(quoteIdentifier(addIndex.getName()), fieldStr); + return "ADD " + buildDataSkippingIndexDdl(addIndex.getName(), fieldStr, "bloom_filter", 3); + + case DATA_SKIPPING_SET: + // The max unique values (N) is always 0 (unlimited) here currently as we can't set it + // by Index: there is no field for it. ClickHouse requires set(N) syntax. + // TODO(yuqi) add a properties field to Index to support user defined max unique values. + return "ADD " + buildDataSkippingIndexDdl(addIndex.getName(), fieldStr, "set(0)", 1); case PRIMARY_KEY: throw new UnsupportedOperationException( @@ -1333,7 +1342,19 @@ public class ClickHouseTableOperations extends JdbcTableOperations { return secondaryIndexes; } - private Index.IndexType getClickHouseIndexType(String rawType) { + /** + * Maps a ClickHouse data skipping index type string to the corresponding Gravitino {@link + * Index.IndexType}. Returns {@code DATA_SKIPPING_MINMAX} for blank/null input (ClickHouse + * default). Also handles the {@code set(N)} parameterized format that some ClickHouse versions + * may return from {@code system.data_skipping_indices}. + * + * @param rawType the index type string from ClickHouse metadata (e.g. "minmax", "bloom_filter", + * "set", "set(0)") + * @return the corresponding Gravitino IndexType + * @throws IllegalArgumentException if the type is not supported + */ + @VisibleForTesting + Index.IndexType getClickHouseIndexType(String rawType) { if (StringUtils.isBlank(rawType)) { return Index.IndexType.DATA_SKIPPING_MINMAX; } @@ -1343,11 +1364,26 @@ public class ClickHouseTableOperations extends JdbcTableOperations { return Index.IndexType.DATA_SKIPPING_MINMAX; case DATA_SKIPPING_BLOOM_FILTER: return Index.IndexType.DATA_SKIPPING_BLOOM_FILTER; + case DATA_SKIPPING_SET: + return Index.IndexType.DATA_SKIPPING_SET; default: + // ClickHouse may return "set(N)" with parameter in some versions; + // match on prefix to handle both "set" and "set(N)" formats. + if (rawType.startsWith(DATA_SKIPPING_SET + "(")) { + return Index.IndexType.DATA_SKIPPING_SET; + } throw new IllegalArgumentException("Unsupported data skipping index type: " + rawType); } } + private String buildDataSkippingIndexDdl( + String indexName, String fieldStr, String typeName, int granularity) { + Preconditions.checkArgument( + StringUtils.isNotBlank(indexName), "Data skipping index name must not be blank"); + return "INDEX %s %s TYPE %s GRANULARITY %d" + .formatted(quoteIdentifier(indexName), fieldStr, typeName, granularity); + } + private StringBuilder appendColumnDefinition(JdbcColumn column, StringBuilder sqlBuilder) { // Add Nullable data type String dataType = typeConverter.fromGravitino(column.dataType()); diff --git a/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/integration/test/CatalogClickHouseClusterIT.java b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/integration/test/CatalogClickHouseClusterIT.java index 48d6ee8f89..7cfdde2b7b 100644 --- a/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/integration/test/CatalogClickHouseClusterIT.java +++ b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/integration/test/CatalogClickHouseClusterIT.java @@ -506,6 +506,24 @@ public class CatalogClickHouseClusterIT extends BaseIT { Arrays.stream(loaded.index()) .anyMatch(index -> Objects.equals(index.name(), "idx_col_1_new"))); + tableCatalog.alterTable( + tableIdentifier, + TableChange.addIndex( + Index.IndexType.DATA_SKIPPING_SET, "idx_col_2_set", new String[][] {{"col_2"}})); + loaded = tableCatalog.loadTable(tableIdentifier); + Assertions.assertTrue( + Arrays.stream(loaded.index()) + .anyMatch( + index -> + Objects.equals(index.name(), "idx_col_2_set") + && index.type() == Index.IndexType.DATA_SKIPPING_SET + && Arrays.deepEquals(index.fieldNames(), new String[][] {{"col_2"}}))); + tableCatalog.alterTable(tableIdentifier, TableChange.deleteIndex("idx_col_2_set", false)); + loaded = tableCatalog.loadTable(tableIdentifier); + Assertions.assertFalse( + Arrays.stream(loaded.index()) + .anyMatch(index -> Objects.equals(index.name(), "idx_col_2_set"))); + RuntimeException autoIncrementTrueException = Assertions.assertThrows( RuntimeException.class, diff --git a/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/integration/test/CatalogClickHouseIT.java b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/integration/test/CatalogClickHouseIT.java index 4da92f33e1..a1f64dacda 100644 --- a/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/integration/test/CatalogClickHouseIT.java +++ b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/integration/test/CatalogClickHouseIT.java @@ -510,7 +510,9 @@ public class CatalogClickHouseIT extends BaseIT { new Index[] { Indexes.primary(Indexes.DEFAULT_PRIMARY_KEY_NAME, new String[][] {{"user_id"}}), Indexes.of( - Index.IndexType.DATA_SKIPPING_MINMAX, "idx_amount", new String[][] {{"amount"}}) + Index.IndexType.DATA_SKIPPING_MINMAX, "idx_amount", new String[][] {{"amount"}}), + Indexes.of( + Index.IndexType.DATA_SKIPPING_SET, "idx_userid_set", new String[][] {{"user_id"}}) }; catalog @@ -555,6 +557,13 @@ public class CatalogClickHouseIT extends BaseIT { idx -> idx.type() == Index.IndexType.DATA_SKIPPING_MINMAX && Arrays.deepEquals(idx.fieldNames(), new String[][] {{"amount"}}))); + Assertions.assertTrue( + Arrays.stream(loadedIndexes) + .anyMatch( + idx -> + idx.type() == Index.IndexType.DATA_SKIPPING_SET + && idx.name().equals("idx_userid_set") + && Arrays.deepEquals(idx.fieldNames(), new String[][] {{"user_id"}}))); } @Test @@ -1335,7 +1344,8 @@ public class CatalogClickHouseIT extends BaseIT { }; Index[] indexes = new Index[] { - Indexes.of(Index.IndexType.DATA_SKIPPING_MINMAX, "idx_note", new String[][] {{"note"}}) + Indexes.of(Index.IndexType.DATA_SKIPPING_MINMAX, "idx_note", new String[][] {{"note"}}), + Indexes.of(Index.IndexType.DATA_SKIPPING_SET, "idx_note_set", new String[][] {{"note"}}) }; TableCatalog tableCatalog = catalog.asTableCatalog(); tableCatalog.createTable( @@ -1353,12 +1363,18 @@ public class CatalogClickHouseIT extends BaseIT { tableCatalog.alterTable( tableIdentifier, TableChange.updateColumnComment(new String[] {"score"}, "score column changed")); - tableCatalog.alterTable(tableIdentifier, TableChange.deleteIndex("idx_note", false)); + tableCatalog.alterTable( + tableIdentifier, + TableChange.deleteIndex("idx_note", false), + TableChange.deleteIndex("idx_note_set", false)); Table loaded = tableCatalog.loadTable(tableIdentifier); Assertions.assertTrue(loaded.columns()[1].nullable()); Assertions.assertEquals("score column changed", loaded.columns()[1].comment()); Assertions.assertFalse( Arrays.stream(loaded.index()).anyMatch(index -> Objects.equals(index.name(), "idx_note"))); + Assertions.assertFalse( + Arrays.stream(loaded.index()) + .anyMatch(index -> Objects.equals(index.name(), "idx_note_set"))); Assertions.assertDoesNotThrow( () -> @@ -1417,7 +1433,8 @@ public class CatalogClickHouseIT extends BaseIT { Indexes.of( Index.IndexType.DATA_SKIPPING_BLOOM_FILTER, "idx_note_bloom", - new String[][] {{"note"}}) + new String[][] {{"note"}}), + Indexes.of(Index.IndexType.DATA_SKIPPING_SET, "idx_score_set", new String[][] {{"score"}}) }; TableCatalog tableCatalog = catalog.asTableCatalog(); tableCatalog.createTable( @@ -1434,15 +1451,27 @@ public class CatalogClickHouseIT extends BaseIT { tableIdentifier, TableChange.addIndex( Index.IndexType.DATA_SKIPPING_MINMAX, "idx_new", new String[][] {{"score"}})); + tableCatalog.alterTable( + tableIdentifier, + TableChange.addIndex( + Index.IndexType.DATA_SKIPPING_SET, "idx_new_set", new String[][] {{"note"}})); Table loaded = tableCatalog.loadTable(tableIdentifier); Assertions.assertTrue( Arrays.stream(loaded.index()).anyMatch(index -> Objects.equals(index.name(), "idx_new"))); + Assertions.assertTrue( + Arrays.stream(loaded.index()) + .anyMatch( + index -> + Objects.equals(index.name(), "idx_new_set") + && index.type() == Index.IndexType.DATA_SKIPPING_SET)); tableCatalog.alterTable( tableIdentifier, TableChange.deleteIndex("idx_score_minmax", false), TableChange.deleteIndex("idx_note_bloom", false), - TableChange.deleteIndex("idx_new", false)); + TableChange.deleteIndex("idx_score_set", false), + TableChange.deleteIndex("idx_new", false), + TableChange.deleteIndex("idx_new_set", false)); loaded = tableCatalog.loadTable(tableIdentifier); Assertions.assertFalse( Arrays.stream(loaded.index()) @@ -1450,8 +1479,14 @@ public class CatalogClickHouseIT extends BaseIT { Assertions.assertFalse( Arrays.stream(loaded.index()) .anyMatch(index -> Objects.equals(index.name(), "idx_note_bloom"))); + Assertions.assertFalse( + Arrays.stream(loaded.index()) + .anyMatch(index -> Objects.equals(index.name(), "idx_score_set"))); Assertions.assertFalse( Arrays.stream(loaded.index()).anyMatch(index -> Objects.equals(index.name(), "idx_new"))); + Assertions.assertFalse( + Arrays.stream(loaded.index()) + .anyMatch(index -> Objects.equals(index.name(), "idx_new_set"))); RuntimeException autoIncrementTrueException = Assertions.assertThrows( diff --git a/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/operations/TestClickHouseTableOperations.java b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/operations/TestClickHouseTableOperations.java index 946a1a3027..3a54b45812 100644 --- a/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/operations/TestClickHouseTableOperations.java +++ b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/operations/TestClickHouseTableOperations.java @@ -1099,6 +1099,7 @@ public class TestClickHouseTableOperations extends TestClickHouse { Indexes.primary(Indexes.DEFAULT_PRIMARY_KEY_NAME, new String[][] {{"c1"}}), Indexes.of(IndexType.DATA_SKIPPING_MINMAX, "idx_c2", new String[][] {{"c2"}}), Indexes.of(IndexType.DATA_SKIPPING_BLOOM_FILTER, "idx_c3", new String[][] {{"c3"}}), + Indexes.of(IndexType.DATA_SKIPPING_SET, "idx_c4", new String[][] {{"c2"}}), }; String sql = @@ -1115,6 +1116,7 @@ public class TestClickHouseTableOperations extends TestClickHouse { Assertions.assertTrue(sql.contains("PARTITION BY `c1`")); Assertions.assertTrue(sql.contains("INDEX `idx_c2` `c2` TYPE minmax GRANULARITY 1")); Assertions.assertTrue(sql.contains("INDEX `idx_c3` `c3` TYPE bloom_filter GRANULARITY 3")); + Assertions.assertTrue(sql.contains("INDEX `idx_c4` `c2` TYPE set(0) GRANULARITY 1")); } @Test @@ -1380,6 +1382,15 @@ public class TestClickHouseTableOperations extends TestClickHouse { Assertions.assertTrue( bloomSql.contains("ADD INDEX `idx_bf` `c2` TYPE bloom_filter GRANULARITY 3")); + String setSql = + ops.buildAlterSql( + "db", + "tbl", + new TableChange[] { + TableChange.addIndex(IndexType.DATA_SKIPPING_SET, "idx_set", new String[][] {{"c2"}}) + }); + Assertions.assertTrue(setSql.contains("ADD INDEX `idx_set` `c2` TYPE set(0) GRANULARITY 1")); + Assertions.assertThrows( IllegalArgumentException.class, () -> @@ -1402,6 +1413,35 @@ public class TestClickHouseTableOperations extends TestClickHouse { })); } + @Test + public void testGetClickHouseIndexType() { + StubClickHouseTableOperations ops = new StubClickHouseTableOperations(); + ops.initialize( + null, + new ClickHouseExceptionConverter(), + new ClickHouseTypeConverter(), + new ClickHouseColumnDefaultValueConverter(), + new HashMap<>()); + + // Exact matches + Assertions.assertEquals(IndexType.DATA_SKIPPING_MINMAX, ops.getClickHouseIndexType("minmax")); + Assertions.assertEquals( + IndexType.DATA_SKIPPING_BLOOM_FILTER, ops.getClickHouseIndexType("bloom_filter")); + Assertions.assertEquals(IndexType.DATA_SKIPPING_SET, ops.getClickHouseIndexType("set")); + + // set(N) variants — ClickHouse may return type with parameter in some versions + Assertions.assertEquals(IndexType.DATA_SKIPPING_SET, ops.getClickHouseIndexType("set(0)")); + Assertions.assertEquals(IndexType.DATA_SKIPPING_SET, ops.getClickHouseIndexType("set(100)")); + + // Blank/null defaults to MINMAX + Assertions.assertEquals(IndexType.DATA_SKIPPING_MINMAX, ops.getClickHouseIndexType("")); + Assertions.assertEquals(IndexType.DATA_SKIPPING_MINMAX, ops.getClickHouseIndexType(null)); + + // Unsupported type + Assertions.assertThrows( + IllegalArgumentException.class, () -> ops.getClickHouseIndexType("unknown_type")); + } + @Test public void testAlterTableNullabilityValidationFails() { StubClickHouseTableOperations ops = new StubClickHouseTableOperations(); diff --git a/docs/jdbc-clickhouse-catalog.md b/docs/jdbc-clickhouse-catalog.md index b6859cdaf1..4075ff2b38 100644 --- a/docs/jdbc-clickhouse-catalog.md +++ b/docs/jdbc-clickhouse-catalog.md @@ -172,7 +172,7 @@ See [Manage Relational Metadata Using Gravitino](./manage-relational-metadata-us | Mapping | Gravitino table maps to a ClickHouse table | | Engines | **MergeTree family** (`MergeTree` default, `ReplacingMergeTree`, `SummingMergeTree`, `AggregatingMergeTree`, `CollapsingMergeTree`, `VersionedCollapsingMergeTree`, `GraphiteMergeTree`): fully supported, data persists across restarts. **Log family** (`TinyLog`, `StripeLog`, `Log`): supported, data and table definition persist across restarts. **`Null`**: supported, table persists, data is always discarded by design. **`Set`**: supported, table definition persists. [...] | Ordering/Partition | MergeTree-family requires exactly one `ORDER BY` column; only single-column identity `PARTITION BY` is supported on MergeTree engines. Other engines reject `ORDER BY`/`PARTITION BY`. | -| Indexes | Primary key; data-skipping indexes `DATA_SKIPPING_MINMAX` and `DATA_SKIPPING_BLOOM_FILTER` (fixed granularities). | +| Indexes | Primary key; data-skipping indexes `DATA_SKIPPING_MINMAX`, `DATA_SKIPPING_BLOOM_FILTER`, and `DATA_SKIPPING_SET` (fixed granularities). | | Distribution | Gravitino enforces `Distributions.NONE`; no custom distribution strategies. | | Column defaults | Supported. | | Unsupported | Engine change after creation; removing table properties; auto-increment columns. | @@ -242,6 +242,7 @@ If you need Gravitino to manage an existing cluster database or table, recreate - Data-skipping indexes: - `DATA_SKIPPING_MINMAX` (`GRANULARITY` fixed to 1) - `DATA_SKIPPING_BLOOM_FILTER` (`GRANULARITY` fixed to 3) + - `DATA_SKIPPING_SET` (`GRANULARITY` fixed to 1) ### Partitioning, Sorting, and Distribution
