public static void AssignExpressionStrategies(
            EPStatementStartMethodSelectDesc selectDesc,
            AggregationService aggregationService,
            IDictionary <ExprSubselectNode, SubSelectStrategyHolder> subselectStrategyInstances,
            IDictionary <ExprPriorNode, ExprPriorEvalStrategy> priorStrategyInstances,
            IDictionary <ExprPreviousNode, ExprPreviousEvalStrategy> previousStrategyInstances,
            ICollection <ExprPreviousMatchRecognizeNode> matchRecognizeNodes,
            RegexExprPreviousEvalStrategy matchRecognizePrevEvalStrategy,
            IDictionary <ExprTableAccessNode, ExprTableAccessEvalStrategy> tableAccessStrategyInstances)
        {
            // initialize aggregation expression nodes
            if (selectDesc.ResultSetProcessorPrototypeDesc.AggregationServiceFactoryDesc != null && aggregationService != null)
            {
                EPStatementStartMethodHelperAssignExpr.AssignAggregations(aggregationService, selectDesc.ResultSetProcessorPrototypeDesc.AggregationServiceFactoryDesc.Expressions);
            }

            // assign subquery nodes
            AssignSubqueryStrategies(selectDesc.SubSelectStrategyCollection, subselectStrategyInstances);

            // assign prior nodes
            AssignPriorStrategies(priorStrategyInstances);

            // assign previous nodes
            AssignPreviousStrategies(previousStrategyInstances);

            // assign match-recognize previous nodes
            AssignMatchRecognizePreviousStrategies(matchRecognizeNodes, matchRecognizePrevEvalStrategy);

            // assign table access nodes
            AssignTableAccessStrategies(tableAccessStrategyInstances);
        }
        public override EPStatementStartResult StartInternal(EPServicesContext services, StatementContext statementContext, bool isNewStatement, bool isRecoveringStatement, bool isRecoveringResilient)
        {
            // validate use of table: may not both read and write
            ValidateTableAccessUse(StatementSpec.IntoTableSpec, StatementSpec.TableNodes);

            var contextName = StatementSpec.OptionalContextName;
            var defaultAgentInstanceContext = GetDefaultAgentInstanceContext(statementContext);
            var selectDesc = EPStatementStartMethodSelectUtil.Prepare(StatementSpec, services, statementContext, isRecoveringResilient, defaultAgentInstanceContext, IsQueryPlanLogging(services), null, null, null);

            statementContext.StatementAgentInstanceFactory = selectDesc.StatementAgentInstanceFactorySelect;

            // allow extension to walk
            statementContext.StatementExtensionServicesContext.PreStartWalk(selectDesc);

            // Determine context
            EPStatementStopMethod stopStatementMethod;
            Viewable           finalViewable;
            AggregationService aggregationService;
            IDictionary <ExprSubselectNode, SubSelectStrategyHolder>       subselectStrategyInstances;
            IDictionary <ExprPriorNode, ExprPriorEvalStrategy>             priorStrategyInstances;
            IDictionary <ExprPreviousNode, ExprPreviousEvalStrategy>       previousStrategyInstances;
            IDictionary <ExprTableAccessNode, ExprTableAccessEvalStrategy> tableAccessStrategyInstances;
            var preloadList = Collections.GetEmptyList <StatementAgentInstancePreload>();
            RegexExprPreviousEvalStrategy matchRecognizePrevEvalStrategy;

            // With context - delegate instantiation to context
            if (StatementSpec.OptionalContextName != null)
            {
                // use statement-wide agent-instance-specific aggregation service
                aggregationService = statementContext.StatementAgentInstanceRegistry.AgentInstanceAggregationService;

                // use statement-wide agent-instance-specific subselects
                var aiRegistryExpr = statementContext.StatementAgentInstanceRegistry.AgentInstanceExprService;

                subselectStrategyInstances = new Dictionary <ExprSubselectNode, SubSelectStrategyHolder>();
                foreach (var entry in selectDesc.SubSelectStrategyCollection.Subqueries)
                {
                    var specificService = aiRegistryExpr.AllocateSubselect(entry.Key);
                    entry.Key.Strategy = specificService;

                    IDictionary <ExprPriorNode, ExprPriorEvalStrategy> subselectPriorStrategies = new Dictionary <ExprPriorNode, ExprPriorEvalStrategy>();
                    foreach (var subselectPrior in entry.Value.PriorNodesList)
                    {
                        var specificSubselectPriorService = aiRegistryExpr.AllocatePrior(subselectPrior);
                        subselectPriorStrategies.Put(subselectPrior, specificSubselectPriorService);
                    }

                    IDictionary <ExprPreviousNode, ExprPreviousEvalStrategy> subselectPreviousStrategies = new Dictionary <ExprPreviousNode, ExprPreviousEvalStrategy>();
                    foreach (var subselectPrevious in entry.Value.PrevNodesList)
                    {
                        var specificSubselectPreviousService = aiRegistryExpr.AllocatePrevious(subselectPrevious);
                        subselectPreviousStrategies.Put(subselectPrevious, specificSubselectPreviousService);
                    }

                    var subselectAggregation = aiRegistryExpr.AllocateSubselectAggregation(entry.Key);
                    var strategyHolder       = new SubSelectStrategyHolder(specificService, subselectAggregation, subselectPriorStrategies, subselectPreviousStrategies, null, null, null);
                    subselectStrategyInstances.Put(entry.Key, strategyHolder);
                }

                // use statement-wide agent-instance-specific "prior"
                priorStrategyInstances = new Dictionary <ExprPriorNode, ExprPriorEvalStrategy>();
                foreach (var priorNode in selectDesc.ViewResourceDelegateUnverified.PriorRequests)
                {
                    var specificService = aiRegistryExpr.AllocatePrior(priorNode);
                    priorStrategyInstances.Put(priorNode, specificService);
                }

                // use statement-wide agent-instance-specific "previous"
                previousStrategyInstances = new Dictionary <ExprPreviousNode, ExprPreviousEvalStrategy>();
                foreach (var previousNode in selectDesc.ViewResourceDelegateUnverified.PreviousRequests)
                {
                    var specificService = aiRegistryExpr.AllocatePrevious(previousNode);
                    previousStrategyInstances.Put(previousNode, specificService);
                }

                // use statement-wide agent-instance-specific match-recognize "previous"
                matchRecognizePrevEvalStrategy = aiRegistryExpr.AllocateMatchRecognizePrevious();

                // use statement-wide agent-instance-specific tables
                tableAccessStrategyInstances = new Dictionary <ExprTableAccessNode, ExprTableAccessEvalStrategy>();
                if (StatementSpec.TableNodes != null)
                {
                    foreach (ExprTableAccessNode tableNode in StatementSpec.TableNodes)
                    {
                        var specificService = aiRegistryExpr.AllocateTableAccess(tableNode);
                        tableAccessStrategyInstances.Put(tableNode, specificService);
                    }
                }

                var mergeView = new ContextMergeView(selectDesc.ResultSetProcessorPrototypeDesc.ResultSetProcessorFactory.ResultEventType);
                finalViewable = mergeView;

                var statement = new ContextManagedStatementSelectDesc(StatementSpec, statementContext, mergeView, selectDesc.StatementAgentInstanceFactorySelect,
                                                                      selectDesc.ResultSetProcessorPrototypeDesc.AggregationServiceFactoryDesc.Expressions,
                                                                      selectDesc.SubSelectStrategyCollection);
                services.ContextManagementService.AddStatement(contextName, statement, isRecoveringResilient);
                var selectStop = selectDesc.StopMethod;
                stopStatementMethod = new ProxyEPStatementStopMethod(() =>
                {
                    services.ContextManagementService.StoppedStatement(
                        contextName,
                        statementContext.StatementName,
                        statementContext.StatementId,
                        statementContext.Expression,
                        statementContext.ExceptionHandlingService);
                    selectStop.Stop();
                });

                selectDesc.DestroyCallbacks.AddCallback(new EPStatementDestroyCallbackContext(services.ContextManagementService, contextName, statementContext.StatementName, statementContext.StatementId));
            }
            // Without context - start here
            else
            {
                var resultOfStart = (StatementAgentInstanceFactorySelectResult)selectDesc.StatementAgentInstanceFactorySelect.NewContext(defaultAgentInstanceContext, isRecoveringResilient);
                finalViewable = resultOfStart.FinalView;
                var startResultStop = services.EpStatementFactory.MakeStopMethod(resultOfStart);
                var selectStop      = selectDesc.StopMethod;
                stopStatementMethod = new ProxyEPStatementStopMethod(() =>
                {
                    StatementAgentInstanceUtil.StopSafe(startResultStop, statementContext);
                    selectStop.Stop();
                });
                aggregationService           = resultOfStart.OptionalAggegationService;
                subselectStrategyInstances   = resultOfStart.SubselectStrategies;
                priorStrategyInstances       = resultOfStart.PriorNodeStrategies;
                previousStrategyInstances    = resultOfStart.PreviousNodeStrategies;
                tableAccessStrategyInstances = resultOfStart.TableAccessEvalStrategies;
                preloadList = resultOfStart.PreloadList;

                matchRecognizePrevEvalStrategy = null;
                if (resultOfStart.TopViews.Length > 0)
                {
                    EventRowRegexNFAViewService matchRecognize = EventRowRegexHelper.RecursiveFindRegexService(resultOfStart.TopViews[0]);
                    if (matchRecognize != null)
                    {
                        matchRecognizePrevEvalStrategy = matchRecognize.PreviousEvaluationStrategy;
                    }
                }

                if (statementContext.StatementExtensionServicesContext != null && statementContext.StatementExtensionServicesContext.StmtResources != null)
                {
                    StatementResourceHolder holder = statementContext.StatementExtensionServicesContext.ExtractStatementResourceHolder(resultOfStart);
                    statementContext.StatementExtensionServicesContext.StmtResources.Unpartitioned = holder;
                    statementContext.StatementExtensionServicesContext.PostProcessStart(resultOfStart, isRecoveringResilient);
                }
            }

            var matchRecognizeNodes = selectDesc.StatementAgentInstanceFactorySelect.ViewResourceDelegate.PerStream[0].MatchRecognizePreviousRequests;

            // assign strategies to expression nodes
            EPStatementStartMethodHelperAssignExpr.AssignExpressionStrategies(
                selectDesc, aggregationService, subselectStrategyInstances, priorStrategyInstances,
                previousStrategyInstances, matchRecognizeNodes, matchRecognizePrevEvalStrategy,
                tableAccessStrategyInstances);

            // execute preload if any
            foreach (var preload in preloadList)
            {
                preload.ExecutePreload();
            }

            // handle association to table
            if (StatementSpec.IntoTableSpec != null)
            {
                services.StatementVariableRefService.AddReferences(statementContext.StatementName, StatementSpec.IntoTableSpec.Name);
            }

            return(new EPStatementStartResult(finalViewable, stopStatementMethod, selectDesc.DestroyCallbacks));
        }
        /// <summary>
        /// Ctor.
        /// </summary>
        /// <param name="statementSpec">is a container for the definition of all statement constructs thatmay have been used in the statement, i.e. if defines the select clauses, insert into, outer joins etc.
        /// </param>
        /// <param name="services">is the service instances for dependency injection</param>
        /// <param name="statementContext">is statement-level information and statement services</param>
        /// <throws>ExprValidationException if the preparation failed</throws>
        public EPPreparedExecuteMethodQuery(StatementSpecCompiled statementSpec,
                                            EPServicesContext services,
                                            StatementContext statementContext)

        {
            var queryPlanLogging = services.ConfigSnapshot.EngineDefaults.LoggingConfig.IsEnableQueryPlan;

            if (queryPlanLogging)
            {
                QueryPlanLog.Info("Query plans for Fire-and-forget query '" + statementContext.Expression + "'");
            }

            _hasTableAccess = (statementSpec.TableNodes != null && statementSpec.TableNodes.Length > 0);
            foreach (var streamSpec in statementSpec.StreamSpecs)
            {
                _hasTableAccess |= streamSpec is TableQueryStreamSpec;
            }

            _statementSpec = statementSpec;
            _services      = services;

            EPPreparedExecuteMethodHelper.ValidateFAFQuery(statementSpec);

            var numStreams     = statementSpec.StreamSpecs.Length;
            var typesPerStream = new EventType[numStreams];
            var namesPerStream = new string[numStreams];

            _processors           = new FireAndForgetProcessor[numStreams];
            _agentInstanceContext = new AgentInstanceContext(statementContext, null, -1, null, null, statementContext.DefaultAgentInstanceScriptContext);

            // resolve types and processors
            for (var i = 0; i < numStreams; i++)
            {
                var streamSpec = statementSpec.StreamSpecs[i];
                _processors[i] = FireAndForgetProcessorFactory.ValidateResolveProcessor(streamSpec, services);

                string streamName = _processors[i].NamedWindowOrTableName;
                if (streamSpec.OptionalStreamName != null)
                {
                    streamName = streamSpec.OptionalStreamName;
                }
                namesPerStream[i] = streamName;
                typesPerStream[i] = _processors[i].EventTypeResultSetProcessor;
            }

            // compile filter to optimize access to named window
            _filters = new FilterSpecCompiled[numStreams];
            if (statementSpec.FilterRootNode != null)
            {
                var tagged = new LinkedHashMap <string, Pair <EventType, string> >();
                for (var i = 0; i < numStreams; i++)
                {
                    try {
                        var types = new StreamTypeServiceImpl(typesPerStream, namesPerStream, new bool[numStreams], services.EngineURI, false);
                        _filters[i] = FilterSpecCompiler.MakeFilterSpec(typesPerStream[i], namesPerStream[i],
                                                                        Collections.SingletonList(statementSpec.FilterRootNode), null,
                                                                        tagged, tagged, types,
                                                                        null, statementContext, Collections.SingletonList(i));
                    }
                    catch (Exception ex) {
                        Log.Warn("Unexpected exception analyzing filter paths: " + ex.Message, ex);
                    }
                }
            }

            // obtain result set processor
            var isIStreamOnly = new bool[namesPerStream.Length];

            CompatExtensions.Fill(isIStreamOnly, true);
            StreamTypeService typeService = new StreamTypeServiceImpl(typesPerStream, namesPerStream, isIStreamOnly, services.EngineURI, true);

            EPStatementStartMethodHelperValidate.ValidateNodes(statementSpec, statementContext, typeService, null);

            var resultSetProcessorPrototype = ResultSetProcessorFactoryFactory.GetProcessorPrototype(statementSpec, statementContext, typeService, null, new bool[0], true, ContextPropertyRegistryImpl.EMPTY_REGISTRY, null, _services.ConfigSnapshot);

            _resultSetProcessor = EPStatementStartMethodHelperAssignExpr.GetAssignResultSetProcessor(_agentInstanceContext, resultSetProcessorPrototype);

            if (statementSpec.SelectClauseSpec.IsDistinct)
            {
                if (_resultSetProcessor.ResultEventType is EventTypeSPI)
                {
                    _eventBeanReader = ((EventTypeSPI)_resultSetProcessor.ResultEventType).GetReader();
                }
                if (_eventBeanReader == null)
                {
                    _eventBeanReader = new EventBeanReaderDefaultImpl(_resultSetProcessor.ResultEventType);
                }
            }

            // plan joins or simple queries
            if (numStreams > 1)
            {
                var streamJoinAnalysisResult = new StreamJoinAnalysisResult(numStreams);
                CompatExtensions.Fill(streamJoinAnalysisResult.NamedWindow, true);
                for (var i = 0; i < numStreams; i++)
                {
                    var processorInstance = _processors[i].GetProcessorInstance(_agentInstanceContext);
                    if (_processors[i].IsVirtualDataWindow)
                    {
                        streamJoinAnalysisResult.ViewExternal[i] = agentInstanceContext => processorInstance.VirtualDataWindow;
                    }
                    var uniqueIndexes = _processors[i].GetUniqueIndexes(processorInstance);
                    streamJoinAnalysisResult.UniqueKeys[i] = uniqueIndexes;
                }

                var hasAggregations = !resultSetProcessorPrototype.AggregationServiceFactoryDesc.Expressions.IsEmpty();
                _joinSetComposerPrototype = JoinSetComposerPrototypeFactory.MakeComposerPrototype(
                    null, null,
                    statementSpec.OuterJoinDescList, statementSpec.FilterRootNode, typesPerStream, namesPerStream,
                    streamJoinAnalysisResult, queryPlanLogging, statementContext, new HistoricalViewableDesc(numStreams),
                    _agentInstanceContext, false, hasAggregations, services.TableService, true);
            }

            // check context partition use
            if (statementSpec.OptionalContextName != null)
            {
                if (numStreams > 1)
                {
                    throw new ExprValidationException("Joins in runtime queries for context partitions are not supported");
                }
            }
        }
