Search in sources :

Example 6 with SqlCall

use of org.apache.calcite.sql.SqlCall 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 7 with SqlCall

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

the class SqlValidatorImpl method performUnconditionalRewrites.

/**
 * Performs expression rewrites which are always used unconditionally. These
 * rewrites massage the expression tree into a standard form so that the
 * rest of the validation logic can be simpler.
 *
 * @param node      expression to be rewritten
 * @param underFrom whether node appears directly under a FROM clause
 * @return rewritten expression
 */
protected SqlNode performUnconditionalRewrites(SqlNode node, boolean underFrom) {
    if (node == null) {
        return node;
    }
    SqlNode newOperand;
    // first transform operands and invoke generic call rewrite
    if (node instanceof SqlCall) {
        if (node instanceof SqlMerge) {
            validatingSqlMerge = true;
        }
        SqlCall call = (SqlCall) node;
        final SqlKind kind = call.getKind();
        final List<SqlNode> operands = call.getOperandList();
        for (int i = 0; i < operands.size(); i++) {
            SqlNode operand = operands.get(i);
            boolean childUnderFrom;
            if (kind == SqlKind.SELECT) {
                childUnderFrom = i == SqlSelect.FROM_OPERAND;
            } else if (kind == SqlKind.AS && (i == 0)) {
                // for an aliased expression, it is under FROM if
                // the AS expression is under FROM
                childUnderFrom = underFrom;
            } else {
                childUnderFrom = false;
            }
            newOperand = performUnconditionalRewrites(operand, childUnderFrom);
            if (newOperand != null && newOperand != operand) {
                call.setOperand(i, newOperand);
            }
        }
        if (call.getOperator() instanceof SqlUnresolvedFunction) {
            assert call instanceof SqlBasicCall;
            final SqlUnresolvedFunction function = (SqlUnresolvedFunction) call.getOperator();
            // This function hasn't been resolved yet.  Perform
            // a half-hearted resolution now in case it's a
            // builtin function requiring special casing.  If it's
            // not, we'll handle it later during overload resolution.
            final List<SqlOperator> overloads = new ArrayList<>();
            opTab.lookupOperatorOverloads(function.getNameAsId(), function.getFunctionType(), SqlSyntax.FUNCTION, overloads);
            if (overloads.size() == 1) {
                ((SqlBasicCall) call).setOperator(overloads.get(0));
            }
        }
        if (rewriteCalls) {
            node = call.getOperator().rewriteCall(this, call);
        }
    } else if (node instanceof SqlNodeList) {
        SqlNodeList list = (SqlNodeList) node;
        for (int i = 0, count = list.size(); i < count; i++) {
            SqlNode operand = list.get(i);
            newOperand = performUnconditionalRewrites(operand, false);
            if (newOperand != null) {
                list.getList().set(i, newOperand);
            }
        }
    }
    // now transform node itself
    final SqlKind kind = node.getKind();
    switch(kind) {
        case VALUES:
            // CHECKSTYLE: IGNORE 1
            if (underFrom || true) {
                // over and over
                return node;
            } else {
                final SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO);
                selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
                return new SqlSelect(node.getParserPosition(), null, selectList, node, null, null, null, null, null, null, null);
            }
        case ORDER_BY:
            {
                SqlOrderBy orderBy = (SqlOrderBy) node;
                handleOffsetFetch(orderBy.offset, orderBy.fetch);
                if (orderBy.query instanceof SqlSelect) {
                    SqlSelect select = (SqlSelect) orderBy.query;
                    // an order-sensitive function like RANK.
                    if (select.getOrderList() == null) {
                        // push ORDER BY into existing select
                        select.setOrderBy(orderBy.orderList);
                        select.setOffset(orderBy.offset);
                        select.setFetch(orderBy.fetch);
                        return select;
                    }
                }
                if (orderBy.query instanceof SqlWith && ((SqlWith) orderBy.query).body instanceof SqlSelect) {
                    SqlWith with = (SqlWith) orderBy.query;
                    SqlSelect select = (SqlSelect) with.body;
                    // an order-sensitive function like RANK.
                    if (select.getOrderList() == null) {
                        // push ORDER BY into existing select
                        select.setOrderBy(orderBy.orderList);
                        select.setOffset(orderBy.offset);
                        select.setFetch(orderBy.fetch);
                        return with;
                    }
                }
                final SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO);
                selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
                final SqlNodeList orderList;
                if (getInnerSelect(node) != null && isAggregate(getInnerSelect(node))) {
                    orderList = SqlNode.clone(orderBy.orderList);
                    // We assume that ORDER BY item is present in SELECT list.
                    for (int i = 0; i < orderList.size(); i++) {
                        SqlNode sqlNode = orderList.get(i);
                        SqlNodeList selectList2 = getInnerSelect(node).getSelectList();
                        for (Ord<SqlNode> sel : Ord.zip(selectList2)) {
                            if (stripAs(sel.e).equalsDeep(sqlNode, Litmus.IGNORE)) {
                                orderList.set(i, SqlLiteral.createExactNumeric(Integer.toString(sel.i + 1), SqlParserPos.ZERO));
                            }
                        }
                    }
                } else {
                    orderList = orderBy.orderList;
                }
                return new SqlSelect(SqlParserPos.ZERO, null, selectList, orderBy.query, null, null, null, null, orderList, orderBy.offset, orderBy.fetch);
            }
        case EXPLICIT_TABLE:
            {
                // (TABLE t) is equivalent to (SELECT * FROM t)
                SqlCall call = (SqlCall) node;
                final SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO);
                selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
                return new SqlSelect(SqlParserPos.ZERO, null, selectList, call.operand(0), null, null, null, null, null, null, null);
            }
        case DELETE:
            {
                SqlDelete call = (SqlDelete) node;
                SqlSelect select = createSourceSelectForDelete(call);
                call.setSourceSelect(select);
                break;
            }
        case UPDATE:
            {
                SqlUpdate call = (SqlUpdate) node;
                SqlSelect select = createSourceSelectForUpdate(call);
                call.setSourceSelect(select);
                // in which case leave it alone).
                if (!validatingSqlMerge) {
                    SqlNode selfJoinSrcExpr = getSelfJoinExprForUpdate(call.getTargetTable(), UPDATE_SRC_ALIAS);
                    if (selfJoinSrcExpr != null) {
                        node = rewriteUpdateToMerge(call, selfJoinSrcExpr);
                    }
                }
                break;
            }
        case MERGE:
            {
                SqlMerge call = (SqlMerge) node;
                rewriteMerge(call);
                break;
            }
    }
    return node;
}
Also used : Ord(org.apache.calcite.linq4j.Ord) SqlCall(org.apache.calcite.sql.SqlCall) SqlOperator(org.apache.calcite.sql.SqlOperator) SqlWith(org.apache.calcite.sql.SqlWith) ArrayList(java.util.ArrayList) SqlKind(org.apache.calcite.sql.SqlKind) SqlUpdate(org.apache.calcite.sql.SqlUpdate) SqlMerge(org.apache.calcite.sql.SqlMerge) SqlSelect(org.apache.calcite.sql.SqlSelect) SqlBasicCall(org.apache.calcite.sql.SqlBasicCall) SqlDelete(org.apache.calcite.sql.SqlDelete) SqlNodeList(org.apache.calcite.sql.SqlNodeList) SqlOrderBy(org.apache.calcite.sql.SqlOrderBy) SqlNode(org.apache.calcite.sql.SqlNode) SqlUnresolvedFunction(org.apache.calcite.sql.SqlUnresolvedFunction)

