Search in sources :

Example 11 with SqlOperator

use of org.apache.calcite.sql.SqlOperator in project drill by apache.

the class DrillOperatorTable method populateWrappedCalciteOperators.

private void populateWrappedCalciteOperators() {
    for (SqlOperator calciteOperator : inner.getOperatorList()) {
        final SqlOperator wrapper;
        if (calciteOperator instanceof SqlAggFunction) {
            wrapper = new DrillCalciteSqlAggFunctionWrapper((SqlAggFunction) calciteOperator, getFunctionListWithInference(calciteOperator.getName()));
        } else if (calciteOperator instanceof SqlFunction) {
            wrapper = new DrillCalciteSqlFunctionWrapper((SqlFunction) calciteOperator, getFunctionListWithInference(calciteOperator.getName()));
        } else {
            final String drillOpName = FunctionCallFactory.replaceOpWithFuncName(calciteOperator.getName());
            final List<DrillFuncHolder> drillFuncHolders = getFunctionListWithInference(drillOpName);
            if (drillFuncHolders.isEmpty() || calciteOperator == SqlStdOperatorTable.UNARY_MINUS || calciteOperator == SqlStdOperatorTable.UNARY_PLUS) {
                continue;
            }
            wrapper = new DrillCalciteSqlOperatorWrapper(calciteOperator, drillOpName, drillFuncHolders);
        }
        calciteToWrapper.put(calciteOperator, wrapper);
    }
}
Also used : SqlOperator(org.apache.calcite.sql.SqlOperator) List(java.util.List) SqlAggFunction(org.apache.calcite.sql.SqlAggFunction) SqlFunction(org.apache.calcite.sql.SqlFunction)

Example 12 with SqlOperator

use of org.apache.calcite.sql.SqlOperator in project drill by apache.

the class DrillConvertletTable method get.

/*
   * Lookup the hash table to see if we have a custom convertlet for a given
   * operator, if we don't use StandardConvertletTable.
   */
@Override
public SqlRexConvertlet get(SqlCall call) {
    SqlRexConvertlet convertlet;
    if (call.getOperator() instanceof DrillCalciteSqlWrapper) {
        final SqlOperator wrapper = call.getOperator();
        final SqlOperator wrapped = DrillCalciteWrapperUtility.extractSqlOperatorFromWrapper(call.getOperator());
        if ((convertlet = map.get(wrapped)) != null) {
            return convertlet;
        }
        ((SqlBasicCall) call).setOperator(wrapped);
        SqlRexConvertlet sqlRexConvertlet = StandardConvertletTable.INSTANCE.get(call);
        ((SqlBasicCall) call).setOperator(wrapper);
        return sqlRexConvertlet;
    }
    if ((convertlet = map.get(call.getOperator())) != null) {
        return convertlet;
    }
    return StandardConvertletTable.INSTANCE.get(call);
}
Also used : SqlBasicCall(org.apache.calcite.sql.SqlBasicCall) SqlOperator(org.apache.calcite.sql.SqlOperator) SqlRexConvertlet(org.apache.calcite.sql2rel.SqlRexConvertlet)

Example 13 with SqlOperator

use of org.apache.calcite.sql.SqlOperator in project hive by apache.

the class HiveRelDecorrelator method decorrelateRel.

/**
 * Rewrite Correlator into a left outer join.
 *
 * @param rel Correlator
 */
