This is an automated email from the ASF dual-hosted git repository.
voonhous pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hudi.git
The following commit(s) were added to refs/heads/master by this push:
new d3856f4b10cf test(metadata): cover getColumnsToIndex when the table
schema is absent (#19859)
d3856f4b10cf is described below
commit d3856f4b10cfcdb25f0e8b5b84e625db3dc14feb
Author: Ranga Reddy <[email protected]>
AuthorDate: Fri Sep 18 12:37:39 2026 +0530
test(metadata): cover getColumnsToIndex when the table schema is absent
(#19859)
* test(metadata): cover getColumnsToIndex when the table schema is absent
Closes #17410.
HUDI-9194 asked whether getColumnsToIndexWithoutRequiredMetaFields needs a
test
case. Its branches are almost all covered already through the public
getColumnsToIndex wrapper: the explicit column list, meta columns inside
that
list, unsupported types, nested fields, the max-columns cap, and meta fields
disabled. One branch was not reachable from any existing case, because every
one of them supplies a schema: the path taken when the table schema is
absent.
Added a case for it, pinning three outcomes that differ in ways worth
fixing in
place:
- No explicit column list: the inner call returns nothing, so the caller is
left with just the always-indexed meta columns. Col stats initialises
rather
than failing.
- An explicit column list: it throws IllegalArgumentException naming the
missing schema, since the configured names cannot be resolved to field
schemas without one, and indexing nothing would look like the config had
been honoured.
- The same list while the table is initialising: the names are recorded
without
schemas, so col stats can be enabled before the first commit has produced
a
schema.
Test-only; no production code touched.
* test(metadata): pin that the initializing branch never resolves the schema
Supply the table schema as a Lazy that fails the test if it is ever forced,
rather than an eagerly computed empty Option. The initializing branch
returns
before touching tableSchemaLazyOpt, and an eager value cannot tell "never
resolved" from "resolved and absent".
This matters on the real path: ColumnStatsIndexer passes isTableInitializing
together with Lazy.lazily(tryResolveSchemaForTable) whenever an explicit
column
list is set, including on tables that already have data, so resolving in
this
branch would cost a schema read there.
Verified by hoisting the checkArgument above the initializing return, which
turns the test red on the supplier.
* test(metadata): trim the test javadoc to what it verifies
---
.../hudi/metadata/TestHoodieTableMetadataUtil.java | 46 ++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git
a/hudi-hadoop-common/src/test/java/org/apache/hudi/metadata/TestHoodieTableMetadataUtil.java
b/hudi-hadoop-common/src/test/java/org/apache/hudi/metadata/TestHoodieTableMetadataUtil.java
index 769af07c7388..6b34762d97fc 100644
---
a/hudi-hadoop-common/src/test/java/org/apache/hudi/metadata/TestHoodieTableMetadataUtil.java
+++
b/hudi-hadoop-common/src/test/java/org/apache/hudi/metadata/TestHoodieTableMetadataUtil.java
@@ -96,6 +96,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
@@ -605,6 +606,51 @@ public class TestHoodieTableMetadataUtil extends
HoodieCommonTestHarness {
Lazy.eagerly(Option.of(schema)), true, V1).keySet()));
}
+ /**
+ * The schema-absent branch of {@code
getColumnsToIndexWithoutRequiredMetaFields}, which
+ * {@link #testGetColumnsToIndex()} never reaches because every case there
supplies a schema. With no
+ * explicit column list it yields only the always-indexed meta columns; with
one it throws, since those
+ * names cannot be resolved without a schema. While initializing it returns
them unresolved instead.
+ */
+ @Test
+ public void testGetColumnsToIndexWhenTableSchemaIsAbsent() {
+ HoodieTableConfig tableConfig = metaClient.getTableConfig();
+
+ HoodieMetadataConfig noColumnList = HoodieMetadataConfig.newBuilder()
+ .enable(true).withMetadataIndexColumnStats(true)
+ .build();
+ assertListEquality(new
ArrayList<>(Arrays.asList(HoodieTableMetadataUtil.META_COLS_TO_ALWAYS_INDEX)),
+ new ArrayList<>(HoodieTableMetadataUtil.getColumnsToIndex(tableConfig,
noColumnList,
+ Lazy.eagerly(Option.empty()), false, V1).keySet()));
+
+ HoodieMetadataConfig withColumnList = HoodieMetadataConfig.newBuilder()
+ .enable(true).withMetadataIndexColumnStats(true)
+ .withColumnStatsIndexForColumns("col_1,col_2")
+ .build();
+ Throwable thrown = assertThrows(IllegalArgumentException.class,
+ () -> HoodieTableMetadataUtil.getColumnsToIndex(tableConfig,
withColumnList,
+ Lazy.eagerly(Option.empty()), false, V1),
+ "an explicit column list cannot be resolved without a table schema");
+ assertTrue(String.valueOf(thrown.getMessage()).contains("Table schema not
found"),
+ () -> "the failure should name the missing schema, but was: " +
thrown.getMessage());
+
+ // Table initialisation is the exception: the configured names are
recorded without schemas, so col
+ // stats can be enabled before the first commit has produced one. The meta
columns are added by the
+ // caller either way.
+ //
+ // The schema is supplied as a lazy that fails if it is ever forced,
because this branch must return
+ // without resolving it at all. ColumnStatsIndexer passes
isTableInitializing=true together with a
+ // Lazy.lazily(tryResolveSchemaForTable) whenever an explicit column list
is set, including on tables
+ // that already have data, so resolving here would cost a schema read on
that path. An eagerly-computed
+ // empty Option cannot tell "never resolved" from "resolved and absent";
this can.
+ List<String> expectedWhileInitialising = new
ArrayList<>(Arrays.asList(HoodieTableMetadataUtil.META_COLS_TO_ALWAYS_INDEX));
+ expectedWhileInitialising.addAll(Arrays.asList("col_1", "col_2"));
+ assertListEquality(expectedWhileInitialising,
+ new ArrayList<>(HoodieTableMetadataUtil.getColumnsToIndex(tableConfig,
withColumnList,
+ Lazy.lazily(() -> fail("the initializing branch must not resolve
the table schema")),
+ true, V1).keySet()));
+ }
+
private void assertListEquality(List<String> expected, List<String> actual) {
Collections.sort(expected);
Collections.sort(actual);