Create a new aggregating set expression using a backing LinkedHashSet

@param groupExpression values for this expression will be accumulated into a set
@param <E>
@param <F>
@return wrapper expression
515554
public static <E, F> GroupExpression<E, Set<F>> set(GroupExpression<E, F> groupExpression) {
        return new MixinGroupExpression<E, F, Set<F>>(groupExpression, GSet.createLinked(groupExpression));
    }
203239
public static <E> AbstractGroupExpression<E, List<E>> list(Expression<E> expression) {
        return new GList<E>(expression);
    }
628081
public static <K extends Comparable<? super K>, V, U> AbstractGroupExpression<Pair<K, V>, SortedMap<K, U>> sortedMap(Expression<K> key,
                                                                                                                         GroupExpression<V, U> value) {
        return sortedMap(new GOne<K>(key), value);
    }
140221
private void calculateIndexGroupByInfo(IndexScanPlanNode root,
            IndexGroupByInfo gbInfo) {
        String fromTableAlias = root.getTargetTableAlias();
        assert(fromTableAlias != null);

        Index index = root.getCatalogIndex();
        if ( ! IndexType.isScannable(index.getType())) {
            return;
        }

        ArrayList<AbstractExpression> bindings = new ArrayList<>();
        gbInfo.m_coveredGroupByColumns = calculateGroupbyColumnsCovered(
                index, fromTableAlias, bindings);
        gbInfo.m_canBeFullySerialized =
                (gbInfo.m_coveredGroupByColumns.size() ==
                m_parsedSelect.groupByColumns().size());
    }
272930
def groupBy(self, f, numPartitions=None, partitionFunc=portable_hash):
        
        return self.map(lambda x: (f(x), x)).groupByKey(numPartitions, partitionFunc)
1038562
public static <E> AbstractGroupExpression<E, Set<E>> set(Expression<E> expression) {
        return GSet.createLinked(expression);
    }
317751
public AggregationBuilder buildAggregation(KunderaQuery query, EntityMetadata entityMetadata, QueryBuilder filter)
    {
        SelectStatement selectStatement = query.getSelectStatement();

        // To apply filter for where clause
        AggregationBuilder aggregationBuilder = buildWhereAggregations(entityMetadata, filter);
        if (KunderaQueryUtils.hasGroupBy(query.getJpqlExpression()))
        {
            TermsBuilder termsBuilder = processGroupByClause(selectStatement.getGroupByClause(), entityMetadata, query);
            aggregationBuilder.subAggregation(termsBuilder);
        }
        else
        {
            if (KunderaQueryUtils.hasHaving(query.getJpqlExpression()))
            {
                logger.error("Identified having clause without group by, Throwing not supported operation Exception");
                throw new UnsupportedOperationException(
                        "Currently, Having clause without group by caluse is not supported.");
            }
            else
            {
                aggregationBuilder = (selectStatement != null) ? query.isAggregated() ? buildSelectAggregations(
                        aggregationBuilder, selectStatement, entityMetadata) : null : null;
            }
        }

        return aggregationBuilder;
    }
1101918
protected final Set<AggregatedGroupMapping> collectAllGroupsFromParams(
            Set<K> keys, AggregatedGroupMapping[] aggregatedGroupMappings) {
        final Builder<AggregatedGroupMapping> groupsBuilder =
                ImmutableSet.<AggregatedGroupMapping>builder();
        // Add all groups from the keyset
        for (K aggregationKey : keys) {
            groupsBuilder.add(aggregationKey.getAggregatedGroup());
        }
        // Add groups from parameters
        groupsBuilder.add(aggregatedGroupMappings);
        return groupsBuilder.build();
    }
