Search in sources :

Example 76 with SqlCall

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

the class PostgresqlSqlDialect method unparseCall.

@Override
public void unparseCall(SqlWriter writer, SqlCall call, int leftPrec, int rightPrec) {
    switch(call.getKind()) {
        case FLOOR:
            if (call.operandCount() != 2) {
                super.unparseCall(writer, call, leftPrec, rightPrec);
                return;
            }
            final SqlLiteral timeUnitNode = call.operand(1);
            final TimeUnitRange timeUnit = timeUnitNode.getValueAs(TimeUnitRange.class);
            SqlCall call2 = SqlFloorFunction.replaceTimeUnitOperand(call, timeUnit.name(), timeUnitNode.getParserPosition());
            SqlFloorFunction.unparseDatetimeFunction(writer, call2, "DATE_TRUNC", false);
            break;
        default:
            super.unparseCall(writer, call, leftPrec, rightPrec);
    }
}
Also used : SqlCall(org.apache.calcite.sql.SqlCall) TimeUnitRange(org.apache.calcite.avatica.util.TimeUnitRange) SqlLiteral(org.apache.calcite.sql.SqlLiteral)

Example 77 with SqlCall

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

the class SqlToRelConverter method convertOver.

private RexNode convertOver(Blackboard bb, SqlNode node) {
    SqlCall call = (SqlCall) node;
    SqlCall aggCall = call.operand(0);
    SqlNode windowOrRef = call.operand(1);
    final SqlWindow window = validator.resolveWindow(windowOrRef, bb.scope, true);
    // ROW_NUMBER() expects specific kind of framing.
    if (aggCall.getKind() == SqlKind.ROW_NUMBER) {
        window.setLowerBound(SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO));
        window.setUpperBound(SqlWindow.createCurrentRow(SqlParserPos.ZERO));
        window.setRows(SqlLiteral.createBoolean(true, SqlParserPos.ZERO));
    }
    final SqlNodeList partitionList = window.getPartitionList();
    final ImmutableList.Builder<RexNode> partitionKeys = ImmutableList.builder();
    for (SqlNode partition : partitionList) {
        partitionKeys.add(bb.convertExpression(partition));
    }
    RexNode lowerBound = bb.convertExpression(window.getLowerBound());
    RexNode upperBound = bb.convertExpression(window.getUpperBound());
    SqlNodeList orderList = window.getOrderList();
    if ((orderList.size() == 0) && !window.isRows()) {
        // A logical range requires an ORDER BY clause. Use the implicit
        // ordering of this relation. There must be one, otherwise it would
        // have failed validation.
        orderList = bb.scope.getOrderList();
        if (orderList == null) {
            throw new AssertionError("Relation should have sort key for implicit ORDER BY");
        }
    }
    final ImmutableList.Builder<RexFieldCollation> orderKeys = ImmutableList.builder();
    final Set<SqlKind> flags = EnumSet.noneOf(SqlKind.class);
    for (SqlNode order : orderList) {
        flags.clear();
        RexNode e = bb.convertSortExpression(order, flags);
        orderKeys.add(new RexFieldCollation(e, flags));
    }
    try {
        Preconditions.checkArgument(bb.window == null, "already in window agg mode");
        bb.window = window;
        RexNode rexAgg = exprConverter.convertCall(bb, aggCall);
        rexAgg = rexBuilder.ensureType(validator.getValidatedNodeType(call), rexAgg, false);
        // Walk over the tree and apply 'over' to all agg functions. This is
        // necessary because the returned expression is not necessarily a call
        // to an agg function. For example, AVG(x) becomes SUM(x) / COUNT(x).
        final SqlLiteral q = aggCall.getFunctionQuantifier();
        final boolean isDistinct = q != null && q.getValue() == SqlSelectKeyword.DISTINCT;
        final RexShuttle visitor = new HistogramShuttle(partitionKeys.build(), orderKeys.build(), RexWindowBound.create(window.getLowerBound(), lowerBound), RexWindowBound.create(window.getUpperBound(), upperBound), window, isDistinct);
        RexNode overNode = rexAgg.accept(visitor);
        return overNode;
    } finally {
        bb.window = null;
    }
}
Also used : RexShuttle(org.apache.calcite.rex.RexShuttle) SqlCall(org.apache.calcite.sql.SqlCall) ImmutableList(com.google.common.collect.ImmutableList) SqlKind(org.apache.calcite.sql.SqlKind) RexFieldCollation(org.apache.calcite.rex.RexFieldCollation) SqlWindow(org.apache.calcite.sql.SqlWindow) SqlNodeList(org.apache.calcite.sql.SqlNodeList) SqlLiteral(org.apache.calcite.sql.SqlLiteral) SqlNode(org.apache.calcite.sql.SqlNode) RexNode(org.apache.calcite.rex.RexNode)

