#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:
2021-03-04 01:04:07 +01:00
parent e4f21f25e8
commit 8dd3d9141c
8 changed files with 107 additions and 9 deletions

View File

@@ -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;

View File

@@ -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());

View File

@@ -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);
}
}

View File

@@ -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) {