Search in sources :

Example 1 with SelectScope

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

the class SqlAbstractGroupFunction method validateCall.

@Override
public void validateCall(SqlCall call, SqlValidator validator, SqlValidatorScope scope, SqlValidatorScope operandScope) {
    super.validateCall(call, validator, scope, operandScope);
    final SelectScope selectScope = SqlValidatorUtil.getEnclosingSelectScope(scope);
    assert selectScope != null;
    final SqlSelect select = selectScope.getNode();
    if (!validator.isAggregate(select)) {
        throw validator.newValidationError(call, Static.RESOURCE.groupingInAggregate(getName()));
    }
    final AggregatingSelectScope aggregatingSelectScope = SqlValidatorUtil.getEnclosingAggregateSelectScope(scope);
    if (aggregatingSelectScope == null) {
        // We're probably in the GROUP BY clause
        throw validator.newValidationError(call, Static.RESOURCE.groupingInWrongClause(getName()));
    }
    for (SqlNode operand : call.getOperandList()) {
        if (scope instanceof OrderByScope) {
            operand = validator.expandOrderExpr(select, operand);
        } else {
            operand = validator.expand(operand, scope);
        }
        if (!aggregatingSelectScope.resolved.get().isGroupingExpr(operand)) {
            throw validator.newValidationError(operand, Static.RESOURCE.groupingArgument(getName()));
        }
    }
}
Also used : SqlSelect(org.apache.calcite.sql.SqlSelect) SelectScope(org.apache.calcite.sql.validate.SelectScope) AggregatingSelectScope(org.apache.calcite.sql.validate.AggregatingSelectScope) OrderByScope(org.apache.calcite.sql.validate.OrderByScope) AggregatingSelectScope(org.apache.calcite.sql.validate.AggregatingSelectScope) SqlNode(org.apache.calcite.sql.SqlNode)

Example 2 with SelectScope

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

the class SqlCallBinding method getGroupCount.

// ~ Methods ----------------------------------------------------------------
@Override
public int getGroupCount() {
    final SelectScope selectScope = SqlValidatorUtil.getEnclosingSelectScope(scope);
    if (selectScope == null) {
        // Probably "VALUES expr". Treat same as "SELECT expr GROUP BY ()"
        return 0;
    }
    final SqlSelect select = selectScope.getNode();
    final SqlNodeList group = select.getGroup();
    if (group != null) {
        int n = 0;
        for (SqlNode groupItem : group) {
            if (!(groupItem instanceof SqlNodeList) || ((SqlNodeList) groupItem).size() != 0) {
                ++n;
            }
        }
        return n;
    }
    return validator.isAggregate(select) ? 0 : -1;
}
Also used : SelectScope(org.apache.calcite.sql.validate.SelectScope)

Example 3 with SelectScope

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

the class SqlToRelConverter method createAggImpl.

