private static AggregationServiceForgeDesc[] PlanAggregations(
            IList<ExprAggregateNode> measureAggregateExprNodes,
            StreamTypeService compositeTypeServiceMeasure,
            string[] allStreamNames,
            EventType[] allTypes,
            IOrderedDictionary<int, string> streamVariables,
            ISet<string> variablesMultiple,
            StatementBaseInfo @base,
            StatementCompileTimeServices services)
        {
            IDictionary<int, IList<ExprAggregateNode>> measureExprAggNodesPerStream =
                new Dictionary<int, IList<ExprAggregateNode>>();

            foreach (var aggregateNode in measureAggregateExprNodes) {
                // validate node and params
                var count = 0;
                var visitor = new ExprNodeIdentifierVisitor(true);
                var isIStreamOnly = new bool[allStreamNames.Length];
                var typeServiceAggregateMeasure = new StreamTypeServiceImpl(
                    allTypes,
                    allStreamNames,
                    isIStreamOnly,
                    false,
                    true);

                var validationContext =
                    new ExprValidationContextBuilder(typeServiceAggregateMeasure, @base.StatementRawInfo, services)
                        .WithAllowBindingConsumption(true)
                        .Build();
                aggregateNode.ValidatePositionals(validationContext);

                if (aggregateNode.OptionalLocalGroupBy != null) {
                    throw new ExprValidationException(
                        "Match-recognize does not allow aggregation functions to specify a group-by");
                }

                foreach (var child in aggregateNode.ChildNodes) {
                    var validated = ExprNodeUtilityValidate.GetValidatedSubtree(
                        ExprNodeOrigin.MATCHRECOGMEASURE,
                        child,
                        validationContext);
                    validated.Accept(visitor);
                    aggregateNode.SetChildNode(count++, new ExprNodeValidated(validated));
                }

                // verify properties used within the aggregation
                ISet<int> aggregatedStreams = new HashSet<int>();
                foreach (var pair in visitor.ExprProperties) {
                    aggregatedStreams.Add(pair.First);
                }

                int? multipleVarStream = null;
                foreach (var streamNumAggregated in aggregatedStreams) {
                    var variable = streamVariables.Get(streamNumAggregated);
                    if (variablesMultiple.Contains(variable)) {
                        if (multipleVarStream == null) {
                            multipleVarStream = streamNumAggregated;
                            continue;
                        }

                        throw new ExprValidationException(
                            "Aggregation functions in the measure-clause must only refer to properties of exactly one group variable returning multiple events");
                    }
                }

                if (multipleVarStream == null) {
                    throw new ExprValidationException(
                        "Aggregation functions in the measure-clause must refer to one or more properties of exactly one group variable returning multiple events");
                }

                var aggNodesForStream = measureExprAggNodesPerStream.Get(multipleVarStream.Value);
                if (aggNodesForStream == null) {
                    aggNodesForStream = new List<ExprAggregateNode>();
                    measureExprAggNodesPerStream.Put(multipleVarStream.Value, aggNodesForStream);
                }

                aggNodesForStream.Add(aggregateNode);
            }

            // validate aggregation itself
            foreach (var entry in measureExprAggNodesPerStream) {
                foreach (var aggregateNode in entry.Value) {
                    var validationContext = new ExprValidationContextBuilder(
                            compositeTypeServiceMeasure,
                            @base.StatementRawInfo,
                            services)
                        .WithAllowBindingConsumption(true)
                        .WithMemberName(new ExprValidationMemberNameQualifiedRowRecogAgg(entry.Key))
                        .Build();
                    aggregateNode.Validate(validationContext);
                }
            }

            // get aggregation service per variable
            var aggServices = new AggregationServiceForgeDesc[allStreamNames.Length];
            var declareds = Arrays.AsList(@base.StatementSpec.DeclaredExpressions);
            foreach (var entry in measureExprAggNodesPerStream) {
                EventType[] typesPerStream = {allTypes[entry.Key]};
                AggregationServiceForgeDesc desc = AggregationServiceFactoryFactory.GetService(
                    entry.Value,
                    EmptyDictionary<ExprNode, string>.Instance, 
                    declareds,
                    new ExprNode[0],
                    null,
                    EmptyList<ExprAggregateNode>.Instance,
                    EmptyList<ExprAggregateNode>.Instance,
                    EmptyList<ExprAggregateNodeGroupKey>.Instance,
                    false,
                    @base.StatementRawInfo.Annotations,
                    services.VariableCompileTimeResolver,
                    true,
                    null,
                    null,
                    typesPerStream,
                    null,
                    @base.ContextName,
                    null,
                    services.TableCompileTimeResolver,
                    false,
                    true,
                    false,
                    services.ImportServiceCompileTime,
                    @base.StatementRawInfo,
                    services.SerdeResolver);

                aggServices[entry.Key] = desc;
            }

            return aggServices;
        }
