Search in sources :

Example 46 with RexLiteral

use of org.apache.calcite.rex.RexLiteral in project drill by apache.

the class MongoPluginImplementor method implement.

@Override
public void implement(PluginSortRel sort) throws IOException {
    runAggregate = true;
    visitChild(sort.getInput());
    if (!sort.collation.getFieldCollations().isEmpty()) {
        BsonDocument sortKeys = new BsonDocument();
        List<RelDataTypeField> fields = sort.getRowType().getFieldList();
        for (RelFieldCollation fieldCollation : sort.collation.getFieldCollations()) {
            String name = fields.get(fieldCollation.getFieldIndex()).getName();
            sortKeys.put(name, new BsonInt32(direction(fieldCollation)));
        }
        operations.add(Aggregates.sort(sortKeys).toBsonDocument());
    }
    if (sort.offset != null) {
        operations.add(Aggregates.skip(rexLiteralIntValue((RexLiteral) sort.offset)).toBsonDocument());
    }
    if (sort.fetch != null) {
        operations.add(Aggregates.limit(rexLiteralIntValue((RexLiteral) sort.fetch)).toBsonDocument());
    }
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) BsonInt32(org.bson.BsonInt32) BsonDocument(org.bson.BsonDocument) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) BsonString(org.bson.BsonString)

Example 47 with RexLiteral

use of org.apache.calcite.rex.RexLiteral in project drill by apache.

the class RexToMongoTranslator method visitCall.

@Override
public BsonValue visitCall(RexCall call) {
    String name = isItem(call);
    if (name != null) {
        return new BsonString("'$" + name + "'");
    }
    List<BsonValue> strings = call.operands.stream().map(operand -> operand.accept(this)).collect(Collectors.toList());
    if (call.getKind() == SqlKind.CAST) {
        return strings.get(0);
    }
    String stdOperator = MONGO_OPERATORS.get(call.getOperator());
    if (stdOperator != null) {
        return new BsonDocument(stdOperator, new BsonArray(strings));
    }
    if (call.getOperator() == SqlStdOperatorTable.ITEM) {
        RexNode op1 = call.operands.get(1);
        if (op1 instanceof RexLiteral) {
            if (op1.getType().getSqlTypeName() == SqlTypeName.INTEGER) {
                return new BsonDocument("$arrayElemAt", new BsonArray(Arrays.asList(strings.get(0), new BsonInt32(((RexLiteral) op1).getValueAs(Integer.class)))));
            } else if (op1.getType().getSqlTypeName() == SqlTypeName.CHAR) {
                return new BsonString(strings.get(0).asString().getValue() + "." + ((RexLiteral) op1).getValueAs(String.class));
            }
        }
    }
    if (call.getOperator() == SqlStdOperatorTable.CASE) {
        // case(a, b, c)  -> $cond:[a, b, c]
        // case(a, b, c, d) -> $cond:[a, b, $cond:[c, d, null]]
        // case(a, b, c, d, e) -> $cond:[a, b, $cond:[c, d, e]]
        BsonDocument result = new BsonDocument();
        BsonArray args = new BsonArray();
        result.put("$cond", args);
        for (int i = 0; i < strings.size(); i += 2) {
            args.add(strings.get(i));
            args.add(strings.get(i + 1));
            if (i == strings.size() - 3) {
                args.add(strings.get(i + 2));
                break;
            }
            if (i == strings.size() - 2) {
                args.add(BsonNull.VALUE);
                break;
            }
            BsonArray innerArgs = new BsonArray();
            BsonDocument innerDocument = new BsonDocument();
            innerDocument.put("$cond", innerArgs);
            args.add(innerDocument);
            args = innerArgs;
        }
        return result;
    }
    throw new IllegalArgumentException("Translation of " + call + " is not supported by MongoProject");
}
Also used : RexToLixTranslator(org.apache.calcite.adapter.enumerable.RexToLixTranslator) JavaTypeFactory(org.apache.calcite.adapter.java.JavaTypeFactory) Arrays(java.util.Arrays) SqlKind(org.apache.calcite.sql.SqlKind) SqlTypeName(org.apache.calcite.sql.type.SqlTypeName) BsonNull(org.bson.BsonNull) RexVisitorImpl(org.apache.calcite.rex.RexVisitorImpl) RexLiteral(org.apache.calcite.rex.RexLiteral) RexImpTable(org.apache.calcite.adapter.enumerable.RexImpTable) BsonString(org.bson.BsonString) Collectors(java.util.stream.Collectors) BsonDocument(org.bson.BsonDocument) BsonValue(org.bson.BsonValue) RexInputRef(org.apache.calcite.rex.RexInputRef) MongoOp(org.apache.drill.exec.store.mongo.common.MongoOp) List(java.util.List) ImmutableMap(org.apache.drill.shaded.guava.com.google.common.collect.ImmutableMap) SqlStdOperatorTable(org.apache.calcite.sql.fun.SqlStdOperatorTable) RexNode(org.apache.calcite.rex.RexNode) BsonArray(org.bson.BsonArray) Map(java.util.Map) BsonInt32(org.bson.BsonInt32) SqlOperator(org.apache.calcite.sql.SqlOperator) RexCall(org.apache.calcite.rex.RexCall) RexLiteral(org.apache.calcite.rex.RexLiteral) BsonInt32(org.bson.BsonInt32) BsonDocument(org.bson.BsonDocument) BsonString(org.bson.BsonString) BsonArray(org.bson.BsonArray) BsonString(org.bson.BsonString) BsonValue(org.bson.BsonValue) RexNode(org.apache.calcite.rex.RexNode)

