Search in sources :

Example 6 with SqlKind

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

the class FilterSelectivityEstimator method getOp.

private SqlKind getOp(RexCall call) {
    SqlKind op = call.getKind();
    if (call.getKind().equals(SqlKind.OTHER_FUNCTION) && SqlTypeUtil.inBooleanFamily(call.getType())) {
        SqlOperator sqlOp = call.getOperator();
        String opName = (sqlOp != null) ? sqlOp.getName() : "";
        if (opName.equalsIgnoreCase("in")) {
            op = SqlKind.IN;
        }
    }
    return op;
}
Also used : SqlOperator(org.apache.calcite.sql.SqlOperator) SqlKind(org.apache.calcite.sql.SqlKind)

Example 7 with SqlKind

use of org.apache.calcite.sql.SqlKind in project druid by druid-io.

the class Expressions method toLeafFilter.

/**
   * Translates "condition" to a Druid filter, assuming it does not contain any boolean expressions. Returns null
   * if we cannot translate the condition.
   *
   * @param plannerContext planner context
   * @param rowSignature   row signature of the dataSource to be filtered
   * @param expression     Calcite row expression
   */
private static DimFilter toLeafFilter(final DruidOperatorTable operatorTable, final PlannerContext plannerContext, final RowSignature rowSignature, final RexNode expression) {
    if (expression.isAlwaysTrue()) {
        return Filtration.matchEverything();
    } else if (expression.isAlwaysFalse()) {
        return Filtration.matchNothing();
    }
    final SqlKind kind = expression.getKind();
    if (kind == SqlKind.LIKE) {
        final List<RexNode> operands = ((RexCall) expression).getOperands();
        final RowExtraction rex = toRowExtraction(operatorTable, plannerContext, rowSignature.getRowOrder(), operands.get(0));
        if (rex == null || !rex.isFilterable(rowSignature)) {
            return null;
        }
        return new LikeDimFilter(rex.getColumn(), RexLiteral.stringValue(operands.get(1)), operands.size() > 2 ? RexLiteral.stringValue(operands.get(2)) : null, rex.getExtractionFn());
    } else if (kind == SqlKind.EQUALS || kind == SqlKind.NOT_EQUALS || kind == SqlKind.GREATER_THAN || kind == SqlKind.GREATER_THAN_OR_EQUAL || kind == SqlKind.LESS_THAN || kind == SqlKind.LESS_THAN_OR_EQUAL) {
        final List<RexNode> operands = ((RexCall) expression).getOperands();
        Preconditions.checkState(operands.size() == 2, "WTF?! Expected 2 operands, got[%,d]", operands.size());
        boolean flip = false;
        RexNode lhs = operands.get(0);
        RexNode rhs = operands.get(1);
        if (lhs.getKind() == SqlKind.LITERAL && rhs.getKind() != SqlKind.LITERAL) {
            // swap lhs, rhs
            RexNode x = lhs;
            lhs = rhs;
            rhs = x;
            flip = true;
        }
        // rhs must be a literal
        if (rhs.getKind() != SqlKind.LITERAL) {
            return null;
        }
        // lhs must be translatable to a RowExtraction to be filterable
        final RowExtraction rex = toRowExtraction(operatorTable, plannerContext, rowSignature.getRowOrder(), lhs);
        if (rex == null || !rex.isFilterable(rowSignature)) {
            return null;
        }
        final String column = rex.getColumn();
        final ExtractionFn extractionFn = rex.getExtractionFn();
        if (column.equals(Column.TIME_COLUMN_NAME) && extractionFn instanceof TimeFormatExtractionFn) {
            // Check if we can strip the extractionFn and convert the filter to a direct filter on __time.
            // This allows potential conversion to query-level "intervals" later on, which is ideal for Druid queries.
            final Granularity granularity = ExtractionFns.toQueryGranularity(extractionFn);
            if (granularity != null) {
                // lhs is FLOOR(__time TO granularity); rhs must be a timestamp
                final long rhsMillis = toMillisLiteral(rhs, plannerContext.getTimeZone());
                final Interval rhsInterval = granularity.bucket(new DateTime(rhsMillis));
                // Is rhs aligned on granularity boundaries?
                final boolean rhsAligned = rhsInterval.getStartMillis() == rhsMillis;
                // Create a BoundRefKey that strips the extractionFn and compares __time as a number.
                final BoundRefKey boundRefKey = new BoundRefKey(column, null, StringComparators.NUMERIC);
                if (kind == SqlKind.EQUALS) {
                    return rhsAligned ? Bounds.interval(boundRefKey, rhsInterval) : Filtration.matchNothing();
                } else if (kind == SqlKind.NOT_EQUALS) {
                    return rhsAligned ? new NotDimFilter(Bounds.interval(boundRefKey, rhsInterval)) : Filtration.matchEverything();
                } else if ((!flip && kind == SqlKind.GREATER_THAN) || (flip && kind == SqlKind.LESS_THAN)) {
                    return Bounds.greaterThanOrEqualTo(boundRefKey, String.valueOf(rhsInterval.getEndMillis()));
                } else if ((!flip && kind == SqlKind.GREATER_THAN_OR_EQUAL) || (flip && kind == SqlKind.LESS_THAN_OR_EQUAL)) {
                    return rhsAligned ? Bounds.greaterThanOrEqualTo(boundRefKey, String.valueOf(rhsInterval.getStartMillis())) : Bounds.greaterThanOrEqualTo(boundRefKey, String.valueOf(rhsInterval.getEndMillis()));
                } else if ((!flip && kind == SqlKind.LESS_THAN) || (flip && kind == SqlKind.GREATER_THAN)) {
                    return rhsAligned ? Bounds.lessThan(boundRefKey, String.valueOf(rhsInterval.getStartMillis())) : Bounds.lessThan(boundRefKey, String.valueOf(rhsInterval.getEndMillis()));
                } else if ((!flip && kind == SqlKind.LESS_THAN_OR_EQUAL) || (flip && kind == SqlKind.GREATER_THAN_OR_EQUAL)) {
                    return Bounds.lessThan(boundRefKey, String.valueOf(rhsInterval.getEndMillis()));
                } else {
                    throw new IllegalStateException("WTF?! Shouldn't have got here...");
                }
            }
        }
        final String val;
        final RexLiteral rhsLiteral = (RexLiteral) rhs;
        if (SqlTypeName.NUMERIC_TYPES.contains(rhsLiteral.getTypeName())) {
            val = String.valueOf(RexLiteral.value(rhsLiteral));
        } else if (SqlTypeName.CHAR_TYPES.contains(rhsLiteral.getTypeName())) {
            val = String.valueOf(RexLiteral.stringValue(rhsLiteral));
        } else if (SqlTypeName.TIMESTAMP == rhsLiteral.getTypeName() || SqlTypeName.DATE == rhsLiteral.getTypeName()) {
            val = String.valueOf(toMillisLiteral(rhsLiteral, plannerContext.getTimeZone()));
        } else {
            // Don't know how to filter on this kind of literal.
            return null;
        }
        // Numeric lhs needs a numeric comparison.
        final boolean lhsIsNumeric = SqlTypeName.NUMERIC_TYPES.contains(lhs.getType().getSqlTypeName()) || SqlTypeName.TIMESTAMP == lhs.getType().getSqlTypeName() || SqlTypeName.DATE == lhs.getType().getSqlTypeName();
        final StringComparator comparator = lhsIsNumeric ? StringComparators.NUMERIC : StringComparators.LEXICOGRAPHIC;
        final BoundRefKey boundRefKey = new BoundRefKey(column, extractionFn, comparator);
        final DimFilter filter;
        // Always use BoundDimFilters, to simplify filter optimization later (it helps to remember the comparator).
        if (kind == SqlKind.EQUALS) {
            filter = Bounds.equalTo(boundRefKey, val);
        } else if (kind == SqlKind.NOT_EQUALS) {
            filter = new NotDimFilter(Bounds.equalTo(boundRefKey, val));
        } else if ((!flip && kind == SqlKind.GREATER_THAN) || (flip && kind == SqlKind.LESS_THAN)) {
            filter = Bounds.greaterThan(boundRefKey, val);
        } else if ((!flip && kind == SqlKind.GREATER_THAN_OR_EQUAL) || (flip && kind == SqlKind.LESS_THAN_OR_EQUAL)) {
            filter = Bounds.greaterThanOrEqualTo(boundRefKey, val);
        } else if ((!flip && kind == SqlKind.LESS_THAN) || (flip && kind == SqlKind.GREATER_THAN)) {
            filter = Bounds.lessThan(boundRefKey, val);
        } else if ((!flip && kind == SqlKind.LESS_THAN_OR_EQUAL) || (flip && kind == SqlKind.GREATER_THAN_OR_EQUAL)) {
            filter = Bounds.lessThanOrEqualTo(boundRefKey, val);
        } else {
            throw new IllegalStateException("WTF?! Shouldn't have got here...");
        }
        return filter;
    } else {
        return null;
    }
}
Also used : TimeFormatExtractionFn(io.druid.query.extraction.TimeFormatExtractionFn) RexLiteral(org.apache.calcite.rex.RexLiteral) NotDimFilter(io.druid.query.filter.NotDimFilter) SqlKind(org.apache.calcite.sql.SqlKind) Granularity(io.druid.java.util.common.granularity.Granularity) StringComparator(io.druid.query.ordering.StringComparator) DateTime(org.joda.time.DateTime) RexCall(org.apache.calcite.rex.RexCall) ExtractionFn(io.druid.query.extraction.ExtractionFn) TimeFormatExtractionFn(io.druid.query.extraction.TimeFormatExtractionFn) LikeDimFilter(io.druid.query.filter.LikeDimFilter) List(java.util.List) BoundRefKey(io.druid.sql.calcite.filtration.BoundRefKey) LikeDimFilter(io.druid.query.filter.LikeDimFilter) OrDimFilter(io.druid.query.filter.OrDimFilter) DimFilter(io.druid.query.filter.DimFilter) NotDimFilter(io.druid.query.filter.NotDimFilter) AndDimFilter(io.druid.query.filter.AndDimFilter) RexNode(org.apache.calcite.rex.RexNode) Interval(org.joda.time.Interval)