313090
void resolveColumnReferencesInGroupBy() {
        if (unresolvedExpressions == null || unresolvedExpressions.isEmpty()) {
            return;
        }

        /**
         * Hsql HashSet does not work properly to remove duplicates, I doubt the hash
         * function or equal function on expression work properly or something else
         * is wrong. So use list
         *
         */
        // resolve GROUP BY columns/expressions
        HsqlList newUnresolvedExpressions = new ArrayListIdentity();

        int size = unresolvedExpressions.size();
        for (int i = 0; i < size; i++) {
            Object obj = unresolvedExpressions.get(i);
            newUnresolvedExpressions.add(obj);
            if (i + 1 < size && obj == unresolvedExpressions.get(i+1)) {
                // unresolvedExpressions is a public member that can be accessed from anywhere and
                // I (xin) am 90% percent sure about the hsql adds the unresolved expression twice
                // together for our targeted GROUP BY alias case.
                // so we want to skip the repeated expression also.
                // For other unresolved expression, it may differs.
                i += 1;
            }
            if (obj instanceof ExpressionColumn == false) {
                continue;
            }
            ExpressionColumn element = (ExpressionColumn) obj;
            if (element.tableName != null) {
                // this alias does not belong to any table
                continue;
            }

            // group by alias which is thought as an column
            if (element.getType() != OpTypes.COLUMN) {
                continue;
            }

            // find the unsolved expression in the groupBy list
            int k = indexLimitVisible;
            int endGroupbyIndex = indexLimitVisible + groupByColumnCount;
            for (; k < endGroupbyIndex; k++) {
                if (element == exprColumns[k]) {
                    break;
                }
            }
            if (k == endGroupbyIndex) {
                // not found in selected list
                continue;
            }
            assert(exprColumns[k].getType() == OpTypes.COLUMN);

            ExpressionColumn exprCol = (ExpressionColumn) exprColumns[k];
            String alias = exprCol.getColumnName();
            if (alias == null) {
                // we should not handle this case (group by constants)
                continue;
            }

            // Find it in the SELECT list.  We need to look at all
            // the select list elements to see if there are more
            // than one.
            int matchcount = 0;
            for (int j = 0; j < indexLimitVisible; j++) {
                Expression selectCol = exprColumns[j];
                if (selectCol.alias == null) {
                    // columns referenced by their alias must have an alias
                    continue;
                }
                if (alias.equals(selectCol.alias.name)) {
                    matchcount += 1;
                    // This may be an alias to an aggregate
                    // column.  But we'll find that later, so
                    // don't check for it here.
                    exprColumns[k] = selectCol;
                    exprColumnList.set(k, selectCol);
                    if (matchcount == 1) {
                        newUnresolvedExpressions.remove(element);
                    }
                }
            }
            if (matchcount > 1) {
                throw new HsqlException(String.format("Group by expression \"%s\" is ambiguous", alias), "", 0);
            }
        }
        unresolvedExpressions = newUnresolvedExpressions;
    }
1170979
public Query groupby(final Expression... groupbyColumns) {
        if (groupbyColumns == null) {
            return this;
        }

        return groupby(Arrays.asList(groupbyColumns));
    }
515432
public GroupedMap putAll(String group, Map<? extends String, ? extends String> m) {
		for (Entry<? extends String, ? extends String> entry : m.entrySet()) {
			this.put(group, entry.getKey(), entry.getValue());
		}
		return this;
	}
668664
public AggregationBuilder makeGroupAgg(Field field) throws SqlParseException {

        //zhongshu-comment script类型的MethodField
        if (field instanceof MethodField && field.getName().equals("script")) {
            MethodField methodField = (MethodField) field;
                /*
                TermsAggregationBuilder termsBuilder的样例：
                来自这条sql的group by子句的gg字段解析结果：
                select a,case when c='1' then 'haha' when c='2' then 'book' else 'hbhb' end as gg from tbl_a group by a,gg
                {
                    "gg":{ //aggs的名字就叫gg
                        "terms":{
                            "script":{
                                "source":"if((doc['c'].value=='1')){'haha'} else if((doc['c'].value=='2')){'book'} else {'hbhb'}",
                                "lang":"painless"
                            },
                            "size":10,
                            "min_doc_count":1,
                            "shard_min_doc_count":0,
                            "show_term_doc_count_error":false,
                            "order":[
                                {
                                    "_count":"desc"
                                },
                                {
                                    "_key":"asc"
                                }
                            ]
                        }
                    }
                }
             */
            TermsAggregationBuilder termsBuilder = AggregationBuilders.terms(methodField.getAlias()).script(new Script(methodField.getParams().get(1).value.toString()));

            //question 这里为什么要将这些信息加到groupMap中？
            groupMap.put(methodField.getAlias(), new KVValue("KEY", termsBuilder));

            return termsBuilder;
        }

        //zhongshu-comment filter类型的MethodField
        if (field instanceof MethodField) {

            MethodField methodField = (MethodField) field;
            if (methodField.getName().equals("filter")) {
                Map<String, Object> paramsAsMap = methodField.getParamsAsMap();
                Where where = (Where) paramsAsMap.get("where");
                return AggregationBuilders.filter(paramsAsMap.get("alias").toString(),
                        QueryMaker.explan(where));
            }
            return makeRangeGroup(methodField);
        } else {
            TermsAggregationBuilder termsBuilder = AggregationBuilders.terms(field.getName()).field(field.getName());
            groupMap.put(field.getName(), new KVValue("KEY", termsBuilder));
            return termsBuilder;
        }
    }
