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 fc823ef78c7..a69d4e25f94 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 @@ -87,6 +87,8 @@ public class ClickHouseTableOperations extends JdbcTableOperations { private static final Pattern PARTITION_BY_PATTERN = Pattern.compile( "(?is)\\bPARTITION\\s+BY\\s*(.+?)(?=\\bORDER\\s+BY\\b|\\bPRIMARY\\s+KEY\\b|\\bSAMPLE\\s+BY\\b|\\bTTL\\b|\\bSETTINGS\\b|\\bCOMMENT\\b|$)"); + private static final Pattern SETTINGS_PATTERN = + Pattern.compile("(?is)\\bSETTINGS\\s+(.+?)(?=\\bCOMMENT\\b|$)"); private static final Pattern DISTRIBUTED_ENGINE_PATTERN = Pattern.compile( "(?i)^Distributed\\(([^,]+),\\s*([^,]+),\\s*([^,]+),\\s*(.+)\\)$", Pattern.DOTALL); @@ -614,6 +616,15 @@ public JdbcTable load(String databaseName, String tableName) throws NoSuchTableE jdbcTableBuilder.withDistribution(distribution); Map tableProperties = getTableProperties(connection, tableName); + // Merge SETTINGS parsed from SHOW CREATE TABLE into table properties. + // SHOW CREATE TABLE is the authoritative source for SETTINGS; it takes precedence + // over any settings.* keys that might exist in system.tables (though getTableProperties() + // currently does not read SETTINGS from system.tables, so no overlap occurs in practice). + if (!metadata.settings.isEmpty()) { + Map merged = new HashMap<>(tableProperties); + merged.putAll(metadata.settings); + tableProperties = Collections.unmodifiableMap(merged); + } jdbcTableBuilder.withProperties(tableProperties); correctJdbcTableFields(connection, databaseName, tableName, jdbcTableBuilder); @@ -1101,14 +1112,43 @@ private ShowCreateTableMetadata parseCreateStatement(String createSql) { metadata.partitioning = parsePartitioning(partitionMatcher.group(1)); } + Matcher settingsMatcher = SETTINGS_PATTERN.matcher(createSql); + if (settingsMatcher.find()) { + metadata.settings = parseSettingsClause(settingsMatcher.group(1)); + } + return metadata; } + // Parses "key1 = val1, key2 = val2" from a SETTINGS clause. + // Keys are prefixed with "settings." to match the write path convention in + // appendTableProperties(). ClickHouse SETTINGS values are scalar (UInt64, Bool, + // String, Enum) — arrays or nested structures are not valid SETTINGS values, + // so splitting by comma is safe. + private static Map parseSettingsClause(String settingsStr) { + Map settings = new HashMap<>(); + for (String pair : settingsStr.split(",")) { + String trimmed = pair.trim(); + int eqIdx = trimmed.indexOf('='); + if (eqIdx > 0) { + String key = trimmed.substring(0, eqIdx).trim(); + String value = trimmed.substring(eqIdx + 1).trim(); + settings.put(TableConstants.SETTINGS_PREFIX + key, value); + } + } + return settings; + } + @VisibleForTesting SortOrder[] parseSortOrdersFromCreateSql(String createSql) { return parseCreateStatement(createSql).sortOrders; } + @VisibleForTesting + Map parseSettingsFromCreateSql(String createSql) { + return parseCreateStatement(createSql).settings; + } + private ShowCreateTableMetadata parseShowCreateTable(Connection connection, String tableName) throws SQLException { String createSql = parseShowCreateTableSql(connection, tableName); @@ -1228,6 +1268,7 @@ private String toOrderBySql(Expression expression) { private static final class ShowCreateTableMetadata { private Transform[] partitioning = Transforms.EMPTY_TRANSFORM; private SortOrder[] sortOrders = SortOrders.NONE; + private Map settings = Collections.emptyMap(); } @VisibleForTesting 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 68f72d2e129..b8da41908a9 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 @@ -1194,6 +1194,40 @@ void testParseSortOrdersFromMultilineShowCreateSql() { Assertions.assertEquals("id", ((NamedReference) sortOrders[0].expression()).fieldName()[0]); } + @Test + void testParseSettingsFromCreateSql() { + TestableClickHouseTableOperations ops = new TestableClickHouseTableOperations(); + + // Single setting + String sql1 = + "CREATE TABLE t1 (id Int32) ENGINE = MergeTree ORDER BY id SETTINGS index_granularity = 4096"; + Map settings1 = ops.parseSettings(sql1); + Assertions.assertEquals(1, settings1.size()); + Assertions.assertEquals("4096", settings1.get("settings.index_granularity")); + + // Multiple settings + String sql2 = + "CREATE TABLE t2 (id Int32) ENGINE = MergeTree ORDER BY id" + + " SETTINGS index_granularity = 4096, min_bytes_for_wide_part = 0"; + Map settings2 = ops.parseSettings(sql2); + Assertions.assertEquals(2, settings2.size()); + Assertions.assertEquals("4096", settings2.get("settings.index_granularity")); + Assertions.assertEquals("0", settings2.get("settings.min_bytes_for_wide_part")); + + // No SETTINGS clause + String sql3 = "CREATE TABLE t3 (id Int32) ENGINE = MergeTree ORDER BY id"; + Map settings3 = ops.parseSettings(sql3); + Assertions.assertTrue(settings3.isEmpty()); + + // SETTINGS with COMMENT after + String sql4 = + "CREATE TABLE t4 (id Int32) ENGINE = MergeTree ORDER BY id" + + " SETTINGS index_granularity = 8192 COMMENT 'test'"; + Map settings4 = ops.parseSettings(sql4); + Assertions.assertEquals(1, settings4.size()); + Assertions.assertEquals("8192", settings4.get("settings.index_granularity")); + } + private static final class TestableClickHouseTableOperations extends ClickHouseTableOperations { String buildCreateSql( String tableName, @@ -1211,6 +1245,10 @@ String buildCreateSql( SortOrder[] parseSortOrders(String createSql) { return parseSortOrdersFromCreateSql(createSql); } + + Map parseSettings(String createSql) { + return parseSettingsFromCreateSql(createSql); + } } @Test