Example #1
0
        public static IList <StmtClassForgeableFactory> HandleSubselectSelectClauses(
            ExprSubselectNode subselect,
            EventType outerEventType,
            string outerEventTypeName,
            string outerStreamName,
            IDictionary <string, Pair <EventType, string> > taggedEventTypes,
            IDictionary <string, Pair <EventType, string> > arrayEventTypes,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            if (subselect.SubselectNumber == -1)
            {
                throw new IllegalStateException("Subselect is unassigned");
            }

            var statementSpec    = subselect.StatementSpecCompiled;
            var filterStreamSpec = statementSpec.StreamSpecs[0];

            IList <ViewFactoryForge> viewForges;
            string subselecteventTypeName;
            IList <StmtClassForgeableFactory> additionalForgeables;

            // construct view factory chain
            EventType eventType;

            try {
                var args = new ViewFactoryForgeArgs(
                    -1,
                    true,
                    subselect.SubselectNumber,
                    StreamSpecOptions.DEFAULT,
                    null,
                    statementRawInfo,
                    services);
                var streamSpec = statementSpec.StreamSpecs[0];

                if (streamSpec is FilterStreamSpecCompiled)
                {
                    var filterStreamSpecCompiled = (FilterStreamSpecCompiled)statementSpec.StreamSpecs[0];
                    subselecteventTypeName = filterStreamSpecCompiled.FilterSpecCompiled.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");
                    }

                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(
                        filterStreamSpecCompiled.ViewSpecs,
                        args,
                        filterStreamSpecCompiled.FilterSpecCompiled.ResultEventType);
                    viewForges           = viewForgeDesc.Forges;
                    additionalForgeables = viewForgeDesc.MultikeyForges;
                    // Register filter, create view factories
                    eventType = viewForges.IsEmpty() ? filterStreamSpecCompiled.FilterSpecCompiled.ResultEventType : viewForges[viewForges.Count - 1].EventType;
                    subselect.RawEventType = eventType;
                }
                else if (streamSpec is NamedWindowConsumerStreamSpec)
                {
                    var namedSpec   = (NamedWindowConsumerStreamSpec)statementSpec.StreamSpecs[0];
                    var namedWindow = namedSpec.NamedWindow;
                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(namedSpec.ViewSpecs, args, namedWindow.EventType);
                    viewForges           = viewForgeDesc.Forges;
                    additionalForgeables = viewForgeDesc.MultikeyForges;
                    var namedWindowName = namedWindow.EventType.Name;
                    subselecteventTypeName = namedWindowName;
                    EPLValidationUtil.ValidateContextName(false, namedWindowName, namedWindow.ContextName, statementRawInfo.ContextName, true);
                    subselect.RawEventType = namedWindow.EventType;
                    eventType = namedWindow.EventType;
                }
                else if (streamSpec is TableQueryStreamSpec)
                {
                    var namedSpec = (TableQueryStreamSpec)statementSpec.StreamSpecs[0];
                    var table     = namedSpec.Table;
                    ViewFactoryForgeDesc viewForgeDesc = ViewFactoryForgeUtil.CreateForges(namedSpec.ViewSpecs, args, table.InternalEventType);
                    viewForges           = viewForgeDesc.Forges;
                    additionalForgeables = viewForgeDesc.MultikeyForges;
                    var namedWindowName = table.TableName;
                    subselecteventTypeName = namedWindowName;
                    EPLValidationUtil.ValidateContextName(false, namedWindowName, table.OptionalContextName, statementRawInfo.ContextName, true);
                    subselect.RawEventType = table.InternalEventType;
                    eventType = table.InternalEventType;
                }
                else
                {
                    throw new IllegalStateException("Unexpected stream spec " + streamSpec);
                }
            }
            catch (ViewProcessingException ex) {
                throw new ExprValidationException("Failed to validate subexpression: " + ex.Message, ex);
            }

            // determine a stream name unless one was supplied
            var subexpressionStreamName = SubselectUtil.GetStreamName(filterStreamSpec.OptionalStreamName, subselect.SubselectNumber);

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

            // 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 (var entry in taggedEventTypes)
                {
                    namesAndTypes.Put(entry.Key, new Pair <EventType, string>(entry.Value.First, entry.Value.Second));
                }
            }

            if (arrayEventTypes != null)
            {
                foreach (var entry in arrayEventTypes)
                {
                    namesAndTypes.Put(entry.Key, new Pair <EventType, string>(entry.Value.First, entry.Value.Second));
                }
            }

            StreamTypeService subselectTypeService = new StreamTypeServiceImpl(namesAndTypes, true, true);
            var viewResourceDelegateSubselect      = new ViewResourceDelegateExpr();

            subselect.FilterSubqueryStreamTypes = subselectTypeService;

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

            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 validationContext = new ExprValidationContextBuilder(subselectTypeService, statementRawInfo, services)
                                            .WithViewResourceDelegate(viewResourceDelegateSubselect)
                                            .WithAllowBindingConsumption(true)
                                            .WithMemberName(new ExprValidationMemberNameQualifiedSubquery(subselect.SubselectNumber))
                                            .Build();
                    selectExpression        = ExprNodeUtilityValidate.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 = ExprNodeUtilityQuery.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 = ExprNodeUtilityQuery.GetExpressionProperties(selectExpression, false);
                        foreach (var pair in propertiesNotAggregated)
                        {
                            if (pair.First == 0)
                            {
                                throw new ExprValidationException("Subselect properties must all be within aggregation functions");
                            }
                        }
                    }
                }
            }

            return(additionalForgeables);
        }
Example #2
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");
                            }
                        }
                    }
                }
            }
        }
Example #3
0
        public static StmtForgeMethodSelectResult Make(
            IContainer container,
            bool dataflowOperator,
            string @namespace,
            string classPostfix,
            StatementBaseInfo @base,
            StatementCompileTimeServices services)
        {
            var filterSpecCompileds = new List<FilterSpecCompiled>();
            var scheduleHandleCallbackProviders = new List<ScheduleHandleCallbackProvider>();
            var namedWindowConsumers = new List<NamedWindowConsumerStreamSpec>();
            var statementSpec = @base.StatementSpec;
            var additionalForgeables = new List<StmtClassForgeableFactory>();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            DetermineViewSchedules(subselectForges, scheduleHandleCallbackProviders);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            var forgeableResult = new StmtForgeMethodResult(
                forgeablesX,
                filterSpecCompileds,
                scheduleHandleCallbackProviders,
                namedWindowConsumers,
                FilterSpecCompiled.MakeExprNodeList(filterSpecCompileds, EmptyList<FilterSpecParamExprNodeForge>.Instance));
            return new StmtForgeMethodSelectResult(forgeableResult, resultSetProcessorDesc.ResultEventType, numStreams);
        }