/** * Computes the cube of bit sets. * * <p>For example, <code>rollup({0}, {1})</code> returns <code>({0, 1}, {0}, {})</code>. * * <p>Bit sets are not necessarily singletons: <code>rollup({0, 2}, {3, 5})</code> returns <code> * ({0, 2, 3, 5}, {0, 2}, {})</code>. */ @VisibleForTesting public static ImmutableList<ImmutableBitSet> cube(List<ImmutableBitSet> bitSets) { // Given the bit sets [{1}, {2, 3}, {5}], // form the lists [[{1}, {}], [{2, 3}, {}], [{5}, {}]]. final Set<List<ImmutableBitSet>> builder = Sets.newLinkedHashSet(); for (ImmutableBitSet bitSet : bitSets) { builder.add(Arrays.asList(bitSet, ImmutableBitSet.of())); } Set<ImmutableBitSet> flattenedBitSets = Sets.newLinkedHashSet(); for (List<ImmutableBitSet> o : Linq4j.product(builder)) { flattenedBitSets.add(ImmutableBitSet.union(o)); } return ImmutableList.copyOf(flattenedBitSets); }
/** Analyzes a component of a tuple in a GROUPING SETS clause. */ private static ImmutableBitSet analyzeGroupExpr( SqlValidatorScope scope, List<SqlNode> groupExprs, Map<Integer, Integer> groupExprProjection, SqlNode groupExpr) { final SqlNode expandedGroupExpr = scope.getValidator().expand(groupExpr, scope); switch (expandedGroupExpr.getKind()) { case ROW: return ImmutableBitSet.union( analyzeGroupTuple( scope, groupExprs, groupExprProjection, ((SqlCall) expandedGroupExpr).getOperandList())); case OTHER: if (expandedGroupExpr instanceof SqlNodeList && ((SqlNodeList) expandedGroupExpr).size() == 0) { return ImmutableBitSet.of(); } } final int ref = lookupGroupExpr(groupExprs, groupExpr); if (expandedGroupExpr instanceof SqlIdentifier) { // SQL 2003 does not allow expressions of column references SqlIdentifier expr = (SqlIdentifier) expandedGroupExpr; // column references should be fully qualified. assert expr.names.size() == 2; String originalRelName = expr.names.get(0); String originalFieldName = expr.names.get(1); final SqlValidatorScope.ResolvedImpl resolved = new SqlValidatorScope.ResolvedImpl(); scope.resolve(ImmutableList.of(originalRelName), false, resolved); assert resolved.count() == 1; final SqlValidatorScope.Resolve resolve = resolved.only(); final SqlValidatorNamespace foundNs = resolve.namespace; final int childNamespaceIndex = resolve.path.steps().get(0).i; int namespaceOffset = 0; if (childNamespaceIndex > 0) { // If not the first child, need to figure out the width of // output types from all the preceding namespaces final SqlValidatorScope ancestorScope = resolve.scope; assert ancestorScope instanceof ListScope; List<SqlValidatorNamespace> children = ((ListScope) ancestorScope).getChildren(); for (int j = 0; j < childNamespaceIndex; j++) { namespaceOffset += children.get(j).getRowType().getFieldCount(); } } RelDataTypeField field = scope.getValidator().getCatalogReader().field(foundNs.getRowType(), originalFieldName); int origPos = namespaceOffset + field.getIndex(); groupExprProjection.put(origPos, ref); } return ImmutableBitSet.of(ref); }