/// <summary> /// Fill in equivalent key properties(navigation entries) on all streams. /// For example, if a=b and b=c then addRelOpInternal a = c.The method adds new equalivalent key properties /// until no additional entries to be added are found, ie. several passes can be made. /// </summary> /// <param name="typesPerStream">type info</param> /// <param name="queryGraph">- navigablity info between streams</param> public static void FillEquivalentNav( EventType[] typesPerStream, QueryGraphForge queryGraph) { bool addedEquivalency; // Repeat until no more entries were added do { addedEquivalency = false; // For each stream-to-stream combination for (var lookupStream = 0; lookupStream < queryGraph.NumStreams; lookupStream++) { for (var indexedStream = 0; indexedStream < queryGraph.NumStreams; indexedStream++) { if (lookupStream == indexedStream) { continue; } var added = FillEquivalentNav(typesPerStream, queryGraph, lookupStream, indexedStream); if (added) { addedEquivalency = true; } } } } while (addedEquivalency); }
/// <summary> /// Looks at the key and index(aka.left and right) properties of the 2 streams and checks /// for each property if any equivalent index properties exist for other streams. /// Example: s0.p0 = s1.p1 and s1.p1 = s2.p2 ==> therefore s0.p0 = s2.p2 /// ==> look stream s0, property p0; indexed stream s1, property p1 /// Is there any other lookup stream that has stream 1 and property p1 as index property? ==> this is stream s2, p2 /// Add navigation entry between stream s0 and property p0 to stream s2, property p2 /// </summary> private static bool FillEquivalentNav( EventType[] typesPerStream, QueryGraphForge queryGraph, int lookupStream, string keyProp, int indexedStream, string indexProp) { var addedEquivalency = false; for (var otherStream = 0; otherStream < queryGraph.NumStreams; otherStream++) { if (otherStream == lookupStream || otherStream == indexedStream) { continue; } var value = queryGraph.GetGraphValue(otherStream, indexedStream); QueryGraphValuePairHashKeyIndexForge hashKeys = value.HashKeyProps; var otherStrictKeyProps = hashKeys.StrictKeys; var otherIndexProps = hashKeys.Indexed; var otherPropertyNum = -1; if (otherIndexProps == null) { continue; } for (var i = 0; i < otherIndexProps.Length; i++) { if (otherIndexProps[i].Equals(indexProp)) { otherPropertyNum = i; break; } } if (otherPropertyNum != -1) { if (otherStrictKeyProps[otherPropertyNum] != null) { ExprIdentNode identNodeLookup = new ExprIdentNodeImpl( typesPerStream[lookupStream], keyProp, lookupStream); ExprIdentNode identNodeOther = new ExprIdentNodeImpl( typesPerStream[otherStream], otherStrictKeyProps[otherPropertyNum], otherStream); var added = queryGraph.AddStrictEquals( lookupStream, keyProp, identNodeLookup, otherStream, otherStrictKeyProps[otherPropertyNum], identNodeOther); if (added) { addedEquivalency = true; } } } } return addedEquivalency; }
public void SetUp() { queryGraph = new QueryGraphForge(3, null, false); types = new EventType[] { supportEventTypeFactory.CreateMapType(CreateType("P0,P00,P01,P02")), supportEventTypeFactory.CreateMapType(CreateType("P1,P10,P11,P12")), supportEventTypeFactory.CreateMapType(CreateType("P2,P20,P21")), supportEventTypeFactory.CreateMapType(CreateType("P3,P30,P31")), supportEventTypeFactory.CreateMapType(CreateType("P4,P40,P41,P42")), }; }
public void TestGetNavigableStreams() { ExprIdentNode fake = supportExprNodeFactory.MakeIdentNode("TheString", "s0"); queryGraph = new QueryGraphForge(5, null, false); queryGraph.AddStrictEquals(3, "p3", fake, 4, "p4", fake); queryGraph.AddStrictEquals(2, "P2", fake, 3, "p3", fake); queryGraph.AddStrictEquals(1, "P1", fake, 2, "P2", fake); Assert.AreEqual(0, queryGraph.GetNavigableStreams(0).Count); EPAssertionUtil.AssertEqualsAnyOrder(new int[] { 2 }, queryGraph.GetNavigableStreams(1)); EPAssertionUtil.AssertEqualsAnyOrder(new int[] { 1, 3 }, queryGraph.GetNavigableStreams(2)); EPAssertionUtil.AssertEqualsAnyOrder(new int[] { 2, 4 }, queryGraph.GetNavigableStreams(3)); EPAssertionUtil.AssertEqualsAnyOrder(new int[] { 3 }, queryGraph.GetNavigableStreams(4)); }
/// <summary> /// Looks at the key and index (aka. left and right) properties of the 2 streams and checks /// for each property if any equivalent index properties exist for other streams. /// </summary> /// <exception cref="IllegalStateException">Unexpected key and index property number mismatch</exception> private static bool FillEquivalentNav( EventType[] typesPerStream, QueryGraphForge queryGraph, int lookupStream, int indexedStream) { var addedEquivalency = false; var value = queryGraph.GetGraphValue(lookupStream, indexedStream); if (value.IsEmptyNotNavigable) { return false; } QueryGraphValuePairHashKeyIndexForge hashKeys = value.HashKeyProps; var strictKeyProps = hashKeys.StrictKeys; var indexProps = hashKeys.Indexed; if (strictKeyProps.Length == 0) { return false; } if (strictKeyProps.Length != indexProps.Length) { throw new IllegalStateException("Unexpected key and index property number mismatch"); } for (var i = 0; i < strictKeyProps.Length; i++) { if (strictKeyProps[i] == null) { continue; // not a strict key } var added = FillEquivalentNav( typesPerStream, queryGraph, lookupStream, strictKeyProps[i], indexedStream, indexProps[i]); if (added) { addedEquivalency = true; } } return addedEquivalency; }
public void TestFillEquivalency() { // test with just 3 streams queryGraph.AddStrictEquals(0, "P00", Make(0, "P00"), 1, "P10", Make(1, "P10")); queryGraph.AddStrictEquals(1, "P10", Make(1, "P10"), 2, "P20", Make(2, "P20")); Assert.IsFalse(queryGraph.IsNavigableAtAll(0, 2)); Assert.AreEqual(0, SupportQueryGraphTestUtil.GetStrictKeyProperties(queryGraph, 0, 2).Length); Assert.AreEqual(0, SupportQueryGraphTestUtil.GetIndexProperties(queryGraph, 0, 2).Length); QueryGraphForge.FillEquivalentNav(types, queryGraph); Assert.IsTrue(queryGraph.IsNavigableAtAll(0, 2)); string[] expectedOne = new string[] { "P00" }; string[] expectedTwo = new string[] { "P20" }; Assert.IsTrue(Arrays.AreEqual(expectedOne, SupportQueryGraphTestUtil.GetStrictKeyProperties(queryGraph, 0, 2))); Assert.IsTrue(Arrays.AreEqual(expectedTwo, SupportQueryGraphTestUtil.GetIndexProperties(queryGraph, 0, 2))); // test with 5 streams, connect all streams to all streams queryGraph = new QueryGraphForge(5, null, false); queryGraph.AddStrictEquals(0, "P0", Make(0, "P0"), 1, "P1", Make(1, "P1")); queryGraph.AddStrictEquals(3, "P3", Make(3, "P3"), 4, "P4", Make(4, "P4")); queryGraph.AddStrictEquals(2, "P2", Make(2, "P2"), 3, "P3", Make(3, "P3")); queryGraph.AddStrictEquals(1, "P1", Make(1, "P1"), 2, "P2", Make(2, "P2")); QueryGraphForge.FillEquivalentNav(types, queryGraph); for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { if (i == j) { continue; } Assert.IsTrue(queryGraph.IsNavigableAtAll(i, j), "Not navigable: i=" + i + " j=" + j); } } }