private LinearAggregationFactoryDesc HandleTableAccessWindow(
            ExprNode[] childNodes,
            AggregationStateType stateType,
            ExprValidationContext validationContext,
            TableMetadataColumnAggregation tableAccess)
        {
            var original = (ExprAggMultiFunctionLinearAccessNodeFactoryAccess) tableAccess.Factory;
            if (childNodes.Length == 0 ||
                childNodes.Length == 1 && childNodes[0] is ExprWildcard)
            {
                var componentType = original.ContainedEventType.UnderlyingType;
                var accessor = new AggregationAccessorWindowNoEval(componentType);
                var factory = new ExprAggMultiFunctionLinearAccessNodeFactoryAccess(this, accessor,
                    TypeHelper.GetArrayType(componentType), original.ContainedEventType, null, null, null);
                return new LinearAggregationFactoryDesc(factory, factory.ContainedEventType, null);
            }

            if (childNodes.Length == 1)
            {
                // Expressions apply to events held, thereby validate in terms of event value expressions
                var paramNode = childNodes[0];
                var streams = TableServiceUtil.StreamTypeFromTableColumn(tableAccess,
                    validationContext.StreamTypeService.EngineURIQualifier);
                var localValidationContext = new ExprValidationContext(streams, validationContext);
                paramNode = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.AGGPARAM, paramNode,
                    localValidationContext);
                var paramNodeEval = paramNode.ExprEvaluator;
                var factory = new ExprAggMultiFunctionLinearAccessNodeFactoryAccess(this,
                    new AggregationAccessorWindowWEval(0, paramNodeEval, paramNodeEval.ReturnType),
                    TypeHelper.GetArrayType(paramNodeEval.ReturnType), original.ContainedEventType, null, null, null);
                return new LinearAggregationFactoryDesc(factory, null, paramNodeEval.ReturnType);
            }

            throw new ExprValidationException("Invalid number of parameters");
        }
        private LinearAggregationFactoryDesc HandleTableAccessFirstLast(
            ExprNode[] childNodes,
            AggregationStateType stateType,
            ExprValidationContext validationContext,
            TableMetadataColumnAggregation tableAccess)
        {
            var original = (ExprAggMultiFunctionLinearAccessNodeFactoryAccess) tableAccess.Factory;
            var resultType = original.ContainedEventType.UnderlyingType;
            var defaultAccessor = stateType == AggregationStateType.FIRST
                ? AggregationAccessorFirstNoEval.INSTANCE
                : (AggregationAccessor) AggregationAccessorLastNoEval.INSTANCE;
            if (childNodes.Length == 0)
            {
                var factoryAccess = new ExprAggMultiFunctionLinearAccessNodeFactoryAccess(this, defaultAccessor,
                    resultType, original.ContainedEventType, null, null, null);
                return new LinearAggregationFactoryDesc(factoryAccess, factoryAccess.ContainedEventType, null);
            }

            if (childNodes.Length == 1)
            {
                if (childNodes[0] is ExprWildcard)
                {
                    var factoryAccess = new ExprAggMultiFunctionLinearAccessNodeFactoryAccess(this, defaultAccessor,
                        resultType, original.ContainedEventType, null, null, null);
                    return new LinearAggregationFactoryDesc(factoryAccess, factoryAccess.ContainedEventType, null);
                }

                if (childNodes[0] is ExprStreamUnderlyingNode)
                    throw new ExprValidationException("Stream-wildcard is not allowed for table column access");
                // Expressions apply to events held, thereby validate in terms of event value expressions
                var paramNode = childNodes[0];
                var streams = TableServiceUtil.StreamTypeFromTableColumn(tableAccess,
                    validationContext.StreamTypeService.EngineURIQualifier);
                var localValidationContext = new ExprValidationContext(streams, validationContext);
                paramNode = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.AGGPARAM, paramNode,
                    localValidationContext);
                var paramNodeEval = paramNode.ExprEvaluator;
                AggregationAccessor accessor;
                if (stateType == AggregationStateType.FIRST)
                    accessor = new AggregationAccessorFirstWEval(0, paramNodeEval);
                else
                    accessor = new AggregationAccessorLastWEval(0, paramNodeEval);
                var factory = new ExprAggMultiFunctionLinearAccessNodeFactoryAccess(
                    this, accessor, paramNodeEval.ReturnType, original.ContainedEventType, null, null, null);
                return new LinearAggregationFactoryDesc(factory, factory.ContainedEventType, null);
            }

            if (childNodes.Length == 2)
            {
                var isFirst = stateType == AggregationStateType.FIRST;
                var constant = -1;
                var indexEvalNode = childNodes[1];
                if (indexEvalNode.IsConstantResult)
                    constant = indexEvalNode.ExprEvaluator.Evaluate(EvaluateParams.EmptyTrue).AsInt();
                var evaluatorIndex = indexEvalNode.ExprEvaluator;
                if (evaluatorIndex.ReturnType.IsInt32()) {
                    throw new ExprValidationException(
                        GetErrorPrefix(stateType) +
                        " requires a constant index expression that returns an integer value");
                }

                var accessor = new AggregationAccessorFirstLastIndexNoEval(evaluatorIndex, constant, isFirst);
                var factory = new ExprAggMultiFunctionLinearAccessNodeFactoryAccess(this, accessor, resultType,
                    original.ContainedEventType, null, null, null);
                return new LinearAggregationFactoryDesc(factory, factory.ContainedEventType, null);
            }

            throw new ExprValidationException("Invalid number of parameters");
        }