/// <summary>
 ///     Ctor.
 /// </summary>
 /// <param name="aggregationNode">expression</param>
 /// <param name="factory">method factory</param>
 public AggregationServiceAggExpressionDesc(
     ExprAggregateNode aggregationNode,
     AggregationForgeFactory factory)
 {
     AggregationNode = aggregationNode;
     Factory = factory;
 }
        /// <summary>
        ///     Add an equivalent aggregation function node
        /// </summary>
        /// <param name="aggNodeToAdd">node to add</param>
        public void AddEquivalent(ExprAggregateNode aggNodeToAdd)
        {
            if (EquivalentNodes == null) {
                EquivalentNodes = new List<ExprAggregateNode>();
            }

            EquivalentNodes.Add(aggNodeToAdd);
        }
Exemplo n.º 3
0
        public override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
        {
            if (!(node is ExprAvedevNode)) {
                return false;
            }

            return true;
        }
Exemplo n.º 4
0
        public override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
        {
            if (node is ExprMinMaxAggrNode other) {
                return other.MinMaxTypeEnum == MinMaxTypeEnum && other.IsEver == IsEver;
            }

            return false;
        }
Exemplo n.º 5
0
        protected override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
        {
            if (!(node is ExprMedianNode))
            {
                return(false);
            }

            return(true);
        }
Exemplo n.º 6
0
        public override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
        {
            if (!(node is ExprFirstLastEverNode)) {
                return false;
            }

            var other = (ExprFirstLastEverNode) node;
            return other.IsFirst == IsFirst;
        }
Exemplo n.º 7
0
        protected override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
        {
            if (node is ExprPlugInAggNode other)
            {
                return(other.AggregationFunctionName == AggregationFunctionName);
            }

            return(false);
        }
Exemplo n.º 8
0
        protected override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
        {
            var other = node as ExprMinMaxAggrNode;

            if (other == null)
            {
                return(false);
            }
            return(other._minMaxTypeEnum == this._minMaxTypeEnum && other._isEver == this._isEver);
        }
Exemplo n.º 9
0
        protected override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
        {
            if (node is ExprMinMaxAggrNode other)
            {
                return(other._minMaxTypeEnum == _minMaxTypeEnum &&
                       other._isEver == _isEver);
            }

            return(false);
        }
Exemplo n.º 10
0
 public TableColumnDescAgg(
     int positionInDeclaration,
     string columnName,
     ExprAggregateNode aggregation,
     EventType optionalAssociatedType)
     : base(positionInDeclaration, columnName)
 {
     Aggregation = aggregation;
     OptionalAssociatedType = optionalAssociatedType;
 }
Exemplo n.º 11
0
        protected override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
        {
            var other = node as ExprPlugInAggNode;

            if (other == null)
            {
                return(false);
            }

            return(((ExprAggregateNodeBase)other).AggregationFunctionName.Equals(AggregationFunctionName));
        }
        public override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
        {
            if (!(node is ExprAggMultiFunctionSortedMinMaxByNode))
            {
                return(false);
            }

            ExprAggMultiFunctionSortedMinMaxByNode other = (ExprAggMultiFunctionSortedMinMaxByNode)node;

            return(_max == other._max && _containedType == other._containedType && _sortedwin == other._sortedwin && _ever == other._ever);
        }
Exemplo n.º 13
0
        protected override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
        {
            var other = node as ExprPlugInAggFunctionFactoryNode;

            if (other == null)
            {
                return(false);
            }

            return(other.AggregationFunctionName == AggregationFunctionName);
        }
