yujun777 commented on code in PR #63639:
URL: https://github.com/apache/doris/pull/63639#discussion_r4140246940
##########
fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVCache.java:
##########
@@ -142,6 +160,19 @@ public static MTMVCache from(String defSql,
.orElse(rewritePlan);
Pair<Plan, StructInfo> finalPlanStructInfoPair =
constructPlanAndStructInfo(
addGuardRewritePlan, cascadesContext);
+ // Analysis records nondeterministic functions before constant
folding erases their origin.
+ // Replanning current_date(), for example, cannot establish a
guarantee about rows stored
+ // by an earlier refresh. Do not export output guarantees from
such a definition.
+ // Alias UDF definitions can also change between refresh and cache
reconstruction,
+ // even when the expanded function body is deterministic.
+ // A lower MV may have refreshed since this MV's rows were stored.
Derive guarantees
+ // from this definition alone, without importing the lower MV's
current output facts.
+ Set<Expression> outputPredicates =
(cascadesContext.getStatementContext().hasNondeterministic()
Review Comment:
[P1] Preserve refresh-time expression bindings before exporting output
facts. These predicates are derived from the expression as currently analyzed,
while only nondeterministic expressions and alias UDFs are excluded. A
replaceable IMMUTABLE Java/Python UDF, or a folded mutable global/session
variable, can change its binding without refreshing the lower MV. After cache
rebuild, the lower cache may incorrectly claim `id > 10` although its stored
rows were built with `id > 1`; an upper MV refreshed with the new bound can
have its real filter removed by `withoutRedundantMvFilters()`, allowing `SELECT
id FROM lower` to lose rows 2..10. Persist and validate the refresh-time
binding/signature, or withhold dependent output guarantees when the binding is
not stable.
##########
fe/fe-core/src/main/java/org/apache/doris/catalog/MTMV.java:
##########
@@ -1683,6 +1687,16 @@ public void writeMvUnlock() {
this.mvRwLock.writeLock().unlock();
}
+ private MTMVCache cacheWithValidOutputPredicates(MTMVCache cache) {
+ // A cache built from the current definition can prove facts about
stored rows only after
+ // every partition has been refreshed. Callers hold the MV lock while
publishing it.
+ if (status.getState() == MTMVState.SCHEMA_CHANGE
Review Comment:
[P1] Suppress output guarantees after direct MTMV writes. This gate only
checks SCHEMA_CHANGE and partition snapshot coverage, but
`allow_modify_materialized_view_data` permits direct writes that do not
invalidate this guarantee. For example, after a lower MV defined with `WHERE id
> 10` is refreshed, inserting `id = 5` directly into it leaves the lower cache
claiming `id > 10`. Refreshing an upper MV defined as `SELECT id FROM lower
WHERE id > 10` omits that row; `withoutRedundantMvFilters()` can then remove
the upper filter and rewrite `SELECT id FROM lower` to the upper MV, losing `id
= 5`. Track direct writes as a persistent loss of output guarantees until a
qualifying refresh; transient cache invalidation alone is insufficient because
rebuilding the same definition repeats the false proof.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]