diff --git a/src/main/antlr4/org/s1ck/gdl/GDL.g4 b/src/main/antlr4/org/s1ck/gdl/GDL.g4 index cb17c08..3745777 100644 --- a/src/main/antlr4/org/s1ck/gdl/GDL.g4 +++ b/src/main/antlr4/org/s1ck/gdl/GDL.g4 @@ -148,6 +148,7 @@ timeFunc interval : intervalSelector | intervalFromStamps + | complexInterval ; @@ -161,8 +162,14 @@ intervalFromStamps ; // TODO: change (only placeholder yet) -complexIntervall - : Identifier '.' IntervalConst +complexInterval + : complexIntervalArgument '.merge(' complexIntervalArgument ')' + | complexIntervalArgument '.join(' complexIntervalArgument ')' + ; + +complexIntervalArgument + : intervalSelector + | intervalFromStamps ; // TODO: add functions that yield timePoint diff --git a/src/main/java/org/s1ck/gdl/GDLLoader.java b/src/main/java/org/s1ck/gdl/GDLLoader.java index 2d18bab..87eea92 100644 --- a/src/main/java/org/s1ck/gdl/GDLLoader.java +++ b/src/main/java/org/s1ck/gdl/GDLLoader.java @@ -433,10 +433,17 @@ public void enterIntvF(GDLParser.IntvFContext ctx){ * @return complex predicate that encodes the interval function. Atoms are time stamp comparisons */ private Predicate buildIntervalFunction(GDLParser.IntvFContext ctx) { + int predicateSizeBefore = currentPredicates.size(); TimePoint[] intv = buildIntervall(ctx.interval()); TimePoint from = intv[0]; TimePoint to = intv[1]; - return createIntervalPredicates(from, to, ctx.intervalFunc()); + Predicate predicate = createIntervalPredicates(from, to, ctx.intervalFunc()); + // additional constraints? + int countConstraints = currentPredicates.size() - predicateSizeBefore; + for(int i = 0; i(b) " + "WHERE tx.between(1970-01-01, 2020-05-01)"); @@ -217,10 +221,10 @@ public void globalPredicateTest(){ // all froms <= l2 new And( new And( - new Comparison(eFrom, Comparator.LTE, l2), - new Comparison(aFrom, Comparator.LTE, l2) + new Comparison(eFrom, LTE, l2), + new Comparison(aFrom, LTE, l2) ), - new Comparison(bFrom, Comparator.LTE, l2) + new Comparison(bFrom, LTE, l2) ), new And( new And( @@ -238,10 +242,10 @@ public void globalPredicateTest(){ Predicate result2 = loader.getPredicates().get(); Or expected2 = new Or( new Or( - new Comparison(l1, Comparator.LTE, eFrom), - new Comparison(l1, Comparator.LTE, aFrom) + new Comparison(l1, LTE, eFrom), + new Comparison(l1, LTE, aFrom) ), - new Comparison(l1, Comparator.LTE, bFrom) + new Comparison(l1, LTE, bFrom) ); assertPredicateEquals(expected2, result2); @@ -281,6 +285,150 @@ public void globalPredicateTest(){ assertPredicateEquals(expected3, result3); } + @Test + public void intervallMergeAndJoinTest(){ + GDLLoader loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + "WHERE a.tx.merge(b.tx).succeeds(Interval(1970-01-01, 2020-05-01))"); + TimeSelector aTxFrom = new TimeSelector("a", TX_FROM); + TimeSelector aTxTo = new TimeSelector("a", TX_TO); + TimeSelector bTxFrom = new TimeSelector("b", TX_FROM); + TimeSelector bTxTo = new TimeSelector("b",TX_TO); + TimeLiteral tl1 = new TimeLiteral("1970-01-01"); + TimeLiteral tl2 = new TimeLiteral("2020-05-01"); + Predicate expected = new And( + //succeeds + new Or( + new Comparison(aTxFrom, GTE, tl2), + new Comparison(bTxFrom, GTE, tl2) + ), + //overlaps/meets + new And( + new And( + new Comparison(aTxFrom, LTE, aTxTo), + new Comparison(aTxFrom, LTE, bTxTo) + ), + new And( + new Comparison(bTxFrom, LTE, aTxTo), + new Comparison(bTxFrom, LTE, bTxTo) + ) + ) + ); + Predicate result = loader.getPredicates().get(); + assertPredicateEquals(expected, result); + + /* + * Join + */ + loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + "WHERE a.tx.join(b.tx).succeeds(Interval(1970-01-01, 2020-05-01))"); + expected = new And( + //succeeds + new And( + new Comparison(aTxFrom, GTE, tl2), + new Comparison(bTxFrom, GTE, tl2) + ), + //overlaps/meets + new And( + new And( + new Comparison(aTxFrom, LTE, aTxTo), + new Comparison(aTxFrom, LTE, bTxTo) + ), + new And( + new Comparison(bTxFrom, LTE, aTxTo), + new Comparison(bTxFrom, LTE, bTxTo) + ) + ) + ); + result = loader.getPredicates().get(); + assertPredicateEquals(expected, result); + /* + * Combine Merge And Join + */ + loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + "WHERE a.tx.join(b.tx).precedes(a.tx.merge(b.tx))"); + expected = new And( + new And( + // actual precedes predicate + new And( + new Or( + new Comparison(aTxTo, LTE, aTxFrom), + new Comparison(aTxTo, LTE, bTxFrom) + ), + new Or( + new Comparison(bTxTo, LTE, aTxFrom), + new Comparison(bTxTo, LTE, bTxFrom) + ) + ), + //first overlap/meet + new And( + new And( + new Comparison(aTxFrom, LTE, aTxTo), + new Comparison(aTxFrom, LTE, bTxTo) + ), + new And( + new Comparison(bTxFrom, LTE, aTxTo), + new Comparison(bTxFrom, LTE, bTxTo) + ) + ) + ), + //second overlap/meet + new And( + new And( + new Comparison(aTxFrom, LTE, aTxTo), + new Comparison(aTxFrom, LTE, bTxTo) + ), + new And( + new Comparison(bTxFrom, LTE, aTxTo), + new Comparison(bTxFrom, LTE, bTxTo) + ) + ) + ); + result = loader.getPredicates().get(); + assertPredicateEquals(expected, result); + loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " + + "WHERE a.tx.merge(b.tx).precedes(a.tx.join(b.tx))"); + expected = new And( + new And( + // actual preceeds predicate + new Or( + new And( + new Comparison(aTxTo, LTE, aTxFrom), + new Comparison(aTxTo, LTE, bTxFrom) + ), + new And( + new Comparison(bTxTo, LTE, aTxFrom), + new Comparison(bTxTo, LTE, bTxFrom) + ) + ), + //first overlap/meet + new And( + new And( + new Comparison(aTxFrom, LTE, aTxTo), + new Comparison(aTxFrom, LTE, bTxTo) + ), + new And( + new Comparison(bTxFrom, LTE, aTxTo), + new Comparison(bTxFrom, LTE, bTxTo) + ) + ) + ), + //second overlap/meet + new And( + new And( + new Comparison(aTxFrom, LTE, aTxTo), + new Comparison(aTxFrom, LTE, bTxTo) + ), + new And( + new Comparison(bTxFrom, LTE, aTxTo), + new Comparison(bTxFrom, LTE, bTxTo) + ) + ) + ); + result = loader.getPredicates().get(); + assertPredicateEquals(result, expected); + System.out.println(loader.getPredicates()); + } + @Test public void graphTimeStampTest(){