-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
[BugFix] Fix union all rewrite bugs in pulling up predicates and add materialized_view_union_rewrite_mode param #42229
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 |
---|---|---|
|
@@ -46,7 +46,6 @@ | |
import com.starrocks.qe.SessionVariable; | ||
import com.starrocks.sql.common.ErrorType; | ||
import com.starrocks.sql.common.PermutationGenerator; | ||
import com.starrocks.sql.common.QueryDebugOptions; | ||
import com.starrocks.sql.common.StarRocksPlannerException; | ||
import com.starrocks.sql.optimizer.ExpressionContext; | ||
import com.starrocks.sql.optimizer.MaterializationContext; | ||
|
@@ -63,10 +62,12 @@ | |
import com.starrocks.sql.optimizer.operator.OperatorBuilderFactory; | ||
import com.starrocks.sql.optimizer.operator.Projection; | ||
import com.starrocks.sql.optimizer.operator.logical.LogicalAggregationOperator; | ||
import com.starrocks.sql.optimizer.operator.logical.LogicalFilterOperator; | ||
import com.starrocks.sql.optimizer.operator.logical.LogicalJoinOperator; | ||
import com.starrocks.sql.optimizer.operator.logical.LogicalOlapScanOperator; | ||
import com.starrocks.sql.optimizer.operator.logical.LogicalOperator; | ||
import com.starrocks.sql.optimizer.operator.logical.LogicalScanOperator; | ||
import com.starrocks.sql.optimizer.operator.logical.LogicalSetOperator; | ||
import com.starrocks.sql.optimizer.operator.logical.LogicalUnionOperator; | ||
import com.starrocks.sql.optimizer.operator.logical.LogicalViewScanOperator; | ||
import com.starrocks.sql.optimizer.operator.scalar.BinaryPredicateOperator; | ||
|
@@ -80,6 +81,7 @@ | |
import com.starrocks.sql.optimizer.rewrite.ReplaceColumnRefRewriter; | ||
import com.starrocks.sql.optimizer.rewrite.scalar.MvNormalizePredicateRule; | ||
import com.starrocks.sql.optimizer.rule.mv.JoinDeriveContext; | ||
import com.starrocks.sql.optimizer.rule.transformation.PushDownPredicateSetRule; | ||
import org.apache.commons.collections4.ListUtils; | ||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
|
@@ -112,6 +114,8 @@ public class MaterializedViewRewriter { | |
protected final OptimizerContext optimizerContext; | ||
// Mark whether query's plan is rewritten by materialized view. | ||
public static final String REWRITE_SUCCESS = "Rewrite Succeed"; | ||
public static final int UNION_REWRITE_EAGER_MODE_1 = 1; | ||
public static final int UNION_REWRITE_EAGER_MODE_2 = 2; | ||
|
||
private static final Map<JoinOperator, List<JoinOperator>> JOIN_COMPATIBLE_MAP = | ||
ImmutableMap.<JoinOperator, List<JoinOperator>>builder() | ||
|
@@ -1544,6 +1548,7 @@ private boolean isPullUpQueryPredicate(ScalarOperator predicate, | |
// t where t.a < 1 | ||
// If you want to use this feature, you can use it by the setting: | ||
// set query_debug_options = "{'enableMVEagerUnionAllRewrite':true}"; | ||
// use union-all rewrite eagerly if union-all rewrite can be used. | ||
if (queryOutputColumnRefs != null && queryOutputColumnRefs.contains(col)) { | ||
return true; | ||
} | ||
|
@@ -1562,8 +1567,14 @@ private PredicateSplit getUnionRewriteQueryCompensation(RewriteContext rewriteCo | |
if (mvCompensationToQuery != null) { | ||
return mvCompensationToQuery; | ||
} | ||
SessionVariable sessionVariable = optimizerContext.getSessionVariable(); | ||
int unionRewriteMode = sessionVariable.getMaterializedViewUnionRewriteMode(); | ||
if (unionRewriteMode != UNION_REWRITE_EAGER_MODE_1 && unionRewriteMode != UNION_REWRITE_EAGER_MODE_2) { | ||
return null; | ||
} | ||
|
||
logMVRewrite(mvRewriteContext, "Try to pull up query's predicates to make possible for union rewrite"); | ||
logMVRewrite(mvRewriteContext, "Try to pull up query's predicates to make possible for union rewrite, " + | ||
"unionRewriteMode:{}", unionRewriteMode); | ||
// try to pull up query's predicates to make possible for rewrite from mv to query. | ||
PredicateSplit mvPredicateSplit = rewriteContext.getMvPredicateSplit(); | ||
PredicateSplit queryPredicateSplit = rewriteContext.getQueryPredicateSplit(); | ||
|
@@ -1580,15 +1591,13 @@ private PredicateSplit getUnionRewriteQueryCompensation(RewriteContext rewriteCo | |
ColumnRefSet queryOnPredicateUsedColRefs = Optional.ofNullable(Utils.compoundAnd(queryOnPredicates)) | ||
.map(x -> x.getUsedColumns()) | ||
.orElse(new ColumnRefSet()); | ||
// use union-all rewrite eagerly if union-all rewrite can be used. | ||
QueryDebugOptions debugOptions = optimizerContext.getSessionVariable().getQueryDebugOptions(); | ||
ColumnRefSet queryOutputColumnRefs = debugOptions.isEnableMVEagerUnionAllRewrite() ? | ||
|
||
ColumnRefSet queryOutputColumnRefs = unionRewriteMode == UNION_REWRITE_EAGER_MODE_2 ? | ||
rewriteContext.getQueryExpression().getOutputColumns() : null; | ||
Set<ScalarOperator> queryExtraPredicates = queryPredicates.stream() | ||
.filter(pred -> isPullUpQueryPredicate(pred, mvPredicateUsedColRefs, | ||
queryOnPredicateUsedColRefs, queryOutputColumnRefs)) | ||
.collect(Collectors.toSet()); | ||
|
||
if (queryExtraPredicates.isEmpty()) { | ||
return null; | ||
} | ||
|
@@ -2106,20 +2115,28 @@ protected OptExpression createUnion(OptExpression queryInput, OptExpression view | |
|
||
// Add extra union all predicates above union all operator. | ||
if (rewriteContext.getUnionRewriteQueryExtraPredicate() != null) { | ||
addUnionAllExtraPredicate(result.getOp(), rewriteContext.getUnionRewriteQueryExtraPredicate()); | ||
result = addUnionAllExtraPredicate(result, rewriteContext.getUnionRewriteQueryExtraPredicate()); | ||
} | ||
|
||
deriveLogicalProperty(result); | ||
return result; | ||
} | ||
|
||
protected void addUnionAllExtraPredicate(Operator unionOp, | ||
ScalarOperator extraPredicate) { | ||
Preconditions.checkState(unionOp.getProjection() != null); | ||
ScalarOperator origPredicate = unionOp.getPredicate(); | ||
ReplaceColumnRefRewriter rewriter = new ReplaceColumnRefRewriter(unionOp.getProjection().getColumnRefMap()); | ||
ScalarOperator rewrittenExtraPredicate = rewriter.rewrite(extraPredicate); | ||
unionOp.setPredicate(Utils.compoundAnd(origPredicate, rewrittenExtraPredicate)); | ||
protected OptExpression addUnionAllExtraPredicate(OptExpression result, | ||
ScalarOperator extraPredicate) { | ||
Operator op = result.getOp(); | ||
if (op instanceof LogicalSetOperator) { | ||
LogicalFilterOperator filter = new LogicalFilterOperator(extraPredicate); | ||
// TODO: Refactor this so can use PUSH_DOWN_PREDICATE rule set after mv rewrite rule. | ||
return PushDownPredicateSetRule.doProcess(filter, result, false).get(0); | ||
} else { | ||
// If op is aggregate operator, use setPredicate directly. | ||
ScalarOperator origPredicate = op.getPredicate(); | ||
ReplaceColumnRefRewriter rewriter = new ReplaceColumnRefRewriter(op.getProjection().getColumnRefMap()); | ||
ScalarOperator rewrittenExtraPredicate = rewriter.rewrite(extraPredicate); | ||
op.setPredicate(Utils.compoundAnd(origPredicate, rewrittenExtraPredicate)); | ||
return result; | ||
} | ||
} | ||
|
||
protected EquationRewriter buildEquationRewriter( | ||
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. The most risky bug in this code is: You can modify the code like this: // Earlier in the code where unionRewriteMode is set based on session variables:
int unionRewriteMode = sessionVariable.getMaterializedViewUnionRewriteMode();
// Ensure the validation check for unionRewriteMode is correct and covers all necessary conditions,
// and use it consistently throughout your implementation. For example:
if (!(unionRewriteMode >= 0 && unionRewriteMode <= 2)) {
// Handle invalid mode appropriately
}
// When checking for `unionRewriteMode`, instead of blindly using it, introduce additional checks or logic as needed to ensure its value is correctly interpreted and applied.
// Example modification (hypothetical, depends on actual intended use of `unionRewriteMode`):
+ if (unionRewriteMode == 1 || (unionRewriteMode == 2 && someOtherCondition)) {
return null;
}
// Make sure the usage of `unionRewriteMode` further down the code respects its meaning and implements the intended logic correctly. Note: Since the provided code snippet is quite specific and targeted at a particular system's internals (seemingly related to SQL optimization and query rewriting in StarRocks), a precise fix requires deeper knowledge of the entire system and how |
||
|
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.
The provided code appears to be a part of a larger Java class focused on managing session variables, specifically for handling materialized view configurations in a database or data processing application. Without the full context, identifying a "bug" can be challenging since it often depends on how these variables and methods interact with the rest of the application. However, based on standard coding practices and the changes highlighted in the diff, there isn't an immediately obvious "risky bug" in terms of syntax or Java language rules.
Potential areas of concern that are more contextual or logical rather than syntactical might include:
materializedViewUnionRewriteMode
variable could lead to inconsistent state.materializedViewUnionRewriteMode
values - The comments describe valid ranges and their meanings, but no validation logic is present in the setter method. Setting an invalid value might lead to undefined behavior elsewhere in the application.Assuming validation of input values for the
materializedViewUnionRewriteMode
field might be beneficial to prevent potential issues, a constructive suggestion would focus on adding such validation:The most risky bug in this code is:
Lack of validation for
materializedViewUnionRewriteMode
values which may lead to unintended application behavior if invalid values are set.You can modify the code like this:
This change introduces a basic check to ensure that only valid values as described in the comments are accepted, helping to avoid potential misconfigurations or logical errors in handling the union rewrite modes.