Example 48 with RexLiteral

use of org.apache.calcite.rex.RexLiteral in project drill by apache.

the class DrillReduceAggregatesRule method reduceStddev.

private RexNode reduceStddev(Aggregate oldAggRel, AggregateCall oldCall, boolean biased, boolean sqrt, List<AggregateCall> newCalls, Map<AggregateCall, RexNode> aggCallMapping, List<RexNode> inputExprs) {
    // stddev_pop(x) ==>
    // power(
    // (sum(x * x) - sum(x) * sum(x) / count(x))
    // / count(x),
    // .5)
    // 
    // stddev_samp(x) ==>
    // power(
    // (sum(x * x) - sum(x) * sum(x) / count(x))
    // / nullif(count(x) - 1, 0),
    // .5)
    final PlannerSettings plannerSettings = (PlannerSettings) oldAggRel.getCluster().getPlanner().getContext();
    final boolean isInferenceEnabled = plannerSettings.isTypeInferenceEnabled();
    final int nGroups = oldAggRel.getGroupCount();
    RelDataTypeFactory typeFactory = oldAggRel.getCluster().getTypeFactory();
    final RexBuilder rexBuilder = oldAggRel.getCluster().getRexBuilder();
    assert oldCall.getArgList().size() == 1 : oldCall.getArgList();
    final int argOrdinal = oldCall.getArgList().get(0);
    final RelDataType argType = getFieldType(oldAggRel.getInput(), argOrdinal);
    // final RexNode argRef = inputExprs.get(argOrdinal);
    RexNode argRef = rexBuilder.makeCall(CastHighOp, inputExprs.get(argOrdinal));
    inputExprs.set(argOrdinal, argRef);
    final RexNode argSquared = rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, argRef, argRef);
    final int argSquaredOrdinal = lookupOrAdd(inputExprs, argSquared);
    RelDataType sumType = TypeInferenceUtils.getDrillSqlReturnTypeInference(SqlKind.SUM.name(), ImmutableList.of()).inferReturnType(oldCall.createBinding(oldAggRel));
    sumType = typeFactory.createTypeWithNullability(sumType, true);
    final AggregateCall sumArgSquaredAggCall = AggregateCall.create(new DrillCalciteSqlAggFunctionWrapper(new SqlSumAggFunction(sumType), sumType), oldCall.isDistinct(), oldCall.isApproximate(), ImmutableIntList.of(argSquaredOrdinal), -1, sumType, null);
    final RexNode sumArgSquared = rexBuilder.addAggCall(sumArgSquaredAggCall, nGroups, newCalls, aggCallMapping, ImmutableList.of(argType));
    final AggregateCall sumArgAggCall = AggregateCall.create(new DrillCalciteSqlAggFunctionWrapper(new SqlSumAggFunction(sumType), sumType), oldCall.isDistinct(), oldCall.isApproximate(), ImmutableIntList.of(argOrdinal), -1, sumType, null);
    final RexNode sumArg = rexBuilder.addAggCall(sumArgAggCall, nGroups, newCalls, aggCallMapping, ImmutableList.of(argType));
    final RexNode sumSquaredArg = rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, sumArg, sumArg);
    final SqlCountAggFunction countAgg = (SqlCountAggFunction) SqlStdOperatorTable.COUNT;
    final RelDataType countType = countAgg.getReturnType(typeFactory);
    final AggregateCall countArgAggCall = AggregateCall.create(countAgg, oldCall.isDistinct(), oldCall.isApproximate(), oldCall.getArgList(), -1, countType, null);
    final RexNode countArg = rexBuilder.addAggCall(countArgAggCall, nGroups, newCalls, aggCallMapping, ImmutableList.of(argType));
    final RexNode avgSumSquaredArg = rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE, sumSquaredArg, countArg);
    final RexNode diff = rexBuilder.makeCall(SqlStdOperatorTable.MINUS, sumArgSquared, avgSumSquaredArg);
    final RexNode denominator;
    if (biased) {
        denominator = countArg;
    } else {
        final RexLiteral one = rexBuilder.makeExactLiteral(BigDecimal.ONE);
        final RexNode nul = rexBuilder.makeNullLiteral(countArg.getType());
        final RexNode countMinusOne = rexBuilder.makeCall(SqlStdOperatorTable.MINUS, countArg, one);
        final RexNode countEqOne = rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, countArg, one);
        denominator = rexBuilder.makeCall(SqlStdOperatorTable.CASE, countEqOne, nul, countMinusOne);
    }
    final SqlOperator divide;
    if (isInferenceEnabled) {
        divide = new DrillSqlOperator("divide", 2, true, oldCall.getType(), false);
    } else {
        divide = SqlStdOperatorTable.DIVIDE;
    }
    final RexNode div = rexBuilder.makeCall(divide, diff, denominator);
    RexNode result = div;
    if (sqrt) {
        final RexNode half = rexBuilder.makeExactLiteral(new BigDecimal("0.5"));
        result = rexBuilder.makeCall(SqlStdOperatorTable.POWER, div, half);
    }
    if (isInferenceEnabled) {
        return result;
    } else {
        /*
      * Currently calcite's strategy to infer the return type of aggregate functions
      * is wrong because it uses the first known argument to determine output type. For
      * instance if we are performing stddev on an integer column then it interprets the
      * output type to be integer which is incorrect as it should be double. So based on
      * this if we add cast after rewriting the aggregate we add an additional cast which
      * would cause wrong results. So we simply add a cast to ANY.
      */
        return rexBuilder.makeCast(typeFactory.createSqlType(SqlTypeName.ANY), result);
    }
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) PlannerSettings(org.apache.drill.exec.planner.physical.PlannerSettings) DrillSqlOperator(org.apache.drill.exec.planner.sql.DrillSqlOperator) SqlOperator(org.apache.calcite.sql.SqlOperator) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlCountAggFunction(org.apache.calcite.sql.fun.SqlCountAggFunction) BigDecimal(java.math.BigDecimal) DrillCalciteSqlAggFunctionWrapper(org.apache.drill.exec.planner.sql.DrillCalciteSqlAggFunctionWrapper) DrillSqlOperator(org.apache.drill.exec.planner.sql.DrillSqlOperator) AggregateCall(org.apache.calcite.rel.core.AggregateCall) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) SqlSumAggFunction(org.apache.calcite.sql.fun.SqlSumAggFunction) RexBuilder(org.apache.calcite.rex.RexBuilder) RexNode(org.apache.calcite.rex.RexNode)

