You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've used the QueryDSL as AST and serializer for RFC-2254. Syntax is a bit unconventional when it comes to to handling parenthesis. It was easier for be to handle them as part of the template without help from QueryDSL. The next issue was AND/OR being not always binary due to usage of prefix notation instead of infix. I could have treated them as such but then the serializer would have created such a mess with the parenthesis here and there that already hard to read syntax would have become quite unreadable. I didn't want to fill my AST with template expressions because the AND/OR operators can still be used in predicate operations supporting arbitrary number of arguments.
Since the dialect doesn't have any separators between indices now that parenthesis are handled by each template, I saw that it's quite easy add range support to templates now that there is operator support already build in to the regular expressions.
I though that args.subList would be the logical component around ranges and I just used - sign to signal that I actually want args.size()-index2. As result I got a syntax that I used below without any major changes.
PS. Only thing that I miss is a similar support for COALESCE/CONCATENATE style SQL syntax and why not RelationalFunctionCall that has to manually express it's repetition. I used Parboiled as parser and came across GramExp that could be used as basis to add support for repetition in EBNF like notation.
TemplateFactory
@@ -216,6 +216,22 @@
*/
public static final class Operation extends Element {
+ static final Operator RANGE = new Operator() {++ private static final long serialVersionUID = 5137034101957917967L;++ @Override+ public String name() {+ return this.getClass().getSimpleName();+ }++ @Override+ public Class<?> getType() {+ return Object.class;+ }++ };+
private static final long serialVersionUID = 1400801176778801584L;
private final int index1, index2;
@@ -233,34 +249,56 @@
@Override
public Object convert(List<?> args) {
- Object arg1 = args.get(index1);- Object arg2 = args.get(index2);- if (isNumber(arg1) && isNumber(arg2)) {- return MathUtils.result(asNumber(arg1), asNumber(arg2), operator);+ if (RANGE.equals(operator)) {+ int fromIndex = index1;+ if (index1 < 0) {+ fromIndex += args.size();+ }+ int toIndex = index2 + 1;+ if (index2 < 0) {+ toIndex += args.size();+ }+ StringBuilder stringBuilder = new StringBuilder((toIndex - fromIndex)*3);+ ImmutableList.Builder<Element> elements = ImmutableList.builder();+ for (int i = fromIndex; i < toIndex; i++) {+ Element element = asString ? new AsString(i) : new ByIndex(i);+ elements.add(element);+ stringBuilder.append('{');+ stringBuilder.append(element);+ stringBuilder.append('}');+ }+ Template template = new Template(stringBuilder.toString(), elements.build());+ return ExpressionUtils.template(Object.class, template, args.subList(fromIndex, toIndex));
} else {
- Expression<?> expr1 = asExpression(arg1);- Expression<?> expr2 = asExpression(arg2);+ Object arg1 = args.get(index1);+ Object arg2 = args.get(index2);+ if (isNumber(arg1) && isNumber(arg2)) {+ return MathUtils.result(asNumber(arg1), asNumber(arg2), operator);+ } else {+ Expression<?> expr1 = asExpression(arg1);+ Expression<?> expr2 = asExpression(arg2);- if (arg2 instanceof Number) {- if (CONVERTIBLES.contains(operator) && expr1 instanceof com.querydsl.core.types.Operation) {- com.querydsl.core.types.Operation operation = (com.querydsl.core.types.Operation) expr1;- if (CONVERTIBLES.contains(operation.getOperator()) && operation.getArg(1) instanceof Constant) {- Number num1 = ((Constant<Number>) operation.getArg(1)).getConstant();- Number num2;- if (operator == operation.getOperator()) {- num2 = MathUtils.result(num1, (Number) arg2, Ops.ADD);- } else if (operator == Ops.ADD) {- num2 = MathUtils.result((Number) arg2, num1, Ops.SUB);- } else {- num2 = MathUtils.result(num1, (Number) arg2, Ops.SUB);+ if (arg2 instanceof Number) {+ if (CONVERTIBLES.contains(operator) && expr1 instanceof com.querydsl.core.types.Operation) {+ com.querydsl.core.types.Operation operation = (com.querydsl.core.types.Operation) expr1;+ if (CONVERTIBLES.contains(operation.getOperator()) && operation.getArg(1) instanceof Constant) {+ Number num1 = ((Constant<Number>) operation.getArg(1)).getConstant();+ Number num2;+ if (operator == operation.getOperator()) {+ num2 = MathUtils.result(num1, (Number) arg2, Ops.ADD);+ } else if (operator == Ops.ADD) {+ num2 = MathUtils.result((Number) arg2, num1, Ops.SUB);+ } else {+ num2 = MathUtils.result(num1, (Number) arg2, Ops.SUB);+ }+ return ExpressionUtils.operation(expr1.getType(), operator,+ operation.getArg(0), Expressions.constant(num2));
}
- return ExpressionUtils.operation(expr1.getType(), operator,- operation.getArg(0), Expressions.constant(num2));
}
}
- }- return ExpressionUtils.operation(expr1.getType(), operator, expr1, expr2);+ return ExpressionUtils.operation(expr1.getType(), operator, expr1, expr2);+ }
}
}
TemplateFactory
@@ -33,8 +33,8 @@
*/
public class TemplateFactory {
- private static final Map<String, Operator> OPERATORS = ImmutableMap.<String, Operator>of(- "+", Ops.ADD, "-", Ops.SUB, "*", Ops.MULT, "/", Ops.DIV);+ static final Map<String, Operator> OPERATORS = ImmutableMap.<String, Operator>of(+ "+", Ops.ADD, "-", Ops.SUB, "*", Ops.MULT, "/", Ops.DIV, "..", Template.Operation.RANGE);
public static final TemplateFactory DEFAULT = new TemplateFactory('\\');
@@ -42,8 +42,8 @@
private static final Pattern elementPattern = Pattern.compile("\\{"
+ "(%?%?)"
- + "(\\d+)"- + "(?:([+-/*])(?:(\\d+)|'(-?\\d+(?:\\.\\d+)?)'))?"+ + "([-]?\\d+)"+ + "(?:([+-/*]|\\.\\.)(?:([-]?\\d+)|'(-?\\d+(?:\\.\\d+)?)'))?"
+ "([slu%]?%?)"
+ "\\}");
The text was updated successfully, but these errors were encountered:
I've used the QueryDSL as AST and serializer for RFC-2254. Syntax is a bit unconventional when it comes to to handling parenthesis. It was easier for be to handle them as part of the template without help from QueryDSL. The next issue was AND/OR being not always binary due to usage of prefix notation instead of infix. I could have treated them as such but then the serializer would have created such a mess with the parenthesis here and there that already hard to read syntax would have become quite unreadable. I didn't want to fill my AST with template expressions because the AND/OR operators can still be used in predicate operations supporting arbitrary number of arguments.
Since the dialect doesn't have any separators between indices now that parenthesis are handled by each template, I saw that it's quite easy add range support to templates now that there is operator support already build in to the regular expressions.
I though that
args.subList
would be the logical component around ranges and I just used-
sign to signal that I actually wantargs.size()-index2
. As result I got a syntax that I used below without any major changes.PS. Only thing that I miss is a similar support for COALESCE/CONCATENATE style SQL syntax and why not
RelationalFunctionCall
that has to manually express it's repetition. I used Parboiled as parser and came across GramExp that could be used as basis to add support for repetition in EBNF like notation.TemplateFactory
TemplateFactory
The text was updated successfully, but these errors were encountered: