Skip to content

Commit

Permalink
[s1ck#49] implemented asOf
Browse files Browse the repository at this point in the history
  • Loading branch information
lc0197 committed Apr 29, 2020
1 parent 1b3e6f9 commit 25102db
Show file tree
Hide file tree
Showing 24 changed files with 352 additions and 71 deletions.
13 changes: 7 additions & 6 deletions src/main/antlr4/org/s1ck/gdl/GDL.g4
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ literal
timeFunc
: interval '.' intervalFunc #intvF
| timePoint '.' stampFunc #stmpF
| Identifier '.asOf(' timePoint ')' #asOf
;

interval
Expand Down Expand Up @@ -169,15 +170,15 @@ timeLiteral
: Datetime
| Date
| Time
| IntegerLiteral;
| IntegerLiteral
| Now;

timeSelector
: Identifier '.' TimeProp
;

intervalFunc
: overlapsIntervallOperator
| asOfOperator
| fromToOperator
| betweenOperator
| precedesOperator
Expand All @@ -187,9 +188,6 @@ overlapsIntervallOperator
: 'overlaps(' interval ')'
;

asOfOperator
: 'asOf' '(' timePoint ')'
;

fromToOperator
: 'fromTo(' timePoint ',' timePoint ')'
Expand All @@ -210,7 +208,6 @@ succeedsOperator
stampFunc
: beforePointOperator
| afterPointOperator
| asOfOperator
| precedesOperator
| succeedsOperator
;
Expand Down Expand Up @@ -346,6 +343,10 @@ Time
: Digit Digit ':' Digit Digit (':' Digit Digit)?
;

Now
: ('N'|'n')('O'|'o')('W'|'w')
;

//-------------------------------
// General fragments
//-------------------------------
Expand Down
117 changes: 84 additions & 33 deletions src/main/java/org/s1ck/gdl/GDLLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import java.util.*;
import java.util.stream.Collectors;

import static org.s1ck.gdl.utils.Comparator.LTE;

class GDLLoader extends GDLBaseListener {

// used to cache elements which are assigned to user-defined variables
Expand Down Expand Up @@ -89,6 +91,7 @@ class GDLLoader extends GDLBaseListener {
private static final String ANONYMOUS_VERTEX_VARIABLE = "__v%d";
private static final String ANONYMOUS_EDGE_VARIABLE = "__e%d";


/**
* Initializes a new GDL Loader.
*
Expand Down Expand Up @@ -375,13 +378,15 @@ public void enterOutgoingEdge(GDLParser.OutgoingEdgeContext outgoingEdgeContext)
* Called when the parser leaves a WHERE expression
*
* Takes care that the filter build from the current expression is stored
* in the graph
* in the graph and that default asOf(now) predicates are added iff there are no constraints
* on any tx_to values
*
* @param ctx where context
*/
@Override
public void exitWhere(GDLParser.WhereContext ctx) {
addPredicates(Collections.singletonList(currentPredicates.pop()));
Predicate predicate = currentPredicates.pop();
addPredicates(Collections.singletonList(predicate));
}

/**
Expand All @@ -396,7 +401,7 @@ public void enterComparisonExpression(GDLParser.ComparisonExpressionContext ctx)

/**
* Builds a {@code Predicate} from the given Intervall-Function (caller is a interval)
* interval functions are e.g. asOf(x), between(x,y)....
* interval functions are e.g. succeeds(x), between(x,y)....
*
* @param ctx interval function context
*/
Expand All @@ -420,7 +425,7 @@ private Predicate buildIntervalFunction(GDLParser.IntvFContext ctx) {

/**
* Creates a new predicate about an intervall. There are different types of intervall predicates/
* functions: asOf, fromTo,...
* functions: precedes, fromTo,...
* @param from represents the start time (from value) of the intervall
* @param to represents the end time (to value) of the intervall
* @param intervalFunc contains the context information needed to create the correct predicate
Expand All @@ -431,9 +436,6 @@ private Predicate createIntervalPredicates(TimePoint from, TimePoint to, GDLPars
if(intervalFunc.overlapsIntervallOperator()!=null){
return createOverlapsPredicates(from, to, intervalFunc.overlapsIntervallOperator());
}
else if(intervalFunc.asOfOperator()!=null){
return createAsOfPredicates(from, to, intervalFunc.asOfOperator());
}
else if(intervalFunc.fromToOperator()!=null){
return createFromToPredicates(from, to, intervalFunc.fromToOperator());
}
Expand Down Expand Up @@ -465,10 +467,6 @@ private Predicate createOverlapsPredicates(TimePoint from, TimePoint to, GDLPars
return new Comparison(mx, Comparator.LT, mn);
}

private Predicate createAsOfPredicates(TimePoint from, TimePoint to, GDLParser.AsOfOperatorContext ctx){
TimePoint x = buildTimePoint(ctx.timePoint());
return new And(new Comparison(from, Comparator.LTE, x), new Comparison(to, Comparator.GTE, x));
}

/**
* Creates a predicate a.fromTo(x,y)= a.from<y AND a.to>x
Expand Down Expand Up @@ -497,7 +495,7 @@ private Predicate createBetweenPredicates(TimePoint from, TimePoint to, GDLParse
TimePoint x = buildTimePoint(ctx.timePoint(0));
TimePoint y = buildTimePoint(ctx.timePoint(1));
return new And(
new Comparison(from, Comparator.LTE, y),
new Comparison(from, LTE, y),
new Comparison(to, Comparator.GT, x)
);
}
Expand All @@ -513,7 +511,7 @@ private Predicate createBetweenPredicates(TimePoint from, TimePoint to, GDLParse
private Predicate createPrecedesPredicates(TimePoint point, GDLParser.PrecedesOperatorContext ctx){
TimePoint[] arg = buildIntervall(ctx.interval());
TimePoint arg_from = arg[0];
return new Comparison(point, Comparator.LTE, arg_from);
return new Comparison(point, LTE, arg_from);
}

/**
Expand Down Expand Up @@ -556,7 +554,7 @@ else if(ctx.intervalFromStamps()!=null){

/**
* Builds a {@code Predicate} from the given TimeStamp-Function (caller is a timestamp)
* time stamp functions are e.g. asOf(x), before(x),...
* time stamp functions are e.g. succeeds(x), before(x),...
*
* @param ctx stamp function context
*/
Expand All @@ -567,7 +565,7 @@ public void enterStmpF(GDLParser.StmpFContext ctx){

/**
* Converts a time stamp function into a (potentially complex) {@code Predicate}
* For example, i.asOf(x) would be translated to a {@code Predicate} i<=x
* For example, i.before(x) would be translated to a {@code Predicate} i<x
*
* @param ctx time stamp function context
* @return (potentially complex) {@code Predicate} that encodes the time stamp function. Atoms are time stamp comparisons
Expand All @@ -581,14 +579,11 @@ private Predicate buildStampFunction(GDLParser.StmpFContext ctx) {
* Returns time stamp {@code Predicate} given the caller (a time stamp) and its context
*
* @param tp the caller
* @param stampFunc context including the operator (e.g. asOf, before,...) and its argument(s)
* @param stampFunc context including the operator (e.g. before,...) and its argument(s)
* @return (potentially complex) {@code Predicate} that encodes the time stamp function. Atoms are time stamp comparisons
*/
private Predicate createStampPredicates(TimePoint tp, GDLParser.StampFuncContext stampFunc) {
if(stampFunc.asOfOperator()!=null){
return createAsOfPredicates(tp, stampFunc.asOfOperator());
}
else if(stampFunc.beforePointOperator()!=null) {
if(stampFunc.beforePointOperator()!=null) {
return createBeforePredicates(tp, stampFunc.beforePointOperator());
}
else if(stampFunc.afterPointOperator()!=null){
Expand All @@ -604,19 +599,6 @@ else if(stampFunc.succeedsOperator()!=null){
}


/**
* Creates an asOf-{@code Predicate} given the caller (a timestamp) and its context
*
* @param from the caller
* @param ctx its context including the argument
* @return a {@code Predicate} encoding the asOf function: from<=x
*/
private Predicate createAsOfPredicates(TimePoint from, GDLParser.AsOfOperatorContext ctx) {
TimePoint x = buildTimePoint(ctx.timePoint());
// TODO hier schon Abschätzung reinbringen?
return new Comparison(from, Comparator.LTE, x);
}

/**
* Creates a before {@code Predicate} given the caller (a timestamp) and its context
*
Expand Down Expand Up @@ -654,6 +636,75 @@ else if (ctx.timeSelector()!=null){
return null;
}

@Override
public void enterAsOf(GDLParser.AsOfContext ctx){
TimePoint tp = buildTimePoint(ctx.timePoint());
String identifier = resolveIdentifier(ctx.Identifier().getText());
currentPredicates.add(new And(
new Comparison(
new TimeSelector(identifier, TimeSelector.TimeField.TX_FROM),
LTE,
tp),
new Comparison(
new TimeSelector(identifier, TimeSelector.TimeField.TX_TO),
Comparator.GTE,
tp)
)
);
}

/**
* Creates the default asOf conditions, that ensure that every element's transaction time is
* as of now. This is only done if no other constraints on transaction times' ends
* are specified in the query.
* @return
*/
private Predicate createDefaultAsOf(){
Set<String> vars = new HashSet<>();
vars.addAll(userEdgeCache.keySet());
vars.addAll(userVertexCache.keySet());
vars.addAll(autoEdgeCache.keySet());
vars.addAll(autoVertexCache.keySet());
if(vars==null){
return null;
}
else{
TimeLiteral now = new TimeLiteral("now");
ArrayList<String> variables = new ArrayList<>();
variables.addAll(vars);
Predicate asOfNow = new And(
new Comparison(
new TimeSelector(variables.get(0), TimeSelector.TimeField.TX_FROM),
Comparator.LTE,
now
),
new Comparison(
new TimeSelector(variables.get(0), TimeSelector.TimeField.TX_TO),
Comparator.GTE,
now
)
);
for(int i=1; i<variables.size(); i++){
asOfNow = new And(
asOfNow,
new And(
new Comparison(
new TimeSelector(variables.get(i), TimeSelector.TimeField.TX_FROM),
Comparator.LTE,
now
),
new Comparison(
new TimeSelector(variables.get(i), TimeSelector.TimeField.TX_TO),
Comparator.GTE,
now
)
)
);
}
return asOfNow;
}
}


/**
* Called when we leave an NotExpression.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.s1ck.gdl.model.comparables;

import org.s1ck.gdl.model.comparables.time.TimeSelector;

import java.io.Serializable;

public interface ComparableExpression extends Serializable{
Expand All @@ -24,4 +26,13 @@ public interface ComparableExpression extends Serializable{
* @return variable
*/
public String getVariable();

/**
* Checks whether a certain type of selector (val_from, val_to, tx_from, tx_to) is contained
* @param type the type of selector (val_from, val_to, tx_from, tx_to)
* @return true iff the specified type of selector is contained
*/
boolean containsSelectorType(TimeSelector.TimeField type);


}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.s1ck.gdl.model.comparables;

import org.s1ck.gdl.model.comparables.time.TimeSelector;

/**
* Used to compare elements (by id)
*/
Expand Down Expand Up @@ -44,6 +46,11 @@ public String getVariable() {
return this.variable;
}

@Override
public boolean containsSelectorType(TimeSelector.TimeField type){
return false;
}

@Override
public String toString() {
return variable;
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/org/s1ck/gdl/model/comparables/Literal.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.s1ck.gdl.model.comparables;

import org.s1ck.gdl.model.comparables.time.TimeSelector;

/**
* Represents a literal like String, Integer, ...
*/
Expand Down Expand Up @@ -48,6 +50,11 @@ public String getVariable() {
return null;
}

@Override
public boolean containsSelectorType(TimeSelector.TimeField type){
return false;
}

@Override
public String toString() {
return value.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.s1ck.gdl.model.comparables;

import org.s1ck.gdl.model.comparables.time.TimeSelector;

/**
* Selects a property of a variable
*/
Expand Down Expand Up @@ -54,6 +56,11 @@ public String getVariable() {
return this.variable;
}

@Override
public boolean containsSelectorType(TimeSelector.TimeField type){
return false;
}

@Override
public String toString() {
return variable + "." + propertyName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ public long getUpperBound(){
return res;
}

@Override
public boolean containsSelectorType(TimeSelector.TimeField type){
for(TimePoint p: args){
if(p.containsSelectorType(type)){
return true;
}
}
return false;
}

@Override
protected Predicate unfoldEQ(TimePoint arg){
//MAX(p1...pn) == x <=> exists pi: (pi>=p1 AND pi>=p2...AND pi>=pn) AND (pi==x)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ public long getUpperBound(){
return res;
}

@Override
public boolean containsSelectorType(TimeSelector.TimeField type){
for(TimePoint p: args){
if(p.containsSelectorType(type)){
return true;
}
}
return false;
}

@Override
protected Predicate unfoldEQ(TimePoint arg){
//MIN(p1...pn) == x <=> exists pi: (pi<=p1 AND pi<=p2...AND pi<=pn) AND (pi==x)
Expand Down
Loading

0 comments on commit 25102db

Please sign in to comment.