Search in sources :

Example 1 with SqlValidatorScope

use of org.apache.calcite.sql.validate.SqlValidatorScope in project calcite by apache.

the class SqlSubstringFunction method checkOperandTypes.

public boolean checkOperandTypes(SqlCallBinding callBinding, boolean throwOnFailure) {
    SqlValidator validator = callBinding.getValidator();
    SqlValidatorScope scope = callBinding.getScope();
    final List<SqlNode> operands = callBinding.operands();
    int n = operands.size();
    assert (3 == n) || (2 == n);
    if (!OperandTypes.STRING.checkSingleOperandType(callBinding, operands.get(0), 0, throwOnFailure)) {
        return false;
    }
    if (2 == n) {
        if (!OperandTypes.NUMERIC.checkSingleOperandType(callBinding, operands.get(1), 0, throwOnFailure)) {
            return false;
        }
    } else {
        RelDataType t1 = validator.deriveType(scope, operands.get(1));
        RelDataType t2 = validator.deriveType(scope, operands.get(2));
        if (SqlTypeUtil.inCharFamily(t1)) {
            if (!OperandTypes.STRING.checkSingleOperandType(callBinding, operands.get(1), 0, throwOnFailure)) {
                return false;
            }
            if (!OperandTypes.STRING.checkSingleOperandType(callBinding, operands.get(2), 0, throwOnFailure)) {
                return false;
            }
            if (!SqlTypeUtil.isCharTypeComparable(callBinding, operands, throwOnFailure)) {
                return false;
            }
        } else {
            if (!OperandTypes.NUMERIC.checkSingleOperandType(callBinding, operands.get(1), 0, throwOnFailure)) {
                return false;
            }
            if (!OperandTypes.NUMERIC.checkSingleOperandType(callBinding, operands.get(2), 0, throwOnFailure)) {
                return false;
            }
        }
        if (!SqlTypeUtil.inSameFamily(t1, t2)) {
            if (throwOnFailure) {
                throw callBinding.newValidationSignatureError();
            }
            return false;
        }
    }
    return true;
}
Also used : SqlValidatorScope(org.apache.calcite.sql.validate.SqlValidatorScope) SqlValidator(org.apache.calcite.sql.validate.SqlValidator) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlNode(org.apache.calcite.sql.SqlNode)

Example 2 with SqlValidatorScope

use of org.apache.calcite.sql.validate.SqlValidatorScope in project calcite by apache.

the class SqlOperatorBaseTest method testArgumentBounds.

/**
 * Test that calls all operators with all possible argument types, and for
 * each type, with a set of tricky values.
 */
