Пример #1
0
        private OnTriggerActivatorDesc ActivatorNamedWindow(
            NamedWindowConsumerStreamSpec namedSpec,
            StatementCompileTimeServices services)
        {
            var namedWindow = namedSpec.NamedWindow;
            var triggerEventTypeName = namedSpec.NamedWindow.EventType.Name;

            var typesFilterValidation = new StreamTypeServiceImpl(
                namedWindow.EventType,
                namedSpec.OptionalStreamName,
                false);
            var filterSingle =
                ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(namedSpec.FilterExpressions);
            var filterQueryGraph = EPLValidationUtil.ValidateFilterGetQueryGraphSafe(
                filterSingle,
                typesFilterValidation,
                @base.StatementRawInfo,
                services);
            var activator = new ViewableActivatorNamedWindowForge(
                namedSpec,
                namedWindow,
                filterSingle,
                filterQueryGraph,
                false,
                namedSpec.OptPropertyEvaluator);

            var activatorResultEventType = namedWindow.EventType;
            if (namedSpec.OptPropertyEvaluator != null) {
                activatorResultEventType = namedSpec.OptPropertyEvaluator.FragmentEventType;
            }

            return new OnTriggerActivatorDesc(activator, triggerEventTypeName, activatorResultEventType);
        }
Пример #2
0
        public void ValidatePositionals(ExprValidationContext validationContext)
        {
            ExprAggregateNodeParamDesc paramDesc = ExprAggregateNodeUtil.GetValidatePositionalParams(ChildNodes, true);
            if (validationContext.StatementRawInfo.StatementType == StatementType.CREATE_TABLE &&
                (paramDesc.OptLocalGroupBy != null || paramDesc.OptionalFilter != null)) {
                throw new ExprValidationException(
                    "The 'group_by' and 'filter' parameter is not allowed in create-table statements");
            }

            optionalAggregateLocalGroupByDesc = paramDesc.OptLocalGroupBy;
            optionalFilter = paramDesc.OptionalFilter;
            if (optionalAggregateLocalGroupByDesc != null) {
                ExprNodeUtilityValidate.ValidateNoSpecialsGroupByExpressions(
                    optionalAggregateLocalGroupByDesc.PartitionExpressions);
            }

            if (optionalFilter != null) {
                ExprNodeUtilityValidate.ValidateNoSpecialsGroupByExpressions(new[] {optionalFilter});
            }

            if (optionalFilter != null && IsFilterExpressionAsLastParameter) {
                if (paramDesc.PositionalParams.Length > 1) {
                    throw new ExprValidationException("Only a single filter expression can be provided");
                }

                positionalParams = ExprNodeUtilityMake.AddExpression(paramDesc.PositionalParams, optionalFilter);
            }
            else {
                positionalParams = paramDesc.PositionalParams;
            }
        }
Пример #3
0
        private static void LogFilterPlans(
            IList<ExprNode> validatedNodes,
            FilterSpecPlanForge plan,
            EventType eventType,
            string optionalStreamName,
            StatementRawInfo statementRawInfo)
        {
            var buf = new StringBuilder();
            buf
                .Append("Filter plan for statement '")
                .Append(statementRawInfo.StatementName)
                .Append("' filtering event type '")
                .Append(eventType.Name + "'");

            if (optionalStreamName != null) {
                buf.Append(" alias '" + optionalStreamName + "'");
            }
            if (validatedNodes.IsEmpty()) {
                buf.Append(" empty");
            } else {
                var andNode = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(validatedNodes);
                var expression = ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(andNode);
                buf
                    .Append(" expression '")
                    .Append(expression)
                    .Append("' for ")
                    .Append(plan.Paths.Length)
                    .Append(" paths");
            }
            buf.Append(Environment.NewLine);

            plan.AppendPlan(buf);

            Log.Info(buf.ToString());
        }
Пример #4
0
        public static IList<ExprNode> ValidateAllowSubquery(
            ExprNodeOrigin exprNodeOrigin,
            IList<ExprNode> exprNodes,
            StreamTypeService streamTypeService,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            IList<ExprNode> validatedNodes = new List<ExprNode>();

            ExprValidationContext validationContext =
                new ExprValidationContextBuilder(streamTypeService, statementRawInfo, services)
                    .WithAllowBindingConsumption(true)
                    .WithIsFilterExpression(true)
                    .Build();
            foreach (var node in exprNodes) {
                // Determine subselects
                var visitor = new ExprNodeSubselectDeclaredDotVisitor();
                node.Accept(visitor);

                // Compile subselects
                if (!visitor.Subselects.IsEmpty()) {
                    // The outer event type is the filtered-type itself
                    foreach (var subselect in visitor.Subselects) {
                        try {
                            SubSelectHelperFilters.HandleSubselectSelectClauses(
                                subselect,
                                streamTypeService.EventTypes[0],
                                streamTypeService.StreamNames[0],
                                streamTypeService.StreamNames[0],
                                taggedEventTypes,
                                arrayEventTypes,
                                statementRawInfo,
                                services);
                        }
                        catch (ExprValidationException ex) {
                            throw new ExprValidationException(
                                "Failed to validate " +
                                ExprNodeUtilityMake.GetSubqueryInfoText(subselect) +
                                ": " +
                                ex.Message,
                                ex);
                        }
                    }
                }

                var validated = ExprNodeUtilityValidate.GetValidatedSubtree(exprNodeOrigin, node, validationContext);
                validatedNodes.Add(validated);

                if (validated.Forge.EvaluationType != typeof(bool?) && validated.Forge.EvaluationType != typeof(bool)) {
                    throw new ExprValidationException(
                        "Filter expression not returning a boolean value: '" +
                        ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(validated) +
                        "'");
                }
            }

            return validatedNodes;
        }
Пример #5
0
        public override AggregationForgeFactory ValidateAggregationChild(ExprValidationContext validationContext)
        {
            string message =
                "The nth aggregation function requires two parameters, an expression returning aggregation values and a numeric index constant";
            if (this.positionalParams.Length != 2) {
                throw new ExprValidationException(message);
            }

            ExprNode first = this.positionalParams[0];
            ExprNode second = this.positionalParams[1];
            if (!second.Forge.ForgeConstantType.IsCompileTimeConstant) {
                throw new ExprValidationException(message);
            }

            var num = second.Forge.ExprEvaluator.Evaluate(null, true, null);
            int size = num.AsInt32();

            if (optionalFilter != null) {
                this.positionalParams = ExprNodeUtilityMake.AddExpression(positionalParams, optionalFilter);
            }

            var childType = first.Forge.EvaluationType;
            var serde = validationContext.SerdeResolver.SerdeForAggregationDistinct(childType, validationContext.StatementRawInfo);
            var distinctValueSerde = isDistinct ? serde : null;
            return new AggregationForgeFactoryNth(this, childType, serde, distinctValueSerde, size);
        }
Пример #6
0
 public ICollection<object> EvaluateGetROCollectionScalar(
     EventBean[] eventsPerStream,
     bool isNewData,
     ExprEvaluatorContext context)
 {
     throw ExprNodeUtilityMake.MakeUnsupportedCompileTime();
 }
Пример #7
0
 public object Evaluate(
     EventBean[] eventsPerStream,
     bool isNewData,
     ExprEvaluatorContext context)
 {
     throw ExprNodeUtilityMake.MakeUnsupportedCompileTime();
 }
        private static FilterSpecPlanPathTripletForge HandleOrAlternateExpression(
            ExprOrNode orNode,
            bool performConditionPlanning,
            IDictionary <string, Pair <EventType, string> > taggedEventTypes,
            IDictionary <string, Pair <EventType, string> > arrayEventTypes,
            ISet <string> allTagNamesOrdered,
            string statementName,
            StreamTypeService streamTypeService,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            IList <ExprNode> valueExpressions = new List <ExprNode>(orNode.ChildNodes.Length);

            foreach (ExprNode child in orNode.ChildNodes)
            {
                FilterSpecExprNodeVisitorValueLimitedExpr visitor = new FilterSpecExprNodeVisitorValueLimitedExpr();
                child.Accept(visitor);
                if (visitor.IsLimited)
                {
                    valueExpressions.Add(child);
                }
            }

            // The or-node must have a single constituent and one or more value expressions
            if (orNode.ChildNodes.Length != valueExpressions.Count + 1)
            {
                return(null);
            }

            IList <ExprNode> constituents = new List <ExprNode>(orNode.ChildNodes);

            constituents.RemoveAll(valueExpressions);
            if (constituents.Count != 1)
            {
                throw new IllegalStateException("Found multiple constituents");
            }

            ExprNode constituent = constituents[0];

            FilterSpecPlanPathTripletForge triplet = MakeFilterParam(
                constituent,
                performConditionPlanning,
                taggedEventTypes,
                arrayEventTypes,
                allTagNamesOrdered,
                statementName,
                streamTypeService,
                raw,
                services);

            if (triplet == null)
            {
                return(null);
            }

            ExprNode controlConfirm = ExprNodeUtilityMake.ConnectExpressionsByLogicalOrWhenNeeded(valueExpressions);

            return(new FilterSpecPlanPathTripletForge(triplet.Param, controlConfirm));
        }
Пример #9
0
 public object Evaluate(
     EventBean[] eventsPerStream,
     bool isNewData,
     ICollection<EventBean> matchingEvents,
     ExprEvaluatorContext exprEvaluatorContext)
 {
     throw ExprNodeUtilityMake.MakeUnsupportedCompileTime();
 }
Пример #10
0
 public void Init(
     ViewFactoryContext viewFactoryContext,
     EPStatementInitServices services)
 {
     Comparer = ExprNodeUtilityMake.GetComparatorHashableMultiKeys(
         SortCriteriaTypes,
         IsUseCollatorSort,
         IsDescendingValues); // hashable-key comparator since we may remove sort keys
 }
Пример #11
0
 private static ExprAndNode MakeValidateAndNode(
     IList<ExprNode> remainingExprNodes,
     FilterSpecCompilerArgs args)
 {
     var andNode = ExprNodeUtilityMake.ConnectExpressionsByLogicalAnd(remainingExprNodes);
     var validationContext = new ExprValidationContextBuilder(args.streamTypeService, args.statementRawInfo, args.compileTimeServices)
         .WithAllowBindingConsumption(true)
         .WithContextDescriptor(args.contextDescriptor)
         .Build();
     andNode.Validate(validationContext);
     return andNode;
 }
