core/src/main/java/com/orientechnologies/orient/core/sql/executor/OSelectExecutionPlanner.java
private static void addGroupByExpressionsToProjections(QueryPlanningInfo info) {
    if (info.groupBy == null || info.groupBy.getItems() == null || info.groupBy.getItems().size() == 0) {
      return;
    }
    OGroupBy newGroupBy = new OGroupBy(-1);
    int i = 0;
    for (OExpression exp : info.groupBy.getItems()) {
      if (exp.isAggregate()) {
        throw new OCommandExecutionException("Cannot group by an aggregate function");
      }
      boolean found = false;
      if (info.preAggregateProjection != null) {
        for (String alias : info.preAggregateProjection.getAllAliases()) {
          //if it's a simple identifier and it's the same as one of the projections in the query,
          //then the projection itself is used for GROUP BY without recalculating; in all the other cases, it is evaluated separately
          if (alias.equals(exp.getDefaultAlias().getStringValue()) && exp.isBaseIdentifier()) {
            found = true;
            newGroupBy.getItems().add(exp);
            break;
          }
        }
      }
      if (!found) {
        OProjectionItem newItem = new OProjectionItem(-1);
        newItem.setExpression(exp);
        OIdentifier groupByAlias = new OIdentifier("_$$$GROUP_BY_ALIAS$$$_" + (i++));
        newItem.setAlias(groupByAlias);
        if (info.preAggregateProjection == null) {
          info.preAggregateProjection = new OProjection(-1);
        }
        if (info.preAggregateProjection.getItems() == null) {
          info.preAggregateProjection.setItems(new ArrayList<>());
        }
        info.preAggregateProjection.getItems().add(newItem);
        newGroupBy.getItems().add(new OExpression(groupByAlias));
      }

      info.groupBy = newGroupBy;
    }

  }
private static void addGroupByExpressionsToProjections(QueryPlanningInfo info) {
    if (info.groupBy == null || info.groupBy.getItems() == null || info.groupBy.getItems().size() == 0) {
      return;
    }
    OGroupBy newGroupBy = new OGroupBy(-1);
    int i = 0;
    for (OExpression exp : info.groupBy.getItems()) {
      if (exp.isAggregate()) {
        throw new OCommandExecutionException("Cannot group by an aggregate function");
      }
      boolean found = false;
      if (info.preAggregateProjection != null) {
        for (String alias : info.preAggregateProjection.getAllAliases()) {
          //if it's a simple identifier and it's the same as one of the projections in the query,
          //then the projection itself is used for GROUP BY without recalculating; in all the other cases, it is evaluated separately
          if (alias.equals(exp.getDefaultAlias().getStringValue()) && exp.isBaseIdentifier()) {
            found = true;
            newGroupBy.getItems().add(exp);
            break;
          }
        }
      }
      if (!found) {
        OProjectionItem newItem = new OProjectionItem(-1);
        newItem.setExpression(exp);
        OIdentifier groupByAlias = new OIdentifier("_$$$GROUP_BY_ALIAS$$$_" + (i++));
        newItem.setAlias(groupByAlias);
        if (info.preAggregateProjection == null) {
          info.preAggregateProjection = new OProjection(-1);
        }
        if (info.preAggregateProjection.getItems() == null) {
          info.preAggregateProjection.setItems(new ArrayList<>());
        }
        info.preAggregateProjection.getItems().add(newItem);
        newGroupBy.getItems().add(new OExpression(groupByAlias));
      }

      info.groupBy = newGroupBy;
    }

  }
private static void addGroupByExpressionsToProjections ( QueryPlanningInfo info ) { if ( info . groupBy == null || info . groupBy . getItems ( ) == null || info . groupBy . getItems ( ) . size ( ) == 0 ) { return ; } OGroupBy newGroupBy = new OGroupBy ( - 1 ) ; int i = 0 ; for ( OExpression exp : info . groupBy . getItems ( ) ) { if ( exp . isAggregate ( ) ) { throw new OCommandExecutionException ( "Cannot group by an aggregate function" ) ; } boolean found = false ; if ( info . preAggregateProjection != null ) { for ( String alias : info . preAggregateProjection . getAllAliases ( ) ) { //if it's a simple identifier and it's the same as one of the projections in the query, //then the projection itself is used for GROUP BY without recalculating; in all the other cases, it is evaluated separately if ( alias . equals ( exp . getDefaultAlias ( ) . getStringValue ( ) ) && exp . isBaseIdentifier ( ) ) { found = true ; newGroupBy . getItems ( ) . add ( exp ) ; break ; } } } if ( ! found ) { OProjectionItem newItem = new OProjectionItem ( - 1 ) ; newItem . setExpression ( exp ) ; OIdentifier groupByAlias = new OIdentifier ( "_$$$GROUP_BY_ALIAS$$$_" + ( i ++ ) ) ; newItem . setAlias ( groupByAlias ) ; if ( info . preAggregateProjection == null ) { info . preAggregateProjection = new OProjection ( - 1 ) ; } if ( info . preAggregateProjection . getItems ( ) == null ) { info . preAggregateProjection . setItems ( new ArrayList <> ( ) ) ; } info . preAggregateProjection . getItems ( ) . add ( newItem ) ; newGroupBy . getItems ( ) . add ( new OExpression ( groupByAlias ) ) ; } info . groupBy = newGroupBy ; } }
if GROUP BY is performed on an expression that is not explicitly in the pre-aggregate projections, then that expression has to
be put in the pre-aggregate (only here, in subsequent steps it's removed)
if GROUP BY is performed on an expression that is not explicitly in the pre - aggregate projections then that expression has to be put in the pre - aggregate ( only here in subsequent steps it s removed )