Exemplo n.º 14
0
        private static void AddEquivalent(
            ExprAggregateNode aggNodeToAdd,
            IList<AggregationServiceAggExpressionDesc> equivalencyList,
            bool intoTableNonRollup)
        {
            // Check any same aggregation nodes among all aggregation clauses
            var foundEquivalent = false;
            foreach (var existing in equivalencyList) {
                var aggNode = existing.AggregationNode;

                // we have equivalence when:
                // (a) equals on node returns true
                // (b) positional parameters are the same
                // (c) non-positional (group-by over, if present, are the same ignoring duplicates)
                if (!aggNode.EqualsNode(aggNodeToAdd, false)) {
                    continue;
                }

                if (!ExprNodeUtilityCompare.DeepEquals(
                    aggNode.PositionalParams,
                    aggNodeToAdd.PositionalParams,
                    false)) {
                    continue;
                }

                if (!ExprNodeUtilityCompare.DeepEqualsNullChecked(
                    aggNode.OptionalFilter,
                    aggNodeToAdd.OptionalFilter,
                    false)) {
                    continue;
                }

                if (aggNode.OptionalLocalGroupBy != null || aggNodeToAdd.OptionalLocalGroupBy != null) {
                    if (aggNode.OptionalLocalGroupBy == null && aggNodeToAdd.OptionalLocalGroupBy != null ||
                        aggNode.OptionalLocalGroupBy != null && aggNodeToAdd.OptionalLocalGroupBy == null) {
                        continue;
                    }

                    if (!ExprNodeUtilityCompare.DeepEqualsIgnoreDupAndOrder(
                        aggNode.OptionalLocalGroupBy.PartitionExpressions,
                        aggNodeToAdd.OptionalLocalGroupBy.PartitionExpressions)) {
                        continue;
                    }
                }

                existing.AddEquivalent(aggNodeToAdd);
                foundEquivalent = true;
                break;
            }

            if (!foundEquivalent || intoTableNonRollup) {
                equivalencyList.Add(new AggregationServiceAggExpressionDesc(aggNodeToAdd, aggNodeToAdd.Factory));
            }
        }
        public override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
        {
            if (node is ExprAggMultiFunctionLinearAccessNode other)
            {
                return(_stateType == other._stateType &&
                       _containedType == other._containedType &&
                       _scalarCollectionComponentType == other._scalarCollectionComponentType);
            }

            return(false);
        }
Exemplo n.º 16
0
        public override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
        {
            if (!(node is ExprAggMultiFunctionSortedMinMaxByNode)) {
                return false;
            }

            var other = (ExprAggMultiFunctionSortedMinMaxByNode) node;
            return IsMax == other.IsMax &&
                   containedType == other.containedType &&
                   sortedwin == other.sortedwin &&
                   ever == other.ever;
        }
Exemplo n.º 17
0
 public static void ValidateAggregationType(
     AggregationMethodFactory requiredFactory,
     AggregationMethodFactory providedFactory)
 {
     if (!TypeHelper.IsSubclassOrImplementsInterface(providedFactory.GetType(), requiredFactory.GetType()))
         throw new ExprValidationException(
             "Not a '" + requiredFactory.AggregationExpression.AggregationFunctionName + "' aggregation");
     ExprAggregateNode aggNodeRequired = requiredFactory.AggregationExpression;
     ExprAggregateNode aggNodeProvided = providedFactory.AggregationExpression;
     if (aggNodeRequired.IsDistinct != aggNodeProvided.IsDistinct)
         throw new ExprValidationException(
             "The aggregation declares " +
             (aggNodeRequired.IsDistinct ? "a" : "no") + " distinct and provided is " +
             (aggNodeProvided.IsDistinct ? "a" : "no") + " distinct");
 }
Exemplo n.º 18
0
        private static string FindColumnNameForAggregation(
            IDictionary<ExprNode, string> selectClauseNamedNodes,
            IList<ExprDeclaredNode> declaredExpressions,
            ExprAggregateNode aggregationNode)
        {
            if (selectClauseNamedNodes.ContainsKey(aggregationNode)) {
                return selectClauseNamedNodes.Get(aggregationNode);
            }

            foreach (var node in declaredExpressions) {
                if (node.Body == aggregationNode) {
                    return node.Prototype.Name;
                }
            }

            return null;
        }
Exemplo n.º 19
0
 public void QExprTableSubpropAccessor(ExprNode exprNode, string tableName, string subpropName, ExprAggregateNode aggregationExpression)
 {
 }
Exemplo n.º 20
0
 protected override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
 {
     throw new UnsupportedOperationException("not implemented");
 }
Exemplo n.º 21
0
 public override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
 {
     return node is ExprLeavingAggNode;
 }
Exemplo n.º 22
0
 /// <summary>
 /// Return true if a expression aggregate node semantically equals the current node, or false if not.
 /// <para />
 /// For use by the equalsNode implementation which compares the distinct flag.
 /// </summary>
 /// <param name="node">to compare to</param>
 /// <returns>true if semantically equal, or false if not equals</returns>
 protected abstract bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node);
 protected override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
 {
     return false;
 }
