예제 #1
0
        public void TestCreateStreamPlan()
        {
            QueryPlanIndex[] indexes = QueryPlanIndexBuilder.BuildIndexSpec(_queryGraph, _typesPerStream, new string[_queryGraph.NumStreams][][]);
            for (int i = 0; i < indexes.Length; i++)
            {
                Log.Debug(".testCreateStreamPlan index " + i + " = " + indexes[i]);
            }

            QueryPlanNode plan = NStreamQueryPlanBuilder.CreateStreamPlan(
                0, new int[] { 2, 4, 3, 1 }, _queryGraph,
                indexes, _typesPerStream, new bool[5], null,
                new TableMetadata[_queryGraph.NumStreams]);

            Log.Debug(".testCreateStreamPlan plan=" + plan);

            Assert.IsTrue(plan is NestedIterationNode);
            var nested          = (NestedIterationNode)plan;
            var tableLookupSpec = (TableLookupNode)nested.ChildNodes[0];

            // Check lookup strategy for first lookup
            var lookupStrategySpec = (IndexedTableLookupPlanSingle)tableLookupSpec.LookupStrategySpec;

            Assert.AreEqual("P01", ((QueryGraphValueEntryHashKeyedProp)lookupStrategySpec.HashKey).KeyProperty);
            Assert.AreEqual(0, lookupStrategySpec.LookupStream);
            Assert.AreEqual(2, lookupStrategySpec.IndexedStream);
            Assert.NotNull(lookupStrategySpec.IndexNum);

            // Check lookup strategy for last lookup
            tableLookupSpec = (TableLookupNode)nested.ChildNodes[3];
            var unkeyedSpecScan = (FullTableScanLookupPlan)tableLookupSpec.LookupStrategySpec;

            Assert.AreEqual(1, unkeyedSpecScan.IndexedStream);
            Assert.NotNull(unkeyedSpecScan.IndexNum);
        }
예제 #2
0
        /// <summary>
        /// Build query plan.
        /// </summary>
        /// <param name="typesPerStream">event types for each stream</param>
        /// <param name="queryGraph">navigability info</param>
        /// <param name="optionalOuterJoinType">outer join type, null if not an outer join</param>
        /// <param name="uniqueIndexProps">The unique index props.</param>
        /// <param name="tablesPerStream">The tables per stream.</param>
        /// <returns>
        /// query plan
        /// </returns>
        public static QueryPlan Build(EventType[] typesPerStream, QueryGraph queryGraph, OuterJoinType?optionalOuterJoinType, string[][][] uniqueIndexProps, TableMetadata[] tablesPerStream)
        {
            var indexSpecs = QueryPlanIndexBuilder.BuildIndexSpec(queryGraph, typesPerStream, uniqueIndexProps);

            var execNodeSpecs = new QueryPlanNode[2];
            var lookupPlans   = new TableLookupPlan[2];

            // plan lookup from 1 to zero
            lookupPlans[1] = NStreamQueryPlanBuilder.CreateLookupPlan(queryGraph, 1, 0, indexSpecs[0], typesPerStream, tablesPerStream[0]);

            // plan lookup from zero to 1
            lookupPlans[0]   = NStreamQueryPlanBuilder.CreateLookupPlan(queryGraph, 0, 1, indexSpecs[1], typesPerStream, tablesPerStream[1]);
            execNodeSpecs[0] = new TableLookupNode(lookupPlans[0]);
            execNodeSpecs[1] = new TableLookupNode(lookupPlans[1]);

            if (optionalOuterJoinType != null)
            {
                if ((optionalOuterJoinType.Equals(OuterJoinType.LEFT)) ||
                    (optionalOuterJoinType.Equals(OuterJoinType.FULL)))
                {
                    execNodeSpecs[0] = new TableOuterLookupNode(lookupPlans[0]);
                }
                if ((optionalOuterJoinType.Equals(OuterJoinType.RIGHT)) ||
                    (optionalOuterJoinType.Equals(OuterJoinType.FULL)))
                {
                    execNodeSpecs[1] = new TableOuterLookupNode(lookupPlans[1]);
                }
            }

            return(new QueryPlan(indexSpecs, execNodeSpecs));
        }
예제 #3
0
        public void TestIndexAlreadyExists()
        {
            _queryGraph = new QueryGraph(5, null, false);
            _queryGraph.AddStrictEquals(0, "p00", Make(0, "p00"), 1, "p10", Make(1, "p10"));
            _queryGraph.AddStrictEquals(0, "p00", Make(0, "p00"), 2, "p20", Make(2, "p20"));

            QueryPlanIndex[] indexes = QueryPlanIndexBuilder.BuildIndexSpec(_queryGraph, _types, new String[_queryGraph.NumStreams][][]);

            String[][] expected = new String[][] { new [] { "p00" } };
            EPAssertionUtil.AssertEqualsExactOrder(indexes[0].IndexProps, expected);
        }
