Пример #1
0
        public static void Validate3Stream(ExprNode topNode)
        {
            var streamTypeService = new SupportStreamTypeSvc3Stream();

            var factoriesPerStream = new ViewFactoryChain[3];

            for (var i = 0; i < factoriesPerStream.Length; i++)
            {
                var factories = new List <ViewFactory>();
                factories.Add(new LengthWindowViewFactory());
                factoriesPerStream[i] = new ViewFactoryChain(streamTypeService.EventTypes[i], factories);
            }
            var viewResources = new ViewResourceDelegateUnverified();

            VariableService variableService = new VariableServiceImpl(0, new SchedulingServiceImpl(new TimeSourceServiceImpl()), SupportEventAdapterService.Service, null);

            variableService.CreateNewVariable(null, "IntPrimitive", typeof(int?).FullName, false, false, false, 10, null);
            variableService.AllocateVariableState("IntPrimitive", 0, null);
            variableService.CreateNewVariable(null, "var1", typeof(string).FullName, false, false, false, "my_variable_value", null);
            variableService.AllocateVariableState("var1", 0, null);

            ExprNodeUtility.GetValidatedSubtree(
                ExprNodeOrigin.SELECT, topNode, new ExprValidationContext(
                    streamTypeService, MethodResService, viewResources,
                    null, variableService, null,
                    new SupportExprEvaluatorContext(null),
                    null, null, null, null, null, null,
                    false, false, false, false, null, false));
        }
Пример #2
0
        public ExprValidationContext(StreamTypeService streamTypeService, EngineImportService engineImportService, StatementExtensionSvcContext statementExtensionSvcContext, ViewResourceDelegateUnverified viewResourceDelegate, TimeProvider timeProvider, VariableService variableService, TableService tableService, ExprEvaluatorContext exprEvaluatorContext, EventAdapterService eventAdapterService, string statementName, int statementId, Attribute[] annotations, ContextDescriptor contextDescriptor, ScriptingService scriptingService, bool disablePropertyExpressionEventCollCache, bool allowRollupFunctions, bool allowBindingConsumption, bool isUnidirectionalJoin, string intoTableName, bool isFilterExpression)
        {
            StreamTypeService            = streamTypeService;
            EngineImportService          = engineImportService;
            StatementExtensionSvcContext = statementExtensionSvcContext;
            ViewResourceDelegate         = viewResourceDelegate;
            TimeProvider         = timeProvider;
            VariableService      = variableService;
            TableService         = tableService;
            ExprEvaluatorContext = exprEvaluatorContext;
            EventAdapterService  = eventAdapterService;
            StatementName        = statementName;
            StatementId          = statementId;
            Annotations          = annotations;
            ContextDescriptor    = contextDescriptor;
            ScriptingService     = scriptingService;
            IsDisablePropertyExpressionEventCollCache = disablePropertyExpressionEventCollCache;
            IsAllowRollupFunctions    = allowRollupFunctions;
            IsAllowBindingConsumption = allowBindingConsumption;
            IsResettingAggregations   = isUnidirectionalJoin;
            IntoTableName             = intoTableName;
            IsFilterExpression        = isFilterExpression;

            IsExpressionAudit       = AuditEnum.EXPRESSION.GetAudit(annotations) != null;
            IsExpressionNestedAudit = AuditEnum.EXPRESSION_NESTED.GetAudit(annotations) != null;
        }
Пример #3
0
 public EPStatementStartMethodSelectDesc(
     StatementAgentInstanceFactorySelect statementAgentInstanceFactorySelect,
     SubSelectStrategyCollection subSelectStrategyCollection,
     ViewResourceDelegateUnverified viewResourceDelegateUnverified,
     ResultSetProcessorFactoryDesc resultSetProcessorPrototypeDesc,
     EPStatementStopMethod stopMethod,
     EPStatementDestroyCallbackList destroyCallbacks)
 {
     StatementAgentInstanceFactorySelect = statementAgentInstanceFactorySelect;
     SubSelectStrategyCollection         = subSelectStrategyCollection;
     ViewResourceDelegateUnverified      = viewResourceDelegateUnverified;
     ResultSetProcessorPrototypeDesc     = resultSetProcessorPrototypeDesc;
     StopMethod       = stopMethod;
     DestroyCallbacks = destroyCallbacks;
 }