@Test
public void testArgumentBounds() {
    if (!CalciteAssert.ENABLE_SLOW) {
        return;
    }
    final SqlValidatorImpl validator = (SqlValidatorImpl) tester.getValidator();
    final SqlValidatorScope scope = validator.getEmptyScope();
    final RelDataTypeFactory typeFactory = validator.getTypeFactory();
    final Builder builder = new Builder(typeFactory);
    builder.add0(SqlTypeName.BOOLEAN, true, false);
    builder.add0(SqlTypeName.TINYINT, 0, 1, -3, Byte.MAX_VALUE, Byte.MIN_VALUE);
    builder.add0(SqlTypeName.SMALLINT, 0, 1, -4, Short.MAX_VALUE, Short.MIN_VALUE);
    builder.add0(SqlTypeName.INTEGER, 0, 1, -2, Integer.MIN_VALUE, Integer.MAX_VALUE);
    builder.add0(SqlTypeName.BIGINT, 0, 1, -5, Integer.MAX_VALUE, Long.MAX_VALUE, Long.MIN_VALUE);
    builder.add1(SqlTypeName.VARCHAR, 11, "", " ", "hello world");
    builder.add1(SqlTypeName.CHAR, 5, "", "e", "hello");
    builder.add0(SqlTypeName.TIMESTAMP, 0L, DateTimeUtils.MILLIS_PER_DAY);
    for (SqlOperator op : SqlStdOperatorTable.instance().getOperatorList()) {
        switch(op.getKind()) {
            // can't handle the flag argument
            case TRIM:
            case EXISTS:
                continue;
        }
        switch(op.getSyntax()) {
            case SPECIAL:
                continue;
        }
        final SqlOperandTypeChecker typeChecker = op.getOperandTypeChecker();
        if (typeChecker == null) {
            continue;
        }
        final SqlOperandCountRange range = typeChecker.getOperandCountRange();
        for (int n = range.getMin(), max = range.getMax(); n <= max; n++) {
            final List<List<ValueType>> argValues = Collections.nCopies(n, builder.values);
            for (final List<ValueType> args : Linq4j.product(argValues)) {
                SqlNodeList nodeList = new SqlNodeList(SqlParserPos.ZERO);
                int nullCount = 0;
                for (ValueType arg : args) {
                    if (arg.value == null) {
                        ++nullCount;
                    }
                    nodeList.add(arg.node);
                }
                final SqlCall call = op.createCall(nodeList);
                final SqlCallBinding binding = new SqlCallBinding(validator, scope, call);
                if (!typeChecker.checkOperandTypes(binding, false)) {
                    continue;
                }
                final SqlPrettyWriter writer = new SqlPrettyWriter(CalciteSqlDialect.DEFAULT);
                op.unparse(writer, call, 0, 0);
                final String s = writer.toSqlString().toString();
                if (s.startsWith("OVERLAY(") || s.contains(" / 0") || s.matches("MOD\\(.*, 0\\)")) {
                    continue;
                }
                final Strong.Policy policy = Strong.policy(op.kind);
                try {
                    if (nullCount > 0 && policy == Strong.Policy.ANY) {
                        tester.checkNull(s);
                    } else {
                        final String query;
                        if (op instanceof SqlAggFunction) {
                            if (op.requiresOrder()) {
                                query = "SELECT " + s + " OVER () FROM (VALUES (1))";
                            } else {
                                query = "SELECT " + s + " FROM (VALUES (1))";
                            }
                        } else {
                            query = SqlTesterImpl.buildQuery(s);
                        }
                        tester.check(query, SqlTests.ANY_TYPE_CHECKER, SqlTests.ANY_PARAMETER_CHECKER, SqlTests.ANY_RESULT_CHECKER);
                    }
                } catch (Error e) {
                    System.out.println(s + ": " + e.getMessage());
                    throw e;
                } catch (Exception e) {
                    System.out.println("Failed: " + s + ": " + e.getMessage());
                }
            }
        }
    }
}
Also used : SqlValidatorScope(org.apache.calcite.sql.validate.SqlValidatorScope) SqlOperator(org.apache.calcite.sql.SqlOperator) SqlCall(org.apache.calcite.sql.SqlCall) TimestampString(org.apache.calcite.util.TimestampString) SqlString(org.apache.calcite.sql.util.SqlString) SqlAggFunction(org.apache.calcite.sql.SqlAggFunction) Strong(org.apache.calcite.plan.Strong) SQLException(java.sql.SQLException) SqlOperandCountRange(org.apache.calcite.sql.SqlOperandCountRange) SqlValidatorImpl(org.apache.calcite.sql.validate.SqlValidatorImpl) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) SqlCallBinding(org.apache.calcite.sql.SqlCallBinding) SqlPrettyWriter(org.apache.calcite.sql.pretty.SqlPrettyWriter) SqlNodeList(org.apache.calcite.sql.SqlNodeList) SqlOperandTypeChecker(org.apache.calcite.sql.type.SqlOperandTypeChecker) List(java.util.List) ArrayList(java.util.ArrayList) SqlNodeList(org.apache.calcite.sql.SqlNodeList) SqlLimitsTest(org.apache.calcite.test.SqlLimitsTest) Test(org.junit.Test)

Example 3 with SqlValidatorScope

use of org.apache.calcite.sql.validate.SqlValidatorScope in project calcite by apache.

the class SqlToRelConverter method convertMatchRecognize.