protected final void createAggImpl(Blackboard bb, final AggConverter aggConverter, SqlNodeList selectList, SqlNodeList groupList, SqlNode having, List<SqlNode> orderExprList) {
    // Find aggregate functions in SELECT and HAVING clause
    final AggregateFinder aggregateFinder = new AggregateFinder();
    selectList.accept(aggregateFinder);
    if (having != null) {
        having.accept(aggregateFinder);
    }
    // first replace the sub-queries inside the aggregates
    // because they will provide input rows to the aggregates.
    replaceSubQueries(bb, aggregateFinder.list, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
    // also replace sub-queries inside filters in the aggregates
    replaceSubQueries(bb, aggregateFinder.filterList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
    // If group-by clause is missing, pretend that it has zero elements.
    if (groupList == null) {
        groupList = SqlNodeList.EMPTY;
    }
    replaceSubQueries(bb, groupList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
    // register the group exprs
    // build a map to remember the projections from the top scope to the
    // output of the current root.
    // 
    // Calcite allows expressions, not just column references in
    // group by list. This is not SQL 2003 compliant, but hey.
    final AggregatingSelectScope scope = aggConverter.aggregatingSelectScope;
    final AggregatingSelectScope.Resolved r = scope.resolved.get();
    for (SqlNode groupExpr : r.groupExprList) {
        aggConverter.addGroupExpr(groupExpr);
    }
    final RexNode havingExpr;
    final List<Pair<RexNode, String>> projects = Lists.newArrayList();
    try {
        Preconditions.checkArgument(bb.agg == null, "already in agg mode");
        bb.agg = aggConverter;
        // convert the select and having expressions, so that the
        // agg converter knows which aggregations are required
        selectList.accept(aggConverter);
        // Assert we don't have dangling items left in the stack
        assert !aggConverter.inOver;
        for (SqlNode expr : orderExprList) {
            expr.accept(aggConverter);
            assert !aggConverter.inOver;
        }
        if (having != null) {
            having.accept(aggConverter);
            assert !aggConverter.inOver;
        }
        // compute inputs to the aggregator
        List<Pair<RexNode, String>> preExprs = aggConverter.getPreExprs();
        if (preExprs.size() == 0) {
            // Special case for COUNT(*), where we can end up with no inputs
            // at all.  The rest of the system doesn't like 0-tuples, so we
            // select a dummy constant here.
            final RexNode zero = rexBuilder.makeExactLiteral(BigDecimal.ZERO);
            preExprs = ImmutableList.of(Pair.of(zero, (String) null));
        }
        final RelNode inputRel = bb.root;
        // Project the expressions required by agg and having.
        bb.setRoot(relBuilder.push(inputRel).projectNamed(Pair.left(preExprs), Pair.right(preExprs), false).build(), false);
        bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
        // REVIEW jvs 31-Oct-2007:  doesn't the declaration of
        // monotonicity here assume sort-based aggregation at
        // the physical level?
        // Tell bb which of group columns are sorted.
        bb.columnMonotonicities.clear();
        for (SqlNode groupItem : groupList) {
            bb.columnMonotonicities.add(bb.scope.getMonotonicity(groupItem));
        }
        // Add the aggregator
        bb.setRoot(createAggregate(bb, r.groupSet, r.groupSets, aggConverter.getAggCalls()), false);
        bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
        // the replaced expressions
        if (having != null) {
            SqlNode newHaving = pushDownNotForIn(bb.scope, having);
            replaceSubQueries(bb, newHaving, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
            havingExpr = bb.convertExpression(newHaving);
        } else {
            havingExpr = relBuilder.literal(true);
        }
        // Now convert the other sub-queries in the select list.
        // This needs to be done separately from the sub-query inside
        // any aggregate in the select list, and after the aggregate rel
        // is allocated.
        replaceSubQueries(bb, selectList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
        // Now sub-queries in the entire select list have been converted.
        // Convert the select expressions to get the final list to be
        // projected.
        int k = 0;
        // For select expressions, use the field names previously assigned
        // by the validator. If we derive afresh, we might generate names
        // like "EXPR$2" that don't match the names generated by the
        // validator. This is especially the case when there are system
        // fields; system fields appear in the relnode's rowtype but do not
        // (yet) appear in the validator type.
        final SelectScope selectScope = SqlValidatorUtil.getEnclosingSelectScope(bb.scope);
        assert selectScope != null;
        final SqlValidatorNamespace selectNamespace = validator.getNamespace(selectScope.getNode());
        final List<String> names = selectNamespace.getRowType().getFieldNames();
        int sysFieldCount = selectList.size() - names.size();
        for (SqlNode expr : selectList) {
            projects.add(Pair.of(bb.convertExpression(expr), k < sysFieldCount ? validator.deriveAlias(expr, k++) : names.get(k++ - sysFieldCount)));
        }
        for (SqlNode expr : orderExprList) {
            projects.add(Pair.of(bb.convertExpression(expr), validator.deriveAlias(expr, k++)));
        }
    } finally {
        bb.agg = null;
    }
    // implement HAVING (we have already checked that it is non-trivial)
    relBuilder.push(bb.root);
    if (havingExpr != null) {
        relBuilder.filter(havingExpr);
    }
    // implement the SELECT list
    relBuilder.project(Pair.left(projects), Pair.right(projects)).rename(Pair.right(projects));
    bb.setRoot(relBuilder.build(), false);
    // Tell bb which of group columns are sorted.
    bb.columnMonotonicities.clear();
    for (SqlNode selectItem : selectList) {
        bb.columnMonotonicities.add(bb.scope.getMonotonicity(selectItem));
    }
}
Also used : SelectScope(org.apache.calcite.sql.validate.SelectScope) AggregatingSelectScope(org.apache.calcite.sql.validate.AggregatingSelectScope) NlsString(org.apache.calcite.util.NlsString) RelNode(org.apache.calcite.rel.RelNode) SqlValidatorNamespace(org.apache.calcite.sql.validate.SqlValidatorNamespace) AggregatingSelectScope(org.apache.calcite.sql.validate.AggregatingSelectScope) SqlNode(org.apache.calcite.sql.SqlNode) RexNode(org.apache.calcite.rex.RexNode) Pair(org.apache.calcite.util.Pair)

Example 4 with SelectScope

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

the class SqlToRelConverter method convertOrderItem.

protected RelFieldCollation convertOrderItem(SqlSelect select, SqlNode orderItem, List<SqlNode> extraExprs, RelFieldCollation.Direction direction, RelFieldCollation.NullDirection nullDirection) {
    assert select != null;
    // Handle DESC keyword, e.g. 'select a, b from t order by a desc'.
    switch(orderItem.getKind()) {
        case DESCENDING:
            return convertOrderItem(select, ((SqlCall) orderItem).operand(0), extraExprs, RelFieldCollation.Direction.DESCENDING, nullDirection);
        case NULLS_FIRST:
            return convertOrderItem(select, ((SqlCall) orderItem).operand(0), extraExprs, direction, RelFieldCollation.NullDirection.FIRST);
        case NULLS_LAST:
            return convertOrderItem(select, ((SqlCall) orderItem).operand(0), extraExprs, direction, RelFieldCollation.NullDirection.LAST);
    }
    SqlNode converted = validator.expandOrderExpr(select, orderItem);
    switch(nullDirection) {
        case UNSPECIFIED:
            nullDirection = validator.getDefaultNullCollation().last(desc(direction)) ? RelFieldCollation.NullDirection.LAST : RelFieldCollation.NullDirection.FIRST;
    }
    // Scan the select list and order exprs for an identical expression.
    final SelectScope selectScope = validator.getRawSelectScope(select);
    int ordinal = -1;
    for (SqlNode selectItem : selectScope.getExpandedSelectList()) {
        ++ordinal;
        if (converted.equalsDeep(stripAs(selectItem), Litmus.IGNORE)) {
            return new RelFieldCollation(ordinal, direction, nullDirection);
        }
    }
    for (SqlNode extraExpr : extraExprs) {
        ++ordinal;
        if (converted.equalsDeep(extraExpr, Litmus.IGNORE)) {
            return new RelFieldCollation(ordinal, direction, nullDirection);
        }
    }
    // TODO:  handle collation sequence
    // TODO: flag expressions as non-standard
    extraExprs.add(converted);
    return new RelFieldCollation(ordinal + 1, direction, nullDirection);
}
Also used : SelectScope(org.apache.calcite.sql.validate.SelectScope) AggregatingSelectScope(org.apache.calcite.sql.validate.AggregatingSelectScope) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) SqlNode(org.apache.calcite.sql.SqlNode)

Aggregations

SelectScope (org.apache.calcite.sql.validate.SelectScope)4 SqlNode (org.apache.calcite.sql.SqlNode)3 AggregatingSelectScope (org.apache.calcite.sql.validate.AggregatingSelectScope)3 RelFieldCollation (org.apache.calcite.rel.RelFieldCollation)1 RelNode (org.apache.calcite.rel.RelNode)1 RexNode (org.apache.calcite.rex.RexNode)1 SqlSelect (org.apache.calcite.sql.SqlSelect)1 OrderByScope (org.apache.calcite.sql.validate.OrderByScope)1 SqlValidatorNamespace (org.apache.calcite.sql.validate.SqlValidatorNamespace)1 NlsString (org.apache.calcite.util.NlsString)1 Pair (org.apache.calcite.util.Pair)1