Example 78 with SqlCall

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

the class SqlToRelConverter method pushDownNotForIn.

/**
 * Push down all the NOT logical operators into any IN/NOT IN operators.
 *
 * @param scope Scope where {@code sqlNode} occurs
 * @param sqlNode the root node from which to look for NOT operators
 * @return the transformed SqlNode representation with NOT pushed down.
 */
private static SqlNode pushDownNotForIn(SqlValidatorScope scope, SqlNode sqlNode) {
    if ((sqlNode instanceof SqlCall) && containsInOperator(sqlNode)) {
        SqlCall sqlCall = (SqlCall) sqlNode;
        if ((sqlCall.getOperator() == SqlStdOperatorTable.AND) || (sqlCall.getOperator() == SqlStdOperatorTable.OR)) {
            SqlNode[] sqlOperands = ((SqlBasicCall) sqlCall).operands;
            for (int i = 0; i < sqlOperands.length; i++) {
                sqlOperands[i] = pushDownNotForIn(scope, sqlOperands[i]);
            }
            return reg(scope, sqlNode);
        } else if (sqlCall.getOperator() == SqlStdOperatorTable.NOT) {
            SqlNode childNode = sqlCall.operand(0);
            assert childNode instanceof SqlCall;
            SqlBasicCall childSqlCall = (SqlBasicCall) childNode;
            if (childSqlCall.getOperator() == SqlStdOperatorTable.AND) {
                SqlNode[] andOperands = childSqlCall.getOperands();
                SqlNode[] orOperands = new SqlNode[andOperands.length];
                for (int i = 0; i < orOperands.length; i++) {
                    orOperands[i] = reg(scope, SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, andOperands[i]));
                }
                for (int i = 0; i < orOperands.length; i++) {
                    orOperands[i] = pushDownNotForIn(scope, orOperands[i]);
                }
                return reg(scope, SqlStdOperatorTable.OR.createCall(SqlParserPos.ZERO, orOperands[0], orOperands[1]));
            } else if (childSqlCall.getOperator() == SqlStdOperatorTable.OR) {
                SqlNode[] orOperands = childSqlCall.getOperands();
                SqlNode[] andOperands = new SqlNode[orOperands.length];
                for (int i = 0; i < andOperands.length; i++) {
                    andOperands[i] = reg(scope, SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, orOperands[i]));
                }
                for (int i = 0; i < andOperands.length; i++) {
                    andOperands[i] = pushDownNotForIn(scope, andOperands[i]);
                }
                return reg(scope, SqlStdOperatorTable.AND.createCall(SqlParserPos.ZERO, andOperands[0], andOperands[1]));
            } else if (childSqlCall.getOperator() == SqlStdOperatorTable.NOT) {
                SqlNode[] notOperands = childSqlCall.getOperands();
                assert notOperands.length == 1;
                return pushDownNotForIn(scope, notOperands[0]);
            } else if (childSqlCall.getOperator() instanceof SqlInOperator) {
                SqlNode[] inOperands = childSqlCall.getOperands();
                SqlInOperator inOp = (SqlInOperator) childSqlCall.getOperator();
                if (inOp.kind == SqlKind.NOT_IN) {
                    return reg(scope, SqlStdOperatorTable.IN.createCall(SqlParserPos.ZERO, inOperands[0], inOperands[1]));
                } else {
                    return reg(scope, SqlStdOperatorTable.NOT_IN.createCall(SqlParserPos.ZERO, inOperands[0], inOperands[1]));
                }
            } else {
                // (only considering AND, OR, NOT)
                return sqlNode;
            }
        } else {
            // (only considering AND, OR, NOT)
            return sqlNode;
        }
    } else {
        // tree rooted at sqlNode does not contain inOperator
        return sqlNode;
    }
}
Also used : SqlBasicCall(org.apache.calcite.sql.SqlBasicCall) SqlCall(org.apache.calcite.sql.SqlCall) SqlInOperator(org.apache.calcite.sql.fun.SqlInOperator) SqlNode(org.apache.calcite.sql.SqlNode)

