code: func (a *aggPushDownSolver) tryToPushDownAgg(aggFuncs []expression.AggregationFunction, gbyCols []*expression.Column, join *Join, childIdx int) LogicalPlan {
  	child := join.GetChildByIndex(childIdx).(LogicalPlan)
  	if a.allFirstRow(aggFuncs) {
  		return child
  	}
  	agg := a.makeNewAgg(aggFuncs, gbyCols)
  	child.SetParents(agg)
  	agg.SetChildren(child)
  	// If agg has no group-by item, it will return a default value, which may cause some bugs.
  	// So here we add a group-by item forcely.
  	if len(agg.GroupByItems) == 0 {
  		agg.GroupByItems = []expression.Expression{&expression.Constant{
  			Value:   types.NewDatum(0),
  			RetType: types.NewFieldType(mysql.TypeLong)}}
  	}
  	if (childIdx == 0 && join.JoinType == RightOuterJoin) || (childIdx == 1 && join.JoinType == LeftOuterJoin) {
  		var existsDefaultValues bool
  		join.DefaultValues, existsDefaultValues = a.getDefaultValues(agg)
  		if !existsDefaultValues {
  			return child
  		}
  	}
  	return agg
  }
docs: // tryToPushDownAgg tries to push down an aggregate function into a join path. If all aggFuncs are first row, we won't
  // process it temporarily. If not, We will add additional group by columns and first row functions. We make a new aggregation
  // operator.