Search in sources :

Example 11 with SqlWindow

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

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

the class SqlValidatorImpl method resolveWindow.

public SqlWindow resolveWindow(SqlNode windowOrRef, SqlValidatorScope scope, boolean populateBounds) {
    SqlWindow window;
    if (windowOrRef instanceof SqlIdentifier) {
        window = getWindowByName((SqlIdentifier) windowOrRef, scope);
    } else {
        window = (SqlWindow) windowOrRef;
    }
    while (true) {
        final SqlIdentifier refId = window.getRefName();
        if (refId == null) {
            break;
        }
        final String refName = refId.getSimple();
        SqlWindow refWindow = scope.lookupWindow(refName);
        if (refWindow == null) {
            throw newValidationError(refId, RESOURCE.windowNotFound(refName));
        }
        window = window.overlay(refWindow, this);
    }
    if (populateBounds) {
        window.populateBounds();
    }
    return window;
}
Also used : SqlWindow(org.apache.calcite.sql.SqlWindow) BitString(org.apache.calcite.util.BitString) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier)

Example 13 with SqlWindow

use of org.apache.calcite.sql.SqlWindow in project drill by apache.

the class UnsupportedOperatorsVisitor method visit.

@Override
public SqlNode visit(SqlCall sqlCall) {
    // Inspect the window functions
    if (sqlCall instanceof SqlSelect) {
        SqlSelect sqlSelect = (SqlSelect) sqlCall;
        checkGrouping((sqlSelect));
        checkRollupCubeGrpSets(sqlSelect);
        for (SqlNode nodeInSelectList : sqlSelect.getSelectList()) {
            // enter the first operand of AS operator
            if (nodeInSelectList.getKind() == SqlKind.AS && (((SqlCall) nodeInSelectList).getOperandList().get(0).getKind() == SqlKind.OVER)) {
                nodeInSelectList = ((SqlCall) nodeInSelectList).getOperandList().get(0);
            }
            if (nodeInSelectList.getKind() == SqlKind.OVER) {
                // Throw exceptions if window functions are disabled
                if (!context.getOptions().getOption(ExecConstants.ENABLE_WINDOW_FUNCTIONS).bool_val) {
                    unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Window functions are disabled\n" + "See Apache Drill JIRA: DRILL-2559");
                    throw new UnsupportedOperationException();
                }
                // DRILL-3182, DRILL-3195
                SqlCall over = (SqlCall) nodeInSelectList;
                if (over.getOperandList().get(0) instanceof SqlCall) {
                    SqlCall function = (SqlCall) over.getOperandList().get(0);
                    // Window function with DISTINCT qualifier is temporarily disabled
                    if (function.getFunctionQuantifier() != null && function.getFunctionQuantifier().getValue() == SqlSelectKeyword.DISTINCT) {
                        unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "DISTINCT for window aggregate functions is not currently supported\n" + "See Apache Drill JIRA: DRILL-3182");
                        throw new UnsupportedOperationException();
                    }
                    // DRILL-3596: we only allow (<column-name>) or (<column-name>, 1)
                    final String functionName = function.getOperator().getName().toUpperCase();
                    if ("LEAD".equals(functionName) || "LAG".equals(functionName)) {
                        boolean supported = true;
                        if (function.operandCount() > 2) {
                            // we don't support more than 2 arguments
                            supported = false;
                        } else if (function.operandCount() == 2) {
                            SqlNode operand = function.operand(1);
                            if (operand instanceof SqlNumericLiteral) {
                                SqlNumericLiteral offsetLiteral = (SqlNumericLiteral) operand;
                                try {
                                    if (offsetLiteral.intValue(true) != 1) {
                                        // we don't support offset != 1
                                        supported = false;
                                    }
                                } catch (AssertionError e) {
                                    // we only support offset as an integer
                                    supported = false;
                                }
                            } else {
                                // we only support offset as a numeric literal
                                supported = false;
                            }
                        }
                        if (!supported) {
                            unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Function " + functionName + " only supports (<value expression>) or (<value expression>, 1)\n" + "See Apache DRILL JIRA: DRILL-3596");
                            throw new UnsupportedOperationException();
                        }
                    }
                }
            }
        }
    }
    // (i.e., BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
    if (sqlCall instanceof SqlWindow) {
        SqlWindow window = (SqlWindow) sqlCall;
        SqlNode lowerBound = window.getLowerBound();
        SqlNode upperBound = window.getUpperBound();
        // If no frame is specified
        // it is a default frame
        boolean isSupported = (lowerBound == null && upperBound == null);
        // RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
        if (window.getOrderList().size() != 0 && !window.isRows() && SqlWindow.isUnboundedPreceding(lowerBound) && (upperBound == null || SqlWindow.isCurrentRow(upperBound) || SqlWindow.isUnboundedFollowing(upperBound))) {
            isSupported = true;
        }
        // is supported with and without the ORDER BY clause
        if (window.isRows() && SqlWindow.isUnboundedPreceding(lowerBound) && (upperBound == null || SqlWindow.isCurrentRow(upperBound))) {
            isSupported = true;
        }
        // is supported with and without an ORDER BY clause
        if (!window.isRows() && SqlWindow.isCurrentRow(lowerBound) && SqlWindow.isCurrentRow(upperBound)) {
            isSupported = true;
        }
        // ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
        if (window.getOrderList().size() == 0 && SqlWindow.isUnboundedPreceding(lowerBound) && SqlWindow.isUnboundedFollowing(upperBound)) {
            isSupported = true;
        }
        if (!isSupported) {
            unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "This type of window frame is currently not supported \n" + "See Apache Drill JIRA: DRILL-3188");
            throw new UnsupportedOperationException();
        }
        // DRILL-3189: Disable DISALLOW PARTIAL
        if (!window.isAllowPartial()) {
            unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Disallowing partial windows is currently not supported \n" + "See Apache Drill JIRA: DRILL-3189");
            throw new UnsupportedOperationException();
        }
    }
    // Disable unsupported Intersect, Except
    if (sqlCall.getKind() == SqlKind.INTERSECT || sqlCall.getKind() == SqlKind.EXCEPT) {
        unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.RELATIONAL, sqlCall.getOperator().getName() + " is not supported\n" + "See Apache Drill JIRA: DRILL-1921");
        throw new UnsupportedOperationException();
    }
    // Disable unsupported JOINs
    if (sqlCall.getKind() == SqlKind.JOIN) {
        SqlJoin join = (SqlJoin) sqlCall;
        // Block Natural Join
        if (join.isNatural()) {
            unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.RELATIONAL, "NATURAL JOIN is not supported\n" + "See Apache Drill JIRA: DRILL-1986");
            throw new UnsupportedOperationException();
        }
    }
    // Disable UNNEST if the configuration disable it
    if (sqlCall.getKind() == SqlKind.UNNEST) {
        if (!context.getPlannerSettings().isUnnestLateralEnabled()) {
            unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.RELATIONAL, "Unnest is not enabled per configuration");
            throw new UnsupportedOperationException();
        }
    }
    // Disable Function
    for (String strOperator : disabledOperators) {
        if (sqlCall.getOperator().isName(strOperator, true)) {
            // true is passed to preserve previous behavior
            unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, sqlCall.getOperator().getName() + " is not supported\n" + "See Apache Drill JIRA: DRILL-2115");
            throw new UnsupportedOperationException();
        }
    }
    // Disable complex functions incorrect placement
    if (sqlCall instanceof SqlSelect) {
        SqlSelect sqlSelect = (SqlSelect) sqlCall;
        for (SqlNode nodeInSelectList : sqlSelect.getSelectList()) {
            if (checkDirExplorers(nodeInSelectList)) {
                unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Directory explorers " + dirExplorers + " functions are not supported in Select List\n" + "See Apache Drill JIRA: DRILL-3944");
                throw new UnsupportedOperationException();
            }
        }
        if (sqlSelect.hasWhere()) {
            if (checkDirExplorers(sqlSelect.getWhere()) && !context.getPlannerSettings().isConstantFoldingEnabled()) {
                unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Directory explorers " + dirExplorers + " functions can not be used " + "when " + PlannerSettings.CONSTANT_FOLDING.getOptionName() + " option is set to false\n" + "See Apache Drill JIRA: DRILL-3944");
                throw new UnsupportedOperationException();
            }
        }
        if (sqlSelect.hasOrderBy()) {
            for (SqlNode sqlNode : sqlSelect.getOrderList()) {
                if (containsFlatten(sqlNode)) {
                    unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Flatten function is not supported in Order By\n" + "See Apache Drill JIRA: DRILL-2181");
                    throw new UnsupportedOperationException();
                } else if (checkDirExplorers(sqlNode)) {
                    unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Directory explorers " + dirExplorers + " functions are not supported in Order By\n" + "See Apache Drill JIRA: DRILL-3944");
                    throw new UnsupportedOperationException();
                }
            }
        }
        if (sqlSelect.getGroup() != null) {
            for (SqlNode sqlNode : sqlSelect.getGroup()) {
                if (containsFlatten(sqlNode)) {
                    unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Flatten function is not supported in Group By\n" + "See Apache Drill JIRA: DRILL-2181");
                    throw new UnsupportedOperationException();
                } else if (checkDirExplorers(sqlNode)) {
                    unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Directory explorers " + dirExplorers + " functions are not supported in Group By\n" + "See Apache Drill JIRA: DRILL-3944");
                    throw new UnsupportedOperationException();
                }
            }
        }
        if (sqlSelect.isDistinct()) {
            for (SqlNode column : sqlSelect.getSelectList()) {
                if (column.getKind() == SqlKind.AS) {
                    if (containsFlatten(((SqlCall) column).getOperandList().get(0))) {
                        unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Flatten function is not supported in Distinct\n" + "See Apache Drill JIRA: DRILL-2181");
                        throw new UnsupportedOperationException();
                    }
                } else {
                    if (containsFlatten(column)) {
                        unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Flatten function is not supported in Distinct\n" + "See Apache Drill JIRA: DRILL-2181");
                        throw new UnsupportedOperationException();
                    }
                }
            }
        }
    }
    if (DrillCalciteWrapperUtility.extractSqlOperatorFromWrapper(sqlCall.getOperator()) instanceof SqlCountAggFunction) {
        for (SqlNode sqlNode : sqlCall.getOperandList()) {
            if (containsFlatten(sqlNode)) {
                unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Flatten function in aggregate functions is not supported\n" + "See Apache Drill JIRA: DRILL-2181");
                throw new UnsupportedOperationException();
            }
        }
    }
    return sqlCall.getOperator().acceptCall(this, sqlCall);
}
Also used : SqlSelect(org.apache.calcite.sql.SqlSelect) SqlCall(org.apache.calcite.sql.SqlCall) SqlJoin(org.apache.calcite.sql.SqlJoin) SqlWindow(org.apache.calcite.sql.SqlWindow) SqlNumericLiteral(org.apache.calcite.sql.SqlNumericLiteral) SqlCountAggFunction(org.apache.calcite.sql.fun.SqlCountAggFunction) SqlNode(org.apache.calcite.sql.SqlNode)