public Frame decorrelateRel(LogicalCorrelate rel) {
    // 
    // Rewrite logic:
    // 
    // The original left input will be joined with the new right input that
    // has generated correlated variables propagated up. For any generated
    // cor vars that are not used in the join key, pass them along to be
    // joined later with the CorrelatorRels that produce them.
    // 
    // the right input to Correlator should produce correlated variables
    final RelNode oldLeft = rel.getInput(0);
    final RelNode oldRight = rel.getInput(1);
    boolean mightRequireValueGen = new findIfValueGenRequired().traverse(oldRight);
    valueGen.push(mightRequireValueGen);
    final Frame leftFrame = getInvoke(oldLeft, rel);
    final Frame rightFrame = getInvoke(oldRight, rel);
    if (leftFrame == null || rightFrame == null) {
        // If any input has not been rewritten, do not rewrite this rel.
        return null;
    }
    if (rightFrame.corDefOutputs.isEmpty()) {
        return null;
    }
    assert rel.getRequiredColumns().cardinality() <= rightFrame.corDefOutputs.keySet().size();
    // Change correlator rel into a join.
    // Join all the correlated variables produced by this correlator rel
    // with the values generated and propagated from the right input
    final SortedMap<CorDef, Integer> corDefOutputs = new TreeMap<>(rightFrame.corDefOutputs);
    final List<RexNode> conditions = new ArrayList<>();
    final List<RelDataTypeField> newLeftOutput = leftFrame.r.getRowType().getFieldList();
    int newLeftFieldCount = newLeftOutput.size();
    final List<RelDataTypeField> newRightOutput = rightFrame.r.getRowType().getFieldList();
    for (Map.Entry<CorDef, Integer> rightOutput : new ArrayList<>(corDefOutputs.entrySet())) {
        final CorDef corDef = rightOutput.getKey();
        if (!corDef.corr.equals(rel.getCorrelationId())) {
            continue;
        }
        final int newLeftPos = leftFrame.oldToNewOutputs.get(corDef.field);
        final int newRightPos = rightOutput.getValue();
        SqlOperator callOp = corDef.getPredicateKind() == null ? SqlStdOperatorTable.EQUALS : corDef.getPredicateKind();
        if (corDef.isLeft) {
            conditions.add(rexBuilder.makeCall(callOp, RexInputRef.of(newLeftPos, newLeftOutput), new RexInputRef(newLeftFieldCount + newRightPos, newRightOutput.get(newRightPos).getType())));
        } else {
            conditions.add(rexBuilder.makeCall(callOp, new RexInputRef(newLeftFieldCount + newRightPos, newRightOutput.get(newRightPos).getType()), RexInputRef.of(newLeftPos, newLeftOutput)));
        }
        // remove this cor var from output position mapping
        corDefOutputs.remove(corDef);
    }
    // vars that are not used in the join key.
    for (CorDef corDef : corDefOutputs.keySet()) {
        int newPos = corDefOutputs.get(corDef) + newLeftFieldCount;
        corDefOutputs.put(corDef, newPos);
    }
    // then add any cor var from the left input. Do not need to change
    // output positions.
    corDefOutputs.putAll(leftFrame.corDefOutputs);
    // Create the mapping between the output of the old correlation rel
    // and the new join rel
    final Map<Integer, Integer> mapOldToNewOutputs = new HashMap<>();
    int oldLeftFieldCount = oldLeft.getRowType().getFieldCount();
    int oldRightFieldCount = oldRight.getRowType().getFieldCount();
    // Left input positions are not changed.
    mapOldToNewOutputs.putAll(leftFrame.oldToNewOutputs);
    final RexNode condition = RexUtil.composeConjunction(rexBuilder, conditions, false);
    RelNode newJoin = null;
    // this indicates original query was either correlated EXISTS or IN
    if (rel.getJoinType() == SemiJoinType.SEMI) {
        final List<Integer> leftKeys = new ArrayList<Integer>();
        final List<Integer> rightKeys = new ArrayList<Integer>();
        RelNode[] inputRels = new RelNode[] { leftFrame.r, rightFrame.r };
        newJoin = HiveSemiJoin.getSemiJoin(rel.getCluster(), rel.getCluster().traitSetOf(HiveRelNode.CONVENTION), leftFrame.r, rightFrame.r, condition, ImmutableIntList.copyOf(leftKeys), ImmutableIntList.copyOf(rightKeys));
    } else {
        // Right input positions are shifted by newLeftFieldCount.
        for (int i = 0; i < oldRightFieldCount; i++) {
            mapOldToNewOutputs.put(i + oldLeftFieldCount, rightFrame.oldToNewOutputs.get(i) + newLeftFieldCount);
        }
        newJoin = LogicalJoin.create(leftFrame.r, rightFrame.r, condition, ImmutableSet.<CorrelationId>of(), rel.getJoinType().toJoinType());
    }
    valueGen.pop();
    return register(rel, newJoin, mapOldToNewOutputs, corDefOutputs);
}
Also used : HashMap(java.util.HashMap) SqlOperator(org.apache.calcite.sql.SqlOperator) ArrayList(java.util.ArrayList) TreeMap(java.util.TreeMap) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) HiveRelNode(org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveRelNode) RelNode(org.apache.calcite.rel.RelNode) RexInputRef(org.apache.calcite.rex.RexInputRef) CorrelationId(org.apache.calcite.rel.core.CorrelationId) Map(java.util.Map) ImmutableSortedMap(com.google.common.collect.ImmutableSortedMap) TreeMap(java.util.TreeMap) ImmutableMap(com.google.common.collect.ImmutableMap) NavigableMap(java.util.NavigableMap) SortedMap(java.util.SortedMap) HashMap(java.util.HashMap) RexNode(org.apache.calcite.rex.RexNode)

