Beispiel #1
0
        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 CompareExecNodeSpec(
     int streamNum,
     QueryPlanNodeForge expected,
     QueryPlanNodeForge actual,
     IDictionary<TableLookupIndexReqKey, TableLookupIndexReqKey> indexNameMapping)
 {
     if (actual is QueryPlanNodeNoOpForge && expected == null) {
     }
     else if (actual is TableLookupNodeForge && expected is TableLookupNodeForge) {
         CompareTableLookup(
             streamNum,
             (TableLookupNodeForge) expected,
             (TableLookupNodeForge) actual,
             indexNameMapping);
     }
     else if (actual is TableOuterLookupNodeForge && expected is TableOuterLookupNodeForge) {
         CompareTableLookupOuter(
             streamNum,
             (TableOuterLookupNodeForge) expected,
             (TableOuterLookupNodeForge) actual,
             indexNameMapping);
     }
     else if (actual is LookupInstructionQueryPlanNodeForge && expected is LookupInstructionQueryPlanNodeForge) {
         CompareInstruction(
             streamNum,
             (LookupInstructionQueryPlanNodeForge) expected,
             (LookupInstructionQueryPlanNodeForge) actual,
             indexNameMapping);
     }
     else {
         Assert.Fail(
             "Failed to compare plan node for stream " +
             streamNum +
             ", unhandled plan " +
             actual.GetType().Name);
     }
 }
