code: static long calculateGrouping(Set<Integer> groupingSet, List<Integer> columns)
      {
          long grouping = (1L << columns.size()) - 1;
  
          for (int index = 0; index < columns.size(); index++) {
              int column = columns.get(index);
  
              if (groupingSet.contains(column)) {
                  // Leftmost argument to grouping() (i.e. when index = 0) corresponds to
                  // the most significant bit in the result. That is why we shift 1L starting
                  // from the columns.size() - 1 bit index.
                  grouping = grouping & ~(1L << (columns.size() - 1 - index));
              }
          }
  
          return grouping;
      }
docs: The grouping function is used in conjunction with GROUPING SETS, ROLLUP and CUBE to
  indicate which columns are present in that grouping.
  
  <p>The grouping function must be invoked with arguments that exactly match the columns
  referenced in the corresponding GROUPING SET, ROLLUP or CUBE clause at the associated
  query level. Those column arguments are not evaluated and instead the function is
  re-written with the arguments below.
  
  <p>To compute the resulting bit set for a particular row, bits are assigned to the
  argument columns with the rightmost column being the most significant bit. For a
  given grouping, a bit is set to 0 if the corresponding column is included in the
  grouping and 1 otherwise. For an example, see the SQL documentation for the
  function.
  
  @param columns The column arguments with which the function was invoked
  converted to ordinals with respect to the base table column ordering.
  @param groupingSet A collection containing the ordinals of the
  columns present in the grouping.
  @return A bit set converted to decimal indicating which columns are present in
  the grouping. If a column is NOT present in the grouping its corresponding
  bit is set to 1 and to 0 if the column is present in the grouping.