Search in sources :

Example 6 with SqlFunction

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

the class ExpressionsTest method testTruncate.

@Test
public void testTruncate() {
    final SqlFunction truncateFunction = new TruncateOperatorConversion().calciteOperator();
    testHelper.testExpression(truncateFunction, testHelper.makeInputRef("a"), DruidExpression.ofExpression(ColumnType.LONG, (args) -> "(cast(cast(" + args.get(0).getExpression() + " * 1,'long'),'double') / 1)", ImmutableList.of(DruidExpression.ofColumn(ColumnType.LONG, "a"))), 10.0);
    testHelper.testExpression(truncateFunction, testHelper.makeInputRef("x"), DruidExpression.ofExpression(ColumnType.FLOAT, (args) -> "(cast(cast(" + args.get(0).getExpression() + " * 1,'long'),'double') / 1)", ImmutableList.of(DruidExpression.ofColumn(ColumnType.FLOAT, "x"))), 2.0);
    testHelper.testExpression(truncateFunction, testHelper.makeInputRef("y"), DruidExpression.ofExpression(ColumnType.LONG, (args) -> "(cast(cast(" + args.get(0).getExpression() + " * 1,'long'),'double') / 1)", ImmutableList.of(DruidExpression.ofColumn(ColumnType.LONG, "y"))), 3.0);
    testHelper.testExpression(truncateFunction, testHelper.makeInputRef("z"), DruidExpression.ofExpression(ColumnType.FLOAT, (args) -> "(cast(cast(" + args.get(0).getExpression() + " * 1,'long'),'double') / 1)", ImmutableList.of(DruidExpression.ofColumn(ColumnType.FLOAT, "z"))), -2.0);
    testHelper.testExpressionString(truncateFunction, ImmutableList.of(testHelper.makeInputRef("x"), testHelper.makeLiteral(1)), DruidExpression.ofExpression(ColumnType.FLOAT, (args) -> "(cast(cast(" + args.get(0).getExpression() + " * 10.0,'long'),'double') / 10.0)", ImmutableList.of(DruidExpression.ofColumn(ColumnType.FLOAT, "x"), DruidExpression.ofLiteral(ColumnType.LONG, DruidExpression.numberLiteral(1)))), 2.2);
    testHelper.testExpressionString(truncateFunction, ImmutableList.of(testHelper.makeInputRef("z"), testHelper.makeLiteral(1)), DruidExpression.ofExpression(ColumnType.FLOAT, (args) -> "(cast(cast(" + args.get(0).getExpression() + " * 10.0,'long'),'double') / 10.0)", ImmutableList.of(DruidExpression.ofColumn(ColumnType.FLOAT, "z"), DruidExpression.ofLiteral(ColumnType.LONG, DruidExpression.numberLiteral(1)))), -2.2);
    testHelper.testExpressionString(truncateFunction, ImmutableList.of(testHelper.makeInputRef("b"), testHelper.makeLiteral(-1)), DruidExpression.ofExpression(ColumnType.LONG, (args) -> "(cast(cast(" + args.get(0).getExpression() + " * 0.1,'long'),'double') / 0.1)", ImmutableList.of(DruidExpression.ofColumn(ColumnType.LONG, "b"), DruidExpression.ofLiteral(ColumnType.LONG, DruidExpression.numberLiteral(-1)))), 20.0);
    testHelper.testExpressionString(truncateFunction, ImmutableList.of(testHelper.makeInputRef("z"), testHelper.makeLiteral(-1)), DruidExpression.ofExpression(ColumnType.FLOAT, (args) -> "(cast(cast(" + args.get(0).getExpression() + " * 0.1,'long'),'double') / 0.1)", ImmutableList.of(DruidExpression.ofColumn(ColumnType.FLOAT, "z"), DruidExpression.ofLiteral(ColumnType.LONG, DruidExpression.numberLiteral(-1)))), 0.0);
}
Also used : RPadOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.RPadOperatorConversion) SqlTrimFunction(org.apache.calcite.sql.fun.SqlTrimFunction) TimeUnit(org.apache.calcite.avatica.util.TimeUnit) ReverseOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.ReverseOperatorConversion) BigDecimal(java.math.BigDecimal) SearchQueryDimFilter(org.apache.druid.query.filter.SearchQueryDimFilter) TimeParseOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.TimeParseOperatorConversion) Map(java.util.Map) LeftOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.LeftOperatorConversion) RoundOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.RoundOperatorConversion) IAE(org.apache.druid.java.util.common.IAE) ContainsOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.ContainsOperatorConversion) TimeFloorOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.TimeFloorOperatorConversion) StringFormatOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.StringFormatOperatorConversion) DateTimes(org.apache.druid.java.util.common.DateTimes) RegexDimFilter(org.apache.druid.query.filter.RegexDimFilter) ImmutableMap(com.google.common.collect.ImmutableMap) RegexpExtractOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.RegexpExtractOperatorConversion) TestExprMacroTable(org.apache.druid.query.expression.TestExprMacroTable) RegexDimExtractionFn(org.apache.druid.query.extraction.RegexDimExtractionFn) TimeCeilOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.TimeCeilOperatorConversion) SqlStdOperatorTable(org.apache.calcite.sql.fun.SqlStdOperatorTable) TruncateOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.TruncateOperatorConversion) RegexpLikeOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.RegexpLikeOperatorConversion) RightOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.RightOperatorConversion) DateTruncOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.DateTruncOperatorConversion) RepeatOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.RepeatOperatorConversion) TimeUnitRange(org.apache.calcite.avatica.util.TimeUnitRange) ImmutableList(com.google.common.collect.ImmutableList) TimeExtractOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.TimeExtractOperatorConversion) ExpressionVirtualColumn(org.apache.druid.segment.virtual.ExpressionVirtualColumn) HumanReadableFormatOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.HumanReadableFormatOperatorConversion) Before(org.junit.Before) TimeShiftOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.TimeShiftOperatorConversion) SqlIntervalQualifier(org.apache.calcite.sql.SqlIntervalQualifier) SqlParserPos(org.apache.calcite.sql.parser.SqlParserPos) Period(org.joda.time.Period) SqlTypeName(org.apache.calcite.sql.type.SqlTypeName) TimeFormatOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.TimeFormatOperatorConversion) LPadOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.LPadOperatorConversion) Test(org.junit.Test) StrposOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.StrposOperatorConversion) SqlFunction(org.apache.calcite.sql.SqlFunction) NullHandling(org.apache.druid.common.config.NullHandling) RowSignature(org.apache.druid.segment.column.RowSignature) ParseLongOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.ParseLongOperatorConversion) ColumnType(org.apache.druid.segment.column.ColumnType) ContainsSearchQuerySpec(org.apache.druid.query.search.ContainsSearchQuerySpec) Collections(java.util.Collections) TruncateOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.TruncateOperatorConversion) SqlFunction(org.apache.calcite.sql.SqlFunction) Test(org.junit.Test)

