diff --git a/ql/src/java/org/apache/hadoop/hive/ql/lib/CostLessRuleDispatcher.java b/ql/src/java/org/apache/hadoop/hive/ql/lib/CostLessRuleDispatcher.java new file mode 100644 index 0000000000..364140ac02 --- /dev/null +++ b/ql/src/java/org/apache/hadoop/hive/ql/lib/CostLessRuleDispatcher.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.hive.ql.lib; + +import java.util.Map; +import java.util.Stack; + +import com.google.common.collect.*; +import org.apache.hadoop.hive.ql.parse.SemanticException; +import org.apache.hadoop.hive.ql.parse.ASTNode; + +/** + * Dispatches calls to relevant method in processor. The user registers various + * rules with the dispatcher, and the processor corresponding to closest + * matching rule is fired. + */ +public class CostLessRuleDispatcher implements Dispatcher { + + private final SetMultimap procRules; + private final NodeProcessorCtx procCtx; + private final NodeProcessor defaultProc; + + /** + * Constructor. + * + * @param defaultProc default processor to be fired if no rule matches + * @param rules operator processor that handles actual processing of the node + * @param procCtx operator processor context, which is opaque to the dispatcher + */ + public CostLessRuleDispatcher(NodeProcessor defaultProc, SetMultimap rules, + NodeProcessorCtx procCtx) { + this.defaultProc = defaultProc; + procRules = rules; + this.procCtx = procCtx; + } + + /** + * Dispatcher function. + * + * @param nd operator to process + * @param ndStack the operators encountered so far + * @throws SemanticException + */ + @Override public Object dispatch(Node nd, Stack ndStack, Object... nodeOutputs) + throws SemanticException { + + int nodeType = ((ASTNode) nd).getType(); + NodeProcessor processor = this.defaultProc; + if (this.procRules.containsKey(nodeType)) { + processor = this.procRules.get(((ASTNode) nd).getType()).iterator().next(); + } + return processor.process(nd, ndStack, procCtx, nodeOutputs); + } +} + diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java index e45276f202..215842b2db 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/TypeCheckProcFactory.java @@ -28,6 +28,8 @@ import java.util.Map; import java.util.Stack; +import com.google.common.collect.*; +import org.apache.calcite.plan.*; import org.apache.calcite.rel.RelNode; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.math.NumberUtils; @@ -47,15 +49,7 @@ import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException; -import org.apache.hadoop.hive.ql.lib.DefaultRuleDispatcher; -import org.apache.hadoop.hive.ql.lib.Dispatcher; -import org.apache.hadoop.hive.ql.lib.SubqueryExpressionWalker; -import org.apache.hadoop.hive.ql.lib.GraphWalker; -import org.apache.hadoop.hive.ql.lib.Node; -import org.apache.hadoop.hive.ql.lib.NodeProcessor; -import org.apache.hadoop.hive.ql.lib.NodeProcessorCtx; -import org.apache.hadoop.hive.ql.lib.Rule; -import org.apache.hadoop.hive.ql.lib.RuleRegExp; +import org.apache.hadoop.hive.ql.lib.*; import org.apache.hadoop.hive.ql.metadata.Hive; import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.ql.optimizer.ConstantPropagateProcFactory; @@ -108,8 +102,7 @@ import org.slf4j.LoggerFactory; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; - +import com.google.common.collect.HashMultimap; /** * The Factory for creating typecheck processors. The typecheck processors are @@ -196,46 +189,52 @@ public static ExprNodeDesc processGByExpr(Node nd, Object procCtx) // create a walker which walks the tree in a DFS manner while maintaining // the operator stack. The dispatcher // generates the plan from the operator tree - Map opRules = new LinkedHashMap(); - - opRules.put(new RuleRegExp("R1", HiveParser.TOK_NULL + "%"), - tf.getNullExprProcessor()); - opRules.put(new RuleRegExp("R2", HiveParser.Number + "%|" + - HiveParser.IntegralLiteral + "%|" + - HiveParser.NumberLiteral + "%"), - tf.getNumExprProcessor()); - opRules - .put(new RuleRegExp("R3", HiveParser.Identifier + "%|" - + HiveParser.StringLiteral + "%|" + HiveParser.TOK_CHARSETLITERAL + "%|" - + HiveParser.TOK_STRINGLITERALSEQUENCE + "%|" - + "%|" + HiveParser.KW_IF + "%|" + HiveParser.KW_CASE + "%|" - + HiveParser.KW_WHEN + "%|" + HiveParser.KW_IN + "%|" - + HiveParser.KW_ARRAY + "%|" + HiveParser.KW_MAP + "%|" - + HiveParser.KW_STRUCT + "%|" + HiveParser.KW_EXISTS + "%|" - + HiveParser.TOK_SUBQUERY_OP_NOTIN + "%"), - tf.getStrExprProcessor()); - opRules.put(new RuleRegExp("R4", HiveParser.KW_TRUE + "%|" - + HiveParser.KW_FALSE + "%"), tf.getBoolExprProcessor()); - opRules.put(new RuleRegExp("R5", HiveParser.TOK_DATELITERAL + "%|" - + HiveParser.TOK_TIMESTAMPLITERAL + "%|" - + HiveParser.TOK_TIMESTAMPLOCALTZLITERAL + "%"), tf.getDateTimeExprProcessor()); - opRules.put(new RuleRegExp("R6", HiveParser.TOK_INTERVAL_YEAR_MONTH_LITERAL + "%|" - + HiveParser.TOK_INTERVAL_DAY_TIME_LITERAL + "%|" - + HiveParser.TOK_INTERVAL_YEAR_LITERAL + "%|" - + HiveParser.TOK_INTERVAL_MONTH_LITERAL + "%|" - + HiveParser.TOK_INTERVAL_DAY_LITERAL + "%|" - + HiveParser.TOK_INTERVAL_HOUR_LITERAL + "%|" - + HiveParser.TOK_INTERVAL_MINUTE_LITERAL + "%|" - + HiveParser.TOK_INTERVAL_SECOND_LITERAL + "%"), tf.getIntervalExprProcessor()); - opRules.put(new RuleRegExp("R7", HiveParser.TOK_TABLE_OR_COL + "%"), - tf.getColumnExprProcessor()); - opRules.put(new RuleRegExp("R8", HiveParser.TOK_SUBQUERY_EXPR + "%"), - tf.getSubQueryExprProcessor()); + + SetMultimap astNodeToProcessor = HashMultimap.create(); + astNodeToProcessor.put(HiveParser.TOK_NULL, tf.getNullExprProcessor()); + + astNodeToProcessor.put(HiveParser.Number, tf.getNumExprProcessor()); + astNodeToProcessor.put(HiveParser.IntegralLiteral, tf.getNumExprProcessor()); + astNodeToProcessor.put(HiveParser.NumberLiteral, tf.getNumExprProcessor()); + + astNodeToProcessor.put(HiveParser.Identifier, tf.getStrExprProcessor()); + astNodeToProcessor.put(HiveParser.StringLiteral, tf.getStrExprProcessor()); + astNodeToProcessor.put(HiveParser.TOK_CHARSETLITERAL, tf.getStrExprProcessor()); + astNodeToProcessor.put(HiveParser.TOK_STRINGLITERALSEQUENCE, tf.getStrExprProcessor()); + astNodeToProcessor.put(HiveParser.KW_IF, tf.getStrExprProcessor()); + astNodeToProcessor.put(HiveParser.KW_CASE, tf.getStrExprProcessor()); + astNodeToProcessor.put(HiveParser.KW_WHEN, tf.getStrExprProcessor()); + astNodeToProcessor.put(HiveParser.KW_IN, tf.getStrExprProcessor()); + astNodeToProcessor.put(HiveParser.KW_ARRAY, tf.getStrExprProcessor()); + astNodeToProcessor.put(HiveParser.KW_MAP, tf.getStrExprProcessor()); + astNodeToProcessor.put(HiveParser.KW_STRUCT, tf.getStrExprProcessor()); + astNodeToProcessor.put(HiveParser.KW_EXISTS, tf.getStrExprProcessor()); + astNodeToProcessor.put(HiveParser.TOK_SUBQUERY_OP_NOTIN, tf.getStrExprProcessor()); + + astNodeToProcessor.put(HiveParser.KW_TRUE, tf.getBoolExprProcessor()); + astNodeToProcessor.put(HiveParser.KW_FALSE, tf.getBoolExprProcessor()); + + astNodeToProcessor.put(HiveParser.TOK_DATELITERAL, tf.getDateTimeExprProcessor()); + astNodeToProcessor.put(HiveParser.TOK_TIMESTAMPLITERAL, tf.getDateTimeExprProcessor()); + astNodeToProcessor.put(HiveParser.TOK_TIMESTAMPLOCALTZLITERAL, tf.getDateTimeExprProcessor()); + + astNodeToProcessor.put(HiveParser.TOK_INTERVAL_YEAR_MONTH_LITERAL, tf.getIntervalExprProcessor()); + astNodeToProcessor.put(HiveParser.TOK_INTERVAL_DAY_TIME_LITERAL, tf.getIntervalExprProcessor()); + astNodeToProcessor.put(HiveParser.TOK_INTERVAL_YEAR_LITERAL, tf.getIntervalExprProcessor()); + astNodeToProcessor.put(HiveParser.TOK_INTERVAL_MONTH_LITERAL, tf.getIntervalExprProcessor()); + astNodeToProcessor.put(HiveParser.TOK_INTERVAL_DAY_LITERAL, tf.getIntervalExprProcessor()); + astNodeToProcessor.put(HiveParser.TOK_INTERVAL_HOUR_LITERAL, tf.getIntervalExprProcessor()); + astNodeToProcessor.put(HiveParser.TOK_INTERVAL_MINUTE_LITERAL, tf.getIntervalExprProcessor()); + astNodeToProcessor.put(HiveParser.TOK_INTERVAL_SECOND_LITERAL, tf.getIntervalExprProcessor()); + + astNodeToProcessor.put(HiveParser.TOK_TABLE_OR_COL, tf.getColumnExprProcessor()); + + astNodeToProcessor.put(HiveParser.TOK_SUBQUERY_EXPR, tf.getSubQueryExprProcessor()); // The dispatcher fires the processor corresponding to the closest matching // rule and passes the context along - Dispatcher disp = new DefaultRuleDispatcher(tf.getDefaultExprProcessor(), - opRules, tcCtx); + Dispatcher disp = new CostLessRuleDispatcher(tf.getDefaultExprProcessor(), + astNodeToProcessor, tcCtx); GraphWalker ogw = new SubqueryExpressionWalker(disp); // Create a list of top nodes