protected void convertMatchRecognize(Blackboard bb, SqlCall call) {
    final SqlMatchRecognize matchRecognize = (SqlMatchRecognize) call;
    final SqlValidatorNamespace ns = validator.getNamespace(matchRecognize);
    final SqlValidatorScope scope = validator.getMatchRecognizeScope(matchRecognize);
    final Blackboard matchBb = createBlackboard(scope, null, false);
    final RelDataType rowType = ns.getRowType();
    // convert inner query, could be a table name or a derived table
    SqlNode expr = matchRecognize.getTableRef();
    convertFrom(matchBb, expr);
    final RelNode input = matchBb.root;
    // PARTITION BY
    final SqlNodeList partitionList = matchRecognize.getPartitionList();
    final List<RexNode> partitionKeys = new ArrayList<>();
    for (SqlNode partition : partitionList) {
        RexNode e = matchBb.convertExpression(partition);
        partitionKeys.add(e);
    }
    // ORDER BY
    final SqlNodeList orderList = matchRecognize.getOrderList();
    final List<RelFieldCollation> orderKeys = new ArrayList<>();
    for (SqlNode order : orderList) {
        final RelFieldCollation.Direction direction;
        switch(order.getKind()) {
            case DESCENDING:
                direction = RelFieldCollation.Direction.DESCENDING;
                order = ((SqlCall) order).operand(0);
                break;
            case NULLS_FIRST:
            case NULLS_LAST:
                throw new AssertionError();
            default:
                direction = RelFieldCollation.Direction.ASCENDING;
                break;
        }
        final RelFieldCollation.NullDirection nullDirection = validator.getDefaultNullCollation().last(desc(direction)) ? RelFieldCollation.NullDirection.LAST : RelFieldCollation.NullDirection.FIRST;
        RexNode e = matchBb.convertExpression(order);
        orderKeys.add(new RelFieldCollation(((RexInputRef) e).getIndex(), direction, nullDirection));
    }
    final RelCollation orders = cluster.traitSet().canonize(RelCollations.of(orderKeys));
    // convert pattern
    final Set<String> patternVarsSet = new HashSet<>();
    SqlNode pattern = matchRecognize.getPattern();
    final SqlBasicVisitor<RexNode> patternVarVisitor = new SqlBasicVisitor<RexNode>() {

        @Override
        public RexNode visit(SqlCall call) {
            List<SqlNode> operands = call.getOperandList();
            List<RexNode> newOperands = Lists.newArrayList();
            for (SqlNode node : operands) {
                newOperands.add(node.accept(this));
            }
            return rexBuilder.makeCall(validator.getUnknownType(), call.getOperator(), newOperands);
        }

        @Override
        public RexNode visit(SqlIdentifier id) {
            assert id.isSimple();
            patternVarsSet.add(id.getSimple());
            return rexBuilder.makeLiteral(id.getSimple());
        }

        @Override
        public RexNode visit(SqlLiteral literal) {
            if (literal instanceof SqlNumericLiteral) {
                return rexBuilder.makeExactLiteral(BigDecimal.valueOf(literal.intValue(true)));
            } else {
                return rexBuilder.makeLiteral(literal.booleanValue());
            }
        }
    };
    final RexNode patternNode = pattern.accept(patternVarVisitor);
    SqlLiteral interval = matchRecognize.getInterval();
    RexNode intervalNode = null;
    if (interval != null) {
        intervalNode = matchBb.convertLiteral(interval);
    }
    // convert subset
    final SqlNodeList subsets = matchRecognize.getSubsetList();
    final Map<String, TreeSet<String>> subsetMap = Maps.newHashMap();
    for (SqlNode node : subsets) {
        List<SqlNode> operands = ((SqlCall) node).getOperandList();
        SqlIdentifier left = (SqlIdentifier) operands.get(0);
        patternVarsSet.add(left.getSimple());
        SqlNodeList rights = (SqlNodeList) operands.get(1);
        final TreeSet<String> list = new TreeSet<String>();
        for (SqlNode right : rights) {
            assert right instanceof SqlIdentifier;
            list.add(((SqlIdentifier) right).getSimple());
        }
        subsetMap.put(left.getSimple(), list);
    }
    SqlNode afterMatch = matchRecognize.getAfter();
    if (afterMatch == null) {
        afterMatch = SqlMatchRecognize.AfterOption.SKIP_TO_NEXT_ROW.symbol(SqlParserPos.ZERO);
    }
    final RexNode after;
    if (afterMatch instanceof SqlCall) {
        List<SqlNode> operands = ((SqlCall) afterMatch).getOperandList();
        SqlOperator operator = ((SqlCall) afterMatch).getOperator();
        assert operands.size() == 1;
        SqlIdentifier id = (SqlIdentifier) operands.get(0);
        assert patternVarsSet.contains(id.getSimple()) : id.getSimple() + " not defined in pattern";
        RexNode rex = rexBuilder.makeLiteral(id.getSimple());
        after = rexBuilder.makeCall(validator.getUnknownType(), operator, ImmutableList.of(rex));
    } else {
        after = matchBb.convertExpression(afterMatch);
    }
    matchBb.setPatternVarRef(true);
    // convert measures
    final ImmutableMap.Builder<String, RexNode> measureNodes = ImmutableMap.builder();
    for (SqlNode measure : matchRecognize.getMeasureList()) {
        List<SqlNode> operands = ((SqlCall) measure).getOperandList();
        String alias = ((SqlIdentifier) operands.get(1)).getSimple();
        RexNode rex = matchBb.convertExpression(operands.get(0));
        measureNodes.put(alias, rex);
    }
    // convert definitions
    final ImmutableMap.Builder<String, RexNode> definitionNodes = ImmutableMap.builder();
    for (SqlNode def : matchRecognize.getPatternDefList()) {
        List<SqlNode> operands = ((SqlCall) def).getOperandList();
        String alias = ((SqlIdentifier) operands.get(1)).getSimple();
        RexNode rex = matchBb.convertExpression(operands.get(0));
        definitionNodes.put(alias, rex);
    }
    final SqlLiteral rowsPerMatch = matchRecognize.getRowsPerMatch();
    final boolean allRows = rowsPerMatch != null && rowsPerMatch.getValue() == SqlMatchRecognize.RowsPerMatchOption.ALL_ROWS;
    matchBb.setPatternVarRef(false);
    final RelFactories.MatchFactory factory = RelFactories.DEFAULT_MATCH_FACTORY;
    final RelNode rel = factory.createMatch(input, patternNode, rowType, matchRecognize.getStrictStart().booleanValue(), matchRecognize.getStrictEnd().booleanValue(), definitionNodes.build(), measureNodes.build(), after, subsetMap, allRows, partitionKeys, orders, intervalNode);
    bb.setRoot(rel, false);
}
Also used : SqlValidatorScope(org.apache.calcite.sql.validate.SqlValidatorScope) SqlOperator(org.apache.calcite.sql.SqlOperator) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) NlsString(org.apache.calcite.util.NlsString) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) TreeSet(java.util.TreeSet) SqlBasicVisitor(org.apache.calcite.sql.util.SqlBasicVisitor) RelFactories(org.apache.calcite.rel.core.RelFactories) SqlNode(org.apache.calcite.sql.SqlNode) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet) SqlCall(org.apache.calcite.sql.SqlCall) SqlMatchRecognize(org.apache.calcite.sql.SqlMatchRecognize) ImmutableMap(com.google.common.collect.ImmutableMap) RelCollation(org.apache.calcite.rel.RelCollation) RelNode(org.apache.calcite.rel.RelNode) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) SqlNodeList(org.apache.calcite.sql.SqlNodeList) RexInputRef(org.apache.calcite.rex.RexInputRef) SqlValidatorNamespace(org.apache.calcite.sql.validate.SqlValidatorNamespace) SqlLiteral(org.apache.calcite.sql.SqlLiteral) SqlNumericLiteral(org.apache.calcite.sql.SqlNumericLiteral) RexNode(org.apache.calcite.rex.RexNode)