Example 7 with SqlFunction

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

the class ExpressionsTest method testRoundWithInvalidSecondArgument.

@Test
public void testRoundWithInvalidSecondArgument() {
    final SqlFunction roundFunction = new RoundOperatorConversion().calciteOperator();
    expectException(IAE.class, "The second argument to the function[round] should be integer type but got the type: STRING");
    testHelper.testExpressionString(roundFunction, ImmutableList.of(testHelper.makeInputRef("x"), testHelper.makeLiteral("foo")), DruidExpression.ofExpression(ColumnType.FLOAT, DruidExpression.functionCall("round"), ImmutableList.of(DruidExpression.ofColumn(ColumnType.FLOAT, "x"), DruidExpression.ofStringLiteral("foo"))), "IAE Exception");
}
Also used : RoundOperatorConversion(org.apache.druid.sql.calcite.expression.builtin.RoundOperatorConversion) SqlFunction(org.apache.calcite.sql.SqlFunction) Test(org.junit.Test)

Example 8 with SqlFunction

use of org.apache.calcite.sql.SqlFunction in project hazelcast by hazelcast.

the class NamedOperandCheckerProgram method check.

public boolean check(HazelcastCallBinding callBinding, boolean throwOnFailure) {
    boolean res = true;
    SqlCall call = callBinding.getCall();
    SqlFunction operator = (SqlFunction) call.getOperator();
    for (int i = 0; i < call.operandCount(); i++) {
        SqlNode operand = call.operand(i);
        assert operand.getKind() == SqlKind.ARGUMENT_ASSIGNMENT;
        SqlIdentifier id = ((SqlCall) operand).operand(1);
        OperandChecker checker = findOperandChecker(id, operator);
        res &= checker.check(callBinding, false, i);
    }
    if (!res && throwOnFailure) {
        throw callBinding.newValidationSignatureError();
    }
    return res;
}
Also used : SqlCall(org.apache.calcite.sql.SqlCall) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlFunction(org.apache.calcite.sql.SqlFunction) SqlNode(org.apache.calcite.sql.SqlNode)

