#12 FQL: Add BETWEEN for date
- Add BETWEEN for date - Add support for other operators than = for date - Document BETWEEN in the query options detail panel
This commit is contained in:
@@ -30,7 +30,7 @@ intExpression
|
||||
booleanExpression
|
||||
: field=IDENTIFIER operator=STRING_OPERATOR value=(TRUE | FALSE) ;
|
||||
dateExpression
|
||||
: field=IDENTIFIER operator=STRING_OPERATOR value=DATE_VALUE ;
|
||||
: field=IDENTIFIER operator=(INT_OPERATOR | STRING_OPERATOR) value=DATE_VALUE ;
|
||||
|
||||
// special expressions
|
||||
specialExpression
|
||||
@@ -47,11 +47,13 @@ inStringExpression
|
||||
|
||||
// BETWEEN expressions
|
||||
betweenExpression
|
||||
: (betweenStringExpression | betweenIntExpression ) ;
|
||||
: (betweenStringExpression | betweenIntExpression | betweenDateExpression ) ;
|
||||
betweenStringExpression
|
||||
: field=IDENTIFIER BETWEEN left=STRING_VALUE AND right=STRING_VALUE ;
|
||||
betweenIntExpression
|
||||
: field=IDENTIFIER BETWEEN left=INT_VALUE AND right=INT_VALUE ;
|
||||
betweenDateExpression
|
||||
: field=IDENTIFIER BETWEEN left=DATE_VALUE AND right=DATE_VALUE ;
|
||||
|
||||
// period expressions
|
||||
periodExpression
|
||||
@@ -121,7 +123,7 @@ R_PAREN : ')' ;
|
||||
IDENTIFIER : [a-zA-Z]+ ;
|
||||
INT_VALUE : [0-9]+ ;
|
||||
STRING_VALUE : '\'' [a-zA-Z0-9\-/.&%@$ ]+ '\'' ;
|
||||
DATE_VALUE : [0-9-]+ ;
|
||||
DATE_VALUE : [0-9][0-9][0-9][0-9][-][0-9][0-9][-][0-9][0-9] ; // ANTLR does not support regex quantifiers
|
||||
|
||||
NEWLINE : ('\r'? '\n' | '\r')+ ;
|
||||
WHITESPACE : ' ' -> skip;
|
||||
@@ -188,11 +188,13 @@ public class FQLVisitorImpl extends FQLBaseVisitor<Predicate> {
|
||||
@Override
|
||||
public Predicate visitDateExpression(FQLParser.DateExpressionContext ctx) {
|
||||
final FieldMapping fieldMapping = FieldMapping.findByFieldName(ctx.field.getText());
|
||||
final DateHandler.DateHandlerParameterContainer con = DateHandler.DateHandlerParameterContainer
|
||||
.of(ctx.operator.getText(), ctx.value.getText());
|
||||
|
||||
fieldMapping.getJoinHandler().apply(this.froms, fieldMapping);
|
||||
|
||||
return fieldMapping.getFieldHandler()
|
||||
.apply(fieldMapping, this.froms, this.criteriaBuilder, ctx.value.getText());
|
||||
.apply(fieldMapping, this.froms, this.criteriaBuilder, con);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -213,6 +215,19 @@ public class FQLVisitorImpl extends FQLBaseVisitor<Predicate> {
|
||||
return new BetweenStringHandler().apply(fieldMapping, this.froms, this.criteriaBuilder, con);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate visitBetweenDateExpression(FQLParser.BetweenDateExpressionContext ctx) {
|
||||
final FieldMapping fieldMapping = FieldMapping.findByFieldName(ctx.field.getText());
|
||||
|
||||
final BetweenDateHandler.BetweenDateHandlerParameterContainer con = BetweenDateHandler.BetweenDateHandlerParameterContainer
|
||||
.of(ctx.left.getText(), ctx.right.getText());
|
||||
|
||||
fieldMapping.getJoinHandler().apply(this.froms, fieldMapping);
|
||||
|
||||
// Overwrite the actual field handler of the field
|
||||
return new BetweenDateHandler().apply(fieldMapping, this.froms, this.criteriaBuilder, con);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate visitBetweenIntExpression(FQLParser.BetweenIntExpressionContext ctx) {
|
||||
final FieldMapping fieldMapping = FieldMapping.findByFieldName(ctx.field.getText());
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package de.financer.fql.field_handler;
|
||||
|
||||
import de.financer.fql.FieldMapping;
|
||||
import de.financer.fql.join_handler.JoinKey;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.From;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Map;
|
||||
|
||||
public class BetweenDateHandler implements FieldHandler<BetweenDateHandler.BetweenDateHandlerParameterContainer> {
|
||||
public static class BetweenDateHandlerParameterContainer {
|
||||
private String left;
|
||||
private String right;
|
||||
|
||||
public static BetweenDateHandlerParameterContainer of(String left, String right) {
|
||||
final BetweenDateHandlerParameterContainer con = new BetweenDateHandlerParameterContainer();
|
||||
|
||||
con.left = left;
|
||||
con.right = right;
|
||||
|
||||
return con;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate apply(FieldMapping fieldMapping, Map<JoinKey, From<?, ?>> froms, CriteriaBuilder criteriaBuilder, BetweenDateHandlerParameterContainer con) {
|
||||
return criteriaBuilder
|
||||
.between(froms.get(fieldMapping.getJoinKey()).get(fieldMapping.getAttributeName()),
|
||||
parseDate(con.left),
|
||||
parseDate(con.right));
|
||||
}
|
||||
|
||||
private LocalDate parseDate(String value) {
|
||||
return LocalDate.parse(value);
|
||||
}
|
||||
}
|
||||
@@ -5,14 +5,53 @@ import de.financer.fql.join_handler.JoinKey;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.From;
|
||||
import javax.persistence.criteria.Path;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Map;
|
||||
|
||||
public class DateHandler implements FieldHandler<String> {
|
||||
public class DateHandler implements FieldHandler<DateHandler.DateHandlerParameterContainer> {
|
||||
public static class DateHandlerParameterContainer {
|
||||
private String operator;
|
||||
private String value;
|
||||
|
||||
public static DateHandler.DateHandlerParameterContainer of(String operator, String value) {
|
||||
DateHandler.DateHandlerParameterContainer con = new DateHandler.DateHandlerParameterContainer();
|
||||
|
||||
con.operator = operator;
|
||||
con.value = value;
|
||||
|
||||
return con;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate apply(FieldMapping fieldMapping, Map<JoinKey, From<?, ?>> froms, CriteriaBuilder criteriaBuilder, String value) {
|
||||
return criteriaBuilder.equal(froms.get(fieldMapping.getJoinKey()).get(fieldMapping.getAttributeName()), parseDate(value));
|
||||
public Predicate apply(FieldMapping fieldMapping, Map<JoinKey, From<?, ?>> froms, CriteriaBuilder criteriaBuilder, DateHandlerParameterContainer con) {
|
||||
final Path<LocalDate> path = froms.get(fieldMapping.getJoinKey()).get(fieldMapping.getAttributeName());
|
||||
Predicate retVal = null;
|
||||
|
||||
switch (con.operator) {
|
||||
case "=":
|
||||
retVal = criteriaBuilder.equal(path, parseDate(con.value));
|
||||
break;
|
||||
case ">":
|
||||
retVal = criteriaBuilder.greaterThan(path, parseDate(con.value));
|
||||
break;
|
||||
case "<":
|
||||
retVal = criteriaBuilder.lessThan(path, parseDate(con.value));
|
||||
break;
|
||||
case ">=":
|
||||
retVal = criteriaBuilder.greaterThanOrEqualTo(path, parseDate(con.value));
|
||||
break;
|
||||
case "<=":
|
||||
retVal = criteriaBuilder.lessThanOrEqualTo(path, parseDate(con.value));
|
||||
break;
|
||||
case "!=":
|
||||
retVal = criteriaBuilder.notEqual(path, parseDate(con.value));
|
||||
break;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private LocalDate parseDate(String value) {
|
||||
|
||||
Reference in New Issue
Block a user