Пример #12
0
        internal static ExprNode DecomposePopulateConsolidate(
            FilterSpecParaForgeMap filterParamExprMap,
            bool performConditionPlanning,
            IList<ExprNode> validatedNodes,
            FilterSpecCompilerArgs args)
        {
            var constituents = DecomposeCheckAggregation(validatedNodes);

            // Remove constituents that are value-expressions
            ExprNode topLevelControl = null;
            if (performConditionPlanning) {
                IList<ExprNode> valueOnlyConstituents = null;
                foreach (var node in constituents) {
                    var visitor = new FilterSpecExprNodeVisitorValueLimitedExpr();
                    node.Accept(visitor);
                    if (visitor.IsLimited) {
                        if (valueOnlyConstituents == null) {
                            valueOnlyConstituents = new List<ExprNode>();
                        }

                        valueOnlyConstituents.Add(node);
                    }
                }

                if (valueOnlyConstituents != null) {
                    constituents.RemoveAll(valueOnlyConstituents);
                    topLevelControl = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(valueOnlyConstituents);
                }
            }

            // Make filter parameter for each expression node, if it can be optimized
            foreach (var constituent in constituents) {
                var triplet = FilterSpecCompilerIndexPlannerConstituent.MakeFilterParam(
                    constituent,
                    performConditionPlanning,
                    args.taggedEventTypes,
                    args.arrayEventTypes,
                    args.allTagNamesOrdered,
                    args.statementRawInfo.StatementName,
                    args.streamTypeService,
                    args.statementRawInfo,
                    args.compileTimeServices);
                filterParamExprMap.Put(constituent, triplet); // accepts null values as the expression may not be optimized
            }

            // Consolidate entries as possible, i.e. (a != 5 and a != 6) is (a not in (5,6))
            // Removes duplicates for same property and same filter operator for filter service index optimizations
            FilterSpecCompilerConsolidateUtil.Consolidate(filterParamExprMap, args.statementRawInfo.StatementName);
            return topLevelControl;
        }
Пример #13
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            if (ChildNodes.Length != 2) {
                throw new ExprValidationException("Prior node must have 2 parameters");
            }

            if (!ChildNodes[0].Forge.ForgeConstantType.IsCompileTimeConstant) {
                throw new ExprValidationException(
                    "Prior function requires a constant-value integer-typed index expression as the first parameter");
            }

            // Child identifier nodes receive optional event
            ExprNodeUtilityMake.SetChildIdentNodesOptionalEvent(this);

            var constantNode = ChildNodes[0];
            var constantNodeType = constantNode.Forge.EvaluationType;
            if (constantNodeType != typeof(int?) && constantNodeType != typeof(int)) {
                throw new ExprValidationException("Prior function requires an integer index parameter");
            }

            var value = constantNode.Forge.ExprEvaluator.Evaluate(null, false, null);
            ConstantIndexNumber = value.AsInt32();
            InnerForge = ChildNodes[1].Forge;

            // Determine stream number
            if (ChildNodes[1] is ExprIdentNode) {
                var identNode = (ExprIdentNode) ChildNodes[1];
                StreamNumber = identNode.StreamId;
                EvaluationType = InnerForge.EvaluationType.GetBoxedType();
            }
            else if (ChildNodes[1] is ExprStreamUnderlyingNode) {
                var streamNode = (ExprStreamUnderlyingNode) ChildNodes[1];
                StreamNumber = streamNode.StreamId;
                EvaluationType = InnerForge.EvaluationType.GetBoxedType();
            }
            else {
                throw new ExprValidationException("Previous function requires an event property as parameter");
            }

            // add request
            if (validationContext.ViewResourceDelegate == null) {
                throw new ExprValidationException("Prior function cannot be used in this context");
            }

            validationContext.ViewResourceDelegate.AddPriorNodeRequest(this);
            priorStrategyFieldName = validationContext.MemberNames.PriorStrategy(StreamNumber);
            return null;
        }
        private static ExprNode GetFilterExpressionInclOnClause(
            ExprNode whereClause,
            OuterJoinDesc[] outerJoinDescList,
            StatementRawInfo rawInfo,
            StatementCompileTimeServices services)
        {
            if (whereClause == null) { // no need to add as query planning is fully based on on-clause
                return null;
            }

            if (outerJoinDescList.Length == 0) { // not an outer-join syntax
                return whereClause;
            }

            if (!OuterJoinDesc.ConsistsOfAllInnerJoins(outerJoinDescList)) { // all-inner joins
                return whereClause;
            }

            var hasOnClauses = OuterJoinDesc.HasOnClauses(outerJoinDescList);
            if (!hasOnClauses) {
                return whereClause;
            }

            IList<ExprNode> expressions = new List<ExprNode>();
            expressions.Add(whereClause);

            foreach (var outerJoinDesc in outerJoinDescList) {
                if (outerJoinDesc.OptLeftNode != null) {
                    expressions.Add(outerJoinDesc.MakeExprNode(rawInfo, services));
                }
            }

            var andNode = ExprNodeUtilityMake.ConnectExpressionsByLogicalAnd(expressions);
            try {
                andNode.Validate(null);
            }
            catch (ExprValidationException ex) {
                throw new EPRuntimeException("Unexpected exception validating expression: " + ex.Message, ex);
            }

            return andNode;
        }
Пример #15
0
        public override AggregationForgeFactory ValidateAggregationChild(ExprValidationContext validationContext)
        {
            string message =
                "The nth aggregation function requires two parameters, an expression returning aggregation values and a numeric index constant";
            if (this.positionalParams.Length != 2) {
                throw new ExprValidationException(message);
            }

            ExprNode first = this.positionalParams[0];
            ExprNode second = this.positionalParams[1];
            if (!second.Forge.ForgeConstantType.IsCompileTimeConstant) {
                throw new ExprValidationException(message);
            }

            var num = second.Forge.ExprEvaluator.Evaluate(null, true, null);
            int size = num.AsInt32();

            if (optionalFilter != null) {
                this.positionalParams = ExprNodeUtilityMake.AddExpression(positionalParams, optionalFilter);
            }

            return new AggregationFactoryMethodNth(this, first.Forge.EvaluationType, size);
        }
        private static CombPermutationTriplets ComputePermutation(
            FilterSpecParaForgeMap filterParamExprMap,
            object[] permutation,
            OrChildNode[][] orChildNodes,
            bool hasControl,
            FilterSpecCompilerArgs args)
        {
            var mapAll = new FilterSpecParaForgeMap();

            mapAll.Add(filterParamExprMap);

            // combine
            IList <ExprNode> nvPerOr      = new List <ExprNode>(permutation.Length);
            IList <ExprNode> negatingPath = new List <ExprNode>(permutation.Length);

            for (var orNodeNum = 0; orNodeNum < permutation.Length; orNodeNum++)
            {
                int orChildNodeNum = permutation[orNodeNum].AsInt32();
                var current        = orChildNodes[orNodeNum][orChildNodeNum];
                if (current is OrChildNodeNV)
                {
                    var nv = (OrChildNodeNV)current;
                    mapAll.Add(nv.Map);
                    if (current is OrChildNodeNVNegated)
                    {
                        negatingPath.Add(((OrChildNodeNVNegated)current).Control);
                    }
                }
                else
                {
                    var v = (OrChildNodeV)current;
                    negatingPath.Add(v.Node);
                }

                var orChildNodesForCurrent = orChildNodes[orNodeNum];
                foreach (var other in orChildNodesForCurrent)
                {
                    if (current == other)
                    {
                        continue;
                    }

                    if (other is OrChildNodeV)
                    {
                        var v   = (OrChildNodeV)other;
                        var not = new ExprNotNode();
                        not.AddChildNode(v.Node);
                        nvPerOr.Add(not);
                    }
                }
            }

            // consolidate across
            FilterSpecCompilerConsolidateUtil.Consolidate(mapAll, args.statementRawInfo.StatementName);

            IList <FilterSpecPlanPathTripletForge> triplets = new List <FilterSpecPlanPathTripletForge>(mapAll.Triplets);
            var countUnassigned = mapAll.CountUnassignedExpressions();

            if (countUnassigned != 0)
            {
                var triplet = MakeRemainingNode(mapAll.UnassignedExpressions, args);
                triplets.Add(triplet);
            }

            // without conditions we are done
            var tripletsArray = triplets.ToArray();

            if (!hasControl)
            {
                return(new CombPermutationTriplets(tripletsArray, null));
            }

            var negatingNode = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(negatingPath);
            var excluded     = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(nvPerOr);
            var merged       = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(negatingNode, excluded);

            return(new CombPermutationTriplets(tripletsArray, merged));
        }
