FQL improvements
This commit is contained in:
@@ -21,7 +21,7 @@ orderByExpression
|
|||||||
|
|
||||||
// regular expressions - NOT regex
|
// regular expressions - NOT regex
|
||||||
regularExpression
|
regularExpression
|
||||||
: (stringExpression | intExpression | booleanExpression | dateExpression) ;
|
: (stringExpression | intExpression | booleanExpression | dateExpression | likeExpression) ;
|
||||||
stringExpression
|
stringExpression
|
||||||
: field=IDENTIFIER operator=STRING_OPERATOR value=STRING_VALUE ;
|
: field=IDENTIFIER operator=STRING_OPERATOR value=STRING_VALUE ;
|
||||||
intExpression
|
intExpression
|
||||||
@@ -32,6 +32,8 @@ booleanExpression
|
|||||||
dateExpression
|
dateExpression
|
||||||
: field=IDENTIFIER operator=STRING_OPERATOR value=DATE_VALUE ;
|
: field=IDENTIFIER operator=STRING_OPERATOR value=DATE_VALUE ;
|
||||||
|
|
||||||
|
likeExpression : field=IDENTIFIER LIKE value=STRING_VALUE ;
|
||||||
|
|
||||||
// BETWEEN expressions
|
// BETWEEN expressions
|
||||||
betweenExpression
|
betweenExpression
|
||||||
: (betweenStringExpression | betweenIntExpression ) ;
|
: (betweenStringExpression | betweenIntExpression ) ;
|
||||||
@@ -70,6 +72,8 @@ fragment Y : ('Y' | 'y') ;
|
|||||||
fragment G : ('G' | 'g') ;
|
fragment G : ('G' | 'g') ;
|
||||||
fragment O : ('O' | 'o') ;
|
fragment O : ('O' | 'o') ;
|
||||||
fragment F : ('F' | 'f') ;
|
fragment F : ('F' | 'f') ;
|
||||||
|
fragment I : ('I' | 'i') ;
|
||||||
|
fragment K : ('K' | 'k') ;
|
||||||
fragment SPACE : ' ' ;
|
fragment SPACE : ' ' ;
|
||||||
|
|
||||||
// Keywords
|
// Keywords
|
||||||
@@ -81,6 +85,7 @@ DESC : D E S C ;
|
|||||||
ASC : A S C ;
|
ASC : A S C ;
|
||||||
TRUE : T R U E ;
|
TRUE : T R U E ;
|
||||||
FALSE : F A L S E ;
|
FALSE : F A L S E ;
|
||||||
|
LIKE : L I K E ;
|
||||||
|
|
||||||
// Constant values
|
// Constant values
|
||||||
CURRENT : C U R R E N T ;
|
CURRENT : C U R R E N T ;
|
||||||
@@ -96,7 +101,7 @@ L_PAREN : '(' ;
|
|||||||
R_PAREN : ')' ;
|
R_PAREN : ')' ;
|
||||||
IDENTIFIER : [a-zA-Z]+ ;
|
IDENTIFIER : [a-zA-Z]+ ;
|
||||||
INT_VALUE : [0-9]+ ;
|
INT_VALUE : [0-9]+ ;
|
||||||
STRING_VALUE : '\'' [a-zA-Z0-9\-/ ]+ '\'' ;
|
STRING_VALUE : '\'' [a-zA-Z0-9\-/.&%@$ ]+ '\'' ;
|
||||||
DATE_VALUE : [0-9-]+ ;
|
DATE_VALUE : [0-9-]+ ;
|
||||||
|
|
||||||
NEWLINE : ('\r'? '\n' | '\r')+ ;
|
NEWLINE : ('\r'? '\n' | '\r')+ ;
|
||||||
|
|||||||
@@ -140,6 +140,16 @@ public class FQLVisitorImpl extends FQLBaseVisitor<Predicate> {
|
|||||||
.apply(fieldMapping, this.froms, this.criteriaBuilder, ctx.value.getText());
|
.apply(fieldMapping, this.froms, this.criteriaBuilder, ctx.value.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Predicate visitLikeExpression(FQLParser.LikeExpressionContext ctx) {
|
||||||
|
final FieldMapping fieldMapping = FieldMapping.findByFieldName(ctx.field.getText());
|
||||||
|
|
||||||
|
fieldMapping.getJoinHandler().apply(this.froms, fieldMapping);
|
||||||
|
|
||||||
|
return fieldMapping.getFieldHandler()
|
||||||
|
.apply(fieldMapping, this.froms, this.criteriaBuilder, ctx.value.getText());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Predicate visitIntExpression(FQLParser.IntExpressionContext ctx) {
|
public Predicate visitIntExpression(FQLParser.IntExpressionContext ctx) {
|
||||||
final FieldMapping fieldMapping = FieldMapping.findByFieldName(ctx.field.getText());
|
final FieldMapping fieldMapping = FieldMapping.findByFieldName(ctx.field.getText());
|
||||||
|
|||||||
@@ -32,7 +32,10 @@ public enum FieldMapping {
|
|||||||
TAX_RELEVANT("taxRelevant", Transaction_.TAX_RELEVANT, Transaction.class, NoopJoinHandler.class,
|
TAX_RELEVANT("taxRelevant", Transaction_.TAX_RELEVANT, Transaction.class, NoopJoinHandler.class,
|
||||||
JoinKey.of(Transaction.class), null, BooleanHandler.class),
|
JoinKey.of(Transaction.class), null, BooleanHandler.class),
|
||||||
|
|
||||||
HAS_FILE("hasFile", File_.ID, File.class, FileJoinHandler.class, JoinKey.of(File.class), null, NotNullSyntheticHandler.class);
|
HAS_FILE("hasFile", File_.ID, File.class, FileJoinHandler.class, JoinKey.of(File.class), null, NotNullSyntheticHandler.class),
|
||||||
|
|
||||||
|
DESCRIPTION("description", Transaction_.DESCRIPTION, Transaction.class, NoopJoinHandler.class, JoinKey.of(Transaction.class),
|
||||||
|
null, LikeHandler.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the field as used in FQL
|
* The name of the field as used in FQL
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
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.util.Map;
|
||||||
|
|
||||||
|
public class LikeHandler implements FieldHandler<String> {
|
||||||
|
@Override
|
||||||
|
public Predicate apply(FieldMapping fieldMapping, Map<JoinKey, From<?, ?>> froms, CriteriaBuilder criteriaBuilder, String value) {
|
||||||
|
return criteriaBuilder
|
||||||
|
.like(criteriaBuilder.lower(froms.get(fieldMapping.getJoinKey()).get(fieldMapping.getAttributeName())), removeQuotes(value).toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String removeQuotes(String value) {
|
||||||
|
return value.replaceAll("'", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -140,6 +140,7 @@ financer.search-transactions.show-query-options.date=date\: the date of the tran
|
|||||||
financer.search-transactions.show-query-options.recurring=recurring\: whether the transaction has been created from a recurring transaction
|
financer.search-transactions.show-query-options.recurring=recurring\: whether the transaction has been created from a recurring transaction
|
||||||
financer.search-transactions.show-query-options.taxRelevant=taxRelevant\: whether the transaction is relevant for tax declaration
|
financer.search-transactions.show-query-options.taxRelevant=taxRelevant\: whether the transaction is relevant for tax declaration
|
||||||
financer.search-transactions.show-query-options.hasFile=hasFile\: whether the transaction has a file linked
|
financer.search-transactions.show-query-options.hasFile=hasFile\: whether the transaction has a file linked
|
||||||
|
financer.search-transactions.show-query-options.description=description\: the description of the transaction
|
||||||
financer.search-transactions.show-query-options.period=period\: the period the transaction is assigned to
|
financer.search-transactions.show-query-options.period=period\: the period the transaction is assigned to
|
||||||
financer.search-transactions.show-query-options.period.CURRENT=CURRENT\: denotes the current expense period
|
financer.search-transactions.show-query-options.period.CURRENT=CURRENT\: denotes the current expense period
|
||||||
financer.search-transactions.show-query-options.period.LAST=LAST\: denotes the last expense period
|
financer.search-transactions.show-query-options.period.LAST=LAST\: denotes the last expense period
|
||||||
@@ -153,6 +154,7 @@ financer.search-transactions.show-query-options.strings=Strings enclosed in sing
|
|||||||
financer.search-transactions.show-query-options.case=Case-insensitive
|
financer.search-transactions.show-query-options.case=Case-insensitive
|
||||||
financer.search-transactions.show-query-options.operators=Possible operators =, >, >=, <, <=, !=
|
financer.search-transactions.show-query-options.operators=Possible operators =, >, >=, <, <=, !=
|
||||||
financer.search-transactions.show-query-options.ordering=Ordering for a single field ASC, DESC via ORDER BY
|
financer.search-transactions.show-query-options.ordering=Ordering for a single field ASC, DESC via ORDER BY
|
||||||
|
financer.search-transactions.show-query-options.like=Fuzzy search with LIKE, % as wildcard (only applicable for field description)
|
||||||
|
|
||||||
financer.chart-select.title=Select a chart to generate
|
financer.chart-select.title=Select a chart to generate
|
||||||
financer.chart-select.submit=Select
|
financer.chart-select.submit=Select
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ financer.search-transactions.show-query-options.date=date\: das Datum der Buchun
|
|||||||
financer.search-transactions.show-query-options.recurring=recurring\: ob die Buchung durch eine wiederkehrende Buchung erzeugt wurde
|
financer.search-transactions.show-query-options.recurring=recurring\: ob die Buchung durch eine wiederkehrende Buchung erzeugt wurde
|
||||||
financer.search-transactions.show-query-options.taxRelevant=taxRelevant\: ob die Buchung als steuerrelevant markiert wurde
|
financer.search-transactions.show-query-options.taxRelevant=taxRelevant\: ob die Buchung als steuerrelevant markiert wurde
|
||||||
financer.search-transactions.show-query-options.hasFile=hasFile\: ob eine Datei der Buchung zugeordnet ist
|
financer.search-transactions.show-query-options.hasFile=hasFile\: ob eine Datei der Buchung zugeordnet ist
|
||||||
|
financer.search-transactions.show-query-options.description=description\: die Beschreibung der Buchung
|
||||||
financer.search-transactions.show-query-options.period=period\: die Periode der Buchung
|
financer.search-transactions.show-query-options.period=period\: die Periode der Buchung
|
||||||
financer.search-transactions.show-query-options.period.CURRENT=CURRENT\: bezeichnet die aktuelle Ausgabenperiode
|
financer.search-transactions.show-query-options.period.CURRENT=CURRENT\: bezeichnet die aktuelle Ausgabenperiode
|
||||||
financer.search-transactions.show-query-options.period.LAST=LAST\: bezeichnet die letzte Ausgabenperiode
|
financer.search-transactions.show-query-options.period.LAST=LAST\: bezeichnet die letzte Ausgabenperiode
|
||||||
@@ -153,6 +154,7 @@ financer.search-transactions.show-query-options.strings=Zeichenketten werden dur
|
|||||||
financer.search-transactions.show-query-options.case=Unterscheidung von Gro\u1E9E- und Kleinschreibung
|
financer.search-transactions.show-query-options.case=Unterscheidung von Gro\u1E9E- und Kleinschreibung
|
||||||
financer.search-transactions.show-query-options.operators=Unterst\u00FCtzte Operatoren =, >, >=, <, <=, !=
|
financer.search-transactions.show-query-options.operators=Unterst\u00FCtzte Operatoren =, >, >=, <, <=, !=
|
||||||
financer.search-transactions.show-query-options.ordering=Sortierung \u00FCber ein einziges Feld mit ASC (aufsteigend), DESC (absteigend) via ORDER BY
|
financer.search-transactions.show-query-options.ordering=Sortierung \u00FCber ein einziges Feld mit ASC (aufsteigend), DESC (absteigend) via ORDER BY
|
||||||
|
financer.search-transactions.show-query-options.like=Platzhaltersuche mit LIKE, % als Platzhalter (nur anwendbar bei Feld description)
|
||||||
|
|
||||||
financer.chart-select.title=Ein Diagramm zum Erzeugen ausw\u00E4hlen
|
financer.chart-select.title=Ein Diagramm zum Erzeugen ausw\u00E4hlen
|
||||||
financer.chart-select.submit=Ausw\u00E4hlen
|
financer.chart-select.submit=Ausw\u00E4hlen
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
v33 -> v34:
|
||||||
|
- Fix a bug in the parsing of FQL
|
||||||
|
- Add the transaction description field to the FQL search
|
||||||
|
- Add LIKE support to the FQL search
|
||||||
|
|
||||||
v32 -> v33:
|
v32 -> v33:
|
||||||
- Introduce Holiday/Weekend Type SKIP to skip an occurrence of a recurring transaction once, if the due date is either a
|
- Introduce Holiday/Weekend Type SKIP to skip an occurrence of a recurring transaction once, if the due date is either a
|
||||||
holiday or a weekend day
|
holiday or a weekend day
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
<li th:text="#{financer.search-transactions.show-query-options.recurring}" />
|
<li th:text="#{financer.search-transactions.show-query-options.recurring}" />
|
||||||
<li th:text="#{financer.search-transactions.show-query-options.taxRelevant}" />
|
<li th:text="#{financer.search-transactions.show-query-options.taxRelevant}" />
|
||||||
<li th:text="#{financer.search-transactions.show-query-options.hasFile}" />
|
<li th:text="#{financer.search-transactions.show-query-options.hasFile}" />
|
||||||
|
<li th:text="#{financer.search-transactions.show-query-options.description}" />
|
||||||
<li><span th:text="#{financer.search-transactions.show-query-options.period}" />
|
<li><span th:text="#{financer.search-transactions.show-query-options.period}" />
|
||||||
<ul>
|
<ul>
|
||||||
<li th:text="#{financer.search-transactions.show-query-options.period.CURRENT}" />
|
<li th:text="#{financer.search-transactions.show-query-options.period.CURRENT}" />
|
||||||
@@ -52,6 +53,7 @@
|
|||||||
<li th:text="#{financer.search-transactions.show-query-options.case}" />
|
<li th:text="#{financer.search-transactions.show-query-options.case}" />
|
||||||
<li th:text="#{financer.search-transactions.show-query-options.operators}" />
|
<li th:text="#{financer.search-transactions.show-query-options.operators}" />
|
||||||
<li th:text="#{financer.search-transactions.show-query-options.ordering}" />
|
<li th:text="#{financer.search-transactions.show-query-options.ordering}" />
|
||||||
|
<li th:text="#{financer.search-transactions.show-query-options.like}" />
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user