Search in sources :

Example 16 with DruidExpression

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

the class TimeShiftOperatorConversion method toDruidExpression.

@Override
public DruidExpression toDruidExpression(final PlannerContext plannerContext, final RowSignature rowSignature, final RexNode rexNode) {
    final RexCall call = (RexCall) rexNode;
    final DruidExpression timeExpression = Expressions.toDruidExpression(plannerContext, rowSignature, call.getOperands().get(0));
    final DruidExpression periodExpression = Expressions.toDruidExpression(plannerContext, rowSignature, call.getOperands().get(1));
    final DruidExpression stepExpression = Expressions.toDruidExpression(plannerContext, rowSignature, call.getOperands().get(2));
    if (timeExpression == null || periodExpression == null || stepExpression == null) {
        return null;
    }
    final DateTimeZone timeZone = OperatorConversions.getOperandWithDefault(call.getOperands(), 3, operand -> DateTimes.inferTzFromString(RexLiteral.stringValue(operand)), plannerContext.getTimeZone());
    return DruidExpression.ofFunctionCall(Calcites.getColumnTypeForRelDataType(rexNode.getType()), "timestamp_shift", ImmutableList.of(timeExpression, periodExpression, stepExpression, DruidExpression.ofStringLiteral(timeZone.getID())));
}
Also used : RexCall(org.apache.calcite.rex.RexCall) DruidExpression(org.apache.druid.sql.calcite.expression.DruidExpression) DateTimeZone(org.joda.time.DateTimeZone)

Example 17 with DruidExpression

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

the class ArrayContainsOperatorConversion method toDruidFilter.

@Nullable
@Override
public DimFilter toDruidFilter(final PlannerContext plannerContext, RowSignature rowSignature, @Nullable VirtualColumnRegistry virtualColumnRegistry, final RexNode rexNode) {
    final List<RexNode> operands = ((RexCall) rexNode).getOperands();
    final List<DruidExpression> druidExpressions = Expressions.toDruidExpressions(plannerContext, rowSignature, operands);
    if (druidExpressions == null) {
        return null;
    }
    // Converts array_contains() function into an AND of Selector filters if possible.
    final DruidExpression leftExpr = druidExpressions.get(0);
    final DruidExpression rightExpr = druidExpressions.get(1);
    if (leftExpr.isSimpleExtraction()) {
        Expr expr = Parser.parse(rightExpr.getExpression(), plannerContext.getExprMacroTable());
        // different package.
        if (expr.isLiteral()) {
            // Evaluate the expression to get out the array elements.
            // We can safely pass a noop ObjectBinding if the expression is literal.
            ExprEval<?> exprEval = expr.eval(InputBindings.nilBindings());
            String[] arrayElements = exprEval.asStringArray();
            if (arrayElements == null || arrayElements.length == 0) {
                // to create an empty array with no argument, we just return null.
                return null;
            } else if (arrayElements.length == 1) {
                return newSelectorDimFilter(leftExpr.getSimpleExtraction(), arrayElements[0]);
            } else {
                final List<DimFilter> selectFilters = Arrays.stream(arrayElements).map(val -> newSelectorDimFilter(leftExpr.getSimpleExtraction(), val)).collect(Collectors.toList());
                return new AndDimFilter(selectFilters);
            }
        }
    }
    return toExpressionFilter(plannerContext, getDruidFunctionName(), druidExpressions);
}
Also used : RexCall(org.apache.calcite.rex.RexCall) DruidExpression(org.apache.druid.sql.calcite.expression.DruidExpression) Expr(org.apache.druid.math.expr.Expr) AndDimFilter(org.apache.druid.query.filter.AndDimFilter) List(java.util.List) RexNode(org.apache.calcite.rex.RexNode) Nullable(javax.annotation.Nullable)

Example 18 with DruidExpression

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

the class ArrayOverlapOperatorConversion method toDruidFilter.

