-
Notifications
You must be signed in to change notification settings - Fork 3.9k
[fix](iceberg) Fix historical scans after schema evolution #67479
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: branch-4.1
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2938,6 +2938,63 @@ public void testHistoricalPredicateUsesSelectedScanSchema() throws Exception { | |
| Mockito.verify(scan).filter(Mockito.argThat(expression -> expression.toString().contains("old_name"))); | ||
| } | ||
|
|
||
| @Test | ||
| public void testHistoricalPredicatePlansAfterColumnRename() throws Exception { | ||
| assertHistoricalPredicatePlansAfterSchemaEvolution(false); | ||
| } | ||
|
|
||
| @Test | ||
| public void testHistoricalPredicatePlansAfterColumnDrop() throws Exception { | ||
| assertHistoricalPredicatePlansAfterSchemaEvolution(true); | ||
| } | ||
|
|
||
| private void assertHistoricalPredicatePlansAfterSchemaEvolution(boolean dropColumn) throws Exception { | ||
| Schema historicalSchema = new Schema( | ||
| Types.NestedField.optional(1, "x", Types.IntegerType.get()), | ||
| Types.NestedField.optional(2, "y", Types.IntegerType.get()), | ||
| Types.NestedField.optional(3, "part", Types.IntegerType.get())); | ||
| HadoopTables tables = new HadoopTables(new Configuration()); | ||
| String tableLocation = temporaryFolder.getRoot().toPath() | ||
| .resolve("historical_predicate_after_" + (dropColumn ? "drop" : "rename")).toUri().toString(); | ||
| Table table = tables.create( | ||
| historicalSchema, PartitionSpec.unpartitioned(), SortOrder.unsorted(), | ||
| ImmutableMap.of(TableProperties.FORMAT_VERSION, "2"), tableLocation); | ||
| DataFile historicalDataFile = DataFiles.builder(table.spec()) | ||
| .withPath(tableLocation + "/data/historical.parquet") | ||
| .withFormat(FileFormat.PARQUET) | ||
| .withFileSizeInBytes(10) | ||
| .withRecordCount(2) | ||
| .build(); | ||
| table.newFastAppend().appendFile(historicalDataFile).commit(); | ||
| long historicalSnapshotId = table.currentSnapshot().snapshotId(); | ||
| int historicalSchemaId = table.currentSnapshot().schemaId(); | ||
|
|
||
| if (dropColumn) { | ||
| table.updateSchema().deleteColumn("x").commit(); | ||
| } else { | ||
| table.updateSchema().renameColumn("x", "renamed_x").commit(); | ||
| } | ||
| DataFile currentDataFile = DataFiles.builder(table.spec()) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P1] Cover schema-only evolution before advancing the snapshot Iceberg schema commits do not create a new snapshot, so immediately after this rename/drop |
||
| .withPath(tableLocation + "/data/current.parquet") | ||
| .withFormat(FileFormat.PARQUET) | ||
| .withFileSizeInBytes(10) | ||
| .withRecordCount(1) | ||
| .build(); | ||
| table.newFastAppend().appendFile(currentDataFile).commit(); | ||
|
|
||
| // Historical filters must be resolved with the snapshot schema after later schema evolution. | ||
| TableScan scan = table.newScan() | ||
| .useSnapshot(historicalSnapshotId) | ||
| .project(table.schemas().get(historicalSchemaId)); | ||
| BinaryPredicate conjunct = new BinaryPredicate(BinaryPredicate.Operator.EQ, | ||
| new SlotRef(new TableName(), "x"), new IntLiteral(1, Type.INT)); | ||
| org.apache.iceberg.expressions.Expression predicate = | ||
| IcebergUtils.convertToIcebergExpr(conjunct, scan.schema()); | ||
| Assert.assertNotNull(predicate); | ||
| scan = scan.filter(predicate); | ||
| Assert.assertEquals(1, materializeTasks(scan).size()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P1] Exercise the Doris planner, not only native planFiles This assertion calls Iceberg's |
||
| } | ||
|
|
||
| @Test | ||
| public void testPinnedBranchUsesFrozenSnapshotWithCurrentSchema() throws Exception { | ||
| Schema snapshotSchema = new Schema(11, ImmutableList.of( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -226,7 +226,7 @@ under the License. | |
| <module>fe-authentication</module> | ||
| </modules> | ||
| <properties> | ||
| <doris.hive.catalog.shade.version>3.1.2</doris.hive.catalog.shade.version> | ||
| <doris.hive.catalog.shade.version>3.1.3-ICEBERG-SNAPSHOT</doris.hive.catalog.shade.version> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P1] Pin an immutable shade release before merging This changes packaged/runtime consumers to |
||
| <!-- iceberg 1.9.1 depends avro on 1.12 --> | ||
| <avro.version>1.12.1</avro.version> | ||
| <parquet.version>1.17.0</parquet.version> | ||
|
|
@@ -333,7 +333,7 @@ under the License. | |
| <!-- ATTN: avro version must be consistent with Iceberg version --> | ||
| <!-- Please modify iceberg.version and avro.version together, | ||
| you can find avro version info in iceberg mvn repository --> | ||
| <iceberg.version>1.10.1</iceberg.version> | ||
| <iceberg.version>1.11.0</iceberg.version> | ||
| <lance.version>9.1.0-beta.3</lance.version> | ||
| <substrait.version>0.40.0</substrait.version> | ||
| <!-- 0.56.1 has bug that "SplitMode" in query response may not be set--> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P2] Expose and wire the historical-schema map
The only Doris caller of the public iterable builder is in another package, so it cannot call this new package-private setter and currently supplies only
icebergTable.specs(). Iceberg 1.11 addedschemasByIdspecifically because current specs no longer contain an equality-delete field after that field is dropped;fieldLookupthen returns null andforDataFilethrows. Doris catches that in the manifest-cache planner and reruns native planning, so every affected scan loses the enabled cache and logs a failure. Please make this hook public, pass the frozen table's fullschemas()map, and cover a dropped equality key through the cache planner.