Beispiel #2
0
        public void Attach(EventType parentEventType, StatementContext statementContext, ViewFactory optionalParentFactory, IList <ViewFactory> parentViewFactories)
        {
            _eventType = parentEventType;

            // define built-in fields
            var builtinTypeDef = ExpressionViewOAFieldEnumExtensions.AsMapOfTypes(_eventType);

            _builtinMapType = statementContext.EventAdapterService.CreateAnonymousObjectArrayType(
                statementContext.StatementId + "_exprview", builtinTypeDef);

            StreamTypeService streamTypeService = new StreamTypeServiceImpl(new EventType[] { _eventType, _builtinMapType }, new String[2], new bool[2], statementContext.EngineURI, false);

            // validate expression
            ExpiryExpression = ViewFactorySupport.ValidateExpr(ViewName, statementContext, ExpiryExpression, streamTypeService, 0);

            var summaryVisitor = new ExprNodeSummaryVisitor();

            ExpiryExpression.Accept(summaryVisitor);
            if (summaryVisitor.HasSubselect || summaryVisitor.HasStreamSelect || summaryVisitor.HasPreviousPrior)
            {
                throw new ViewParameterException("Invalid expiry expression: Sub-select, previous or prior functions are not supported in this context");
            }

            var returnType = ExpiryExpression.ExprEvaluator.ReturnType;

            if (returnType.GetBoxedType() != typeof(bool?))
            {
                throw new ViewParameterException("Invalid return value for expiry expression, expected a bool return value but received " + returnType.GetParameterAsString());
            }

            // determine variables used, if any
            var visitor = new ExprNodeVariableVisitor();

            ExpiryExpression.Accept(visitor);
            VariableNames = visitor.VariableNames;

            // determine aggregation nodes, if any
            var aggregateNodes = new List <ExprAggregateNode>();

            ExprAggregateNodeUtil.GetAggregatesBottomUp(ExpiryExpression, aggregateNodes);
            if (aggregateNodes.IsNotEmpty())
            {
                try {
                    AggregationServiceFactoryDesc = AggregationServiceFactoryFactory.GetService(
                        Collections.GetEmptyList <ExprAggregateNode>(),
                        Collections.GetEmptyMap <ExprNode, String>(),
                        Collections.GetEmptyList <ExprDeclaredNode>(),
                        null, aggregateNodes,
                        Collections.GetEmptyList <ExprAggregateNode>(),
                        Collections.GetEmptyList <ExprAggregateNodeGroupKey>(), false,
                        statementContext.Annotations,
                        statementContext.VariableService, false, false, null, null,
                        AggregationServiceFactoryServiceImpl.DEFAULT_FACTORY,
                        streamTypeService.EventTypes,
                        statementContext.MethodResolutionService, null,
                        statementContext.ContextName,
                        null, null);
                }
                catch (ExprValidationException ex) {
                    throw new ViewParameterException(ex.Message, ex);
                }
            }
        }