@Nullable
@Override
public DimFilter toDruidFilter(final PlannerContext plannerContext, RowSignature rowSignature, @Nullable VirtualColumnRegistry virtualColumnRegistry, final RexNode rexNode) {
    final List<RexNode> operands = ((RexCall) rexNode).getOperands();
    final List<DruidExpression> druidExpressions = Expressions.toDruidExpressions(plannerContext, rowSignature, operands);
    if (druidExpressions == null) {
        return null;
    }
    // Converts array_overlaps() function into an OR of Selector filters if possible.
    final boolean leftSimpleExtractionExpr = druidExpressions.get(0).isSimpleExtraction();
    final boolean rightSimpleExtractionExpr = druidExpressions.get(1).isSimpleExtraction();
    final DruidExpression simpleExtractionExpr;
    final DruidExpression complexExpr;
    if (leftSimpleExtractionExpr ^ rightSimpleExtractionExpr) {
        if (leftSimpleExtractionExpr) {
            simpleExtractionExpr = druidExpressions.get(0);
            complexExpr = druidExpressions.get(1);
        } else {
            simpleExtractionExpr = druidExpressions.get(1);
            complexExpr = druidExpressions.get(0);
        }
    } else {
        return toExpressionFilter(plannerContext, getDruidFunctionName(), druidExpressions);
    }
    Expr expr = Parser.parse(complexExpr.getExpression(), plannerContext.getExprMacroTable());
    if (expr.isLiteral()) {
        // Evaluate the expression to take out the array elements.
        // We can safely pass null if the expression is literal.
        ExprEval<?> exprEval = expr.eval(InputBindings.nilBindings());
        String[] arrayElements = exprEval.asStringArray();
        if (arrayElements == null || arrayElements.length == 0) {
            // to create an empty array with no argument, we just return null.
            return null;
        } else if (arrayElements.length == 1) {
            return newSelectorDimFilter(simpleExtractionExpr.getSimpleExtraction(), arrayElements[0]);
        } else {
            return new InDimFilter(simpleExtractionExpr.getSimpleExtraction().getColumn(), Sets.newHashSet(arrayElements), simpleExtractionExpr.getSimpleExtraction().getExtractionFn(), null);
        }
    }
    return toExpressionFilter(plannerContext, getDruidFunctionName(), druidExpressions);
}
Also used : RexCall(org.apache.calcite.rex.RexCall) DruidExpression(org.apache.druid.sql.calcite.expression.DruidExpression) Expr(org.apache.druid.math.expr.Expr) InDimFilter(org.apache.druid.query.filter.InDimFilter) RexNode(org.apache.calcite.rex.RexNode) Nullable(javax.annotation.Nullable)

Example 19 with DruidExpression

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

the class RegexpExtractOperatorConversion method toDruidExpression.

@Override
public DruidExpression toDruidExpression(final PlannerContext plannerContext, final RowSignature rowSignature, final RexNode rexNode) {
    return OperatorConversions.convertDirectCallWithExtraction(plannerContext, rowSignature, rexNode, StringUtils.toLowerCase(calciteOperator().getName()), inputExpressions -> {
        final DruidExpression arg = inputExpressions.get(0);
        final Expr patternExpr = inputExpressions.get(1).parse(plannerContext.getExprMacroTable());
        final Expr indexExpr = inputExpressions.size() > 2 ? inputExpressions.get(2).parse(plannerContext.getExprMacroTable()) : null;
        if (arg.isSimpleExtraction() && patternExpr.isLiteral() && (indexExpr == null || indexExpr.isLiteral())) {
            final String pattern = (String) patternExpr.getLiteralValue();
            return arg.getSimpleExtraction().cascade(new RegexDimExtractionFn(// non-SQL-compliant null handling mode).
            StringUtils.nullToEmptyNonDruidDataString(pattern), indexExpr == null ? DEFAULT_INDEX : ((Number) indexExpr.getLiteralValue()).intValue(), true, null));
        } else {
            return null;
        }
    });
}
Also used : DruidExpression(org.apache.druid.sql.calcite.expression.DruidExpression) Expr(org.apache.druid.math.expr.Expr) RegexDimExtractionFn(org.apache.druid.query.extraction.RegexDimExtractionFn)

Example 20 with DruidExpression

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

the class TDigestSketchQuantileSqlAggregator method toDruidAggregation.