Example 9 with SqlFunction

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

the class HiveSubQueryRemoveRule method rewriteInExists.

private RexNode rewriteInExists(RexSubQuery e, Set<CorrelationId> variablesSet, RelOptUtil.Logic logic, RelBuilder builder, int offset, boolean isCorrScalarAgg) {
    // Most general case, where the left and right keys might have nulls, and
    // caller requires 3-valued logic return.
    // 
    // select e.deptno, e.deptno in (select deptno from emp)
    // 
    // becomes
    // 
    // select e.deptno,
    // case
    // when ct.c = 0 then false
    // when dt.i is not null then true
    // when e.deptno is null then null
    // when ct.ck < ct.c then null
    // else false
    // end
    // from e
    // left join (
    // (select count(*) as c, count(deptno) as ck from emp) as ct
    // cross join (select distinct deptno, true as i from emp)) as dt
    // on e.deptno = dt.deptno
    // 
    // If keys are not null we can remove "ct" and simplify to
    // 
    // select e.deptno,
    // case
    // when dt.i is not null then true
    // else false
    // end
    // from e
    // left join (select distinct deptno, true as i from emp) as dt
    // on e.deptno = dt.deptno
    // 
    // We could further simplify to
    // 
    // select e.deptno,
    // dt.i is not null
    // from e
    // left join (select distinct deptno, true as i from emp) as dt
    // on e.deptno = dt.deptno
    // 
    // but have not yet.
    // 
    // If the logic is TRUE we can just kill the record if the condition
    // evaluates to FALSE or UNKNOWN. Thus the query simplifies to an inner
    // join:
    // 
    // select e.deptno,
    // true
    // from e
    // inner join (select distinct deptno from emp) as dt
    // on e.deptno = dt.deptno
    // 
    final List<RexNode> fields = new ArrayList<>();
    if (e.getKind() == SqlKind.IN) {
        builder.push(e.rel);
        fields.addAll(builder.fields());
        // will produce wrong results (because we further rewrite such queries into JOIN)
        if (isCorrScalarAgg) {
            // returns single row/column
            builder.aggregate(builder.groupKey(), builder.count(false, "cnt_in"));
            if (!variablesSet.isEmpty()) {
                builder.join(JoinRelType.LEFT, builder.literal(true), variablesSet);
            } else {
                builder.join(JoinRelType.INNER, builder.literal(true), variablesSet);
            }
            SqlFunction inCountCheck = new SqlFunction("sq_count_check", SqlKind.OTHER_FUNCTION, ReturnTypes.BOOLEAN, InferTypes.RETURN_TYPE, OperandTypes.NUMERIC, SqlFunctionCategory.USER_DEFINED_FUNCTION);
            // we create FILTER (sq_count_check(count())) instead of PROJECT
            // because RelFieldTrimmer ends up getting rid of Project
            // since it is not used further up the tree.
            // sq_count_check returns true when subquery returns single row, else it fails
            builder.filter(// true here indicates that sq_count_check is for IN/NOT IN subqueries
            builder.call(inCountCheck, builder.field("cnt_in"), builder.literal(true)));
            offset = offset + 1;
            builder.push(e.rel);
        }
    } else if (e.getKind() == SqlKind.EXISTS && !variablesSet.isEmpty()) {
        // Query has 'exists' and correlation:
        // select * from web_sales ws1
        // where exists (select 1 from web_sales ws2 where ws1.ws_order_number = ws2.ws_order_number limit 1);
        // 
        // HiveRelDecorrelator will replace LogicalCorrelate with a SemiJoin. Hence the right hand side won't be
        // evaluated for every row coming from left and SortLimit cuts the right result set incorrectly. (HIVE-24199)
        builder.push(e.rel.accept(new HiveSortLimitRemover()));
    } else {
        // Query may has exists but no correlation
        // select * from web_sales ws1
        // where exists (select 1 from web_sales ws2 where ws2.ws_order_number = 2 limit 1);
        builder.push(e.rel);
    }
    boolean isCandidateForAntiJoin = false;
    // First, the cross join
    switch(logic) {
        case TRUE_FALSE_UNKNOWN:
        case UNKNOWN_AS_TRUE:
            // null keys we do not need to generate count(*), count(c)
            if (e.getKind() == SqlKind.EXISTS) {
                logic = RelOptUtil.Logic.TRUE_FALSE;
                if (conf.getBoolVar(HiveConf.ConfVars.HIVE_CONVERT_ANTI_JOIN)) {
                    // TODO : As of now anti join is first converted to left outer join
                    // and then converted to anti join.
                    // logic = RelOptUtil.Logic.FALSE;
                    isCandidateForAntiJoin = true;
                }
                break;
            }
            builder.aggregate(builder.groupKey(), builder.count(false, "c"), builder.aggregateCall(SqlStdOperatorTable.COUNT, false, null, "ck", builder.fields()));
            builder.as("ct");
            if (!variablesSet.isEmpty()) {
                // builder.join(JoinRelType.INNER, builder.literal(true), variablesSet);
                builder.join(JoinRelType.LEFT, builder.literal(true), variablesSet);
            } else {
                builder.join(JoinRelType.INNER, builder.literal(true), variablesSet);
            }
            offset += 2;
            builder.push(e.rel);
            break;
    }
    // Now the left join
    String trueLiteral = "literalTrue";
    switch(logic) {
        case TRUE:
        case FALSE:
            if (fields.isEmpty()) {
                if (logic == RelOptUtil.Logic.TRUE) {
                    builder.project(builder.alias(builder.literal(true), trueLiteral));
                } else {
                    builder.project(builder.alias(builder.literal(false), "literalFalse"));
                }
                if (!variablesSet.isEmpty() && (e.getKind() == SqlKind.EXISTS || e.getKind() == SqlKind.IN)) {
                    // since this is rewritting into semijoin
                    break;
                } else {
                    builder.aggregate(builder.groupKey(0));
                }
            } else {
                if (!variablesSet.isEmpty() && (e.getKind() == SqlKind.EXISTS || e.getKind() == SqlKind.IN)) {
                    // since this is rewritting into semijoin
                    break;
                } else {
                    builder.aggregate(builder.groupKey(fields));
                }
            }
            break;
        default:
            fields.add(builder.alias(builder.literal(true), trueLiteral));
            builder.project(fields);
            // later during semi/anti join processing at genMapGroupByForSemijoin.
            if (!isCandidateForAntiJoin || variablesSet.isEmpty()) {
                builder.distinct();
            }
    }
    builder.as("dt");
    final List<RexNode> conditions = new ArrayList<>();
    for (Pair<RexNode, RexNode> pair : Pair.zip(e.getOperands(), builder.fields())) {
        conditions.add(builder.equals(pair.left, RexUtil.shift(pair.right, offset)));
    }
    switch(logic) {
        case TRUE:
            builder.join(JoinRelType.SEMI, builder.and(conditions), variablesSet);
            return builder.literal(true);
        case FALSE:
            builder.join(JoinRelType.ANTI, builder.and(conditions), variablesSet);
            return builder.literal(false);
    }
    builder.join(JoinRelType.LEFT, builder.and(conditions), variablesSet);
    final List<RexNode> keyIsNulls = new ArrayList<>();
    for (RexNode operand : e.getOperands()) {
        if (operand.getType().isNullable()) {
            keyIsNulls.add(builder.isNull(operand));
        }
    }
    final ImmutableList.Builder<RexNode> operands = ImmutableList.builder();
    switch(logic) {
        case TRUE_FALSE_UNKNOWN:
        case UNKNOWN_AS_TRUE:
            operands.add(builder.equals(builder.field("ct", "c"), builder.literal(0)), builder.literal(false));
            // now that we are using LEFT OUTER JOIN to join inner count, count(*)
            // with outer table, we wouldn't be able to tell if count is zero
            // for inner table since inner join with correlated values will get rid
            // of all values where join cond is not true (i.e where actual inner table
            // will produce zero result). To  handle this case we need to check both
            // count is zero or count is null
            operands.add((builder.isNull(builder.field("ct", "c"))), builder.literal(false));
            break;
    }
    operands.add(builder.isNotNull(builder.field("dt", trueLiteral)), builder.literal(true));
    if (!keyIsNulls.isEmpty()) {
        // Calcite creates null literal with Null type here but
        // because HIVE doesn't support null type it is appropriately typed boolean
        operands.add(builder.or(keyIsNulls), e.rel.getCluster().getRexBuilder().makeNullLiteral(SqlTypeName.BOOLEAN));
    // we are creating filter here so should not be returning NULL.
    // Not sure why Calcite return NULL
    }
    RexNode b = builder.literal(true);
    switch(logic) {
        case TRUE_FALSE_UNKNOWN:
            b = e.rel.getCluster().getRexBuilder().makeNullLiteral(SqlTypeName.BOOLEAN);
        // fall through
        case UNKNOWN_AS_TRUE:
            operands.add(builder.call(SqlStdOperatorTable.LESS_THAN, builder.field("ct", "ck"), builder.field("ct", "c")), b);
            break;
    }
    operands.add(builder.literal(false));
    return builder.call(SqlStdOperatorTable.CASE, operands.build());
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) ArrayList(java.util.ArrayList) RexNode(org.apache.calcite.rex.RexNode) SqlFunction(org.apache.calcite.sql.SqlFunction)

