This is an automated email from the ASF dual-hosted git repository.
jerryshao pushed a commit to branch branch-1.3
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/branch-1.3 by this push:
new 4458ae8a2d [Cherry-pick to branch-1.3] [#11972] fix(clickhouse): read
sort key from system.tables (#12016) (#12704)
4458ae8a2d is described below
commit 4458ae8a2db84947e04d52d983d7913a9a7750d3
Author: StormSpirit <[email protected]>
AuthorDate: Fri Aug 28 15:49:43 2026 +0800
[Cherry-pick to branch-1.3] [#11972] fix(clickhouse): read sort key from
system.tables (#12016) (#12704)
### What changes were proposed in this pull request?
This PR manually backports #12016 to `branch-1.3` and supersedes the
unresolved automated cherry-pick PR #12684.
- Read table sort orders from the canonical `system.tables.sorting_key`
field instead of parsing `ORDER BY` from the full `SHOW CREATE TABLE`
output.
- Read table-level Settings from `system.tables.engine_full`, preventing
projection-level `WITH SETTINGS` clauses from being exposed as table
properties.
- Keep the existing `SHOW CREATE TABLE` path only for partition metadata
and preserve the engine-parameter behavior already backported by #12672.
- Add focused unit coverage for the exact metadata query, expression
conversion, blank values, Settings, and missing rows, plus a real
ClickHouse projection regression test.
The manual conflict resolution starts from the latest `branch-1.3`,
retains #12672, and excludes the unrelated enum round-trip test that
exists only on the source branch.
### Why are the changes needed?
When a ClickHouse table contains a projection with its own `ORDER BY`,
parsing the complete `SHOW CREATE TABLE` output can select the
projection's `ORDER BY` instead of the table-level sorting key.
Gravitino then returns incorrect sort-order metadata without reporting
an error.
The automated backport was generated before the dependent
engine-parameter change reached `branch-1.3`, so its three-way
cherry-pick produced unresolved conflicts in the ClickHouse
implementation and tests.
Fix: #11972
### Does this PR introduce _any_ user-facing change?
No public API or property key changes are introduced. Loading a
ClickHouse table with projections now returns the correct table-level
sort orders while preserving the existing `settings.*` property
contract.
### How was this patch tested?
- `./gradlew :catalogs-contrib:catalog-jdbc-clickhouse:spotlessCheck` —
passed.
- `./gradlew rat` — passed.
- `./gradlew :catalogs-contrib:catalog-jdbc-clickhouse:test --tests
org.apache.gravitino.catalog.clickhouse.operations.TestClickHouseTableOperationsUnit
-PskipITs -PskipDockerTests=true` — passed.
- `./gradlew :catalogs-contrib:catalog-jdbc-clickhouse:test -PskipITs
-PskipDockerTests=true` — passed.
- `./gradlew :catalogs-contrib:catalog-jdbc-clickhouse:test --tests
org.apache.gravitino.catalog.clickhouse.integration.test.CatalogClickHouseIT
-PskipDockerTests=false` — 52 tests, 0 skipped, 0 failures, 0 errors;
`testLoadTableWithProjectionUsesTableSortKey` executed successfully.
- `./gradlew :catalogs-contrib:catalog-jdbc-clickhouse:test --tests
org.apache.gravitino.catalog.clickhouse.integration.test.CatalogClickHouseClusterIT
-PskipDockerTests=false` — 17 tests, 0 skipped, 0 failures, 0 errors.
- `./gradlew :catalogs-contrib:catalog-jdbc-clickhouse:build -x test` —
passed.
Signed-off-by: jiangxt2 <[email protected]>
Co-authored-by: Qi Yu <[email protected]>
---
.../operations/ClickHouseTableOperations.java | 87 +++++++++-----
.../integration/test/CatalogClickHouseIT.java | 40 ++++++-
.../operations/TestClickHouseTableOperations.java | 58 +++-------
.../TestClickHouseTableOperationsUnit.java | 127 +++++++++++++++++++++
4 files changed, 238 insertions(+), 74 deletions(-)
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 a5be1b0753..8d7afb9ed5 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
@@ -102,10 +102,6 @@ public class ClickHouseTableOperations extends
JdbcTableOperations {
ENGINE.SUMMINGMERGETREE,
ENGINE.COLLAPSINGMERGETREE,
ENGINE.VERSIONEDCOLLAPSINGMERGETREE));
-
- private static final Pattern ORDER_BY_PATTERN =
- Pattern.compile(
-
"(?is)\\bORDER\\s+BY\\s*(.+?)(?=\\bPARTITION\\s+BY\\b|\\bPRIMARY\\s+KEY\\b|\\bSAMPLE\\s+BY\\b|\\bTTL\\b|\\bSETTINGS\\b|\\bCOMMENT\\b|$)");
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|$)");
@@ -808,25 +804,28 @@ public class ClickHouseTableOperations extends
JdbcTableOperations {
List<Index> indexes = getIndexes(connection, databaseName, tableName);
jdbcTableBuilder.withIndexes(indexes.toArray(new Index[0]));
- ShowCreateTableMetadata metadata = parseShowCreateTable(connection,
tableName);
- Transform[] partitioning = metadata.partitioning;
+ SystemTableMetadata systemTableMetadata =
+ getSystemTableMetadata(connection, databaseName, tableName);
+ ShowCreateTableMetadata showCreateMetadata =
parseShowCreateTable(connection, tableName);
+ Transform[] partitioning = showCreateMetadata.partitioning;
if (ArrayUtils.isEmpty(partitioning)) {
partitioning = getTablePartitioning(connection, databaseName,
tableName);
}
jdbcTableBuilder.withPartitioning(partitioning);
- jdbcTableBuilder.withSortOrders(metadata.sortOrders);
+ jdbcTableBuilder.withSortOrders(systemTableMetadata.sortOrders());
Distribution distribution = getDistributionInfo(connection,
databaseName, tableName);
jdbcTableBuilder.withDistribution(distribution);
Map<String, String> 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
+ // Merge SETTINGS parsed from system.tables.engine_full into table
properties.
+ // engine_full contains only table-level storage clauses, so projection
SETTINGS cannot be
+ // mistaken for table SETTINGS. These values take 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()) {
+ if (!systemTableMetadata.settings().isEmpty()) {
Map<String, String> merged = new HashMap<>(tableProperties);
- merged.putAll(metadata.settings);
+ merged.putAll(systemTableMetadata.settings());
tableProperties = Collections.unmodifiableMap(merged);
}
jdbcTableBuilder.withProperties(tableProperties);
@@ -856,6 +855,26 @@ public class ClickHouseTableOperations extends
JdbcTableOperations {
return kinds;
}
+ @VisibleForTesting
+ SystemTableMetadata getSystemTableMetadata(
+ Connection connection, String databaseName, String tableName) throws
SQLException {
+ String sql =
+ "SELECT sorting_key, engine_full FROM system.tables WHERE database = ?
AND name = ?";
+ try (PreparedStatement statement = connection.prepareStatement(sql)) {
+ statement.setString(1, databaseName);
+ statement.setString(2, tableName);
+ try (ResultSet resultSet = statement.executeQuery()) {
+ if (resultSet.next()) {
+ return new SystemTableMetadata(
+ parseOrderByClause(resultSet.getString("sorting_key")),
+ parseSettingsFromEngineFull(resultSet.getString("engine_full")));
+ }
+ }
+ }
+
+ throw new NoSuchTableException("Table %s does not exist in %s.",
tableName, databaseName);
+ }
+
@Override
protected Transform[] getTablePartitioning(
Connection connection, String databaseName, String tableName) throws
SQLException {
@@ -1408,21 +1427,11 @@ public class ClickHouseTableOperations extends
JdbcTableOperations {
return metadata;
}
- Matcher orderMatcher = ORDER_BY_PATTERN.matcher(createSql);
- if (orderMatcher.find()) {
- metadata.sortOrders = parseOrderByClause(orderMatcher.group(1));
- }
-
Matcher partitionMatcher = PARTITION_BY_PATTERN.matcher(createSql);
if (partitionMatcher.find()) {
metadata.partitioning = parsePartitioning(partitionMatcher.group(1));
}
- Matcher settingsMatcher = SETTINGS_PATTERN.matcher(createSql);
- if (settingsMatcher.find()) {
- metadata.settings = parseSettingsClause(settingsMatcher.group(1));
- }
-
return metadata;
}
@@ -1446,13 +1455,16 @@ public class ClickHouseTableOperations extends
JdbcTableOperations {
}
@VisibleForTesting
- SortOrder[] parseSortOrdersFromCreateSql(String createSql) {
- return parseCreateStatement(createSql).sortOrders;
- }
+ Map<String, String> parseSettingsFromEngineFull(String engineFull) {
+ if (StringUtils.isBlank(engineFull)) {
+ return Collections.emptyMap();
+ }
- @VisibleForTesting
- Map<String, String> parseSettingsFromCreateSql(String createSql) {
- return parseCreateStatement(createSql).settings;
+ Matcher settingsMatcher = SETTINGS_PATTERN.matcher(engineFull);
+ if (settingsMatcher.find()) {
+ return parseSettingsClause(settingsMatcher.group(1));
+ }
+ return Collections.emptyMap();
}
private ShowCreateTableMetadata parseShowCreateTable(Connection connection,
String tableName)
@@ -1571,10 +1583,27 @@ public class ClickHouseTableOperations extends
JdbcTableOperations {
return expression.toString();
}
+ @VisibleForTesting
+ static final class SystemTableMetadata {
+ private final SortOrder[] sortOrders;
+ private final Map<String, String> settings;
+
+ private SystemTableMetadata(SortOrder[] sortOrders, Map<String, String>
settings) {
+ this.sortOrders = sortOrders;
+ this.settings = settings;
+ }
+
+ SortOrder[] sortOrders() {
+ return sortOrders;
+ }
+
+ Map<String, String> settings() {
+ return settings;
+ }
+ }
+
private static final class ShowCreateTableMetadata {
private Transform[] partitioning = Transforms.EMPTY_TRANSFORM;
- private SortOrder[] sortOrders = SortOrders.NONE;
- private Map<String, String> settings = Collections.emptyMap();
}
@VisibleForTesting
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 f05224a795..f99ee59ed2 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
@@ -431,8 +431,8 @@ public class CatalogClickHouseIT extends BaseIT {
}
@Test
- void testLoadTableFromShowCreateParsing() {
- String name = GravitinoITUtils.genRandomName("show_create_table");
+ void testLoadTableMetadataFromNativeSql() {
+ String name = GravitinoITUtils.genRandomName("native_table_metadata");
clickhouseService.executeQuery(
String.format(
"CREATE TABLE `%s`.`%s` (\n"
@@ -2876,6 +2876,42 @@ public class CatalogClickHouseIT extends BaseIT {
Indexes.EMPTY_INDEXES));
}
+ @Test
+ void testLoadTableWithProjectionUsesTableSortKey() {
+ String name = GravitinoITUtils.genRandomName("proj_normal");
+ clickhouseService.executeQuery(
+ String.format(
+ "CREATE TABLE `%s`.`%s` (\n"
+ + " `id` Int64,\n"
+ + " `dt` Date,\n"
+ + " `val` String,\n"
+ + " PROJECTION p_normal\n"
+ + " (\n"
+ + " SELECT *\n"
+ + " ORDER BY dt\n"
+ + " )\n"
+ + ")\n"
+ + "ENGINE = MergeTree\n"
+ + "ORDER BY (id, dt)\n"
+ + "SETTINGS index_granularity = 8192",
+ schemaName, name));
+
+ Table loaded =
catalog.asTableCatalog().loadTable(NameIdentifier.of(schemaName, name));
+ SortOrder[] sortOrders = loaded.sortOrder();
+
+ Assertions.assertEquals(2, sortOrders.length);
+ Assertions.assertTrue(
+ sortOrders[0].expression() instanceof NamedReference,
+ "First sort key should be a named reference");
+ Assertions.assertArrayEquals(
+ new String[] {"id"}, ((NamedReference)
sortOrders[0].expression()).fieldName());
+ Assertions.assertTrue(sortOrders[1].expression() instanceof
NamedReference);
+ Assertions.assertArrayEquals(
+ new String[] {"dt"}, ((NamedReference)
sortOrders[1].expression()).fieldName());
+ Assertions.assertEquals(
+ "8192", loaded.properties().get(TableConstants.SETTINGS_PREFIX +
"index_granularity"));
+ }
+
@Test
void testEngineParametersRoundTrip() {
// Create a ReplacingMergeTree table with engine parameter via Gravitino
API and verify
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 909b5ec81a..5f3fdbd8ea 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
@@ -1362,44 +1362,20 @@ public class TestClickHouseTableOperations extends
TestClickHouse {
}
@Test
- void testParseSortOrdersFromMultilineShowCreateSql() {
- TestableClickHouseTableOperations ops = new
TestableClickHouseTableOperations();
- String showCreateSql =
- """
- CREATE TABLE `t1`
- (
- `id` Int32,
- `event_time` DateTime
- )
- ENGINE = MergeTree
- ORDER BY
- (`id`, toDate(`event_time`))
- SETTINGS index_granularity = 8192
- """;
-
- SortOrder[] sortOrders = ops.parseSortOrders(showCreateSql);
- Assertions.assertEquals(2, sortOrders.length);
- Assertions.assertTrue(sortOrders[0].expression() instanceof
NamedReference);
- Assertions.assertEquals("id", ((NamedReference)
sortOrders[0].expression()).fieldName()[0]);
- }
-
- @Test
- void testParseSettingsFromCreateSql() {
+ void testParseSettingsFromEngineFull() {
TestableClickHouseTableOperations ops = new
TestableClickHouseTableOperations();
// Single setting
- String sql1 =
- "CREATE TABLE t1 (id Int32) ENGINE = MergeTree ORDER BY id SETTINGS
index_granularity = 4096";
- Map<String, String> settings1 = ops.parseSettings(sql1);
+ String engineFull1 = "MergeTree ORDER BY id SETTINGS index_granularity =
4096";
+ Map<String, String> settings1 = ops.parseSettings(engineFull1);
Assertions.assertEquals(1, settings1.size());
Assertions.assertEquals(
"4096", settings1.get(TableConstants.SETTINGS_PREFIX +
"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<String, String> settings2 = ops.parseSettings(sql2);
+ String engineFull2 =
+ "MergeTree ORDER BY id" + " SETTINGS index_granularity = 4096,
min_bytes_for_wide_part = 0";
+ Map<String, String> settings2 = ops.parseSettings(engineFull2);
Assertions.assertEquals(2, settings2.size());
Assertions.assertEquals(
"4096", settings2.get(TableConstants.SETTINGS_PREFIX +
"index_granularity"));
@@ -1407,15 +1383,15 @@ public class TestClickHouseTableOperations extends
TestClickHouse {
"0", settings2.get(TableConstants.SETTINGS_PREFIX +
"min_bytes_for_wide_part"));
// No SETTINGS clause
- String sql3 = "CREATE TABLE t3 (id Int32) ENGINE = MergeTree ORDER BY id";
- Map<String, String> settings3 = ops.parseSettings(sql3);
+ String engineFull3 = "MergeTree ORDER BY id";
+ Map<String, String> settings3 = ops.parseSettings(engineFull3);
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<String, String> settings4 = ops.parseSettings(sql4);
+ // Engine arguments before SETTINGS
+ String engineFull4 =
+ "ReplicatedMergeTree('/path', '{replica}') ORDER BY id"
+ + " SETTINGS index_granularity = 8192";
+ Map<String, String> settings4 = ops.parseSettings(engineFull4);
Assertions.assertEquals(1, settings4.size());
Assertions.assertEquals(
"8192", settings4.get(TableConstants.SETTINGS_PREFIX +
"index_granularity"));
@@ -1435,12 +1411,8 @@ public class TestClickHouseTableOperations extends
TestClickHouse {
tableName, columns, comment, properties, partitioning, distribution,
indexes, sortOrders);
}
- SortOrder[] parseSortOrders(String createSql) {
- return parseSortOrdersFromCreateSql(createSql);
- }
-
- Map<String, String> parseSettings(String createSql) {
- return parseSettingsFromCreateSql(createSql);
+ Map<String, String> parseSettings(String engineFull) {
+ return parseSettingsFromEngineFull(engineFull);
}
}
diff --git
a/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/operations/TestClickHouseTableOperationsUnit.java
b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/operations/TestClickHouseTableOperationsUnit.java
index e2cfa0ad07..ae24dbf649 100644
---
a/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/operations/TestClickHouseTableOperationsUnit.java
+++
b/catalogs-contrib/catalog-jdbc-clickhouse/src/test/java/org/apache/gravitino/catalog/clickhouse/operations/TestClickHouseTableOperationsUnit.java
@@ -32,7 +32,11 @@ import
org.apache.gravitino.catalog.clickhouse.converter.ClickHouseColumnDefault
import
org.apache.gravitino.catalog.clickhouse.converter.ClickHouseExceptionConverter;
import
org.apache.gravitino.catalog.clickhouse.converter.ClickHouseTypeConverter;
import org.apache.gravitino.catalog.jdbc.JdbcColumn;
+import org.apache.gravitino.exceptions.NoSuchTableException;
+import org.apache.gravitino.rel.expressions.FunctionExpression;
+import org.apache.gravitino.rel.expressions.NamedReference;
import org.apache.gravitino.rel.expressions.distributions.Distributions;
+import org.apache.gravitino.rel.expressions.sorts.SortOrder;
import org.apache.gravitino.rel.expressions.transforms.Transforms;
import org.apache.gravitino.rel.indexes.Index;
import org.apache.gravitino.rel.indexes.Indexes;
@@ -50,6 +54,11 @@ public class TestClickHouseTableOperationsUnit {
return getIndexes(connection, databaseName, tableName);
}
+ SystemTableMetadata callGetSystemTableMetadata(
+ Connection connection, String databaseName, String tableName) throws
Exception {
+ return getSystemTableMetadata(connection, databaseName, tableName);
+ }
+
Map<String, String> callGetTableProperties(Connection connection, String
tableName)
throws Exception {
return getTableProperties(connection, tableName);
@@ -136,6 +145,124 @@ public class TestClickHouseTableOperationsUnit {
Assertions.assertTrue(primaryKeySql.contains("t''1"), "table single quote
should be doubled");
}
+ @Test
+ void testGetSystemTableMetadataQueriesExactTable() throws Exception {
+ ExposedClickHouseTableOperations ops = newOps();
+ Connection connection = Mockito.mock(Connection.class);
+ PreparedStatement statement = Mockito.mock(PreparedStatement.class);
+ ResultSet resultSet = Mockito.mock(ResultSet.class);
+ ArgumentCaptor<String> sqlCaptor = ArgumentCaptor.forClass(String.class);
+
+
Mockito.when(connection.prepareStatement(sqlCaptor.capture())).thenReturn(statement);
+ Mockito.when(statement.executeQuery()).thenReturn(resultSet);
+ Mockito.when(resultSet.next()).thenReturn(true);
+ Mockito.when(resultSet.getString("sorting_key")).thenReturn("id");
+ Mockito.when(resultSet.getString("engine_full")).thenReturn("MergeTree
ORDER BY id");
+
+ ClickHouseTableOperations.SystemTableMetadata metadata =
+ ops.callGetSystemTableMetadata(connection, "db_name", "table_name");
+
+ Assertions.assertEquals(
+ "SELECT sorting_key, engine_full FROM system.tables WHERE database = ?
AND name = ?",
+ sqlCaptor.getValue());
+ Mockito.verify(statement).setString(1, "db_name");
+ Mockito.verify(statement).setString(2, "table_name");
+ Assertions.assertEquals(1, metadata.sortOrders().length);
+ Assertions.assertEquals(NamedReference.field("id"),
metadata.sortOrders()[0].expression());
+ Assertions.assertTrue(metadata.settings().isEmpty());
+ Mockito.verify(resultSet).close();
+ Mockito.verify(statement).close();
+ }
+
+ @Test
+ void testGetSystemTableMetadataParsesCompoundAndFunctionExpressions() throws
Exception {
+ ExposedClickHouseTableOperations ops = newOps();
+ Connection connection = Mockito.mock(Connection.class);
+ PreparedStatement statement = Mockito.mock(PreparedStatement.class);
+ ResultSet resultSet = Mockito.mock(ResultSet.class);
+
+
Mockito.when(connection.prepareStatement(Mockito.anyString())).thenReturn(statement);
+ Mockito.when(statement.executeQuery()).thenReturn(resultSet);
+ Mockito.when(resultSet.next()).thenReturn(true);
+ Mockito.when(resultSet.getString("sorting_key")).thenReturn("id,
toDate(event_time)");
+ Mockito.when(resultSet.getString("engine_full")).thenReturn("MergeTree
ORDER BY id");
+
+ SortOrder[] sortOrders =
+ ops.callGetSystemTableMetadata(connection, "db_name",
"table_name").sortOrders();
+
+ Assertions.assertEquals(2, sortOrders.length);
+ Assertions.assertEquals(NamedReference.field("id"),
sortOrders[0].expression());
+ Assertions.assertEquals(
+ FunctionExpression.of("toDate", NamedReference.field("event_time")),
+ sortOrders[1].expression());
+ }
+
+ @Test
+ void testGetSystemTableMetadataReturnsNoneForBlankValues() throws Exception {
+ ExposedClickHouseTableOperations ops = newOps();
+ Connection connection = Mockito.mock(Connection.class);
+ PreparedStatement statement = Mockito.mock(PreparedStatement.class);
+ ResultSet resultSet = Mockito.mock(ResultSet.class);
+
+
Mockito.when(connection.prepareStatement(Mockito.anyString())).thenReturn(statement);
+ Mockito.when(statement.executeQuery()).thenReturn(resultSet);
+ Mockito.when(resultSet.next()).thenReturn(true);
+ Mockito.when(resultSet.getString("sorting_key")).thenReturn(" ");
+ Mockito.when(resultSet.getString("engine_full")).thenReturn(" ");
+
+ ClickHouseTableOperations.SystemTableMetadata metadata =
+ ops.callGetSystemTableMetadata(connection, "db_name", "table_name");
+
+ Assertions.assertArrayEquals(new SortOrder[0], metadata.sortOrders());
+ Assertions.assertTrue(metadata.settings().isEmpty());
+ }
+
+ @Test
+ void testGetSystemTableMetadataParsesSettingsFromEngineFull() throws
Exception {
+ ExposedClickHouseTableOperations ops = newOps();
+ Connection connection = Mockito.mock(Connection.class);
+ PreparedStatement statement = Mockito.mock(PreparedStatement.class);
+ ResultSet resultSet = Mockito.mock(ResultSet.class);
+
+
Mockito.when(connection.prepareStatement(Mockito.anyString())).thenReturn(statement);
+ Mockito.when(statement.executeQuery()).thenReturn(resultSet);
+ Mockito.when(resultSet.next()).thenReturn(true);
+ Mockito.when(resultSet.getString("sorting_key")).thenReturn("id");
+ Mockito.when(resultSet.getString("engine_full"))
+ .thenReturn(
+ "MergeTree ORDER BY id SETTINGS index_granularity = 4096, "
+ + "min_bytes_for_wide_part = 0");
+
+ Map<String, String> settings =
+ ops.callGetSystemTableMetadata(connection, "db_name",
"table_name").settings();
+
+ Assertions.assertEquals(2, settings.size());
+ Assertions.assertEquals(
+ "4096", settings.get(TableConstants.SETTINGS_PREFIX +
"index_granularity"));
+ Assertions.assertEquals(
+ "0", settings.get(TableConstants.SETTINGS_PREFIX +
"min_bytes_for_wide_part"));
+ }
+
+ @Test
+ void testGetSystemTableMetadataThrowsWhenTableIsNotVisible() throws
Exception {
+ ExposedClickHouseTableOperations ops = newOps();
+ Connection connection = Mockito.mock(Connection.class);
+ PreparedStatement statement = Mockito.mock(PreparedStatement.class);
+ ResultSet resultSet = Mockito.mock(ResultSet.class);
+
+
Mockito.when(connection.prepareStatement(Mockito.anyString())).thenReturn(statement);
+ Mockito.when(statement.executeQuery()).thenReturn(resultSet);
+ Mockito.when(resultSet.next()).thenReturn(false);
+
+ NoSuchTableException exception =
+ Assertions.assertThrows(
+ NoSuchTableException.class,
+ () -> ops.callGetSystemTableMetadata(connection, "db_name",
"table_name"));
+
+ Assertions.assertTrue(exception.getMessage().contains("table_name"));
+ Assertions.assertTrue(exception.getMessage().contains("db_name"));
+ }
+
//
---------------------------------------------------------------------------
// extractEngineParams
//
---------------------------------------------------------------------------