1158125
private Object getAggregatedResult(InternalAggregations internalAggs, String identifier, Expression exp)
    {
        switch (identifier)
        {
        case Expression.MIN:
            return (((InternalMin) internalAggs.get(exp.toParsedText())).getValue());

        case Expression.MAX:
            return (((InternalMax) internalAggs.get(exp.toParsedText())).getValue());

        case Expression.AVG:
            return (((InternalAvg) internalAggs.get(exp.toParsedText())).getValue());

        case Expression.SUM:
            return (((InternalSum) internalAggs.get(exp.toParsedText())).getValue());

        case Expression.COUNT:
            return (((InternalValueCount) internalAggs.get(exp.toParsedText())).getValue());
        }

        throw new KunderaException("No support for " + identifier + " aggregation.");
    }
1279570
@SuppressWarnings({ "unchecked", "rawtypes" })
    public Table aggregate(ListMultimap<String, AggregateFunction<?,?>> functions) {
        Preconditions.checkArgument(!getSlices().isEmpty());
        Table groupTable = summaryTableName(sourceTable);
        StringColumn groupColumn = StringColumn.create("Group");
        groupTable.addColumns(groupColumn);
        for (Map.Entry<String, Collection<AggregateFunction<?,?>>> entry : functions.asMap().entrySet()) {
            String columnName = entry.getKey();
            int functionCount = 0;
            for (AggregateFunction function : entry.getValue()) {
                String colName = aggregateColumnName(columnName, function.functionName());
                ColumnType type = function.returnType();
                Column resultColumn = type.create(colName);
                for (TableSlice subTable : getSlices()) {
                    Object result = function.summarize(subTable.column(columnName));
                    if (functionCount == 0) {
                        groupColumn.append(subTable.name());
                    }
                    if (result instanceof Number) {
                        Number number = (Number) result;
                        resultColumn.append(number.doubleValue());
                    } else {
                        resultColumn.append(result);
                    }
                }
                groupTable.addColumns(resultColumn);
                functionCount++;
            }
        }
        return splitGroupingColumn(groupTable);
    }
1297708
public static WithinGroup<Object> listagg(Expression<?> expr, String delimiter) {
        return new WithinGroup<Object>(Object.class, SQLOps.LISTAGG, expr, ConstantImpl.create(delimiter));
    }