Example 4 with SqlValidatorScope

use of org.apache.calcite.sql.validate.SqlValidatorScope in project calcite by apache.

the class SqlToRelConverter method convertSelect.

/**
 * Converts a SELECT statement's parse tree into a relational expression.
 */
public RelNode convertSelect(SqlSelect select, boolean top) {
    final SqlValidatorScope selectScope = validator.getWhereScope(select);
    final Blackboard bb = createBlackboard(selectScope, null, top);
    convertSelectImpl(bb, select);
    return bb.root;
}
Also used : SqlValidatorScope(org.apache.calcite.sql.validate.SqlValidatorScope)

Example 5 with SqlValidatorScope

use of org.apache.calcite.sql.validate.SqlValidatorScope in project calcite by apache.

the class SqlWindow method validate.

@Override
public void validate(SqlValidator validator, SqlValidatorScope scope) {
    // REVIEW
    SqlValidatorScope operandScope = scope;
    SqlIdentifier declName = this.declName;
    SqlIdentifier refName = this.refName;
    SqlNodeList partitionList = this.partitionList;
    SqlNodeList orderList = this.orderList;
    SqlLiteral isRows = this.isRows;
    SqlNode lowerBound = this.lowerBound;
    SqlNode upperBound = this.upperBound;
    SqlLiteral allowPartial = this.allowPartial;
    if (refName != null) {
        SqlWindow win = validator.resolveWindow(this, operandScope, false);
        partitionList = win.partitionList;
        orderList = win.orderList;
        isRows = win.isRows;
        lowerBound = win.lowerBound;
        upperBound = win.upperBound;
        allowPartial = win.allowPartial;
    }
    for (SqlNode partitionItem : partitionList) {
        try {
            partitionItem.accept(Util.OverFinder.INSTANCE);
        } catch (ControlFlowException e) {
            throw validator.newValidationError(this, RESOURCE.partitionbyShouldNotContainOver());
        }
        partitionItem.validateExpr(validator, operandScope);
    }
    for (SqlNode orderItem : orderList) {
        boolean savedColumnReferenceExpansion = validator.getColumnReferenceExpansion();
        validator.setColumnReferenceExpansion(false);
        try {
            orderItem.accept(Util.OverFinder.INSTANCE);
        } catch (ControlFlowException e) {
            throw validator.newValidationError(this, RESOURCE.orderbyShouldNotContainOver());
        }
        try {
            orderItem.validateExpr(validator, scope);
        } finally {
            validator.setColumnReferenceExpansion(savedColumnReferenceExpansion);
        }
    }
    // 6.10 rule 6a Function RANK & DENSE_RANK require ORDER BY clause
    if (orderList.size() == 0 && !SqlValidatorUtil.containsMonotonic(scope) && windowCall != null && windowCall.getOperator().requiresOrder()) {
        throw validator.newValidationError(this, RESOURCE.funcNeedsOrderBy());
    }
    // Run framing checks if there are any
    if (upperBound != null || lowerBound != null) {
        // 6.10 Rule 6a RANK & DENSE_RANK do not allow ROWS or RANGE
        if (windowCall != null && !windowCall.getOperator().allowsFraming()) {
            throw validator.newValidationError(isRows, RESOURCE.rankWithFrame());
        }
        SqlTypeFamily orderTypeFam = null;
        // SQL03 7.10 Rule 11a
        if (orderList.size() > 0) {
            // if order by is a compound list then range not allowed
            if (orderList.size() > 1 && !isRows()) {
                throw validator.newValidationError(isRows, RESOURCE.compoundOrderByProhibitsRange());
            }
            // get the type family for the sort key for Frame Boundary Val.
            RelDataType orderType = validator.deriveType(operandScope, orderList.get(0));
            orderTypeFam = orderType.getSqlTypeName().getFamily();
        } else {
            // sorted already
            if (!isRows() && !SqlValidatorUtil.containsMonotonic(scope)) {
                throw validator.newValidationError(this, RESOURCE.overMissingOrderBy());
            }
        }
        // Let the bounds validate themselves
        validateFrameBoundary(lowerBound, isRows(), orderTypeFam, validator, operandScope);
        validateFrameBoundary(upperBound, isRows(), orderTypeFam, validator, operandScope);
        // Validate across boundaries. 7.10 Rule 8 a-d
        checkSpecialLiterals(this, validator);
    } else if (orderList.size() == 0 && !SqlValidatorUtil.containsMonotonic(scope) && windowCall != null && windowCall.getOperator().requiresOrder()) {
        throw validator.newValidationError(this, RESOURCE.overMissingOrderBy());
    }
    if (!isRows() && !isAllowPartial()) {
        throw validator.newValidationError(allowPartial, RESOURCE.cannotUseDisallowPartialWithRange());
    }
}
Also used : SqlValidatorScope(org.apache.calcite.sql.validate.SqlValidatorScope) ControlFlowException(org.apache.calcite.util.ControlFlowException) SqlTypeFamily(org.apache.calcite.sql.type.SqlTypeFamily) RelDataType(org.apache.calcite.rel.type.RelDataType)