Beispiel #3
0
        public static QueryPlanForgeDesc Build(
            QueryGraphForge queryGraph,
            EventType[] typesPerStream,
            HistoricalViewableDesc historicalViewableDesc,
            DependencyGraph dependencyGraph,
            HistoricalStreamIndexListForge[] historicalStreamIndexLists,
            bool hasForceNestedIter,
            string[][][] indexedStreamsUniqueProps,
            TableMetaData[] tablesPerStream,
            StreamJoinAnalysisResultCompileTime streamJoinAnalysisResult,
            StatementRawInfo raw,
            SerdeCompileTimeResolver serdeResolver)
        {
            if (Log.IsDebugEnabled) {
                Log.Debug(".build filterQueryGraph=" + queryGraph);
            }

            var numStreams = queryGraph.NumStreams;
            var additionalForgeables = new List<StmtClassForgeableFactory>();   
            var indexSpecs = QueryPlanIndexBuilder.BuildIndexSpec(
                queryGraph,
                typesPerStream,
                indexedStreamsUniqueProps);
            if (Log.IsDebugEnabled) {
                Log.Debug(".build Index build completed, indexes=" + QueryPlanIndexForge.Print(indexSpecs));
            }

            // any historical streams don't get indexes, the lookup strategy accounts for cached indexes
            if (historicalViewableDesc.IsHistorical) {
                for (var i = 0; i < historicalViewableDesc.Historical.Length; i++) {
                    if (historicalViewableDesc.Historical[i]) {
                        indexSpecs[i] = null;
                    }
                }
            }

            var planNodeSpecs = new QueryPlanNodeForge[numStreams];
            var worstDepth = int.MaxValue;
            for (var streamNo = 0; streamNo < numStreams; streamNo++) {
                // no plan for historical streams that are dependent upon other streams
                if (historicalViewableDesc.Historical[streamNo] && dependencyGraph.HasDependency(streamNo)) {
                    planNodeSpecs[streamNo] = new QueryPlanNodeNoOpForge();
                    continue;
                }

                var bestChainResult = ComputeBestPath(streamNo, queryGraph, dependencyGraph);
                var bestChain = bestChainResult.Chain;
                if (Log.IsDebugEnabled) {
                    Log.Debug(".build For stream " + streamNo + " bestChain=" + bestChain.RenderAny());
                }

                if (bestChainResult.Depth < worstDepth) {
                    worstDepth = bestChainResult.Depth;
                }

                var planDesc = CreateStreamPlan(
                    streamNo,
                    bestChain,
                    queryGraph,
                    indexSpecs,
                    typesPerStream,
                    historicalViewableDesc.Historical,
                    historicalStreamIndexLists,
                    tablesPerStream,
                    streamJoinAnalysisResult,
                    raw,
                    serdeResolver);

                planNodeSpecs[streamNo] = planDesc.Forge;
                additionalForgeables.AddAll(planDesc.AdditionalForgeables);
                
                if (Log.IsDebugEnabled) {
                    Log.Debug(".build spec=" + planNodeSpecs[streamNo]);
                }
            }

            // We use the merge/nested (outer) join algorithm instead.
            if (worstDepth < numStreams - 1 && !hasForceNestedIter) {
                return null;
            }

            // build historical index and lookup strategies
            for (var i = 0; i < numStreams; i++) {
                var plan = planNodeSpecs[i];
                QueryPlanNodeForgeVisitor visitor = new ProxyQueryPlanNodeForgeVisitor {
                    ProcVisit = node => {
                        if (node is HistoricalDataPlanNodeForge) {
                            var historical = (HistoricalDataPlanNodeForge) node;
                            JoinSetComposerPrototypeHistoricalDesc desc = historicalStreamIndexLists[historical.StreamNum].GetStrategy(
                                historical.LookupStreamNum, raw, serdeResolver);
                            historical.PollResultIndexingStrategy = desc.IndexingForge;
                            historical.HistoricalIndexLookupStrategy = desc.LookupForge;
                            additionalForgeables.AddAll(desc.AdditionalForgeables);
                        }
                    }
                };
                plan.Accept(visitor);
            }

            var forge = new QueryPlanForge(indexSpecs, planNodeSpecs);
            return new QueryPlanForgeDesc(forge, additionalForgeables);
        }
        /// <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);
        }
 public void Visit(QueryPlanNodeForge node)
 {
     ProcVisit?.Invoke(node);
 }
        internal static QueryPlanForgeDesc Build(
            QueryGraphForge queryGraph,
            OuterJoinDesc[] outerJoinDescList,
            string[] streamNames,
            EventType[] typesPerStream,
            HistoricalViewableDesc historicalViewableDesc,
            DependencyGraph dependencyGraph,
            HistoricalStreamIndexListForge[] historicalStreamIndexLists,
            string[][][] indexedStreamsUniqueProps,
            TableMetaData[] tablesPerStream,
            StreamJoinAnalysisResultCompileTime streamJoinAnalysisResult,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            if (Log.IsDebugEnabled) {
                Log.Debug(".build filterQueryGraph=" + queryGraph);
            }

            var numStreams = queryGraph.NumStreams;
            var planNodeSpecs = new QueryPlanNodeForge[numStreams];
            var additionalForgeables = new List<StmtClassForgeableFactory>();

            // Build index specifications
            var indexSpecs = QueryPlanIndexBuilder.BuildIndexSpec(
                queryGraph,
                typesPerStream,
                indexedStreamsUniqueProps);

            // any historical streams don't get indexes, the lookup strategy accounts for cached indexes
            if (historicalViewableDesc.IsHistorical) {
                for (var i = 0; i < historicalViewableDesc.Historical.Length; i++) {
                    if (historicalViewableDesc.Historical[i]) {
                        indexSpecs[i] = null;
                    }
                }
            }

            // Build graph of the outer join to inner table relationships.
            // Build a map of inner joins.
            OuterInnerDirectionalGraph outerInnerGraph;
            InnerJoinGraph innerJoinGraph;
            if (outerJoinDescList.Length > 0) {
                outerInnerGraph = GraphOuterJoins(numStreams, outerJoinDescList);
                innerJoinGraph = InnerJoinGraph.GraphInnerJoins(numStreams, outerJoinDescList);
            }
            else {
                // all inner joins - thereby no (or empty) directional graph
                outerInnerGraph = new OuterInnerDirectionalGraph(numStreams);
                innerJoinGraph = new InnerJoinGraph(numStreams, true);
            }

            if (Log.IsDebugEnabled) {
                Log.Debug(".build directional graph=" + outerInnerGraph.Print());
            }

            // For each stream determine the query plan
            for (var streamNo = 0; streamNo < numStreams; streamNo++) {
                // no plan for historical streams that are dependent upon other streams
                if (historicalViewableDesc.Historical[streamNo] && dependencyGraph.HasDependency(streamNo)) {
                    planNodeSpecs[streamNo] = new QueryPlanNodeNoOpForge();
                    continue;
                }

                QueryPlanNodeForgeDesc desc = BuildPlanNode(
                    numStreams,
                    streamNo,
                    streamNames,
                    queryGraph,
                    outerInnerGraph,
                    outerJoinDescList,
                    innerJoinGraph,
                    indexSpecs,
                    typesPerStream,
                    historicalViewableDesc.Historical,
                    dependencyGraph,
                    historicalStreamIndexLists,
                    tablesPerStream,
                    streamJoinAnalysisResult,
                    statementRawInfo,
                    services);
                QueryPlanNodeForge queryPlanNode = desc.Forge;
                additionalForgeables.AddAll(desc.AdditionalForgeables);

                if (Log.IsDebugEnabled) {
                    Log.Debug(
                        ".build spec for stream '" +
                        streamNames[streamNo] +
                        "' number " +
                        streamNo +
                        " is " +
                        queryPlanNode);
                }

                planNodeSpecs[streamNo] = queryPlanNode;
            }

            var queryPlan = new QueryPlanForge(indexSpecs, planNodeSpecs);
            if (Log.IsDebugEnabled) {
                Log.Debug(".build query plan=" + queryPlan);
            }

            return new QueryPlanForgeDesc(queryPlan, additionalForgeables);
        }