Example 14 with SqlOperator

use of org.apache.calcite.sql.SqlOperator in project hive by apache.

the class HiveRelDecorrelator method decorrelateInputWithValueGenerator.

private Frame decorrelateInputWithValueGenerator(RelNode rel) {
    // currently only handles one input input
    assert rel.getInputs().size() == 1;
    RelNode oldInput = rel.getInput(0);
    final Frame frame = map.get(oldInput);
    final SortedMap<CorDef, Integer> corDefOutputs = new TreeMap<>(frame.corDefOutputs);
    final Collection<CorRef> corVarList = cm.mapRefRelToCorRef.get(rel);
    // This means that we do not need a value generator.
    if (rel instanceof Filter) {
        SortedMap<CorDef, Integer> coreMap = new TreeMap<>();
        for (CorRef correlation : corVarList) {
            final CorDef def = correlation.def();
            if (corDefOutputs.containsKey(def) || coreMap.containsKey(def)) {
                continue;
            }
            try {
                findCorrelationEquivalent(correlation, ((Filter) rel).getCondition());
            } catch (Util.FoundOne e) {
                // we need to keep predicate kind e.g. EQUAL or NOT EQUAL
                // so that later while decorrelating LogicalCorrelate appropriate join predicate
                // is generated
                def.setPredicateKind((SqlOperator) ((Pair) ((Pair) e.getNode()).getValue()).getKey());
                def.setIsLeft((boolean) ((Pair) ((Pair) e.getNode()).getValue()).getValue());
                coreMap.put(def, (Integer) ((Pair) e.getNode()).getKey());
            }
        }
        // generator.
        if (coreMap.size() == corVarList.size()) {
            coreMap.putAll(frame.corDefOutputs);
            return register(oldInput, frame.r, frame.oldToNewOutputs, coreMap);
        }
    }
    int leftInputOutputCount = frame.r.getRowType().getFieldCount();
    // can directly add positions into corDefOutputs since join
    // does not change the output ordering from the inputs.
    RelNode valueGenRel = createValueGenerator(corVarList, leftInputOutputCount, corDefOutputs);
    RelNode join = LogicalJoin.create(frame.r, valueGenRel, rexBuilder.makeLiteral(true), ImmutableSet.<CorrelationId>of(), JoinRelType.INNER);
    // LogicalFilter) are in the output and in the same position.
    return register(oldInput, join, frame.oldToNewOutputs, corDefOutputs);
}
Also used : SqlOperator(org.apache.calcite.sql.SqlOperator) SqlValidatorUtil(org.apache.calcite.sql.validate.SqlValidatorUtil) RelMdUtil(org.apache.calcite.rel.metadata.RelMdUtil) RexUtil(org.apache.calcite.rex.RexUtil) RelOptUtil(org.apache.calcite.plan.RelOptUtil) ReflectUtil(org.apache.calcite.util.ReflectUtil) Util(org.apache.calcite.util.Util) TreeMap(java.util.TreeMap) HiveRelNode(org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveRelNode) RelNode(org.apache.calcite.rel.RelNode) HiveFilter(org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveFilter) Filter(org.apache.calcite.rel.core.Filter) LogicalFilter(org.apache.calcite.rel.logical.LogicalFilter) Pair(org.apache.calcite.util.Pair)

Example 15 with SqlOperator

use of org.apache.calcite.sql.SqlOperator in project hive by apache.

the class RexNodeConverter method convert.