Пример #17
0
        public void Apply(QueryGraphForge filterQueryGraph)
        {
            if (targetStreamNum == parameterStreamNum) {
                return;
            }

            var targetStartExpr = ExprNodeUtilityMake.MakeExprIdentNode(
                typesPerStream,
                targetStreamNum,
                targetStartProp);
            var targetEndExpr = ExprNodeUtilityMake.MakeExprIdentNode(typesPerStream, targetStreamNum, targetEndProp);
            var parameterStartExpr = ExprNodeUtilityMake.MakeExprIdentNode(
                typesPerStream,
                parameterStreamNum,
                parameterStartProp);
            var parameterEndExpr = ExprNodeUtilityMake.MakeExprIdentNode(
                typesPerStream,
                parameterStreamNum,
                parameterEndProp);

            if (targetStartExpr.Forge.EvaluationType != parameterStartExpr.Forge.EvaluationType) {
                return;
            }

            if (currentMethod == DateTimeMethodEnum.BEFORE) {
                // a.end < b.start
                filterQueryGraph.AddRelationalOpStrict(
                    targetStreamNum,
                    targetEndExpr,
                    parameterStreamNum,
                    parameterStartExpr,
                    RelationalOpEnum.LT);
            }
            else if (currentMethod == DateTimeMethodEnum.AFTER) {
                // a.start > b.end
                filterQueryGraph.AddRelationalOpStrict(
                    targetStreamNum,
                    targetStartExpr,
                    parameterStreamNum,
                    parameterEndExpr,
                    RelationalOpEnum.GT);
            }
            else if (currentMethod == DateTimeMethodEnum.COINCIDES) {
                // a.startTimestamp = b.startTimestamp and a.endTimestamp = b.endTimestamp
                filterQueryGraph.AddStrictEquals(
                    targetStreamNum,
                    targetStartProp,
                    targetStartExpr,
                    parameterStreamNum,
                    parameterStartProp,
                    parameterStartExpr);

                var noDuration = parameterEndProp.Equals(parameterStartProp) && targetEndProp.Equals(targetStartProp);
                if (!noDuration) {
                    var leftEndExpr = ExprNodeUtilityMake.MakeExprIdentNode(
                        typesPerStream,
                        targetStreamNum,
                        targetEndProp);
                    var rightEndExpr = ExprNodeUtilityMake.MakeExprIdentNode(
                        typesPerStream,
                        parameterStreamNum,
                        parameterEndProp);
                    filterQueryGraph.AddStrictEquals(
                        targetStreamNum,
                        targetEndProp,
                        leftEndExpr,
                        parameterStreamNum,
                        parameterEndProp,
                        rightEndExpr);
                }
            }
            else if (currentMethod == DateTimeMethodEnum.DURING || currentMethod == DateTimeMethodEnum.INCLUDES) {
                // DURING:   b.startTimestamp < a.startTimestamp <= a.endTimestamp < b.endTimestamp
                // INCLUDES: a.startTimestamp < b.startTimestamp <= b.endTimestamp < a.endTimestamp
                var relop = currentMethod == DateTimeMethodEnum.DURING ? RelationalOpEnum.LT : RelationalOpEnum.GT;
                filterQueryGraph.AddRelationalOpStrict(
                    parameterStreamNum,
                    parameterStartExpr,
                    targetStreamNum,
                    targetStartExpr,
                    relop);

                filterQueryGraph.AddRelationalOpStrict(
                    targetStreamNum,
                    targetEndExpr,
                    parameterStreamNum,
                    parameterEndExpr,
                    relop);
            }
            else if (currentMethod == DateTimeMethodEnum.FINISHES || currentMethod == DateTimeMethodEnum.FINISHEDBY) {
                // FINISHES:   b.startTimestamp < a.startTimestamp and a.endTimestamp = b.endTimestamp
                // FINISHEDBY: a.startTimestamp < b.startTimestamp and a.endTimestamp = b.endTimestamp
                var relop = currentMethod == DateTimeMethodEnum.FINISHES ? RelationalOpEnum.LT : RelationalOpEnum.GT;
                filterQueryGraph.AddRelationalOpStrict(
                    parameterStreamNum,
                    parameterStartExpr,
                    targetStreamNum,
                    targetStartExpr,
                    relop);

                filterQueryGraph.AddStrictEquals(
                    targetStreamNum,
                    targetEndProp,
                    targetEndExpr,
                    parameterStreamNum,
                    parameterEndProp,
                    parameterEndExpr);
            }
            else if (currentMethod == DateTimeMethodEnum.MEETS) {
                // a.endTimestamp = b.startTimestamp
                filterQueryGraph.AddStrictEquals(
                    targetStreamNum,
                    targetEndProp,
                    targetEndExpr,
                    parameterStreamNum,
                    parameterStartProp,
                    parameterStartExpr);
            }
            else if (currentMethod == DateTimeMethodEnum.METBY) {
                // a.startTimestamp = b.endTimestamp
                filterQueryGraph.AddStrictEquals(
                    targetStreamNum,
                    targetStartProp,
                    targetStartExpr,
                    parameterStreamNum,
                    parameterEndProp,
                    parameterEndExpr);
            }
            else if (currentMethod == DateTimeMethodEnum.OVERLAPS || currentMethod == DateTimeMethodEnum.OVERLAPPEDBY) {
                // OVERLAPS:     a.startTimestamp < b.startTimestamp < a.endTimestamp < b.endTimestamp
                // OVERLAPPEDBY: b.startTimestamp < a.startTimestamp < b.endTimestamp < a.endTimestamp
                var relop = currentMethod == DateTimeMethodEnum.OVERLAPS ? RelationalOpEnum.LT : RelationalOpEnum.GT;
                filterQueryGraph.AddRelationalOpStrict(
                    targetStreamNum,
                    targetStartExpr,
                    parameterStreamNum,
                    parameterStartExpr,
                    relop);

                filterQueryGraph.AddRelationalOpStrict(
                    targetStreamNum,
                    targetEndExpr,
                    parameterStreamNum,
                    parameterEndExpr,
                    relop);

                if (currentMethod == DateTimeMethodEnum.OVERLAPS) {
                    filterQueryGraph.AddRelationalOpStrict(
                        parameterStreamNum,
                        parameterStartExpr,
                        targetStreamNum,
                        targetEndExpr,
                        RelationalOpEnum.LT);
                }
                else {
                    filterQueryGraph.AddRelationalOpStrict(
                        targetStreamNum,
                        targetStartExpr,
                        parameterStreamNum,
                        parameterEndExpr,
                        RelationalOpEnum.LT);
                }
            }
            else if (currentMethod == DateTimeMethodEnum.STARTS || currentMethod == DateTimeMethodEnum.STARTEDBY) {
                // STARTS:       a.startTimestamp = b.startTimestamp and a.endTimestamp < b.endTimestamp
                // STARTEDBY:    a.startTimestamp = b.startTimestamp and b.endTimestamp < a.endTimestamp
                filterQueryGraph.AddStrictEquals(
                    targetStreamNum,
                    targetStartProp,
                    targetStartExpr,
                    parameterStreamNum,
                    parameterStartProp,
                    parameterStartExpr);

                var relop = currentMethod == DateTimeMethodEnum.STARTS ? RelationalOpEnum.LT : RelationalOpEnum.GT;
                filterQueryGraph.AddRelationalOpStrict(
                    targetStreamNum,
                    targetEndExpr,
                    parameterStreamNum,
                    parameterEndExpr,
                    relop);
            }
        }
Пример #18
0
        public static SubSelectActivationDesc CreateSubSelectActivation(
            IList <FilterSpecCompiled> filterSpecCompileds,
            IList <NamedWindowConsumerStreamSpec> namedWindowConsumers,
            StatementBaseInfo statement,
            StatementCompileTimeServices services)
        {
            IDictionary <ExprSubselectNode, SubSelectActivationPlan> result = new LinkedHashMap <ExprSubselectNode, SubSelectActivationPlan>();
            IList <StmtClassForgeableFactory> additionalForgeables          = new List <StmtClassForgeableFactory>();

            // Process all subselect expression nodes
            foreach (ExprSubselectNode subselect in statement.StatementSpec.SubselectNodes)
            {
                StatementSpecCompiled statementSpec = subselect.StatementSpecCompiled;
                StreamSpecCompiled    streamSpec    = statementSpec.StreamSpecs[0];
                int subqueryNumber = subselect.SubselectNumber;
                if (subqueryNumber == -1)
                {
                    throw new IllegalStateException("Unexpected subquery");
                }

                ViewFactoryForgeArgs args = new ViewFactoryForgeArgs(-1, true, subqueryNumber, streamSpec.Options, null, statement.StatementRawInfo, services);

                if (streamSpec is FilterStreamSpecCompiled)
                {
                    if (services.IsFireAndForget)
                    {
                        throw new ExprValidationException("Fire-and-forget queries only allow subqueries against named windows and tables");
                    }

                    FilterStreamSpecCompiled filterStreamSpec = (FilterStreamSpecCompiled)statementSpec.StreamSpecs[0];

                    // Register filter, create view factories
                    ViewableActivatorForge activatorDeactivator = new ViewableActivatorFilterForge(
                        filterStreamSpec.FilterSpecCompiled,
                        false,
                        null,
                        true,
                        subqueryNumber);
                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(
                        streamSpec.ViewSpecs,
                        args,
                        filterStreamSpec.FilterSpecCompiled.ResultEventType);
                    IList <ViewFactoryForge> forges = viewForgeDesc.Forges;
                    additionalForgeables.AddAll(viewForgeDesc.MultikeyForges);
                    EventType eventType = forges.IsEmpty() ? filterStreamSpec.FilterSpecCompiled.ResultEventType : forges[forges.Count - 1].EventType;
                    subselect.RawEventType = eventType;
                    filterSpecCompileds.Add(filterStreamSpec.FilterSpecCompiled);

                    // Add lookup to list, for later starts
                    result.Put(
                        subselect,
                        new SubSelectActivationPlan(filterStreamSpec.FilterSpecCompiled.ResultEventType, forges, activatorDeactivator, streamSpec));
                }
                else if (streamSpec is TableQueryStreamSpec)
                {
                    TableQueryStreamSpec   table             = (TableQueryStreamSpec)streamSpec;
                    ExprNode               filter            = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(table.FilterExpressions);
                    ViewableActivatorForge viewableActivator = new ViewableActivatorTableForge(table.Table, filter);
                    result.Put(
                        subselect,
                        new SubSelectActivationPlan(table.Table.InternalEventType, EmptyList <ViewFactoryForge> .Instance, viewableActivator, streamSpec));
                    subselect.RawEventType = table.Table.InternalEventType;
                }
                else
                {
                    NamedWindowConsumerStreamSpec namedSpec = (NamedWindowConsumerStreamSpec)statementSpec.StreamSpecs[0];
                    namedWindowConsumers.Add(namedSpec);
                    NamedWindowMetaData nwinfo = namedSpec.NamedWindow;

                    EventType namedWindowType = nwinfo.EventType;
                    if (namedSpec.OptPropertyEvaluator != null)
                    {
                        namedWindowType = namedSpec.OptPropertyEvaluator.FragmentEventType;
                    }

                    // if named-window index sharing is disabled (the default) or filter expressions are provided then consume the insert-remove stream
                    bool disableIndexShare          = HintEnum.DISABLE_WINDOW_SUBQUERY_INDEXSHARE.GetHint(statement.StatementRawInfo.Annotations) != null;
                    bool processorDisableIndexShare = !namedSpec.NamedWindow.IsEnableIndexShare;
                    if (disableIndexShare && namedSpec.NamedWindow.IsVirtualDataWindow)
                    {
                        disableIndexShare = false;
                    }

                    if ((!namedSpec.FilterExpressions.IsEmpty() || processorDisableIndexShare || disableIndexShare) && (!services.IsFireAndForget))
                    {
                        ExprNode filterEvaluator = null;
                        if (!namedSpec.FilterExpressions.IsEmpty())
                        {
                            filterEvaluator = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(namedSpec.FilterExpressions);
                        }

                        ViewableActivatorForge activatorNamedWindow = new ViewableActivatorNamedWindowForge(
                            namedSpec,
                            nwinfo,
                            filterEvaluator,
                            null,
                            true,
                            namedSpec.OptPropertyEvaluator);
                        ViewFactoryForgeDesc     viewForgeDesc = ViewFactoryForgeUtil.CreateForges(streamSpec.ViewSpecs, args, namedWindowType);
                        IList <ViewFactoryForge> forges        = viewForgeDesc.Forges;
                        additionalForgeables.AddAll(viewForgeDesc.MultikeyForges);
                        subselect.RawEventType = forges.IsEmpty() ? namedWindowType : forges[forges.Count - 1].EventType;
                        result.Put(subselect, new SubSelectActivationPlan(namedWindowType, forges, activatorNamedWindow, streamSpec));
                    }
                    else
                    {
                        // else if there are no named window stream filter expressions and index sharing is enabled
                        ViewFactoryForgeDesc     viewForgeDesc = ViewFactoryForgeUtil.CreateForges(streamSpec.ViewSpecs, args, namedWindowType);
                        IList <ViewFactoryForge> forges        = viewForgeDesc.Forges;
                        additionalForgeables.AddAll(viewForgeDesc.MultikeyForges);
                        subselect.RawEventType = namedWindowType;
                        ViewableActivatorForge activatorNamedWindow = new ViewableActivatorSubselectNoneForge(namedWindowType);
                        result.Put(subselect, new SubSelectActivationPlan(namedWindowType, forges, activatorNamedWindow, streamSpec));
                    }
                }
            }

            return(new SubSelectActivationDesc(result, additionalForgeables));
        }
