From 6633774a8029773400599548c3597de745604b81 Mon Sep 17 00:00:00 2001 From: morrySnow Date: Wed, 9 Sep 2026 16:19:12 +0800 Subject: [PATCH] [fix](mv) Prevent snapshot reads from using current MVs (#67700) ## Problem An external-table query that explicitly reads an older snapshot can still enter materialized view rewrite. The candidate materialized view represents the table state at its refresh snapshot, so using a current materialized view for a historical query can silently return data from the wrong point in time. ## Root cause `LogicalFileScan` stores standard `FOR TIME AS OF` and `FOR VERSION AS OF` clauses in `tableSnapshot`. The materialized-view eligibility checker rejected scans with table samples or scan parameters, but did not inspect `tableSnapshot`. As a result, the historical scan was treated like an ordinary latest-snapshot scan. ## How to reproduce 1. Create an Iceberg table and insert an initial row, then record that snapshot ID. 2. Insert newer data and refresh a materialized view over the table at the current snapshot. 3. Enable materialized-view rewrite and query the Iceberg table with `FOR VERSION AS OF ` (the same issue applies to `FOR TIME AS OF`). 4. Before this change, the historical query can be considered eligible for rewrite by the current-snapshot materialized view, producing current rather than historical results. The same condition can be reproduced directly in the optimizer by building a `LogicalFileScan` with a non-empty `tableSnapshot`: the table-query-operator checker previously returned false. ## Fix Treat a non-empty `LogicalFileScan.tableSnapshot` as a table-level query operator, alongside table samples and scan parameters. This conservatively prevents materialized-view rewrite until the optimizer can prove that the query snapshot and materialized-view refresh snapshot are semantically equivalent. Add a unit test that constructs a file scan with a version snapshot and verifies that the checker rejects it from ordinary rewrite eligibility. --- .../rules/exploration/mv/MaterializedViewUtils.java | 6 ++++-- .../exploration/mv/MaterializedViewUtilsTest.java | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/MaterializedViewUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/MaterializedViewUtils.java index bab7db768faab0..1fe2bcc4274ab4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/MaterializedViewUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/MaterializedViewUtils.java @@ -619,9 +619,11 @@ public static final class TableQueryOperatorChecker extends DefaultPlanVisitor