271544
@Override
  public MtasTokenCollection createTokenCollection(Reader reader)
      throws MtasParserException, MtasConfigException {
    AtomicInteger position = new AtomicInteger(0);
    Integer unknownAncestors = 0;

    Map<String, Set<Integer>> idPositions = new HashMap<>();
    Map<String, Integer[]> idOffsets = new HashMap<>();

    Map<String, Map<Integer, Set<String>>> updateList = createUpdateList();
    Map<String, List<MtasParserObject>> currentList = createCurrentList();

    tokenCollection = new MtasTokenCollection();
    MtasTokenIdFactory mtasTokenIdFactory = new MtasTokenIdFactory();
    try (MtasBufferedReader br = new MtasBufferedReader(reader)) {
      String line;
      int currentOffset;
      int previousOffset = br.getPosition();
      MtasParserType tmpCurrentType;
      MtasParserObject currentObject;
      Pattern groupPattern = Pattern.compile("^<([^\\/>]+)\\/>$");
      Pattern groupStartPattern = Pattern
          .compile("^<([^>\\/\\s][^>\\s]*)(|\\s[^>]+)>$");
      Pattern groupEndPattern = Pattern.compile("^<\\/([^>\\s]+)>$");
      Pattern attributePattern = Pattern.compile("([^\\s]+)=\"([^\"]*)\"");
      while ((line = br.readLine()) != null) {
        currentOffset = br.getPosition();
        // group
        if (line.trim().matches("^<[^>]*>$")) {
          Matcher matcherGroupStart = groupStartPattern.matcher(line.trim());
          Matcher matcherGroupEnd = groupEndPattern.matcher(line.trim());
          Matcher matcherGroup = groupPattern.matcher(line.trim());
          if (matcherGroup.find()) {
            // full group, ignore
          } else if (matcherGroupStart.find()) {
            // start group
            // System.out.println("Start "+matcherGroupStart.group(1)+" -
            // "+matcherGroupStart.group(2));
            if ((currentList.get(MAPPING_TYPE_WORD).isEmpty())
                && (currentList.get(MAPPING_TYPE_RELATION).isEmpty())
                && (currentList.get(MAPPING_TYPE_GROUP_ANNOTATION).isEmpty())
                && (tmpCurrentType = groupTypes
                    .get(matcherGroupStart.group(1))) != null) {
              currentObject = new MtasParserObject(tmpCurrentType);
              currentObject.setUnknownAncestorNumber(unknownAncestors);
              currentObject.setRealOffsetStart(previousOffset);
              String attributeText = matcherGroupStart.group(2).trim();
              if (!attributeText.equals("")) {
                Matcher matcherAttribute = attributePattern
                    .matcher(attributeText);
                currentObject.objectAttributes = new HashMap<String, String>();
                while (matcherAttribute.find()) {
                  currentObject.objectAttributes.put(matcherAttribute.group(1),
                      matcherAttribute.group(2));
                }
              }
              if (!prevalidateObject(currentObject, currentList)) {
                unknownAncestors++;
              } else {
                currentList.get(MAPPING_TYPE_GROUP).add(currentObject);
                unknownAncestors = 0;
              }
            }
          } else if (matcherGroupEnd.find()) {
            // end group
            if (!currentList.get(MAPPING_TYPE_GROUP).isEmpty()) {
              if ((tmpCurrentType = groupTypes
                  .get(matcherGroupEnd.group(1))) != null) {
                currentObject = currentList.get(MAPPING_TYPE_GROUP)
                    .remove(currentList.get(MAPPING_TYPE_GROUP).size() - 1);
                assert unknownAncestors == 0 : "error in administration "
                    + currentObject.getType().getName();
                // ignore text: should not occur
                currentObject.setRealOffsetEnd(currentOffset - 1);
                idPositions.put(currentObject.getId(),
                    currentObject.getPositions());
                idOffsets.put(currentObject.getId(), currentObject.getOffset());
                currentObject.updateMappings(idPositions, idOffsets);
                unknownAncestors = currentObject.getUnknownAncestorNumber();
                computeMappingsFromObject(mtasTokenIdFactory, currentObject,
                    currentList, updateList);
              }
            }
          }
        } else {
          if ((currentList.get(MAPPING_TYPE_RELATION).isEmpty())
              && (currentList.get(MAPPING_TYPE_GROUP_ANNOTATION).isEmpty())
              && (currentList.get(MAPPING_TYPE_WORD).isEmpty())
              && (currentList.get(MAPPING_TYPE_WORD_ANNOTATION).isEmpty())
              && (wordType != null)) {
            // start word
            currentObject = new MtasParserObject(wordType);
            currentObject.setOffsetStart(previousOffset);
            currentObject.setRealOffsetStart(previousOffset);
            currentObject.setUnknownAncestorNumber(unknownAncestors);
            if (!prevalidateObject(currentObject, currentList)) {
              unknownAncestors++;
            } else {
              int p = position.getAndIncrement();
              currentObject.addPosition(p);
              currentList.get(MAPPING_TYPE_WORD).add(currentObject);
              unknownAncestors = 0;
            }
            if ((currentList.get(MAPPING_TYPE_RELATION).isEmpty())
                && (currentList.get(MAPPING_TYPE_GROUP_ANNOTATION).isEmpty())
                && (!currentList.get(MAPPING_TYPE_WORD).isEmpty())) {
              // start and finish word annotations
              String[] items = line.split("\t");
              for (int i = 0; i < items.length; i++) {
                if ((tmpCurrentType = wordAnnotationTypes.get(i)) != null) {
                  // start word annotation
                  currentObject = new MtasParserObject(tmpCurrentType);
                  currentObject.setRealOffsetStart(previousOffset);
                  currentObject.addPositions(currentList.get(MAPPING_TYPE_WORD)
                      .get((currentList.get(MAPPING_TYPE_WORD).size() - 1))
                      .getPositions());
                  currentObject.setUnknownAncestorNumber(unknownAncestors);
                  if (!prevalidateObject(currentObject, currentList)) {
                    unknownAncestors++;
                  } else {
                    currentList.get(MAPPING_TYPE_WORD_ANNOTATION)
                        .add(currentObject);
                    unknownAncestors = 0;
                  }
                  // finish word annotation
                  if (unknownAncestors > 0) {
                    unknownAncestors--;
                  } else {
                    currentObject = currentList
                        .get(MAPPING_TYPE_WORD_ANNOTATION).remove(
                            currentList.get(MAPPING_TYPE_WORD_ANNOTATION).size()
                                - 1);
                    assert unknownAncestors == 0 : "error in administration "
                        + currentObject.getType().getName();
                    currentObject.setText(items[i]);
                    currentObject.setRealOffsetEnd(currentOffset - 1);
                    idPositions.put(currentObject.getId(),
                        currentObject.getPositions());
                    idOffsets.put(currentObject.getId(),
                        currentObject.getOffset());
                    // offset always null, so update later with word (should be
                    // possible)
                    if ((currentObject.getId() != null)
                        && (!currentList.get(MAPPING_TYPE_WORD).isEmpty())) {
                      currentList.get(MAPPING_TYPE_WORD)
                          .get((currentList.get(MAPPING_TYPE_WORD).size() - 1))
                          .addUpdateableIdWithOffset(currentObject.getId());
                    }
                    currentObject.updateMappings(idPositions, idOffsets);
                    unknownAncestors = currentObject.getUnknownAncestorNumber();
                    computeMappingsFromObject(mtasTokenIdFactory, currentObject,
                        currentList, updateList);
                  }
                }
              }
            }
            // finish word
            if (unknownAncestors > 0) {
              unknownAncestors--;
            } else {
              currentObject = currentList.get(MAPPING_TYPE_WORD)
                  .remove(currentList.get(MAPPING_TYPE_WORD).size() - 1);
              assert unknownAncestors == 0 : "error in administration "
                  + currentObject.getType().getName();
              currentObject.setText(null);
              currentObject.setOffsetEnd(currentOffset - 1);
              currentObject.setRealOffsetEnd(currentOffset - 1);
              // update ancestor groups with position and offset
              for (MtasParserObject currentGroup : currentList
                  .get(MAPPING_TYPE_GROUP)) {
                currentGroup.addPositions(currentObject.getPositions());
                currentGroup.addOffsetStart(currentObject.getOffsetStart());
                currentGroup.addOffsetEnd(currentObject.getOffsetEnd());
              }
              idPositions.put(currentObject.getId(),
                  currentObject.getPositions());
              idOffsets.put(currentObject.getId(), currentObject.getOffset());
              currentObject.updateMappings(idPositions, idOffsets);
              unknownAncestors = currentObject.getUnknownAncestorNumber();
              computeMappingsFromObject(mtasTokenIdFactory, currentObject,
                  currentList, updateList);
            }
          }
        }
        previousOffset = br.getPosition();
      }
    } catch (IOException e) {
      log.debug(e);
      throw new MtasParserException(e.getMessage());
    }
    // update tokens with offset
    for (Entry<Integer, Set<String>> updateItem : updateList
        .get(UPDATE_TYPE_OFFSET).entrySet()) {
      for (String refId : updateItem.getValue()) {
        Integer[] refOffset = idOffsets.get(refId);
        if (refOffset != null) {
          tokenCollection.get(updateItem.getKey()).addOffset(refOffset[0],
              refOffset[1]);
        }
      }
    }
    // update tokens with position
    for (Entry<Integer, Set<String>> updateItem : updateList
        .get(UPDATE_TYPE_POSITION).entrySet()) {
      for (String refId : updateItem.getValue()) {
        MtasToken token = tokenCollection.get(updateItem.getKey());
        token.addPositions(idPositions.get(refId));
      }
    }
    // final check
    tokenCollection.check(autorepair, makeunique);
    return tokenCollection;
  }
74278
@Override
    public IGroupByDocumentQuery<T> groupBy(String fieldName, String... fieldNames) {
        _groupBy(fieldName, fieldNames);

        return new GroupByDocumentQuery<>(this);
    }