Example 49 with RexLiteral

use of org.apache.calcite.rex.RexLiteral in project drill by apache.

the class FieldsReWriterUtil method getFieldNameFromItemStarField.

/**
 * Checks if operator call is using item star field.
 * Will return field name if true. null otherwise.
 *
 * @param rexCall operator call
 * @param fieldNames list of field names
 * @return field name, null otherwise
 */
public static String getFieldNameFromItemStarField(RexCall rexCall, List<String> fieldNames) {
    if (!SqlStdOperatorTable.ITEM.equals(rexCall.getOperator())) {
        return null;
    }
    if (rexCall.getOperands().size() != 2) {
        return null;
    }
    if (!(rexCall.getOperands().get(0) instanceof RexInputRef && rexCall.getOperands().get(1) instanceof RexLiteral)) {
        return null;
    }
    // get parent field reference from the first operand (ITEM($0, 'col_name' -> $0)
    // and check if it corresponds to the dynamic star
    RexInputRef rexInputRef = (RexInputRef) rexCall.getOperands().get(0);
    String parentFieldName = fieldNames.get(rexInputRef.getIndex());
    if (!SchemaPath.DYNAMIC_STAR.equals(parentFieldName)) {
        return null;
    }
    // get field name from the second operand (ITEM($0, 'col_name') -> col_name)
    RexLiteral rexLiteral = (RexLiteral) rexCall.getOperands().get(1);
    if (SqlTypeName.CHAR.equals(rexLiteral.getType().getSqlTypeName())) {
        return RexLiteral.stringValue(rexLiteral);
    }
    return null;
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) RexInputRef(org.apache.calcite.rex.RexInputRef)