Example 8 with SqlKind

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

the class JoinPrel method buildJoinConditions.

/**
   * Build the list of join conditions for this join.
   * A join condition is built only for equality and IS NOT DISTINCT FROM comparisons. The difference is:
   * null == null is FALSE whereas null IS NOT DISTINCT FROM null is TRUE
   * For a use case of the IS NOT DISTINCT FROM comparison, see
   * {@link org.apache.calcite.rel.rules.RemoveDistinctAggregateRule}
   * @param conditions populated list of join conditions
   * @param leftFields join fields from the left input
   * @param rightFields join fields from the right input
   */
protected void buildJoinConditions(List<JoinCondition> conditions, List<String> leftFields, List<String> rightFields, List<Integer> leftKeys, List<Integer> rightKeys) {
    List<RexNode> conjuncts = RelOptUtil.conjunctions(this.getCondition());
    short i = 0;
    for (Pair<Integer, Integer> pair : Pair.zip(leftKeys, rightKeys)) {
        final RexNode conditionExpr = conjuncts.get(i++);
        final SqlKind kind = conditionExpr.getKind();
        if (kind != SqlKind.EQUALS && kind != SqlKind.IS_NOT_DISTINCT_FROM) {
            throw UserException.unsupportedError().message("Unsupported comparator in join condition %s", conditionExpr).build(logger);
        }
        conditions.add(new JoinCondition(kind.toString(), FieldReference.getWithQuotedRef(leftFields.get(pair.left)), FieldReference.getWithQuotedRef(rightFields.get(pair.right))));
    }
}
Also used : SqlKind(org.apache.calcite.sql.SqlKind) RexNode(org.apache.calcite.rex.RexNode) JoinCondition(org.apache.drill.common.logical.data.JoinCondition)