Пример #4
0
        public static void Validate3Stream(ExprNode topNode)
        {
            var supportContainer  = SupportContainer.Instance;
            var streamTypeService = new SupportStreamTypeSvc3Stream();

            var factoriesPerStream = new ViewFactoryChain[3];

            for (var i = 0; i < factoriesPerStream.Length; i++)
            {
                var factories = new List <ViewFactory>();
                factories.Add(new LengthWindowViewFactory());
                factoriesPerStream[i] = new ViewFactoryChain(streamTypeService.EventTypes[i], factories);
            }
            var viewResources = new ViewResourceDelegateUnverified();

            EngineImportService engineImportService = SupportEngineImportServiceFactory.Make(supportContainer);

            VariableService variableService = new VariableServiceImpl(
                supportContainer, 0,
                new SchedulingServiceImpl(new TimeSourceServiceImpl(), supportContainer),
                SupportContainer.Resolve <EventAdapterService>(),
                null);

            variableService.CreateNewVariable(null, "IntPrimitive", typeof(int?).FullName, false, false, false, 10, engineImportService);
            variableService.AllocateVariableState("IntPrimitive", EPStatementStartMethodConst.DEFAULT_AGENT_INSTANCE_ID, null, false);
            variableService.CreateNewVariable(null, "var1", typeof(string).FullName, false, false, false, "my_variable_value", engineImportService);
            variableService.AllocateVariableState("var1", EPStatementStartMethodConst.DEFAULT_AGENT_INSTANCE_ID, null, false);

            ExprNodeUtility.GetValidatedSubtree(
                ExprNodeOrigin.SELECT, topNode, new ExprValidationContext(
                    supportContainer,
                    streamTypeService,
                    SupportEngineImportServiceFactory.Make(supportContainer),
                    null, viewResources,
                    null, variableService, null,
                    new SupportExprEvaluatorContext(supportContainer, null),
                    null, null, 1, null, null, null,
                    false, false, false, false, null, false));
        }
        public static ViewResourceDelegateVerified VerifyPreviousAndPriorRequirements(ViewFactoryChain[] unmaterializedViewChain, ViewResourceDelegateUnverified @delegate)
        {
            var hasPriorNodes    = [email protected]();
            var hasPreviousNodes = [email protected]();

            var numStreams = unmaterializedViewChain.Length;
            var perStream  = new ViewResourceDelegateVerifiedStream[numStreams];

            // verify "previous"
            var previousPerStream = new IList <ExprPreviousNode> [numStreams];

            foreach (var previousNode in @delegate.PreviousRequests)
            {
                var stream    = previousNode.StreamNumber;
                var factories = unmaterializedViewChain[stream].FactoryChain;

                var pass = InspectViewFactoriesForPrevious(factories);
                if (!pass)
                {
                    throw new ExprValidationException("Previous function requires a single data window view onto the stream");
                }

                var found = factories.OfType <DataWindowViewWithPrevious>().Any();
                if (!found)
                {
                    throw new ExprValidationException("Required data window not found for the 'prev' function, specify a data window for which previous events are retained");
                }

                if (previousPerStream[stream] == null)
                {
                    previousPerStream[stream] = new List <ExprPreviousNode>();
                }
                previousPerStream[stream].Add(previousNode);
            }

            // verify "prior"
            var priorPerStream = new IDictionary <int, IList <ExprPriorNode> > [numStreams];

            foreach (var priorNode in @delegate.PriorRequests)
            {
                var stream = priorNode.StreamNumber;

                if (priorPerStream[stream] == null)
                {
                    priorPerStream[stream] = new SortedDictionary <int, IList <ExprPriorNode> >();
                }

                var treemap      = priorPerStream[stream];
                var callbackList = treemap.Get(priorNode.ConstantIndexNumber);
                if (callbackList == null)
                {
                    callbackList = new List <ExprPriorNode>();
                    treemap.Put(priorNode.ConstantIndexNumber, callbackList);
                }
                callbackList.Add(priorNode);
            }

            // build per-stream info
            for (var i = 0; i < numStreams; i++)
            {
                if (previousPerStream[i] == null)
                {
                    previousPerStream[i] = Collections.GetEmptyList <ExprPreviousNode>();
                }
                if (priorPerStream[i] == null)
                {
                    priorPerStream[i] = new OrderedDictionary <int, IList <ExprPriorNode> >();
                }

                // determine match-recognize "prev"
                var matchRecognizePrevious = Collections.GetEmptySet <ExprPreviousMatchRecognizeNode>();
                if (i == 0)
                {
                    foreach (var viewFactory in unmaterializedViewChain[i].FactoryChain)
                    {
                        if (viewFactory is EventRowRegexNFAViewFactory)
                        {
                            var matchRecognize = (EventRowRegexNFAViewFactory)viewFactory;
                            matchRecognizePrevious = matchRecognize.PreviousExprNodes;
                        }
                    }
                }

                perStream[i] = new ViewResourceDelegateVerifiedStream(previousPerStream[i], priorPerStream[i], matchRecognizePrevious);
            }

            return(new ViewResourceDelegateVerified(hasPriorNodes, hasPreviousNodes, perStream));
        }
        /// <summary>
        /// Validate filter and join expression nodes.
        /// </summary>
        /// <param name="statementSpec">the compiled statement</param>
        /// <param name="statementContext">the statement services</param>
        /// <param name="typeService">the event types for streams</param>
        /// <param name="viewResourceDelegate">the delegate to verify expressions that use view resources</param>
        internal static void ValidateNodes(
            StatementSpecCompiled statementSpec,
            StatementContext statementContext,
            StreamTypeService typeService,
            ViewResourceDelegateUnverified viewResourceDelegate)
        {
            var methodResolutionService = statementContext.MethodResolutionService;
            var evaluatorContextStmt    = new ExprEvaluatorContextStatement(statementContext, false);
            var intoTableName           = statementSpec.IntoTableSpec == null ? null : statementSpec.IntoTableSpec.Name;

            if (statementSpec.FilterRootNode != null)
            {
                var optionalFilterNode = statementSpec.FilterRootNode;

                // Validate where clause, initializing nodes to the stream ids used
                try
                {
                    var validationContext = new ExprValidationContext(
                        typeService,
                        methodResolutionService,
                        viewResourceDelegate,
                        statementContext.SchedulingService,
                        statementContext.VariableService,
                        statementContext.TableService,
                        evaluatorContextStmt,
                        statementContext.EventAdapterService,
                        statementContext.StatementName,
                        statementContext.StatementId,
                        statementContext.Annotations,
                        statementContext.ContextDescriptor,
                        statementContext.ScriptingService,
                        false, false, true, false,
                        intoTableName, false);
                    optionalFilterNode = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.FILTER, optionalFilterNode, validationContext);
                    if (optionalFilterNode.ExprEvaluator.ReturnType != typeof(bool) && optionalFilterNode.ExprEvaluator.ReturnType != typeof(bool?))
                    {
                        throw new ExprValidationException("The where-clause filter expression must return a boolean value");
                    }
                    statementSpec.FilterExprRootNode = optionalFilterNode;

                    // Make sure there is no aggregation in the where clause
                    var aggregateNodes = new List <ExprAggregateNode>();
                    ExprAggregateNodeUtil.GetAggregatesBottomUp(optionalFilterNode, aggregateNodes);
                    if (!aggregateNodes.IsEmpty())
                    {
                        throw new ExprValidationException("An aggregate function may not appear in a WHERE clause (use the HAVING clause)");
                    }
                }
                catch (ExprValidationException ex)
                {
                    Log.Debug(".validateNodes Validation exception for filter=" + ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(optionalFilterNode), ex);
                    throw new EPStatementException("Error validating expression: " + ex.Message, ex, statementContext.Expression);
                }
            }

            if ((statementSpec.OutputLimitSpec != null) && ((statementSpec.OutputLimitSpec.WhenExpressionNode != null) || (statementSpec.OutputLimitSpec.AndAfterTerminateExpr != null)))
            {
                // Validate where clause, initializing nodes to the stream ids used
                try
                {
                    var outputLimitType = OutputConditionExpressionFactory.GetBuiltInEventType(statementContext.EventAdapterService);
                    StreamTypeService typeServiceOutputWhen = new StreamTypeServiceImpl(new EventType[] { outputLimitType }, new String[] { null }, new bool[] { true }, statementContext.EngineURI, false);
                    var validationContext = new ExprValidationContext(
                        typeServiceOutputWhen,
                        methodResolutionService, null,
                        statementContext.SchedulingService,
                        statementContext.VariableService,
                        statementContext.TableService,
                        evaluatorContextStmt,
                        statementContext.EventAdapterService,
                        statementContext.StatementName,
                        statementContext.StatementId,
                        statementContext.Annotations,
                        statementContext.ContextDescriptor,
                        statementContext.ScriptingService,
                        false, false, false, false,
                        intoTableName, false);

                    var outputLimitWhenNode = statementSpec.OutputLimitSpec.WhenExpressionNode;
                    if (outputLimitWhenNode != null)
                    {
                        outputLimitWhenNode = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.OUTPUTLIMIT, outputLimitWhenNode, validationContext);
                        statementSpec.OutputLimitSpec.WhenExpressionNode = outputLimitWhenNode;

                        if (TypeHelper.GetBoxedType(outputLimitWhenNode.ExprEvaluator.ReturnType) != typeof(bool?))
                        {
                            throw new ExprValidationException("The when-trigger expression in the OUTPUT WHEN clause must return a boolean-type value");
                        }
                        EPStatementStartMethodHelperValidate.ValidateNoAggregations(outputLimitWhenNode, "An aggregate function may not appear in a OUTPUT LIMIT clause");
                    }

                    // validate and-terminate expression if provided
                    if (statementSpec.OutputLimitSpec.AndAfterTerminateExpr != null)
                    {
                        if (statementSpec.OutputLimitSpec.RateType != OutputLimitRateType.WHEN_EXPRESSION && statementSpec.OutputLimitSpec.RateType != OutputLimitRateType.TERM)
                        {
                            throw new ExprValidationException("A terminated-and expression must be used with the OUTPUT WHEN clause");
                        }
                        var validated = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.OUTPUTLIMIT, statementSpec.OutputLimitSpec.AndAfterTerminateExpr, validationContext);
                        statementSpec.OutputLimitSpec.AndAfterTerminateExpr = validated;

                        if (validated.ExprEvaluator.ReturnType.GetBoxedType() != typeof(bool?))
                        {
                            throw new ExprValidationException("The terminated-and expression must return a boolean-type value");
                        }
                        EPStatementStartMethodHelperValidate.ValidateNoAggregations(validated, "An aggregate function may not appear in a terminated-and clause");
                    }

                    // validate then-expression
                    ValidateThenSetAssignments(statementSpec.OutputLimitSpec.ThenExpressions, validationContext);

                    // validate after-terminated then-expression
                    ValidateThenSetAssignments(statementSpec.OutputLimitSpec.AndAfterTerminateThenExpressions, validationContext);
                }
                catch (ExprValidationException ex)
                {
                    throw new EPStatementException("Error validating expression: " + ex.Message, statementContext.Expression);
                }
            }

            for (var outerJoinCount = 0; outerJoinCount < statementSpec.OuterJoinDescList.Length; outerJoinCount++)
            {
                var outerJoinDesc = statementSpec.OuterJoinDescList[outerJoinCount];

                // validate on-expression nodes, if provided
                if (outerJoinDesc.OptLeftNode != null)
                {
                    var streamIdPair = ValidateOuterJoinPropertyPair(statementContext, outerJoinDesc.OptLeftNode, outerJoinDesc.OptRightNode, outerJoinCount,
                                                                     typeService, viewResourceDelegate);

                    if (outerJoinDesc.AdditionalLeftNodes != null)
                    {
                        ISet <int?> streamSet = new HashSet <int?>();
                        streamSet.Add(streamIdPair.First);
                        streamSet.Add(streamIdPair.Second);
                        for (var i = 0; i < outerJoinDesc.AdditionalLeftNodes.Length; i++)
                        {
                            var streamIdPairAdd = ValidateOuterJoinPropertyPair(statementContext, outerJoinDesc.AdditionalLeftNodes[i], outerJoinDesc.AdditionalRightNodes[i], outerJoinCount,
                                                                                typeService, viewResourceDelegate);

                            // make sure all additional properties point to the same two streams
                            if ((!streamSet.Contains(streamIdPairAdd.First) || (!streamSet.Contains(streamIdPairAdd.Second))))
                            {
                                const string message = "Outer join ON-clause columns must refer to properties of the same joined streams" +
                                                       " when using multiple columns in the on-clause";
                                throw new EPStatementException("Error validating expression: " + message, statementContext.Expression);
                            }
                        }
                    }
                }
            }
        }
        internal static UniformPair <int?> ValidateOuterJoinPropertyPair(
            StatementContext statementContext,
            ExprIdentNode leftNode,
            ExprIdentNode rightNode,
            int outerJoinCount,
            StreamTypeService typeService,
            ViewResourceDelegateUnverified viewResourceDelegate)
        {
            // Validate the outer join clause using an artificial equals-node on top.
            // Thus types are checked via equals.
            // Sets stream ids used for validated nodes.
            ExprNode equalsNode = new ExprEqualsNodeImpl(false, false);

            equalsNode.AddChildNode(leftNode);
            equalsNode.AddChildNode(rightNode);
            var evaluatorContextStmt = new ExprEvaluatorContextStatement(statementContext, false);

            try
            {
                var validationContext = new ExprValidationContext(
                    typeService,
                    statementContext.MethodResolutionService, viewResourceDelegate,
                    statementContext.SchedulingService,
                    statementContext.VariableService,
                    statementContext.TableService,
                    evaluatorContextStmt,
                    statementContext.EventAdapterService,
                    statementContext.StatementName,
                    statementContext.StatementId,
                    statementContext.Annotations,
                    statementContext.ContextDescriptor,
                    statementContext.ScriptingService,
                    false, false, true, false,
                    null, false);
                ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.JOINON, equalsNode, validationContext);
            }
            catch (ExprValidationException ex)
            {
                Log.Debug("Validation exception for outer join node=" + ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(equalsNode), ex);
                throw new EPStatementException("Error validating expression: " + ex.Message, statementContext.Expression);
            }

            // Make sure we have left-hand-side and right-hand-side refering to different streams
            var streamIdLeft  = leftNode.StreamId;
            var streamIdRight = rightNode.StreamId;

            if (streamIdLeft == streamIdRight)
            {
                const string message = "Outer join ON-clause cannot refer to properties of the same stream";
                throw new EPStatementException("Error validating expression: " + message, statementContext.Expression);
            }

            // Make sure one of the properties refers to the acutual stream currently being joined
            var expectedStreamJoined = outerJoinCount + 1;

            if ((streamIdLeft != expectedStreamJoined) && (streamIdRight != expectedStreamJoined))
            {
                var message = "Outer join ON-clause must refer to at least one property of the joined stream" +
                              " for stream " + expectedStreamJoined;
                throw new EPStatementException("Error validating expression: " + message, statementContext.Expression);
            }

            // Make sure neither of the streams refer to a 'future' stream
            String badPropertyName = null;

            if (streamIdLeft > outerJoinCount + 1)
            {
                badPropertyName = leftNode.ResolvedPropertyName;
            }
            if (streamIdRight > outerJoinCount + 1)
            {
                badPropertyName = rightNode.ResolvedPropertyName;
            }
            if (badPropertyName != null)
            {
                var message = "Outer join ON-clause invalid scope for property" +
                              " '" + badPropertyName + "', expecting the current or a prior stream scope";
                throw new EPStatementException("Error validating expression: " + message, statementContext.Expression);
            }

            return(new UniformPair <int?>(streamIdLeft, streamIdRight));
        }
