diff --git a/src/main/java/com/aerospike/dsl/DSLParser.java b/src/main/java/com/aerospike/dsl/DSLParser.java
new file mode 100644
index 0000000..a6d70ae
--- /dev/null
+++ b/src/main/java/com/aerospike/dsl/DSLParser.java
@@ -0,0 +1,111 @@
+package com.aerospike.dsl;
+
+import com.aerospike.client.exp.Expression;
+import com.aerospike.client.query.Filter;
+import com.aerospike.dsl.exception.AerospikeDSLException;
+
+import java.util.List;
+
+/**
+ * Contains API to convert dot separated String path into an Aerospike filter -
+ * a functional language for applying predicates to bin data and record metadata.
+ *
+ * Such filters are used in different areas of Aerospike Server functionality including the following:
+ *
+ * - filtering queries (acting as the WHERE clause),
+ * - filtering batch operations,
+ * - conditionally executing single key operations (get, put, delete, operate),
+ * - defining secondary indexes.
+ *
+ */
+public interface DSLParser {
+
+ /**
+ * Parse String DSL path into Aerospike filter Expression.
+ *
+ * Examples:
+ *
+ *
+ * | $.binName | Bin “binName” |
+ *
+ *
+ * | a | Map key “a” |
+ *
+ *
+ * | '1' | Map key (String) “1” |
+ *
+ *
+ * | 1 | Map key 1 |
+ *
+ *
+ * | {1} | Map index 1 |
+ *
+ *
+ * | {=1} | Map value (int) 1 |
+ *
+ *
+ * | {=bb} | Map value “bb” |
+ *
+ *
+ * | {='1'} | Map value (String) “1” |
+ *
+ * {#1} | Map rank 1 |
+ *
+ *
+ * | [1] | List index 1 |
+ *
+ *
+ * | [=1] | List value 1 |
+ *
+ *
+ * | [#1] | List rank 1 |
+ *
+ *
+ *
+ *
+ * | $.binName | [binName] |
+ *
+ *
+ * | $.mapBinName.k | [mapBinName -> mapKey("a")] |
+ *
+ *
+ * | $.mapBinName.a.aa.aaa | [mapBinName -> mapKey("a") -> mapKey("aa") -> mapKey("aaa")] |
+ *
+ *
+ * | $.mapBinName.a.55 | [mapBinName -> mapKey("a") -> mapKey(55)] |
+ *
+ *
+ * | $.listBinName.[1].aa | [listBinName -> listIndex(1) -> mapKey("aa")] |
+ *
+ *
+ * | $.mapBinName.ab.cd.[-1].'10' | [mapBinName -> mapKey("ab") -> mapKey("cd") -> listIndex(-1) ->
+ * mapKey("10")] |
+ *
+ *
+ * @param input String consisting of dot separated elements, typically bin name and optional context
+ * @return Expression object
+ * @throws AerospikeDSLException in case of unsupported DSL String or invalid syntax
+ */
+ Expression parseExpression(String input);
+
+ /**
+ * Parse String DSL path into Aerospike secondary index Filter.
+ *
+ * Examples:
+ *
+ *
+ * | $.intBin1 == 10 | Filter.equal("intBin1", 10) |
+ *
+ *
+ * | $.intBin1 > 10 | Filter.range("intBin1", 11, Long.MAX_VALUE) |
+ *
+ *
+ * | $.stringBin1 == 'text' | Filter.equal("stringBin1", "text") |
+ *
+ *
+ * @param input String consisting of dot separated elements, typically bin name and value
+ * @return List of Filter objects
+ * @throws AerospikeDSLException in case of unsupported DSL String or invalid syntax
+ */
+ List parseFilters(String input);
+}
diff --git a/src/main/java/com/aerospike/dsl/ConditionTranslator.java b/src/main/java/com/aerospike/dsl/DSLParserImpl.java
similarity index 55%
rename from src/main/java/com/aerospike/dsl/ConditionTranslator.java
rename to src/main/java/com/aerospike/dsl/DSLParserImpl.java
index 4f26b7c..8a9287b 100644
--- a/src/main/java/com/aerospike/dsl/ConditionTranslator.java
+++ b/src/main/java/com/aerospike/dsl/DSLParserImpl.java
@@ -2,19 +2,22 @@
import com.aerospike.client.exp.Exp;
import com.aerospike.client.exp.Expression;
+import com.aerospike.client.query.Filter;
import com.aerospike.dsl.annotation.Beta;
import com.aerospike.dsl.exception.AerospikeDSLException;
import com.aerospike.dsl.model.AbstractPart;
-import lombok.experimental.UtilityClass;
+import com.aerospike.dsl.visitor.ExpressionConditionVisitor;
+import com.aerospike.dsl.visitor.FilterConditionVisitor;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
-@UtilityClass
-public class ConditionTranslator {
+import java.util.List;
+
+public class DSLParserImpl implements DSLParser {
@Beta
- public static Expression translate(String input) {
+ public Expression parseExpression(String input) {
ConditionLexer lexer = new ConditionLexer(CharStreams.fromString(input));
ConditionParser parser = new ConditionParser(new CommonTokenStream(lexer));
ParseTree tree = parser.parse();
@@ -29,4 +32,19 @@ public static Expression translate(String input) {
Exp expResult = abstractPart.getExp();
return Exp.build(expResult);
}
+
+ @Beta
+ public List parseFilters(String input) {
+ ConditionLexer lexer = new ConditionLexer(CharStreams.fromString(input));
+ ConditionParser parser = new ConditionParser(new CommonTokenStream(lexer));
+ ParseTree tree = parser.parse();
+
+ FilterConditionVisitor visitor = new FilterConditionVisitor();
+ AbstractPart abstractPart = visitor.visit(tree);
+
+ if (abstractPart == null) {
+ throw new AerospikeDSLException("Could not parse given input, wrong syntax");
+ }
+ return abstractPart.getSIndexFilter().getFilters();
+ }
}
diff --git a/src/main/java/com/aerospike/dsl/model/AbstractPart.java b/src/main/java/com/aerospike/dsl/model/AbstractPart.java
index 8d7d71d..2499c79 100644
--- a/src/main/java/com/aerospike/dsl/model/AbstractPart.java
+++ b/src/main/java/com/aerospike/dsl/model/AbstractPart.java
@@ -11,6 +11,7 @@ public abstract class AbstractPart {
protected Exp.Type expType;
protected PartType partType;
protected Exp exp;
+ protected SIndexFilter sIndexFilter;
protected AbstractPart(PartType partType) {
this.partType = partType;
@@ -22,6 +23,11 @@ protected AbstractPart(PartType partType, Exp exp) {
this.exp = exp;
}
+ protected AbstractPart(PartType partType, SIndexFilter filters) {
+ this.partType = partType;
+ this.sIndexFilter = filters;
+ }
+
public enum PartType {
INT_OPERAND,
FLOAT_OPERAND,
diff --git a/src/main/java/com/aerospike/dsl/model/BinPart.java b/src/main/java/com/aerospike/dsl/model/BinPart.java
index c037bb7..98098ac 100644
--- a/src/main/java/com/aerospike/dsl/model/BinPart.java
+++ b/src/main/java/com/aerospike/dsl/model/BinPart.java
@@ -9,7 +9,7 @@ public class BinPart extends Expr {
private final String binName;
public BinPart(String binName) {
- super(null); // Exp unknown
+ super((Exp) null); // Exp unknown
this.binName = binName;
this.partType = PartType.BIN_PART;
this.expType = null; // Exp type unknown
diff --git a/src/main/java/com/aerospike/dsl/model/Expr.java b/src/main/java/com/aerospike/dsl/model/Expr.java
index 116a52a..ce68eeb 100644
--- a/src/main/java/com/aerospike/dsl/model/Expr.java
+++ b/src/main/java/com/aerospike/dsl/model/Expr.java
@@ -6,7 +6,29 @@
@Getter
public class Expr extends AbstractPart {
+ protected AbstractPart left;
+ protected AbstractPart right;
+ private ExprPartsOperation operationType;
+
public Expr(Exp exp) {
super(PartType.EXPR, exp);
}
+
+ public Expr(SIndexFilter filter) {
+ super(PartType.EXPR, filter);
+ }
+
+ public Expr(AbstractPart left, AbstractPart right, ExprPartsOperation operationType) {
+ super(PartType.EXPR);
+ this.left = left;
+ this.right = right;
+ this.operationType = operationType;
+ }
+
+ public enum ExprPartsOperation {
+ ADD,
+ SUB,
+ DIV,
+ MUL
+ }
}
diff --git a/src/main/java/com/aerospike/dsl/model/SIndexFilter.java b/src/main/java/com/aerospike/dsl/model/SIndexFilter.java
new file mode 100644
index 0000000..54a9c15
--- /dev/null
+++ b/src/main/java/com/aerospike/dsl/model/SIndexFilter.java
@@ -0,0 +1,22 @@
+package com.aerospike.dsl.model;
+
+import com.aerospike.client.query.Filter;
+import lombok.Getter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class SIndexFilter {
+
+ @Getter
+ protected final List filters = new ArrayList<>();
+
+ public SIndexFilter(Filter filter) {
+ filters.add(filter);
+ }
+
+ public SIndexFilter(Collection filters) {
+ this.filters.addAll(filters);
+ }
+}
diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListRankRangeRelative.java b/src/main/java/com/aerospike/dsl/model/cdt/list/ListRankRangeRelative.java
index 1d603a5..cad2325 100644
--- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListRankRangeRelative.java
+++ b/src/main/java/com/aerospike/dsl/model/cdt/list/ListRankRangeRelative.java
@@ -7,8 +7,8 @@
import com.aerospike.dsl.ConditionParser;
import com.aerospike.dsl.exception.AerospikeDSLException;
import com.aerospike.dsl.model.BasePath;
-import com.aerospike.dsl.util.ParsingUtils;
+import static com.aerospike.dsl.util.ParsingUtils.unquote;
import static com.aerospike.dsl.util.ParsingUtils.subtractNullable;
public class ListRankRangeRelative extends ListPart {
@@ -51,7 +51,7 @@ public static ListRankRangeRelative from(ConditionParser.ListRankRangeRelativeCo
} else if (valueIdentifierContext.NAME_IDENTIFIER() != null) {
relativeValue = valueIdentifierContext.NAME_IDENTIFIER().getText();
} else if (valueIdentifierContext.QUOTED_STRING() != null) {
- relativeValue = ParsingUtils.getWithoutQuotes(valueIdentifierContext.QUOTED_STRING().getText());
+ relativeValue = unquote(valueIdentifierContext.QUOTED_STRING().getText());
}
}
diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListValue.java b/src/main/java/com/aerospike/dsl/model/cdt/list/ListValue.java
index ac3f165..580ec96 100644
--- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListValue.java
+++ b/src/main/java/com/aerospike/dsl/model/cdt/list/ListValue.java
@@ -6,7 +6,8 @@
import com.aerospike.client.exp.ListExp;
import com.aerospike.dsl.ConditionParser;
import com.aerospike.dsl.model.BasePath;
-import com.aerospike.dsl.util.ParsingUtils;
+
+import static com.aerospike.dsl.util.ParsingUtils.unquote;
public class ListValue extends ListPart {
private final Object value;
@@ -21,7 +22,7 @@ public static ListValue from(ConditionParser.ListValueContext ctx) {
if (ctx.valueIdentifier().NAME_IDENTIFIER() != null) {
listValue = ctx.valueIdentifier().NAME_IDENTIFIER().getText();
} else if (ctx.valueIdentifier().QUOTED_STRING() != null) {
- listValue = ParsingUtils.getWithoutQuotes(ctx.valueIdentifier().QUOTED_STRING().getText());
+ listValue = unquote(ctx.valueIdentifier().QUOTED_STRING().getText());
} else if (ctx.valueIdentifier().INT() != null) {
listValue = Integer.parseInt(ctx.valueIdentifier().INT().getText());
}
diff --git a/src/main/java/com/aerospike/dsl/model/cdt/list/ListValueList.java b/src/main/java/com/aerospike/dsl/model/cdt/list/ListValueList.java
index 8cf5926..de762e4 100644
--- a/src/main/java/com/aerospike/dsl/model/cdt/list/ListValueList.java
+++ b/src/main/java/com/aerospike/dsl/model/cdt/list/ListValueList.java
@@ -10,7 +10,7 @@
import java.util.List;
-import static com.aerospike.dsl.util.ParsingUtils.getWithoutQuotes;
+import static com.aerospike.dsl.util.ParsingUtils.unquote;
public class ListValueList extends ListPart {
private final boolean inverted;
@@ -36,7 +36,7 @@ public static ListValueList from(ConditionParser.ListValueListContext ctx) {
if (listValue.NAME_IDENTIFIER() != null) {
return listValue.NAME_IDENTIFIER().getText();
} else if (listValue.QUOTED_STRING() != null) {
- return getWithoutQuotes(listValue.QUOTED_STRING().getText());
+ return unquote(listValue.QUOTED_STRING().getText());
}
return Integer.parseInt(listValue.INT().getText());
}
diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapIndexRangeRelative.java b/src/main/java/com/aerospike/dsl/model/cdt/map/MapIndexRangeRelative.java
index 9efcee1..e0fc6c6 100644
--- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapIndexRangeRelative.java
+++ b/src/main/java/com/aerospike/dsl/model/cdt/map/MapIndexRangeRelative.java
@@ -7,8 +7,8 @@
import com.aerospike.dsl.ConditionParser;
import com.aerospike.dsl.exception.AerospikeDSLException;
import com.aerospike.dsl.model.BasePath;
-import com.aerospike.dsl.util.ParsingUtils;
+import static com.aerospike.dsl.util.ParsingUtils.unquote;
import static com.aerospike.dsl.util.ParsingUtils.subtractNullable;
public class MapIndexRangeRelative extends MapPart {
@@ -47,7 +47,7 @@ public static MapIndexRangeRelative from(ConditionParser.MapIndexRangeRelativeCo
if (mapKeyContext.NAME_IDENTIFIER() != null) {
relativeKey = mapKeyContext.NAME_IDENTIFIER().getText();
} else if (mapKeyContext.QUOTED_STRING() != null) {
- relativeKey = ParsingUtils.getWithoutQuotes(mapKeyContext.QUOTED_STRING().getText());
+ relativeKey = unquote(mapKeyContext.QUOTED_STRING().getText());
}
}
return new MapIndexRangeRelative(isInverted, start, end, relativeKey);
diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapKey.java b/src/main/java/com/aerospike/dsl/model/cdt/map/MapKey.java
index a52bf49..8bd7774 100644
--- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapKey.java
+++ b/src/main/java/com/aerospike/dsl/model/cdt/map/MapKey.java
@@ -7,7 +7,8 @@
import com.aerospike.dsl.ConditionParser;
import com.aerospike.dsl.exception.AerospikeDSLException;
import com.aerospike.dsl.model.BasePath;
-import com.aerospike.dsl.util.ParsingUtils;
+
+import static com.aerospike.dsl.util.ParsingUtils.unquote;
public class MapKey extends MapPart {
private final String key;
@@ -19,7 +20,7 @@ public MapKey(String key) {
public static MapKey from(ConditionParser.MapKeyContext ctx) {
if (ctx.QUOTED_STRING() != null) {
- return new MapKey(ParsingUtils.getWithoutQuotes(ctx.QUOTED_STRING().getText()));
+ return new MapKey(unquote(ctx.QUOTED_STRING().getText()));
}
if (ctx.NAME_IDENTIFIER() != null) {
return new MapKey(ctx.NAME_IDENTIFIER().getText());
diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyList.java b/src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyList.java
index f7e273a..be5c428 100644
--- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyList.java
+++ b/src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyList.java
@@ -7,10 +7,11 @@
import com.aerospike.dsl.ConditionParser;
import com.aerospike.dsl.exception.AerospikeDSLException;
import com.aerospike.dsl.model.BasePath;
-import com.aerospike.dsl.util.ParsingUtils;
import java.util.List;
+import static com.aerospike.dsl.util.ParsingUtils.unquote;
+
public class MapKeyList extends MapPart {
private final boolean inverted;
private final List keyList;
@@ -35,7 +36,7 @@ public static MapKeyList from(ConditionParser.MapKeyListContext ctx) {
if (mapKey.NAME_IDENTIFIER() != null) {
return mapKey.NAME_IDENTIFIER().getText();
} else {
- return ParsingUtils.getWithoutQuotes(mapKey.QUOTED_STRING().getText());
+ return unquote(mapKey.QUOTED_STRING().getText());
}
}
).toList();
diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyRange.java b/src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyRange.java
index 4ffbeae..1c223da 100644
--- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyRange.java
+++ b/src/main/java/com/aerospike/dsl/model/cdt/map/MapKeyRange.java
@@ -7,10 +7,11 @@
import com.aerospike.dsl.ConditionParser;
import com.aerospike.dsl.exception.AerospikeDSLException;
import com.aerospike.dsl.model.BasePath;
-import com.aerospike.dsl.util.ParsingUtils;
import java.util.Optional;
+import static com.aerospike.dsl.util.ParsingUtils.unquote;
+
public class MapKeyRange extends MapPart {
private final boolean inverted;
private final String start;
@@ -34,12 +35,12 @@ public static MapKeyRange from(ConditionParser.MapKeyRangeContext ctx) {
String startKey = range.mapKey(0).NAME_IDENTIFIER() != null
? range.mapKey(0).NAME_IDENTIFIER().getText()
- : ParsingUtils.getWithoutQuotes(range.mapKey(0).QUOTED_STRING().getText());
+ : unquote(range.mapKey(0).QUOTED_STRING().getText());
String endKey = Optional.ofNullable(range.mapKey(1))
.map(keyCtx -> keyCtx.NAME_IDENTIFIER() != null
? keyCtx.NAME_IDENTIFIER().getText()
- : ParsingUtils.getWithoutQuotes(keyCtx.QUOTED_STRING().getText()))
+ : unquote(keyCtx.QUOTED_STRING().getText()))
.orElse(null);
return new MapKeyRange(isInverted, startKey, endKey);
diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapRankRangeRelative.java b/src/main/java/com/aerospike/dsl/model/cdt/map/MapRankRangeRelative.java
index cdf78df..7afef60 100644
--- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapRankRangeRelative.java
+++ b/src/main/java/com/aerospike/dsl/model/cdt/map/MapRankRangeRelative.java
@@ -7,8 +7,8 @@
import com.aerospike.dsl.ConditionParser;
import com.aerospike.dsl.exception.AerospikeDSLException;
import com.aerospike.dsl.model.BasePath;
-import com.aerospike.dsl.util.ParsingUtils;
+import static com.aerospike.dsl.util.ParsingUtils.unquote;
import static com.aerospike.dsl.util.ParsingUtils.subtractNullable;
public class MapRankRangeRelative extends MapPart {
@@ -50,7 +50,7 @@ public static MapRankRangeRelative from(ConditionParser.MapRankRangeRelativeCont
} else if (valueIdentifierContext.NAME_IDENTIFIER() != null) {
relativeValue = valueIdentifierContext.NAME_IDENTIFIER().getText();
} else if (valueIdentifierContext.QUOTED_STRING() != null) {
- relativeValue = ParsingUtils.getWithoutQuotes(valueIdentifierContext.QUOTED_STRING().getText());
+ relativeValue = unquote(valueIdentifierContext.QUOTED_STRING().getText());
}
}
diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapValue.java b/src/main/java/com/aerospike/dsl/model/cdt/map/MapValue.java
index 40dda20..4427e9d 100644
--- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapValue.java
+++ b/src/main/java/com/aerospike/dsl/model/cdt/map/MapValue.java
@@ -6,7 +6,8 @@
import com.aerospike.client.exp.MapExp;
import com.aerospike.dsl.ConditionParser;
import com.aerospike.dsl.model.BasePath;
-import com.aerospike.dsl.util.ParsingUtils;
+
+import static com.aerospike.dsl.util.ParsingUtils.unquote;
public class MapValue extends MapPart {
private final Object value;
@@ -21,7 +22,7 @@ public static MapValue from(ConditionParser.MapValueContext ctx) {
if (ctx.valueIdentifier().NAME_IDENTIFIER() != null) {
mapValue = ctx.valueIdentifier().NAME_IDENTIFIER().getText();
} else if (ctx.valueIdentifier().QUOTED_STRING() != null) {
- mapValue = ParsingUtils.getWithoutQuotes(ctx.valueIdentifier().QUOTED_STRING().getText());
+ mapValue = unquote(ctx.valueIdentifier().QUOTED_STRING().getText());
} else if (ctx.valueIdentifier().INT() != null) {
mapValue = Integer.parseInt(ctx.valueIdentifier().INT().getText());
}
diff --git a/src/main/java/com/aerospike/dsl/model/cdt/map/MapValueList.java b/src/main/java/com/aerospike/dsl/model/cdt/map/MapValueList.java
index 13307b8..e0be45c 100644
--- a/src/main/java/com/aerospike/dsl/model/cdt/map/MapValueList.java
+++ b/src/main/java/com/aerospike/dsl/model/cdt/map/MapValueList.java
@@ -10,7 +10,7 @@
import java.util.List;
-import static com.aerospike.dsl.util.ParsingUtils.getWithoutQuotes;
+import static com.aerospike.dsl.util.ParsingUtils.unquote;
public class MapValueList extends MapPart {
private final boolean inverted;
@@ -36,7 +36,7 @@ public static MapValueList from(ConditionParser.MapValueListContext ctx) {
if (listValue.NAME_IDENTIFIER() != null) {
return listValue.NAME_IDENTIFIER().getText();
} else if (listValue.QUOTED_STRING() != null) {
- return getWithoutQuotes(listValue.QUOTED_STRING().getText());
+ return unquote(listValue.QUOTED_STRING().getText());
}
return Integer.parseInt(listValue.INT().getText());
}
diff --git a/src/main/java/com/aerospike/dsl/util/ParsingUtils.java b/src/main/java/com/aerospike/dsl/util/ParsingUtils.java
index a1cd428..8677e88 100644
--- a/src/main/java/com/aerospike/dsl/util/ParsingUtils.java
+++ b/src/main/java/com/aerospike/dsl/util/ParsingUtils.java
@@ -12,7 +12,7 @@ public class ParsingUtils {
* @param str String input
* @return String inside the quotes
*/
- public static String getWithoutQuotes(String str) {
+ public static String unquote(String str) {
if (str.length() > 2) {
return str.substring(1, str.length() - 1);
} else {
diff --git a/src/main/java/com/aerospike/dsl/ExpressionConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java
similarity index 63%
rename from src/main/java/com/aerospike/dsl/ExpressionConditionVisitor.java
rename to src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java
index 8cad64f..175e948 100644
--- a/src/main/java/com/aerospike/dsl/ExpressionConditionVisitor.java
+++ b/src/main/java/com/aerospike/dsl/visitor/ExpressionConditionVisitor.java
@@ -1,6 +1,8 @@
-package com.aerospike.dsl;
+package com.aerospike.dsl.visitor;
import com.aerospike.client.exp.Exp;
+import com.aerospike.dsl.ConditionBaseVisitor;
+import com.aerospike.dsl.ConditionParser;
import com.aerospike.dsl.exception.AerospikeDSLException;
import com.aerospike.dsl.model.*;
import com.aerospike.dsl.model.cdt.list.ListIndex;
@@ -14,18 +16,15 @@
import com.aerospike.dsl.model.cdt.list.ListValueRange;
import com.aerospike.dsl.model.cdt.map.*;
import com.aerospike.dsl.util.TypeUtils;
-import com.aerospike.dsl.util.ValidationUtils;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.RuleNode;
import java.util.ArrayList;
-import java.util.Base64;
import java.util.List;
import java.util.TreeMap;
-import java.util.function.BinaryOperator;
-import java.util.function.UnaryOperator;
-import static com.aerospike.dsl.util.ParsingUtils.getWithoutQuotes;
+import static com.aerospike.dsl.util.ParsingUtils.unquote;
+import static com.aerospike.dsl.visitor.VisitorUtils.*;
public class ExpressionConditionVisitor extends ConditionBaseVisitor {
@@ -101,17 +100,6 @@ public AbstractPart visitExclusiveExpression(ConditionParser.ExclusiveExpression
return new Expr(Exp.exclusive(expressions.toArray(new Exp[0])));
}
- private void logicalSetBinsAsBooleanExpr(Expr left, Expr right) {
- logicalSetBinAsBooleanExpr(left);
- logicalSetBinAsBooleanExpr(right);
- }
-
- private void logicalSetBinAsBooleanExpr(Expr expr) {
- if (expr instanceof BinPart) {
- ((BinPart) expr).updateExp(Exp.Type.BOOL);
- }
- }
-
@Override
public AbstractPart visitGreaterThanExpression(ConditionParser.GreaterThanExpressionContext ctx) {
AbstractPart left = visit(ctx.operand(0));
@@ -264,150 +252,6 @@ public AbstractPart visitIntRShiftExpression(ConditionParser.IntRShiftExpression
return new Expr(exp);
}
- // 2 operands Expressions
- private Exp getExpOrFail(AbstractPart left, AbstractPart right, BinaryOperator operator) {
- if (left == null) {
- throw new AerospikeDSLException("Unable to parse left operand");
- }
- if (right == null) {
- throw new AerospikeDSLException("Unable to parse right operand");
- }
-
- if (left.getPartType() == AbstractPart.PartType.BIN_PART) {
- return getExpLeftBinTypeComparison((BinPart) left, right, operator);
- }
- if (right.getPartType() == AbstractPart.PartType.BIN_PART) {
- return getExpRightBinTypeComparison(left, (BinPart) right, operator);
- }
-
- // Handle non Bin operands cases
- Exp leftExp = left.getExp();
- Exp rightExp = right.getExp();
- return operator.apply(leftExp, rightExp);
- }
-
- private Exp getExpLeftBinTypeComparison(BinPart left, AbstractPart right, BinaryOperator operator) {
- String binNameLeft = left.getBinName();
- return switch (right.getPartType()) {
- case INT_OPERAND -> {
- ValidationUtils.validateComparableTypes(left.getExpType(), Exp.Type.INT);
- yield operator.apply(left.getExp(), right.getExp());
- }
- case FLOAT_OPERAND -> {
- ValidationUtils.validateComparableTypes(left.getExpType(), Exp.Type.FLOAT);
- yield operator.apply(left.getExp(), right.getExp());
- }
- case BOOL_OPERAND -> {
- ValidationUtils.validateComparableTypes(left.getExpType(), Exp.Type.BOOL);
- yield operator.apply(left.getExp(), right.getExp());
- }
- case STRING_OPERAND -> {
- if (left.getExpType() != null &&
- left.getExpType().equals(Exp.Type.BLOB)) {
- // Base64 Blob
- ValidationUtils.validateComparableTypes(left.getExpType(), Exp.Type.BLOB);
- String base64String = ((StringOperand) right).getValue();
- byte[] value = Base64.getDecoder().decode(base64String);
- yield operator.apply(left.getExp(), Exp.val(value));
- } else {
- // String
- ValidationUtils.validateComparableTypes(left.getExpType(), Exp.Type.STRING);
- yield operator.apply(left.getExp(), right.getExp());
- }
- }
- case METADATA_OPERAND -> {
- // No need to validate, types are determined by metadata function
- Exp.Type binType = Exp.Type.valueOf(((MetadataOperand) right).getMetadataType().toString());
- yield operator.apply(
- Exp.bin(binNameLeft, binType),
- right.getExp()
- );
- }
- case EXPR, PATH_OPERAND ->
- operator.apply(left.getExp(), right.getExp()); // Can't validate with Expr on one side
- // Left and right are both bin parts
- case BIN_PART -> {
- // Validate types if possible
- ValidationUtils.validateComparableTypes(left.getExpType(), right.getExpType());
- yield operator.apply(left.getExp(), right.getExp());
- }
- case LIST_OPERAND -> {
- ValidationUtils.validateComparableTypes(left.getExpType(), Exp.Type.LIST);
- yield operator.apply(left.getExp(), right.getExp());
- }
- case MAP_OPERAND -> {
- ValidationUtils.validateComparableTypes(left.getExpType(), Exp.Type.MAP);
- yield operator.apply(left.getExp(), right.getExp());
- }
- default -> throw new AerospikeDSLException("Operand type not supported: %s".formatted(right.getPartType()));
- };
- }
-
- private Exp getExpRightBinTypeComparison(AbstractPart left, BinPart right, BinaryOperator operator) {
- String binNameRight = right.getBinName();
- return switch (left.getPartType()) {
- case INT_OPERAND -> {
- ValidationUtils.validateComparableTypes(Exp.Type.INT, right.getExpType());
- yield operator.apply(left.getExp(), right.getExp());
- }
- case FLOAT_OPERAND -> {
- ValidationUtils.validateComparableTypes(Exp.Type.FLOAT, right.getExpType());
- yield operator.apply(left.getExp(), right.getExp());
- }
- case BOOL_OPERAND -> {
- ValidationUtils.validateComparableTypes(Exp.Type.BOOL, right.getExpType());
- yield operator.apply(left.getExp(), right.getExp());
- }
- case STRING_OPERAND -> {
- if (right.getExpType() != null &&
- right.getExpType().equals(Exp.Type.BLOB)) {
- // Base64 Blob
- ValidationUtils.validateComparableTypes(Exp.Type.BLOB, right.getExpType());
- String base64String = ((StringOperand) left).getValue();
- byte[] value = Base64.getDecoder().decode(base64String);
- yield operator.apply(Exp.val(value), right.getExp());
- } else {
- // String
- ValidationUtils.validateComparableTypes(Exp.Type.STRING, right.getExpType());
- yield operator.apply(left.getExp(), right.getExp());
- }
- }
- case METADATA_OPERAND -> {
- // No need to validate, types are determined by metadata function
- Exp.Type binType = Exp.Type.valueOf(((MetadataOperand) left).getMetadataType().toString());
- yield operator.apply(
- left.getExp(),
- Exp.bin(binNameRight, binType)
- );
- }
- case EXPR, PATH_OPERAND ->
- operator.apply(left.getExp(), right.getExp()); // Can't validate with Expr on one side
- // No need for 2 BIN_OPERAND handling since it's covered in the left condition
- case LIST_OPERAND -> {
- ValidationUtils.validateComparableTypes(Exp.Type.LIST, right.getExpType());
- yield operator.apply(left.getExp(), right.getExp());
- }
- case MAP_OPERAND -> {
- ValidationUtils.validateComparableTypes(Exp.Type.MAP, right.getExpType());
- yield operator.apply(left.getExp(), right.getExp());
- }
- default -> throw new AerospikeDSLException("Operand type not supported: %s".formatted(left.getPartType()));
- };
- }
-
- // 1 operand Expressions
- private Exp getExpOrFail(AbstractPart operand, UnaryOperator operator) {
- if (operand == null) {
- throw new AerospikeDSLException("Unable to parse operand");
- }
-
- // 1 Operand Expression is always a BIN Operand
- String binName = ((BinPart) operand).getBinName();
-
- // There is only 1 case of a single operand expression (int not), and it always gets an integer
- return operator.apply(Exp.bin(binName, Exp.Type.INT));
- }
-
@Override
public AbstractPart visitPathFunctionGet(ConditionParser.PathFunctionGetContext ctx) {
PathFunction.ReturnParam returnParam = null;
@@ -429,20 +273,6 @@ public AbstractPart visitPathFunctionCount(ConditionParser.PathFunctionCountCont
return new PathFunction(PathFunction.PathFunctionType.COUNT, PathFunction.ReturnParam.COUNT, null);
}
- private String getPathFunctionParam(ConditionParser.PathFunctionParamContext paramCtx, String paramName) {
- String paramNameText;
- String paramNameValue;
- String paramValue = null;
- if (paramCtx.pathFunctionParamName() != null) {
- paramNameText = paramCtx.pathFunctionParamName().getText();
- paramNameValue = paramCtx.pathFunctionParamValue().getText();
- if (paramNameText.equalsIgnoreCase(paramName)) {
- paramValue = paramNameValue;
- }
- }
- return paramValue;
- }
-
@Override
public AbstractPart visitPathFunctionCast(ConditionParser.PathFunctionCastContext ctx) {
String typeVal = extractTypeFromMethod(ctx.PATH_FUNCTION_CAST().getText());
@@ -452,14 +282,6 @@ public AbstractPart visitPathFunctionCast(ConditionParser.PathFunctionCastContex
return new PathFunction(PathFunction.PathFunctionType.CAST, null, binType);
}
- private static String extractTypeFromMethod(String methodName) {
- if (methodName.startsWith("as") && methodName.endsWith("()")) {
- return methodName.substring(2, methodName.length() - 2);
- } else {
- throw new AerospikeDSLException("Invalid method name: %s".formatted(methodName));
- }
- }
-
@Override
public AbstractPart visitMetadata(ConditionParser.MetadataContext ctx) {
String text = ctx.METADATA_FUNCTION().getText();
@@ -473,22 +295,6 @@ public AbstractPart visitMetadata(ConditionParser.MetadataContext ctx) {
}
}
- private String extractFunctionName(String text) {
- int startParen = text.indexOf('(');
- return (startParen != -1) ? text.substring(0, startParen) : text;
- }
-
- private Integer extractParameter(String text) {
- int startParen = text.indexOf('(');
- int endParen = text.indexOf(')');
-
- if (startParen != -1 && endParen != -1 && endParen > startParen + 1) {
- String numberStr = text.substring(startParen + 1, endParen);
- return Integer.parseInt(numberStr);
- }
- return null;
- }
-
@Override
public AbstractPart visitBinPart(ConditionParser.BinPartContext ctx) {
return new BinPart(ctx.NAME_IDENTIFIER().getText());
@@ -528,13 +334,6 @@ public ListOperand readChildrenIntoListOperand(RuleNode listNode) {
return new ListOperand(list);
}
- private boolean shouldVisitListElement(int i, int size, ParseTree child) {
- return size > 0 // size is not 0
- && i != 0 // not the first element ('[')
- && i != size - 1 // not the last element (']')
- && !child.getText().equals(","); // not a comma (list elements separator)
- }
-
@Override
public AbstractPart visitOrderedMapConstant(ConditionParser.OrderedMapConstantContext ctx) {
return readChildrenIntoMapOperand(ctx);
@@ -572,17 +371,9 @@ public MapOperand readChildrenIntoMapOperand(RuleNode mapNode) {
return new MapOperand(map);
}
- private boolean shouldVisitMapElement(int i, int size, ParseTree child) {
- return size > 0 // size is not 0
- && i != 0 // not the first element ('{')
- && i != size - 1 // not the last element ('}')
- && !child.getText().equals(":") // not a colon (map key and value separator)
- && !child.getText().equals(","); // not a comma (map pairs separator)
- }
-
@Override
public AbstractPart visitStringOperand(ConditionParser.StringOperandContext ctx) {
- String text = getWithoutQuotes(ctx.getText());
+ String text = unquote(ctx.getText());
return new StringOperand(text);
}
@@ -640,14 +431,6 @@ public AbstractPart visitVariable(ConditionParser.VariableContext ctx) {
return new VariableOperand(extractVariableName(text));
}
- private String extractVariableName(String variableReference) {
- if (variableReference.startsWith("${") && variableReference.endsWith("}")) {
- return variableReference.substring(2, variableReference.length() - 1);
- } else {
- throw new IllegalArgumentException("Input string is not in the correct format");
- }
- }
-
private AbstractPart overrideType(AbstractPart part, ParseTree ctx) {
ConditionParser.PathFunctionContext pathFunctionContext =
((ConditionParser.PathContext) ctx.getParent()).pathFunction();
@@ -683,34 +466,6 @@ private AbstractPart overrideType(AbstractPart part, ParseTree ctx) {
return part;
}
- private Exp.Type detectImplicitTypeFromUpperTree(ParseTree ctx) {
- // Search for a "leaf" operand child (Int, Float, String and Boolean)
- // in the above levels of the current path in the expression tree
- while (ctx.getParent() != null) {
- ctx = ctx.getParent();
-
- for (int i = 0; i < ctx.getChildCount(); i++) {
- ParseTree child = ctx.getChild(i);
-
- if (child instanceof ConditionParser.OperandContext operandContext) {
- if (operandContext.numberOperand() != null) {
- if (operandContext.numberOperand().intOperand() != null) {
- return Exp.Type.INT;
- } else if (operandContext.numberOperand().floatOperand() != null) {
- return Exp.Type.FLOAT;
- }
- } else if (operandContext.stringOperand() != null) {
- return Exp.Type.STRING;
- } else if (operandContext.booleanOperand() != null) {
- return Exp.Type.BOOL;
- }
- }
- }
- }
- // Could not detect, return null and determine defaults later on
- return null;
- }
-
@Override
public AbstractPart visitPath(ConditionParser.PathContext ctx) {
BasePath basePath = (BasePath) visit(ctx.basePath());
diff --git a/src/main/java/com/aerospike/dsl/visitor/FilterConditionVisitor.java b/src/main/java/com/aerospike/dsl/visitor/FilterConditionVisitor.java
new file mode 100644
index 0000000..c11829f
--- /dev/null
+++ b/src/main/java/com/aerospike/dsl/visitor/FilterConditionVisitor.java
@@ -0,0 +1,102 @@
+package com.aerospike.dsl.visitor;
+
+import com.aerospike.client.query.Filter;
+import com.aerospike.dsl.ConditionParser;
+import com.aerospike.dsl.exception.AerospikeDSLException;
+import com.aerospike.dsl.model.AbstractPart;
+import com.aerospike.dsl.model.Expr;
+import com.aerospike.dsl.model.SIndexFilter;
+
+import static com.aerospike.dsl.model.Expr.ExprPartsOperation.*;
+import static com.aerospike.dsl.visitor.VisitorUtils.FilterOperationType.*;
+import static com.aerospike.dsl.visitor.VisitorUtils.getFilterOrFail;
+import static com.aerospike.dsl.visitor.VisitorUtils.validateNumericBin;
+
+public class FilterConditionVisitor extends ExpressionConditionVisitor {
+
+ @Override
+ public AbstractPart visitGreaterThanExpression(ConditionParser.GreaterThanExpressionContext ctx) {
+ AbstractPart left = visit(ctx.operand(0));
+ AbstractPart right = visit(ctx.operand(1));
+
+ Filter filter = getFilterOrFail(left, right, GT);
+ return new Expr(new SIndexFilter(filter));
+ }
+
+ @Override
+ public AbstractPart visitGreaterThanOrEqualExpression(ConditionParser.GreaterThanOrEqualExpressionContext ctx) {
+ AbstractPart left = visit(ctx.operand(0));
+ AbstractPart right = visit(ctx.operand(1));
+
+ Filter filter = getFilterOrFail(left, right, GTEQ);
+ return new Expr(new SIndexFilter(filter));
+ }
+
+ @Override
+ public AbstractPart visitLessThanExpression(ConditionParser.LessThanExpressionContext ctx) {
+ AbstractPart left = visit(ctx.operand(0));
+ AbstractPart right = visit(ctx.operand(1));
+
+ Filter filter = getFilterOrFail(left, right, LT);
+ return new Expr(new SIndexFilter(filter));
+ }
+
+ @Override
+ public AbstractPart visitLessThanOrEqualExpression(ConditionParser.LessThanOrEqualExpressionContext ctx) {
+ AbstractPart left = visit(ctx.operand(0));
+ AbstractPart right = visit(ctx.operand(1));
+
+ Filter filter = getFilterOrFail(left, right, LTEQ);
+ return new Expr(new SIndexFilter(filter));
+ }
+
+ @Override
+ public AbstractPart visitEqualityExpression(ConditionParser.EqualityExpressionContext ctx) {
+ AbstractPart left = visit(ctx.operand(0));
+ AbstractPart right = visit(ctx.operand(1));
+
+ Filter filter = getFilterOrFail(left, right, EQ);
+ return new Expr(new SIndexFilter(filter));
+ }
+
+ @Override
+ public AbstractPart visitInequalityExpression(ConditionParser.InequalityExpressionContext ctx) {
+ throw new AerospikeDSLException("The operation is not supported by secondary index filter");
+ }
+
+ @Override
+ public AbstractPart visitAddExpression(ConditionParser.AddExpressionContext ctx) {
+ AbstractPart left = visit(ctx.operand(0));
+ AbstractPart right = visit(ctx.operand(1));
+
+ validateNumericBin(left, right);
+ return new Expr(left, right, ADD);
+ }
+
+ @Override
+ public AbstractPart visitSubExpression(ConditionParser.SubExpressionContext ctx) {
+ AbstractPart left = visit(ctx.operand(0));
+ AbstractPart right = visit(ctx.operand(1));
+
+ validateNumericBin(left, right);
+ return new Expr(left, right, SUB);
+ }
+
+ @Override
+ public AbstractPart visitDivExpression(ConditionParser.DivExpressionContext ctx) {
+ AbstractPart left = visit(ctx.operand(0));
+ AbstractPart right = visit(ctx.operand(1));
+
+ validateNumericBin(left, right);
+ return new Expr(left, right, DIV);
+ }
+
+ @Override
+ public AbstractPart visitMulExpression(ConditionParser.MulExpressionContext ctx) {
+ AbstractPart left = visit(ctx.operand(0));
+ AbstractPart right = visit(ctx.operand(1));
+
+ validateNumericBin(left, right);
+ return new Expr(left, right, MUL);
+ }
+}
diff --git a/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java
new file mode 100644
index 0000000..744416e
--- /dev/null
+++ b/src/main/java/com/aerospike/dsl/visitor/VisitorUtils.java
@@ -0,0 +1,629 @@
+package com.aerospike.dsl.visitor;
+
+import com.aerospike.client.exp.Exp;
+import com.aerospike.client.query.Filter;
+import com.aerospike.dsl.ConditionParser;
+import com.aerospike.dsl.exception.AerospikeDSLException;
+import com.aerospike.dsl.model.AbstractPart;
+import com.aerospike.dsl.model.BinPart;
+import com.aerospike.dsl.model.Expr;
+import com.aerospike.dsl.model.IntOperand;
+import com.aerospike.dsl.model.MetadataOperand;
+import com.aerospike.dsl.model.StringOperand;
+import lombok.experimental.UtilityClass;
+import org.antlr.v4.runtime.misc.Pair;
+import org.antlr.v4.runtime.tree.ParseTree;
+
+import java.util.Base64;
+import java.util.Objects;
+import java.util.function.BinaryOperator;
+import java.util.function.UnaryOperator;
+
+import static com.aerospike.dsl.model.Expr.ExprPartsOperation.*;
+import static com.aerospike.dsl.util.ValidationUtils.validateComparableTypes;
+import static com.aerospike.dsl.visitor.VisitorUtils.ArithmeticTermType.*;
+import static com.aerospike.dsl.visitor.VisitorUtils.FilterOperationType.*;
+
+@UtilityClass
+public class VisitorUtils {
+
+ protected enum FilterOperationType {
+ GT,
+ GTEQ,
+ LT,
+ LTEQ,
+ EQ,
+ NOTEQ
+ }
+
+ protected enum ArithmeticTermType {
+ ADDEND,
+ SUBTR,
+ MIN,
+ DIFFERENCE,
+ DIVIDEND,
+ DIVISOR,
+ QUOTIENT,
+ MULTIPLICAND,
+ MULTIPLIER,
+ PRODUCT
+ }
+
+ static String extractVariableName(String variableReference) {
+ if (variableReference.startsWith("${") && variableReference.endsWith("}")) {
+ return variableReference.substring(2, variableReference.length() - 1);
+ }
+ throw new IllegalArgumentException("Input string is not in the correct format");
+
+ }
+
+ static Exp.Type detectImplicitTypeFromUpperTree(ParseTree ctx) {
+ // Search for a "leaf" operand child (Int, Float, String and Boolean)
+ // in the above levels of the current path in the expression tree
+ while (ctx.getParent() != null) {
+ ctx = ctx.getParent();
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+
+ if (child instanceof ConditionParser.OperandContext operandContext) {
+ if (operandContext.numberOperand() != null) {
+ if (operandContext.numberOperand().intOperand() != null) {
+ return Exp.Type.INT;
+ } else if (operandContext.numberOperand().floatOperand() != null) {
+ return Exp.Type.FLOAT;
+ }
+ } else if (operandContext.stringOperand() != null) {
+ return Exp.Type.STRING;
+ } else if (operandContext.booleanOperand() != null) {
+ return Exp.Type.BOOL;
+ }
+ }
+ }
+ }
+ // Could not detect, return null and determine defaults later on
+ return null;
+ }
+
+ static void logicalSetBinsAsBooleanExpr(Expr left, Expr right) {
+ logicalSetBinAsBooleanExpr(left);
+ logicalSetBinAsBooleanExpr(right);
+ }
+
+ static void logicalSetBinAsBooleanExpr(Expr expr) {
+ if (expr instanceof BinPart) {
+ ((BinPart) expr).updateExp(Exp.Type.BOOL);
+ }
+ }
+
+ static boolean shouldVisitListElement(int i, int size, ParseTree child) {
+ return size > 0 // size is not 0
+ && i != 0 // not the first element ('[')
+ && i != size - 1 // not the last element (']')
+ && !child.getText().equals(","); // not a comma (list elements separator)
+ }
+
+ static boolean shouldVisitMapElement(int i, int size, ParseTree child) {
+ return size > 0 // size is not 0
+ && i != 0 // not the first element ('{')
+ && i != size - 1 // not the last element ('}')
+ && !child.getText().equals(":") // not a colon (map key and value separator)
+ && !child.getText().equals(","); // not a comma (map pairs separator)
+ }
+
+ // 2 operands Expressions
+ static Exp getExpOrFail(AbstractPart left, AbstractPart right, BinaryOperator operator) {
+ if (left == null) {
+ throw new AerospikeDSLException("Unable to parse left operand");
+ }
+ if (right == null) {
+ throw new AerospikeDSLException("Unable to parse right operand");
+ }
+
+ if (left.getPartType() == AbstractPart.PartType.BIN_PART) {
+ return getExpLeftBinTypeComparison((BinPart) left, right, operator);
+ }
+ if (right.getPartType() == AbstractPart.PartType.BIN_PART) {
+ return getExpRightBinTypeComparison(left, (BinPart) right, operator);
+ }
+
+ // Handle non Bin operands cases
+ Exp leftExp = left.getExp();
+ Exp rightExp = right.getExp();
+ return operator.apply(leftExp, rightExp);
+ }
+
+ static Exp getExpLeftBinTypeComparison(BinPart left, AbstractPart right, BinaryOperator operator) {
+ String binNameLeft = left.getBinName();
+ return switch (right.getPartType()) {
+ case INT_OPERAND -> {
+ validateComparableTypes(left.getExpType(), Exp.Type.INT);
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ case FLOAT_OPERAND -> {
+ validateComparableTypes(left.getExpType(), Exp.Type.FLOAT);
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ case BOOL_OPERAND -> {
+ validateComparableTypes(left.getExpType(), Exp.Type.BOOL);
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ case STRING_OPERAND -> {
+ if (left.getExpType() != null &&
+ left.getExpType().equals(Exp.Type.BLOB)) {
+ // Base64 Blob
+ validateComparableTypes(left.getExpType(), Exp.Type.BLOB);
+ String base64String = ((StringOperand) right).getValue();
+ byte[] value = Base64.getDecoder().decode(base64String);
+ yield operator.apply(left.getExp(), Exp.val(value));
+ } else {
+ // String
+ validateComparableTypes(left.getExpType(), Exp.Type.STRING);
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ }
+ case METADATA_OPERAND -> {
+ // No need to validate, types are determined by metadata function
+ Exp.Type binType = Exp.Type.valueOf(((MetadataOperand) right).getMetadataType().toString());
+ yield operator.apply(
+ Exp.bin(binNameLeft, binType),
+ right.getExp()
+ );
+ }
+ case EXPR, PATH_OPERAND ->
+ operator.apply(left.getExp(), right.getExp()); // Can't validate with Expr on one side
+ // Left and right are both bin parts
+ case BIN_PART -> {
+ // Validate types if possible
+ validateComparableTypes(left.getExpType(), right.getExpType());
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ case LIST_OPERAND -> {
+ validateComparableTypes(left.getExpType(), Exp.Type.LIST);
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ case MAP_OPERAND -> {
+ validateComparableTypes(left.getExpType(), Exp.Type.MAP);
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ default -> throw new AerospikeDSLException("Operand type not supported: %s".formatted(right.getPartType()));
+ };
+ }
+
+ static Exp getExpRightBinTypeComparison(AbstractPart left, BinPart right, BinaryOperator operator) {
+ String binNameRight = right.getBinName();
+ return switch (left.getPartType()) {
+ case INT_OPERAND -> {
+ validateComparableTypes(Exp.Type.INT, right.getExpType());
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ case FLOAT_OPERAND -> {
+ validateComparableTypes(Exp.Type.FLOAT, right.getExpType());
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ case BOOL_OPERAND -> {
+ validateComparableTypes(Exp.Type.BOOL, right.getExpType());
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ case STRING_OPERAND -> {
+ if (right.getExpType() != null &&
+ right.getExpType().equals(Exp.Type.BLOB)) {
+ // Base64 Blob
+ validateComparableTypes(Exp.Type.BLOB, right.getExpType());
+ String base64String = ((StringOperand) left).getValue();
+ byte[] value = Base64.getDecoder().decode(base64String);
+ yield operator.apply(Exp.val(value), right.getExp());
+ } else {
+ // String
+ validateComparableTypes(Exp.Type.STRING, right.getExpType());
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ }
+ case METADATA_OPERAND -> {
+ // No need to validate, types are determined by metadata function
+ Exp.Type binType = Exp.Type.valueOf(((MetadataOperand) left).getMetadataType().toString());
+ yield operator.apply(
+ left.getExp(),
+ Exp.bin(binNameRight, binType)
+ );
+ }
+ case EXPR, PATH_OPERAND ->
+ operator.apply(left.getExp(), right.getExp()); // Can't validate with Expr on one side
+ // No need for 2 BIN_OPERAND handling since it's covered in the left condition
+ case LIST_OPERAND -> {
+ validateComparableTypes(Exp.Type.LIST, right.getExpType());
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ case MAP_OPERAND -> {
+ validateComparableTypes(Exp.Type.MAP, right.getExpType());
+ yield operator.apply(left.getExp(), right.getExp());
+ }
+ default -> throw new AerospikeDSLException("Operand type not supported: %s".formatted(left.getPartType()));
+ };
+ }
+
+ // 1 operand Expressions
+ static Exp getExpOrFail(AbstractPart operand, UnaryOperator operator) {
+ if (operand == null) {
+ throw new AerospikeDSLException("Unable to parse operand");
+ }
+
+ // 1 Operand Expression is always a BIN Operand
+ String binName = ((BinPart) operand).getBinName();
+
+ // There is only 1 case of a single operand expression (int not), and it always gets an integer
+ return operator.apply(Exp.bin(binName, Exp.Type.INT));
+ }
+
+ static String getPathFunctionParam(ConditionParser.PathFunctionParamContext paramCtx, String paramName) {
+ String paramNameText;
+ String paramNameValue;
+ String paramValue = null;
+ if (paramCtx.pathFunctionParamName() != null) {
+ paramNameText = paramCtx.pathFunctionParamName().getText();
+ paramNameValue = paramCtx.pathFunctionParamValue().getText();
+ if (paramNameText.equalsIgnoreCase(paramName)) {
+ paramValue = paramNameValue;
+ }
+ }
+ return paramValue;
+ }
+
+ static String extractTypeFromMethod(String methodName) {
+ if (methodName.startsWith("as") && methodName.endsWith("()")) {
+ return methodName.substring(2, methodName.length() - 2);
+ } else {
+ throw new AerospikeDSLException("Invalid method name: %s".formatted(methodName));
+ }
+ }
+
+ static String extractFunctionName(String text) {
+ int startParen = text.indexOf('(');
+ return (startParen != -1) ? text.substring(0, startParen) : text;
+ }
+
+ static Integer extractParameter(String text) {
+ int startParen = text.indexOf('(');
+ int endParen = text.indexOf(')');
+
+ if (startParen != -1 && endParen != -1 && endParen > startParen + 1) {
+ String numberStr = text.substring(startParen + 1, endParen);
+ return Integer.parseInt(numberStr);
+ }
+ return null;
+ }
+
+ // 2 operands Filters
+ static Filter getFilterOrFail(AbstractPart left, AbstractPart right, FilterOperationType type) {
+ if (left == null) {
+ throw new AerospikeDSLException("Unable to parse left operand");
+ }
+ if (right == null) {
+ throw new AerospikeDSLException("Unable to parse right operand");
+ }
+
+ if (left.getPartType() == AbstractPart.PartType.BIN_PART) {
+ return getFilter((BinPart) left, right, type);
+ }
+ if (right.getPartType() == AbstractPart.PartType.BIN_PART) {
+ return getFilter((BinPart) right, left, invertType(type));
+ }
+
+ // Handle non Bin operands cases
+ if (left instanceof Expr leftExpr) {
+ return getFilterOrFail(leftExpr.getLeft(), leftExpr.getRight(), leftExpr.getOperationType(), right, type);
+ }
+ if (right instanceof Expr rightExpr) {
+ return getFilterOrFail(rightExpr.getLeft(), rightExpr.getRight(), rightExpr.getOperationType(), left, type);
+ }
+ return null;
+ }
+
+ // 2 operands Filters
+ static Filter getFilterOrFail(AbstractPart exprLeft, AbstractPart exprRight, Expr.ExprPartsOperation operationType,
+ AbstractPart right, FilterOperationType type) {
+ if (exprLeft == null) {
+ throw new AerospikeDSLException("Unable to parse left operand of expression");
+ }
+ if (exprRight == null) {
+ throw new AerospikeDSLException("Unable to parse right operand of expression");
+ }
+
+ if (exprLeft.getPartType() == AbstractPart.PartType.BIN_PART) { // bin is on the left side
+ if (exprRight instanceof IntOperand leftOperand && right instanceof IntOperand rightOperand) {
+ validateComparableTypes(exprLeft.getExpType(), Exp.Type.INT);
+ return applyFilterOperator(((BinPart) exprLeft).getBinName(), leftOperand, rightOperand,
+ operationType, type, getTermType(operationType, true));
+ }
+ throw new AerospikeDSLException(
+ String.format("Operands not supported in secondary index Filter: %s, %s", exprRight, right));
+ }
+ if (exprRight.getPartType() == AbstractPart.PartType.BIN_PART) { // bin is on the right side
+ if (exprLeft instanceof IntOperand leftOperand && right instanceof IntOperand rightOperand) {
+ validateComparableTypes(exprRight.getExpType(), Exp.Type.INT);
+ return applyFilterOperator(((BinPart) exprRight).getBinName(), leftOperand, rightOperand,
+ operationType, type, getTermType(operationType, false));
+ }
+ throw new AerospikeDSLException(
+ String.format("Operands not supported in secondary index Filter: %s, %s", exprRight, right));
+ }
+
+ // Handle non Bin operands cases
+ if (exprLeft instanceof Expr leftExpr) {
+ return getFilterOrFail(leftExpr.getLeft(), leftExpr.getRight(), type);
+ }
+ return null;
+ }
+
+ static void validateNumericBin(AbstractPart left, AbstractPart right) {
+ if (!isNumericBin(left, right)) {
+ throw new AerospikeDSLException("The operation is not supported by secondary index filter");
+ }
+ }
+
+ private static boolean isNumericBin(AbstractPart left, AbstractPart right) {
+ return (left instanceof BinPart && right instanceof IntOperand)
+ || (right instanceof BinPart && left instanceof IntOperand);
+ }
+
+ private static ArithmeticTermType getTermType(Expr.ExprPartsOperation operationType, boolean isLeftTerm) {
+ return switch (operationType) {
+ case ADD -> ADDEND;
+ case SUB -> isLeftTerm ? SUBTR : MIN;
+ case DIV -> isLeftTerm ? DIVIDEND : DIVISOR;
+ case MUL -> isLeftTerm ? MULTIPLICAND : MULTIPLIER;
+ default -> throw new UnsupportedOperationException("Not supported: " + operationType);
+ };
+ }
+
+ private static Pair getLimitsForDivision(long left, long right, FilterOperationType type,
+ ArithmeticTermType termType) {
+ // Prevent division by zero
+ if (right == 0) {
+ throw new AerospikeDSLException("Cannot divide by zero");
+ }
+
+ return switch (termType) {
+ case DIVIDEND -> LimitsForBinDividend(left, right, type);
+ case DIVISOR -> getLimitsForBinDivisor(left, right, type);
+ default -> throw new UnsupportedOperationException("Unsupported term type for division: " + termType);
+ };
+ }
+
+ private static Pair LimitsForBinDividend(long left, long right,
+ FilterOperationType operationType) {
+ if (left > 0 && right > 0) {
+ // both operands are positive
+ return getLimitsForBinDividendWithLeftNumberPositive(operationType, left, right);
+ } else if (left == 0 && right == 0) {
+ throw new AerospikeDSLException("Undefined division for 0 / 0");
+ } else if (left < 0 && right < 0) {
+ // both operands are negative
+ return getLimitsForBinDividendWithLeftNumberNegative(operationType, left, right);
+ } else if (left > 0 && right < 0) {
+ // left positive, right negative
+ return getLimitsForBinDividendWithLeftNumberPositive(operationType, left, right);
+ } else if (right > 0 && left < 0) {
+ // left negative, right positive
+ return getLimitsForBinDividendWithLeftNumberNegative(operationType, left, right);
+ } else if (left != 0) {
+ throw new AerospikeDSLException("Division by zero is not allowed");
+ } else {
+ return new Pair<>(null, null);
+ }
+ }
+
+ private static Pair getLimitsForBinDividendWithLeftNumberNegative(FilterOperationType operationType,
+ long left, long right) {
+ return switch (operationType) {
+ case GT:
+ yield new Pair<>(Long.MIN_VALUE, left * right - 1);
+ case GTEQ:
+ yield new Pair<>(Long.MIN_VALUE, left * right);
+ case LT:
+ yield new Pair<>(left * right + 1, Long.MAX_VALUE);
+ case LTEQ:
+ yield new Pair<>(left * right, Long.MAX_VALUE);
+ default:
+ throw new AerospikeDSLException("OperationType not supported for division: " + operationType);
+ };
+ }
+
+ private static Pair getLimitsForBinDividendWithLeftNumberPositive(FilterOperationType operationType,
+ long left, long right) {
+ return switch (operationType) {
+ case GT:
+ yield new Pair<>(left * right + 1, Long.MAX_VALUE);
+ case GTEQ:
+ yield new Pair<>(left * right, Long.MAX_VALUE);
+ case LT:
+ yield new Pair<>(Long.MIN_VALUE, left * right - 1);
+ case LTEQ:
+ yield new Pair<>(Long.MIN_VALUE, left * right);
+ default:
+ throw new AerospikeDSLException("OperationType not supported for division: " + operationType);
+ };
+ }
+
+ private static Pair getLimitsForBinDivisor(long left, long right, FilterOperationType operationType) {
+ if (left > 0 && right > 0) {
+ // both operands are positive
+ return switch (operationType) {
+ case GT:
+ yield new Pair<>(1L, getClosestLongToTheLeft((float) left / right));
+ case GTEQ:
+ yield new Pair<>(1L, left / right);
+ case LT, LTEQ:
+ yield new Pair<>(null, null);
+ default:
+ throw new AerospikeDSLException("OperationType not supported for division: " + operationType);
+ };
+ } else if (left == 0 && right == 0) {
+ throw new AerospikeDSLException("Cannot divide by zero");
+ } else if (left < 0 && right < 0) {
+ // both operands are negative
+ return switch (operationType) {
+ case GT, GTEQ:
+ yield new Pair<>(null, null);
+ case LT:
+ yield new Pair<>(1L, getClosestLongToTheLeft((float) left / right));
+ case LTEQ:
+ yield new Pair<>(1L, left / right);
+ default:
+ throw new AerospikeDSLException("OperationType not supported for division: " + operationType);
+ };
+ } else if (left > 0 && right < 0) {
+ // left positive, right negative
+ return switch (operationType) {
+ case GT, GTEQ:
+ yield new Pair<>(null, null);
+ case LT:
+ yield new Pair<>(getClosestLongToTheRight((float) left / right), -1L);
+ case LTEQ:
+ yield new Pair<>(left / right, -1L);
+ default:
+ throw new AerospikeDSLException("OperationType not supported for division: " + operationType);
+ };
+ } else if (right > 0 && left < 0) {
+ // right positive, left negative
+ return switch (operationType) {
+ case GT:
+ yield new Pair<>(getClosestLongToTheRight((float) left / right), -1L);
+ case GTEQ:
+ yield new Pair<>(left / right, -1L);
+ case LT, LTEQ:
+ yield new Pair<>(null, null);
+ default:
+ throw new AerospikeDSLException("OperationType not supported for division: " + operationType);
+ };
+ } else if (left != 0) {
+ throw new AerospikeDSLException("Division by zero is not allowed");
+ } else {
+ return new Pair<>(null, null);
+ }
+ }
+
+ private static Filter getFilterForDivOrFail(String binName, Pair value, FilterOperationType type) {
+ // Based on the operation type, generate the appropriate filter range
+ return switch (type) {
+ case GT, GTEQ, LT, LTEQ -> Filter.range(binName, value.a, value.b); // Range from 1 to value - 1
+ case EQ -> Filter.equal(binName, value.a); // Exact match for equality case
+ default -> throw new AerospikeDSLException("OperationType not supported for division: " + type);
+ };
+ }
+
+ private static Filter getFilter(BinPart bin, AbstractPart operand, FilterOperationType type) {
+ String binName = bin.getBinName();
+ return switch (operand.getPartType()) {
+ case INT_OPERAND -> {
+ validateComparableTypes(bin.getExpType(), Exp.Type.INT);
+ yield getFilterForArithmeticOrFail(binName, ((IntOperand) operand).getValue(), type);
+
+ }
+ case STRING_OPERAND -> {
+ if (type != EQ) throw new AerospikeDSLException("Operand type not supported");
+
+ if (bin.getExpType() != null &&
+ bin.getExpType().equals(Exp.Type.BLOB)) {
+ // Base64 Blob
+ validateComparableTypes(bin.getExpType(), Exp.Type.BLOB);
+ String base64String = ((StringOperand) operand).getValue();
+ byte[] value = Base64.getDecoder().decode(base64String);
+ yield Filter.equal(binName, value);
+ } else {
+ // String
+ validateComparableTypes(bin.getExpType(), Exp.Type.STRING);
+ yield Filter.equal(binName, ((StringOperand) operand).getValue());
+ }
+ }
+ default ->
+ throw new AerospikeDSLException("Operand type not supported: %s".formatted(operand.getPartType()));
+ };
+ }
+
+ private static Filter applyFilterOperator(String binName, IntOperand leftOperand, IntOperand rightOperand,
+ Expr.ExprPartsOperation operationType, FilterOperationType type,
+ ArithmeticTermType termType) {
+ long leftValue = leftOperand.getValue();
+ long rightValue = rightOperand.getValue();
+ float value;
+ if (Objects.requireNonNull(operationType) == ADD) {
+ value = rightValue - leftValue;
+ } else if (operationType == SUB) {
+ value = switch (termType) {
+ case SUBTR -> rightValue + leftValue;
+ case MIN -> {
+ type = invertType(type);
+ yield leftValue - rightValue;
+ }
+ default -> throw new IllegalStateException("Unexpected term type: " + termType);
+ };
+ } else if (operationType == DIV) {
+ Pair valueForDiv = getLimitsForDivision(leftValue, rightValue, type, termType);
+ if (valueForDiv.a == null
+ || valueForDiv.b == null
+ || valueForDiv.a > valueForDiv.b
+ || (valueForDiv.a == 0 && valueForDiv.b == 0)) {
+ throw new AerospikeDSLException("The operation is not supported by secondary index filter");
+ }
+ return getFilterForDivOrFail(binName, valueForDiv, type);
+ } else if (operationType == MUL) {
+ if (leftValue <= 0) {
+ if (leftValue == 0) throw new AerospikeDSLException("Cannot divide by zero");
+ type = invertType(type);
+ }
+ float val = (float) rightValue / leftValue;
+ return getFilterForArithmeticOrFail(binName, val, type);
+ } else {
+ throw new UnsupportedOperationException("Not supported");
+ }
+
+ return getFilterForArithmeticOrFail(binName, value, type);
+ }
+
+ private static Filter getFilterForArithmeticOrFail(String binName, float value, FilterOperationType type) {
+ return switch (type) {
+ // "$.intBin1 > 100" and "100 < $.intBin1" represent the same Filter
+ case GT -> Filter.range(binName, getClosestLongToTheRight(value), Long.MAX_VALUE);
+ case GTEQ -> Filter.range(binName, (long) value, Long.MAX_VALUE);
+ case LT -> Filter.range(binName, Long.MIN_VALUE, getClosestLongToTheLeft(value));
+ case LTEQ -> Filter.range(binName, Long.MIN_VALUE, (long) value);
+ case EQ -> Filter.equal(binName, (long) value);
+ default -> throw new AerospikeDSLException("The operation is not supported by secondary index filter");
+ };
+ }
+
+ private static long getClosestLongToTheLeft(float value) {
+ // Get the largest integer less than or equal to the float
+ long flooredValue = (long) Math.floor(value);
+
+ // If the float is a round number, subtract 1
+ if (value == flooredValue) {
+ return flooredValue - 1;
+ }
+
+ return flooredValue;
+ }
+
+ private static long getClosestLongToTheRight(float value) {
+ // Get the smallest integer greater than or equal to the float
+ long ceiledValue = (long) Math.ceil(value);
+
+ // If the float is a round number, add 1
+ if (value == ceiledValue) {
+ return ceiledValue + 1;
+ }
+
+ return ceiledValue;
+ }
+
+ private FilterOperationType invertType(FilterOperationType type) {
+ return switch (type) {
+ case GT -> LT;
+ case GTEQ -> LTEQ;
+ case LT -> GT;
+ case LTEQ -> GTEQ;
+ default -> type;
+ };
+ }
+}
diff --git a/src/test/java/com/aerospike/dsl/BinExpressionsTests.java b/src/test/java/com/aerospike/dsl/BinExpressionsTests.java
deleted file mode 100644
index 9d319e4..0000000
--- a/src/test/java/com/aerospike/dsl/BinExpressionsTests.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.aerospike.dsl;
-
-import com.aerospike.client.exp.Exp;
-import com.aerospike.dsl.exception.AerospikeDSLException;
-import org.junit.jupiter.api.Test;
-
-import static com.aerospike.dsl.util.TestUtils.translate;
-import static com.aerospike.dsl.util.TestUtils.translateAndCompare;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-class BinExpressionsTests {
-
- @Test
- void binGT() {
- // Bin as right
- translateAndCompare("$.intBin1 > 100", Exp.gt(Exp.intBin("intBin1"), Exp.val(100)));
- translateAndCompare("$.stringBin1 > 'text'", Exp.gt(Exp.stringBin("stringBin1"), Exp.val("text")));
- translateAndCompare("$.stringBin1 > \"text\"", Exp.gt(Exp.stringBin("stringBin1"), Exp.val("text")));
-
- // Bin as left (considered as lt)
- translateAndCompare("100 < $.intBin1", Exp.lt(Exp.val(100), Exp.intBin("intBin1")));
- translateAndCompare("'text' < $.stringBin1", Exp.lt(Exp.val("text"), Exp.stringBin("stringBin1")));
- translateAndCompare("\"text\" < $.stringBin1", Exp.lt(Exp.val("text"), Exp.stringBin("stringBin1")));
- }
-
- @Test
- void binGE() {
- translateAndCompare("$.intBin1 >= 100", Exp.ge(Exp.intBin("intBin1"), Exp.val(100)));
- translateAndCompare("$.stringBin1 >= 'text'", Exp.ge(Exp.stringBin("stringBin1"), Exp.val("text")));
- translateAndCompare("$.stringBin1 >= \"text\"", Exp.ge(Exp.stringBin("stringBin1"), Exp.val("text")));
- }
-
- @Test
- void binLT() {
- translateAndCompare("$.intBin1 < 100", Exp.lt(Exp.intBin("intBin1"), Exp.val(100)));
- translateAndCompare("$.stringBin1 < 'text'", Exp.lt(Exp.stringBin("stringBin1"), Exp.val("text")));
- translateAndCompare("$.stringBin1 < \"text\"", Exp.lt(Exp.stringBin("stringBin1"), Exp.val("text")));
- }
-
- @Test
- void binLE() {
- translateAndCompare("$.intBin1 <= 100", Exp.le(Exp.intBin("intBin1"), Exp.val(100)));
- translateAndCompare("$.stringBin1 <= 'text'", Exp.le(Exp.stringBin("stringBin1"), Exp.val("text")));
- translateAndCompare("$.stringBin1 <= \"text\"", Exp.le(Exp.stringBin("stringBin1"), Exp.val("text")));
- }
-
- @Test
- void binEquals() {
- translateAndCompare("$.intBin1 == 100", Exp.eq(Exp.intBin("intBin1"), Exp.val(100)));
- translateAndCompare("$.strBin == \"yes\"", Exp.eq(Exp.stringBin("strBin"), Exp.val("yes")));
- translateAndCompare("$.strBin == 'yes'", Exp.eq(Exp.stringBin("strBin"), Exp.val("yes")));
- }
-
- @Test
- void binNotEquals() {
- translateAndCompare("$.intBin1 != 100", Exp.ne(Exp.intBin("intBin1"), Exp.val(100)));
- translateAndCompare("$.strBin != \"yes\"", Exp.ne(Exp.stringBin("strBin"), Exp.val("yes")));
- translateAndCompare("$.strBin != 'yes'", Exp.ne(Exp.stringBin("strBin"), Exp.val("yes")));
- }
-
- @Test
- void negativeStringBinEquals() {
- assertThatThrownBy(() -> translate("$.strBin == yes"))
- .isInstanceOf(AerospikeDSLException.class)
- .hasMessage("Unable to parse right operand");
- }
-
- // TODO: Will be handled in FMWK-486
- //@Test
- //void logicalOperators_functionCalls() {
- // translate("$.a.exists() and $.b.exists()");
- //}
-}
diff --git a/src/test/java/com/aerospike/dsl/ArithmeticExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java
similarity index 66%
rename from src/test/java/com/aerospike/dsl/ArithmeticExpressionsTests.java
rename to src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java
index db1d8da..7876e58 100644
--- a/src/test/java/com/aerospike/dsl/ArithmeticExpressionsTests.java
+++ b/src/test/java/com/aerospike/dsl/expression/ArithmeticExpressionsTests.java
@@ -1,123 +1,123 @@
-package com.aerospike.dsl;
+package com.aerospike.dsl.expression;
import com.aerospike.client.exp.Exp;
import com.aerospike.dsl.exception.AerospikeDSLException;
import org.junit.jupiter.api.Test;
-import static com.aerospike.dsl.util.TestUtils.translate;
-import static com.aerospike.dsl.util.TestUtils.translateAndCompare;
+import static com.aerospike.dsl.util.TestUtils.parseExpression;
+import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class ArithmeticExpressionsTests {
@Test
void add() {
- translateAndCompare("($.apples + $.bananas) > 10",
+ parseExpressionAndCompare("($.apples + $.bananas) > 10",
Exp.gt(Exp.add(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10)));
- translateAndCompare("($.apples + 5) > 10",
+ parseExpressionAndCompare("($.apples + 5) > 10",
Exp.gt(Exp.add(Exp.intBin("apples"), Exp.val(5)), Exp.val(10)));
- translateAndCompare("(5 + $.bananas) > 10",
+ parseExpressionAndCompare("(5 + $.bananas) > 10",
Exp.gt(Exp.add(Exp.val(5), Exp.intBin("bananas")), Exp.val(10)));
- translateAndCompare("(5.2 + $.bananas) > 10.2",
+ parseExpressionAndCompare("(5.2 + $.bananas) > 10.2",
Exp.gt(Exp.add(Exp.val(5.2), Exp.floatBin("bananas")), Exp.val(10.2)));
}
@Test
void sub() {
- translateAndCompare("($.apples - $.bananas) == 10",
+ parseExpressionAndCompare("($.apples - $.bananas) == 10",
Exp.eq(Exp.sub(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10)));
- translateAndCompare("($.apples - 5) == 10",
+ parseExpressionAndCompare("($.apples - 5) == 10",
Exp.eq(Exp.sub(Exp.intBin("apples"), Exp.val(5)), Exp.val(10)));
- translateAndCompare("(15 - $.bananas) == 10",
+ parseExpressionAndCompare("(15 - $.bananas) == 10",
Exp.eq(Exp.sub(Exp.val(15), Exp.intBin("bananas")), Exp.val(10)));
}
@Test
void mul() {
- translateAndCompare("($.apples * $.bananas) != 10",
+ parseExpressionAndCompare("($.apples * $.bananas) != 10",
Exp.ne(Exp.mul(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10)));
- translateAndCompare("($.apples * 7) != 10",
+ parseExpressionAndCompare("($.apples * 7) != 10",
Exp.ne(Exp.mul(Exp.intBin("apples"), Exp.val(7)), Exp.val(10)));
- translateAndCompare("(3 * $.bananas) != 10",
+ parseExpressionAndCompare("(3 * $.bananas) != 10",
Exp.ne(Exp.mul(Exp.val(3), Exp.intBin("bananas")), Exp.val(10)));
}
@Test
void div() {
- translateAndCompare("($.apples / $.bananas) <= 10",
+ parseExpressionAndCompare("($.apples / $.bananas) <= 10",
Exp.le(Exp.div(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10)));
- translateAndCompare("($.apples / 5) <= 10",
+ parseExpressionAndCompare("($.apples / 5) <= 10",
Exp.le(Exp.div(Exp.intBin("apples"), Exp.val(5)), Exp.val(10)));
- translateAndCompare("(33 / $.bananas) <= 10",
+ parseExpressionAndCompare("(33 / $.bananas) <= 10",
Exp.le(Exp.div(Exp.val(33), Exp.intBin("bananas")), Exp.val(10)));
// Exp should be constructed and equal and therefore the test is passing
// but when actually triggered server will throw divide by zero exception
- translateAndCompare("($.apples / 0) <= 10",
+ parseExpressionAndCompare("($.apples / 0) <= 10",
Exp.le(Exp.div(Exp.intBin("apples"), Exp.val(0)), Exp.val(10)));
}
@Test
void mod() {
- translateAndCompare("($.apples % $.bananas) != 10",
+ parseExpressionAndCompare("($.apples % $.bananas) != 10",
Exp.ne(Exp.mod(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10)));
- translateAndCompare("($.apples % 7) != 10",
+ parseExpressionAndCompare("($.apples % 7) != 10",
Exp.ne(Exp.mod(Exp.intBin("apples"), Exp.val(7)), Exp.val(10)));
- translateAndCompare("(3 % $.bananas) != 10",
+ parseExpressionAndCompare("(3 % $.bananas) != 10",
Exp.ne(Exp.mod(Exp.val(3), Exp.intBin("bananas")), Exp.val(10)));
}
@Test
void intAnd() {
- translateAndCompare("($.apples & $.bananas) != 10",
+ parseExpressionAndCompare("($.apples & $.bananas) != 10",
Exp.ne(Exp.intAnd(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10)));
- translateAndCompare("($.apples & 7) != 10",
+ parseExpressionAndCompare("($.apples & 7) != 10",
Exp.ne(Exp.intAnd(Exp.intBin("apples"), Exp.val(7)), Exp.val(10)));
- translateAndCompare("(3 & $.bananas) != 10",
+ parseExpressionAndCompare("(3 & $.bananas) != 10",
Exp.ne(Exp.intAnd(Exp.val(3), Exp.intBin("bananas")), Exp.val(10)));
}
@Test
void intOr() {
- translateAndCompare("($.apples | $.bananas) != 10",
+ parseExpressionAndCompare("($.apples | $.bananas) != 10",
Exp.ne(Exp.intOr(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10)));
- translateAndCompare("($.apples | 7) != 10",
+ parseExpressionAndCompare("($.apples | 7) != 10",
Exp.ne(Exp.intOr(Exp.intBin("apples"), Exp.val(7)), Exp.val(10)));
- translateAndCompare("(3 | $.bananas) != 10",
+ parseExpressionAndCompare("(3 | $.bananas) != 10",
Exp.ne(Exp.intOr(Exp.val(3), Exp.intBin("bananas")), Exp.val(10)));
}
@Test
void intXor() {
- translateAndCompare("($.apples ^ $.bananas) != 10",
+ parseExpressionAndCompare("($.apples ^ $.bananas) != 10",
Exp.ne(Exp.intXor(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(10)));
- translateAndCompare("($.apples ^ 7) != 10",
+ parseExpressionAndCompare("($.apples ^ 7) != 10",
Exp.ne(Exp.intXor(Exp.intBin("apples"), Exp.val(7)), Exp.val(10)));
- translateAndCompare("(3 ^ $.bananas) != 10",
+ parseExpressionAndCompare("(3 ^ $.bananas) != 10",
Exp.ne(Exp.intXor(Exp.val(3), Exp.intBin("bananas")), Exp.val(10)));
}
@Test
void intNot() {
- translateAndCompare("(~$.apples) != 10",
+ parseExpressionAndCompare("(~$.apples) != 10",
Exp.ne(Exp.intNot(Exp.intBin("apples")), Exp.val(10)));
}
@Test
void intLShift() {
- translateAndCompare("$.visits << 1",
+ parseExpressionAndCompare("$.visits << 1",
Exp.lshift(Exp.intBin("visits"), Exp.val(1)));
}
@Test
void intRShift() {
- translateAndCompare("(($.flags >> 6) & 1) == 1",
+ parseExpressionAndCompare("(($.flags >> 6) & 1) == 1",
Exp.eq(Exp.intAnd(Exp.rshift(Exp.intBin("flags"), Exp.val(6)), Exp.val(1)), Exp.val(1)));
}
@Test
void negativeArithmetic() {
- assertThatThrownBy(() -> translate("($.apples.get(type: STRING) + 5) > 10"))
+ assertThatThrownBy(() -> parseExpression("($.apples.get(type: STRING) + 5) > 10"))
.isInstanceOf(AerospikeDSLException.class)
.hasMessageContaining("Cannot compare STRING to INT");
diff --git a/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java
new file mode 100644
index 0000000..eb0d85a
--- /dev/null
+++ b/src/test/java/com/aerospike/dsl/expression/BinExpressionsTests.java
@@ -0,0 +1,71 @@
+package com.aerospike.dsl.expression;
+
+import com.aerospike.client.exp.Exp;
+import com.aerospike.dsl.exception.AerospikeDSLException;
+import org.junit.jupiter.api.Test;
+
+import static com.aerospike.dsl.util.TestUtils.parseExpression;
+import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+class BinExpressionsTests {
+
+ @Test
+ void binGT() {
+ parseExpressionAndCompare("$.intBin1 > 100", Exp.gt(Exp.intBin("intBin1"), Exp.val(100)));
+ parseExpressionAndCompare("$.stringBin1 > 'text'", Exp.gt(Exp.stringBin("stringBin1"), Exp.val("text")));
+ parseExpressionAndCompare("$.stringBin1 > \"text\"", Exp.gt(Exp.stringBin("stringBin1"), Exp.val("text")));
+
+ parseExpressionAndCompare("100 < $.intBin1", Exp.lt(Exp.val(100), Exp.intBin("intBin1")));
+ parseExpressionAndCompare("'text' < $.stringBin1", Exp.lt(Exp.val("text"), Exp.stringBin("stringBin1")));
+ parseExpressionAndCompare("\"text\" < $.stringBin1", Exp.lt(Exp.val("text"), Exp.stringBin("stringBin1")));
+ }
+
+ @Test
+ void binGE() {
+ parseExpressionAndCompare("$.intBin1 >= 100", Exp.ge(Exp.intBin("intBin1"), Exp.val(100)));
+ parseExpressionAndCompare("$.stringBin1 >= 'text'", Exp.ge(Exp.stringBin("stringBin1"), Exp.val("text")));
+ parseExpressionAndCompare("$.stringBin1 >= \"text\"", Exp.ge(Exp.stringBin("stringBin1"), Exp.val("text")));
+ }
+
+ @Test
+ void binLT() {
+ parseExpressionAndCompare("$.intBin1 < 100", Exp.lt(Exp.intBin("intBin1"), Exp.val(100)));
+ parseExpressionAndCompare("$.stringBin1 < 'text'", Exp.lt(Exp.stringBin("stringBin1"), Exp.val("text")));
+ parseExpressionAndCompare("$.stringBin1 < \"text\"", Exp.lt(Exp.stringBin("stringBin1"), Exp.val("text")));
+ }
+
+ @Test
+ void binLE() {
+ parseExpressionAndCompare("$.intBin1 <= 100", Exp.le(Exp.intBin("intBin1"), Exp.val(100)));
+ parseExpressionAndCompare("$.stringBin1 <= 'text'", Exp.le(Exp.stringBin("stringBin1"), Exp.val("text")));
+ parseExpressionAndCompare("$.stringBin1 <= \"text\"", Exp.le(Exp.stringBin("stringBin1"), Exp.val("text")));
+ }
+
+ @Test
+ void binEquals() {
+ parseExpressionAndCompare("$.intBin1 == 100", Exp.eq(Exp.intBin("intBin1"), Exp.val(100)));
+ parseExpressionAndCompare("$.strBin == \"yes\"", Exp.eq(Exp.stringBin("strBin"), Exp.val("yes")));
+ parseExpressionAndCompare("$.strBin == 'yes'", Exp.eq(Exp.stringBin("strBin"), Exp.val("yes")));
+ }
+
+ @Test
+ void binNotEquals() {
+ parseExpressionAndCompare("$.intBin1 != 100", Exp.ne(Exp.intBin("intBin1"), Exp.val(100)));
+ parseExpressionAndCompare("$.strBin != \"yes\"", Exp.ne(Exp.stringBin("strBin"), Exp.val("yes")));
+ parseExpressionAndCompare("$.strBin != 'yes'", Exp.ne(Exp.stringBin("strBin"), Exp.val("yes")));
+ }
+
+ @Test
+ void negativeStringBinEquals() {
+ assertThatThrownBy(() -> parseExpression("$.strBin == yes"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Unable to parse right operand");
+ }
+
+ // TODO: Will be handled in FMWK-486
+ //@Test
+ //void logicalOperators_functionCalls() {
+ // translate("$.a.exists() and $.b.exists()");
+ //}
+}
diff --git a/src/test/java/com/aerospike/dsl/CastingTests.java b/src/test/java/com/aerospike/dsl/expression/CastingTests.java
similarity index 56%
rename from src/test/java/com/aerospike/dsl/CastingTests.java
rename to src/test/java/com/aerospike/dsl/expression/CastingTests.java
index 9dafa7b..c398386 100644
--- a/src/test/java/com/aerospike/dsl/CastingTests.java
+++ b/src/test/java/com/aerospike/dsl/expression/CastingTests.java
@@ -1,11 +1,11 @@
-package com.aerospike.dsl;
+package com.aerospike.dsl.expression;
import com.aerospike.client.exp.Exp;
import com.aerospike.dsl.exception.AerospikeDSLException;
import org.junit.jupiter.api.Test;
-import static com.aerospike.dsl.util.TestUtils.translate;
-import static com.aerospike.dsl.util.TestUtils.translateAndCompare;
+import static com.aerospike.dsl.util.TestUtils.parseExpression;
+import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class CastingTests {
@@ -14,19 +14,19 @@ public class CastingTests {
void floatToIntComparison() {
Exp expectedExp = Exp.gt(Exp.intBin("intBin1"), Exp.intBin("floatBin1"));
// Int is default
- translateAndCompare("$.intBin1 > $.floatBin1.asInt()", expectedExp);
- translateAndCompare("$.intBin1.get(type: INT) > $.floatBin1.asInt()", expectedExp);
+ parseExpressionAndCompare("$.intBin1 > $.floatBin1.asInt()", expectedExp);
+ parseExpressionAndCompare("$.intBin1.get(type: INT) > $.floatBin1.asInt()", expectedExp);
}
@Test
void intToFloatComparison() {
- translateAndCompare("$.intBin1.get(type: INT) > $.intBin2.asFloat()",
+ parseExpressionAndCompare("$.intBin1.get(type: INT) > $.intBin2.asFloat()",
Exp.gt(Exp.intBin("intBin1"), Exp.floatBin("intBin2")));
}
@Test
void negativeInvalidTypesComparison() {
- assertThatThrownBy(() -> translate("$.stringBin1.get(type: STRING) > $.intBin2.asFloat()"))
+ assertThatThrownBy(() -> parseExpression("$.stringBin1.get(type: STRING) > $.intBin2.asFloat()"))
.isInstanceOf(AerospikeDSLException.class)
.hasMessageContaining("Cannot compare STRING to FLOAT");
}
diff --git a/src/test/java/com/aerospike/dsl/ControlStructuresTests.java b/src/test/java/com/aerospike/dsl/expression/ControlStructuresTests.java
similarity index 74%
rename from src/test/java/com/aerospike/dsl/ControlStructuresTests.java
rename to src/test/java/com/aerospike/dsl/expression/ControlStructuresTests.java
index 8ecbf6e..14b7c94 100644
--- a/src/test/java/com/aerospike/dsl/ControlStructuresTests.java
+++ b/src/test/java/com/aerospike/dsl/expression/ControlStructuresTests.java
@@ -1,9 +1,9 @@
-package com.aerospike.dsl;
+package com.aerospike.dsl.expression;
import com.aerospike.client.exp.Exp;
import org.junit.jupiter.api.Test;
-import static com.aerospike.dsl.util.TestUtils.translateAndCompare;
+import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare;
public class ControlStructuresTests {
@@ -17,10 +17,10 @@ void whenWithASingleDeclaration() {
Exp.val("other")
);
- translateAndCompare("when ($.who == 1 => \"bob\", default => \"other\")",
+ parseExpressionAndCompare("when ($.who == 1 => \"bob\", default => \"other\")",
expected);
// different spacing style
- translateAndCompare("when($.who == 1 => \"bob\", default => \"other\")",
+ parseExpressionAndCompare("when($.who == 1 => \"bob\", default => \"other\")",
expected);
}
@@ -40,7 +40,7 @@ void whenUsingTheResult() {
// Implicit detect as String
//translateAndCompare("$.stringBin1 == (when ($.who == 1 => \"bob\", default => \"other\"))",
// expected);
- translateAndCompare("$.stringBin1.get(type: STRING) == (when ($.who == 1 => \"bob\", default => \"other\"))",
+ parseExpressionAndCompare("$.stringBin1.get(type: STRING) == (when ($.who == 1 => \"bob\", default => \"other\"))",
expected);
}
@@ -58,7 +58,7 @@ void whenWithMultipleDeclarations() {
Exp.val("other")
);
- translateAndCompare("when ($.who == 1 => \"bob\", $.who == 2 => \"fred\", default => \"other\")",
+ parseExpressionAndCompare("when ($.who == 1 => \"bob\", $.who == 2 => \"fred\", default => \"other\")",
expected);
}
@@ -74,10 +74,10 @@ void withMultipleVariablesDefinitionAndUsage() {
Exp.add(Exp.var("x"), Exp.var("y"))
);
- translateAndCompare("with (x = 1, y = ${x} + 1) do (${x} + ${y})",
+ parseExpressionAndCompare("with (x = 1, y = ${x} + 1) do (${x} + ${y})",
expected);
// different spacing style
- translateAndCompare("with(x = 1, y = ${x}+1) do(${x}+${y})",
+ parseExpressionAndCompare("with(x = 1, y = ${x}+1) do(${x}+${y})",
expected);
}
}
diff --git a/src/test/java/com/aerospike/dsl/ExplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java
similarity index 69%
rename from src/test/java/com/aerospike/dsl/ExplicitTypesTests.java
rename to src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java
index f738b2d..7774aa5 100644
--- a/src/test/java/com/aerospike/dsl/ExplicitTypesTests.java
+++ b/src/test/java/com/aerospike/dsl/expression/ExplicitTypesTests.java
@@ -1,4 +1,4 @@
-package com.aerospike.dsl;
+package com.aerospike.dsl.expression;
import com.aerospike.client.exp.Exp;
import com.aerospike.dsl.exception.AerospikeDSLException;
@@ -8,8 +8,8 @@
import java.util.List;
import java.util.TreeMap;
-import static com.aerospike.dsl.util.TestUtils.translate;
-import static com.aerospike.dsl.util.TestUtils.translateAndCompare;
+import static com.aerospike.dsl.util.TestUtils.parseExpression;
+import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
// Explicit types tests, list and map explicit types are tested in their own test classes
@@ -17,33 +17,33 @@ public class ExplicitTypesTests {
@Test
void integerComparison() {
- translateAndCompare("$.intBin1.get(type: INT) > 5",
+ parseExpressionAndCompare("$.intBin1.get(type: INT) > 5",
Exp.gt(Exp.intBin("intBin1"), Exp.val(5)));
- translateAndCompare("5 < $.intBin1.get(type: INT)",
+ parseExpressionAndCompare("5 < $.intBin1.get(type: INT)",
Exp.lt(Exp.val(5), Exp.intBin("intBin1")));
}
@Test
void stringComparison() {
// A String constant must contain quoted Strings
- translateAndCompare("$.stringBin1.get(type: STRING) == \"yes\"",
+ parseExpressionAndCompare("$.stringBin1.get(type: STRING) == \"yes\"",
Exp.eq(Exp.stringBin("stringBin1"), Exp.val("yes")));
- translateAndCompare("$.stringBin1.get(type: STRING) == 'yes'",
+ parseExpressionAndCompare("$.stringBin1.get(type: STRING) == 'yes'",
Exp.eq(Exp.stringBin("stringBin1"), Exp.val("yes")));
- translateAndCompare("\"yes\" == $.stringBin1.get(type: STRING)",
+ parseExpressionAndCompare("\"yes\" == $.stringBin1.get(type: STRING)",
Exp.eq(Exp.val("yes"), Exp.stringBin("stringBin1")));
- translateAndCompare("'yes' == $.stringBin1.get(type: STRING)",
+ parseExpressionAndCompare("'yes' == $.stringBin1.get(type: STRING)",
Exp.eq(Exp.val("yes"), Exp.stringBin("stringBin1")));
}
@Test
void stringComparisonNegativeTest() {
// A String constant must be quoted
- assertThatThrownBy(() -> translateAndCompare("$.stringBin1.get(type: STRING) == yes",
+ assertThatThrownBy(() -> parseExpressionAndCompare("$.stringBin1.get(type: STRING) == yes",
Exp.eq(Exp.stringBin("stringBin1"), Exp.val("yes"))))
.isInstanceOf(AerospikeDSLException.class)
.hasMessage("Unable to parse right operand");
@@ -53,65 +53,65 @@ void stringComparisonNegativeTest() {
void blobComparison() {
byte[] data = new byte[]{1, 2, 3};
String encodedString = Base64.getEncoder().encodeToString(data);
- translateAndCompare("$.blobBin1.get(type: BLOB) == \"" + encodedString + "\"",
+ parseExpressionAndCompare("$.blobBin1.get(type: BLOB) == \"" + encodedString + "\"",
Exp.eq(Exp.blobBin("blobBin1"), Exp.val(data)));
// Reverse
- translateAndCompare("\"" + encodedString + "\"" + " == $.blobBin1.get(type: BLOB)",
+ parseExpressionAndCompare("\"" + encodedString + "\"" + " == $.blobBin1.get(type: BLOB)",
Exp.eq(Exp.val(data), Exp.blobBin("blobBin1")));
}
@Test
void floatComparison() {
- translateAndCompare("$.floatBin1.get(type: FLOAT) == 1.5",
+ parseExpressionAndCompare("$.floatBin1.get(type: FLOAT) == 1.5",
Exp.eq(Exp.floatBin("floatBin1"), Exp.val(1.5)));
- translateAndCompare("1.5 == $.floatBin1.get(type: FLOAT)",
+ parseExpressionAndCompare("1.5 == $.floatBin1.get(type: FLOAT)",
Exp.eq(Exp.val(1.5), Exp.floatBin("floatBin1")));
}
@Test
void booleanComparison() {
- translateAndCompare("$.boolBin1.get(type: BOOL) == true",
+ parseExpressionAndCompare("$.boolBin1.get(type: BOOL) == true",
Exp.eq(Exp.boolBin("boolBin1"), Exp.val(true)));
- translateAndCompare("true == $.boolBin1.get(type: BOOL)",
+ parseExpressionAndCompare("true == $.boolBin1.get(type: BOOL)",
Exp.eq(Exp.val(true), Exp.boolBin("boolBin1")));
}
@Test
void negativeBooleanComparison() {
- assertThatThrownBy(() -> translate("$.boolBin1.get(type: BOOL) == 5"))
+ assertThatThrownBy(() -> parseExpression("$.boolBin1.get(type: BOOL) == 5"))
.isInstanceOf(AerospikeDSLException.class)
.hasMessageContaining("Cannot compare BOOL to INT");
}
@Test
void listComparison_constantOnRightSide() {
- translateAndCompare("$.listBin1.get(type: LIST) == [100]",
+ parseExpressionAndCompare("$.listBin1.get(type: LIST) == [100]",
Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of(100))));
- translateAndCompare("$.listBin1.[] == [100]",
+ parseExpressionAndCompare("$.listBin1.[] == [100]",
Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of(100))));
// integer values are read as long
- translateAndCompare("$.listBin1.get(type: LIST) == [100, 200, 300, 400]",
+ parseExpressionAndCompare("$.listBin1.get(type: LIST) == [100, 200, 300, 400]",
Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of(100, 200, 300, 400))));
// integer values are read as long
- translateAndCompare("$.listBin1.get(type: LIST) == [100, 200, 300, 400]",
+ parseExpressionAndCompare("$.listBin1.get(type: LIST) == [100, 200, 300, 400]",
Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of(100L, 200L, 300L, 400L))));
- translateAndCompare("$.listBin1.get(type: LIST) == ['yes']",
+ parseExpressionAndCompare("$.listBin1.get(type: LIST) == ['yes']",
Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes"))));
- translateAndCompare("$.listBin1.get(type: LIST) == ['yes', 'of course']",
+ parseExpressionAndCompare("$.listBin1.get(type: LIST) == ['yes', 'of course']",
Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes", "of course"))));
- translateAndCompare("$.listBin1.get(type: LIST) == [\"yes\"]",
+ parseExpressionAndCompare("$.listBin1.get(type: LIST) == [\"yes\"]",
Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes"))));
- translateAndCompare("$.listBin1.get(type: LIST) == [\"yes\", \"of course\"]",
+ parseExpressionAndCompare("$.listBin1.get(type: LIST) == [\"yes\", \"of course\"]",
Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes", "of course"))));
}
@@ -119,7 +119,7 @@ void listComparison_constantOnRightSide() {
void listComparison_constantOnRightSide_NegativeTest() {
// A String constant must be quoted
assertThatThrownBy(() ->
- translateAndCompare("$.listBin1.get(type: LIST) == [yes, of course]",
+ parseExpressionAndCompare("$.listBin1.get(type: LIST) == [yes, of course]",
Exp.eq(Exp.listBin("listBin1"), Exp.val(List.of("yes", "of course"))))
)
.isInstanceOf(AerospikeDSLException.class)
@@ -128,30 +128,30 @@ void listComparison_constantOnRightSide_NegativeTest() {
@Test
void listComparison_constantOnLeftSide() {
- translateAndCompare("[100] == $.listBin1.get(type: LIST)",
+ parseExpressionAndCompare("[100] == $.listBin1.get(type: LIST)",
Exp.eq(Exp.val(List.of(100)), Exp.listBin("listBin1")));
- translateAndCompare("[100] == $.listBin1.[]",
+ parseExpressionAndCompare("[100] == $.listBin1.[]",
Exp.eq(Exp.val(List.of(100)), Exp.listBin("listBin1")));
// integer values are read as long
- translateAndCompare("[100, 200, 300, 400] == $.listBin1.get(type: LIST)",
+ parseExpressionAndCompare("[100, 200, 300, 400] == $.listBin1.get(type: LIST)",
Exp.eq(Exp.val(List.of(100, 200, 300, 400)), Exp.listBin("listBin1")));
// integer values are read as long
- translateAndCompare("[100, 200, 300, 400] == $.listBin1.get(type: LIST)",
+ parseExpressionAndCompare("[100, 200, 300, 400] == $.listBin1.get(type: LIST)",
Exp.eq(Exp.val(List.of(100L, 200L, 300L, 400L)), Exp.listBin("listBin1")));
- translateAndCompare("['yes'] == $.listBin1.get(type: LIST)",
+ parseExpressionAndCompare("['yes'] == $.listBin1.get(type: LIST)",
Exp.eq(Exp.val(List.of("yes")), Exp.listBin("listBin1")));
- translateAndCompare("['yes', 'of course'] == $.listBin1.get(type: LIST)",
+ parseExpressionAndCompare("['yes', 'of course'] == $.listBin1.get(type: LIST)",
Exp.eq(Exp.val(List.of("yes", "of course")), Exp.listBin("listBin1")));
- translateAndCompare("[\"yes\"] == $.listBin1.get(type: LIST)",
+ parseExpressionAndCompare("[\"yes\"] == $.listBin1.get(type: LIST)",
Exp.eq(Exp.val(List.of("yes")), Exp.listBin("listBin1")));
- translateAndCompare("[\"yes\", \"of course\"] == $.listBin1.get(type: LIST)",
+ parseExpressionAndCompare("[\"yes\", \"of course\"] == $.listBin1.get(type: LIST)",
Exp.eq(Exp.val(List.of("yes", "of course")), Exp.listBin("listBin1")));
}
@@ -159,7 +159,7 @@ void listComparison_constantOnLeftSide() {
void listComparison_constantOnLeftSide_NegativeTest() {
// A String constant must be quoted
assertThatThrownBy(() ->
- translateAndCompare("[yes, of course] == $.listBin1.get(type: LIST)",
+ parseExpressionAndCompare("[yes, of course] == $.listBin1.get(type: LIST)",
Exp.eq(Exp.val(List.of("yes", "of course")), Exp.listBin("listBin1")))
)
.isInstanceOf(AerospikeDSLException.class)
@@ -185,39 +185,39 @@ public static TreeMap treeMapOf(Object... entries) {
@Test
void mapComparison_constantOnRightSide() {
// Prerequisite for comparing maps: both sides must be ordered maps
- translateAndCompare("$.mapBin1.get(type: MAP) == {100:100}",
+ parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {100:100}",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100, 100))));
- translateAndCompare("$.mapBin1.get(type: MAP) == {100 : 100}",
+ parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {100 : 100}",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100, 100))));
- translateAndCompare("$.mapBin1.{} == {100:100}",
+ parseExpressionAndCompare("$.mapBin1.{} == {100:100}",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100, 100))));
byte[] blobKey = new byte[]{1, 2, 3};
String encodedBlobKey = Base64.getEncoder().encodeToString(blobKey);
// encoded blob key must be quoted as it is a String
- translateAndCompare("$.mapBin1.{} == {'" + encodedBlobKey + "':100}",
+ parseExpressionAndCompare("$.mapBin1.{} == {'" + encodedBlobKey + "':100}",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(encodedBlobKey, 100))));
// integer values are read as long
- translateAndCompare("$.mapBin1.get(type: MAP) == {100:200, 300:400}",
+ parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {100:200, 300:400}",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100L, 200L, 300L, 400L))));
- translateAndCompare("$.mapBin1.get(type: MAP) == {100:200, 300:400}",
+ parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {100:200, 300:400}",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf(100, 200, 300, 400))));
- translateAndCompare("$.mapBin1.get(type: MAP) == {'yes?':'yes!'}",
+ parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {'yes?':'yes!'}",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes?", "yes!"))));
- translateAndCompare("$.mapBin1.get(type: MAP) == {\"yes\" : \"yes\"}",
+ parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {\"yes\" : \"yes\"}",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes", "yes"))));
- translateAndCompare(
+ parseExpressionAndCompare(
"$.mapBin1.get(type: MAP) == {\"yes of course\" : \"yes of course\"}",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes of course", "yes of course"))));
- translateAndCompare("$.mapBin1.get(type: MAP) == {\"yes\" : [\"yes\", \"of course\"]}",
+ parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {\"yes\" : [\"yes\", \"of course\"]}",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes", List.of("yes", "of course")))));
}
@@ -225,14 +225,14 @@ void mapComparison_constantOnRightSide() {
void mapComparison_constantOnRightSide_NegativeTest() {
// A String constant must be quoted
assertThatThrownBy(() ->
- translateAndCompare("$.mapBin1.get(type: MAP) == {yes, of course}",
+ parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {yes, of course}",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("yes", "of course"))))
)
.isInstanceOf(AerospikeDSLException.class)
.hasMessage("Unable to parse map operand");
assertThatThrownBy(() ->
- translateAndCompare("$.mapBin1.get(type: MAP) == ['yes', 'of course']",
+ parseExpressionAndCompare("$.mapBin1.get(type: MAP) == ['yes', 'of course']",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(List.of("yes", "of course"))))
)
.isInstanceOf(AerospikeDSLException.class)
@@ -240,7 +240,7 @@ void mapComparison_constantOnRightSide_NegativeTest() {
// Map key can only be Integer or String
assertThatThrownBy(() ->
- translateAndCompare("$.mapBin1.get(type: MAP) == {[100]:[100]}",
+ parseExpressionAndCompare("$.mapBin1.get(type: MAP) == {[100]:[100]}",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(List.of("yes", "of course"))))
)
.isInstanceOf(AerospikeDSLException.class)
@@ -250,39 +250,39 @@ void mapComparison_constantOnRightSide_NegativeTest() {
@Test
void mapComparison_constantOnLeftSide() {
// Prerequisite for comparing maps: both sides must be ordered maps
- translateAndCompare("{100:100} == $.mapBin1.get(type: MAP)",
+ parseExpressionAndCompare("{100:100} == $.mapBin1.get(type: MAP)",
Exp.eq(Exp.val(treeMapOf(100, 100)), Exp.mapBin("mapBin1")));
- translateAndCompare("{100 : 100} == $.mapBin1.get(type: MAP)",
+ parseExpressionAndCompare("{100 : 100} == $.mapBin1.get(type: MAP)",
Exp.eq(Exp.val(treeMapOf(100, 100)), Exp.mapBin("mapBin1")));
- translateAndCompare("{100:100} == $.mapBin1.{}",
+ parseExpressionAndCompare("{100:100} == $.mapBin1.{}",
Exp.eq(Exp.val(treeMapOf(100, 100)), Exp.mapBin("mapBin1")));
byte[] blobKey = new byte[]{1, 2, 3};
String encodedBlobKey = Base64.getEncoder().encodeToString(blobKey);
// encoded blob key must be quoted as it is a String
- translateAndCompare("{'" + encodedBlobKey + "':100} == $.mapBin1.{}",
+ parseExpressionAndCompare("{'" + encodedBlobKey + "':100} == $.mapBin1.{}",
Exp.eq(Exp.val(treeMapOf(encodedBlobKey, 100)), Exp.mapBin("mapBin1")));
// integer values are read as long
- translateAndCompare("{100:200, 300:400} == $.mapBin1.get(type: MAP)",
+ parseExpressionAndCompare("{100:200, 300:400} == $.mapBin1.get(type: MAP)",
Exp.eq(Exp.val(treeMapOf(100L, 200L, 300L, 400L)), Exp.mapBin("mapBin1")));
- translateAndCompare("{100:200, 300:400} == $.mapBin1.get(type: MAP)",
+ parseExpressionAndCompare("{100:200, 300:400} == $.mapBin1.get(type: MAP)",
Exp.eq(Exp.val(treeMapOf(100, 200, 300, 400)), Exp.mapBin("mapBin1")));
- translateAndCompare("{'yes?':'yes!'} == $.mapBin1.get(type: MAP)",
+ parseExpressionAndCompare("{'yes?':'yes!'} == $.mapBin1.get(type: MAP)",
Exp.eq(Exp.val(treeMapOf("yes?", "yes!")), Exp.mapBin("mapBin1")));
- translateAndCompare("{\"yes\" : \"yes\"} == $.mapBin1.get(type: MAP)",
+ parseExpressionAndCompare("{\"yes\" : \"yes\"} == $.mapBin1.get(type: MAP)",
Exp.eq(Exp.val(treeMapOf("yes", "yes")), Exp.mapBin("mapBin1")));
- translateAndCompare(
+ parseExpressionAndCompare(
"{\"yes of course\" : \"yes of course\"} == $.mapBin1.get(type: MAP)",
Exp.eq(Exp.val(treeMapOf("yes of course", "yes of course")), Exp.mapBin("mapBin1")));
- translateAndCompare("{\"yes\" : [\"yes\", \"of course\"]} == $.mapBin1.get(type: MAP)",
+ parseExpressionAndCompare("{\"yes\" : [\"yes\", \"of course\"]} == $.mapBin1.get(type: MAP)",
Exp.eq(Exp.val(treeMapOf("yes", List.of("yes", "of course"))), Exp.mapBin("mapBin1")));
}
@@ -290,14 +290,14 @@ void mapComparison_constantOnLeftSide() {
void mapComparison_constantOnLeftSide_NegativeTest() {
// A String constant must be quoted
assertThatThrownBy(() ->
- translateAndCompare("{yes, of course} == $.mapBin1.get(type: MAP)",
+ parseExpressionAndCompare("{yes, of course} == $.mapBin1.get(type: MAP)",
Exp.eq(Exp.mapBin("mapBin1"), Exp.val(treeMapOf("of course", "yes"))))
)
.isInstanceOf(AerospikeDSLException.class)
.hasMessage("Could not parse given input, wrong syntax");
assertThatThrownBy(() ->
- translateAndCompare("['yes', 'of course'] == $.mapBin1.get(type: MAP)", // incorrect: must be {}
+ parseExpressionAndCompare("['yes', 'of course'] == $.mapBin1.get(type: MAP)", // incorrect: must be {}
Exp.eq(Exp.val(List.of("yes", "of course")), Exp.mapBin("mapBin1")))
)
.isInstanceOf(AerospikeDSLException.class)
@@ -305,7 +305,7 @@ void mapComparison_constantOnLeftSide_NegativeTest() {
// Map key can only be Integer or String
assertThatThrownBy(() ->
- translateAndCompare("{[100]:[100]} == $.mapBin1.get(type: MAP)",
+ parseExpressionAndCompare("{[100]:[100]} == $.mapBin1.get(type: MAP)",
Exp.eq(Exp.val(List.of("yes", "of course")), Exp.mapBin("mapBin1")))
)
.isInstanceOf(AerospikeDSLException.class)
@@ -314,44 +314,44 @@ void mapComparison_constantOnLeftSide_NegativeTest() {
@Test
void twoStringBinsComparison() {
- translateAndCompare("$.stringBin1.get(type: STRING) == $.stringBin2.get(type: STRING)",
+ parseExpressionAndCompare("$.stringBin1.get(type: STRING) == $.stringBin2.get(type: STRING)",
Exp.eq(Exp.stringBin("stringBin1"), Exp.stringBin("stringBin2")));
}
@Test
void twoIntegerBinsComparison() {
- translateAndCompare("$.intBin1.get(type: INT) == $.intBin2.get(type: INT)",
+ parseExpressionAndCompare("$.intBin1.get(type: INT) == $.intBin2.get(type: INT)",
Exp.eq(Exp.intBin("intBin1"), Exp.intBin("intBin2")));
}
@Test
void twoFloatBinsComparison() {
- translateAndCompare("$.floatBin1.get(type: FLOAT) == $.floatBin2.get(type: FLOAT)",
+ parseExpressionAndCompare("$.floatBin1.get(type: FLOAT) == $.floatBin2.get(type: FLOAT)",
Exp.eq(Exp.floatBin("floatBin1"), Exp.floatBin("floatBin2")));
}
@Test
void twoBlobBinsComparison() {
- translateAndCompare("$.blobBin1.get(type: BLOB) == $.blobBin2.get(type: BLOB)",
+ parseExpressionAndCompare("$.blobBin1.get(type: BLOB) == $.blobBin2.get(type: BLOB)",
Exp.eq(Exp.blobBin("blobBin1"), Exp.blobBin("blobBin2")));
}
@Test
void negativeTwoDifferentBinTypesComparison() {
- assertThatThrownBy(() -> translate("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)"))
+ assertThatThrownBy(() -> parseExpression("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)"))
.isInstanceOf(AerospikeDSLException.class)
.hasMessageContaining("Cannot compare STRING to FLOAT");
}
@Test
void secondDegreeExplicitFloat() {
- translateAndCompare("($.apples.get(type: FLOAT) + $.bananas.get(type: FLOAT)) > 10.5",
+ parseExpressionAndCompare("($.apples.get(type: FLOAT) + $.bananas.get(type: FLOAT)) > 10.5",
Exp.gt(Exp.add(Exp.floatBin("apples"), Exp.floatBin("bananas")), Exp.val(10.5)));
}
@Test
void forthDegreeComplicatedExplicitFloat() {
- translateAndCompare("(($.apples.get(type: FLOAT) + $.bananas.get(type: FLOAT))" +
+ parseExpressionAndCompare("(($.apples.get(type: FLOAT) + $.bananas.get(type: FLOAT))" +
" + ($.oranges.get(type: FLOAT) + $.acai.get(type: FLOAT))) > 10.5",
Exp.gt(
Exp.add(
@@ -382,7 +382,7 @@ void complicatedWhenExplicitTypeIntDefault() {
)
);
- translateAndCompare("$.a.get(type: INT) == " +
+ parseExpressionAndCompare("$.a.get(type: INT) == " +
"(when($.b.get(type: INT) == 1 => $.a1.get(type: INT)," +
" $.b.get(type: INT) == 2 => $.a2.get(type: INT)," +
" $.b.get(type: INT) == 3 => $.a3.get(type: INT)," +
@@ -411,7 +411,7 @@ void complicatedWhenExplicitTypeString() {
)
);
- translateAndCompare("$.a.get(type: STRING) == " +
+ parseExpressionAndCompare("$.a.get(type: STRING) == " +
"(when($.b == 1 => $.a1.get(type: STRING)," +
" $.b == 2 => $.a2.get(type: STRING)," +
" $.b == 3 => $.a3.get(type: STRING)," +
diff --git a/src/test/java/com/aerospike/dsl/ImplicitTypesTests.java b/src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java
similarity index 75%
rename from src/test/java/com/aerospike/dsl/ImplicitTypesTests.java
rename to src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java
index fe3de74..641f6aa 100644
--- a/src/test/java/com/aerospike/dsl/ImplicitTypesTests.java
+++ b/src/test/java/com/aerospike/dsl/expression/ImplicitTypesTests.java
@@ -1,25 +1,25 @@
-package com.aerospike.dsl;
+package com.aerospike.dsl.expression;
import com.aerospike.client.exp.Exp;
import org.junit.jupiter.api.Test;
-import static com.aerospike.dsl.util.TestUtils.translateAndCompare;
+import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare;
public class ImplicitTypesTests {
@Test
void floatComparison() {
- translateAndCompare("$.floatBin1 >= 100.25",
+ parseExpressionAndCompare("$.floatBin1 >= 100.25",
Exp.ge(Exp.floatBin("floatBin1"), Exp.val(100.25)));
}
@Test
void booleanComparison() {
- translateAndCompare("$.boolBin1 == true",
+ parseExpressionAndCompare("$.boolBin1 == true",
Exp.eq(Exp.boolBin("boolBin1"), Exp.val(true)));
- translateAndCompare("false == $.boolBin1",
+ parseExpressionAndCompare("false == $.boolBin1",
Exp.eq(Exp.val(false), Exp.boolBin("boolBin1")));
- translateAndCompare("$.boolBin1 != false",
+ parseExpressionAndCompare("$.boolBin1 != false",
Exp.ne(Exp.boolBin("boolBin1"), Exp.val(false)));
}
@@ -27,31 +27,31 @@ void booleanComparison() {
// this can also be an expression that evaluates to a boolean result
@Test
void binBooleanImplicitLogicalComparison() {
- translateAndCompare("$.boolBin1 and $.boolBin2",
+ parseExpressionAndCompare("$.boolBin1 and $.boolBin2",
Exp.and(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2")));
- translateAndCompare("$.boolBin1 or $.boolBin2",
+ parseExpressionAndCompare("$.boolBin1 or $.boolBin2",
Exp.or(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2")));
- translateAndCompare("not($.boolBin1)",
+ parseExpressionAndCompare("not($.boolBin1)",
Exp.not(Exp.boolBin("boolBin1")));
- translateAndCompare("exclusive($.boolBin1, $.boolBin2)",
+ parseExpressionAndCompare("exclusive($.boolBin1, $.boolBin2)",
Exp.exclusive(Exp.boolBin("boolBin1"), Exp.boolBin("boolBin2")));
}
@Test
void implicitDefaultIntComparison() {
- translateAndCompare("$.intBin1 < $.intBin2",
+ parseExpressionAndCompare("$.intBin1 < $.intBin2",
Exp.lt(Exp.intBin("intBin1"), Exp.intBin("intBin2")));
}
@Test
void secondDegreeImplicitCastingFloat() {
- translateAndCompare("($.apples + $.bananas) > 10.5",
+ parseExpressionAndCompare("($.apples + $.bananas) > 10.5",
Exp.gt(Exp.add(Exp.floatBin("apples"), Exp.floatBin("bananas")), Exp.val(10.5)));
}
@Test
void secondDegreeComplicatedFloatFirstImplicitCastingFloat() {
- translateAndCompare("($.apples + $.bananas) > 10.5 and ($.oranges + $.grapes) <= 5",
+ parseExpressionAndCompare("($.apples + $.bananas) > 10.5 and ($.oranges + $.grapes) <= 5",
Exp.and(
Exp.gt(Exp.add(Exp.floatBin("apples"), Exp.floatBin("bananas")), Exp.val(10.5)),
Exp.le(Exp.add(Exp.intBin("oranges"), Exp.intBin("grapes")), Exp.val(5)))
@@ -60,7 +60,7 @@ void secondDegreeComplicatedFloatFirstImplicitCastingFloat() {
@Test
void secondDegreeComplicatedIntFirstImplicitCastingFloat() {
- translateAndCompare("($.apples + $.bananas) > 5 and ($.oranges + $.grapes) <= 10.5",
+ parseExpressionAndCompare("($.apples + $.bananas) > 5 and ($.oranges + $.grapes) <= 10.5",
Exp.and(
Exp.gt(Exp.add(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.val(5)),
Exp.le(Exp.add(Exp.floatBin("oranges"), Exp.floatBin("grapes")), Exp.val(10.5)))
@@ -69,7 +69,7 @@ void secondDegreeComplicatedIntFirstImplicitCastingFloat() {
@Test
void thirdDegreeComplicatedDefaultInt() {
- translateAndCompare("(($.apples + $.bananas) + $.oranges) > 10",
+ parseExpressionAndCompare("(($.apples + $.bananas) + $.oranges) > 10",
Exp.gt(
Exp.add(Exp.add(Exp.intBin("apples"), Exp.intBin("bananas")), Exp.intBin("oranges")),
Exp.val(10))
@@ -78,7 +78,7 @@ void thirdDegreeComplicatedDefaultInt() {
@Test
void thirdDegreeComplicatedImplicitCastingFloat() {
- translateAndCompare("(($.apples + $.bananas) + $.oranges) > 10.5",
+ parseExpressionAndCompare("(($.apples + $.bananas) + $.oranges) > 10.5",
Exp.gt(
Exp.add(Exp.add(Exp.floatBin("apples"), Exp.floatBin("bananas")), Exp.floatBin("oranges")),
Exp.val(10.5))
@@ -87,7 +87,7 @@ void thirdDegreeComplicatedImplicitCastingFloat() {
@Test
void forthDegreeComplicatedDefaultInt() {
- translateAndCompare("(($.apples + $.bananas) + ($.oranges + $.acai)) > 10",
+ parseExpressionAndCompare("(($.apples + $.bananas) + ($.oranges + $.acai)) > 10",
Exp.gt(
Exp.add(
Exp.add(Exp.intBin("apples"), Exp.intBin("bananas")),
@@ -98,7 +98,7 @@ void forthDegreeComplicatedDefaultInt() {
@Test
void forthDegreeComplicatedImplicitCastingFloat() {
- translateAndCompare("(($.apples + $.bananas) + ($.oranges + $.acai)) > 10.5",
+ parseExpressionAndCompare("(($.apples + $.bananas) + ($.oranges + $.acai)) > 10.5",
Exp.gt(
Exp.add(
Exp.add(Exp.floatBin("apples"), Exp.floatBin("bananas")),
@@ -128,7 +128,7 @@ void complicatedWhenImplicitTypeInt() {
)
);
- translateAndCompare("$.a == (when($.b == 1 => $.a1, $.b == 2 => $.a2, $.b == 3 => $.a3, default => $.a4+1))",
+ parseExpressionAndCompare("$.a == (when($.b == 1 => $.a1, $.b == 2 => $.a2, $.b == 3 => $.a3, default => $.a4+1))",
expected);
}
@@ -154,7 +154,7 @@ void complicatedWhenImplicitTypeString() {
)
);
- translateAndCompare("$.a == (when($.b == 1 => $.a1, $.b == 2 => $.a2, $.b == 3 => $.a3, default => \"hello\"))",
+ parseExpressionAndCompare("$.a == (when($.b == 1 => $.a1, $.b == 2 => $.a2, $.b == 3 => $.a3, default => \"hello\"))",
expected);
}
}
diff --git a/src/test/java/com/aerospike/dsl/ListExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java
similarity index 69%
rename from src/test/java/com/aerospike/dsl/ListExpressionsTests.java
rename to src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java
index 45b2c93..fa6f36c 100644
--- a/src/test/java/com/aerospike/dsl/ListExpressionsTests.java
+++ b/src/test/java/com/aerospike/dsl/expression/ListExpressionsTests.java
@@ -1,4 +1,4 @@
-package com.aerospike.dsl;
+package com.aerospike.dsl.expression;
import com.aerospike.client.cdt.CTX;
import com.aerospike.client.cdt.ListReturnType;
@@ -9,8 +9,8 @@
import java.util.List;
-import static com.aerospike.dsl.util.TestUtils.translate;
-import static com.aerospike.dsl.util.TestUtils.translateAndCompare;
+import static com.aerospike.dsl.util.TestUtils.parseExpression;
+import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
class ListExpressionsTests {
@@ -26,10 +26,10 @@ void listByIndexInteger() {
),
Exp.val(100));
// Implicit detect as Int
- translateAndCompare("$.listBin1.[0] == 100", expected);
- translateAndCompare("$.listBin1.[0].get(type: INT) == 100", expected);
- translateAndCompare("$.listBin1.[0].get(type: INT, return: VALUE) == 100", expected);
- translateAndCompare("$.listBin1.[0].asInt() == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[0] == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[0].get(type: INT) == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[0].get(type: INT, return: VALUE) == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[0].asInt() == 100", expected);
}
@Test
@@ -43,9 +43,9 @@ void listByIndexOtherTypes() {
),
Exp.val("stringVal"));
// Implicit detect as string
- translateAndCompare("$.listBin1.[0] == \"stringVal\"", expected);
- translateAndCompare("$.listBin1.[0].get(type: STRING) == \"stringVal\"", expected);
- translateAndCompare("$.listBin1.[0].get(type: STRING, return: VALUE) == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.listBin1.[0] == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.listBin1.[0].get(type: STRING) == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.listBin1.[0].get(type: STRING, return: VALUE) == \"stringVal\"", expected);
expected = Exp.eq(
ListExp.getByIndex(
@@ -56,9 +56,9 @@ void listByIndexOtherTypes() {
),
Exp.val(true));
// Implicit detect as boolean
- translateAndCompare("$.listBin1.[0] == true", expected);
- translateAndCompare("$.listBin1.[0].get(type: BOOL) == true", expected);
- translateAndCompare("$.listBin1.[0].get(type: BOOL, return: VALUE) == true", expected);
+ parseExpressionAndCompare("$.listBin1.[0] == true", expected);
+ parseExpressionAndCompare("$.listBin1.[0].get(type: BOOL) == true", expected);
+ parseExpressionAndCompare("$.listBin1.[0].get(type: BOOL, return: VALUE) == true", expected);
}
@Test
@@ -70,10 +70,10 @@ void listByValue() {
Exp.listBin("listBin1")
),
Exp.val(100));
- translateAndCompare("$.listBin1.[=100] == 100", expected);
- translateAndCompare("$.listBin1.[=100].get(type: INT) == 100", expected);
- translateAndCompare("$.listBin1.[=100].get(type: INT, return: VALUE) == 100", expected);
- translateAndCompare("$.listBin1.[=100].asInt() == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[=100] == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[=100].get(type: INT) == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[=100].get(type: INT, return: VALUE) == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[=100].asInt() == 100", expected);
}
@Test
@@ -84,8 +84,8 @@ void listByValueCount() {
Exp.listBin("listBin1")),
Exp.val(0)
);
- translateAndCompare("$.listBin1.[=100].count() > 0", expected);
- translateAndCompare("$.listBin1.[=100].[].count() > 0", expected);
+ parseExpressionAndCompare("$.listBin1.[=100].count() > 0", expected);
+ parseExpressionAndCompare("$.listBin1.[=100].[].count() > 0", expected);
}
@Test
@@ -98,10 +98,10 @@ void listByRank() {
Exp.listBin("listBin1")
),
Exp.val(100));
- translateAndCompare("$.listBin1.[#-1] == 100", expected);
- translateAndCompare("$.listBin1.[#-1].get(type: INT) == 100", expected);
- translateAndCompare("$.listBin1.[#-1].get(type: INT, return: VALUE) == 100", expected);
- translateAndCompare("$.listBin1.[#-1].asInt() == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[#-1] == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[#-1].get(type: INT) == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[#-1].get(type: INT, return: VALUE) == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[#-1].asInt() == 100", expected);
}
@Test
@@ -116,9 +116,9 @@ void listBinElementEquals_Nested() {
CTX.listIndex(0)
),
Exp.val(100));
- translateAndCompare("$.listBin1.[0].[0].[0] == 100", expected);
- translateAndCompare("$.listBin1.[0].[0].[0].get(type: INT) == 100", expected);
- translateAndCompare("$.listBin1.[0].[0].[0].get(type: INT, return: VALUE) == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[0].[0].[0] == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[0].[0].[0].get(type: INT) == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[0].[0].[0].get(type: INT, return: VALUE) == 100", expected);
}
@Test
@@ -126,10 +126,10 @@ void listSize() {
Exp expected = Exp.eq(
ListExp.size(Exp.listBin("listBin1")),
Exp.val(1));
- translateAndCompare("$.listBin1.[].count() == 1", expected);
+ parseExpressionAndCompare("$.listBin1.[].count() == 1", expected);
// the default behaviour for count() without List '[]' or Map '{}' designators is List
- translateAndCompare("$.listBin1.count() == 1", expected);
+ parseExpressionAndCompare("$.listBin1.count() == 1", expected);
}
@Test
@@ -143,10 +143,10 @@ void nestedListSize() {
Exp.listBin("listBin1"))
),
Exp.val(100));
- translateAndCompare("$.listBin1.[1].[].count() == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[1].[].count() == 100", expected);
// the default behaviour for count() without List '[]' or Map '{}' designators is List
- translateAndCompare("$.listBin1.[1].count() == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[1].count() == 100", expected);
}
@@ -162,10 +162,10 @@ void nestedListSizeWithContext() {
CTX.listIndex(1))
),
Exp.val(100));
- translateAndCompare("$.listBin1.[1].[2].[].count() == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[1].[2].[].count() == 100", expected);
// the default behaviour for count() without List '[]' or Map '{}' designators is List
- translateAndCompare("$.listBin1.[1].[2].count() == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[1].[2].count() == 100", expected);
}
@Test
@@ -179,7 +179,7 @@ void nestedLists() {
CTX.listIndex(5)
),
Exp.val("stringVal"));
- translateAndCompare("$.listBin1.[5].[1].get(type: STRING) == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.listBin1.[5].[1].get(type: STRING) == \"stringVal\"", expected);
}
@Test
@@ -195,8 +195,8 @@ void nestedListsWithDifferentContextTypes() {
),
Exp.val("stringVal"));
// Implicit detect as String
- translateAndCompare("$.listBin1.[5].[#-1] == \"stringVal\"", expected);
- translateAndCompare("$.listBin1.[5].[#-1].get(type: STRING) == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.listBin1.[5].[#-1] == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.listBin1.[5].[#-1].get(type: STRING) == \"stringVal\"", expected);
// Nested List Rank Value
expected = Exp.eq(
@@ -209,7 +209,7 @@ void nestedListsWithDifferentContextTypes() {
),
Exp.val(200));
// Implicit detect as Int
- translateAndCompare("$.listBin1.[5].[#-1].[=100] == 200", expected);
+ parseExpressionAndCompare("$.listBin1.[5].[#-1].[=100] == 200", expected);
}
@Test
@@ -223,21 +223,21 @@ void listBinElementCount() {
),
Exp.val(100)
);
- translateAndCompare("$.listBin1.[0].count() == 100", expected);
- translateAndCompare("$.listBin1.[0].[].count() == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[0].count() == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[0].[].count() == 100", expected);
}
@Test
void negativeSyntaxList() {
// TODO: throw meaningful exception (by ANTLR?)
- assertThatThrownBy(() -> translate("$.listBin1.[stringValue] == 100"))
+ assertThatThrownBy(() -> parseExpression("$.listBin1.[stringValue] == 100"))
.isInstanceOf(AerospikeDSLException.class);
}
//@Test
void negativeTypeComparisonList() {
// TODO: should fail? Exp is successfully created but comparing int to a string value (validations on List)
- assertThatThrownBy(() -> translate("$.listBin1.[#-1].get(type: INT) == \"stringValue\""))
+ assertThatThrownBy(() -> parseExpression("$.listBin1.[#-1].get(type: INT) == \"stringValue\""))
.isInstanceOf(NullPointerException.class);
}
@@ -248,7 +248,7 @@ void listIndexRange() {
Exp.val(1),
Exp.val(2),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[1:3]", expected);
+ parseExpressionAndCompare("$.listBin1.[1:3]", expected);
// Negative
expected = ListExp.getByIndexRange(
@@ -256,7 +256,7 @@ void listIndexRange() {
Exp.val(-3),
Exp.val(4),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[-3:1]", expected);
+ parseExpressionAndCompare("$.listBin1.[-3:1]", expected);
// Inverted
expected = ListExp.getByIndexRange(
@@ -264,14 +264,14 @@ void listIndexRange() {
Exp.val(2),
Exp.val(2),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[!2:4]", expected);
+ parseExpressionAndCompare("$.listBin1.[!2:4]", expected);
// From start till the end
expected = ListExp.getByIndexRange(
ListReturnType.VALUE,
Exp.val(1),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[1:]", expected);
+ parseExpressionAndCompare("$.listBin1.[1:]", expected);
}
@Test
@@ -280,23 +280,23 @@ void listValueList() {
ListReturnType.VALUE,
Exp.val(List.of("a", "b", "c")),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[=a,b,c]", expected);
- translateAndCompare("$.listBin1.[=\"a\",\"b\",\"c\"]", expected);
+ parseExpressionAndCompare("$.listBin1.[=a,b,c]", expected);
+ parseExpressionAndCompare("$.listBin1.[=\"a\",\"b\",\"c\"]", expected);
// Integer
expected = ListExp.getByValueList(
ListReturnType.VALUE,
Exp.val(List.of(1, 2, 3)),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[=1,2,3]", expected);
+ parseExpressionAndCompare("$.listBin1.[=1,2,3]", expected);
// Inverted
expected = ListExp.getByValueList(
ListReturnType.VALUE | ListReturnType.INVERTED,
Exp.val(List.of("a", "b", "c")),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[!=a,b,c]", expected);
- translateAndCompare("$.listBin1.[!=\"a\",\"b\",\"c\"]", expected);
+ parseExpressionAndCompare("$.listBin1.[!=a,b,c]", expected);
+ parseExpressionAndCompare("$.listBin1.[!=\"a\",\"b\",\"c\"]", expected);
}
@Test
@@ -307,7 +307,7 @@ void listValueRange() {
Exp.val(111),
Exp.val(334),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[=111:334]", expected);
+ parseExpressionAndCompare("$.listBin1.[=111:334]", expected);
// Inverted
expected = ListExp.getByValueRange(
@@ -315,7 +315,7 @@ void listValueRange() {
Exp.val(10),
Exp.val(20),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[!=10:20]", expected);
+ parseExpressionAndCompare("$.listBin1.[!=10:20]", expected);
// From start till the end
expected = ListExp.getByValueRange(
@@ -323,7 +323,7 @@ void listValueRange() {
Exp.val(111),
null,
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[=111:]", expected);
+ parseExpressionAndCompare("$.listBin1.[=111:]", expected);
}
@Test
@@ -333,7 +333,7 @@ void listRankRange() {
Exp.val(0),
Exp.val(3),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[#0:3]", expected);
+ parseExpressionAndCompare("$.listBin1.[#0:3]", expected);
// Inverted
expected = ListExp.getByRankRange(
@@ -341,14 +341,14 @@ void listRankRange() {
Exp.val(0),
Exp.val(3),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[!#0:3]", expected);
+ parseExpressionAndCompare("$.listBin1.[!#0:3]", expected);
// From start till the end
expected = ListExp.getByRankRange(
ListReturnType.VALUE,
Exp.val(-3),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[#-3:]", expected);
+ parseExpressionAndCompare("$.listBin1.[#-3:]", expected);
// From start till the end with context
expected = ListExp.getByRankRange(
@@ -356,7 +356,7 @@ void listRankRange() {
Exp.val(-3),
Exp.listBin("listBin1"),
CTX.listIndex(5));
- translateAndCompare("$.listBin1.[5].[#-3:]", expected);
+ parseExpressionAndCompare("$.listBin1.[5].[#-3:]", expected);
}
@Test
@@ -367,7 +367,7 @@ void listRankRangeRelative() {
Exp.val("b"),
Exp.val(2),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[#-3:-1~b]", expected);
+ parseExpressionAndCompare("$.listBin1.[#-3:-1~b]", expected);
// Inverted
expected = ListExp.getByValueRelativeRankRange(
@@ -376,7 +376,7 @@ void listRankRangeRelative() {
Exp.val("b"),
Exp.val(2),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[!#-3:-1~b]", expected);
+ parseExpressionAndCompare("$.listBin1.[!#-3:-1~b]", expected);
// From start till the end
expected = ListExp.getByValueRelativeRankRange(
@@ -384,7 +384,7 @@ void listRankRangeRelative() {
Exp.val(-3),
Exp.val("b"),
Exp.listBin("listBin1"));
- translateAndCompare("$.listBin1.[#-3:~b]", expected);
+ parseExpressionAndCompare("$.listBin1.[#-3:~b]", expected);
}
@Test
@@ -398,7 +398,7 @@ void listReturnTypes() {
),
Exp.val(5));
// Implicit detect as Int
- translateAndCompare("$.listBin1.[0].get(return: COUNT) == 5", expected);
+ parseExpressionAndCompare("$.listBin1.[0].get(return: COUNT) == 5", expected);
expected = Exp.eq(
ListExp.getByIndex(
@@ -409,7 +409,7 @@ void listReturnTypes() {
),
Exp.val(true));
// Implicit detect as Int
- translateAndCompare("$.listBin1.[0].get(return: EXISTS) == true", expected);
+ parseExpressionAndCompare("$.listBin1.[0].get(return: EXISTS) == true", expected);
expected = Exp.eq(
ListExp.getByIndex(
@@ -420,6 +420,6 @@ void listReturnTypes() {
),
Exp.val(1));
// Implicit detect as Int
- translateAndCompare("$.listBin1.[0].get(return: INDEX) == 1", expected);
+ parseExpressionAndCompare("$.listBin1.[0].get(return: INDEX) == 1", expected);
}
}
diff --git a/src/test/java/com/aerospike/dsl/LogicalExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java
similarity index 67%
rename from src/test/java/com/aerospike/dsl/LogicalExpressionsTests.java
rename to src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java
index c0f8f97..28a7b86 100644
--- a/src/test/java/com/aerospike/dsl/LogicalExpressionsTests.java
+++ b/src/test/java/com/aerospike/dsl/expression/LogicalExpressionsTests.java
@@ -1,12 +1,12 @@
-package com.aerospike.dsl;
+package com.aerospike.dsl.expression;
import com.aerospike.client.exp.Exp;
import com.aerospike.dsl.exception.AerospikeDSLException;
import org.junit.jupiter.api.Test;
import org.opentest4j.AssertionFailedError;
-import static com.aerospike.dsl.util.TestUtils.translate;
-import static com.aerospike.dsl.util.TestUtils.translateAndCompare;
+import static com.aerospike.dsl.util.TestUtils.parseExpression;
+import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class LogicalExpressionsTests {
@@ -15,7 +15,7 @@ public class LogicalExpressionsTests {
void binLogicalAndOrCombinations() {
Exp expected1 = Exp.and(Exp.gt(Exp.intBin("intBin1"), Exp.val(100)),
Exp.gt(Exp.intBin("intBin2"), Exp.val(100)));
- translateAndCompare("$.intBin1 > 100 and $.intBin2 > 100", expected1);
+ parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100", expected1);
Exp expected2 = Exp.or(
Exp.and(
@@ -25,8 +25,8 @@ void binLogicalAndOrCombinations() {
Exp.lt(Exp.intBin("intBin3"), Exp.val(100))
);
// TODO: what should be the default behaviour with no parentheses?
- translateAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 < 100", expected2);
- translateAndCompare("($.intBin1 > 100 and $.intBin2 > 100) or $.intBin3 < 100", expected2);
+ parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 or $.intBin3 < 100", expected2);
+ parseExpressionAndCompare("($.intBin1 > 100 and $.intBin2 > 100) or $.intBin3 < 100", expected2);
Exp expected3 = Exp.and(
Exp.gt(Exp.intBin("intBin1"), Exp.val(100)),
@@ -35,27 +35,27 @@ void binLogicalAndOrCombinations() {
Exp.lt(Exp.intBin("intBin3"), Exp.val(100))
)
);
- translateAndCompare("($.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 < 100))", expected3);
+ parseExpressionAndCompare("($.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 < 100))", expected3);
// check that parentheses make difference
- assertThatThrownBy(() -> translateAndCompare("($.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 < 100))", expected2))
+ assertThatThrownBy(() -> parseExpressionAndCompare("($.intBin1 > 100 and ($.intBin2 > 100 or $.intBin3 < 100))", expected2))
.isInstanceOf(AssertionFailedError.class);
}
@Test
void logicalNot() {
- translateAndCompare("not($.keyExists())", Exp.not(Exp.keyExists()));
+ parseExpressionAndCompare("not($.keyExists())", Exp.not(Exp.keyExists()));
}
@Test
void binLogicalExclusive() {
- translateAndCompare("exclusive($.hand == \"hook\", $.leg == \"peg\")",
+ parseExpressionAndCompare("exclusive($.hand == \"hook\", $.leg == \"peg\")",
Exp.exclusive(
Exp.eq(Exp.stringBin("hand"), Exp.val("hook")),
Exp.eq(Exp.stringBin("leg"), Exp.val("peg"))));
// More than 2 expressions exclusive
- translateAndCompare("exclusive($.a == \"aVal\", $.b == \"bVal\", $.c == \"cVal\", $.d == 4)",
+ parseExpressionAndCompare("exclusive($.a == \"aVal\", $.b == \"bVal\", $.c == \"cVal\", $.d == 4)",
Exp.exclusive(
Exp.eq(Exp.stringBin("a"), Exp.val("aVal")),
Exp.eq(Exp.stringBin("b"), Exp.val("bVal")),
@@ -66,7 +66,7 @@ void binLogicalExclusive() {
//TODO: FMWK-488
//@Test
void flatHierarchyAnd() {
- translateAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 < 100",
+ parseExpressionAndCompare("$.intBin1 > 100 and $.intBin2 > 100 and $.intBin3 < 100",
Exp.and(
Exp.gt(
Exp.intBin("intBin1"),
@@ -81,26 +81,26 @@ void flatHierarchyAnd() {
@Test
void negativeSyntaxLogicalOperators() {
- assertThatThrownBy(() -> translate("($.intBin1 > 100 and ($.intBin2 > 100) or"))
+ assertThatThrownBy(() -> parseExpression("($.intBin1 > 100 and ($.intBin2 > 100) or"))
.isInstanceOf(AerospikeDSLException.class)
.hasMessageContaining("Could not parse given input");
- assertThatThrownBy(() -> translate("and ($.intBin1 > 100 and ($.intBin2 > 100)"))
+ assertThatThrownBy(() -> parseExpression("and ($.intBin1 > 100 and ($.intBin2 > 100)"))
.isInstanceOf(AerospikeDSLException.class)
.hasMessageContaining("Could not parse given input");
- assertThatThrownBy(() -> translate("($.intBin1 > 100 and ($.intBin2 > 100) not"))
+ assertThatThrownBy(() -> parseExpression("($.intBin1 > 100 and ($.intBin2 > 100) not"))
.isInstanceOf(AerospikeDSLException.class)
.hasMessageContaining("Could not parse given input");
- assertThatThrownBy(() -> translate("($.intBin1 > 100 and ($.intBin2 > 100) exclusive"))
+ assertThatThrownBy(() -> parseExpression("($.intBin1 > 100 and ($.intBin2 > 100) exclusive"))
.isInstanceOf(AerospikeDSLException.class)
.hasMessageContaining("Could not parse given input");
}
@Test
void negativeBinLogicalExclusiveWithOneParam() {
- assertThatThrownBy(() -> translateAndCompare("exclusive($.hand == \"hook\")",
+ assertThatThrownBy(() -> parseExpressionAndCompare("exclusive($.hand == \"hook\")",
Exp.exclusive(
Exp.eq(Exp.stringBin("hand"), Exp.val("hook")))))
.isInstanceOf(AerospikeDSLException.class)
diff --git a/src/test/java/com/aerospike/dsl/MapAndListExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/MapAndListExpressionsTests.java
similarity index 81%
rename from src/test/java/com/aerospike/dsl/MapAndListExpressionsTests.java
rename to src/test/java/com/aerospike/dsl/expression/MapAndListExpressionsTests.java
index 795b7a3..5bff0a5 100644
--- a/src/test/java/com/aerospike/dsl/MapAndListExpressionsTests.java
+++ b/src/test/java/com/aerospike/dsl/expression/MapAndListExpressionsTests.java
@@ -1,4 +1,4 @@
-package com.aerospike.dsl;
+package com.aerospike.dsl.expression;
import com.aerospike.client.Value;
import com.aerospike.client.cdt.CTX;
@@ -9,7 +9,7 @@
import com.aerospike.client.exp.MapExp;
import org.junit.jupiter.api.Test;
-import static com.aerospike.dsl.util.TestUtils.translateAndCompare;
+import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare;
public class MapAndListExpressionsTests {
@@ -24,7 +24,7 @@ void listInsideAMap() {
CTX.mapKey(Value.get("a"))
),
Exp.val(100));
- translateAndCompare("$.mapBin1.a.[0] == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.a.[0] == 100", expected);
expected = Exp.gt(
ListExp.getByIndex(
@@ -35,7 +35,7 @@ void listInsideAMap() {
CTX.mapKey(Value.get("a")),
CTX.mapKey(Value.get("cc"))
), Exp.val(100));
- translateAndCompare("$.mapBin1.a.cc.[2].get(type: INT) > 100", expected);
+ parseExpressionAndCompare("$.mapBin1.a.cc.[2].get(type: INT) > 100", expected);
}
@Test
@@ -50,7 +50,7 @@ void mapListList() {
CTX.listIndex(0)
),
Exp.val(100));
- translateAndCompare("$.mapBin1.a.[0].[0] == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.a.[0].[0] == 100", expected);
}
@Test
@@ -63,7 +63,7 @@ void mapInsideAList() {
Exp.listBin("listBin1"),
CTX.listIndex(2)
), Exp.val(100));
- translateAndCompare("$.listBin1.[2].cc.get(type: INT) > 100", expected);
+ parseExpressionAndCompare("$.listBin1.[2].cc.get(type: INT) > 100", expected);
}
@Test
@@ -77,8 +77,8 @@ void listMapMap() {
CTX.listIndex(2),
CTX.mapKey(Value.get("aa"))
), Exp.val(100));
- translateAndCompare("$.listBin1.[2].aa.cc > 100", expected);
- translateAndCompare("$.listBin1.[2].aa.cc.get(type: INT) > 100", expected);
+ parseExpressionAndCompare("$.listBin1.[2].aa.cc > 100", expected);
+ parseExpressionAndCompare("$.listBin1.[2].aa.cc.get(type: INT) > 100", expected);
}
@Test
@@ -93,7 +93,7 @@ void listMapList() {
CTX.mapKey(Value.get("a"))
),
Exp.val(100));
- translateAndCompare("$.listBin1.[1].a.[0] == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[1].a.[0] == 100", expected);
}
@Test
@@ -110,8 +110,8 @@ void listMapListSize() {
)
),
Exp.val(100));
- translateAndCompare("$.listBin1.[1].a.[0].count() == 100", expected);
- translateAndCompare("$.listBin1.[1].a.[0].[].count() == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[1].a.[0].count() == 100", expected);
+ parseExpressionAndCompare("$.listBin1.[1].a.[0].[].count() == 100", expected);
}
@Test
@@ -125,8 +125,8 @@ void mapListMap() {
CTX.mapKey(Value.get("a")),
CTX.listIndex(0)
), Exp.val(100));
- translateAndCompare("$.mapBin1.a.[0].cc > 100", expected);
- translateAndCompare("$.mapBin1.a.[0].cc.get(type: INT) > 100", expected);
+ parseExpressionAndCompare("$.mapBin1.a.[0].cc > 100", expected);
+ parseExpressionAndCompare("$.mapBin1.a.[0].cc.get(type: INT) > 100", expected);
}
//@Test
diff --git a/src/test/java/com/aerospike/dsl/MapExpressionsTests.java b/src/test/java/com/aerospike/dsl/expression/MapExpressionsTests.java
similarity index 69%
rename from src/test/java/com/aerospike/dsl/MapExpressionsTests.java
rename to src/test/java/com/aerospike/dsl/expression/MapExpressionsTests.java
index 120da08..68f36fb 100644
--- a/src/test/java/com/aerospike/dsl/MapExpressionsTests.java
+++ b/src/test/java/com/aerospike/dsl/expression/MapExpressionsTests.java
@@ -1,4 +1,4 @@
-package com.aerospike.dsl;
+package com.aerospike.dsl.expression;
import com.aerospike.client.Value;
import com.aerospike.client.cdt.CTX;
@@ -11,7 +11,7 @@
import java.util.List;
-import static com.aerospike.dsl.util.TestUtils.translateAndCompare;
+import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare;
public class MapExpressionsTests {
@@ -27,10 +27,10 @@ void mapOneLevelExpressions() {
),
Exp.val(200));
// Implicit detect as Int
- translateAndCompare("$.mapBin1.a == 200", expected);
- translateAndCompare("$.mapBin1.a.get(type: INT) == 200", expected);
- translateAndCompare("$.mapBin1.a.get(type: INT, return: VALUE) == 200", expected);
- translateAndCompare("$.mapBin1.a.asInt() == 200", expected);
+ parseExpressionAndCompare("$.mapBin1.a == 200", expected);
+ parseExpressionAndCompare("$.mapBin1.a.get(type: INT) == 200", expected);
+ parseExpressionAndCompare("$.mapBin1.a.get(type: INT, return: VALUE) == 200", expected);
+ parseExpressionAndCompare("$.mapBin1.a.asInt() == 200", expected);
// String
expected = Exp.eq(
@@ -42,9 +42,9 @@ void mapOneLevelExpressions() {
),
Exp.val("stringVal"));
// Implicit detect as String
- translateAndCompare("$.mapBin1.a == \"stringVal\"", expected);
- translateAndCompare("$.mapBin1.a.get(type: STRING) == \"stringVal\"", expected);
- translateAndCompare("$.mapBin1.a.get(type: STRING, return: VALUE) == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.mapBin1.a == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.mapBin1.a.get(type: STRING) == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.mapBin1.a.get(type: STRING, return: VALUE) == \"stringVal\"", expected);
}
@Test
@@ -58,9 +58,9 @@ void mapNestedLevelExpressions() {
CTX.mapKey(Value.get("a")), CTX.mapKey(Value.get("bb"))
),
Exp.val(200));
- translateAndCompare("$.mapBin1.a.bb.bcc > 200", expected);
- translateAndCompare("$.mapBin1.a.bb.bcc.get(type: INT) > 200", expected);
- translateAndCompare("$.mapBin1.a.bb.bcc.get(type: INT, return: VALUE) > 200", expected);
+ parseExpressionAndCompare("$.mapBin1.a.bb.bcc > 200", expected);
+ parseExpressionAndCompare("$.mapBin1.a.bb.bcc.get(type: INT) > 200", expected);
+ parseExpressionAndCompare("$.mapBin1.a.bb.bcc.get(type: INT, return: VALUE) > 200", expected);
// String
expected = Exp.eq(
@@ -73,9 +73,9 @@ void mapNestedLevelExpressions() {
),
Exp.val("stringVal"));
// Implicit detect as String
- translateAndCompare("$.mapBin1.a.bb.bcc == \"stringVal\"", expected);
- translateAndCompare("$.mapBin1.a.bb.bcc.get(type: STRING) == \"stringVal\"", expected);
- translateAndCompare("$.mapBin1.a.bb.bcc.get(type: STRING, return: VALUE) == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.mapBin1.a.bb.bcc == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.mapBin1.a.bb.bcc.get(type: STRING) == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.mapBin1.a.bb.bcc.get(type: STRING, return: VALUE) == \"stringVal\"", expected);
}
@Test
@@ -89,9 +89,9 @@ void quotedStringInExpressionPath() {
CTX.mapKey(Value.get("a")), CTX.mapKey(Value.get("bb"))
),
Exp.val(200));
- translateAndCompare("$.mapBin1.a.bb.bcc.get(type: INT) > 200", expected);
- translateAndCompare("$.mapBin1.a.\"bb\".bcc.get(type: INT) > 200", expected);
- translateAndCompare("$.mapBin1.a.'bb'.bcc.get(type: INT) > 200", expected);
+ parseExpressionAndCompare("$.mapBin1.a.bb.bcc.get(type: INT) > 200", expected);
+ parseExpressionAndCompare("$.mapBin1.a.\"bb\".bcc.get(type: INT) > 200", expected);
+ parseExpressionAndCompare("$.mapBin1.a.'bb'.bcc.get(type: INT) > 200", expected);
expected = Exp.gt(
MapExp.getByKey(
@@ -102,8 +102,8 @@ void quotedStringInExpressionPath() {
CTX.mapKey(Value.get("127.0.0.1"))
),
Exp.val(200));
- translateAndCompare("$.mapBin1.\"127.0.0.1\".bcc.get(type: INT) > 200", expected);
- translateAndCompare("$.mapBin1.'127.0.0.1'.bcc.get(type: INT) > 200", expected);
+ parseExpressionAndCompare("$.mapBin1.\"127.0.0.1\".bcc.get(type: INT) > 200", expected);
+ parseExpressionAndCompare("$.mapBin1.'127.0.0.1'.bcc.get(type: INT) > 200", expected);
}
@Test
@@ -113,7 +113,7 @@ void mapSize() {
Exp.mapBin("mapBin1")
),
Exp.val(200));
- translateAndCompare("$.mapBin1.{}.count() > 200", expected);
+ parseExpressionAndCompare("$.mapBin1.{}.count() > 200", expected);
// the default behaviour for count() without List '[]' or Map '{}' designators is List
Exp expected2 = Exp.gt(
@@ -121,7 +121,7 @@ void mapSize() {
Exp.listBin("mapBin1")
),
Exp.val(200));
- translateAndCompare("$.mapBin1.count() > 200", expected2);
+ parseExpressionAndCompare("$.mapBin1.count() > 200", expected2);
}
@Test
@@ -135,7 +135,7 @@ void nestedMapSize() {
Exp.mapBin("mapBin1"))
),
Exp.val(200));
- translateAndCompare("$.mapBin1.a.{}.count() == 200", expected);
+ parseExpressionAndCompare("$.mapBin1.a.{}.count() == 200", expected);
// the default behaviour for count() without Map '{}' or List '[]' designators is List
Exp expected2 = Exp.eq(
@@ -146,7 +146,7 @@ void nestedMapSize() {
Exp.mapBin("mapBin1"))
),
Exp.val(200));
- translateAndCompare("$.mapBin1.a.count() == 200", expected2);
+ parseExpressionAndCompare("$.mapBin1.a.count() == 200", expected2);
}
@Test
@@ -161,7 +161,7 @@ void nestedMapSizeWithContext() {
CTX.mapKey(Value.get("a")))
),
Exp.val(200));
- translateAndCompare("$.mapBin1.a.b.{}.count() == 200", expected);
+ parseExpressionAndCompare("$.mapBin1.a.b.{}.count() == 200", expected);
// the default behaviour for count() without Map '{}' or List '[]' designators is List
Exp expected2 = Exp.eq(
@@ -173,7 +173,7 @@ void nestedMapSizeWithContext() {
CTX.mapKey(Value.get("a")))
),
Exp.val(200));
- translateAndCompare("$.mapBin1.a.b.count() == 200", expected2);
+ parseExpressionAndCompare("$.mapBin1.a.b.count() == 200", expected2);
}
@Test
@@ -186,10 +186,10 @@ void mapByIndex() {
Exp.mapBin("mapBin1")
),
Exp.val(100));
- translateAndCompare("$.mapBin1.{0} == 100", expected);
- translateAndCompare("$.mapBin1.{0}.get(type: INT) == 100", expected);
- translateAndCompare("$.mapBin1.{0}.get(type: INT, return: VALUE) == 100", expected);
- translateAndCompare("$.mapBin1.{0}.asInt() == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.{0} == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.{0}.get(type: INT) == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.{0}.get(type: INT, return: VALUE) == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.{0}.asInt() == 100", expected);
}
@Test
@@ -201,10 +201,10 @@ void mapByValue() {
Exp.mapBin("mapBin1")
),
Exp.val(100));
- translateAndCompare("$.mapBin1.{=100} == 100", expected);
- translateAndCompare("$.mapBin1.{=100}.get(type: INT) == 100", expected);
- translateAndCompare("$.mapBin1.{=100}.get(type: INT, return: VALUE) == 100", expected);
- translateAndCompare("$.mapBin1.{=100}.asInt() == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.{=100} == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.{=100}.get(type: INT) == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.{=100}.get(type: INT, return: VALUE) == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.{=100}.asInt() == 100", expected);
}
@Test
@@ -215,8 +215,8 @@ void mapByValueCount() {
Exp.mapBin("mapBin1")),
Exp.val(0)
);
- translateAndCompare("$.mapBin1.{=100}.count() > 0", expected);
- translateAndCompare("$.mapBin1.{=100}.{}.count() > 0", expected);
+ parseExpressionAndCompare("$.mapBin1.{=100}.count() > 0", expected);
+ parseExpressionAndCompare("$.mapBin1.{=100}.{}.count() > 0", expected);
}
@Test
@@ -229,10 +229,10 @@ void mapByRank() {
Exp.mapBin("mapBin1")
),
Exp.val(100));
- translateAndCompare("$.mapBin1.{#-1} == 100", expected);
- translateAndCompare("$.mapBin1.{#-1}.get(type: INT) == 100", expected);
- translateAndCompare("$.mapBin1.{#-1}.get(type: INT, return: VALUE) == 100", expected);
- translateAndCompare("$.mapBin1.{#-1}.asInt() == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.{#-1} == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.{#-1}.get(type: INT) == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.{#-1}.get(type: INT, return: VALUE) == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.{#-1}.asInt() == 100", expected);
}
@Test
@@ -246,10 +246,10 @@ void mapByRankWithNesting() {
CTX.mapKey(Value.get("a"))
),
Exp.val(100));
- translateAndCompare("$.mapBin1.a.{#-1} == 100", expected);
- translateAndCompare("$.mapBin1.a.{#-1}.get(type: INT) == 100", expected);
- translateAndCompare("$.mapBin1.a.{#-1}.get(type: INT, return: VALUE) == 100", expected);
- translateAndCompare("$.mapBin1.a.{#-1}.asInt() == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.a.{#-1} == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.a.{#-1}.get(type: INT) == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.a.{#-1}.get(type: INT, return: VALUE) == 100", expected);
+ parseExpressionAndCompare("$.mapBin1.a.{#-1}.asInt() == 100", expected);
}
@Test
@@ -265,8 +265,8 @@ void nestedListsWithDifferentContextTypes() {
),
Exp.val("stringVal"));
// Implicit detect as String
- translateAndCompare("$.mapBin1.{5}.{#-1} == \"stringVal\"", expected);
- translateAndCompare("$.mapBin1.{5}.{#-1}.get(type: STRING) == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.mapBin1.{5}.{#-1} == \"stringVal\"", expected);
+ parseExpressionAndCompare("$.mapBin1.{5}.{#-1}.get(type: STRING) == \"stringVal\"", expected);
// Nested List Rank Value
expected = Exp.eq(
@@ -278,7 +278,7 @@ void nestedListsWithDifferentContextTypes() {
CTX.mapRank(-1)
),
Exp.val(200));
- translateAndCompare("$.mapBin1.{5}.{#-1}.{=100} == 200", expected);
+ parseExpressionAndCompare("$.mapBin1.{5}.{#-1}.{=100} == 200", expected);
}
@Test
@@ -288,8 +288,8 @@ void mapKeyRange() {
Exp.val("a"),
Exp.val("c"),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{a-c}", expected);
- translateAndCompare("$.mapBin1.{\"a\"-\"c\"}", expected);
+ parseExpressionAndCompare("$.mapBin1.{a-c}", expected);
+ parseExpressionAndCompare("$.mapBin1.{\"a\"-\"c\"}", expected);
// Inverted
expected = MapExp.getByKeyRange(
@@ -297,8 +297,8 @@ void mapKeyRange() {
Exp.val("a"),
Exp.val("c"),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{!a-c}", expected);
- translateAndCompare("$.mapBin1.{!\"a\"-\"c\"}", expected);
+ parseExpressionAndCompare("$.mapBin1.{!a-c}", expected);
+ parseExpressionAndCompare("$.mapBin1.{!\"a\"-\"c\"}", expected);
// From start till the end
expected = MapExp.getByKeyRange(
@@ -306,8 +306,8 @@ void mapKeyRange() {
Exp.val("a"),
null,
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{a-}", expected);
- translateAndCompare("$.mapBin1.{\"a\"-}", expected);
+ parseExpressionAndCompare("$.mapBin1.{a-}", expected);
+ parseExpressionAndCompare("$.mapBin1.{\"a\"-}", expected);
}
@Test
@@ -316,16 +316,16 @@ void mapKeyList() {
MapReturnType.VALUE,
Exp.val(List.of("a", "b", "c")),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{a,b,c}", expected);
- translateAndCompare("$.mapBin1.{\"a\",\"b\",\"c\"}", expected);
+ parseExpressionAndCompare("$.mapBin1.{a,b,c}", expected);
+ parseExpressionAndCompare("$.mapBin1.{\"a\",\"b\",\"c\"}", expected);
// Inverted
expected = MapExp.getByKeyList(
MapReturnType.VALUE | MapReturnType.INVERTED,
Exp.val(List.of("a", "b", "c")),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{!a,b,c}", expected);
- translateAndCompare("$.mapBin1.{!\"a\",\"b\",\"c\"}", expected);
+ parseExpressionAndCompare("$.mapBin1.{!a,b,c}", expected);
+ parseExpressionAndCompare("$.mapBin1.{!\"a\",\"b\",\"c\"}", expected);
}
@Test
@@ -335,7 +335,7 @@ void mapIndexRange() {
Exp.val(1),
Exp.val(2),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{1:3}", expected);
+ parseExpressionAndCompare("$.mapBin1.{1:3}", expected);
// Negative
expected = MapExp.getByIndexRange(
@@ -343,7 +343,7 @@ void mapIndexRange() {
Exp.val(-3),
Exp.val(4),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{-3:1}", expected);
+ parseExpressionAndCompare("$.mapBin1.{-3:1}", expected);
// Inverted
expected = MapExp.getByIndexRange(
@@ -351,14 +351,14 @@ void mapIndexRange() {
Exp.val(2),
Exp.val(2),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{!2:4}", expected);
+ parseExpressionAndCompare("$.mapBin1.{!2:4}", expected);
// From start till the end
expected = MapExp.getByIndexRange(
MapReturnType.VALUE,
Exp.val(1),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{1:}", expected);
+ parseExpressionAndCompare("$.mapBin1.{1:}", expected);
}
@Test
@@ -367,23 +367,23 @@ void mapValueList() {
MapReturnType.VALUE,
Exp.val(List.of("a", "b", "c")),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{=a,b,c}", expected);
- translateAndCompare("$.mapBin1.{=\"a\",\"b\",\"c\"}", expected);
+ parseExpressionAndCompare("$.mapBin1.{=a,b,c}", expected);
+ parseExpressionAndCompare("$.mapBin1.{=\"a\",\"b\",\"c\"}", expected);
// Integer
expected = MapExp.getByValueList(
MapReturnType.VALUE,
Exp.val(List.of(1, 2, 3)),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{=1,2,3}", expected);
+ parseExpressionAndCompare("$.mapBin1.{=1,2,3}", expected);
// Inverted
expected = MapExp.getByValueList(
MapReturnType.VALUE | MapReturnType.INVERTED,
Exp.val(List.of("a", "b", "c")),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{!=a,b,c}", expected);
- translateAndCompare("$.mapBin1.{!=\"a\",\"b\",\"c\"}", expected);
+ parseExpressionAndCompare("$.mapBin1.{!=a,b,c}", expected);
+ parseExpressionAndCompare("$.mapBin1.{!=\"a\",\"b\",\"c\"}", expected);
}
@Test
@@ -393,7 +393,7 @@ void mapValueRange() {
Exp.val(111),
Exp.val(334),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{=111:334}", expected);
+ parseExpressionAndCompare("$.mapBin1.{=111:334}", expected);
// Inverted
expected = MapExp.getByValueRange(
@@ -401,7 +401,7 @@ void mapValueRange() {
Exp.val(10),
Exp.val(20),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{!=10:20}", expected);
+ parseExpressionAndCompare("$.mapBin1.{!=10:20}", expected);
// From start till the end
expected = MapExp.getByValueRange(
@@ -409,7 +409,7 @@ void mapValueRange() {
Exp.val(111),
null,
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{=111:}", expected);
+ parseExpressionAndCompare("$.mapBin1.{=111:}", expected);
}
@Test
@@ -419,7 +419,7 @@ void mapRankRange() {
Exp.val(0),
Exp.val(3),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{#0:3}", expected);
+ parseExpressionAndCompare("$.mapBin1.{#0:3}", expected);
// Inverted
expected = MapExp.getByRankRange(
@@ -427,14 +427,14 @@ void mapRankRange() {
Exp.val(0),
Exp.val(3),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{!#0:3}", expected);
+ parseExpressionAndCompare("$.mapBin1.{!#0:3}", expected);
// From start till the end
expected = MapExp.getByRankRange(
MapReturnType.VALUE,
Exp.val(-3),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{#-3:}", expected);
+ parseExpressionAndCompare("$.mapBin1.{#-3:}", expected);
// From start till the end with context
expected = MapExp.getByRankRange(
@@ -442,7 +442,7 @@ void mapRankRange() {
Exp.val(-3),
Exp.mapBin("mapBin1"),
CTX.mapIndex(5));
- translateAndCompare("$.mapBin1.{5}.{#-3:}", expected);
+ parseExpressionAndCompare("$.mapBin1.{5}.{#-3:}", expected);
}
@Test
@@ -453,7 +453,7 @@ void mapRankRangeRelative() {
Exp.val(10),
Exp.val(2),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{#-1:1~10}", expected);
+ parseExpressionAndCompare("$.mapBin1.{#-1:1~10}", expected);
// Inverted
expected = MapExp.getByValueRelativeRankRange(
@@ -462,7 +462,7 @@ void mapRankRangeRelative() {
Exp.val(10),
Exp.val(2),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{!#-1:1~10}", expected);
+ parseExpressionAndCompare("$.mapBin1.{!#-1:1~10}", expected);
// From start till the end
expected = MapExp.getByValueRelativeRankRange(
@@ -470,7 +470,7 @@ void mapRankRangeRelative() {
Exp.val(-2),
Exp.val(10),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{#-2:~10}", expected);
+ parseExpressionAndCompare("$.mapBin1.{#-2:~10}", expected);
}
@Test
@@ -481,7 +481,7 @@ void mapIndexRangeRelative() {
Exp.val(0),
Exp.val(1),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{0:1~a}", expected);
+ parseExpressionAndCompare("$.mapBin1.{0:1~a}", expected);
// Inverted
expected = MapExp.getByKeyRelativeIndexRange(
@@ -490,7 +490,7 @@ void mapIndexRangeRelative() {
Exp.val(0),
Exp.val(1),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{!0:1~a}", expected);
+ parseExpressionAndCompare("$.mapBin1.{!0:1~a}", expected);
// From start till the end
expected = MapExp.getByKeyRelativeIndexRange(
@@ -498,7 +498,7 @@ void mapIndexRangeRelative() {
Exp.val("a"),
Exp.val(0),
Exp.mapBin("mapBin1"));
- translateAndCompare("$.mapBin1.{0:~a}", expected);
+ parseExpressionAndCompare("$.mapBin1.{0:~a}", expected);
}
@Test
@@ -512,7 +512,7 @@ void mapReturnTypes() {
),
Exp.val(5));
// Implicit detect as Int
- translateAndCompare("$.mapBin1.a.get(type: INT, return: COUNT) == 5", expected);
+ parseExpressionAndCompare("$.mapBin1.a.get(type: INT, return: COUNT) == 5", expected);
expected = MapExp.getByKey(
MapReturnType.ORDERED_MAP,
@@ -521,7 +521,7 @@ void mapReturnTypes() {
Exp.mapBin("mapBin1")
);
// Implicit detect as Int
- translateAndCompare("$.mapBin1.a.get(return: ORDERED_MAP)", expected);
+ parseExpressionAndCompare("$.mapBin1.a.get(return: ORDERED_MAP)", expected);
expected = Exp.eq(
MapExp.getByKey(
@@ -532,6 +532,6 @@ void mapReturnTypes() {
),
Exp.val(5));
// Implicit detect as Int
- translateAndCompare("$.mapBin1.a.get(type: INT, return: RANK) == 5", expected);
+ parseExpressionAndCompare("$.mapBin1.a.get(type: INT, return: RANK) == 5", expected);
}
}
diff --git a/src/test/java/com/aerospike/dsl/RecordMetadataTests.java b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java
similarity index 80%
rename from src/test/java/com/aerospike/dsl/RecordMetadataTests.java
rename to src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java
index 1c2a398..ca59c28 100644
--- a/src/test/java/com/aerospike/dsl/RecordMetadataTests.java
+++ b/src/test/java/com/aerospike/dsl/expression/RecordMetadataTests.java
@@ -1,11 +1,11 @@
-package com.aerospike.dsl;
+package com.aerospike.dsl.expression;
import com.aerospike.client.exp.Exp;
import com.aerospike.dsl.exception.AerospikeDSLException;
import org.junit.jupiter.api.Test;
-import static com.aerospike.dsl.util.TestUtils.translate;
-import static com.aerospike.dsl.util.TestUtils.translateAndCompare;
+import static com.aerospike.dsl.util.TestUtils.parseExpression;
+import static com.aerospike.dsl.util.TestUtils.parseExpressionAndCompare;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
class RecordMetadataTests {
@@ -15,7 +15,7 @@ void deviceSize() {
// Expression to find records that occupy more than 1 MiB of storage space
String input = "$.deviceSize() > 1048576";
Exp expected = Exp.gt(Exp.deviceSize(), Exp.val(1024 * 1024));
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
}
@Test
@@ -23,7 +23,7 @@ void memorySize() {
// Expression to find records that occupy more than 1 MiB of memory
String input = "$.memorySize() > 1048576";
Exp expected = Exp.gt(Exp.memorySize(), Exp.val(1024 * 1024));
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
}
@Test
@@ -31,7 +31,7 @@ void recordSize() {
// Expression to find records that occupy more than 1 MiB of memory
String input = "$.recordSize() > 1048576";
Exp expected = Exp.gt(Exp.recordSize(), Exp.val(1024 * 1024));
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
}
@Test
@@ -39,12 +39,12 @@ void digestModulo() {
// Expression to find records where digest mod 3 equals 0
String input = "$.digestModulo(3) == 0";
Exp expected = Exp.eq(Exp.digestModulo(3), Exp.val(0));
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
// Expression to find records where digest mod 3 equals the value stored in the bin called "digestModulo"
String input2 = "$.digestModulo(3) == $.digestModulo";
Exp expected2 = Exp.eq(Exp.digestModulo(3), Exp.intBin("digestModulo"));
- translateAndCompare(input2, expected2);
+ parseExpressionAndCompare(input2, expected2);
}
@Test
@@ -52,7 +52,7 @@ void isTombstone() {
// Expression to find records that are tombstones
String input = "$.isTombstone()";
Exp expected = Exp.isTombstone();
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
}
@Test
@@ -60,7 +60,7 @@ void keyExists() {
// Expression to find records that has a stored key
String input = "$.keyExists()";
Exp expected = Exp.keyExists();
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
}
// Comparing Metadata to a Bin
@@ -69,12 +69,12 @@ void lastUpdate() {
// Expression to find records where the last-update-time is less than bin 'updateBy'
String inputMetadataLeft = "$.lastUpdate() < $.updateBy";
Exp expectedLeft = Exp.lt(Exp.lastUpdate(), Exp.intBin("updateBy"));
- translateAndCompare(inputMetadataLeft, expectedLeft);
+ parseExpressionAndCompare(inputMetadataLeft, expectedLeft);
// Expression to find records where the last-update-time is less than bin 'updateBy'
String inputMetadataRight = "$.updateBy > $.lastUpdate()";
Exp expectedRight = Exp.gt(Exp.intBin("updateBy"), Exp.lastUpdate());
- translateAndCompare(inputMetadataRight, expectedRight);
+ parseExpressionAndCompare(inputMetadataRight, expectedRight);
}
@Test
@@ -82,22 +82,22 @@ void sinceUpdate() {
// Expression to find records that were updated within the last 2 hours
String input = "$.sinceUpdate() < 7200000";
Exp expected = Exp.lt(Exp.sinceUpdate(), Exp.val(2 * 60 * 60 * 1000));
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
// Expression to find records that were update within the value stored in the bin called "intBin"
String input2 = "$.sinceUpdate() < $.intBin";
Exp expected2 = Exp.lt(Exp.sinceUpdate(), Exp.intBin("intBin"));
- translateAndCompare(input2, expected2);
+ parseExpressionAndCompare(input2, expected2);
// Expression to find records that were updated within the value stored in the bin called "sinceUpdate"
String input3 = "$.sinceUpdate() < $.sinceUpdate";
Exp expected3 = Exp.lt(Exp.sinceUpdate(), Exp.intBin("sinceUpdate"));
- translateAndCompare(input3, expected3);
+ parseExpressionAndCompare(input3, expected3);
// Expression to find records that were updated within the value stored in the bin called "sinceUpdate"
String input4 = "$.sinceUpdate > $.sinceUpdate()";
Exp expected4 = Exp.gt(Exp.intBin("sinceUpdate"), Exp.sinceUpdate());
- translateAndCompare(input4, expected4);
+ parseExpressionAndCompare(input4, expected4);
}
@Test
@@ -108,12 +108,12 @@ void setName() {
Exp.eq(Exp.setName(), Exp.val("groupA")),
Exp.eq(Exp.setName(), Exp.val("groupB"))
);
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
// set name compared with String Bin
input = "$.mySetBin == $.setName()";
expected = Exp.eq(Exp.stringBin("mySetBin"), Exp.setName());
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
}
@Test
@@ -121,13 +121,13 @@ void ttl() {
// Expression to find records that will expire within 24 hours
String input = "$.ttl() <= 86400";
Exp expected = Exp.le(Exp.ttl(), Exp.val(24 * 60 * 60));
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
}
//@Test
void negativeTtlAsDifferentType() {
// TODO: should be supported when adding operator + metadata validations (requires a refactor)
- assertThatThrownBy(() -> translate("$.ttl() == true"))
+ assertThatThrownBy(() -> parseExpression("$.ttl() == true"))
.isInstanceOf(AerospikeDSLException.class)
.hasMessageContaining("Expecting non-bin operand, got BOOL_OPERAND");
}
@@ -137,7 +137,7 @@ void voidTime() {
// Expression to find records where the void-time is set to 'never expire'
String input = "$.voidTime() == -1";
Exp expected = Exp.eq(Exp.voidTime(), Exp.val(-1));
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
}
@Test
@@ -148,7 +148,7 @@ void metadataWithLogicalOperatorsExpressions() {
Exp.gt(Exp.deviceSize(), Exp.val(1024)),
Exp.lt(Exp.ttl(), Exp.val(300))
);
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
// test OR
String input2 = "$.deviceSize() > 1024 or $.ttl() < 300";
@@ -156,7 +156,7 @@ void metadataWithLogicalOperatorsExpressions() {
Exp.gt(Exp.deviceSize(), Exp.val(1024)),
Exp.lt(Exp.ttl(), Exp.val(300))
);
- translateAndCompare(input2, expected2);
+ parseExpressionAndCompare(input2, expected2);
}
@Test
@@ -166,13 +166,13 @@ void metadataAsExpressionWithLogicalOperator() {
Exp.isTombstone(),
Exp.lt(Exp.ttl(), Exp.val(300))
);
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
input = "$.ttl() < 300 or $.keyExists()";
expected = Exp.or(
Exp.lt(Exp.ttl(), Exp.val(300)),
Exp.keyExists()
);
- translateAndCompare(input, expected);
+ parseExpressionAndCompare(input, expected);
}
}
diff --git a/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java
new file mode 100644
index 0000000..c5e3cef
--- /dev/null
+++ b/src/test/java/com/aerospike/dsl/filter/ArithmeticFiltersTests.java
@@ -0,0 +1,376 @@
+package com.aerospike.dsl.filter;
+
+import com.aerospike.client.query.Filter;
+import com.aerospike.dsl.exception.AerospikeDSLException;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static com.aerospike.dsl.util.TestUtils.parseFilters;
+import static com.aerospike.dsl.util.TestUtils.parseFiltersAndCompare;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class ArithmeticFiltersTests {
+
+ @Test
+ void add() {
+ assertThatThrownBy(() -> parseFilters("($.apples + $.bananas) > 10"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ parseFiltersAndCompare("($.apples + 5) > 10",
+ List.of(Filter.range("apples", 10 - 5 + 1, Long.MAX_VALUE)));
+ parseFiltersAndCompare("($.apples + 5) >= 10",
+ List.of(Filter.range("apples", 10 - 5, Long.MAX_VALUE)));
+ parseFiltersAndCompare("($.apples + 5) < 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 10 - 5 - 1)));
+ parseFiltersAndCompare("($.apples + 5) <= 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 10 - 5)));
+
+ parseFiltersAndCompare("(9 + $.bananas) > 10",
+ List.of(Filter.range("bananas", 10 - 9 + 1, Long.MAX_VALUE)));
+ parseFiltersAndCompare("(9 + $.bananas) >= 10",
+ List.of(Filter.range("bananas", 10 - 9, Long.MAX_VALUE)));
+ parseFiltersAndCompare("(9 + $.bananas) < 10",
+ List.of(Filter.range("bananas", Long.MIN_VALUE, 10 - 9 - 1)));
+ parseFiltersAndCompare("(9 + $.bananas) <= 10",
+ List.of(Filter.range("bananas", Long.MIN_VALUE, 10 - 9)));
+
+ assertThatThrownBy(() -> parseFilters("(5.2 + $.bananas) > 10.2"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ assertThatThrownBy(() -> parseFilters("($.apples + $.bananas + 5) > 10"))
+ .isInstanceOf(AerospikeDSLException.class) // not supported by the current grammar
+ .hasMessageContaining("Could not parse given input, wrong syntax");
+ }
+
+ @Test
+ void sub() {
+ assertThatThrownBy(() -> parseFilters("($.apples - $.bananas) > 10"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ parseFiltersAndCompare("($.apples - 5) > 10",
+ List.of(Filter.range("apples", 10 + 5 + 1, Long.MAX_VALUE)));
+ parseFiltersAndCompare("($.apples - 5) >= 10",
+ List.of(Filter.range("apples", 10 + 5, Long.MAX_VALUE)));
+ parseFiltersAndCompare("($.apples - 5) < 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 10 + 5 - 1)));
+ parseFiltersAndCompare("($.apples - 5) <= 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 10 + 5)));
+
+ parseFiltersAndCompare("($.apples - 5) > -10",
+ List.of(Filter.range("apples", -10 + 5 + 1, Long.MAX_VALUE)));
+ parseFiltersAndCompare("($.apples - 5) >= -10",
+ List.of(Filter.range("apples", -10 + 5, Long.MAX_VALUE)));
+ parseFiltersAndCompare("($.apples - 5) < -10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, -10 + 5 - 1)));
+ parseFiltersAndCompare("($.apples - 5) <= -10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, -10 + 5)));
+
+ parseFiltersAndCompare("(9 - $.bananas) > 10",
+ List.of(Filter.range("bananas", Long.MIN_VALUE, 9 - 10 - 1)));
+ parseFiltersAndCompare("(9 - $.bananas) >= 10",
+ List.of(Filter.range("bananas", Long.MIN_VALUE, 9 - 10)));
+ parseFiltersAndCompare("(9 - $.bananas) < 10",
+ List.of(Filter.range("bananas", 9 - 10 + 1, Long.MAX_VALUE)));
+ parseFiltersAndCompare("(9 - $.bananas) <= 10",
+ List.of(Filter.range("bananas", 9 - 10, Long.MAX_VALUE)));
+
+ assertThatThrownBy(() -> parseFilters("($.apples - $.bananas) > 10"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("($.apples - $.bananas - 5) > 10"))
+ .isInstanceOf(AerospikeDSLException.class) // not supported by the current grammar
+ .hasMessageContaining("Could not parse given input, wrong syntax");
+ }
+
+ @Test
+ void mul() {
+ assertThatThrownBy(() -> parseFilters("($.apples * $.bananas) > 10"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ parseFiltersAndCompare("($.apples * 5) > 10",
+ List.of(Filter.range("apples", 10 / 5 + 1, Long.MAX_VALUE)));
+ parseFiltersAndCompare("($.apples * 5) >= 10",
+ List.of(Filter.range("apples", 10 / 5, Long.MAX_VALUE)));
+ parseFiltersAndCompare("($.apples * 5) < 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 10 / 5 - 1)));
+ parseFiltersAndCompare("($.apples * 5) <= 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 10 / 5)));
+
+ parseFiltersAndCompare("(9 * $.bananas) > 10",
+ List.of(Filter.range("bananas", 10 / 9 + 1, Long.MAX_VALUE)));
+ parseFiltersAndCompare("(9 * $.bananas) >= 10",
+ List.of(Filter.range("bananas", 10 / 9, Long.MAX_VALUE)));
+ parseFiltersAndCompare("(9 * $.bananas) < 10",
+ List.of(Filter.range("bananas", Long.MIN_VALUE, 10 / 9)));
+ parseFiltersAndCompare("(9 * $.bananas) <= 10",
+ List.of(Filter.range("bananas", Long.MIN_VALUE, 10 / 9)));
+
+ parseFiltersAndCompare("($.apples * -5) > 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 10 / -5 - 1)));
+ parseFiltersAndCompare("($.apples * -5) >= 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 10 / -5)));
+ parseFiltersAndCompare("($.apples * -5) < 10",
+ List.of(Filter.range("apples", 10 / -5 + 1, Long.MAX_VALUE)));
+ parseFiltersAndCompare("($.apples * -5) <= 10",
+ List.of(Filter.range("apples", 10 / -5, Long.MAX_VALUE)));
+
+ assertThatThrownBy(() -> parseFilters("(0 * $.bananas) > 10"))
+ .isInstanceOf(AerospikeDSLException.class) // not supported by the current grammar
+ .hasMessageContaining("Cannot divide by zero");
+
+ parseFiltersAndCompare("(9 * $.bananas) > 0",
+ List.of(Filter.range("bananas", 0 / 9 + 1, Long.MAX_VALUE)));
+
+ assertThatThrownBy(() -> parseFilters("($.apples * $.bananas - 5) > 10"))
+ .isInstanceOf(AerospikeDSLException.class) // not supported by the current grammar
+ .hasMessageContaining("Could not parse given input, wrong syntax");
+ }
+
+ @Test
+ void div_twoBins() {
+ assertThatThrownBy(() -> parseFilters("($.apples / $.bananas) <= 10"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ }
+
+ @Test
+ void div_binIsDivided_leftNumberIsLarger() {
+ parseFiltersAndCompare("($.apples / 50) > 10",
+ List.of(Filter.range("apples", 50 * 10 + 1, Long.MAX_VALUE))); // [501, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / 50) >= 10",
+ List.of(Filter.range("apples", 50 * 10, Long.MAX_VALUE))); // [500, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / 50) < 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 50 * 10 - 1))); // [-2^63, 499]
+ parseFiltersAndCompare("($.apples / 50) <= 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 50 * 10))); // [-2^63, 500]
+
+ parseFiltersAndCompare("($.apples / -50) > 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, -50 * 10 - 1))); // [-2^63, -501]
+ parseFiltersAndCompare("($.apples / -50) >= 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, -50 * 10))); // [-2^63, -500]
+ parseFiltersAndCompare("($.apples / -50) < 10",
+ List.of(Filter.range("apples", -50 * 10 + 1, Long.MAX_VALUE))); // [-499, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / -50) <= 10",
+ List.of(Filter.range("apples", -50 * 10, Long.MAX_VALUE))); // [-500, 2^63 - 1]
+
+ parseFiltersAndCompare("($.apples / 50) > -10",
+ List.of(Filter.range("apples", 50 * -10 + 1, Long.MAX_VALUE))); // [-499, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / 50) >= -10",
+ List.of(Filter.range("apples", 50 * -10, Long.MAX_VALUE))); // [-500, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / 50) < -10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 50 * -10 - 1))); // [-2^63, -501]
+ parseFiltersAndCompare("($.apples / 50) <= -10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 50 * -10))); // [-2^63, -500]
+
+ parseFiltersAndCompare("($.apples / -50) > -10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, -50 * -10 - 1))); // [-2^63, 499]
+ parseFiltersAndCompare("($.apples / -50) >= -10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, -10 * -50))); // [-2^63, 500]
+ parseFiltersAndCompare("($.apples / -50) < -10",
+ List.of(Filter.range("apples", -10 * -50 + 1, Long.MAX_VALUE))); // [501, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / -50) <= -10",
+ List.of(Filter.range("apples", -10 * -50, Long.MAX_VALUE))); // [500, 2^63 - 1]
+ }
+
+ @Test
+ void div_binIsDivided_leftNumberIsSmaller() {
+ parseFiltersAndCompare("($.apples / 5) > 10",
+ List.of(Filter.range("apples", 5 * 10 + 1, Long.MAX_VALUE))); // [51, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / 5) >= 10",
+ List.of(Filter.range("apples", 5 * 10, Long.MAX_VALUE))); // [50, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / 5) < 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 5 * 10 - 1))); // [-2^63, 49]
+ parseFiltersAndCompare("($.apples / 5) <= 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 5 * 10))); // [-2^63, 50]
+
+ parseFiltersAndCompare("($.apples / -5) > 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, -5 * 10 - 1))); // [-2^63, -51]
+ parseFiltersAndCompare("($.apples / -5) >= 10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, -5 * 10))); // [-2^63, -50]
+ parseFiltersAndCompare("($.apples / -5) < 10",
+ List.of(Filter.range("apples", -5 * 10 + 1, Long.MAX_VALUE))); // [-49, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / -5) <= 10",
+ List.of(Filter.range("apples", -5 * 10, Long.MAX_VALUE))); // [-50, 2^63 - 1]
+
+ parseFiltersAndCompare("($.apples / 5) > -10",
+ List.of(Filter.range("apples", 5 * -10 + 1, Long.MAX_VALUE))); // [-49, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / 5) >= -10",
+ List.of(Filter.range("apples", 5 * -10, Long.MAX_VALUE))); // [-50, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / 5) < -10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 5 * -10 - 1))); // [-2^63, -51]
+ parseFiltersAndCompare("($.apples / 5) <= -10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 5 * -10))); // [-2^63, -50]
+
+ parseFiltersAndCompare("($.apples / -5) > -10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, -5 * -10 - 1))); // [-2^63, 49]
+ parseFiltersAndCompare("($.apples / -5) >= -10",
+ List.of(Filter.range("apples", Long.MIN_VALUE, -10 * -5))); // [-2^63, 50]
+ parseFiltersAndCompare("($.apples / -5) < -10",
+ List.of(Filter.range("apples", -10 * -5 + 1, Long.MAX_VALUE))); // [51, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / -5) <= -10",
+ List.of(Filter.range("apples", -10 * -5, Long.MAX_VALUE))); // [50, 2^63 - 1]
+ }
+
+ @Test
+ void div_binIsDivided_leftNumberEqualsRight() {
+ parseFiltersAndCompare("($.apples / 5) > 5",
+ List.of(Filter.range("apples", 5 * 5 + 1, Long.MAX_VALUE))); // [26, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / 5) >= 5",
+ List.of(Filter.range("apples", 5 * 5, Long.MAX_VALUE))); // [25, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / 5) < 5",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 5 * 5 - 1))); // [-2^63, 24]
+ parseFiltersAndCompare("($.apples / 5) <= 5",
+ List.of(Filter.range("apples", Long.MIN_VALUE, 5 * 5))); // [-2^63, 25]
+
+ parseFiltersAndCompare("($.apples / -5) > -5",
+ List.of(Filter.range("apples", Long.MIN_VALUE, -5 * -5 - 1))); // [-2^63, 24]
+ parseFiltersAndCompare("($.apples / -5) >= -5",
+ List.of(Filter.range("apples", Long.MIN_VALUE, -5 * -5))); // [-2^63, 25]
+ parseFiltersAndCompare("($.apples / -5) < -5",
+ List.of(Filter.range("apples", -5 * -5 + 1, Long.MAX_VALUE))); // [26, 2^63 - 1]
+ parseFiltersAndCompare("($.apples / -5) <= -5",
+ List.of(Filter.range("apples", -5 * -5, Long.MAX_VALUE))); // [25, 2^63 - 1]
+ }
+
+ @Test
+ void div_binIsDivisor_leftNumberIsLarger() {
+ parseFiltersAndCompare("(90 / $.bananas) > 10",
+ List.of(Filter.range("bananas", 1, 90 / 10 - 1))); // [1,8]
+ parseFiltersAndCompare("(90 / $.bananas) >= 10",
+ List.of(Filter.range("bananas", 1, 90 / 10))); // [1,9]
+ assertThatThrownBy(() -> parseFilters("(90 / $.bananas) < 10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(90 / $.bananas) <= 10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ assertThatThrownBy(() -> parseFilters("(90 / $.bananas) > -10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(90 / $.bananas) >= -10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ parseFiltersAndCompare("(90 / $.bananas) < -10",
+ List.of(Filter.range("bananas", 90 / -10 + 1, -1))); // [-8, -1]
+ parseFiltersAndCompare("(90 / $.bananas) <= -10",
+ List.of(Filter.range("bananas", 90 / -10, -1))); // [-8, -1]
+
+ parseFiltersAndCompare("(-90 / $.bananas) > 10",
+ List.of(Filter.range("bananas", -90 / 10 + 1, -1))); // [-8, -1]
+ parseFiltersAndCompare("(90 / $.bananas) >= 10",
+ List.of(Filter.range("bananas", 1, 90 / 10))); // [1,9]
+ assertThatThrownBy(() -> parseFilters("(-90 / $.bananas) < 10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(-90 / $.bananas) <= 10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ assertThatThrownBy(() -> parseFilters("(-90 / $.bananas) > -10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(-90 / $.bananas) >= -10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ parseFiltersAndCompare("(-90 / $.bananas) < -10",
+ List.of(Filter.range("bananas", 1L, -90 / -10 - 1))); // [1, 8]
+ parseFiltersAndCompare("(-90 / $.bananas) <= -10",
+ List.of(Filter.range("bananas", 1L, -90 / -10))); // [1, 9]
+ }
+
+ @Test
+ void div_binIsDivisor_leftNumberIsSmaller() {
+ assertThatThrownBy(() -> parseFilters("(9 / $.bananas) > 10")) // no integer numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(9 / $.bananas) >= 10")) // no integer numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(9 / $.bananas) < 10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(9 / $.bananas) <= 10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ assertThatThrownBy(() -> parseFilters("(9 / $.bananas) > -10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(9 / $.bananas) >= -10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(9 / $.bananas) < -10")) // no integer numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(9 / $.bananas) <= -10")) // no integer numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ assertThatThrownBy(() -> parseFilters("(-9 / $.bananas) > 10")) // no integer numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(-9 / $.bananas) >= 10")) // no integer numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(-9 / $.bananas) < 10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(-9 / $.bananas) <= 10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ assertThatThrownBy(() -> parseFilters("(-9 / $.bananas) > -10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(-9 / $.bananas) >= -10")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(-9 / $.bananas) < -10")) // no integer numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(-9 / $.bananas) <= -10")) // no integer numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ assertThatThrownBy(() -> parseFilters("(0 / $.bananas) > 10"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ assertThatThrownBy(() -> parseFilters("(9 / $.bananas) > 0"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("Cannot divide by zero");
+ }
+
+ @Test
+ void div_binIsDivisor_leftNumberEqualsRight() {
+ assertThatThrownBy(() -> parseFilters("(90 / $.bananas) > 90")) // no integer numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ parseFiltersAndCompare("(90 / $.bananas) >= 90",
+ List.of(Filter.range("bananas", 90 / 90, 90 / 90))); // [1, 1]
+ assertThatThrownBy(() -> parseFilters("(90 / $.bananas) < 90")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(90 / $.bananas) <= 90")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ assertThatThrownBy(() -> parseFilters("(-90 / $.bananas) > -90")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(-90 / $.bananas) >= -90")) // maximal range is all numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("(-90 / $.bananas) < -90")) // no integer numbers
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ parseFiltersAndCompare("(-90 / $.bananas) <= -90",
+ List.of(Filter.range("bananas", 1L, 90 / 90))); // [1, 1]
+ }
+}
diff --git a/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java
new file mode 100644
index 0000000..1161383
--- /dev/null
+++ b/src/test/java/com/aerospike/dsl/filter/BinFiltersTests.java
@@ -0,0 +1,105 @@
+package com.aerospike.dsl.filter;
+
+import com.aerospike.client.query.Filter;
+import com.aerospike.dsl.exception.AerospikeDSLException;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static com.aerospike.dsl.util.TestUtils.parseFilters;
+import static com.aerospike.dsl.util.TestUtils.parseFiltersAndCompare;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+class BinFiltersTests {
+
+ @Test
+ void binGT() {
+ parseFiltersAndCompare("$.intBin1 > 100",
+ List.of(Filter.range("intBin1", 101, Long.MAX_VALUE)));
+ parseFiltersAndCompare("$.intBin1 > -100",
+ List.of(Filter.range("intBin1", -99, Long.MAX_VALUE)));
+
+ assertThatThrownBy(() -> parseFilters("$.stringBin1 > 'text'"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("Operand type not supported");
+ assertThatThrownBy(() -> parseFilters("$.stringBin1 > \"text\""))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("Operand type not supported");
+
+ // "$.intBin1 > 100" and "100 < $.intBin1" represent identical Filters
+ parseFiltersAndCompare("100 < $.intBin1",
+ List.of(Filter.range("intBin1", 101, Long.MAX_VALUE)));
+
+ assertThatThrownBy(() -> parseFilters("'text' > $.stringBin1"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("Operand type not supported");
+ assertThatThrownBy(() -> parseFilters("\"text\" > $.stringBin1"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("Operand type not supported");
+ }
+
+ @Test
+ void binGE() {
+ parseFiltersAndCompare("$.intBin1 >= 100",
+ List.of(Filter.range("intBin1", 100, Long.MAX_VALUE)));
+
+ // "$.intBin1 >= 100" and "100 <= $.intBin1" represent identical Filters
+ parseFiltersAndCompare("100 <= $.intBin1",
+ List.of(Filter.range("intBin1", 100, Long.MAX_VALUE)));
+ }
+
+ @Test
+ void binLT() {
+ parseFiltersAndCompare("$.intBin1 < 100",
+ List.of(Filter.range("intBin1", Long.MIN_VALUE, 99)));
+
+ parseFiltersAndCompare("100 > $.intBin1",
+ List.of(Filter.range("intBin1", Long.MIN_VALUE, 99)));
+ }
+
+ @Test
+ void binLE() {
+ parseFiltersAndCompare("$.intBin1 <= 100",
+ List.of(Filter.range("intBin1", Long.MIN_VALUE, 100)));
+
+ parseFiltersAndCompare("100 >= $.intBin1",
+ List.of(Filter.range("intBin1", Long.MIN_VALUE, 100)));
+ }
+
+ @Test
+ void binEQ() {
+ parseFiltersAndCompare("$.intBin1 == 100",
+ List.of(Filter.equal("intBin1", 100)));
+ parseFiltersAndCompare("100 == $.intBin1",
+ List.of(Filter.equal("intBin1", 100)));
+
+ parseFiltersAndCompare("$.stringBin1 == 'text'",
+ List.of(Filter.equal("stringBin1", "text")));
+ parseFiltersAndCompare("$.stringBin1 == \"text\"",
+ List.of(Filter.equal("stringBin1", "text")));
+ }
+
+ @Test
+ void binNOTEQ() {
+ // NOT EQUAL is not supported by secondary index filter
+ assertThatThrownBy(() -> parseFilters("$.intBin1 != 100"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("$.stringBin1 != 'text'"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("$.stringBin1 != \"text\""))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+
+ assertThatThrownBy(() -> parseFilters("100 != $.intBin1"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("100 != 'text'"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ assertThatThrownBy(() -> parseFilters("100 != \"text\""))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessageContaining("The operation is not supported by secondary index filter");
+ }
+}
diff --git a/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java
new file mode 100644
index 0000000..8fcf9db
--- /dev/null
+++ b/src/test/java/com/aerospike/dsl/filter/ExplicitTypesFiltersTests.java
@@ -0,0 +1,181 @@
+package com.aerospike.dsl.filter;
+
+import com.aerospike.client.query.Filter;
+import com.aerospike.dsl.exception.AerospikeDSLException;
+import org.junit.jupiter.api.Test;
+
+import java.util.Base64;
+import java.util.List;
+
+import static com.aerospike.dsl.util.TestUtils.parseFilters;
+import static com.aerospike.dsl.util.TestUtils.parseFiltersAndCompare;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class ExplicitTypesFiltersTests {
+
+ @Test
+ void integerComparison() {
+ parseFiltersAndCompare("$.intBin1.get(type: INT) > 5",
+ List.of(Filter.range("intBin1", 6, Long.MAX_VALUE)));
+
+ parseFiltersAndCompare("5 < $.intBin1.get(type: INT)",
+ List.of(Filter.range("intBin1", 6, Long.MAX_VALUE)));
+ }
+
+ @Test
+ void stringComparison() {
+ parseFiltersAndCompare("$.stringBin1.get(type: STRING) == \"yes\"",
+ List.of(Filter.equal("stringBin1", "yes")));
+
+ parseFiltersAndCompare("$.stringBin1.get(type: STRING) == 'yes'",
+ List.of(Filter.equal("stringBin1", "yes")));
+
+ parseFiltersAndCompare("\"yes\" == $.stringBin1.get(type: STRING)",
+ List.of(Filter.equal("stringBin1", "yes")));
+
+ parseFiltersAndCompare("'yes' == $.stringBin1.get(type: STRING)",
+ List.of(Filter.equal("stringBin1", "yes")));
+ }
+
+ @Test
+ void stringComparisonNegativeTest() {
+ // A String constant must be quoted
+ assertThatThrownBy(() -> parseFilters("$.stringBin1.get(type: STRING) == yes"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Unable to parse right operand");
+ }
+
+ @Test
+ void blobComparison() {
+ byte[] data = new byte[]{1, 2, 3};
+ String encodedString = Base64.getEncoder().encodeToString(data);
+ parseFiltersAndCompare("$.blobBin1.get(type: BLOB) == \"" + encodedString + "\"",
+ List.of(Filter.equal("blobBin1", data)));
+
+ // Reverse
+ parseFiltersAndCompare("\"" + encodedString + "\" == $.blobBin1.get(type: BLOB)",
+ List.of(Filter.equal("blobBin1", data)));
+ }
+
+ @Test
+ void floatComparison() {
+ // No float support in secondary index filter
+ assertThatThrownBy(() -> parseFilters("$.floatBin1.get(type: FLOAT) == 1.5"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: FLOAT_OPERAND");
+
+ assertThatThrownBy(() -> parseFilters("1.5 == $.floatBin1.get(type: FLOAT)"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: FLOAT_OPERAND");
+ }
+
+ @Test
+ void booleanComparison() {
+ // No boolean support in secondary index filter
+ assertThatThrownBy(() -> parseFilters("$.boolBin1.get(type: BOOL) == true"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: BOOL_OPERAND");
+
+ assertThatThrownBy(() -> parseFilters("true == $.boolBin1.get(type: BOOL)"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: BOOL_OPERAND");
+ }
+
+ @Test
+ void negativeBooleanComparison() {
+ assertThatThrownBy(() -> parseFilters("$.boolBin1.get(type: BOOL) == 5"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Cannot compare BOOL to INT");
+ }
+
+ @Test
+ void listComparison_constantOnRightSide() {
+ assertThatThrownBy(() -> parseFilters("$.listBin1.get(type: LIST) == [100]"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: LIST_OPERAND");
+ }
+
+ @Test
+ void listComparison_constantOnRightSide_NegativeTest() {
+ assertThatThrownBy(() -> parseFilters("$.listBin1.get(type: LIST) == [yes, of course]"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Unable to parse list operand");
+ }
+
+ @Test
+ void listComparison_constantOnLeftSide() {
+ assertThatThrownBy(() -> parseFilters("[100] == $.listBin1.get(type: LIST)"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: LIST_OPERAND");
+ }
+
+ @Test
+ void listComparison_constantOnLeftSide_NegativeTest() {
+ assertThatThrownBy(() -> parseFilters("[yes, of course] == $.listBin1.get(type: LIST)"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Could not parse given input, wrong syntax");
+ }
+
+ @Test
+ void mapComparison_constantOnRightSide() {
+ assertThatThrownBy(() -> parseFilters("$.mapBin1.get(type: MAP) == {100:100}"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: MAP_OPERAND");
+ }
+
+ @Test
+ void mapComparison_constantOnRightSide_NegativeTest() {
+ assertThatThrownBy(() -> parseFilters("$.mapBin1.get(type: MAP) == {yes, of course}"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Unable to parse map operand");
+ }
+
+ @Test
+ void mapComparison_constantOnLeftSide() {
+ assertThatThrownBy(() -> parseFilters("{100:100} == $.mapBin1.get(type: MAP)"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: MAP_OPERAND");
+ }
+
+ @Test
+ void mapComparison_constantOnLeftSide_NegativeTest() {
+ assertThatThrownBy(() -> parseFilters("{yes, of course} == $.mapBin1.get(type: MAP)"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Could not parse given input, wrong syntax");
+ }
+
+ @Test
+ void twoStringBinsComparison() {
+ assertThatThrownBy(() -> parseFilters("$.stringBin1.get(type: STRING) == $.stringBin2.get(type: STRING)"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: BIN_PART");
+ }
+
+ @Test
+ void twoIntegerBinsComparison() {
+ assertThatThrownBy(() -> parseFilters("$.intBin1.get(type: INT) == $.intBin2.get(type: INT)"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: BIN_PART");
+ }
+
+ @Test
+ void twoFloatBinsComparison() {
+ assertThatThrownBy(() -> parseFilters("$.floatBin1.get(type: FLOAT) == $.floatBin2.get(type: FLOAT)"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: BIN_PART");
+ }
+
+ @Test
+ void twoBlobBinsComparison() {
+ assertThatThrownBy(() -> parseFilters("$.blobBin1.get(type: BLOB) == $.blobBin2.get(type: BLOB)"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: BIN_PART");
+ }
+
+ @Test
+ void negativeTwoDifferentBinTypesComparison() {
+ assertThatThrownBy(() -> parseFilters("$.stringBin1.get(type: STRING) == $.floatBin2.get(type: FLOAT)"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: BIN_PART");
+ }
+}
diff --git a/src/test/java/com/aerospike/dsl/filter/ImplicitTypesFiltersTests.java b/src/test/java/com/aerospike/dsl/filter/ImplicitTypesFiltersTests.java
new file mode 100644
index 0000000..15f4cb5
--- /dev/null
+++ b/src/test/java/com/aerospike/dsl/filter/ImplicitTypesFiltersTests.java
@@ -0,0 +1,31 @@
+package com.aerospike.dsl.filter;
+
+import com.aerospike.dsl.exception.AerospikeDSLException;
+import org.junit.jupiter.api.Test;
+
+import static com.aerospike.dsl.util.TestUtils.parseFilters;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class ImplicitTypesFiltersTests {
+
+ @Test
+ void implicitDefaultIntComparison() {
+ assertThatThrownBy(() -> parseFilters("$.intBin1 < $.intBin2"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: BIN_PART");
+ }
+
+ @Test
+ void floatComparison() {
+ assertThatThrownBy(() -> parseFilters("$.floatBin1 >= 100.25"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: FLOAT_OPERAND");
+ }
+
+ @Test
+ void booleanComparison() {
+ assertThatThrownBy(() -> parseFilters("$.boolBin1 == true"))
+ .isInstanceOf(AerospikeDSLException.class)
+ .hasMessage("Operand type not supported: BOOL_OPERAND");
+ }
+}
diff --git a/src/test/java/com/aerospike/dsl/util/TestUtils.java b/src/test/java/com/aerospike/dsl/util/TestUtils.java
index a7b3882..b85a950 100644
--- a/src/test/java/com/aerospike/dsl/util/TestUtils.java
+++ b/src/test/java/com/aerospike/dsl/util/TestUtils.java
@@ -2,21 +2,35 @@
import com.aerospike.client.exp.Exp;
import com.aerospike.client.exp.Expression;
-import com.aerospike.dsl.ConditionTranslator;
+import com.aerospike.client.query.Filter;
+import com.aerospike.dsl.DSLParserImpl;
import lombok.experimental.UtilityClass;
+import java.util.List;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
@UtilityClass
public class TestUtils {
- public static void translate(String input) {
- ConditionTranslator.translate(input);
+ private final DSLParserImpl parser = new DSLParserImpl();
+
+ public static void parseExpression(String input) {
+ parser.parseExpression(input);
}
- public static void translateAndCompare(String input, Exp expected) {
- Expression actualExpression = ConditionTranslator.translate(input);
+ public static void parseExpressionAndCompare(String input, Exp expected) {
+ Expression actualExpression = parser.parseExpression(input);
Expression expectedExpression = Exp.build(expected);
assertEquals(actualExpression, expectedExpression);
}
+
+ public static void parseFilters(String input) {
+ parser.parseFilters(input);
+ }
+
+ public static void parseFiltersAndCompare(String input, List expected) {
+ List actualFilter = parser.parseFilters(input);
+ assertEquals(actualFilter, expected);
+ }
}