Aggregations

SqlWindow (org.apache.calcite.sql.SqlWindow)13 SqlIdentifier (org.apache.calcite.sql.SqlIdentifier)8 SqlNode (org.apache.calcite.sql.SqlNode)6 SqlNodeList (org.apache.calcite.sql.SqlNodeList)5 SqlCall (org.apache.calcite.sql.SqlCall)4 BitString (org.apache.calcite.util.BitString)4 ImmutableList (com.google.common.collect.ImmutableList)3 SqlSelect (org.apache.calcite.sql.SqlSelect)3 AbstractList (java.util.AbstractList)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 SqlJoin (org.apache.calcite.sql.SqlJoin)2 SqlNumericLiteral (org.apache.calcite.sql.SqlNumericLiteral)2 SqlCountAggFunction (org.apache.calcite.sql.fun.SqlCountAggFunction)2 ImmutableNullableList (org.apache.calcite.util.ImmutableNullableList)2 RexFieldCollation (org.apache.calcite.rex.RexFieldCollation)1 RexNode (org.apache.calcite.rex.RexNode)1 RexShuttle (org.apache.calcite.rex.RexShuttle)1 SqlKind (org.apache.calcite.sql.SqlKind)1 SqlLiteral (org.apache.calcite.sql.SqlLiteral)1