Пример #19
0
 public double GetFilterValue(
     MatchedEventMap matchedEvents,
     ExprEvaluatorContext exprEvaluatorContext)
 {
     throw ExprNodeUtilityMake.MakeUnsupportedCompileTime();
 }
Пример #20
0
 public void Apply(QueryGraphForge queryGraph)
 {
     var targetExpr = ExprNodeUtilityMake.MakeExprIdentNode(typesPerStream, targetStreamNum, targetPropertyName);
     RangeFilterAnalyzer.Apply(targetExpr, start, end, includeLow, includeHigh, false, queryGraph);
 }
Пример #21
0
        public FAFQueryMethodSelectDesc(
            StatementSpecCompiled statementSpec,
            Compilable compilable,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            Annotations = statementSpec.Annotations;
            ContextName = statementSpec.Raw.OptionalContextName;

            var queryPlanLogging = services.Configuration.Common.Logging.IsEnableQueryPlan;
            if (queryPlanLogging) {
                QUERY_PLAN_LOG.Info("Query plans for Fire-and-forget query '" + compilable.ToEPL() + "'");
            }

            HasTableAccess = statementSpec.TableAccessNodes != null && statementSpec.TableAccessNodes.Count > 0;
            foreach (var streamSpec in statementSpec.StreamSpecs) {
                HasTableAccess |= streamSpec is TableQueryStreamSpec;
            }

            HasTableAccess |= StatementLifecycleSvcUtil.IsSubqueryWithTable(
                statementSpec.SubselectNodes, services.TableCompileTimeResolver);
            IsDistinct = statementSpec.SelectClauseCompiled.IsDistinct;

            FAFQueryMethodHelper.ValidateFAFQuery(statementSpec);

            var numStreams = statementSpec.StreamSpecs.Length;
            var typesPerStream = new EventType[numStreams];
            var namesPerStream = new string[numStreams];
            var eventTypeNames = new string[numStreams];
            Processors = new FireAndForgetProcessorForge[numStreams];
            ConsumerFilters = new ExprNode[numStreams];

            // check context partition use
            if (statementSpec.Raw.OptionalContextName != null) {
                if (numStreams > 1) {
                    throw new ExprValidationException(
                        "Joins in runtime queries for context partitions are not supported");
                }
            }

            // resolve types and processors
            for (var i = 0; i < numStreams; i++) {
                var streamSpec = statementSpec.StreamSpecs[i];
                Processors[i] = FireAndForgetProcessorForgeFactory.ValidateResolveProcessor(streamSpec);
                if (numStreams > 1 && Processors[i].ContextName != null) {
                    throw new ExprValidationException(
                        "Joins against named windows that are under context are not supported");
                }

                var streamName = Processors[i].NamedWindowOrTableName;
                if (streamSpec.OptionalStreamName != null) {
                    streamName = streamSpec.OptionalStreamName;
                }

                namesPerStream[i] = streamName;
                typesPerStream[i] = Processors[i].EventTypeRspInputEvents;
                eventTypeNames[i] = typesPerStream[i].Name;

                IList<ExprNode> consumerFilterExprs;
                if (streamSpec is NamedWindowConsumerStreamSpec) {
                    var namedSpec = (NamedWindowConsumerStreamSpec) streamSpec;
                    consumerFilterExprs = namedSpec.FilterExpressions;
                }
                else {
                    var tableSpec = (TableQueryStreamSpec) streamSpec;
                    consumerFilterExprs = tableSpec.FilterExpressions;
                }

                ConsumerFilters[i] = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(consumerFilterExprs);
            }

            // compile filter to optimize access to named window
            var optionalStreamsIfAny = OuterJoinAnalyzer.OptionalStreamsIfAny(statementSpec.Raw.OuterJoinDescList);
            var types = new StreamTypeServiceImpl(
                typesPerStream,
                namesPerStream,
                new bool[numStreams],
                false,
                optionalStreamsIfAny);
            var excludePlanHint = ExcludePlanHint.GetHint(types.StreamNames, statementRawInfo, services);
            QueryGraph = new QueryGraphForge(numStreams, excludePlanHint, false);
            if (statementSpec.Raw.WhereClause != null) {
                for (var i = 0; i < numStreams; i++) {
                    try {
                        var validationContext = new ExprValidationContextBuilder(types, statementRawInfo, services)
                            .WithAllowBindingConsumption(true)
                            .WithIsFilterExpression(true)
                            .Build();
                        var validated = ExprNodeUtilityValidate.GetValidatedSubtree(
                            ExprNodeOrigin.FILTER,
                            statementSpec.Raw.WhereClause,
                            validationContext);
                        FilterExprAnalyzer.Analyze(validated, QueryGraph, false);
                    }
                    catch (Exception ex) {
                        Log.Warn("Unexpected exception analyzing filter paths: " + ex.Message, ex);
                    }
                }
            }
            
            // handle subselects
            // first we create streams for subselects, if there are any
            var @base = new StatementBaseInfo(compilable, statementSpec, null, statementRawInfo, null);
            var subqueryNamedWindowConsumers = new List<NamedWindowConsumerStreamSpec>();
            SubSelectActivationDesc subSelectActivationDesc = SubSelectHelperActivations.CreateSubSelectActivation(
                EmptyList<FilterSpecCompiled>.Instance, subqueryNamedWindowConsumers, @base, services);
            IDictionary<ExprSubselectNode, SubSelectActivationPlan> subselectActivation = subSelectActivationDesc.Subselects;
            AdditionalForgeables.AddAll(subSelectActivationDesc.AdditionalForgeables);

            SubSelectHelperForgePlan subSelectForgePlan = SubSelectHelperForgePlanner.PlanSubSelect(
                @base, subselectActivation, namesPerStream, typesPerStream, eventTypeNames, services);
            SubselectForges = subSelectForgePlan.Subselects;
            AdditionalForgeables.AddAll(subSelectForgePlan.AdditionalForgeables);

            // obtain result set processor
            var isIStreamOnly = new bool[namesPerStream.Length];
            isIStreamOnly.Fill(true);
            StreamTypeService typeService = new StreamTypeServiceImpl(
                typesPerStream,
                namesPerStream,
                isIStreamOnly,
                true,
                optionalStreamsIfAny);
            WhereClause = EPStatementStartMethodHelperValidate.ValidateNodes(
                statementSpec.Raw,
                typeService,
                null,
                statementRawInfo,
                services);

            var resultSetSpec = new ResultSetSpec(statementSpec);
            ResultSetProcessor = ResultSetProcessorFactoryFactory.GetProcessorPrototype(
                resultSetSpec,
                typeService,
                null,
                new bool[0],
                true,
                null,
                true,
                false,
                statementRawInfo,
                services);
            AdditionalForgeables.AddAll(ResultSetProcessor.AdditionalForgeables);

            // plan table access
            TableAccessForges = ExprTableEvalHelperPlan.PlanTableAccess(statementSpec.Raw.TableExpressions);

            // plan joins or simple queries
            if (numStreams > 1) {
                var streamJoinAnalysisResult = new StreamJoinAnalysisResultCompileTime(numStreams);
                CompatExtensions.Fill(streamJoinAnalysisResult.NamedWindowsPerStream, (NamedWindowMetaData) null);
                for (var i = 0; i < numStreams; i++) {
                    var uniqueIndexes = Processors[i].UniqueIndexes;
                    streamJoinAnalysisResult.UniqueKeys[i] = uniqueIndexes;
                }

                var hasAggregations = ResultSetProcessor.ResultSetProcessorType.IsAggregated();
                var desc = JoinSetComposerPrototypeForgeFactory.MakeComposerPrototype(
                    statementSpec,
                    streamJoinAnalysisResult,
                    types,
                    new HistoricalViewableDesc(numStreams),
                    true,
                    hasAggregations,
                    statementRawInfo,
                    services);
                AdditionalForgeables.AddAll(desc.AdditionalForgeables);
                Joins = desc.Forge;
            }
            else {
                Joins = null;
            }
            
            var multiKeyPlan = MultiKeyPlanner.PlanMultiKeyDistinct(
                IsDistinct, ResultSetProcessor.ResultEventType, statementRawInfo, SerdeCompileTimeResolverNonHA.INSTANCE);
            AdditionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables);
            DistinctMultiKey = multiKeyPlan.ClassRef;
        }
