/// <summary> /// Walks the chain of lookups and constructs lookup strategy and plan specification based /// on the index specifications. /// </summary> /// <param name="lookupStream">the stream to construct the query plan for</param> /// <param name="bestChain">the chain that the lookup follows to make best use of indexes</param> /// <param name="queryGraph">the repository for key properties to indexes</param> /// <param name="indexSpecsPerStream">specifications of indexes</param> /// <param name="typesPerStream">event types for each stream</param> /// <param name="isHistorical">indicator for each stream if it is a historical streams or not</param> /// <param name="historicalStreamIndexLists">index management, populated for the query plan</param> /// <param name="tablesPerStream">tables</param> /// <param name="streamJoinAnalysisResult">stream join analysis</param> /// <param name="raw">raw statement information</param> /// <param name="serdeResolver">serde resolver</param> /// <returns>NestedIterationNode with lookups attached underneath</returns> public static QueryPlanNodeForgeDesc CreateStreamPlan( int lookupStream, int[] bestChain, QueryGraphForge queryGraph, QueryPlanIndexForge[] indexSpecsPerStream, EventType[] typesPerStream, bool[] isHistorical, HistoricalStreamIndexListForge[] historicalStreamIndexLists, TableMetaData[] tablesPerStream, StreamJoinAnalysisResultCompileTime streamJoinAnalysisResult, StatementRawInfo raw, SerdeCompileTimeResolver serdeResolver) { var nestedIterNode = new NestedIterationNodeForge(bestChain); var currentLookupStream = lookupStream; var additionalForgeables = new List<StmtClassForgeableFactory>(); // Walk through each successive lookup for (var i = 0; i < bestChain.Length; i++) { var indexedStream = bestChain[i]; QueryPlanNodeForge node; if (isHistorical[indexedStream]) { if (historicalStreamIndexLists[indexedStream] == null) { historicalStreamIndexLists[indexedStream] = new HistoricalStreamIndexListForge( indexedStream, typesPerStream, queryGraph); } historicalStreamIndexLists[indexedStream].AddIndex(currentLookupStream); node = new HistoricalDataPlanNodeForge( indexedStream, lookupStream, currentLookupStream, typesPerStream.Length, null); } else { var tableLookupPlan = CreateLookupPlan( queryGraph, currentLookupStream, indexedStream, streamJoinAnalysisResult.IsVirtualDW(indexedStream), indexSpecsPerStream[indexedStream], typesPerStream, tablesPerStream[indexedStream], raw, serdeResolver); node = new TableLookupNodeForge(tableLookupPlan.Forge); additionalForgeables.AddAll(tableLookupPlan.AdditionalForgeables); } nestedIterNode.AddChildNode(node); currentLookupStream = bestChain[i]; } return new QueryPlanNodeForgeDesc(nestedIterNode, additionalForgeables); }
public void TestCreateStreamPlan() { QueryPlanIndexForge[] indexes = QueryPlanIndexBuilder.BuildIndexSpec(queryGraph, typesPerStream, new string[queryGraph.NumStreams][][]); for (int i = 0; i < indexes.Length; i++) { log.Debug(".testCreateStreamPlan index " + i + " = " + indexes[i]); } QueryPlanNodeForge plan = NStreamQueryPlanBuilder.CreateStreamPlan(0, new int[] { 2, 4, 3, 1 }, queryGraph, indexes, typesPerStream, new bool[5], null, new TableMetaData[queryGraph.NumStreams], new StreamJoinAnalysisResultCompileTime(5)); log.Debug(".testCreateStreamPlan plan=" + plan); Assert.IsTrue(plan is NestedIterationNodeForge); NestedIterationNodeForge nested = (NestedIterationNodeForge)plan; TableLookupNodeForge tableLookupSpec = (TableLookupNodeForge)nested.ChildNodes[0]; // Check lookup strategy for first lookup IndexedTableLookupPlanHashedOnlyForge lookupStrategySpec = (IndexedTableLookupPlanHashedOnlyForge)tableLookupSpec.LookupStrategySpec; Assert.AreEqual("P01", ((ExprIdentNode)(lookupStrategySpec.HashKeys[0]).KeyExpr).ResolvedPropertyName); Assert.AreEqual(0, lookupStrategySpec.LookupStream); Assert.AreEqual(2, lookupStrategySpec.IndexedStream); Assert.IsNotNull(lookupStrategySpec.IndexNum); // Check lookup strategy for last lookup tableLookupSpec = (TableLookupNodeForge)nested.ChildNodes[3]; FullTableScanLookupPlanForge unkeyedSpecScan = (FullTableScanLookupPlanForge)tableLookupSpec.LookupStrategySpec; Assert.AreEqual(1, unkeyedSpecScan.IndexedStream); Assert.IsNotNull(unkeyedSpecScan.IndexNum); }
private static void CompareTableLookup( int streamNum, TableLookupNodeForge expected, TableLookupNodeForge actual, IDictionary<TableLookupIndexReqKey, TableLookupIndexReqKey> indexNameMapping) { CompareTableLookupPlan(streamNum, 0, expected.TableLookupPlan, actual.TableLookupPlan, indexNameMapping); }
/// <summary> /// Build query plan. /// </summary> /// <param name="queryGraph">navigability info</param> /// <param name="optionalOuterJoinType">outer join type, null if not an outer join</param> /// <param name="typesPerStream">event types for each stream</param> /// <param name="streamJoinAnalysisResult">stream join analysis</param> /// <returns>query plan</returns> public static QueryPlanForgeDesc Build( EventType[] typesPerStream, QueryGraphForge queryGraph, OuterJoinType? optionalOuterJoinType, StreamJoinAnalysisResultCompileTime streamJoinAnalysisResult, StatementRawInfo raw) { var uniqueIndexProps = streamJoinAnalysisResult.UniqueKeys; var tablesPerStream = streamJoinAnalysisResult.TablesPerStream; var additionalForgeable = new List<StmtClassForgeableFactory>(); var indexSpecs = QueryPlanIndexBuilder.BuildIndexSpec( queryGraph, typesPerStream, uniqueIndexProps); var execNodeSpecs = new QueryPlanNodeForge[2]; var lookupPlans = new TableLookupPlanForge[2]; // plan lookup from 1 to zero TableLookupPlanDesc plan1to0 = NStreamQueryPlanBuilder.CreateLookupPlan( queryGraph, 1, 0, streamJoinAnalysisResult.IsVirtualDW(0), indexSpecs[0], typesPerStream, tablesPerStream[0], raw, SerdeCompileTimeResolverNonHA.INSTANCE); lookupPlans[1] = plan1to0.Forge; additionalForgeable.AddAll(plan1to0.AdditionalForgeables); // plan lookup from zero to 1 TableLookupPlanDesc plan0to1 = NStreamQueryPlanBuilder.CreateLookupPlan( queryGraph, 0, 1, streamJoinAnalysisResult.IsVirtualDW(1), indexSpecs[1], typesPerStream, tablesPerStream[1], raw, SerdeCompileTimeResolverNonHA.INSTANCE); lookupPlans[0] = plan0to1.Forge; additionalForgeable.AddAll(plan0to1.AdditionalForgeables); execNodeSpecs[0] = new TableLookupNodeForge(lookupPlans[0]); execNodeSpecs[1] = new TableLookupNodeForge(lookupPlans[1]); if (optionalOuterJoinType != null) { if ((optionalOuterJoinType.Equals(OuterJoinType.LEFT)) || (optionalOuterJoinType.Equals(OuterJoinType.FULL))) { execNodeSpecs[0] = new TableOuterLookupNodeForge(lookupPlans[0]); } if ((optionalOuterJoinType.Equals(OuterJoinType.RIGHT)) || (optionalOuterJoinType.Equals(OuterJoinType.FULL))) { execNodeSpecs[1] = new TableOuterLookupNodeForge(lookupPlans[1]); } } var forge = new QueryPlanForge(indexSpecs, execNodeSpecs); return new QueryPlanForgeDesc(forge, additionalForgeable); }