Exemplo n.º 4
0
        public override EPStatementStartResult StartInternal(EPServicesContext services, StatementContext statementContext, bool isNewStatement, bool isRecoveringStatement, bool isRecoveringResilient)
        {
            // define stop and destroy
            var stopCallbacks    = new List <StopCallback>();
            var destroyCallbacks = new EPStatementDestroyCallbackList();

            // determine context
            var contextName = StatementSpec.OptionalContextName;

            if (contextName != null)
            {
                throw new ExprValidationException("Update IStream is not supported in conjunction with a context");
            }

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

            var    streamSpec = StatementSpec.StreamSpecs[0];
            var    updateSpec = StatementSpec.UpdateSpec;
            String triggereventTypeName;

            if (streamSpec is FilterStreamSpecCompiled)
            {
                var filterStreamSpec = (FilterStreamSpecCompiled)streamSpec;
                triggereventTypeName = filterStreamSpec.FilterSpec.FilterForEventTypeName;
            }
            else if (streamSpec is NamedWindowConsumerStreamSpec)
            {
                var namedSpec = (NamedWindowConsumerStreamSpec)streamSpec;
                triggereventTypeName = namedSpec.WindowName;
            }
            else if (streamSpec is TableQueryStreamSpec)
            {
                throw new ExprValidationException("Tables cannot be used in an update-istream statement");
            }
            else
            {
                throw new ExprValidationException("Unknown stream specification streamEventType: " + streamSpec);
            }

            // determine a stream name
            var streamName = triggereventTypeName;

            if (updateSpec.OptionalStreamName != null)
            {
                streamName = updateSpec.OptionalStreamName;
            }

            var streamEventType           = services.EventAdapterService.GetEventTypeByName(triggereventTypeName);
            StreamTypeService typeService = new StreamTypeServiceImpl(new EventType[] { streamEventType }, new String[] { streamName }, new bool[] { true }, services.EngineURI, false);

            // determine subscriber result types
            var evaluatorContextStmt = new ExprEvaluatorContextStatement(statementContext, false);

            statementContext.StatementResultService.SetSelectClause(new Type[] { streamEventType.UnderlyingType }, new String[] { "*" }, false, null, evaluatorContextStmt);

            // Materialize sub-select views
            var subSelectStrategyCollection = EPStatementStartMethodHelperSubselect.PlanSubSelect(services, statementContext, IsQueryPlanLogging(services), subSelectStreamDesc, new String[] { streamName }, new EventType[] { streamEventType }, new String[] { triggereventTypeName }, StatementSpec.DeclaredExpressions, null);

            var validationContext = new ExprValidationContext(
                typeService,
                statementContext.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,
                null, false);

            foreach (var assignment in updateSpec.Assignments)
            {
                var validated = ExprNodeUtility.GetValidatedAssignment(assignment, validationContext);
                assignment.Expression = validated;
                EPStatementStartMethodHelperValidate.ValidateNoAggregations(validated, "Aggregation functions may not be used within an update-clause");
            }
            if (updateSpec.OptionalWhereClause != null)
            {
                var validated = ExprNodeUtility.GetValidatedSubtree(
                    ExprNodeOrigin.WHERE, updateSpec.OptionalWhereClause, validationContext);
                updateSpec.OptionalWhereClause = validated;
                EPStatementStartMethodHelperValidate.ValidateNoAggregations(validated, "Aggregation functions may not be used within an update-clause");
            }

            // preprocessing view
            var onExprView = new InternalRoutePreprocessView(streamEventType, statementContext.StatementResultService);

            // validation
            var routerDesc = services.InternalEventRouter.GetValidatePreprocessing(onExprView.EventType, updateSpec, statementContext.Annotations);

            // create context factory
            var contextFactory = new StatementAgentInstanceFactoryUpdate(statementContext, services, streamEventType, updateSpec, onExprView, routerDesc, subSelectStrategyCollection);

            // perform start of hook-up to start
            Viewable finalViewable;
            EPStatementStopMethod stopStatementMethod;
            IDictionary <ExprSubselectNode, SubSelectStrategyHolder> subselectStrategyInstances;

            // With context - delegate instantiation to context
            EPStatementStopMethod stopMethod = new EPStatementStopMethodImpl(statementContext, stopCallbacks).Stop;

            if (StatementSpec.OptionalContextName != null)
            {
                // use statement-wide agent-instance-specific subselects
                var aiRegistryExpr = statementContext.StatementAgentInstanceRegistry.AgentInstanceExprService;
                subselectStrategyInstances = new Dictionary <ExprSubselectNode, SubSelectStrategyHolder>();
                foreach (var node in subSelectStrategyCollection.Subqueries.Keys)
                {
                    var specificService = aiRegistryExpr.AllocateSubselect(node);
                    node.Strategy = specificService;
                    subselectStrategyInstances.Put(node, new SubSelectStrategyHolder(null, null, null, null, null, null));
                }

                var mergeView = new ContextMergeView(onExprView.EventType);
                finalViewable = mergeView;

                var statement = new ContextManagedStatementOnTriggerDesc(StatementSpec, statementContext, mergeView, contextFactory);
                services.ContextManagementService.AddStatement(StatementSpec.OptionalContextName, statement, isRecoveringResilient);
                stopStatementMethod = () =>
                {
                    services.ContextManagementService.StoppedStatement(contextName, statementContext.StatementName, statementContext.StatementId);
                    stopMethod.Invoke();
                };

                destroyCallbacks.AddCallback(EPStatementDestroyCallbackContext.New(
                                                 services.ContextManagementService,
                                                 StatementSpec.OptionalContextName,
                                                 statementContext.StatementName,
                                                 statementContext.StatementId));
            }
            // Without context - start here
            else
            {
                var agentInstanceContext = GetDefaultAgentInstanceContext(statementContext);
                var resultOfStart        = (StatementAgentInstanceFactoryUpdateResult)
                                           contextFactory.NewContext(agentInstanceContext, isRecoveringResilient);
                finalViewable       = resultOfStart.FinalView;
                stopStatementMethod = new EPStatementStopMethod(() =>
                {
                    resultOfStart.StopCallback.Invoke();
                    stopMethod.Invoke();
                });
                subselectStrategyInstances = resultOfStart.SubselectStrategies;
            }

            // assign subquery nodes
            EPStatementStartMethodHelperAssignExpr.AssignSubqueryStrategies(subSelectStrategyCollection, subselectStrategyInstances);

            return(new EPStatementStartResult(finalViewable, stopStatementMethod, destroyCallbacks.Destroy));
        }
        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));
        }
        public override EPStatementStartResult StartInternal(EPServicesContext services, StatementContext statementContext, bool isNewStatement, bool isRecoveringStatement, bool isRecoveringResilient)
        {
            var createDesc = StatementSpec.CreateVariableDesc;

            VariableServiceUtil.CheckAlreadyDeclaredTable(createDesc.VariableName, services.TableService);

            // Get assignment value
            Object value = null;

            if (createDesc.Assignment != null)
            {
                // Evaluate assignment expression
                var typeService          = new StreamTypeServiceImpl(new EventType[0], new String[0], new bool[0], services.EngineURI, false);
                var evaluatorContextStmt = new ExprEvaluatorContextStatement(statementContext, false);
                var validationContext    = new ExprValidationContext(
                    typeService,
                    statementContext.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, null, false);
                var validated = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.VARIABLEASSIGN, createDesc.Assignment, validationContext);
                value = validated.ExprEvaluator.Evaluate(new EvaluateParams(null, true, evaluatorContextStmt));
            }

            // Create variable
            try
            {
                services.VariableService.CreateNewVariable(
                    StatementSpec.OptionalContextName,
                    createDesc.VariableName,
                    createDesc.VariableType,
                    createDesc.IsConstant,
                    createDesc.IsArray,
                    createDesc.IsArrayOfPrimitive,
                    value,
                    services.EngineImportService);
            }
            catch (VariableExistsException ex)
            {
                // for new statement we don't allow creating the same variable
                if (isNewStatement)
                {
                    throw new ExprValidationException("Cannot create variable: " + ex.Message, ex);
                }
            }
            catch (VariableDeclarationException ex)
            {
                throw new ExprValidationException("Cannot create variable: " + ex.Message, ex);
            }

            var destroyMethod = new EPStatementDestroyCallbackList();

            destroyMethod.AddCallback(
                () =>
            {
                try
                {
                    services.StatementVariableRefService.RemoveReferencesStatement(statementContext.StatementName);
                }
                catch (Exception ex)
                {
                    Log.Error("Error removing variable '" + createDesc.VariableName + "': " + ex.Message);
                }
            });

            var stopMethod = new EPStatementStopMethod(() => { });

            VariableMetaData variableMetaData = services.VariableService.GetVariableMetaData(createDesc.VariableName);
            Viewable         outputView;

            if (StatementSpec.OptionalContextName != null)
            {
                EventType eventType      = CreateVariableView.GetEventType(statementContext.StatementId, services.EventAdapterService, variableMetaData);
                var       contextFactory = new StatementAgentInstanceFactoryCreateVariable(statementContext, services, variableMetaData, eventType);
                var       mergeView      = new ContextMergeView(eventType);
                outputView = mergeView;
                var statement = new ContextManagedStatementCreateVariableDesc(StatementSpec, statementContext, mergeView, contextFactory);
                services.ContextManagementService.AddStatement(StatementSpec.OptionalContextName, statement, isRecoveringResilient);

                ContextManagementService contextManagementService = services.ContextManagementService;
                destroyMethod.AddCallback(() => contextManagementService.DestroyedStatement(StatementSpec.OptionalContextName, statementContext.StatementName, statementContext.StatementId));
            }
            else
            {
                // allocate
                services.VariableService.AllocateVariableState(createDesc.VariableName, VariableServiceConstants.NOCONTEXT_AGENTINSTANCEID, statementContext.StatementExtensionServicesContext);
                var createView = new CreateVariableView(statementContext.StatementId, services.EventAdapterService, services.VariableService, createDesc.VariableName, statementContext.StatementResultService);

                services.VariableService.RegisterCallback(createDesc.VariableName, 0, createView.Update);
                statementContext.StatementStopService.StatementStopped +=
                    () => services.VariableService.UnregisterCallback(createDesc.VariableName, 0, createView.Update);

                // Create result set processor, use wildcard selection
                StatementSpec.SelectClauseSpec.SetSelectExprList(new SelectClauseElementWildcard());
                StatementSpec.SelectStreamDirEnum = SelectClauseStreamSelectorEnum.RSTREAM_ISTREAM_BOTH;
                StreamTypeService typeService   = new StreamTypeServiceImpl(new EventType[] { createView.EventType }, new String[] { "create_variable" }, new bool[] { true }, services.EngineURI, false);
                var agentInstanceContext        = GetDefaultAgentInstanceContext(statementContext);
                var resultSetProcessorPrototype = ResultSetProcessorFactoryFactory.GetProcessorPrototype(
                    StatementSpec, statementContext, typeService, null, new bool[0], true, ContextPropertyRegistryImpl.EMPTY_REGISTRY, null, services.ConfigSnapshot);
                var resultSetProcessor = EPStatementStartMethodHelperAssignExpr.GetAssignResultSetProcessor(agentInstanceContext, resultSetProcessorPrototype);

                // Attach output view
                var outputViewFactory = OutputProcessViewFactoryFactory.Make(StatementSpec, services.InternalEventRouter, agentInstanceContext.StatementContext, resultSetProcessor.ResultEventType, null, services.TableService, resultSetProcessorPrototype.ResultSetProcessorFactory.ResultSetProcessorType);
                var outputViewBase    = outputViewFactory.MakeView(resultSetProcessor, agentInstanceContext);
                createView.AddView(outputViewBase);
                outputView = outputViewBase;
            }

            services.StatementVariableRefService.AddReferences(statementContext.StatementName, Collections.SingletonList(createDesc.VariableName), null);

            return(new EPStatementStartResult(outputView, stopMethod, destroyMethod.Destroy));
        }