Пример #22
0
        public override AggregationForgeFactory ValidateAggregationChild(ExprValidationContext validationContext)
        {
            Type[] parameterTypes = new Type[positionalParams.Length];
            object[] constant = new object[positionalParams.Length];
            bool[] isConstant = new bool[positionalParams.Length];
            ExprNode[] expressions = new ExprNode[positionalParams.Length];

            int count = 0;
            bool hasDataWindows = true;
            foreach (ExprNode child in positionalParams) {
                if (child.Forge.ForgeConstantType == ExprForgeConstantType.COMPILETIMECONST) {
                    isConstant[count] = true;
                    constant[count] = child.Forge.ExprEvaluator.Evaluate(null, true, null);
                }

                parameterTypes[count] = child.Forge.EvaluationType;
                expressions[count] = child;

                if (!ExprNodeUtilityAggregation.HasRemoveStreamForAggregations(
                    child,
                    validationContext.StreamTypeService,
                    validationContext.IsResettingAggregations)) {
                    hasDataWindows = false;
                }

                if (child is ExprWildcard) {
                    ExprAggMultiFunctionUtil.CheckWildcardNotJoinOrSubquery(
                        validationContext.StreamTypeService,
                        functionName);
                    parameterTypes[count] = validationContext.StreamTypeService.EventTypes[0].UnderlyingType;
                    isConstant[count] = false;
                    constant[count] = null;
                }

                count++;
            }

            LinkedHashMap<string, IList<ExprNode>> namedParameters = null;
            if (optionalFilter != null) {
                namedParameters = new LinkedHashMap<string, IList<ExprNode>>();
                namedParameters.Put("filter", Collections.SingletonList(optionalFilter));
                positionalParams = ExprNodeUtilityMake.AddExpression(positionalParams, optionalFilter);
            }

            AggregationFunctionValidationContext context = new AggregationFunctionValidationContext(
                parameterTypes,
                isConstant,
                constant,
                base.IsDistinct,
                hasDataWindows,
                expressions,
                namedParameters);
            try {
                // the aggregation function factory is transient, obtain if not provided
                if (aggregationFunctionForge == null) {
                    aggregationFunctionForge =
                        validationContext.ImportService.ResolveAggregationFunction(functionName);
                }

                aggregationFunctionForge.Validate(context);
            }
            catch (Exception ex) {
                throw new ExprValidationException(
                    "Plug-in aggregation function '" + functionName + "' failed validation: " + ex.Message,
                    ex);
            }

            AggregationFunctionMode mode = aggregationFunctionForge.AggregationFunctionMode;
            if (mode == null) {
                throw new ExprValidationException("Aggregation function forge returned a null value for mode");
            }

            if (mode is AggregationFunctionModeManaged) {
                if (positionalParams.Length > 2) {
                    throw new ExprValidationException(
                        "Aggregation function forge single-value mode requires zero, one or two parameters");
                }
            }
            else if (mode is AggregationFunctionModeMultiParam || mode is AggregationFunctionModeCodeGenerated) {
            }
            else {
                throw new ExprValidationException("Aggregation function forge returned an unrecognized mode " + mode);
            }

            return new AggregationMethodFactoryPluginMethod(this, aggregationFunctionForge, mode);
        }
Пример #23
0
 private void InitInnerEvaluatorTypable()
 {
     throw ExprNodeUtilityMake.MakeUnsupportedCompileTime();
 }
Пример #24
0
        public override AggregationForgeFactory ValidateAggregationChild(ExprValidationContext validationContext)
        {
            if (this.positionalParams.Length == 0) {
                throw new ExprValidationException(
                    "The rate aggregation function minimally requires a numeric constant or expression as a parameter.");
            }

            // handle "ever"
            ExprNode first = this.positionalParams[0];
            if (first.Forge.ForgeConstantType.IsCompileTimeConstant) {
                string messageX =
                    "The rate aggregation function requires a numeric constant or time period as the first parameter in the constant-value notation";
                long intervalTime;
                if (first is ExprTimePeriod) {
                    double secInterval = ((ExprTimePeriod) first).EvaluateAsSeconds(null, true, null);
                    intervalTime =
                        validationContext.ImportService.TimeAbacus.DeltaForSecondsDouble(secInterval);
                }
                else if (ExprNodeUtilityQuery.IsConstant(first)) {
                    if (!first.Forge.EvaluationType.IsNumeric()) {
                        throw new ExprValidationException(messageX);
                    }

                    var num = first.Forge.ExprEvaluator.Evaluate(null, true, null);
                    intervalTime = validationContext.ImportService.TimeAbacus.DeltaForSecondsNumber(num);
                }
                else {
                    throw new ExprValidationException(messageX);
                }

                if (optionalFilter == null) {
                    this.positionalParams = ExprNodeUtilityQuery.EMPTY_EXPR_ARRAY;
                }
                else {
                    this.positionalParams = new ExprNode[] {optionalFilter};
                }

                return new AggregationForgeFactoryRate(this, true, intervalTime, validationContext.ImportService.TimeAbacus);
            }

            string message =
                "The rate aggregation function requires a property or expression returning a non-constant long-type value as the first parameter in the timestamp-property notation";
            Type boxedParamOne = first.Forge.EvaluationType.GetBoxedType();
            if (boxedParamOne != typeof(long?)) {
                throw new ExprValidationException(message);
            }

            if (first.Forge.ForgeConstantType.IsConstant) {
                throw new ExprValidationException(message);
            }

            if (first is ExprTimestampNode) {
                throw new ExprValidationException(
                    "The rate aggregation function does not allow the current runtime timestamp as a parameter");
            }

            if (this.positionalParams.Length > 1) {
                if (!this.positionalParams[1].Forge.EvaluationType.IsNumeric()) {
                    throw new ExprValidationException(
                        "The rate aggregation function accepts an expression returning a numeric value to accumulate as an optional second parameter");
                }
            }

            bool hasDataWindows = ExprNodeUtilityAggregation.HasRemoveStreamForAggregations(
                first,
                validationContext.StreamTypeService,
                validationContext.IsResettingAggregations);
            if (!hasDataWindows) {
                throw new ExprValidationException(
                    "The rate aggregation function in the timestamp-property notation requires data windows");
            }

            if (optionalFilter != null) {
                positionalParams = ExprNodeUtilityMake.AddExpression(positionalParams, optionalFilter);
            }

            return new AggregationForgeFactoryRate(this, false, -1, validationContext.ImportService.TimeAbacus);
        }
        private AggregationLinearFactoryDesc HandleNonIntoTable(
            ExprNode[] childNodes,
            AggregationAccessorLinearType?stateType,
            ExprValidationContext validationContext)
        {
            var       streamTypeService = validationContext.StreamTypeService;
            int       streamNum;
            Type      resultType;
            ExprForge forge;
            ExprNode  evaluatorIndex = null;
            bool      istreamOnly;
            EventType containedType;
            Type      scalarCollectionComponentType = null;

            // validate wildcard use
            var isWildcard = childNodes.Length == 0 || childNodes.Length > 0 && childNodes[0] is ExprWildcard;

            if (isWildcard)
            {
                ExprAggMultiFunctionUtil.ValidateWildcardStreamNumbers(validationContext.StreamTypeService, stateType?.GetNameInvariant());
                streamNum     = 0;
                containedType = streamTypeService.EventTypes[0];
                resultType    = containedType.UnderlyingType;
                var tableMetadataX = validationContext.TableCompileTimeResolver.ResolveTableFromEventType(containedType);
                forge       = ExprNodeUtilityMake.MakeUnderlyingForge(0, resultType, tableMetadataX);
                istreamOnly = GetIstreamOnly(streamTypeService, 0);
                if ((stateType == AggregationAccessorLinearType.WINDOW) && istreamOnly && !streamTypeService.IsOnDemandStreams)
                {
                    throw MakeUnboundValidationEx(stateType);
                }
            }
            else if (childNodes.Length > 0 && childNodes[0] is ExprStreamUnderlyingNode)
            {
                // validate "stream.*"
                streamNum   = ExprAggMultiFunctionUtil.ValidateStreamWildcardGetStreamNum(childNodes[0]);
                istreamOnly = GetIstreamOnly(streamTypeService, streamNum);
                if ((stateType == AggregationAccessorLinearType.WINDOW) && istreamOnly && !streamTypeService.IsOnDemandStreams)
                {
                    throw MakeUnboundValidationEx(stateType);
                }

                var type = streamTypeService.EventTypes[streamNum];
                containedType = type;
                resultType    = type.UnderlyingType;
                var tableMetadataX = validationContext.TableCompileTimeResolver.ResolveTableFromEventType(type);
                forge = ExprNodeUtilityMake.MakeUnderlyingForge(streamNum, resultType, tableMetadataX);
            }
            else
            {
                // validate when neither wildcard nor "stream.*"
                var child   = childNodes[0];
                var streams = ExprNodeUtilityQuery.GetIdentStreamNumbers(child);
                if (streams.IsEmpty() || (streams.Count > 1))
                {
                    throw new ExprValidationException(
                              GetErrorPrefix(stateType) +
                              " requires that any child expressions evaluate properties of the same stream; Use 'firstever' or 'lastever' or 'nth' instead");
                }

                streamNum   = streams.First();
                istreamOnly = GetIstreamOnly(streamTypeService, streamNum);
                if ((stateType == AggregationAccessorLinearType.WINDOW) && istreamOnly && !streamTypeService.IsOnDemandStreams)
                {
                    throw MakeUnboundValidationEx(stateType);
                }

                resultType = childNodes[0].Forge.EvaluationType;
                forge      = childNodes[0].Forge;
                if (streamNum >= streamTypeService.EventTypes.Length)
                {
                    containedType = streamTypeService.EventTypes[0];
                }
                else
                {
                    containedType = streamTypeService.EventTypes[streamNum];
                }

                scalarCollectionComponentType = resultType;
            }

            if (childNodes.Length > 1)
            {
                if (stateType == AggregationAccessorLinearType.WINDOW)
                {
                    throw new ExprValidationException(GetErrorPrefix(stateType) + " does not accept an index expression; Use 'first' or 'last' instead");
                }

                evaluatorIndex = childNodes[1];
                var indexResultType = evaluatorIndex.Forge.EvaluationType;
                if (indexResultType != typeof(int?) && indexResultType != typeof(int))
                {
                    throw new ExprValidationException(GetErrorPrefix(stateType) + " requires an index expression that returns an integer value");
                }
            }

            // determine accessor
            AggregationAccessorForge accessor;

            if (evaluatorIndex != null)
            {
                var       isFirst  = stateType == AggregationAccessorLinearType.FIRST;
                var       constant = -1;
                ExprForge forgeIndex;
                if (evaluatorIndex.Forge.ForgeConstantType.IsCompileTimeConstant)
                {
                    constant   = evaluatorIndex.Forge.ExprEvaluator.Evaluate(null, true, null).AsInt32();
                    forgeIndex = null;
                }
                else
                {
                    forgeIndex = evaluatorIndex.Forge;
                }

                accessor = new AggregationAccessorFirstLastIndexWEvalForge(streamNum, forge, forgeIndex, constant, isFirst);
            }
            else
            {
                if (stateType == AggregationAccessorLinearType.FIRST)
                {
                    accessor = new AggregationAccessorFirstWEvalForge(streamNum, forge);
                }
                else if (stateType == AggregationAccessorLinearType.LAST)
                {
                    accessor = new AggregationAccessorLastWEvalForge(streamNum, forge);
                }
                else if (stateType == AggregationAccessorLinearType.WINDOW)
                {
                    accessor = new AggregationAccessorWindowWEvalForge(streamNum, forge, resultType);
                }
                else
                {
                    throw new IllegalStateException("Access type is undefined or not known as code '" + stateType + "'");
                }
            }

            var accessorResultType = resultType;

            if (stateType == AggregationAccessorLinearType.WINDOW)
            {
                accessorResultType = TypeHelper.GetArrayType(resultType);
            }

            var isFafWindow   = streamTypeService.IsOnDemandStreams && stateType == AggregationAccessorLinearType.WINDOW;
            var tableMetadata = validationContext.TableCompileTimeResolver.ResolveTableFromEventType(containedType);

            if (tableMetadata == null && !isFafWindow && (istreamOnly || streamTypeService.IsOnDemandStreams))
            {
                if (optionalFilter != null)
                {
                    positionalParams = ExprNodeUtilityMake.AddExpression(positionalParams, optionalFilter);
                }

                var serde = validationContext.SerdeResolver.SerdeForAggregation(accessorResultType, validationContext.StatementRawInfo);
                AggregationForgeFactory factoryX = new AggregationForgeFactoryFirstLastUnbound(this, accessorResultType, optionalFilter != null, serde);
                return(new AggregationLinearFactoryDesc(factoryX, containedType, scalarCollectionComponentType, streamNum));
            }

            var stateKey = new AggregationStateKeyWStream(
                streamNum,
                containedType,
                AggregationStateTypeWStream.DATAWINDOWACCESS_LINEAR,
                ExprNodeUtilityQuery.EMPTY_EXPR_ARRAY,
                optionalFilter);

            var optionalFilterForge = optionalFilter == null ? null : optionalFilter.Forge;
            AggregationStateFactoryForge stateFactory = new AggregationStateLinearForge(this, streamNum, optionalFilterForge);

            var factory = new AggregationForgeFactoryAccessLinear(
                this,
                accessor,
                accessorResultType,
                stateKey,
                stateFactory,
                AggregationAgentDefault.INSTANCE,
                containedType);
            var enumerationType = scalarCollectionComponentType == null ? containedType : null;

            var serdeForgables = SerdeEventTypeUtility.Plan(
                containedType,
                validationContext.StatementRawInfo,
                validationContext.SerdeEventTypeRegistry,
                validationContext.SerdeResolver);

            validationContext.AdditionalForgeables.AddAll(serdeForgables);

            return(new AggregationLinearFactoryDesc(factory, enumerationType, scalarCollectionComponentType, streamNum));
        }
