public void TestRecursiveBuild() { var streamNum = 2; var queryGraph = new QueryGraphForge(6, null, false); var outerInnerGraph = new OuterInnerDirectionalGraph(6); var completedStreams = new HashSet <int>(); var substreamsPerStream = new LinkedHashMap <int, int[]>(); var requiredPerStream = new bool[6]; outerInnerGraph.Add(3, 2).Add(2, 1).Add(4, 3).Add(1, 0).Add(3, 5); var fake = supportExprNodeFactory.MakeIdentNode("TheString", "s0"); queryGraph.AddStrictEquals(2, "", fake, 3, "", fake); queryGraph.AddStrictEquals(3, "", fake, 4, "", fake); queryGraph.AddStrictEquals(3, "", fake, 5, "", fake); queryGraph.AddStrictEquals(2, "", fake, 1, "", fake); queryGraph.AddStrictEquals(1, "", fake, 0, "", fake); ISet <InterchangeablePair <int, int> > innerJoins = new HashSet <InterchangeablePair <int, int> >(); var innerJoinGraph = new InnerJoinGraph(6, innerJoins); var streamStack = new Stack <int>(); NStreamOuterQueryPlanBuilder.RecursiveBuild( streamNum, streamStack, queryGraph, outerInnerGraph, innerJoinGraph, completedStreams, substreamsPerStream, requiredPerStream, new DependencyGraph(6, false)); Assert.AreEqual(6, substreamsPerStream.Count); EPAssertionUtil.AssertEqualsExactOrder(substreamsPerStream.Get(2), new[] { 3, 1 }); EPAssertionUtil.AssertEqualsExactOrder(substreamsPerStream.Get(3), new[] { 4, 5 }); EPAssertionUtil.AssertEqualsExactOrder(substreamsPerStream.Get(1), new[] { 0 }); EPAssertionUtil.AssertEqualsExactOrder(substreamsPerStream.Get(4), new int[] { }); EPAssertionUtil.AssertEqualsExactOrder(substreamsPerStream.Get(5), new int[] { }); EPAssertionUtil.AssertEqualsExactOrder(substreamsPerStream.Get(0), new int[] { }); NStreamOuterQueryPlanBuilder.VerifyJoinedPerStream(2, substreamsPerStream); EPAssertionUtil.AssertEqualsExactOrder( requiredPerStream, new[] { false, false, false, true, true, false } ); }
/// <summary> /// Builds a graph of outer joins given the outer join information from the statement. /// Eliminates right and left joins and full joins by placing the information in a graph object. /// </summary> /// <param name="numStreams">is the number of streams</param> /// <param name="outerJoinDescList">list of outer join stream numbers and property names</param> /// <returns>graph object</returns> public static OuterInnerDirectionalGraph GraphOuterJoins( int numStreams, OuterJoinDesc[] outerJoinDescList) { if (outerJoinDescList.Length + 1 != numStreams) { throw new ArgumentException("Number of outer join descriptors and number of streams not matching up"); } var graph = new OuterInnerDirectionalGraph(numStreams); for (var i = 0; i < outerJoinDescList.Length; i++) { var desc = outerJoinDescList[i]; var streamMax = i + 1; // the outer join must references streams less then streamMax // Check outer join on-expression, if provided int streamOne; int streamTwo; int lowerStream; int higherStream; if (desc.OptLeftNode != null) { streamOne = desc.OptLeftNode.StreamId; streamTwo = desc.OptRightNode.StreamId; if (streamOne > streamMax || streamTwo > streamMax || streamOne == streamTwo) { throw new ArgumentException("Outer join descriptors reference future streams, or same streams"); } // Determine who is the first stream in the streams listed lowerStream = streamOne; higherStream = streamTwo; if (streamOne > streamTwo) { lowerStream = streamTwo; higherStream = streamOne; } } else { streamOne = i; streamTwo = i + 1; lowerStream = i; higherStream = i + 1; graph.AddUnqualifiedNavigable(streamOne, streamTwo); } // Add to graph if (desc.OuterJoinType == OuterJoinType.FULL) { graph.Add(streamOne, streamTwo); graph.Add(streamTwo, streamOne); } else if (desc.OuterJoinType == OuterJoinType.LEFT) { graph.Add(lowerStream, higherStream); } else if (desc.OuterJoinType == OuterJoinType.RIGHT) { graph.Add(higherStream, lowerStream); } else if (desc.OuterJoinType == OuterJoinType.INNER) { // no navigability for inner joins } else { throw new ArgumentException( "Outer join descriptors join type not handled, type=" + desc.OuterJoinType); } } return graph; }