Exemplo n.º 24
0
 public override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
 {
     return node is ExprMedianNode;
 }
        public static AggregationServiceFactoryDesc GetService(
            IList<ExprAggregateNode> selectAggregateExprNodes,
            IDictionary<ExprNode, string> selectClauseNamedNodes,
            IList<ExprDeclaredNode> declaredExpressions,
            ExprNode[] groupByNodes,
            IList<ExprAggregateNode> havingAggregateExprNodes,
            IList<ExprAggregateNode> orderByAggregateExprNodes,
            IList<ExprAggregateNodeGroupKey> groupKeyExpressions,
            bool hasGroupByClause,
            Attribute[] annotations,
            VariableService variableService,
            bool isJoin,
            bool isDisallowNoReclaim,
            ExprNode whereClause,
            ExprNode havingClause,
            AggregationServiceFactoryService factoryService,
            EventType[] typesPerStream,
            AggregationGroupByRollupDesc groupByRollupDesc,
            string optionalContextName,
            IntoTableSpec intoTableSpec,
            TableService tableService,
            bool isUnidirectional,
            bool isFireAndForget,
            bool isOnSelect,
            EngineImportService engineImportService)
        {
            // No aggregates used, we do not need this service
            if ((selectAggregateExprNodes.IsEmpty()) && (havingAggregateExprNodes.IsEmpty()))
            {
                if (intoTableSpec != null)
                {
                    throw new ExprValidationException("Into-table requires at least one aggregation function");
                }
                return new AggregationServiceFactoryDesc(
                    factoryService.GetNullAggregationService(),
                    Collections.GetEmptyList<AggregationServiceAggExpressionDesc>(),
                    Collections.GetEmptyList<ExprAggregateNodeGroupKey>());
            }

            // Validate the absence of "prev" function in where-clause:
            // Since the "previous" function does not post remove stream results, disallow when used with aggregations.
            if ((whereClause != null) || (havingClause != null))
            {
                var visitor = new ExprNodePreviousVisitorWParent();
                if (whereClause != null)
                {
                    whereClause.Accept(visitor);
                }
                if (havingClause != null)
                {
                    havingClause.Accept(visitor);
                }
                if ((visitor.Previous != null) && (!visitor.Previous.IsEmpty()))
                {
                    string funcname = visitor.Previous[0].Second.PreviousType.ToString().ToLowerInvariant();
                    throw new ExprValidationException(
                        "The '" + funcname +
                        "' function may not occur in the where-clause or having-clause of a statement with aggregations as 'previous' does not provide remove stream data; Use the 'first','last','window' or 'count' aggregation functions instead");
                }
            }

            // Compile a map of aggregation nodes and equivalent-to aggregation nodes.
            // Equivalent-to functions are for example "select Sum(a*b), 5*Sum(a*b)".
            // Reducing the total number of aggregation functions.
            var aggregations = new List<AggregationServiceAggExpressionDesc>();
            foreach (ExprAggregateNode selectAggNode in selectAggregateExprNodes)
            {
                AddEquivalent(selectAggNode, aggregations);
            }
            foreach (ExprAggregateNode havingAggNode in havingAggregateExprNodes)
            {
                AddEquivalent(havingAggNode, aggregations);
            }
            foreach (ExprAggregateNode orderByAggNode in orderByAggregateExprNodes)
            {
                AddEquivalent(orderByAggNode, aggregations);
            }

            // Construct a list of evaluation node for the aggregation functions (regular agg).
            // For example "Sum(2 * 3)" would make the sum an evaluation node.
            var methodAggEvaluatorsList = new List<ExprEvaluator>();
            foreach (AggregationServiceAggExpressionDesc aggregation in aggregations)
            {
                ExprAggregateNode aggregateNode = aggregation.AggregationNode;
                if (!aggregateNode.Factory.IsAccessAggregation)
                {
                    ExprEvaluator evaluator =
                        aggregateNode.Factory.GetMethodAggregationEvaluator(typesPerStream.Length > 1, typesPerStream);
                    methodAggEvaluatorsList.Add(evaluator);
                }
            }

            // determine local group-by, report when hook provided
            AggregationGroupByLocalGroupDesc localGroupDesc = AnalyzeLocalGroupBy(
                aggregations, groupByNodes, groupByRollupDesc, intoTableSpec);

            // determine binding
            AggregationServiceFactory serviceFactory;
            if (intoTableSpec != null)
            {
                // obtain metadata
                TableMetadata metadata = tableService.GetTableMetadata(intoTableSpec.Name);
                if (metadata == null)
                {
                    throw new ExprValidationException(
                        "Invalid into-table clause: Failed to find table by name '" + intoTableSpec.Name + "'");
                }

                EPLValidationUtil.ValidateContextName(
                    true, intoTableSpec.Name, metadata.ContextName, optionalContextName, false);

                // validate group keys
                Type[] groupByTypes = ExprNodeUtility.GetExprResultTypes(groupByNodes);
                ExprTableNodeUtil.ValidateExpressions(
                    intoTableSpec.Name, groupByTypes, "group-by", groupByNodes,
                    metadata.KeyTypes, "group-by");

                // determine how this binds to existing aggregations, assign column numbers
                BindingMatchResult bindingMatchResult = MatchBindingsAssignColumnNumbers(
                    intoTableSpec, metadata, aggregations, selectClauseNamedNodes, methodAggEvaluatorsList,
                    declaredExpressions);

                // return factory
                if (!hasGroupByClause)
                {
                    serviceFactory = factoryService.GetNoGroupWBinding(
                        bindingMatchResult.Accessors, isJoin, bindingMatchResult.MethodPairs, intoTableSpec.Name,
                        bindingMatchResult.TargetStates, bindingMatchResult.AccessStateExpr, bindingMatchResult.Agents);
                }
                else
                {
                    serviceFactory = factoryService.GetGroupWBinding(
                        metadata, bindingMatchResult.MethodPairs, bindingMatchResult.Accessors, isJoin, intoTableSpec,
                        bindingMatchResult.TargetStates, bindingMatchResult.AccessStateExpr, bindingMatchResult.Agents,
                        groupByRollupDesc);
                }
                return new AggregationServiceFactoryDesc(serviceFactory, aggregations, groupKeyExpressions);
            }

            // Assign a column number to each aggregation node. The regular aggregation goes first followed by access-aggregation.
            int columnNumber = 0;
            foreach (AggregationServiceAggExpressionDesc entry in aggregations)
            {
                if (!entry.Factory.IsAccessAggregation)
                {
                    entry.ColumnNum = columnNumber++;
                }
            }
            foreach (AggregationServiceAggExpressionDesc entry in aggregations)
            {
                if (entry.Factory.IsAccessAggregation)
                {
                    entry.ColumnNum = columnNumber++;
                }
            }

            // determine method aggregation factories and Evaluators(non-access)
            ExprEvaluator[] methodAggEvaluators = methodAggEvaluatorsList.ToArray();
            var methodAggFactories = new AggregationMethodFactory[methodAggEvaluators.Length];
            int count = 0;
            foreach (AggregationServiceAggExpressionDesc aggregation in aggregations)
            {
                ExprAggregateNode aggregateNode = aggregation.AggregationNode;
                if (!aggregateNode.Factory.IsAccessAggregation)
                {
                    methodAggFactories[count] = aggregateNode.Factory;
                    count++;
                }
            }

            // handle access aggregations
            AggregationMultiFunctionAnalysisResult multiFunctionAggPlan =
                AggregationMultiFunctionAnalysisHelper.AnalyzeAccessAggregations(aggregations);
            AggregationAccessorSlotPair[] accessorPairs = multiFunctionAggPlan.AccessorPairs;
            AggregationStateFactory[] accessAggregations = multiFunctionAggPlan.StateFactories;

            // analyze local group by
            AggregationLocalGroupByPlan localGroupByPlan = null;
            if (localGroupDesc != null)
            {
                localGroupByPlan = AggregationGroupByLocalGroupByAnalyzer.Analyze(
                    methodAggEvaluators, methodAggFactories, accessAggregations, localGroupDesc, groupByNodes,
                    accessorPairs);
                try
                {
                    var hook =
                        (AggregationLocalLevelHook)
                            TypeHelper.GetAnnotationHook(
                                annotations, HookType.INTERNAL_AGGLOCALLEVEL, typeof (AggregationLocalLevelHook),
                                engineImportService);
                    if (hook != null)
                    {
                        hook.Planned(localGroupDesc, localGroupByPlan);
                    }
                }
                catch (ExprValidationException)
                {
                    throw new EPException("Failed to obtain hook for " + HookType.INTERNAL_AGGLOCALLEVEL);
                }
            }

            // Handle without a group-by clause: we group all into the same pot
            if (!hasGroupByClause)
            {
                if (localGroupByPlan != null)
                {
                    serviceFactory = factoryService.GetNoGroupLocalGroupBy(
                        isJoin, localGroupByPlan, isUnidirectional, isFireAndForget, isOnSelect);
                }
                else if ((methodAggEvaluators.Length > 0) && (accessorPairs.Length == 0))
                {
                    serviceFactory = factoryService.GetNoGroupNoAccess(
                        methodAggEvaluators, methodAggFactories, isUnidirectional, isFireAndForget, isOnSelect);
                }
                else if ((methodAggEvaluators.Length == 0) && (accessorPairs.Length > 0))
                {
                    serviceFactory = factoryService.GetNoGroupAccessOnly(
                        accessorPairs, accessAggregations, isJoin, isUnidirectional, isFireAndForget, isOnSelect);
                }
                else
                {
                    serviceFactory = factoryService.GetNoGroupAccessMixed(
                        methodAggEvaluators, methodAggFactories, accessorPairs, accessAggregations, isJoin,
                        isUnidirectional, isFireAndForget, isOnSelect);
                }
            }
            else
            {
                bool hasNoReclaim = HintEnum.DISABLE_RECLAIM_GROUP.GetHint(annotations) != null;
                HintAttribute reclaimGroupAged = HintEnum.RECLAIM_GROUP_AGED.GetHint(annotations);
                HintAttribute reclaimGroupFrequency = HintEnum.RECLAIM_GROUP_AGED.GetHint(annotations);
                if (localGroupByPlan != null)
                {
                    serviceFactory = factoryService.GetGroupLocalGroupBy(
                        isJoin, localGroupByPlan, isUnidirectional, isFireAndForget, isOnSelect);
                }
                else
                {
                    if (!isDisallowNoReclaim && hasNoReclaim)
                    {
                        if (groupByRollupDesc != null)
                        {
                            throw GetRollupReclaimEx();
                        }
                        if ((methodAggEvaluators.Length > 0) && (accessorPairs.Length == 0))
                        {
                            serviceFactory = factoryService.GetGroupedNoReclaimNoAccess(
                                groupByNodes, methodAggEvaluators, methodAggFactories, isUnidirectional, isFireAndForget,
                                isOnSelect);
                        }
                        else if ((methodAggEvaluators.Length == 0) && (accessorPairs.Length > 0))
                        {
                            serviceFactory = factoryService.GetGroupNoReclaimAccessOnly(
                                groupByNodes, accessorPairs, accessAggregations, isJoin, isUnidirectional,
                                isFireAndForget, isOnSelect);
                        }
                        else
                        {
                            serviceFactory = factoryService.GetGroupNoReclaimMixed(
                                groupByNodes, methodAggEvaluators, methodAggFactories, accessorPairs, accessAggregations,
                                isJoin, isUnidirectional, isFireAndForget, isOnSelect);
                        }
                    }
                    else if (!isDisallowNoReclaim && reclaimGroupAged != null)
                    {
                        if (groupByRollupDesc != null)
                        {
                            throw GetRollupReclaimEx();
                        }
                        serviceFactory = factoryService.GetGroupReclaimAged(
                            groupByNodes, methodAggEvaluators, methodAggFactories, reclaimGroupAged,
                            reclaimGroupFrequency, variableService, accessorPairs, accessAggregations, isJoin,
                            optionalContextName, isUnidirectional, isFireAndForget, isOnSelect);
                    }
                    else if (groupByRollupDesc != null)
                    {
                        serviceFactory = factoryService.GetGroupReclaimMixableRollup(
                            groupByNodes, groupByRollupDesc, methodAggEvaluators, methodAggFactories, accessorPairs,
                            accessAggregations, isJoin, groupByRollupDesc, isUnidirectional, isFireAndForget, isOnSelect);
                    }
                    else
                    {
                        if ((methodAggEvaluators.Length > 0) && (accessorPairs.Length == 0))
                        {
                            serviceFactory = factoryService.GetGroupReclaimNoAccess(
                                groupByNodes, methodAggEvaluators, methodAggFactories, accessorPairs, accessAggregations,
                                isJoin, isUnidirectional, isFireAndForget, isOnSelect);
                        }
                        else
                        {
                            serviceFactory = factoryService.GetGroupReclaimMixable(
                                groupByNodes, methodAggEvaluators, methodAggFactories, accessorPairs, accessAggregations,
                                isJoin, isUnidirectional, isFireAndForget, isOnSelect);
                        }
                    }
                }
            }

            return new AggregationServiceFactoryDesc(serviceFactory, aggregations, groupKeyExpressions);
        }