Example 79 with SqlCall

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

the class SqlToRelConverter method convertMultisets.

private RelNode convertMultisets(final List<SqlNode> operands, Blackboard bb) {
    // NOTE: Wael 2/04/05: this implementation is not the most efficient in
    // terms of planning since it generates XOs that can be reduced.
    final List<Object> joinList = new ArrayList<>();
    List<SqlNode> lastList = new ArrayList<>();
    for (int i = 0; i < operands.size(); i++) {
        SqlNode operand = operands.get(i);
        if (!(operand instanceof SqlCall)) {
            lastList.add(operand);
            continue;
        }
        final SqlCall call = (SqlCall) operand;
        final RelNode input;
        switch(call.getKind()) {
            case MULTISET_VALUE_CONSTRUCTOR:
            case ARRAY_VALUE_CONSTRUCTOR:
                final SqlNodeList list = new SqlNodeList(call.getOperandList(), call.getParserPosition());
                CollectNamespace nss = (CollectNamespace) validator.getNamespace(call);
                Blackboard usedBb;
                if (null != nss) {
                    usedBb = createBlackboard(nss.getScope(), null, false);
                } else {
                    usedBb = createBlackboard(new ListScope(bb.scope) {

                        public SqlNode getNode() {
                            return call;
                        }
                    }, null, false);
                }
                RelDataType multisetType = validator.getValidatedNodeType(call);
                ((SqlValidatorImpl) validator).setValidatedNodeType(list, multisetType.getComponentType());
                input = convertQueryOrInList(usedBb, list, null);
                break;
            case MULTISET_QUERY_CONSTRUCTOR:
            case ARRAY_QUERY_CONSTRUCTOR:
                final RelRoot root = convertQuery(call.operand(0), false, true);
                input = root.rel;
                break;
            default:
                lastList.add(operand);
                continue;
        }
        if (lastList.size() > 0) {
            joinList.add(lastList);
        }
        lastList = new ArrayList<>();
        Collect collect = new Collect(cluster, cluster.traitSetOf(Convention.NONE), input, validator.deriveAlias(call, i));
        joinList.add(collect);
    }
    if (joinList.size() == 0) {
        joinList.add(lastList);
    }
    for (int i = 0; i < joinList.size(); i++) {
        Object o = joinList.get(i);
        if (o instanceof List) {
            @SuppressWarnings("unchecked") List<SqlNode> projectList = (List<SqlNode>) o;
            final List<RexNode> selectList = new ArrayList<>();
            final List<String> fieldNameList = new ArrayList<>();
            for (int j = 0; j < projectList.size(); j++) {
                SqlNode operand = projectList.get(j);
                selectList.add(bb.convertExpression(operand));
                // REVIEW angel 5-June-2005: Use deriveAliasFromOrdinal
                // instead of deriveAlias to match field names from
                // SqlRowOperator. Otherwise, get error   Type
                // 'RecordType(INTEGER EMPNO)' has no field 'EXPR$0' when
                // doing   select * from unnest(     select multiset[empno]
                // from sales.emps);
                fieldNameList.add(SqlUtil.deriveAliasFromOrdinal(j));
            }
            relBuilder.push(LogicalValues.createOneRow(cluster)).projectNamed(selectList, fieldNameList, true);
            joinList.set(i, relBuilder.build());
        }
    }
    RelNode ret = (RelNode) joinList.get(0);
    for (int i = 1; i < joinList.size(); i++) {
        RelNode relNode = (RelNode) joinList.get(i);
        ret = RelFactories.DEFAULT_JOIN_FACTORY.createJoin(ret, relNode, rexBuilder.makeLiteral(true), ImmutableSet.<CorrelationId>of(), JoinRelType.INNER, false);
    }
    return ret;
}
Also used : Collect(org.apache.calcite.rel.core.Collect) SqlCall(org.apache.calcite.sql.SqlCall) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) RelRoot(org.apache.calcite.rel.RelRoot) NlsString(org.apache.calcite.util.NlsString) SqlValidatorImpl(org.apache.calcite.sql.validate.SqlValidatorImpl) RelNode(org.apache.calcite.rel.RelNode) SqlNodeList(org.apache.calcite.sql.SqlNodeList) ArrayList(java.util.ArrayList) AbstractList(java.util.AbstractList) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) SqlNodeList(org.apache.calcite.sql.SqlNodeList) CorrelationId(org.apache.calcite.rel.core.CorrelationId) CollectNamespace(org.apache.calcite.sql.validate.CollectNamespace) ListScope(org.apache.calcite.sql.validate.ListScope) SqlNode(org.apache.calcite.sql.SqlNode) RexNode(org.apache.calcite.rex.RexNode)