Пример #26
0
        public static StmtForgeMethodSelectResult Make(
            IContainer container,
            bool dataflowOperator,
            string @namespace,
            string classPostfix,
            StatementBaseInfo @base,
            StatementCompileTimeServices services)
        {
            var filterSpecCompileds = new List<FilterSpecCompiled>();
            var scheduleHandleCallbackProviders = new List<ScheduleHandleCallbackProvider>();
            var namedWindowConsumers = new List<NamedWindowConsumerStreamSpec>();
            var statementSpec = @base.StatementSpec;
            var additionalForgeables = new List<StmtClassForgeableFactory>();

            var streamNames = StatementForgeMethodSelectUtil.DetermineStreamNames(statementSpec.StreamSpecs);
            var numStreams = streamNames.Length;
            if (numStreams == 0) {
                throw new ExprValidationException("The from-clause is required but has not been specified");
            }

            // first we create streams for subselects, if there are any
            SubSelectActivationDesc subSelectActivationDesc = SubSelectHelperActivations.CreateSubSelectActivation(
                filterSpecCompileds, namedWindowConsumers, @base, services);
            IDictionary<ExprSubselectNode, SubSelectActivationPlan> subselectActivation = subSelectActivationDesc.Subselects;
            additionalForgeables.AddAll(subSelectActivationDesc.AdditionalForgeables);

            // verify for joins that required views are present
            StreamJoinAnalysisResultCompileTime joinAnalysisResult = StatementForgeMethodSelectUtil.VerifyJoinViews(statementSpec);

            var streamEventTypes = new EventType[statementSpec.StreamSpecs.Length];
            var eventTypeNames = new string[numStreams];
            var isNamedWindow = new bool[numStreams];
            var viewableActivatorForges = new ViewableActivatorForge[numStreams];
            var viewForges = new IList<ViewFactoryForge>[numStreams];
            var historicalEventViewables = new HistoricalEventViewableForge[numStreams];

            for (var stream = 0; stream < numStreams; stream++) {
                var streamSpec = statementSpec.StreamSpecs[stream];
                var isCanIterateUnbound = streamSpec.ViewSpecs.Length == 0 &&
                                          (services.Configuration.Compiler.ViewResources.IsIterableUnbound ||
                                           AnnotationUtil.HasAnnotation(statementSpec.Annotations, typeof(IterableUnboundAttribute)));

                var args = new ViewFactoryForgeArgs(
                    stream,
                    false,
                    -1,
                    streamSpec.Options,
                    null,
                    @base.StatementRawInfo,
                    services);

                if (dataflowOperator) {
                    var dfResult = HandleDataflowActivation(args, streamSpec);
                    streamEventTypes[stream] = dfResult.StreamEventType;
                    eventTypeNames[stream] = dfResult.EventTypeName;
                    viewableActivatorForges[stream] = dfResult.ViewableActivatorForge;
                    viewForges[stream] = dfResult.ViewForges;
                    additionalForgeables.AddAll(dfResult.AdditionalForgeables);
                }
                else if (streamSpec is FilterStreamSpecCompiled) {
                    var filterStreamSpec = (FilterStreamSpecCompiled) statementSpec.StreamSpecs[stream];
                    var filterSpecCompiled = filterStreamSpec.FilterSpecCompiled;
                    streamEventTypes[stream] = filterSpecCompiled.ResultEventType;
                    eventTypeNames[stream] = filterStreamSpec.FilterSpecCompiled.FilterForEventTypeName;

                    viewableActivatorForges[stream] = new ViewableActivatorFilterForge(
                        filterSpecCompiled,
                        isCanIterateUnbound,
                        stream,
                        false,
                        -1);
                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(streamSpec.ViewSpecs, args, streamEventTypes[stream]);
                    viewForges[stream] = viewForgeDesc.Forges;
                    additionalForgeables.AddAll(viewForgeDesc.MultikeyForges);
                    filterSpecCompileds.Add(filterSpecCompiled);
                }
                else if (streamSpec is PatternStreamSpecCompiled) {
                    var patternStreamSpec = (PatternStreamSpecCompiled) streamSpec;
                    var forges = patternStreamSpec.Root.CollectFactories();
                    foreach (var forgeNode in forges) {
                        forgeNode.CollectSelfFilterAndSchedule(filterSpecCompileds, scheduleHandleCallbackProviders);
                    }

                    var patternType = ViewableActivatorPatternForge.MakeRegisterPatternType(
                        @base,
                        stream,
                        patternStreamSpec,
                        services);
                    var patternContext = new PatternContext(0, patternStreamSpec.MatchedEventMapMeta, false, -1, false);
                    viewableActivatorForges[stream] = new ViewableActivatorPatternForge(
                        patternType,
                        patternStreamSpec,
                        patternContext,
                        isCanIterateUnbound);
                    streamEventTypes[stream] = patternType;
                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(streamSpec.ViewSpecs, args, patternType);
                    viewForges[stream] = viewForgeDesc.Forges;
                    additionalForgeables.AddAll(viewForgeDesc.MultikeyForges);
                }
                else if (streamSpec is NamedWindowConsumerStreamSpec) {
                    var namedSpec = (NamedWindowConsumerStreamSpec) streamSpec;
                    var namedWindow =
                        services.NamedWindowCompileTimeResolver.Resolve(namedSpec.NamedWindow.EventType.Name);
                    var namedWindowType = namedWindow.EventType;
                    if (namedSpec.OptPropertyEvaluator != null) {
                        namedWindowType = namedSpec.OptPropertyEvaluator.FragmentEventType;
                    }

                    var typesFilterValidation = new StreamTypeServiceImpl(
                        namedWindowType,
                        namedSpec.OptionalStreamName,
                        false);
                    var filterSingle =
                        ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(namedSpec.FilterExpressions);
                    var filterQueryGraph = EPLValidationUtil.ValidateFilterGetQueryGraphSafe(
                        filterSingle,
                        typesFilterValidation,
                        @base.StatementRawInfo,
                        services);

                    namedWindowConsumers.Add(namedSpec);
                    viewableActivatorForges[stream] = new ViewableActivatorNamedWindowForge(
                        namedSpec,
                        namedWindow,
                        filterSingle,
                        filterQueryGraph,
                        true,
                        namedSpec.OptPropertyEvaluator);
                    streamEventTypes[stream] = namedWindowType;
                    viewForges[stream] = Collections.GetEmptyList<ViewFactoryForge>();
                    joinAnalysisResult.SetNamedWindowsPerStream(stream, namedWindow);
                    eventTypeNames[stream] = namedSpec.NamedWindow.EventType.Name;
                    isNamedWindow[stream] = true;

                    // Consumers to named windows cannot declare a data window view onto the named window to avoid duplicate remove streams
                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(streamSpec.ViewSpecs, args, namedWindowType);
                    viewForges[stream] = viewForgeDesc.Forges;
                    additionalForgeables.AddAll(viewForgeDesc.MultikeyForges);

                    EPStatementStartMethodHelperValidate.ValidateNoDataWindowOnNamedWindow(viewForges[stream]);
                }
                else if (streamSpec is TableQueryStreamSpec) {
                    ValidateNoViews(streamSpec, "Table data");
                    var tableStreamSpec = (TableQueryStreamSpec) streamSpec;
                    if (numStreams > 1 && tableStreamSpec.FilterExpressions.Count > 0) {
                        throw new ExprValidationException(
                            "Joins with tables do not allow table filter expressions, please add table filters to the where-clause instead");
                    }

                    var table = tableStreamSpec.Table;
                    EPLValidationUtil.ValidateContextName(
                        true,
                        table.TableName,
                        table.OptionalContextName,
                        statementSpec.Raw.OptionalContextName,
                        false);
                    var filter =
                        ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(tableStreamSpec.FilterExpressions);
                    viewableActivatorForges[stream] = new ViewableActivatorTableForge(table, filter);
                    viewForges[stream] = Collections.GetEmptyList<ViewFactoryForge>();
                    eventTypeNames[stream] = tableStreamSpec.Table.TableName;
                    streamEventTypes[stream] = tableStreamSpec.Table.InternalEventType;
                    joinAnalysisResult.SetTablesForStream(stream, table);

                    if (tableStreamSpec.Options.IsUnidirectional) {
                        throw new ExprValidationException("Tables cannot be marked as unidirectional");
                    }

                    if (tableStreamSpec.Options.IsRetainIntersection || tableStreamSpec.Options.IsRetainUnion) {
                        throw new ExprValidationException("Tables cannot be marked with retain");
                    }
                }
                else if (streamSpec is DBStatementStreamSpec) {
                    ValidateNoViews(streamSpec, "Historical data");
                    var sqlStreamSpec = (DBStatementStreamSpec) streamSpec;
                    var typeConversionHook = (SQLColumnTypeConversion) ImportUtil.GetAnnotationHook(
                        statementSpec.Annotations,
                        HookType.SQLCOL,
                        typeof(SQLColumnTypeConversion),
                        services.ImportServiceCompileTime);
                    var outputRowConversionHook = (SQLOutputRowConversion) ImportUtil.GetAnnotationHook(
                        statementSpec.Annotations,
                        HookType.SQLROW,
                        typeof(SQLOutputRowConversion),
                        services.ImportServiceCompileTime);
                    var viewable = HistoricalEventViewableDatabaseForgeFactory.CreateDBStatementView(
                        stream,
                        sqlStreamSpec,
                        typeConversionHook,
                        outputRowConversionHook,
                        @base,
                        services,
                        statementSpec.Annotations);
                    streamEventTypes[stream] = viewable.EventType;
                    viewForges[stream] = Collections.GetEmptyList<ViewFactoryForge>();
                    viewableActivatorForges[stream] = new ViewableActivatorHistoricalForge(viewable);
                    historicalEventViewables[stream] = viewable;
                }
                else if (streamSpec is MethodStreamSpec) {
                    ValidateNoViews(streamSpec, "Method data");
                    var methodStreamSpec = (MethodStreamSpec) streamSpec;
                    var viewable = HistoricalEventViewableMethodForgeFactory.CreateMethodStatementView(
                        stream,
                        methodStreamSpec,
                        @base,
                        services);
                    historicalEventViewables[stream] = viewable;
                    streamEventTypes[stream] = viewable.EventType;
                    viewForges[stream] = Collections.GetEmptyList<ViewFactoryForge>();
                    viewableActivatorForges[stream] = new ViewableActivatorHistoricalForge(viewable);
                    historicalEventViewables[stream] = viewable;
                }
                else {
                    throw new IllegalStateException("Unrecognized stream " + streamSpec);
                }
                
                // plan serde for iterate-unbound
                if (isCanIterateUnbound) {
                    var serdeForgeables = SerdeEventTypeUtility.Plan(
                        streamEventTypes[stream], @base.StatementRawInfo, services.SerdeEventTypeRegistry, services.SerdeResolver);
                    additionalForgeables.AddAll(serdeForgeables);
                }
            }

            // handle match-recognize pattern
            if (statementSpec.Raw.MatchRecognizeSpec != null) {
                if (numStreams > 1) {
                    throw new ExprValidationException("Joins are not allowed when using match-recognize");
                }

                if (joinAnalysisResult.TablesPerStream[0] != null) {
                    throw new ExprValidationException("Tables cannot be used with match-recognize");
                }

                var isUnbound = viewForges[0].IsEmpty() &&
                                !(statementSpec.StreamSpecs[0] is NamedWindowConsumerStreamSpec);
                var eventType = viewForges[0].IsEmpty()
                    ? streamEventTypes[0]
                    : viewForges[0][(viewForges[0].Count - 1)].EventType;
                
                var plan = RowRecogNFAViewPlanUtil.ValidateAndPlan(services.Container, eventType, isUnbound, @base, services);
                var forge = new RowRecogNFAViewFactoryForge(plan.Forge);
                additionalForgeables.AddAll(plan.AdditionalForgeables);
                scheduleHandleCallbackProviders.Add(forge);
                viewForges[0].Add(forge);
                var serdeForgeables = SerdeEventTypeUtility.Plan(
                    eventType, @base.StatementRawInfo, services.SerdeEventTypeRegistry, services.SerdeResolver);
                additionalForgeables.AddAll(serdeForgeables);
            }

            // Obtain event types from view factory chains
            for (var i = 0; i < viewForges.Length; i++) {
                streamEventTypes[i] = viewForges[i].IsEmpty()
                    ? streamEventTypes[i]
                    : viewForges[i][(viewForges[i].Count - 1)].EventType;
            }

            // add unique-information to join analysis
            joinAnalysisResult.AddUniquenessInfo(viewForges, statementSpec.Annotations);

            // plan sub-selects
            SubSelectHelperForgePlan subselectForgePlan = SubSelectHelperForgePlanner.PlanSubSelect(
                @base, subselectActivation, streamNames, streamEventTypes, eventTypeNames, services);
            var subselectForges = subselectForgePlan.Subselects;
            additionalForgeables.AddAll(subselectForgePlan.AdditionalForgeables);

            DetermineViewSchedules(subselectForges, scheduleHandleCallbackProviders);

            // determine view schedules
            var viewResourceDelegateExpr = new ViewResourceDelegateExpr();
            ViewFactoryForgeUtil.DetermineViewSchedules(viewForges, scheduleHandleCallbackProviders);

            var hasIStreamOnly = StatementForgeMethodSelectUtil.GetHasIStreamOnly(isNamedWindow, viewForges);
            var optionalStreamsIfAny = OuterJoinAnalyzer.OptionalStreamsIfAny(statementSpec.Raw.OuterJoinDescList);
            StreamTypeService typeService = new StreamTypeServiceImpl(
                streamEventTypes,
                streamNames,
                hasIStreamOnly,
                false,
                optionalStreamsIfAny);

            // Validate views that require validation, specifically streams that don't have
            // sub-views such as DB SQL joins
            var historicalViewableDesc = new HistoricalViewableDesc(numStreams);
            for (var stream = 0; stream < historicalEventViewables.Length; stream++) {
                var historicalEventViewable = historicalEventViewables[stream];
                if (historicalEventViewable == null) {
                    continue;
                }

                scheduleHandleCallbackProviders.Add(historicalEventViewable);
                IList<StmtClassForgeableFactory> forgeables = historicalEventViewable.Validate(typeService, @base, services);
                additionalForgeables.AddAll(forgeables);
                historicalViewableDesc.SetHistorical(stream, historicalEventViewable.RequiredStreams);
                if (historicalEventViewable.RequiredStreams.Contains(stream)) {
                    throw new ExprValidationException(
                        "Parameters for historical stream " +
                        stream +
                        " indicate that the stream is subordinate to itself as stream parameters originate in the same stream");
                }
            }

            // Validate where-clause filter tree, outer join clause and output limit expression
            var whereClauseValidated = EPStatementStartMethodHelperValidate.ValidateNodes(
                statementSpec.Raw,
                typeService,
                viewResourceDelegateExpr,
                @base.StatementRawInfo,
                services);
            var whereClauseForge = whereClauseValidated?.Forge;

            // Obtain result set processor
            var resultSetProcessorDesc = ResultSetProcessorFactoryFactory.GetProcessorPrototype(
                new ResultSetSpec(statementSpec),
                typeService,
                viewResourceDelegateExpr,
                joinAnalysisResult.UnidirectionalInd,
                true,
                @base.ContextPropertyRegistry,
                false,
                false,
                @base.StatementRawInfo,
                services);
            additionalForgeables.AddAll(resultSetProcessorDesc.AdditionalForgeables);

            // Handle 'prior' function nodes in terms of view requirements
            var viewResourceDelegateDesc =
                ViewResourceVerifyHelper.VerifyPreviousAndPriorRequirements(viewForges, viewResourceDelegateExpr);
            var hasPrior = ViewResourceDelegateDesc.HasPrior(viewResourceDelegateDesc);
            if (hasPrior) {
                for (var stream = 0; stream < numStreams; stream++) {
                    if (!viewResourceDelegateDesc[stream].PriorRequests.IsEmpty()) {
                        viewForges[stream].Add(new PriorEventViewForge(viewForges[stream].IsEmpty(), streamEventTypes[stream]));
                        var serdeForgeables = SerdeEventTypeUtility.Plan(
                            streamEventTypes[stream], @base.StatementRawInfo, services.SerdeEventTypeRegistry, services.SerdeResolver);
                        additionalForgeables.AddAll(serdeForgeables);
                    }
                }
            }

            var outputProcessDesc = OutputProcessViewForgeFactory.Make(
                typeService.EventTypes,
                resultSetProcessorDesc.ResultEventType,
                resultSetProcessorDesc.ResultSetProcessorType,
                statementSpec,
                @base.StatementRawInfo,
                services);
            var outputProcessViewFactoryForge = outputProcessDesc.Forge;
            additionalForgeables.AddAll(outputProcessDesc.AdditionalForgeables);
            outputProcessViewFactoryForge.CollectSchedules(scheduleHandleCallbackProviders);

            JoinSetComposerPrototypeForge joinForge = null;
            if (numStreams > 1) {
                var hasAggregations = !resultSetProcessorDesc.AggregationServiceForgeDesc.Expressions.IsEmpty();
                var desc = JoinSetComposerPrototypeForgeFactory.MakeComposerPrototype(
                    statementSpec,
                    joinAnalysisResult,
                    typeService,
                    historicalViewableDesc,
                    false,
                    hasAggregations,
                    @base.StatementRawInfo,
                    services);
                joinForge = desc.Forge;
                additionalForgeables.AddAll(desc.AdditionalForgeables);
                HandleIndexDependencies(joinForge.OptionalQueryPlan, services);
            }

            // plan table access
            var tableAccessForges =
                ExprTableEvalHelperPlan.PlanTableAccess(@base.StatementSpec.TableAccessNodes);
            ValidateTableAccessUse(statementSpec.Raw.IntoTableSpec, statementSpec.Raw.TableExpressions);
            if (joinAnalysisResult.IsUnidirectional && statementSpec.Raw.IntoTableSpec != null) {
                throw new ExprValidationException("Into-table does not allow unidirectional joins");
            }

            var orderByWithoutOutputLimit = statementSpec.Raw.OrderByList != null &&
                                            !statementSpec.Raw.OrderByList.IsEmpty() &&
                                            statementSpec.Raw.OutputLimitSpec == null;

            var statementAIFactoryProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple(
                typeof(StatementAIFactoryProvider),
                classPostfix);
            var resultSetProcessorProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple(
                typeof(ResultSetProcessorFactoryProvider),
                classPostfix);
            var outputProcessViewProviderClassName = CodeGenerationIDGenerator.GenerateClassNameSimple(
                typeof(OutputProcessViewFactoryProvider),
                classPostfix);
            var statementProviderClassName =
                CodeGenerationIDGenerator.GenerateClassNameSimple(typeof(StatementProvider), classPostfix);
            var statementFieldsClassName =
                CodeGenerationIDGenerator.GenerateClassNameSimple(typeof(StatementFields), classPostfix);
            //var statementFieldsClassName = namespaceScope.FieldsClassNameOptional;

            var forgeX = new StatementAgentInstanceFactorySelectForge(
                typeService.StreamNames,
                viewableActivatorForges,
                resultSetProcessorProviderClassName,
                viewForges,
                viewResourceDelegateDesc,
                whereClauseForge,
                joinForge,
                outputProcessViewProviderClassName,
                subselectForges,
                tableAccessForges,
                orderByWithoutOutputLimit,
                joinAnalysisResult.IsUnidirectional);

            var namespaceScope = new CodegenNamespaceScope(
                @namespace,
                statementFieldsClassName,
                services.IsInstrumented);

            var forgeablesX = additionalForgeables
                .Select(additional => additional.Make(namespaceScope, classPostfix))
                .ToList();

            forgeablesX.Add(
                new StmtClassForgeableRSPFactoryProvider(
                    resultSetProcessorProviderClassName,
                    resultSetProcessorDesc,
                    namespaceScope,
                    @base.StatementRawInfo));
            forgeablesX.Add(
                new StmtClassForgeableOPVFactoryProvider(
                    outputProcessViewProviderClassName,
                    outputProcessViewFactoryForge,
                    namespaceScope,
                    numStreams,
                    @base.StatementRawInfo));
            forgeablesX.Add(
                new StmtClassForgeableAIFactoryProviderSelect(statementAIFactoryProviderClassName, namespaceScope, forgeX));
            forgeablesX.Add(
                new StmtClassForgeableStmtFields(statementFieldsClassName, namespaceScope, numStreams));

            if (!dataflowOperator) {
                var informationals = StatementInformationalsUtil.GetInformationals(
                    @base,
                    filterSpecCompileds,
                    scheduleHandleCallbackProviders,
                    namedWindowConsumers,
                    true,
                    resultSetProcessorDesc.SelectSubscriberDescriptor,
                    namespaceScope,
                    services);
                forgeablesX.Add(
                    new StmtClassForgeableStmtProvider(statementAIFactoryProviderClassName, statementProviderClassName, informationals, namespaceScope));
            }

            var forgeableResult = new StmtForgeMethodResult(
                forgeablesX,
                filterSpecCompileds,
                scheduleHandleCallbackProviders,
                namedWindowConsumers,
                FilterSpecCompiled.MakeExprNodeList(filterSpecCompileds, EmptyList<FilterSpecParamExprNodeForge>.Instance));
            return new StmtForgeMethodSelectResult(forgeableResult, resultSetProcessorDesc.ResultEventType, numStreams);
        }
        internal static FilterSpecPlanForge PlanRemainingNodesWithConditions(
            FilterSpecParaForgeMap overallExpressions,
            FilterSpecCompilerArgs args,
            int filterServiceMaxFilterWidth,
            ExprNode topLevelNegator)
        {
            var unassigned = overallExpressions.UnassignedExpressions;
            var orNodes    = new List <ExprOrNode>(unassigned.Count);

            foreach (var node in unassigned)
            {
                if (node is ExprOrNode)
                {
                    orNodes.Add((ExprOrNode)node);
                }
            }

            var expressionsWithoutOr = new FilterSpecParaForgeMap();

            expressionsWithoutOr.Add(overallExpressions);

            // first dimension: or-node index
            // second dimension: or child node index
            var countOr        = 0;
            var sizeFactorized = 1;
            var sizePerOr      = new int[orNodes.Count];
            var orChildNodes   = new OrChildNode[orNodes.Count][];
            var hasControl     = false;

            foreach (var orNode in orNodes)
            {
                expressionsWithoutOr.RemoveNode(orNode);

                // get value-nodes and non-value nodes
                var nonValueNodes = GetNonValueChildNodes(orNode);
                var valueNodes    = new List <ExprNode>(Arrays.AsList(orNode.ChildNodes));
                valueNodes.RemoveAll(nonValueNodes);
                ExprNode singleValueNode = ExprNodeUtilityMake.ConnectExpressionsByLogicalOrWhenNeeded(valueNodes);

                // get all child nodes; last one is confirm if present
                IList <ExprNode> allChildNodes = new List <ExprNode>(nonValueNodes);
                if (singleValueNode != null)
                {
                    allChildNodes.Add(singleValueNode);
                }

                var len = allChildNodes.Count;
                orChildNodes[countOr] = new OrChildNode[len];

                for (var i = 0; i < len; i++)
                {
                    var child = allChildNodes[i];
                    if (child == singleValueNode)
                    {
                        hasControl = true;
                        orChildNodes[countOr][i] = new OrChildNodeV(singleValueNode);
                    }
                    else
                    {
                        var map     = new FilterSpecParaForgeMap();
                        var nodes   = Collections.SingletonList(child);
                        var confirm = DecomposePopulateConsolidate(map, true, nodes, args);
                        if (confirm == null)
                        {
                            orChildNodes[countOr][i] = new OrChildNodeNV(child, map);
                        }
                        else
                        {
                            hasControl = true;
                            orChildNodes[countOr][i] = new OrChildNodeNVNegated(child, map, confirm);
                        }
                    }
                }

                sizePerOr[countOr] = len;
                sizeFactorized     = sizeFactorized * len;
                countOr++;
            }

            // compute permutations
            var permutations           = new CombPermutationTriplets[sizeFactorized];
            var combinationEnumeration = CombinationEnumeration.FromZeroBasedRanges(sizePerOr);
            var count = 0;

            foreach (var permutation in combinationEnumeration)
            {
                permutations[count] = ComputePermutation(expressionsWithoutOr, permutation, orChildNodes, hasControl, args);
                count++;
            }

            // Remove any permutations that only have a control-confirm
            var result             = new List <FilterSpecPlanPathForge>(sizeFactorized);
            var pathControlConfirm = new List <ExprNode>();

            foreach (var permutation in permutations)
            {
                if (permutation.Triplets.Length > 0)
                {
                    result.Add(new FilterSpecPlanPathForge(permutation.Triplets, permutation.NegateCondition));
                }
                else
                {
                    pathControlConfirm.Add(permutation.NegateCondition);
                }
            }

            if (result.Count > filterServiceMaxFilterWidth)
            {
                return(null);
            }

            var      pathArray         = result.ToArray();
            ExprNode topLevelConfirmer = ExprNodeUtilityMake.ConnectExpressionsByLogicalOrWhenNeeded(pathControlConfirm);

            // determine when the path-negate condition is the same as the root confirm-expression
            if (topLevelConfirmer != null)
            {
                var not = new ExprNotNode();
                not.AddChildNode(topLevelConfirmer);
                foreach (var path in pathArray)
                {
                    if (ExprNodeUtilityCompare.DeepEquals(not, path.PathNegate, true))
                    {
                        path.PathNegate = null;
                    }
                }
            }

            var convertor = new MatchedEventConvertorForge(
                args.taggedEventTypes,
                args.arrayEventTypes,
                args.allTagNamesOrdered,
                null,
                true);

            return(new FilterSpecPlanForge(pathArray, topLevelConfirmer, topLevelNegator, convertor));
        }