Example 8 with SqlCall

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

the class SqlValidatorImpl method getTableConstructorRowType.

/**
 * Returns null if there is no common type. E.g. if the rows have a
 * different number of columns.
 */
RelDataType getTableConstructorRowType(SqlCall values, SqlValidatorScope scope) {
    final List<SqlNode> rows = values.getOperandList();
    assert rows.size() >= 1;
    final List<RelDataType> rowTypes = new ArrayList<>();
    for (final SqlNode row : rows) {
        assert row.getKind() == SqlKind.ROW;
        SqlCall rowConstructor = (SqlCall) row;
        // REVIEW jvs 10-Sept-2003: Once we support single-row queries as
        // rows, need to infer aliases from there.
        final List<String> aliasList = new ArrayList<>();
        final List<RelDataType> typeList = new ArrayList<>();
        for (Ord<SqlNode> column : Ord.zip(rowConstructor.getOperandList())) {
            final String alias = deriveAlias(column.e, column.i);
            aliasList.add(alias);
            final RelDataType type = deriveType(scope, column.e);
            typeList.add(type);
        }
        rowTypes.add(typeFactory.createStructType(typeList, aliasList));
    }
    if (rows.size() == 1) {
        // leastRestrictive can handle all cases
        return rowTypes.get(0);
    }
    return typeFactory.leastRestrictive(rowTypes);
}
Also used : SqlCall(org.apache.calcite.sql.SqlCall) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) BitString(org.apache.calcite.util.BitString) SqlNode(org.apache.calcite.sql.SqlNode)