Example 10 with SqlFunction

use of org.apache.calcite.sql.SqlFunction in project calcite by apache.

the class SqlValidatorImpl method handleUnresolvedFunction.

public CalciteException handleUnresolvedFunction(SqlCall call, SqlFunction unresolvedFunction, List<RelDataType> argTypes, List<String> argNames) {
    // For builtins, we can give a better error message
    final List<SqlOperator> overloads = new ArrayList<>();
    opTab.lookupOperatorOverloads(unresolvedFunction.getNameAsId(), null, SqlSyntax.FUNCTION, overloads);
    if (overloads.size() == 1) {
        SqlFunction fun = (SqlFunction) overloads.get(0);
        if ((fun.getSqlIdentifier() == null) && (fun.getSyntax() != SqlSyntax.FUNCTION_ID)) {
            final int expectedArgCount = fun.getOperandCountRange().getMin();
            throw newValidationError(call, RESOURCE.invalidArgCount(call.getOperator().getName(), expectedArgCount));
        }
    }
    AssignableOperandTypeChecker typeChecking = new AssignableOperandTypeChecker(argTypes, argNames);
    String signature = typeChecking.getAllowedSignatures(unresolvedFunction, unresolvedFunction.getName());
    throw newValidationError(call, RESOURCE.validatorUnknownFunction(signature));
}
Also used : AssignableOperandTypeChecker(org.apache.calcite.sql.type.AssignableOperandTypeChecker) SqlOperator(org.apache.calcite.sql.SqlOperator) ArrayList(java.util.ArrayList) BitString(org.apache.calcite.util.BitString) SqlFunction(org.apache.calcite.sql.SqlFunction)