Exemplo n.º 26
0
 public override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
 {
     return(false);
 }
Exemplo n.º 27
0
 protected override bool EqualsNodeAggregateMethodOnly(ExprAggregateNode node)
 {
     return(node is ExprRateAggNode);
 }
        /// <summary>
        ///     Produces an aggregation service for use with match-recognice.
        /// </summary>
        /// <param name="numStreams">number of streams</param>
        /// <param name="measureExprNodesPerStream">measure nodes</param>
        /// <param name="typesPerStream">type information</param>
        /// <exception cref="ExprValidationException">for validation errors</exception>
        /// <returns>service</returns>
        public static AggregationServiceMatchRecognizeFactoryDesc GetServiceMatchRecognize(
            int numStreams,
            IDictionary<int, IList<ExprAggregateNode>> measureExprNodesPerStream,
            EventType[] typesPerStream)
        {
            var equivalencyListPerStream = new OrderedDictionary<int, List<AggregationServiceAggExpressionDesc>>();

            foreach (var entry in measureExprNodesPerStream)
            {
                var equivalencyList = new List<AggregationServiceAggExpressionDesc>();
                equivalencyListPerStream.Put(entry.Key, equivalencyList);
                foreach (ExprAggregateNode selectAggNode in entry.Value)
                {
                    AddEquivalent(selectAggNode, equivalencyList);
                }
            }

            var aggregatorsPerStream = new LinkedHashMap<int, AggregationMethodFactory[]>();
            var evaluatorsPerStream = new Dictionary<int, ExprEvaluator[]>();

            foreach (var equivalencyPerStream in equivalencyListPerStream)
            {
                int index = 0;
                int stream = equivalencyPerStream.Key;

                var aggregators = new AggregationMethodFactory[equivalencyPerStream.Value.Count];
                aggregatorsPerStream.Put(stream, aggregators);

                var evaluators = new ExprEvaluator[equivalencyPerStream.Value.Count];
                evaluatorsPerStream.Put(stream, evaluators);

                foreach (AggregationServiceAggExpressionDesc aggregation in equivalencyPerStream.Value)
                {
                    ExprAggregateNode aggregateNode = aggregation.AggregationNode;
                    if (aggregateNode.ChildNodes.Count > 1)
                    {
                        evaluators[index] = ExprMethodAggUtil.GetMultiNodeEvaluator(
                            aggregateNode.ChildNodes, typesPerStream.Length > 1, typesPerStream);
                    }
                    else if (aggregateNode.ChildNodes.Count > 0)
                    {
                        // Use the evaluation node under the aggregation node to obtain the aggregation value
                        evaluators[index] = aggregateNode.ChildNodes[0].ExprEvaluator;
                    }
                    else
                    {
                        // For aggregation that doesn't evaluate any particular sub-expression, return null on evaluation
                        evaluators[index] = new ProxyExprEvaluator
                        {
                            ProcEvaluate = eventParams => null,
                            ProcReturnType = () => null
                        };
                    }

                    aggregators[index] = aggregateNode.Factory;
                    index++;
                }
            }

            // Assign a column number to each aggregation node. The regular aggregation goes first followed by access-aggregation.
            int columnNumber = 0;
            var allExpressions = new List<AggregationServiceAggExpressionDesc>();
            foreach (var equivalencyPerStream in equivalencyListPerStream)
            {
                foreach (AggregationServiceAggExpressionDesc entry in equivalencyPerStream.Value)
                {
                    entry.ColumnNum = columnNumber++;
                }
                allExpressions.AddAll(equivalencyPerStream.Value);
            }

            var factory = new AggregationServiceMatchRecognizeFactoryImpl(
                numStreams, aggregatorsPerStream, evaluatorsPerStream);
            return new AggregationServiceMatchRecognizeFactoryDesc(factory, allExpressions);
        }