Example 9 with SqlCall

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

the class SqlValidatorImpl method navigationInMeasure.

private SqlNode navigationInMeasure(SqlNode node, boolean allRows) {
    final Set<String> prefix = node.accept(new PatternValidator(true));
    Util.discard(prefix);
    final List<SqlNode> ops = ((SqlCall) node).getOperandList();
    final SqlOperator defaultOp = allRows ? SqlStdOperatorTable.RUNNING : SqlStdOperatorTable.FINAL;
    final SqlNode op0 = ops.get(0);
    if (!isRunningOrFinal(op0.getKind()) || !allRows && op0.getKind() == SqlKind.RUNNING) {
        SqlNode newNode = defaultOp.createCall(SqlParserPos.ZERO, op0);
        node = SqlStdOperatorTable.AS.createCall(SqlParserPos.ZERO, newNode, ops.get(1));
    }
    node = new NavigationExpander().go(node);
    return node;
}
Also used : SqlCall(org.apache.calcite.sql.SqlCall) SqlOperator(org.apache.calcite.sql.SqlOperator) BitString(org.apache.calcite.util.BitString) SqlNode(org.apache.calcite.sql.SqlNode)

Example 10 with SqlCall

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

the class SqlValidatorImpl method deriveConstructorType.

public RelDataType deriveConstructorType(SqlValidatorScope scope, SqlCall call, SqlFunction unresolvedConstructor, SqlFunction resolvedConstructor, List<RelDataType> argTypes) {
    SqlIdentifier sqlIdentifier = unresolvedConstructor.getSqlIdentifier();
    assert sqlIdentifier != null;
    RelDataType type = catalogReader.getNamedType(sqlIdentifier);
    if (type == null) {
        // TODO jvs 12-Feb-2005:  proper type name formatting
        throw newValidationError(sqlIdentifier, RESOURCE.unknownDatatypeName(sqlIdentifier.toString()));
    }
    if (resolvedConstructor == null) {
        if (call.operandCount() > 0) {
            // no user-defined constructor could be found
            throw handleUnresolvedFunction(call, unresolvedConstructor, argTypes, null);
        }
    } else {
        SqlCall testCall = resolvedConstructor.createCall(call.getParserPosition(), call.getOperandList());
        RelDataType returnType = resolvedConstructor.validateOperands(this, scope, testCall);
        assert type == returnType;
    }
    if (shouldExpandIdentifiers()) {
        if (resolvedConstructor != null) {
            ((SqlBasicCall) call).setOperator(resolvedConstructor);
        } else {
            // fake a fully-qualified call to the default constructor
            ((SqlBasicCall) call).setOperator(new SqlFunction(type.getSqlIdentifier(), ReturnTypes.explicit(type), null, null, null, SqlFunctionCategory.USER_DEFINED_CONSTRUCTOR));
        }
    }
    return type;
}
Also used : SqlBasicCall(org.apache.calcite.sql.SqlBasicCall) SqlCall(org.apache.calcite.sql.SqlCall) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlFunction(org.apache.calcite.sql.SqlFunction)

Aggregations

SqlCall (org.apache.calcite.sql.SqlCall)108 SqlNode (org.apache.calcite.sql.SqlNode)81 SqlIdentifier (org.apache.calcite.sql.SqlIdentifier)32 SqlNodeList (org.apache.calcite.sql.SqlNodeList)32 RelDataType (org.apache.calcite.rel.type.RelDataType)30 SqlOperator (org.apache.calcite.sql.SqlOperator)26 BitString (org.apache.calcite.util.BitString)19 ArrayList (java.util.ArrayList)18 SqlSelect (org.apache.calcite.sql.SqlSelect)17 RexNode (org.apache.calcite.rex.RexNode)13 SqlBasicCall (org.apache.calcite.sql.SqlBasicCall)12 RelDataTypeFactory (org.apache.calcite.rel.type.RelDataTypeFactory)11 SqlLiteral (org.apache.calcite.sql.SqlLiteral)11 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)9 SqlKind (org.apache.calcite.sql.SqlKind)9 SqlParserPos (org.apache.calcite.sql.parser.SqlParserPos)9 List (java.util.List)8 SqlCallBinding (org.apache.calcite.sql.SqlCallBinding)8 Pair (org.apache.calcite.util.Pair)8 RelNode (org.apache.calcite.rel.RelNode)7