Example 80 with SqlCall

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

the class SqlToRelConverter method convertCollectionTable.

protected void convertCollectionTable(Blackboard bb, SqlCall call) {
    final SqlOperator operator = call.getOperator();
    if (operator == SqlStdOperatorTable.TABLESAMPLE) {
        final String sampleName = SqlLiteral.unchain(call.operand(0)).getValueAs(String.class);
        datasetStack.push(sampleName);
        SqlCall cursorCall = call.operand(1);
        SqlNode query = cursorCall.operand(0);
        RelNode converted = convertQuery(query, false, false).rel;
        bb.setRoot(converted, false);
        datasetStack.pop();
        return;
    }
    replaceSubQueries(bb, call, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
    // Expand table macro if possible. It's more efficient than
    // LogicalTableFunctionScan.
    final SqlCallBinding callBinding = new SqlCallBinding(bb.scope.getValidator(), bb.scope, call);
    if (operator instanceof SqlUserDefinedTableMacro) {
        final SqlUserDefinedTableMacro udf = (SqlUserDefinedTableMacro) operator;
        final TranslatableTable table = udf.getTable(typeFactory, callBinding.operands());
        final RelDataType rowType = table.getRowType(typeFactory);
        RelOptTable relOptTable = RelOptTableImpl.create(null, rowType, table, udf.getNameAsId().names);
        RelNode converted = toRel(relOptTable);
        bb.setRoot(converted, true);
        return;
    }
    Type elementType;
    if (operator instanceof SqlUserDefinedTableFunction) {
        SqlUserDefinedTableFunction udtf = (SqlUserDefinedTableFunction) operator;
        elementType = udtf.getElementType(typeFactory, callBinding.operands());
    } else {
        elementType = null;
    }
    RexNode rexCall = bb.convertExpression(call);
    final List<RelNode> inputs = bb.retrieveCursors();
    Set<RelColumnMapping> columnMappings = getColumnMappings(operator);
    LogicalTableFunctionScan callRel = LogicalTableFunctionScan.create(cluster, inputs, rexCall, elementType, validator.getValidatedNodeType(call), columnMappings);
    bb.setRoot(callRel, true);
    afterTableFunction(bb, call, callRel);
}
Also used : SqlOperator(org.apache.calcite.sql.SqlOperator) SqlCall(org.apache.calcite.sql.SqlCall) SqlUserDefinedTableMacro(org.apache.calcite.sql.validate.SqlUserDefinedTableMacro) RelDataType(org.apache.calcite.rel.type.RelDataType) NlsString(org.apache.calcite.util.NlsString) LogicalTableFunctionScan(org.apache.calcite.rel.logical.LogicalTableFunctionScan) JoinType(org.apache.calcite.sql.JoinType) RelDataType(org.apache.calcite.rel.type.RelDataType) JoinRelType(org.apache.calcite.rel.core.JoinRelType) JoinConditionType(org.apache.calcite.sql.JoinConditionType) Type(java.lang.reflect.Type) SemiJoinType(org.apache.calcite.sql.SemiJoinType) SqlUserDefinedTableFunction(org.apache.calcite.sql.validate.SqlUserDefinedTableFunction) RelNode(org.apache.calcite.rel.RelNode) SqlCallBinding(org.apache.calcite.sql.SqlCallBinding) TranslatableTable(org.apache.calcite.schema.TranslatableTable) RelOptTable(org.apache.calcite.plan.RelOptTable) RelColumnMapping(org.apache.calcite.rel.metadata.RelColumnMapping) SqlNode(org.apache.calcite.sql.SqlNode) RexNode(org.apache.calcite.rex.RexNode)

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