private RexNode convert(ExprNodeGenericFuncDesc func) throws SemanticException {
    ExprNodeDesc tmpExprNode;
    RexNode tmpRN;
    List<RexNode> childRexNodeLst = new ArrayList<RexNode>();
    Builder<RelDataType> argTypeBldr = ImmutableList.<RelDataType>builder();
    // TODO: 1) Expand to other functions as needed 2) What about types other than primitive.
    TypeInfo tgtDT = null;
    GenericUDF tgtUdf = func.getGenericUDF();
    boolean isNumeric = (tgtUdf instanceof GenericUDFBaseBinary && func.getTypeInfo().getCategory() == Category.PRIMITIVE && (PrimitiveGrouping.NUMERIC_GROUP == PrimitiveObjectInspectorUtils.getPrimitiveGrouping(((PrimitiveTypeInfo) func.getTypeInfo()).getPrimitiveCategory())));
    boolean isCompare = !isNumeric && tgtUdf instanceof GenericUDFBaseCompare;
    boolean isWhenCase = tgtUdf instanceof GenericUDFWhen || tgtUdf instanceof GenericUDFCase;
    boolean isTransformableTimeStamp = func.getGenericUDF() instanceof GenericUDFUnixTimeStamp && func.getChildren().size() != 0;
    boolean isBetween = !isNumeric && tgtUdf instanceof GenericUDFBetween;
    boolean isIN = !isNumeric && tgtUdf instanceof GenericUDFIn;
    boolean isAllPrimitive = true;
    if (isNumeric) {
        tgtDT = func.getTypeInfo();
        assert func.getChildren().size() == 2;
    // TODO: checking 2 children is useless, compare already does that.
    } else if (isCompare && (func.getChildren().size() == 2)) {
        tgtDT = FunctionRegistry.getCommonClassForComparison(func.getChildren().get(0).getTypeInfo(), func.getChildren().get(1).getTypeInfo());
    } else if (isWhenCase) {
        // as they are not allowed
        if (checkForStatefulFunctions(func.getChildren())) {
            throw new SemanticException("Stateful expressions cannot be used inside of CASE");
        }
    } else if (isTransformableTimeStamp) {
        // unix_timestamp(args) -> to_unix_timestamp(args)
        func = ExprNodeGenericFuncDesc.newInstance(new GenericUDFToUnixTimeStamp(), func.getChildren());
    } else if (isBetween) {
        assert func.getChildren().size() == 4;
        // We skip first child as is not involved (is the revert boolean)
        // The target type needs to account for all 3 operands
        tgtDT = FunctionRegistry.getCommonClassForComparison(func.getChildren().get(1).getTypeInfo(), FunctionRegistry.getCommonClassForComparison(func.getChildren().get(2).getTypeInfo(), func.getChildren().get(3).getTypeInfo()));
    } else if (isIN) {
        // We're only considering the first element of the IN list for the type
        assert func.getChildren().size() > 1;
        tgtDT = FunctionRegistry.getCommonClassForComparison(func.getChildren().get(0).getTypeInfo(), func.getChildren().get(1).getTypeInfo());
    }
    for (int i = 0; i < func.getChildren().size(); ++i) {
        ExprNodeDesc childExpr = func.getChildren().get(i);
        tmpExprNode = childExpr;
        if (tgtDT != null && TypeInfoUtils.isConversionRequiredForComparison(tgtDT, childExpr.getTypeInfo())) {
            if (isCompare || isBetween || isIN) {
                // For BETWEEN skip the first child (the revert boolean)
                if (!isBetween || i > 0) {
                    tmpExprNode = ParseUtils.createConversionCast(childExpr, (PrimitiveTypeInfo) tgtDT);
                }
            } else if (isNumeric) {
                // For numeric, we'll do minimum necessary cast - if we cast to the type
                // of expression, bad things will happen.
                PrimitiveTypeInfo minArgType = ExprNodeDescUtils.deriveMinArgumentCast(childExpr, tgtDT);
                tmpExprNode = ParseUtils.createConversionCast(childExpr, minArgType);
            } else {
                throw new AssertionError("Unexpected " + tgtDT + " - not a numeric op or compare");
            }
        }
        isAllPrimitive = isAllPrimitive && tmpExprNode.getTypeInfo().getCategory() == Category.PRIMITIVE;
        argTypeBldr.add(TypeConverter.convert(tmpExprNode.getTypeInfo(), cluster.getTypeFactory()));
        tmpRN = convert(tmpExprNode);
        childRexNodeLst.add(tmpRN);
    }
    // See if this is an explicit cast.
    RexNode expr = null;
    RelDataType retType = null;
    expr = handleExplicitCast(func, childRexNodeLst);
    if (expr == null) {
        // This is not a cast; process the function.
        retType = TypeConverter.convert(func.getTypeInfo(), cluster.getTypeFactory());
        SqlOperator calciteOp = SqlFunctionConverter.getCalciteOperator(func.getFuncText(), func.getGenericUDF(), argTypeBldr.build(), retType);
        if (calciteOp.getKind() == SqlKind.CASE) {
            // If it is a case operator, we need to rewrite it
            childRexNodeLst = rewriteCaseChildren(func, childRexNodeLst);
        } else if (HiveExtractDate.ALL_FUNCTIONS.contains(calciteOp)) {
            // If it is a extract operator, we need to rewrite it
            childRexNodeLst = rewriteExtractDateChildren(calciteOp, childRexNodeLst);
        } else if (HiveFloorDate.ALL_FUNCTIONS.contains(calciteOp)) {
            // If it is a floor <date> operator, we need to rewrite it
            childRexNodeLst = rewriteFloorDateChildren(calciteOp, childRexNodeLst);
        } else if (calciteOp.getKind() == SqlKind.IN && childRexNodeLst.size() == 2 && isAllPrimitive) {
            // if it is a single item in an IN clause, transform A IN (B) to A = B
            // from IN [A,B] => EQUALS [A,B]
            // except complex types
            calciteOp = SqlFunctionConverter.getCalciteOperator("=", FunctionRegistry.getFunctionInfo("=").getGenericUDF(), argTypeBldr.build(), retType);
        }
        expr = cluster.getRexBuilder().makeCall(retType, calciteOp, childRexNodeLst);
    } else {
        retType = expr.getType();
    }
    // an exception
    if (flattenExpr && (expr instanceof RexCall) && !(((RexCall) expr).getOperator() instanceof SqlCastFunction)) {
        RexCall call = (RexCall) expr;
        expr = cluster.getRexBuilder().makeCall(retType, call.getOperator(), RexUtil.flatten(call.getOperands(), call.getOperator()));
    }
    return expr;
}
Also used : GenericUDFBetween(org.apache.hadoop.hive.ql.udf.generic.GenericUDFBetween) GenericUDFCase(org.apache.hadoop.hive.ql.udf.generic.GenericUDFCase) SqlCastFunction(org.apache.calcite.sql.fun.SqlCastFunction) SqlOperator(org.apache.calcite.sql.SqlOperator) GenericUDFBaseBinary(org.apache.hadoop.hive.ql.udf.generic.GenericUDFBaseBinary) GenericUDFWhen(org.apache.hadoop.hive.ql.udf.generic.GenericUDFWhen) ArrayList(java.util.ArrayList) GenericUDFToUnixTimeStamp(org.apache.hadoop.hive.ql.udf.generic.GenericUDFToUnixTimeStamp) RelDataType(org.apache.calcite.rel.type.RelDataType) GenericUDFUnixTimeStamp(org.apache.hadoop.hive.ql.udf.generic.GenericUDFUnixTimeStamp) PrimitiveTypeInfo(org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo) TypeInfo(org.apache.hadoop.hive.serde2.typeinfo.TypeInfo) PrimitiveTypeInfo(org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo) RexCall(org.apache.calcite.rex.RexCall) GenericUDF(org.apache.hadoop.hive.ql.udf.generic.GenericUDF) GenericUDFBaseCompare(org.apache.hadoop.hive.ql.udf.generic.GenericUDFBaseCompare) GenericUDFIn(org.apache.hadoop.hive.ql.udf.generic.GenericUDFIn) ExprNodeDesc(org.apache.hadoop.hive.ql.plan.ExprNodeDesc) RexNode(org.apache.calcite.rex.RexNode) SemanticException(org.apache.hadoop.hive.ql.parse.SemanticException) CalciteSubquerySemanticException(org.apache.hadoop.hive.ql.optimizer.calcite.CalciteSubquerySemanticException) CalciteSemanticException(org.apache.hadoop.hive.ql.optimizer.calcite.CalciteSemanticException)

Aggregations

SqlOperator (org.apache.calcite.sql.SqlOperator)17 ArrayList (java.util.ArrayList)7 RexNode (org.apache.calcite.rex.RexNode)7 RelDataType (org.apache.calcite.rel.type.RelDataType)5 RelNode (org.apache.calcite.rel.RelNode)3 SqlFunction (org.apache.calcite.sql.SqlFunction)3 SqlKind (org.apache.calcite.sql.SqlKind)3 TreeMap (java.util.TreeMap)2 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)2 RexBuilder (org.apache.calcite.rex.RexBuilder)2 RexCall (org.apache.calcite.rex.RexCall)2 RexInputRef (org.apache.calcite.rex.RexInputRef)2 RexLiteral (org.apache.calcite.rex.RexLiteral)2 DrillSqlOperator (org.apache.drill.exec.planner.sql.DrillSqlOperator)2 CalciteSemanticException (org.apache.hadoop.hive.ql.optimizer.calcite.CalciteSemanticException)2 HiveRelNode (org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveRelNode)2 Function (com.google.common.base.Function)1 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 ImmutableSortedMap (com.google.common.collect.ImmutableSortedMap)1