Пример #8
0
        private static void HandleSubselectSelectClauses(
            int subselectStreamNumber,
            StatementContext statementContext,
            ExprSubselectNode subselect,
            EventType outerEventType,
            string outerEventTypeName,
            string outerStreamName,
            IDictionary <string, Pair <EventType, string> > taggedEventTypes,
            IDictionary <string, Pair <EventType, string> > arrayEventTypes)
        {
            var statementSpec    = subselect.StatementSpecCompiled;
            var filterStreamSpec = statementSpec.StreamSpecs[0];

            ViewFactoryChain viewFactoryChain;
            string           subselecteventTypeName = null;

            // construct view factory chain
            try {
                if (statementSpec.StreamSpecs[0] is FilterStreamSpecCompiled)
                {
                    var filterStreamSpecCompiled = (FilterStreamSpecCompiled)statementSpec.StreamSpecs[0];
                    subselecteventTypeName = filterStreamSpecCompiled.FilterSpec.FilterForEventTypeName;

                    // A child view is required to limit the stream
                    if (filterStreamSpec.ViewSpecs.Length == 0)
                    {
                        throw new ExprValidationException("Subqueries require one or more views to limit the stream, consider declaring a length or time window");
                    }

                    // Register filter, create view factories
                    viewFactoryChain       = statementContext.ViewService.CreateFactories(subselectStreamNumber, filterStreamSpecCompiled.FilterSpec.ResultEventType, filterStreamSpec.ViewSpecs, filterStreamSpec.Options, statementContext);
                    subselect.RawEventType = viewFactoryChain.EventType;
                }
                else
                {
                    var namedSpec = (NamedWindowConsumerStreamSpec)statementSpec.StreamSpecs[0];
                    var processor = statementContext.NamedWindowService.GetProcessor(namedSpec.WindowName);
                    viewFactoryChain       = statementContext.ViewService.CreateFactories(0, processor.NamedWindowType, namedSpec.ViewSpecs, namedSpec.Options, statementContext);
                    subselecteventTypeName = namedSpec.WindowName;
                    EPLValidationUtil.ValidateContextName(false, processor.NamedWindowName, processor.ContextName, statementContext.ContextName, true);
                }
            }
            catch (ViewProcessingException ex) {
                throw new ExprValidationException("Error validating subexpression: " + ex.Message, ex);
            }

            // the final event type
            var eventType = viewFactoryChain.EventType;

            // determine a stream name unless one was supplied
            var subexpressionStreamName = filterStreamSpec.OptionalStreamName;

            if (subexpressionStreamName == null)
            {
                subexpressionStreamName = "$subselect_" + subselectStreamNumber;
            }

            // Named windows don't allow data views
            if (filterStreamSpec is NamedWindowConsumerStreamSpec)
            {
                EPStatementStartMethodHelperValidate.ValidateNoDataWindowOnNamedWindow(viewFactoryChain.FactoryChain);
            }

            // Streams event types are the original stream types with the stream zero the subselect stream
            var namesAndTypes = new LinkedHashMap <string, Pair <EventType, string> >();

            namesAndTypes.Put(subexpressionStreamName, new Pair <EventType, string>(eventType, subselecteventTypeName));
            namesAndTypes.Put(outerStreamName, new Pair <EventType, string>(outerEventType, outerEventTypeName));
            if (taggedEventTypes != null)
            {
                foreach (KeyValuePair <string, Pair <EventType, string> > entry in taggedEventTypes)
                {
                    namesAndTypes.Put(entry.Key, new Pair <EventType, string>(entry.Value.First, entry.Value.Second));
                }
            }
            if (arrayEventTypes != null)
            {
                foreach (KeyValuePair <string, Pair <EventType, string> > entry in arrayEventTypes)
                {
                    namesAndTypes.Put(entry.Key, new Pair <EventType, string>(entry.Value.First, entry.Value.Second));
                }
            }
            StreamTypeService subselectTypeService = new StreamTypeServiceImpl(namesAndTypes, statementContext.EngineURI, true, true);
            var viewResourceDelegateSubselect      = new ViewResourceDelegateUnverified();

            subselect.FilterSubqueryStreamTypes = subselectTypeService;

            // Validate select expression
            var selectClauseSpec = subselect.StatementSpecCompiled.SelectClauseSpec;

            if (selectClauseSpec.SelectExprList.Length > 0)
            {
                if (selectClauseSpec.SelectExprList.Length > 1)
                {
                    throw new ExprValidationException("Subquery multi-column select is not allowed in this context.");
                }

                var element = selectClauseSpec.SelectExprList[0];
                if (element is SelectClauseExprCompiledSpec)
                {
                    // validate
                    var compiled             = (SelectClauseExprCompiledSpec)element;
                    var selectExpression     = compiled.SelectExpression;
                    var evaluatorContextStmt = new ExprEvaluatorContextStatement(statementContext, false);
                    var validationContext    = new ExprValidationContext(
                        subselectTypeService, statementContext.MethodResolutionService, viewResourceDelegateSubselect,
                        statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService,
                        evaluatorContextStmt, statementContext.EventAdapterService, statementContext.StatementName,
                        statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor,
                        statementContext.ScriptingService,
                        false, false, true, false, null, false);
                    selectExpression        = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.SUBQUERYSELECT, selectExpression, validationContext);
                    subselect.SelectClause  = new ExprNode[] { selectExpression };
                    subselect.SelectAsNames = new string[] { compiled.AssignedName };

                    // handle aggregation
                    var aggExprNodes = new List <ExprAggregateNode>();
                    ExprAggregateNodeUtil.GetAggregatesBottomUp(selectExpression, aggExprNodes);
                    if (aggExprNodes.Count > 0)
                    {
                        // Other stream properties, if there is aggregation, cannot be under aggregation.
                        foreach (var aggNode in aggExprNodes)
                        {
                            var propertiesNodesAggregated = ExprNodeUtility.GetExpressionProperties(aggNode, true);
                            foreach (var pair in propertiesNodesAggregated)
                            {
                                if (pair.First != 0)
                                {
                                    throw new ExprValidationException("Subselect aggregation function cannot aggregate across correlated properties");
                                }
                            }
                        }

                        // This stream (stream 0) properties must either all be under aggregation, or all not be.
                        var propertiesNotAggregated = ExprNodeUtility.GetExpressionProperties(selectExpression, false);
                        foreach (var pair in propertiesNotAggregated)
                        {
                            if (pair.First == 0)
                            {
                                throw new ExprValidationException("Subselect properties must all be within aggregation functions");
                            }
                        }
                    }
                }
            }
        }
        public static EPStatementStartMethodSelectDesc Prepare(
            StatementSpecCompiled statementSpec,
            EPServicesContext services,
            StatementContext statementContext,
            bool recoveringResilient,
            AgentInstanceContext defaultAgentInstanceContext,
            bool queryPlanLogging,
            ViewableActivatorFactory optionalViewableActivatorFactory,
            OutputProcessViewCallback optionalOutputProcessViewCallback,
            SelectExprProcessorDeliveryCallback selectExprProcessorDeliveryCallback)
        {
            // define stop and destroy
            var stopCallbacks    = new List <StopCallback>();
            var destroyCallbacks = new EPStatementDestroyCallbackList();

            // determine context
            var contextName             = statementSpec.OptionalContextName;
            var contextPropertyRegistry = (contextName != null) ? services.ContextManagementService.GetContextDescriptor(contextName).ContextPropertyRegistry : null;

            // Determine stream names for each stream - some streams may not have a name given
            var streamNames = EPStatementStartMethodHelperUtil.DetermineStreamNames(statementSpec.StreamSpecs);
            var numStreams  = streamNames.Length;

            if (numStreams == 0)
            {
                throw new ExprValidationException("The from-clause is required but has not been specified");
            }
            var isJoin     = statementSpec.StreamSpecs.Length > 1;
            var hasContext = statementSpec.OptionalContextName != null;

            // First we create streams for subselects, if there are any
            var subSelectStreamDesc = EPStatementStartMethodHelperSubselect.CreateSubSelectActivation(services, statementSpec, statementContext, destroyCallbacks);

            // Create streams and views
            var eventStreamParentViewableActivators = new ViewableActivator[numStreams];
            var unmaterializedViewChain             = new ViewFactoryChain[numStreams];
            var eventTypeNames           = new string[numStreams];
            var isNamedWindow            = new bool[numStreams];
            var historicalEventViewables = new HistoricalEventViewable[numStreams];

            // verify for joins that required views are present
            var joinAnalysisResult   = VerifyJoinViews(statementSpec, statementContext.NamedWindowMgmtService, defaultAgentInstanceContext);
            var evaluatorContextStmt = new ExprEvaluatorContextStatement(statementContext, false);

            for (var i = 0; i < statementSpec.StreamSpecs.Length; i++)
            {
                var streamSpec = statementSpec.StreamSpecs[i];

                var isCanIterateUnbound = streamSpec.ViewSpecs.Length == 0 &&
                                          (services.ConfigSnapshot.EngineDefaults.ViewResourcesConfig.IsIterableUnbound ||
                                           AnnotationUtil.FindAttribute(statementSpec.Annotations, typeof(IterableUnboundAttribute)) != null);

                // Create view factories and parent view based on a filter specification
                if (streamSpec is FilterStreamSpecCompiled)
                {
                    var filterStreamSpec = (FilterStreamSpecCompiled)streamSpec;
                    eventTypeNames[i] = filterStreamSpec.FilterSpec.FilterForEventTypeName;

                    // Since only for non-joins we get the existing stream's lock and try to reuse it's views
                    var filterSubselectSameStream = EPStatementStartMethodHelperUtil.DetermineSubquerySameStream(statementSpec, filterStreamSpec);

                    // create activator
                    ViewableActivator activatorDeactivator;
                    if (optionalViewableActivatorFactory != null)
                    {
                        activatorDeactivator = optionalViewableActivatorFactory.CreateActivatorSimple(filterStreamSpec);
                        if (activatorDeactivator == null)
                        {
                            throw new IllegalStateException("Viewable activate is null for " + filterStreamSpec.FilterSpec.FilterForEventType.Name);
                        }
                    }
                    else
                    {
                        if (!hasContext)
                        {
                            activatorDeactivator = services.ViewableActivatorFactory.CreateStreamReuseView(services, statementContext, statementSpec, filterStreamSpec, isJoin, evaluatorContextStmt, filterSubselectSameStream, i, isCanIterateUnbound);
                        }
                        else
                        {
                            InstrumentationAgent instrumentationAgentFilter = null;
                            if (InstrumentationHelper.ENABLED)
                            {
                                var eventTypeName = filterStreamSpec.FilterSpec.FilterForEventType.Name;
                                var streamNumber  = i;
                                instrumentationAgentFilter = new ProxyInstrumentationAgent()
                                {
                                    ProcIndicateQ = () => {
                                        InstrumentationHelper.Get().QFilterActivationStream(eventTypeName, streamNumber);
                                    },
                                    ProcIndicateA = () => {
                                        InstrumentationHelper.Get().AFilterActivationStream();
                                    },
                                };
                            }

                            activatorDeactivator = services.ViewableActivatorFactory.CreateFilterProxy(services, filterStreamSpec.FilterSpec, statementSpec.Annotations, false, instrumentationAgentFilter, isCanIterateUnbound, i);
                        }
                    }
                    eventStreamParentViewableActivators[i] = activatorDeactivator;

                    var resultEventType = filterStreamSpec.FilterSpec.ResultEventType;
                    unmaterializedViewChain[i] = services.ViewService.CreateFactories(i, resultEventType, streamSpec.ViewSpecs, streamSpec.Options, statementContext, false, -1);
                }
                // Create view factories and parent view based on a pattern expression
                else if (streamSpec is PatternStreamSpecCompiled)
                {
                    var patternStreamSpec = (PatternStreamSpecCompiled)streamSpec;
                    var usedByChildViews  = streamSpec.ViewSpecs.Length > 0 || (statementSpec.InsertIntoDesc != null);
                    var patternTypeName   = statementContext.StatementId + "_pattern_" + i;
                    var eventType         = services.EventAdapterService.CreateSemiAnonymousMapType(patternTypeName, patternStreamSpec.TaggedEventTypes, patternStreamSpec.ArrayEventTypes, usedByChildViews);
                    unmaterializedViewChain[i] = services.ViewService.CreateFactories(i, eventType, streamSpec.ViewSpecs, streamSpec.Options, statementContext, false, -1);

                    var rootFactoryNode = services.PatternNodeFactory.MakeRootNode(patternStreamSpec.EvalFactoryNode);
                    var patternContext  = statementContext.PatternContextFactory.CreateContext(statementContext, i, rootFactoryNode, patternStreamSpec.MatchedEventMapMeta, true);

                    // create activator
                    var patternActivator = services.ViewableActivatorFactory.CreatePattern(patternContext, rootFactoryNode, eventType, EPStatementStartMethodHelperUtil.IsConsumingFilters(patternStreamSpec.EvalFactoryNode), patternStreamSpec.IsSuppressSameEventMatches, patternStreamSpec.IsDiscardPartialsOnMatch, isCanIterateUnbound);
                    eventStreamParentViewableActivators[i] = patternActivator;
                }
                // Create view factories and parent view based on a database SQL statement
                else if (streamSpec is DBStatementStreamSpec)
                {
                    ValidateNoViews(streamSpec, "Historical data");
                    var sqlStreamSpec                  = (DBStatementStreamSpec)streamSpec;
                    var typeConversionHook             = (SQLColumnTypeConversion)TypeHelper.GetAnnotationHook(statementSpec.Annotations, HookType.SQLCOL, typeof(SQLColumnTypeConversion), statementContext.MethodResolutionService);
                    var outputRowConversionHook        = (SQLOutputRowConversion)TypeHelper.GetAnnotationHook(statementSpec.Annotations, HookType.SQLROW, typeof(SQLOutputRowConversion), statementContext.MethodResolutionService);
                    var epStatementAgentInstanceHandle = defaultAgentInstanceContext.EpStatementAgentInstanceHandle;
                    var historicalEventViewable        = DatabasePollingViewableFactory.CreateDBStatementView(
                        statementContext.StatementId, i, sqlStreamSpec,
                        services.DatabaseRefService,
                        services.EventAdapterService,
                        epStatementAgentInstanceHandle,
                        statementContext.Annotations,
                        typeConversionHook,
                        outputRowConversionHook,
                        statementContext.ConfigSnapshot.EngineDefaults.LoggingConfig.IsEnableADO,
                        services.DataCacheFactory,
                        statementContext);
                    historicalEventViewables[i]            = historicalEventViewable;
                    unmaterializedViewChain[i]             = ViewFactoryChain.FromTypeNoViews(historicalEventViewable.EventType);
                    eventStreamParentViewableActivators[i] = services.ViewableActivatorFactory.MakeHistorical(historicalEventViewable);
                    stopCallbacks.Add(historicalEventViewable);
                }
                else if (streamSpec is MethodStreamSpec)
                {
                    ValidateNoViews(streamSpec, "Method data");
                    var methodStreamSpec = (MethodStreamSpec)streamSpec;
                    var epStatementAgentInstanceHandle = defaultAgentInstanceContext.EpStatementAgentInstanceHandle;
                    var historicalEventViewable        = MethodPollingViewableFactory.CreatePollMethodView(
                        i, methodStreamSpec, services.EventAdapterService, epStatementAgentInstanceHandle,
                        statementContext.MethodResolutionService, services.EngineImportService,
                        statementContext.SchedulingService, statementContext.ScheduleBucket, evaluatorContextStmt,
                        statementContext.VariableService, statementContext.ContextName, services.DataCacheFactory,
                        statementContext);
                    historicalEventViewables[i]            = historicalEventViewable;
                    unmaterializedViewChain[i]             = ViewFactoryChain.FromTypeNoViews(historicalEventViewable.EventType);
                    eventStreamParentViewableActivators[i] = services.ViewableActivatorFactory.MakeHistorical(historicalEventViewable);
                    stopCallbacks.Add(historicalEventViewable);
                }
                else if (streamSpec is TableQueryStreamSpec)
                {
                    ValidateNoViews(streamSpec, "Table data");
                    var tableStreamSpec = (TableQueryStreamSpec)streamSpec;
                    if (isJoin && 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             metadata         = services.TableService.GetTableMetadata(tableStreamSpec.TableName);
                    ExprEvaluator[] tableFilterEvals = null;
                    if (tableStreamSpec.FilterExpressions.Count > 0)
                    {
                        tableFilterEvals = ExprNodeUtility.GetEvaluators(tableStreamSpec.FilterExpressions);
                    }
                    EPLValidationUtil.ValidateContextName(true, metadata.TableName, metadata.ContextName, statementSpec.OptionalContextName, false);
                    eventStreamParentViewableActivators[i] = services.ViewableActivatorFactory.CreateTable(metadata, tableFilterEvals);
                    unmaterializedViewChain[i]             = ViewFactoryChain.FromTypeNoViews(metadata.InternalEventType);
                    eventTypeNames[i] = tableStreamSpec.TableName;
                    joinAnalysisResult.SetTablesForStream(i, metadata);
                    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");
                    }
                    if (isJoin)
                    {
                        destroyCallbacks.AddCallback(new EPStatementDestroyCallbackTableIdxRef(services.TableService, metadata, statementContext.StatementName));
                    }
                    services.StatementVariableRefService.AddReferences(statementContext.StatementName, metadata.TableName);
                }
                else if (streamSpec is NamedWindowConsumerStreamSpec)
                {
                    var namedSpec       = (NamedWindowConsumerStreamSpec)streamSpec;
                    var processor       = services.NamedWindowMgmtService.GetProcessor(namedSpec.WindowName);
                    var namedWindowType = processor.TailView.EventType;
                    if (namedSpec.OptPropertyEvaluator != null)
                    {
                        namedWindowType = namedSpec.OptPropertyEvaluator.FragmentEventType;
                    }

                    eventStreamParentViewableActivators[i] = services.ViewableActivatorFactory.CreateNamedWindow(processor, namedSpec, statementContext);
                    services.NamedWindowConsumerMgmtService.AddConsumer(statementContext, namedSpec);
                    unmaterializedViewChain[i] = services.ViewService.CreateFactories(i, namedWindowType, namedSpec.ViewSpecs, namedSpec.Options, statementContext, false, -1);
                    joinAnalysisResult.SetNamedWindow(i);
                    eventTypeNames[i] = namedSpec.WindowName;
                    isNamedWindow[i]  = true;

                    // Consumers to named windows cannot declare a data window view onto the named window to avoid duplicate remove streams
                    EPStatementStartMethodHelperValidate.ValidateNoDataWindowOnNamedWindow(unmaterializedViewChain[i].FactoryChain);
                }
                else
                {
                    throw new ExprValidationException("Unknown stream specification type: " + streamSpec);
                }
            }

            // handle match-recognize pattern
            if (statementSpec.MatchRecognizeSpec != null)
            {
                if (isJoin)
                {
                    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 = (unmaterializedViewChain[0].FactoryChain.IsEmpty()) && (!(statementSpec.StreamSpecs[0] is NamedWindowConsumerStreamSpec));
                var factoryX  = services.RegexHandlerFactory.MakeViewFactory(unmaterializedViewChain[0], statementSpec.MatchRecognizeSpec, defaultAgentInstanceContext, isUnbound, statementSpec.Annotations, services.ConfigSnapshot.EngineDefaults.MatchRecognizeConfig);
                unmaterializedViewChain[0].FactoryChain.Add(factoryX);

                EPStatementStartMethodHelperAssignExpr.AssignAggregations(factoryX.AggregationService, factoryX.AggregationExpressions);
            }

            // Obtain event types from view factory chains
            var streamEventTypes = new EventType[statementSpec.StreamSpecs.Length];

            for (var i = 0; i < unmaterializedViewChain.Length; i++)
            {
                streamEventTypes[i] = unmaterializedViewChain[i].EventType;
            }

            // Add uniqueness information useful for joins
            joinAnalysisResult.AddUniquenessInfo(unmaterializedViewChain, statementSpec.Annotations);

            // Validate sub-select views
            var subSelectStrategyCollection = EPStatementStartMethodHelperSubselect.PlanSubSelect(services, statementContext, queryPlanLogging, subSelectStreamDesc, streamNames, streamEventTypes, eventTypeNames, statementSpec.DeclaredExpressions, contextPropertyRegistry);

            // Construct type information per stream
            StreamTypeService typeService      = new StreamTypeServiceImpl(streamEventTypes, streamNames, EPStatementStartMethodHelperUtil.GetHasIStreamOnly(isNamedWindow, unmaterializedViewChain), services.EngineURI, false);
            var viewResourceDelegateUnverified = new ViewResourceDelegateUnverified();

            // 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;
                }
                historicalEventViewable.Validate(
                    services.EngineImportService,
                    typeService,
                    statementContext.MethodResolutionService,
                    statementContext.TimeProvider,
                    statementContext.VariableService, statementContext.TableService,
                    statementContext.ScriptingService, evaluatorContextStmt,
                    services.ConfigSnapshot, services.SchedulingService, services.EngineURI,
                    statementSpec.SqlParameters,
                    statementContext.EventAdapterService, statementContext);
                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");
                }
            }

            // unidirectional is not supported with into-table
            if (joinAnalysisResult.IsUnidirectional && statementSpec.IntoTableSpec != null)
            {
                throw new ExprValidationException("Into-table does not allow unidirectional joins");
            }

            // Construct a processor for results posted by views and joins, which takes care of aggregation if required.
            // May return null if we don't need to post-process results posted by views or joins.
            var resultSetProcessorPrototypeDesc = ResultSetProcessorFactoryFactory.GetProcessorPrototype(
                statementSpec, statementContext, typeService, viewResourceDelegateUnverified, joinAnalysisResult.UnidirectionalInd, true, contextPropertyRegistry, selectExprProcessorDeliveryCallback, services.ConfigSnapshot, services.ResultSetProcessorHelperFactory, false, false);

            // Validate where-clause filter tree, outer join clause and output limit expression
            EPStatementStartMethodHelperValidate.ValidateNodes(statementSpec, statementContext, typeService, viewResourceDelegateUnverified);

            // Handle 'prior' function nodes in terms of view requirements
            var viewResourceDelegateVerified = EPStatementStartMethodHelperViewResources.VerifyPreviousAndPriorRequirements(unmaterializedViewChain, viewResourceDelegateUnverified);

            // handle join
            JoinSetComposerPrototype joinSetComposerPrototype = null;

            if (numStreams > 1)
            {
                var selectsRemoveStream =
                    statementSpec.SelectStreamSelectorEnum.IsSelectsRStream() ||
                    statementSpec.OutputLimitSpec != null;
                var hasAggregations = !resultSetProcessorPrototypeDesc.AggregationServiceFactoryDesc.Expressions.IsEmpty();
                joinSetComposerPrototype = JoinSetComposerPrototypeFactory.MakeComposerPrototype(
                    statementContext.StatementName, statementContext.StatementId,
                    statementSpec.OuterJoinDescList, statementSpec.FilterRootNode, typeService.EventTypes, streamNames,
                    joinAnalysisResult, queryPlanLogging, statementContext, historicalViewableDesc, defaultAgentInstanceContext,
                    selectsRemoveStream, hasAggregations, services.TableService, false, services.EventTableIndexService.AllowInitIndex(recoveringResilient));
            }

            // obtain factory for output limiting
            var outputViewFactory = OutputProcessViewFactoryFactory.Make(statementSpec, services.InternalEventRouter, statementContext, resultSetProcessorPrototypeDesc.ResultSetProcessorFactory.ResultEventType, optionalOutputProcessViewCallback, services.TableService, resultSetProcessorPrototypeDesc.ResultSetProcessorFactory.ResultSetProcessorType, services.ResultSetProcessorHelperFactory, services.StatementVariableRefService);

            // Factory for statement-context instances
            var factory = new StatementAgentInstanceFactorySelect(
                numStreams, eventStreamParentViewableActivators,
                statementContext, statementSpec, services,
                typeService, unmaterializedViewChain, resultSetProcessorPrototypeDesc, joinAnalysisResult, recoveringResilient,
                joinSetComposerPrototype, subSelectStrategyCollection, viewResourceDelegateVerified, outputViewFactory);

            EPStatementStopMethod stopMethod = new EPStatementStopMethodImpl(statementContext, stopCallbacks);

            return(new EPStatementStartMethodSelectDesc(factory, subSelectStrategyCollection, viewResourceDelegateUnverified, resultSetProcessorPrototypeDesc, stopMethod, destroyCallbacks));
        }