예제 #4
0
        public void TestBuildIndexSpec()
        {
            QueryPlanIndex[] indexes = QueryPlanIndexBuilder.BuildIndexSpec(_queryGraph, _types, new String[_queryGraph.NumStreams][][]);

            String[][] expected = new String[][] { new [] { "p00" }, new [] { "p01" } };
            EPAssertionUtil.AssertEqualsExactOrder(indexes[0].IndexProps, expected);

            expected = new String[][] { new [] { "p10" } };
            EPAssertionUtil.AssertEqualsExactOrder(indexes[1].IndexProps, expected);

            expected = new String[][] { new [] { "p20" }, new [] { "p21" } };
            EPAssertionUtil.AssertEqualsExactOrder(indexes[2].IndexProps, expected);

            expected = new String[][] { new [] { "p30", "p31" } };
            EPAssertionUtil.AssertEqualsExactOrder(indexes[3].IndexProps, expected);

            expected = new String[][] { new [] { "p42" }, new [] { "p40", "p41" } };
            EPAssertionUtil.AssertEqualsExactOrder(indexes[4].IndexProps, expected);

            // Test no index, should have a single entry with a zero-length property name array
            _queryGraph = new QueryGraph(3, null, false);
            indexes     = QueryPlanIndexBuilder.BuildIndexSpec(_queryGraph, _types, new String[_queryGraph.NumStreams][][]);
            Assert.AreEqual(1, indexes[1].IndexProps.Length);
        }
예제 #5
0
        /// <summary>
        /// Build a query plan based on the stream property relationships indicated in queryGraph.
        /// </summary>
        /// <param name="queryGraph">navigation info between streams</param>
        /// <param name="typesPerStream">event types for each stream</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="hasForceNestedIter">if set to <c>true</c> [has force nested iter].</param>
        /// <param name="indexedStreamsUniqueProps">The indexed streams unique props.</param>
        /// <param name="tablesPerStream">The tables per stream.</param>
        /// <returns>
        /// query plan
        /// </returns>
        internal static QueryPlan Build(
            QueryGraph queryGraph,
            EventType[] typesPerStream,
            HistoricalViewableDesc historicalViewableDesc,
            DependencyGraph dependencyGraph,
            HistoricalStreamIndexList[] historicalStreamIndexLists,
            bool hasForceNestedIter,
            string[][][] indexedStreamsUniqueProps,
            TableMetadata[] tablesPerStream)
        {
            if (Log.IsDebugEnabled)
            {
                Log.Debug(".build queryGraph=" + queryGraph);
            }

            var numStreams = queryGraph.NumStreams;
            var indexSpecs = QueryPlanIndexBuilder.BuildIndexSpec(queryGraph, typesPerStream, indexedStreamsUniqueProps);

            if (Log.IsDebugEnabled)
            {
                Log.Debug(".build Index build completed, indexes=" + QueryPlanIndex.Print(indexSpecs));
            }

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

            var planNodeSpecs = new QueryPlanNode[numStreams];
            int 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 QueryPlanNodeNoOp();
                    continue;
                }

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

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

                planNodeSpecs[streamNo] = CreateStreamPlan(streamNo, bestChain, queryGraph, indexSpecs, typesPerStream, historicalViewableDesc.Historical, historicalStreamIndexLists, tablesPerStream);
                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);
            }
            return(new QueryPlan(indexSpecs, planNodeSpecs));
        }
예제 #6
0
        /// <summary>
        /// Build a query plan based on the stream property relationships indicated in queryGraph.
        /// </summary>
        /// <param name="queryGraph">navigation info between streams</param>
        /// <param name="outerJoinDescList">descriptors for all outer joins</param>
        /// <param name="streamNames">stream names</param>
        /// <param name="typesPerStream">event types for each stream</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="exprEvaluatorContext">context for expression evalauation</param>
        /// <param name="indexedStreamsUniqueProps">The indexed streams unique props.</param>
        /// <param name="tablesPerStream">The tables per stream.</param>
        /// <returns>
        /// query plan
        /// </returns>
        /// <throws>ExprValidationException if the query planning failed</throws>
        internal static QueryPlan Build(
            QueryGraph queryGraph,
            OuterJoinDesc[] outerJoinDescList,
            string[] streamNames,
            EventType[] typesPerStream,
            HistoricalViewableDesc historicalViewableDesc,
            DependencyGraph dependencyGraph,
            HistoricalStreamIndexList[] historicalStreamIndexLists,
            ExprEvaluatorContext exprEvaluatorContext,
            string[][][] indexedStreamsUniqueProps,
            TableMetadata[] tablesPerStream)
        {
            if (Log.IsDebugEnabled)
            {
                Log.Debug(".build queryGraph=" + queryGraph);
            }

            var numStreams    = queryGraph.NumStreams;
            var planNodeSpecs = new QueryPlanNode[numStreams];

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

            if (Log.IsDebugEnabled)
            {
                Log.Debug(".build Index build completed, indexes=" + QueryPlanIndex.Print(indexSpecs));
            }

            // any historical streams don't get indexes, the lookup strategy accounts for cached indexes
            if (historicalViewableDesc.HasHistorical)
            {
                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 QueryPlanNodeNoOp();
                    continue;
                }

                var queryPlanNode = BuildPlanNode(numStreams, streamNo, streamNames, queryGraph, outerInnerGraph, outerJoinDescList, innerJoinGraph, indexSpecs, typesPerStream, historicalViewableDesc.Historical, dependencyGraph, historicalStreamIndexLists, exprEvaluatorContext, tablesPerStream);

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

                planNodeSpecs[streamNo] = queryPlanNode;
            }

            var queryPlan = new QueryPlan(indexSpecs, planNodeSpecs);

            if (Log.IsDebugEnabled)
            {
                Log.Debug(".build query plan=" + queryPlan);
            }

            return(queryPlan);
        }