Example 9 with SqlKind

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

the class RewriteCombineBinaryOperators method visitCall.

@Override
public RexNode visitCall(RexCall call) {
    SqlOperator op = call.getOperator();
    SqlKind kind = op.getKind();
    RelDataType type = call.getType();
    if (kind == SqlKind.AND) {
        List<RexNode> conjuncts = Lists.newArrayList();
        for (RexNode child : call.getOperands()) {
            conjuncts.addAll(RelOptUtil.conjunctions(child.accept(this)));
        }
        return RexUtil.composeConjunction(builder, conjuncts, true);
    }
    if (kind == SqlKind.OR) {
        List<RexNode> disjuncts = Lists.newArrayList();
        for (RexNode child : call.getOperands()) {
            disjuncts.addAll(RelOptUtil.disjunctions(child.accept(this)));
        }
        return RexUtil.composeDisjunction(builder, disjuncts, true);
    }
    return builder.makeCall(type, op, visitChildren(call));
}
Also used : SqlOperator(org.apache.calcite.sql.SqlOperator) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlKind(org.apache.calcite.sql.SqlKind) RexNode(org.apache.calcite.rex.RexNode)

Example 10 with SqlKind

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

the class FilterSelectivityEstimator method visitCall.

public Double visitCall(RexCall call) {
    if (!deep) {
        return 1.0;
    }
    /*
     * Ignore any predicates on partition columns because we have already
     * accounted for these in the Table row count.
     */
    if (isPartitionPredicate(call, this.childRel)) {
        return 1.0;
    }
    Double selectivity = null;
    SqlKind op = getOp(call);
    switch(op) {
        case AND:
            {
                selectivity = computeConjunctionSelectivity(call);
                break;
            }
        case OR:
            {
                selectivity = computeDisjunctionSelectivity(call);
                break;
            }
        case NOT:
        case NOT_EQUALS:
            {
                selectivity = computeNotEqualitySelectivity(call);
                break;
            }
        case IS_NOT_NULL:
            {
                if (childRel instanceof HiveTableScan) {
                    double noOfNulls = getMaxNulls(call, (HiveTableScan) childRel);
                    double totalNoOfTuples = mq.getRowCount(childRel);
                    if (totalNoOfTuples >= noOfNulls) {
                        selectivity = (totalNoOfTuples - noOfNulls) / Math.max(totalNoOfTuples, 1);
                    } else {
                        throw new RuntimeException("Invalid Stats number of null > no of tuples");
                    }
                } else {
                    selectivity = computeNotEqualitySelectivity(call);
                }
                break;
            }
        case LESS_THAN_OR_EQUAL:
        case GREATER_THAN_OR_EQUAL:
        case LESS_THAN:
        case GREATER_THAN:
            {
                selectivity = ((double) 1 / (double) 3);
                break;
            }
        case IN:
            {
                // TODO: 1) check for duplicates 2) We assume in clause values to be
                // present in NDV which may not be correct (Range check can find it) 3) We
                // assume values in NDV set is uniformly distributed over col values
                // (account for skewness - histogram).
                selectivity = computeFunctionSelectivity(call) * (call.operands.size() - 1);
                if (selectivity <= 0.0) {
                    selectivity = 0.10;
                } else if (selectivity >= 1.0) {
                    selectivity = 1.0;
                }
                break;
            }
        default:
            selectivity = computeFunctionSelectivity(call);
    }
    return selectivity;
}
Also used : SqlKind(org.apache.calcite.sql.SqlKind) HiveTableScan(org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveTableScan)