Aggregations

SqlValidatorScope (org.apache.calcite.sql.validate.SqlValidatorScope)20 RelDataType (org.apache.calcite.rel.type.RelDataType)12 SqlNode (org.apache.calcite.sql.SqlNode)10 ArrayList (java.util.ArrayList)7 SqlNodeList (org.apache.calcite.sql.SqlNodeList)6 SqlValidator (org.apache.calcite.sql.validate.SqlValidator)6 RelNode (org.apache.calcite.rel.RelNode)5 SqlCall (org.apache.calcite.sql.SqlCall)5 List (java.util.List)4 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)4 SqlIdentifier (org.apache.calcite.sql.SqlIdentifier)4 NlsString (org.apache.calcite.util.NlsString)4 RelDataTypeFactory (org.apache.calcite.rel.type.RelDataTypeFactory)3 RexNode (org.apache.calcite.rex.RexNode)3 SqlOperator (org.apache.calcite.sql.SqlOperator)3 SqlSelect (org.apache.calcite.sql.SqlSelect)3 ImmutableList (com.google.common.collect.ImmutableList)2 HazelcastSqlValidator (com.hazelcast.jet.sql.impl.validate.HazelcastSqlValidator)2 QueryDataTypeFamily (com.hazelcast.sql.impl.type.QueryDataTypeFamily)2 Consumer (java.util.function.Consumer)2