Example 50 with RexLiteral

use of org.apache.calcite.rex.RexLiteral in project drill by apache.

the class MapRDBStatistics method convertLikeToRange.

/*
   * Helper function to perform additional pre-processing for LIKE predicates
   */
private RexNode convertLikeToRange(RexCall condition, RexBuilder builder) {
    Preconditions.checkArgument(condition.getOperator().getKind() == SqlKind.LIKE, "Unable to convertLikeToRange: argument is not a LIKE condition!");
    HBaseRegexParser parser = null;
    RexNode arg = null;
    RexLiteral pattern = null, escape = null;
    String patternStr = null, escapeStr = null;
    if (condition.getOperands().size() == 2) {
        // No escape character specified
        for (RexNode op : condition.getOperands()) {
            if (op.getKind() == SqlKind.LITERAL) {
                pattern = (RexLiteral) op;
            } else {
                arg = op;
            }
        }
        // Get the PATTERN strings from the corresponding RexLiteral
        if (pattern.getTypeName() == SqlTypeName.DECIMAL || pattern.getTypeName() == SqlTypeName.INTEGER) {
            patternStr = pattern.getValue().toString();
        } else if (pattern.getTypeName() == SqlTypeName.CHAR) {
            patternStr = pattern.getValue2().toString();
        }
        if (patternStr != null) {
            parser = new HBaseRegexParser(patternStr);
        }
    } else if (condition.getOperands().size() == 3) {
        // Escape character specified
        for (RexNode op : condition.getOperands()) {
            if (op.getKind() == SqlKind.LITERAL) {
                // Assume first literal specifies PATTERN and the second literal specifies the ESCAPE char
                if (pattern == null) {
                    pattern = (RexLiteral) op;
                } else {
                    escape = (RexLiteral) op;
                }
            } else {
                arg = op;
            }
        }
        // Get the PATTERN and ESCAPE strings from the corresponding RexLiteral
        if (pattern.getTypeName() == SqlTypeName.DECIMAL || pattern.getTypeName() == SqlTypeName.INTEGER) {
            patternStr = pattern.getValue().toString();
        } else if (pattern.getTypeName() == SqlTypeName.CHAR) {
            patternStr = pattern.getValue2().toString();
        }
        if (escape.getTypeName() == SqlTypeName.DECIMAL || escape.getTypeName() == SqlTypeName.INTEGER) {
            escapeStr = escape.getValue().toString();
        } else if (escape.getTypeName() == SqlTypeName.CHAR) {
            escapeStr = escape.getValue2().toString();
        }
        if (patternStr != null && escapeStr != null) {
            parser = new HBaseRegexParser(patternStr, escapeStr.toCharArray()[0]);
        }
    }
    if (parser != null) {
        parser.parse();
        String prefix = parser.getPrefixString();
        /*
       * If there is a literal prefix, convert it into an EQUALITY or RANGE predicate
       */
        if (prefix != null) {
            if (prefix.equals(parser.getLikeString())) {
                // No WILDCARD present. This turns the LIKE predicate to EQUALITY predicate
                if (arg != null) {
                    return builder.makeCall(SqlStdOperatorTable.EQUALS, arg, pattern);
                }
            } else {
                // WILDCARD present. This turns the LIKE predicate to RANGE predicate
                byte[] startKey = HConstants.EMPTY_START_ROW;
                byte[] stopKey = HConstants.EMPTY_END_ROW;
                startKey = prefix.getBytes(Charsets.UTF_8);
                stopKey = startKey.clone();
                boolean isMaxVal = true;
                for (int i = stopKey.length - 1; i >= 0; --i) {
                    int nextByteValue = (0xff & stopKey[i]) + 1;
                    if (nextByteValue < 0xff) {
                        stopKey[i] = (byte) nextByteValue;
                        isMaxVal = false;
                        break;
                    } else {
                        stopKey[i] = 0;
                    }
                }
                if (isMaxVal) {
                    stopKey = HConstants.EMPTY_END_ROW;
                }
                try {
                    // TODO: This maybe a potential bug since we assume UTF-8 encoding. However, we follow the
                    // current DB implementation. See HBaseFilterBuilder.createHBaseScanSpec "like" CASE statement
                    RexLiteral startKeyLiteral = builder.makeLiteral(new String(startKey, Charsets.UTF_8.toString()));
                    RexLiteral stopKeyLiteral = builder.makeLiteral(new String(stopKey, Charsets.UTF_8.toString()));
                    if (arg != null) {
                        RexNode startPred = builder.makeCall(SqlStdOperatorTable.GREATER_THAN_OR_EQUAL, arg, startKeyLiteral);
                        RexNode stopPred = builder.makeCall(SqlStdOperatorTable.LESS_THAN, arg, stopKeyLiteral);
                        return builder.makeCall(SqlStdOperatorTable.AND, startPred, stopPred);
                    }
                } catch (UnsupportedEncodingException ex) {
                    // Encoding not supported - Do nothing!
                    logger.debug("Statistics: convertLikeToRange: Unsupported Encoding Exception -> {}", ex.getMessage());
                }
            }
        }
    }
    // Could not convert - return condition as-is.
    return condition;
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) HBaseRegexParser(org.apache.drill.exec.store.hbase.HBaseRegexParser) UnsupportedEncodingException(java.io.UnsupportedEncodingException) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

RexLiteral (org.apache.calcite.rex.RexLiteral)150 RexNode (org.apache.calcite.rex.RexNode)92 ArrayList (java.util.ArrayList)51 RelDataType (org.apache.calcite.rel.type.RelDataType)45 RexCall (org.apache.calcite.rex.RexCall)45 Test (org.junit.Test)32 BigDecimal (java.math.BigDecimal)28 RexInputRef (org.apache.calcite.rex.RexInputRef)26 RelNode (org.apache.calcite.rel.RelNode)22 ImmutableList (com.google.common.collect.ImmutableList)18 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)17 List (java.util.List)16 Map (java.util.Map)16 RexBuilder (org.apache.calcite.rex.RexBuilder)16 AggregateCall (org.apache.calcite.rel.core.AggregateCall)15 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)12 RexLiteral (org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexLiteral)11 NlsString (org.apache.calcite.util.NlsString)11 HashMap (java.util.HashMap)10 RexNode (org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode)10