Aggregations

SqlKind (org.apache.calcite.sql.SqlKind)10 RexNode (org.apache.calcite.rex.RexNode)7 RelDataType (org.apache.calcite.rel.type.RelDataType)4 RexCall (org.apache.calcite.rex.RexCall)4 SqlOperator (org.apache.calcite.sql.SqlOperator)3 ISE (io.druid.java.util.common.ISE)2 AndDimFilter (io.druid.query.filter.AndDimFilter)2 DimFilter (io.druid.query.filter.DimFilter)2 NotDimFilter (io.druid.query.filter.NotDimFilter)2 List (java.util.List)2 RexBuilder (org.apache.calcite.rex.RexBuilder)2 RexLiteral (org.apache.calcite.rex.RexLiteral)2 SqlTypeName (org.apache.calcite.sql.type.SqlTypeName)2 Granularity (io.druid.java.util.common.granularity.Granularity)1 ExprType (io.druid.math.expr.ExprType)1 AggregatorFactory (io.druid.query.aggregation.AggregatorFactory)1 CountAggregatorFactory (io.druid.query.aggregation.CountAggregatorFactory)1 DoubleMaxAggregatorFactory (io.druid.query.aggregation.DoubleMaxAggregatorFactory)1 DoubleMinAggregatorFactory (io.druid.query.aggregation.DoubleMinAggregatorFactory)1 DoubleSumAggregatorFactory (io.druid.query.aggregation.DoubleSumAggregatorFactory)1