/// <summary> /// Recursive method to run through all child nodes and, for each result set tuple returned /// by a child node, execute the inner child of the child node until there are no inner child nodes. /// </summary> /// <param name="lookupEvent">current event to use for lookup by child node</param> /// <param name="nestingOrderIndex">index within the child nodes indicating what nesting level we are at</param> /// <param name="currentPath">prototype result row to use by child nodes for generating result rows</param> /// <param name="result">result tuple rows to be populated</param> /// <param name="exprEvaluatorContext">context for expression evalauation</param> protected void RecursiveNestedJoin( EventBean lookupEvent, int nestingOrderIndex, EventBean[] currentPath, ICollection<EventBean[]> result, ExprEvaluatorContext exprEvaluatorContext) { IList<EventBean[]> nestedResult = new List<EventBean[]>(); ExecNode nestedExecNode = childNodes[nestingOrderIndex]; nestedExecNode.Process(lookupEvent, currentPath, nestedResult, exprEvaluatorContext); bool isLastStream = nestingOrderIndex == nestingOrderLength - 1; // This is not the last nesting level so no result rows are added. Invoke next nesting level for // each event found. if (!isLastStream) { foreach (EventBean[] row in nestedResult) { EventBean lookup = row[nestedStreams[nestingOrderIndex]]; RecursiveNestedJoin(lookup, nestingOrderIndex + 1, row, result, exprEvaluatorContext); } return; } // Loop to add result rows foreach (EventBean[] row in nestedResult) { result.Add(row); } }
public void Lookup(EventBean[] lookupEvents, ICollection <MultiKey <EventBean> > joinSet, ExprEvaluatorContext exprEvaluatorContext) { if ((lookupEvents != null) && (lookupEvents.Length != 0)) { unchecked { var results = new List <EventBean[]>(); int count = lookupEvents.Length; for (int ii = 0; ii < count; ii++) { var theEvent = lookupEvents[ii]; var prototype = new EventBean[NumStreams]; // Set up _prototype row prototype[ForStream] = theEvent; // Perform execution ExecNode.Process(theEvent, prototype, results, exprEvaluatorContext); // Convert results into unique set results.ForEach(row => joinSet.Add(new MultiKey <EventBean>(row))); results.Clear(); } } } }
public override ExecNode MakeExec( string statementName, string statementId, Attribute[] annotations, IDictionary <TableLookupIndexReqKey, EventTable>[] indexPerStream, EventType[] streamTypes, Viewable[] streamViews, HistoricalStreamIndexList[] historicalStreamIndexList, VirtualDWView[] viewExternal, ILockable[] tableSecondaryIndexLocks) { if (_childNodes.IsEmpty()) { throw new IllegalStateException("Zero child nodes for nested iteration"); } var execNode = new NestedIterationExecNode(_nestingOrder); foreach (QueryPlanNode child in _childNodes) { ExecNode childExec = child.MakeExec( statementName, statementId, annotations, indexPerStream, streamTypes, streamViews, historicalStreamIndexList, viewExternal, tableSecondaryIndexLocks); execNode.AddChildNode(childExec); } return(execNode); }
public JoinSetComposerDesc Create(Viewable[] streamViews, bool isFireAndForget, AgentInstanceContext agentInstanceContext) { // Build indexes var indexesPerStream = new IDictionary <TableLookupIndexReqKey, EventTable> [_indexSpecs.Length]; var tableSecondaryIndexLocks = new ILockable[_indexSpecs.Length]; var hasTable = false; for (var streamNo = 0; streamNo < _indexSpecs.Length; streamNo++) { if (_indexSpecs[streamNo] == null) { continue; } var items = _indexSpecs[streamNo].Items; indexesPerStream[streamNo] = new LinkedHashMap <TableLookupIndexReqKey, EventTable>(); if (_streamJoinAnalysisResult.TablesPerStream[streamNo] != null) { // build for tables var metadata = _streamJoinAnalysisResult.TablesPerStream[streamNo]; var state = _tableService.GetState(metadata.TableName, agentInstanceContext.AgentInstanceId); foreach (var indexName in state.SecondaryIndexes) // add secondary indexes { var eventTable = state.GetIndex(indexName); indexesPerStream[streamNo].Put(new TableLookupIndexReqKey(indexName, metadata.TableName), eventTable); } var index = state.GetIndex(metadata.TableName); // add primary index indexesPerStream[streamNo].Put(new TableLookupIndexReqKey(metadata.TableName, metadata.TableName), index); hasTable = true; tableSecondaryIndexLocks[streamNo] = agentInstanceContext.StatementContext.IsWritesToTables ? state.TableLevelRWLock.WriteLock : state.TableLevelRWLock.ReadLock; } else { // build tables for implicit indexes foreach (var entry in items) { EventTable index; if (_streamJoinAnalysisResult.ViewExternal[streamNo] != null) { var view = _streamJoinAnalysisResult.ViewExternal[streamNo].Invoke(agentInstanceContext); index = view.GetJoinIndexTable(items.Get(entry.Key)); } else { index = EventTableUtil.BuildIndex(streamNo, items.Get(entry.Key), _streamTypes[streamNo], false, entry.Value.IsUnique, null); } indexesPerStream[streamNo].Put(entry.Key, index); } } } // obtain any external views var externalViewProviders = _streamJoinAnalysisResult.ViewExternal; var externalViews = new VirtualDWView[externalViewProviders.Length]; for (var i = 0; i < externalViews.Length; i++) { if (externalViewProviders[i] != null) { externalViews[i] = _streamJoinAnalysisResult.ViewExternal[i].Invoke(agentInstanceContext); } } // Build strategies var queryExecSpecs = _queryPlan.ExecNodeSpecs; var queryStrategies = new QueryStrategy[queryExecSpecs.Length]; for (var i = 0; i < queryExecSpecs.Length; i++) { var planNode = queryExecSpecs[i]; if (planNode == null) { Log.Debug(".makeComposer No execution node for stream " + i + " '" + _streamNames[i] + "'"); continue; } var executionNode = planNode.MakeExec(_statementName, _statementId, _annotations, indexesPerStream, _streamTypes, streamViews, _historicalStreamIndexLists, externalViews, tableSecondaryIndexLocks); if (Log.IsDebugEnabled) { Log.Debug(".makeComposer Execution nodes for stream " + i + " '" + _streamNames[i] + "' : \n" + ExecNode.Print(executionNode)); } queryStrategies[i] = new ExecNodeQueryStrategy(i, _streamTypes.Length, executionNode); } // Remove indexes that are from tables as these are only available to query strategies if (hasTable) { indexesPerStream = RemoveTableIndexes(indexesPerStream, _streamJoinAnalysisResult.TablesPerStream); } // If this is not unidirectional and not a self-join (excluding self-outer-join) JoinSetComposerDesc joinSetComposerDesc; if ((!_streamJoinAnalysisResult.IsUnidirectional) && (!_streamJoinAnalysisResult.IsPureSelfJoin || _outerJoinDescList.Length > 0)) { JoinSetComposer composer; if (_historicalViewableDesc.HasHistorical) { composer = new JoinSetComposerHistoricalImpl(indexesPerStream, queryStrategies, streamViews, _exprEvaluatorContext); } else { if (isFireAndForget) { composer = new JoinSetComposerFAFImpl(indexesPerStream, queryStrategies, _streamJoinAnalysisResult.IsPureSelfJoin, _exprEvaluatorContext, _joinRemoveStream, _isOuterJoins); } else { composer = new JoinSetComposerImpl(indexesPerStream, queryStrategies, _streamJoinAnalysisResult.IsPureSelfJoin, _exprEvaluatorContext, _joinRemoveStream); } } // rewrite the filter expression for all-inner joins in case "on"-clause outer join syntax was used to include those expressions var filterExpression = GetFilterExpressionInclOnClause(_optionalFilterNode, _outerJoinDescList); var postJoinEval = filterExpression == null ? null : filterExpression.ExprEvaluator; joinSetComposerDesc = new JoinSetComposerDesc(composer, postJoinEval); } else { QueryStrategy driver; int unidirectionalStream; if (_streamJoinAnalysisResult.UnidirectionalStreamNumber != -1) { unidirectionalStream = _streamJoinAnalysisResult.UnidirectionalStreamNumber; driver = queryStrategies[unidirectionalStream]; } else { unidirectionalStream = 0; driver = queryStrategies[0]; } JoinSetComposer composer = new JoinSetComposerStreamToWinImpl(indexesPerStream, _streamJoinAnalysisResult.IsPureSelfJoin, unidirectionalStream, driver, _streamJoinAnalysisResult.UnidirectionalNonDriving); var postJoinEval = _optionalFilterNode == null ? null : _optionalFilterNode.ExprEvaluator; joinSetComposerDesc = new JoinSetComposerDesc(composer, postJoinEval); } // compile prior events per stream to preload any indexes var eventsPerStream = new EventBean[_streamNames.Length][]; var events = new List <EventBean>(); for (var i = 0; i < eventsPerStream.Length; i++) { // For named windows and tables, we don't need to preload indexes from the iterators as this is always done already if (_streamJoinAnalysisResult.NamedWindow[i] || _streamJoinAnalysisResult.TablesPerStream[i] != null) { continue; } IEnumerator <EventBean> en = null; if (!(streamViews[i] is HistoricalEventViewable) && !(streamViews[i] is DerivedValueView)) { try { en = streamViews[i].GetEnumerator(); } catch (UnsupportedOperationException) { // Joins do not support the iterator } } if (en != null) { while (en.MoveNext()) { events.Add(en.Current); } eventsPerStream[i] = events.ToArray(); events.Clear(); } else { eventsPerStream[i] = new EventBean[0]; } } // init joinSetComposerDesc.JoinSetComposer.Init(eventsPerStream); return(joinSetComposerDesc); }
/// <summary> /// Add a child node. /// </summary> /// <param name="childNode">to add</param> public void AddChildNode(ExecNode childNode) { childNodes.Add(childNode); }
/// <summary>CTor. </summary> /// <param name="forStream">stream the strategy is for</param> /// <param name="numStreams">number of streams in total</param> /// <param name="execNode">execution node for building join tuple set</param> public ExecNodeQueryStrategy(int forStream, int numStreams, ExecNode execNode) { ForStream = forStream; NumStreams = numStreams; ExecNode = execNode; }