对原始的sql文本做一定程度的改写使得SQL更简单,执行效率更高;一般是条件表达式改写、子查询改写等。
在Doris中,有一个接口 ExprRewriteRule 负责表达式的改写规则,基于该接口与各种不同的规则有不同的实现,在 Analyzer类的内部类 GlobalState 构造函数中,注册了诸多的规则到rules集合中,而该list会被传递到ExprRewriter类中被应用。
StmtRewriter 类处理子查询改写逻辑,其中的方法会处理各种场景下的子查询改写,比如rewriteSelectStatement方法.
这一步骤的处理是基于词法语法解析后生成的AST树进行的。
[code]public class GlobalState(Env env, ConnectContext context) { this.env = env; this.context = context; List rules = Lists.newArrayList(); // BetweenPredicates must be rewritten to be executable. Other non-essential // expr rewrites can be disabled via a query option. When rewrites are enabled // BetweenPredicates should be rewritten first to help trigger other rules. rules.add(BetweenToCompoundRule.INSTANCE); // Binary predicates must be rewritten to a canonical form for both predicate // pushdown and Parquet row group pruning based on min/max statistics. rules.add(NormalizeBinaryPredicatesRule.INSTANCE); // Put it after NormalizeBinaryPredicatesRule, make sure slotRef is on the left and Literal is on the right. rules.add(RewriteBinaryPredicatesRule.INSTANCE); rules.add(RewriteImplicitCastRule.INSTANCE); rules.add(RoundLiteralInBinaryPredicatesRule.INSTANCE); rules.add(FoldConstantsRule.INSTANCE); rules.add(EraseRedundantCastExpr.INSTANCE); rules.add(RewriteFromUnixTimeRule.INSTANCE); rules.add(CompoundPredicateWriteRule.INSTANCE); rules.add(RewriteDateLiteralRule.INSTANCE); rules.add(RewriteEncryptKeyRule.INSTANCE); rules.add(RewriteInPredicateRule.INSTANCE); rules.add(RewriteAliasFunctionRule.INSTANCE); rules.add(RewriteIsNullIsNotNullRule.INSTANCE); rules.add(MatchPredicateRule.INSTANCE); rules.add(EliminateUnnecessaryFunctions.INSTANCE); List onceRules = Lists.newArrayList(); onceRules.add(ExtractCommonFactorsRule.INSTANCE); onceRules.add(InferFiltersRule.INSTANCE); exprRewriter = new ExprRewriter(rules, onceRules); // init mv rewriter List mvRewriteRules = Lists.newArrayList(); mvRewriteRules.add(new ExprToSlotRefRule()); mvRewriteRules.add(ToBitmapToSlotRefRule.INSTANCE); mvRewriteRules.add(CountDistinctToBitmapOrHLLRule.INSTANCE); mvRewriteRules.add(CountDistinctToBitmap.INSTANCE); mvRewriteRules.add(NDVToHll.INSTANCE); mvRewriteRules.add(HLLHashToSlotRefRule.INSTANCE); mvExprRewriter = new ExprRewriter(mvRewriteRules); // context maybe null. eg, for StreamLoadPlanner. // and autoBroadcastJoinThreshold is only used for Query's DistributedPlanner. // so it is ok to not set autoBroadcastJoinThreshold if context is null if (context != null) { // compute max exec mem could be used for broadcast join long perNodeMemLimit = context.getSessionVariable().getMaxExecMemByte(); double autoBroadcastJoinThresholdPercentage = context.getSessionVariable().autoBroadcastJoinThreshold; if (autoBroadcastJoinThresholdPercentage > 1) { autoBroadcastJoinThresholdPercentage = 1.0; } else if (autoBroadcastJoinThresholdPercentage