@Nullable
@Override
public Aggregation toDruidAggregation(final PlannerContext plannerContext, final RowSignature rowSignature, final VirtualColumnRegistry virtualColumnRegistry, final RexBuilder rexBuilder, final String name, final AggregateCall aggregateCall, final Project project, final List<Aggregation> existingAggregations, final boolean finalizeAggregations) {
    // This is expected to be a tdigest sketch
    final DruidExpression input = Aggregations.toDruidExpressionForNumericAggregator(plannerContext, rowSignature, Expressions.fromFieldAccess(rowSignature, project, aggregateCall.getArgList().get(0)));
    if (input == null) {
        return null;
    }
    final AggregatorFactory aggregatorFactory;
    final String sketchName = StringUtils.format("%s:agg", name);
    // this is expected to be quantile fraction
    final RexNode quantileArg = Expressions.fromFieldAccess(rowSignature, project, aggregateCall.getArgList().get(1));
    if (!quantileArg.isA(SqlKind.LITERAL)) {
        // Quantile must be a literal in order to plan.
        return null;
    }
    final double quantile = ((Number) RexLiteral.value(quantileArg)).floatValue();
    Integer compression = TDigestSketchAggregatorFactory.DEFAULT_COMPRESSION;
    if (aggregateCall.getArgList().size() > 2) {
        final RexNode compressionArg = Expressions.fromFieldAccess(rowSignature, project, aggregateCall.getArgList().get(2));
        compression = ((Number) RexLiteral.value(compressionArg)).intValue();
    }
    // Look for existing matching aggregatorFactory.
    for (final Aggregation existing : existingAggregations) {
        for (AggregatorFactory factory : existing.getAggregatorFactories()) {
            if (factory instanceof TDigestSketchAggregatorFactory) {
                final boolean matches = TDigestSketchUtils.matchingAggregatorFactoryExists(virtualColumnRegistry, input, compression, (TDigestSketchAggregatorFactory) factory);
                if (matches) {
                    // Found existing one. Use this.
                    return Aggregation.create(ImmutableList.of(), new TDigestSketchToQuantilePostAggregator(name, new FieldAccessPostAggregator(factory.getName(), factory.getName()), quantile));
                }
            }
        }
    }
    // No existing match found. Create a new one.
    if (input.isDirectColumnAccess()) {
        aggregatorFactory = new TDigestSketchAggregatorFactory(sketchName, input.getDirectColumn(), compression);
    } else {
        String virtualColumnName = virtualColumnRegistry.getOrCreateVirtualColumnForExpression(input, ColumnType.FLOAT);
        aggregatorFactory = new TDigestSketchAggregatorFactory(sketchName, virtualColumnName, compression);
    }
    return Aggregation.create(ImmutableList.of(aggregatorFactory), new TDigestSketchToQuantilePostAggregator(name, new FieldAccessPostAggregator(sketchName, sketchName), quantile));
}
Also used : Aggregation(org.apache.druid.sql.calcite.aggregation.Aggregation) TDigestSketchAggregatorFactory(org.apache.druid.query.aggregation.tdigestsketch.TDigestSketchAggregatorFactory) FieldAccessPostAggregator(org.apache.druid.query.aggregation.post.FieldAccessPostAggregator) DruidExpression(org.apache.druid.sql.calcite.expression.DruidExpression) TDigestSketchToQuantilePostAggregator(org.apache.druid.query.aggregation.tdigestsketch.TDigestSketchToQuantilePostAggregator) TDigestSketchAggregatorFactory(org.apache.druid.query.aggregation.tdigestsketch.TDigestSketchAggregatorFactory) AggregatorFactory(org.apache.druid.query.aggregation.AggregatorFactory) RexNode(org.apache.calcite.rex.RexNode) Nullable(javax.annotation.Nullable)

Aggregations

DruidExpression (org.apache.druid.sql.calcite.expression.DruidExpression)53 RexNode (org.apache.calcite.rex.RexNode)34 Nullable (javax.annotation.Nullable)30 RexCall (org.apache.calcite.rex.RexCall)20 ColumnType (org.apache.druid.segment.column.ColumnType)15 AggregatorFactory (org.apache.druid.query.aggregation.AggregatorFactory)14 RexLiteral (org.apache.calcite.rex.RexLiteral)12 Aggregation (org.apache.druid.sql.calcite.aggregation.Aggregation)12 List (java.util.List)11 RowSignature (org.apache.druid.segment.column.RowSignature)11 RelDataType (org.apache.calcite.rel.type.RelDataType)10 Expressions (org.apache.druid.sql.calcite.expression.Expressions)10 SqlKind (org.apache.calcite.sql.SqlKind)9 PlannerContext (org.apache.druid.sql.calcite.planner.PlannerContext)9 RexBuilder (org.apache.calcite.rex.RexBuilder)8 SqlAggFunction (org.apache.calcite.sql.SqlAggFunction)8 SqlFunctionCategory (org.apache.calcite.sql.SqlFunctionCategory)8 ExprMacroTable (org.apache.druid.math.expr.ExprMacroTable)8 Collectors (java.util.stream.Collectors)7 AggregateCall (org.apache.calcite.rel.core.AggregateCall)7