/** * Analyzes an expression in a GROUP BY clause. * * <p>It may be an expression, an empty list (), or a call to {@code GROUPING SETS}, {@code CUBE} * or {@code ROLLUP}. * * <p>Each group item produces a list of group sets, which are written to {@code topBuilder}. To * find the grouping sets of the query, we will take the cartesian product of the group sets. */ public static void analyzeGroupItem( SqlValidatorScope scope, List<SqlNode> groupExprs, Map<Integer, Integer> groupExprProjection, ImmutableList.Builder<ImmutableList<ImmutableBitSet>> topBuilder, SqlNode groupExpr) { final ImmutableList.Builder<ImmutableBitSet> builder; switch (groupExpr.getKind()) { case CUBE: case ROLLUP: // E.g. ROLLUP(a, (b, c)) becomes [{0}, {1, 2}] // then we roll up to [(0, 1, 2), (0), ()] -- note no (0, 1) List<ImmutableBitSet> bitSets = analyzeGroupTuple( scope, groupExprs, groupExprProjection, ((SqlCall) groupExpr).getOperandList()); switch (groupExpr.getKind()) { case ROLLUP: topBuilder.add(rollup(bitSets)); return; default: topBuilder.add(cube(bitSets)); return; } case OTHER: if (groupExpr instanceof SqlNodeList) { SqlNodeList list = (SqlNodeList) groupExpr; for (SqlNode node : list) { analyzeGroupItem(scope, groupExprs, groupExprProjection, topBuilder, node); } return; } // fall through case GROUPING_SETS: default: builder = ImmutableList.builder(); convertGroupSet(scope, groupExprs, groupExprProjection, builder, groupExpr); topBuilder.add(builder.build()); } }
/** Analyzes a GROUPING SETS item in a GROUP BY clause. */ private static void convertGroupSet( SqlValidatorScope scope, List<SqlNode> groupExprs, Map<Integer, Integer> groupExprProjection, ImmutableList.Builder<ImmutableBitSet> builder, SqlNode groupExpr) { switch (groupExpr.getKind()) { case GROUPING_SETS: final SqlCall call = (SqlCall) groupExpr; for (SqlNode node : call.getOperandList()) { convertGroupSet(scope, groupExprs, groupExprProjection, builder, node); } return; case ROW: final List<ImmutableBitSet> bitSets = analyzeGroupTuple( scope, groupExprs, groupExprProjection, ((SqlCall) groupExpr).getOperandList()); builder.add(ImmutableBitSet.union(bitSets)); return; default: builder.add(analyzeGroupExpr(scope, groupExprs, groupExprProjection, groupExpr)); return; } }