Skip to content

Commit

Permalink
[s1ck#49] implemented comparisons between timestamps
Browse files Browse the repository at this point in the history
  • Loading branch information
lc0197 committed Jun 15, 2020
1 parent 042d670 commit a7fc9d6
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 7 deletions.
10 changes: 7 additions & 3 deletions src/main/antlr4/org/s1ck/gdl/GDL.g4
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ expression2 : atom ;
atom : parenthesizedExpression
| comparisonExpression
| timeFunc
| temporalComparison
;

comparisonExpression
Expand All @@ -113,8 +114,7 @@ comparisonExpression
comparisonElement
: Identifier
| propertyLookup
| literal
| timeSelector
| literal
;

parenthesizedExpression : '(' expression ')' ;
Expand All @@ -132,13 +132,17 @@ literal
| FloatingPointLiteral
| NaN
| Null
| timeLiteral
;


//------------------------
// time-related
//________________________

temporalComparison
: timePoint ComparisonOP timePoint
;

timeFunc
: interval '.' intervalFunc #intvF
| timePoint '.' stampFunc #stmpF
Expand Down
50 changes: 48 additions & 2 deletions src/main/java/org/s1ck/gdl/GDLLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,11 @@ public void enterComparisonExpression(GDLParser.ComparisonExpressionContext ctx)
currentPredicates.add(buildComparison(ctx));
}

@Override
public void enterTemporalComparison(GDLParser.TemporalComparisonContext ctx){
currentPredicates.add(buildTemporalComparison(ctx));
}

/**
* Builds a {@code Predicate} from the given Intervall-Function (caller is a interval)
* interval functions are e.g. succeeds(x), between(x,y)....
Expand All @@ -427,6 +432,20 @@ public void enterIntvF(GDLParser.IntvFContext ctx){
currentPredicates.add(buildIntervalFunction(ctx));
}

/**
* Builds a Comparison filter operator from comparison context
*
* @param ctx the comparison context that will be parsed
* @return parsed operator
*/
private Comparison buildTemporalComparison(GDLParser.TemporalComparisonContext ctx) {
ComparableExpression lhs = buildTimePoint(ctx.timePoint(0));
ComparableExpression rhs = buildTimePoint(ctx.timePoint(1));
Comparator comp = Comparator.fromString(ctx .ComparisonOP().getText());

return new Comparison(lhs, comp, rhs);
}

/**
* Converts an interval function into a (complex) predicate
* For example, i.between(x,y) would be translated to a predicate ((i.from<= y) AND (i.to>x))
Expand Down Expand Up @@ -608,7 +627,14 @@ else if(ctx.complexInterval()!=null){
}
return null;
}


/**
* Creates an intervall as an array {@code {from, to}} from a selector context.
* I.e., a intervall like {@code a.val} would result in {@code {a.val_from, a.val_to}}.
* What is more, {@code val} results in {@code GLOBAL_SELECTOR.val_from, GLOBAL_SELECTOR.val_to}
* @param ctx context from which to derive the interval
* @return {@code {from, to}} representing the interval
*/
private TimePoint[] buildIntervalFromSelector(GDLParser.IntervalSelectorContext ctx){
String var = ctx.Identifier()!=null ?
resolveIdentifier(ctx.Identifier().getText()) : TimeSelector.GLOBAL_SELECTOR;
Expand All @@ -618,12 +644,31 @@ private TimePoint[] buildIntervalFromSelector(GDLParser.IntervalSelectorContext
return new TimePoint[]{from, to};
}

/**
* Creates an intervall as an array {@code {from, to}} from a interval constant context.
* I.e., a intervall like {@code Interval(1970-01-01, 2020-01-01)} would result in
* {@code {1970-01-01, 2020-01-01}}.
* @param ctx context from which to derive the interval
* @return {@code {from, to}} representing the interval
*/
private TimePoint[] buildIntervalFromStamps(GDLParser.IntervalFromStampsContext ctx){
TimePoint from = buildTimePoint(ctx.timePoint(0));
TimePoint to = buildTimePoint(ctx.timePoint(1));
return new TimePoint[]{from,to};
}

/**
* Creates an intervall as an array {@code {from, to}} from a complex interval context, i.e.
* {@code merge} and {@code join} expressions.
* An intervall like {@code a.merge(b)} would result in {@code {max(a.from, b.from), min(a.to, b.to}}
* while {@code a.join(b)} results in {@code {min(a.from, b.from), max(a.to, b.to)}}.
* Furthermore, a constraint {max(a.from, b.from)<= min(a.to, b.to)} is added (intervals must overlap,
* in at least one ms)
* @param arg1 context from which to derive the calling interval
* @param arg2 context from which to derive the callee interval
* @param join true iff join should be performed, false iff merge is desired
* @return {@code {from, to}} representing the interval
*/
private TimePoint[] buildIntervalFromComplex(GDLParser.ComplexIntervalArgumentContext arg1,
GDLParser.ComplexIntervalArgumentContext arg2,
boolean join){
Expand Down Expand Up @@ -1157,7 +1202,8 @@ private ComparableExpression extractComparableExpression(GDLParser.ComparisonEle
return new Literal(getPropertyValue(element.literal()));
} else if(element.propertyLookup() != null) {
return buildPropertySelector(element.propertyLookup());
} else {
}
else {
return new ElementSelector(element.Identifier().getText());
}
}
Expand Down
19 changes: 17 additions & 2 deletions src/test/java/org/s1ck/gdl/GDLLoaderTemporalTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.s1ck.gdl.model.comparables.time.TimeSelector.TimeField.*;
import static org.s1ck.gdl.utils.Comparator.GTE;
import static org.s1ck.gdl.utils.Comparator.LTE;
import static org.s1ck.gdl.utils.Comparator.*;

public class GDLLoaderTemporalTest {

Expand Down Expand Up @@ -439,6 +438,22 @@ public void containsTest(){
assertPredicateEquals(expected, loader.getPredicates().get());
}

@Test
public void comparisonTest(){
GDLLoader loader = getLoaderFromGDLString("MATCH (a)-[e]->(b) " +
"WHERE a.tx_from > b.val_from AND 2013-06-01 <= a.val_to");
Predicate expected = new And(
new Comparison(new TimeSelector("a", TX_FROM), GT,
new TimeSelector("b", VAL_FROM)),
new Comparison(new TimeLiteral("2013-06-01"), LTE,
new TimeSelector("a", VAL_TO)
)
);
System.out.println(loader.getPredicates().get());
System.out.println(expected);
assertPredicateEquals(loader.getPredicates().get(), expected);
}

/**
* Does not fail iff {@code result==expected} or {@code result.switchSides()==expected}
* @param result predicate to compare
Expand Down

0 comments on commit a7fc9d6

Please sign in to comment.