-
Notifications
You must be signed in to change notification settings - Fork 5.5k
fix(analyzer): Materialized view with logical view and cte #26713
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
Conversation
Reviewer's GuideExtends the analyzer to track WHERE predicates from logical view accessors and combine them with the current subquery predicate when computing materialized view status, and adds regression tests covering partition-based MV selection through logical views and CTEs. Sequence diagram for logical view WHERE predicate propagation into materialized view statussequenceDiagram
actor User
participant Planner
participant StatementAnalyzer
participant Analysis
participant MetadataResolver
participant MaterializedViewStatus
User->>Planner: submit query referencing logical_view with WHERE
Planner->>StatementAnalyzer: analyze query
Note over StatementAnalyzer,Analysis: Processing logical view access
StatementAnalyzer->>Analysis: getCurrentQuerySpecification()
Analysis-->>StatementAnalyzer: Optional currentQuerySpecification
alt currentQuerySpecification present and has WHERE
StatementAnalyzer->>Analysis: setViewAccessorWhereClause(Optional whereClause)
end
StatementAnalyzer->>StatementAnalyzer: parseView and analyzeView(logical_view)
Note over StatementAnalyzer,Analysis: Inside analysis of view, resolve materialized view
StatementAnalyzer->>Analysis: getCurrentQuerySpecification()
Analysis-->>StatementAnalyzer: Optional currentSubquery
StatementAnalyzer->>Analysis: getViewAccessorWhereClause()
Analysis-->>StatementAnalyzer: Optional viewAccessorWhereClause
StatementAnalyzer->>StatementAnalyzer: build wherePredicates list
StatementAnalyzer->>StatementAnalyzer: combinedWhereClause = ExpressionUtils.combineConjuncts(wherePredicates)
StatementAnalyzer->>StatementAnalyzer: conjuncts = ExpressionUtils.extractConjuncts(combinedWhereClause)
StatementAnalyzer->>MetadataResolver: getMaterializedViewDefinition(materializedViewName)
MetadataResolver-->>StatementAnalyzer: Optional materializedViewDefinition
StatementAnalyzer->>StatementAnalyzer: filter conjuncts on MV columns
StatementAnalyzer-->>MaterializedViewStatus: create MaterializedViewStatus
Note over StatementAnalyzer,Analysis: After view analysis completes
StatementAnalyzer->>Analysis: clearViewAccessorWhereClause()
StatementAnalyzer-->>Planner: analysis result for query
Planner-->>User: planned query using materialized view when valid
Class diagram for updated Analysis and StatementAnalyzer materialized view handlingclassDiagram
class Analysis {
- Optional~QuerySpecification~ currentQuerySpecification
- Optional~Expression~ viewAccessorWhereClause
+ void setCurrentSubquery(QuerySpecification currentSubQuery)
+ Optional~QuerySpecification~ getCurrentQuerySpecification()
+ void setViewAccessorWhereClause(Optional~Expression~ whereClause)
+ void clearViewAccessorWhereClause()
+ Optional~Expression~ getViewAccessorWhereClause()
}
class StatementAnalyzer {
- Analysis analysis
+ Scope processView(Table table, Optional~Scope~ scope, QualifiedObjectName name)
- MaterializedViewStatus getMaterializedViewStatus(QualifiedObjectName materializedViewName, Table table, Optional~Scope~ scope, Session session, MetadataResolver metadataResolver)
}
class Expression {
}
class QuerySpecification {
+ Optional~Expression~ getWhere()
}
class MaterializedViewStatus {
}
class ExpressionUtils {
+ static Expression combineConjuncts(List~Expression~ predicates)
+ static List~Expression~ extractConjuncts(Expression predicate)
}
class VariablesExtractor {
+ static Set~QualifiedName~ extractNames(Expression expression, Set~Expression~ columnReferences)
}
Analysis --> QuerySpecification : uses
Analysis --> Expression : tracks
StatementAnalyzer --> Analysis : collaborates
StatementAnalyzer --> MaterializedViewStatus : computes
StatementAnalyzer --> ExpressionUtils : uses
StatementAnalyzer --> VariablesExtractor : uses
QuerySpecification --> Expression : where
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
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.
Hey there - I've reviewed your changes - here's some feedback:
- When saving and restoring
viewAccessorWhereClauseinStatementAnalyzer.processView, you currently only clear it after analyzing the view; if view analysis is nested (view within view), this will lose any outer accessor predicate—consider saving the previous value and restoring it rather than unconditionally clearing. - The new MV/CTE logical view tests have a lot of duplicated setup (creating similar partitioned tables, MVs, sessions, and assertions); consider extracting common helpers to reduce duplication and make future changes to these scenarios less error-prone.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- When saving and restoring `viewAccessorWhereClause` in `StatementAnalyzer.processView`, you currently only clear it after analyzing the view; if view analysis is nested (view within view), this will lose any outer accessor predicate—consider saving the previous value and restoring it rather than unconditionally clearing.
- The new MV/CTE logical view tests have a lot of duplicated setup (creating similar partitioned tables, MVs, sessions, and assertions); consider extracting common helpers to reduce duplication and make future changes to these scenarios less error-prone.
## Individual Comments
### Comment 1
<location> `presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java:2375-2379` </location>
<code_context>
analysis.getAccessControlReferences().addViewDefinitionReference(name, view);
+ Optional<Expression> savedViewAccessorWhereClause = Optional.empty();
+ if (analysis.getCurrentQuerySpecification().isPresent()) {
+ QuerySpecification currentQuerySpec = analysis.getCurrentQuerySpecification().get();
+ savedViewAccessorWhereClause = currentQuerySpec.getWhere();
+ if (savedViewAccessorWhereClause.isPresent()) {
+ analysis.setViewAccessorWhereClause(savedViewAccessorWhereClause);
+ }
</code_context>
<issue_to_address>
**issue (bug_risk):** viewAccessorWhereClause is not restored to its previous value, which can break nested view/materialized-view analysis
Here, `viewAccessorWhereClause` is updated and then cleared based only on the current query’s `WHERE` clause, which breaks proper nesting:
1. If an outer context already set `viewAccessorWhereClause` and this view also has a `WHERE`, the outer value is overwritten and then lost, so outer predicates are dropped for later MV partition filtering.
2. If this view has no `WHERE`, you leave any existing `viewAccessorWhereClause` in place, so unrelated outer predicates are incorrectly applied to this view.
To keep nesting semantics correct, capture the previous value, set the current value (including explicitly clearing it when there is no `WHERE`), and restore the previous value in a `try/finally`:
```java
Optional<Expression> previousAccessorWhere = analysis.getViewAccessorWhereClause();
Optional<Expression> currentAccessorWhere = currentQuerySpec.getWhere();
analysis.setViewAccessorWhereClause(currentAccessorWhere);
try {
// analyze view
}
finally {
analysis.setViewAccessorWhereClause(previousAccessorWhere);
}
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java
Outdated
Show resolved
Hide resolved
hantangwangd
left a comment
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.
@zation99 thanks for this fix, overall looks good to me. Just a couple of little nits.
presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java
Outdated
Show resolved
Hide resolved
presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java
Outdated
Show resolved
Hide resolved
…26713) Summary: If a materialized view is a part of a logical view, the logical view's where predicate is not pushed down to materialized view so that it doesn't check the overlap correctly. It caused the comparison between mv's data and ALL base table data instead of the ones specified in the query. This diff fixes it by storing the where predicate when processing a logical view. So mv can combine the where predicate in logical view as well when getting mv status. It also fixes the issue during with using the logical view/mv in cte. Differential Revision: D87928199
f9c19b8 to
eb29e15
Compare
…26713) Summary: If a materialized view is a part of a logical view, the logical view's where predicate is not pushed down to materialized view so that it doesn't check the overlap correctly. It caused the comparison between mv's data and ALL base table data instead of the ones specified in the query. This diff fixes it by storing the where predicate when processing a logical view. So mv can combine the where predicate in logical view as well when getting mv status. It also fixes the issue during with using the logical view/mv in cte. Differential Revision: D87928199
eb29e15 to
16281cd
Compare
hantangwangd
left a comment
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.
Thanks for the fix, lgtm!
Summary:
If a materialized view is a part of a logical view, the logical view's where predicate is not pushed down to materialized view so that it doesn't check the overlap correctly. It caused the comparison between mv's data and ALL base table data instead of the ones specified in the query.
This diff fixes it by storing the where predicate when processing a logical view. So mv can combine the where predicate in logical view as well when getting mv status. It also fixes the issue during with using the logical view/mv in cte.
Differential Revision: D87928199