internal AggregationMFIdentifier(
     AggregationMultiFunctionStateKey aggregationStateKey,
     ExprAggregateLocalGroupByDesc optionalLocalGroupBy,
     int slot)
 {
     AggregationStateKey = aggregationStateKey;
     OptionalLocalGroupBy = optionalLocalGroupBy;
     Slot = slot;
 }
        private static AggregationGroupByLocalGroupDesc AnalyzeLocalGroupBy(
            IList<AggregationServiceAggExpressionDesc> aggregations,
            ExprNode[] groupByNodes,
            AggregationGroupByRollupDesc groupByRollupDesc,
            IntoTableSpec intoTableSpec)
        {
            bool hasOver = false;
            foreach (AggregationServiceAggExpressionDesc desc in aggregations)
            {
                if (desc.AggregationNode.OptionalLocalGroupBy != null)
                {
                    hasOver = true;
                    break;
                }
            }
            if (!hasOver)
            {
                return null;
            }
            if (groupByRollupDesc != null)
            {
                throw new ExprValidationException("Roll-up and group-by parameters cannot be combined");
            }
            if (intoTableSpec != null)
            {
                throw new ExprValidationException("Into-table and group-by parameters cannot be combined");
            }

            var partitions = new List<AggregationGroupByLocalGroupLevel>();
            foreach (AggregationServiceAggExpressionDesc desc in aggregations)
            {
                ExprAggregateLocalGroupByDesc localGroupBy = desc.AggregationNode.OptionalLocalGroupBy;

                IList<ExprNode> partitionExpressions = localGroupBy == null
                    ? groupByNodes
                    : localGroupBy.PartitionExpressions;
                IList<AggregationServiceAggExpressionDesc> found = FindPartition(partitions, partitionExpressions);
                if (found == null)
                {
                    found = new List<AggregationServiceAggExpressionDesc>();
                    var level = new AggregationGroupByLocalGroupLevel(partitionExpressions, found);
                    partitions.Add(level);
                }
                found.Add(desc);
            }

            // check single group-by partition and it matches the group-by clause
            if (partitions.Count == 1 &&
                ExprNodeUtility.DeepEqualsIgnoreDupAndOrder(partitions[0].PartitionExpr, groupByNodes))
            {
                return null;
            }
            return new AggregationGroupByLocalGroupDesc(aggregations.Count, partitions.ToArray());
        }
        private static AggregationMFIdentifier FindExisting(
            Deque<AggregationMFIdentifier> accessProviderSlots,
            AggregationMultiFunctionStateKey providerKey,
            ExprAggregateLocalGroupByDesc optionalOver,
            ExprNode[] groupByNodes)
        {
            foreach (var ident in accessProviderSlots) {
                if (!providerKey.Equals(ident.AggregationStateKey)) {
                    continue;
                }

                // if there is no local-group by, but there is group-by-clause, and the ident-over matches, use that
                if (optionalOver == null &&
                    groupByNodes.Length > 0 &&
                    ident.OptionalLocalGroupBy != null &&
                    ExprNodeUtilityCompare.DeepEqualsIgnoreDupAndOrder(
                        groupByNodes,
                        ident.OptionalLocalGroupBy.PartitionExpressions)) {
                    return ident;
                }

                if (optionalOver == null && ident.OptionalLocalGroupBy == null) {
                    return ident;
                }

                if (optionalOver != null &&
                    ident.OptionalLocalGroupBy != null &&
                    ExprNodeUtilityCompare.DeepEqualsIgnoreDupAndOrder(
                        optionalOver.PartitionExpressions,
                        ident.OptionalLocalGroupBy.PartitionExpressions)) {
                    return ident;
                }
            }

            return null;
        }
 internal static AggregationMFIdentifier FindExisting(IEnumerable <AggregationMFIdentifier> accessProviderSlots, AggregationStateKey providerKey, ExprAggregateLocalGroupByDesc optionalOver)
 {
     foreach (AggregationMFIdentifier ident in accessProviderSlots)
     {
         if (!Equals(providerKey, ident.AggregationStateKey))
         {
             continue;
         }
         if (optionalOver == null && ident.OptionalLocalGroupBy == null)
         {
             return(ident);
         }
         if (optionalOver != null &&
             ident.OptionalLocalGroupBy != null &&
             ExprNodeUtility.DeepEqualsIgnoreDupAndOrder(optionalOver.PartitionExpressions, ident.OptionalLocalGroupBy.PartitionExpressions))
         {
             return(ident);
         }
     }
     return(null);
 }