Aggregations

SqlFunction (org.apache.calcite.sql.SqlFunction)57 SqlOperator (org.apache.calcite.sql.SqlOperator)26 ArrayList (java.util.ArrayList)13 RoundOperatorConversion (org.apache.druid.sql.calcite.expression.builtin.RoundOperatorConversion)12 Test (org.junit.Test)12 RexNode (org.apache.calcite.rex.RexNode)8 SqlCall (org.apache.calcite.sql.SqlCall)8 SqlIdentifier (org.apache.calcite.sql.SqlIdentifier)8 AssignableOperandTypeChecker (org.apache.calcite.sql.type.AssignableOperandTypeChecker)6 BitString (org.apache.calcite.util.BitString)6 ImmutableList (com.google.common.collect.ImmutableList)5 RelDataType (org.apache.calcite.rel.type.RelDataType)5 SqlBasicCall (org.apache.calcite.sql.SqlBasicCall)5 RexCall (org.apache.calcite.rex.RexCall)4 RexLiteral (org.apache.calcite.rex.RexLiteral)4 FunctionDefinition (org.apache.flink.table.functions.FunctionDefinition)4 ScalarFunctionDefinition (org.apache.flink.table.functions.ScalarFunctionDefinition)4 BigDecimal (java.math.BigDecimal)3 TimeUnitRange (org.apache.calcite.avatica.util.TimeUnitRange)3 SqlTypeName (org.apache.calcite.sql.type.SqlTypeName)3