public StatementAgentInstanceFactorySelect( int numStreams, ViewableActivator[] eventStreamParentViewableActivators, StatementContext statementContext, StatementSpecCompiled statementSpec, EPServicesContext services, StreamTypeService typeService, ViewFactoryChain[] unmaterializedViewChain, ResultSetProcessorFactoryDesc resultSetProcessorFactoryDesc, StreamJoinAnalysisResult joinAnalysisResult, bool recoveringResilient, JoinSetComposerPrototype joinSetComposerPrototype, SubSelectStrategyCollection subSelectStrategyCollection, ViewResourceDelegateVerified viewResourceDelegate, OutputProcessViewFactory outputProcessViewFactory) : base(statementSpec.Annotations) { _numStreams = numStreams; _eventStreamParentViewableActivators = eventStreamParentViewableActivators; _statementContext = statementContext; _statementSpec = statementSpec; _services = services; _typeService = typeService; _unmaterializedViewChain = unmaterializedViewChain; _resultSetProcessorFactoryDesc = resultSetProcessorFactoryDesc; _joinAnalysisResult = joinAnalysisResult; _joinSetComposerPrototype = joinSetComposerPrototype; _subSelectStrategyCollection = subSelectStrategyCollection; _viewResourceDelegate = viewResourceDelegate; _outputProcessViewFactory = outputProcessViewFactory; }
public JoinSetComposerPrototypeImpl(string statementName, string statementId, OuterJoinDesc[] outerJoinDescList, ExprNode optionalFilterNode, EventType[] streamTypes, string[] streamNames, StreamJoinAnalysisResult streamJoinAnalysisResult, Attribute[] annotations, HistoricalViewableDesc historicalViewableDesc, ExprEvaluatorContext exprEvaluatorContext, QueryPlanIndex[] indexSpecs, QueryPlan queryPlan, HistoricalStreamIndexList[] historicalStreamIndexLists, bool joinRemoveStream, bool isOuterJoins, TableService tableService) { _statementName = statementName; _statementId = statementId; _outerJoinDescList = outerJoinDescList; _optionalFilterNode = optionalFilterNode; _streamTypes = streamTypes; _streamNames = streamNames; _streamJoinAnalysisResult = streamJoinAnalysisResult; _annotations = annotations; _historicalViewableDesc = historicalViewableDesc; _exprEvaluatorContext = exprEvaluatorContext; _indexSpecs = indexSpecs; _queryPlan = queryPlan; _historicalStreamIndexLists = historicalStreamIndexLists; _joinRemoveStream = joinRemoveStream; _isOuterJoins = isOuterJoins; _tableService = tableService; }
private JoinPlanResult HandleJoin( string[] streamNames, Viewable[] streamViews, ResultSetProcessor resultSetProcessor, AgentInstanceContext agentInstanceContext, IList <StopCallback> stopCallbacks, StreamJoinAnalysisResult joinAnalysisResult, bool isRecoveringResilient) { var joinSetComposerDesc = _joinSetComposerPrototype.Create(streamViews, false, agentInstanceContext, isRecoveringResilient); stopCallbacks.Add(new ProxyStopCallback(() => joinSetComposerDesc.JoinSetComposer.Destroy())); var filter = new JoinSetFilter(joinSetComposerDesc.PostJoinFilterEvaluator); var indicatorView = _outputProcessViewFactory.MakeView(resultSetProcessor, agentInstanceContext); // Create strategy for join execution JoinExecutionStrategy execution = new JoinExecutionStrategyImpl(joinSetComposerDesc.JoinSetComposer, filter, indicatorView, agentInstanceContext); // The view needs a reference to the join execution to pull iterator values indicatorView.JoinExecutionStrategy = execution; // Hook up dispatchable with buffer and execution strategy var joinStatementDispatch = new JoinExecStrategyDispatchable(execution, _statementSpec.StreamSpecs.Length); agentInstanceContext.EpStatementAgentInstanceHandle.OptionalDispatchable = joinStatementDispatch; JoinPreloadMethod preloadMethod; if (joinAnalysisResult.UnidirectionalStreamNumber >= 0) { preloadMethod = new JoinPreloadMethodNull(); } else { if (!joinSetComposerDesc.JoinSetComposer.AllowsInit) { preloadMethod = new JoinPreloadMethodNull(); } else { preloadMethod = new JoinPreloadMethodImpl(streamNames.Length, joinSetComposerDesc.JoinSetComposer); } } // Create buffer for each view. Point buffer to dispatchable for join. for (var i = 0; i < _statementSpec.StreamSpecs.Length; i++) { var buffer = new BufferView(i); streamViews[i].AddView(buffer); buffer.Observer = joinStatementDispatch; preloadMethod.SetBuffer(buffer, i); } return(new JoinPlanResult(indicatorView, preloadMethod, joinSetComposerDesc)); }
// Remove plans for non-unidirectional streams private static void RemoveUnidirectionalAndTable(QueryPlan queryPlan, StreamJoinAnalysisResult streamJoinAnalysisResult) { for (int streamNum = 0; streamNum < queryPlan.ExecNodeSpecs.Length; streamNum++) { bool unidirectional = streamJoinAnalysisResult.IsUnidirectional && !streamJoinAnalysisResult.UnidirectionalInd[streamNum]; bool table = streamJoinAnalysisResult.TablesPerStream[streamNum] != null; if (unidirectional || table) { queryPlan.ExecNodeSpecs[streamNum] = new QueryPlanNodeNoOp(); } } }
private static void VerifyJoinUnidirectional( StreamJoinAnalysisResult analysisResult, StatementSpecCompiled statementSpec) { var numUnidirectionalStreams = analysisResult.UnidirectionalCount; var numStreams = statementSpec.StreamSpecs.Length; // only a single stream is unidirectional (applies to all but all-full-outer-join) if (!IsFullOuterJoinAllStreams(statementSpec)) { if (numUnidirectionalStreams > 1) { throw new ExprValidationException( "The unidirectional keyword can only apply to one stream in a join"); } } else { // verify full-outer-join: requires unidirectional for all streams if (numUnidirectionalStreams > 1 && numUnidirectionalStreams < numStreams) { throw new ExprValidationException( "The unidirectional keyword must either apply to a single stream or all streams in a full outer join"); } } // verify no-child-view for unidirectional for (var i = 0; i < statementSpec.StreamSpecs.Length; i++) { if (analysisResult.UnidirectionalInd[i]) { if (analysisResult.HasChildViews[i]) { throw new ExprValidationException( "The unidirectional keyword requires that no views are declared onto the stream (applies to stream " + i + ")"); } } } }
/// <summary> /// Build query plan using the filter. /// </summary> /// <param name="typesPerStream">event types for each stream</param> /// <param name="outerJoinDescList">list of outer join criteria, or null if there are no outer joins</param> /// <param name="queryGraph">relationships between streams based on filter expressions and outer-join on-criteria</param> /// <param name="streamNames">names of streams</param> /// <param name="historicalViewableDesc">The historical viewable desc.</param> /// <param name="dependencyGraph">dependencies between historical streams</param> /// <param name="historicalStreamIndexLists">index management, populated for the query plan</param> /// <param name="streamJoinAnalysisResult">The stream join analysis result.</param> /// <param name="isQueryPlanLogging">if set to <c>true</c> [is query plan logging].</param> /// <param name="annotations">The annotations.</param> /// <param name="exprEvaluatorContext">The expr evaluator context.</param> /// <returns> /// query plan /// </returns> /// <exception cref="System.ArgumentException"> /// Number of join stream types is less then 2 /// or /// Too many outer join descriptors found /// </exception> /// <throws>ExprValidationException if the query plan fails</throws> public static QueryPlan GetPlan(EventType[] typesPerStream, OuterJoinDesc[] outerJoinDescList, QueryGraph queryGraph, string[] streamNames, HistoricalViewableDesc historicalViewableDesc, DependencyGraph dependencyGraph, HistoricalStreamIndexList[] historicalStreamIndexLists, StreamJoinAnalysisResult streamJoinAnalysisResult, bool isQueryPlanLogging, Attribute[] annotations, ExprEvaluatorContext exprEvaluatorContext) { string methodName = ".getPlan "; int numStreams = typesPerStream.Length; if (numStreams < 2) { throw new ArgumentException("Number of join stream types is less then 2"); } if (outerJoinDescList.Length >= numStreams) { throw new ArgumentException("Too many outer join descriptors found"); } if (numStreams == 2) { OuterJoinType?outerJoinType = null; if (outerJoinDescList.Length > 0) { outerJoinType = outerJoinDescList[0].OuterJoinType; } QueryPlan queryPlanX = TwoStreamQueryPlanBuilder.Build(typesPerStream, queryGraph, outerJoinType, streamJoinAnalysisResult.UniqueKeys, streamJoinAnalysisResult.TablesPerStream); RemoveUnidirectionalAndTable(queryPlanX, streamJoinAnalysisResult); if (log.IsDebugEnabled) { log.Debug(methodName + "2-Stream queryPlan=" + queryPlanX); } return(queryPlanX); } bool hasPreferMergeJoin = HintEnum.PREFER_MERGE_JOIN.GetHint(annotations) != null; bool hasForceNestedIter = HintEnum.FORCE_NESTED_ITER.GetHint(annotations) != null; bool isAllInnerJoins = outerJoinDescList.Length == 0 || OuterJoinDesc.ConsistsOfAllInnerJoins(outerJoinDescList); if (isAllInnerJoins && !hasPreferMergeJoin) { QueryPlan queryPlanX = NStreamQueryPlanBuilder.Build(queryGraph, typesPerStream, historicalViewableDesc, dependencyGraph, historicalStreamIndexLists, hasForceNestedIter, streamJoinAnalysisResult.UniqueKeys, streamJoinAnalysisResult.TablesPerStream); if (queryPlanX != null) { RemoveUnidirectionalAndTable(queryPlanX, streamJoinAnalysisResult); if (log.IsDebugEnabled) { log.Debug(methodName + "Count-Stream inner-join queryPlan=" + queryPlanX); } return(queryPlanX); } if (isQueryPlanLogging && queryPlanLog.IsInfoEnabled) { log.Info("Switching to Outer-NStream algorithm for query plan"); } } QueryPlan queryPlan = NStreamOuterQueryPlanBuilder.Build(queryGraph, outerJoinDescList, streamNames, typesPerStream, historicalViewableDesc, dependencyGraph, historicalStreamIndexLists, exprEvaluatorContext, streamJoinAnalysisResult.UniqueKeys, streamJoinAnalysisResult.TablesPerStream); RemoveUnidirectionalAndTable(queryPlan, streamJoinAnalysisResult); return(queryPlan); }
/// <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"); } } }
private static StreamJoinAnalysisResult VerifyJoinViews(StatementSpecCompiled statementSpec, NamedWindowMgmtService namedWindowMgmtService, AgentInstanceContext defaultAgentInstanceContext) { var streamSpecs = statementSpec.StreamSpecs; var analysisResult = new StreamJoinAnalysisResult(streamSpecs.Length); if (streamSpecs.Length < 2) { return(analysisResult); } // Determine if any stream has a unidirectional keyword // inspect unidirectional indicator and named window flags var unidirectionalStreamNumber = -1; for (var i = 0; i < statementSpec.StreamSpecs.Length; i++) { var streamSpec = statementSpec.StreamSpecs[i]; if (streamSpec.Options.IsUnidirectional) { analysisResult.SetUnidirectionalInd(i); if (unidirectionalStreamNumber != -1) { throw new ExprValidationException("The unidirectional keyword can only apply to one stream in a join"); } unidirectionalStreamNumber = i; } if (streamSpec.ViewSpecs.Length > 0) { analysisResult.SetHasChildViews(i); } if (streamSpec is NamedWindowConsumerStreamSpec) { var nwSpec = (NamedWindowConsumerStreamSpec)streamSpec; if (nwSpec.OptPropertyEvaluator != null && !streamSpec.Options.IsUnidirectional) { throw new ExprValidationException("Failed to validate named window use in join, contained-event is only allowed for named windows when marked as unidirectional"); } analysisResult.SetNamedWindow(i); var processor = namedWindowMgmtService.GetProcessor(nwSpec.WindowName); string[][] uniqueIndexes = processor.UniqueIndexes; analysisResult.UniqueKeys[i] = uniqueIndexes; if (processor.IsVirtualDataWindow) { analysisResult.ViewExternal[i] = agentInstanceContext => processor.GetProcessorInstance(agentInstanceContext).RootViewInstance.VirtualDataWindow; } } } if ((unidirectionalStreamNumber != -1) && (analysisResult.HasChildViews[unidirectionalStreamNumber])) { throw new ExprValidationException("The unidirectional keyword requires that no views are declared onto the stream"); } analysisResult.UnidirectionalStreamNumber = unidirectionalStreamNumber; // count streams that provide data, excluding streams that poll data (DB and method) var countProviderNonpolling = 0; for (var i = 0; i < statementSpec.StreamSpecs.Length; i++) { var streamSpec = statementSpec.StreamSpecs[i]; if ((streamSpec is MethodStreamSpec) || (streamSpec is DBStatementStreamSpec) || (streamSpec is TableQueryStreamSpec)) { continue; } countProviderNonpolling++; } // if there is only one stream providing data, the analysis is done if (countProviderNonpolling == 1) { return(analysisResult); } // there are multiple driving streams, verify the presence of a view for insert/remove stream // validation of join views works differently for unidirectional as there can be self-joins that don't require a view // see if this is a self-join in which all streams are filters and filter specification is the same. FilterSpecCompiled unidirectionalFilterSpec = null; FilterSpecCompiled lastFilterSpec = null; var pureSelfJoin = true; foreach (var streamSpec in statementSpec.StreamSpecs) { if (!(streamSpec is FilterStreamSpecCompiled)) { pureSelfJoin = false; continue; } var filterSpec = ((FilterStreamSpecCompiled)streamSpec).FilterSpec; if ((lastFilterSpec != null) && (!lastFilterSpec.EqualsTypeAndFilter(filterSpec))) { pureSelfJoin = false; } if (streamSpec.ViewSpecs.Length > 0) { pureSelfJoin = false; } lastFilterSpec = filterSpec; if (streamSpec.Options.IsUnidirectional) { unidirectionalFilterSpec = filterSpec; } } // self-join without views and not unidirectional if ((pureSelfJoin) && (unidirectionalFilterSpec == null)) { analysisResult.IsPureSelfJoin = true; return(analysisResult); } // weed out filter and pattern streams that don't have a view in a join for (var i = 0; i < statementSpec.StreamSpecs.Length; i++) { var streamSpec = statementSpec.StreamSpecs[i]; if (streamSpec.ViewSpecs.Length > 0) { continue; } var name = streamSpec.OptionalStreamName; if ((name == null) && (streamSpec is FilterStreamSpecCompiled)) { name = ((FilterStreamSpecCompiled)streamSpec).FilterSpec.FilterForEventTypeName; } if ((name == null) && (streamSpec is PatternStreamSpecCompiled)) { name = "pattern event stream"; } if (streamSpec.Options.IsUnidirectional) { continue; } // allow a self-join without a child view, in that the filter spec is the same as the unidirection's stream filter if ((unidirectionalFilterSpec != null) && (streamSpec is FilterStreamSpecCompiled) && (((FilterStreamSpecCompiled)streamSpec).FilterSpec.EqualsTypeAndFilter(unidirectionalFilterSpec))) { analysisResult.SetUnidirectionalNonDriving(i); continue; } if ((streamSpec is FilterStreamSpecCompiled) || (streamSpec is PatternStreamSpecCompiled)) { throw new ExprValidationException("Joins require that at least one view is specified for each stream, no view was specified for " + name); } } return(analysisResult); }
/// <summary> /// Builds join tuple composer. /// </summary> /// <param name="statementName">Name of the statement.</param> /// <param name="statementId">The statement identifier.</param> /// <param name="outerJoinDescList">list of descriptors for outer join criteria</param> /// <param name="optionalFilterNode">filter tree for analysis to build indexes for fast access</param> /// <param name="streamTypes">types of streams</param> /// <param name="streamNames">names of streams</param> /// <param name="streamJoinAnalysisResult">The stream join analysis result.</param> /// <param name="queryPlanLogging">if set to <c>true</c> [query plan logging].</param> /// <param name="statementContext">The statement context.</param> /// <param name="historicalViewableDesc">The historical viewable desc.</param> /// <param name="exprEvaluatorContext">The expr evaluator context.</param> /// <param name="selectsRemoveStream">if set to <c>true</c> [selects remove stream].</param> /// <param name="hasAggregations">if set to <c>true</c> [has aggregations].</param> /// <param name="tableService">The table service.</param> /// <param name="isOnDemandQuery">if set to <c>true</c> [is on demand query].</param> /// <param name="allowIndexInit">if set to <c>true</c> [allow index initialize].</param> /// <returns> /// composer implementation /// </returns> /// <throws>com.espertech.esper.epl.expression.core.ExprValidationException is thrown to indicate thatvalidation of view use in joins failed. /// {D255958A-8513-4226-94B9-080D98F904A1}</throws> public static JoinSetComposerPrototype MakeComposerPrototype(string statementName, int statementId, OuterJoinDesc[] outerJoinDescList, ExprNode optionalFilterNode, EventType[] streamTypes, string[] streamNames, StreamJoinAnalysisResult streamJoinAnalysisResult, bool queryPlanLogging, StatementContext statementContext, HistoricalViewableDesc historicalViewableDesc, ExprEvaluatorContext exprEvaluatorContext, bool selectsRemoveStream, bool hasAggregations, TableService tableService, bool isOnDemandQuery, bool allowIndexInit) { // Determine if there is a historical stream, and what dependencies exist var historicalDependencyGraph = new DependencyGraph(streamTypes.Length, false); for (var i = 0; i < streamTypes.Length; i++) { if (historicalViewableDesc.Historical[i]) { var streamsThisStreamDependsOn = historicalViewableDesc.DependenciesPerHistorical[i]; historicalDependencyGraph.AddDependency(i, streamsThisStreamDependsOn); } } if (log.IsDebugEnabled) { log.Debug("Dependency graph: " + historicalDependencyGraph); } // Handle a join with a database or other historical data source for 2 streams if ((historicalViewableDesc.HasHistorical) && (streamTypes.Length == 2)) { return(MakeComposerHistorical2Stream(outerJoinDescList, optionalFilterNode, streamTypes, historicalViewableDesc, queryPlanLogging, exprEvaluatorContext, statementContext, streamNames, allowIndexInit)); } var isOuterJoins = !OuterJoinDesc.ConsistsOfAllInnerJoins(outerJoinDescList); // Query graph for graph relationships between streams/historicals // For outer joins the query graph will just contain outer join relationships var hint = ExcludePlanHint.GetHint(streamNames, statementContext); var queryGraph = new QueryGraph(streamTypes.Length, hint, false); if (outerJoinDescList.Length > 0) { OuterJoinAnalyzer.Analyze(outerJoinDescList, queryGraph); if (log.IsDebugEnabled) { log.Debug(".makeComposer After outer join queryGraph=\n" + queryGraph); } } // Let the query graph reflect the where-clause if (optionalFilterNode != null) { // Analyze relationships between streams using the optional filter expression. // Relationships are properties in AND and EQUALS nodes of joins. FilterExprAnalyzer.Analyze(optionalFilterNode, queryGraph, isOuterJoins); if (log.IsDebugEnabled) { log.Debug(".makeComposer After filter expression queryGraph=\n" + queryGraph); } // Add navigation entries based on key and index property equivalency (a=b, b=c follows a=c) QueryGraph.FillEquivalentNav(streamTypes, queryGraph); if (log.IsDebugEnabled) { log.Debug(".makeComposer After fill equiv. nav. queryGraph=\n" + queryGraph); } } // Historical index lists var historicalStreamIndexLists = new HistoricalStreamIndexList[streamTypes.Length]; var queryPlan = QueryPlanBuilder.GetPlan(streamTypes, outerJoinDescList, queryGraph, streamNames, historicalViewableDesc, historicalDependencyGraph, historicalStreamIndexLists, streamJoinAnalysisResult, queryPlanLogging, statementContext.Annotations, exprEvaluatorContext); // remove unused indexes - consider all streams or all unidirectional var usedIndexes = new HashSet <TableLookupIndexReqKey>(); var indexSpecs = queryPlan.IndexSpecs; for (var streamNum = 0; streamNum < queryPlan.ExecNodeSpecs.Length; streamNum++) { var planNode = queryPlan.ExecNodeSpecs[streamNum]; if (planNode != null) { planNode.AddIndexes(usedIndexes); } } foreach (var indexSpec in indexSpecs) { if (indexSpec == null) { continue; } var items = indexSpec.Items; var indexNames = items.Keys.ToArray(); foreach (var indexName in indexNames) { if (!usedIndexes.Contains(indexName)) { items.Remove(indexName); } } } var hook = QueryPlanIndexHookUtil.GetHook(statementContext.Annotations); if (queryPlanLogging && (QueryPlanLog.IsInfoEnabled || hook != null)) { QueryPlanLog.Info("Query plan: " + queryPlan.ToQueryPlan()); if (hook != null) { hook.Join(queryPlan); } } // register index-use references for tables if (!isOnDemandQuery) { foreach (var usedIndex in usedIndexes) { if (usedIndex.TableName != null) { tableService.GetTableMetadata(usedIndex.TableName).AddIndexReference(usedIndex.Name, statementName); } } } var joinRemoveStream = selectsRemoveStream || hasAggregations; return(new JoinSetComposerPrototypeImpl( statementName, statementId, outerJoinDescList, optionalFilterNode, streamTypes, streamNames, streamJoinAnalysisResult, statementContext.Annotations, historicalViewableDesc, exprEvaluatorContext, indexSpecs, queryPlan, historicalStreamIndexLists, joinRemoveStream, isOuterJoins, tableService, statementContext.EventTableIndexService)); }